From: Eli Zaretskii Date: Sat, 23 May 2015 08:35:45 +0000 (+0300) Subject: Fix etags reading of compressed files X-Git-Tag: emacs-25.0.90~2010 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=1f83c3e52480d35b0970d5db95e565f31686d227;p=emacs.git Fix etags reading of compressed files * lib-src/etags.c (O_CLOEXEC) [WINDOWSNT]: Define. Include fcntl.h, for O_CLOEXEC. (process_file_name): Don't use 'popen', whose streams cannot be rewound. Instead, uncompress the file to a temporary file, created by 'etags_mktmp', and read from that as usual. (etags_mktmp): New function. * test/etags/ETAGS.good_1: * test/etags/ETAGS.good_2: * test/etags/ETAGS.good_3: * test/etags/ETAGS.good_4: * test/etags/ETAGS.good_5: Update to be consistent with latest changes in etags.c regarding reading compressed files. --- diff --git a/lib-src/etags.c b/lib-src/etags.c index 0a308c1984f..28729da8720 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c @@ -116,6 +116,7 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4"; # undef HAVE_NTGUI # undef DOS_NT # define DOS_NT +# define O_CLOEXEC O_NOINHERIT #endif /* WINDOWSNT */ #include @@ -125,6 +126,7 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4"; #include #include #include +#include #include #include #include @@ -336,6 +338,7 @@ static char *absolute_filename (char *, char *); static char *absolute_dirname (char *, char *); static bool filename_is_absolute (char *f); static void canonicalize_filename (char *); +static char *etags_mktmp (void); static void linebuffer_init (linebuffer *); static void linebuffer_setlen (linebuffer *, int); static void *xmalloc (size_t); @@ -1437,7 +1440,7 @@ process_file_name (char *file, language *lang) fdesc *fdp; compressor *compr; char *compressed_name, *uncompressed_name; - char *ext, *real_name; + char *ext, *real_name, *tmp_name; int retval; canonicalize_filename (file); @@ -1522,9 +1525,20 @@ process_file_name (char *file, language *lang) } if (real_name == compressed_name) { - char *cmd = concat (compr->command, " ", real_name); - inf = popen (cmd, "r" FOPEN_BINARY); - free (cmd); + tmp_name = etags_mktmp (); + if (!tmp_name) + inf = NULL; + else + { + char *cmd1 = concat (compr->command, " ", real_name); + char *cmd = concat (cmd1, " > ", tmp_name); + free (cmd1); + if (system (cmd) == -1) + inf = NULL; + else + inf = fopen (tmp_name, "r" FOPEN_BINARY); + free (cmd); + } } else inf = fopen (real_name, "r" FOPEN_BINARY); @@ -1536,10 +1550,12 @@ process_file_name (char *file, language *lang) process_file (inf, uncompressed_name, lang); + retval = fclose (inf); if (real_name == compressed_name) - retval = pclose (inf); - else - retval = fclose (inf); + { + remove (tmp_name); + free (tmp_name); + } if (retval < 0) pfatal (file); @@ -1707,9 +1723,6 @@ find_entries (FILE *inf) } } - /* We rewind here, even if inf may be a pipe. We fail if the - length of the first line is longer than the pipe block size, - which is unlikely. */ rewind (inf); /* Else try to guess the language given the case insensitive file name. */ @@ -1734,8 +1747,6 @@ find_entries (FILE *inf) if (old_last_node == last_node) /* No Fortran entries found. Try C. */ { - /* We do not tag if rewind fails. - Only the file name will be recorded in the tags file. */ rewind (inf); curfdp->lang = get_language_from_langname (cplusplus ? "c++" : "c"); find_entries (inf); @@ -5015,8 +5026,6 @@ TEX_mode (FILE *inf) TEX_opgrp = '<'; TEX_clgrp = '>'; } - /* If the input file is compressed, inf is a pipe, and rewind may fail. - No attempt is made to correct the situation. */ rewind (inf); } @@ -6344,6 +6353,51 @@ etags_getcwd (void) return path; } +/* Return a newly allocated string containing a name of a temporary file. */ +static char * +etags_mktmp (void) +{ + const char *tmpdir = getenv ("TMPDIR"); + const char *slash = "/"; + +#if MSDOS || defined (DOS_NT) + if (!tmpdir) + tmpdir = getenv ("TEMP"); + if (!tmpdir) + tmpdir = getenv ("TMP"); + if (!tmpdir) + tmpdir = "."; + if (tmpdir[strlen (tmpdir) - 1] == '/' + || tmpdir[strlen (tmpdir) - 1] == '\\') + slash = ""; +#else + if (!tmpdir) + tmpdir = "/tmp"; + if (tmpdir[strlen (tmpdir) - 1] == '/') + slash = ""; +#endif + + char *templt = concat (tmpdir, slash, "etXXXXXX"); + int fd = mkostemp (templt, O_CLOEXEC); + if (fd < 0) + { + free (templt); + templt = NULL; + } + else + close (fd); + +#if defined (DOS_NT) + /* The file name will be used in shell redirection, so it needs to have + DOS-style backslashes, or else the Windows shell will barf. */ + char *p; + for (p = templt; *p; p++) + if (*p == '/') + *p = '\\'; +#endif + return templt; +} + /* Return a newly allocated string containing the file name of FILE relative to the absolute directory DIR (which should end with a slash). */ static char * diff --git a/test/etags/ETAGS.good_1 b/test/etags/ETAGS.good_1 index 370d0574781..cabcd2c41a1 100644 --- a/test/etags/ETAGS.good_1 +++ b/test/etags/ETAGS.good_1 @@ -2243,12 +2243,12 @@ f-src/entry.strange_suffix,172 & intensity1(577,12231 character*(*) function foo(579,12307 -f-src/entry.strange,171 - LOGICAL FUNCTION PRTPKG 2,2 - ENTRY SETPRT 193,3793 - ENTRY MSGSEL 394,8405 - & intensity1(576,12158 - character*(*) function foo(578,12234 +f-src/entry.strange,172 + LOGICAL FUNCTION PRTPKG 3,75 + ENTRY SETPRT 194,3866 + ENTRY MSGSEL 395,8478 + & intensity1(577,12231 + character*(*) function foo(579,12307 forth-src/test-forth.fth,408 : a-forth-word 20,301 diff --git a/test/etags/ETAGS.good_2 b/test/etags/ETAGS.good_2 index b09e61e5628..5d4f7061e0a 100644 --- a/test/etags/ETAGS.good_2 +++ b/test/etags/ETAGS.good_2 @@ -2810,12 +2810,12 @@ f-src/entry.strange_suffix,172 & intensity1(577,12231 character*(*) function foo(579,12307 -f-src/entry.strange,171 - LOGICAL FUNCTION PRTPKG 2,2 - ENTRY SETPRT 193,3793 - ENTRY MSGSEL 394,8405 - & intensity1(576,12158 - character*(*) function foo(578,12234 +f-src/entry.strange,172 + LOGICAL FUNCTION PRTPKG 3,75 + ENTRY SETPRT 194,3866 + ENTRY MSGSEL 395,8478 + & intensity1(577,12231 + character*(*) function foo(579,12307 forth-src/test-forth.fth,408 : a-forth-word 20,301 diff --git a/test/etags/ETAGS.good_3 b/test/etags/ETAGS.good_3 index 5a9a2bfc25b..1d8e34ad3e7 100644 --- a/test/etags/ETAGS.good_3 +++ b/test/etags/ETAGS.good_3 @@ -2560,12 +2560,12 @@ f-src/entry.strange_suffix,172 & intensity1(577,12231 character*(*) function foo(579,12307 -f-src/entry.strange,171 - LOGICAL FUNCTION PRTPKG 2,2 - ENTRY SETPRT 193,3793 - ENTRY MSGSEL 394,8405 - & intensity1(576,12158 - character*(*) function foo(578,12234 +f-src/entry.strange,172 + LOGICAL FUNCTION PRTPKG 3,75 + ENTRY SETPRT 194,3866 + ENTRY MSGSEL 395,8478 + & intensity1(577,12231 + character*(*) function foo(579,12307 forth-src/test-forth.fth,408 : a-forth-word 20,301 diff --git a/test/etags/ETAGS.good_4 b/test/etags/ETAGS.good_4 index f6023ea7b3d..30ea7dcb6f7 100644 --- a/test/etags/ETAGS.good_4 +++ b/test/etags/ETAGS.good_4 @@ -2407,12 +2407,12 @@ f-src/entry.strange_suffix,172 & intensity1(577,12231 character*(*) function foo(579,12307 -f-src/entry.strange,171 - LOGICAL FUNCTION PRTPKG 2,2 - ENTRY SETPRT 193,3793 - ENTRY MSGSEL 394,8405 - & intensity1(576,12158 - character*(*) function foo(578,12234 +f-src/entry.strange,172 + LOGICAL FUNCTION PRTPKG 3,75 + ENTRY SETPRT 194,3866 + ENTRY MSGSEL 395,8478 + & intensity1(577,12231 + character*(*) function foo(579,12307 forth-src/test-forth.fth,408 : a-forth-word 20,301 diff --git a/test/etags/ETAGS.good_5 b/test/etags/ETAGS.good_5 index b6bb6260c75..dfa261b44fb 100644 --- a/test/etags/ETAGS.good_5 +++ b/test/etags/ETAGS.good_5 @@ -3291,12 +3291,12 @@ f-src/entry.strange_suffix,172 & intensity1(577,12231 character*(*) function foo(579,12307 -f-src/entry.strange,171 - LOGICAL FUNCTION PRTPKG 2,2 - ENTRY SETPRT 193,3793 - ENTRY MSGSEL 394,8405 - & intensity1(576,12158 - character*(*) function foo(578,12234 +f-src/entry.strange,172 + LOGICAL FUNCTION PRTPKG 3,75 + ENTRY SETPRT 194,3866 + ENTRY MSGSEL 395,8478 + & intensity1(577,12231 + character*(*) function foo(579,12307 forth-src/test-forth.fth,408 : a-forth-word 20,301