aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorEli Zaretskii2015-05-23 11:35:45 +0300
committerEli Zaretskii2015-05-23 11:35:45 +0300
commit1f83c3e52480d35b0970d5db95e565f31686d227 (patch)
tree42fd9e23b5bfec403e2e5f636e604f64b208bc20 /lib-src
parentb8e18b63a3270090469b1092dea9520bb2c9a435 (diff)
downloademacs-1f83c3e52480d35b0970d5db95e565f31686d227.tar.gz
emacs-1f83c3e52480d35b0970d5db95e565f31686d227.zip
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.
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/etags.c82
1 files changed, 68 insertions, 14 deletions
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";
116# undef HAVE_NTGUI 116# undef HAVE_NTGUI
117# undef DOS_NT 117# undef DOS_NT
118# define DOS_NT 118# define DOS_NT
119# define O_CLOEXEC O_NOINHERIT
119#endif /* WINDOWSNT */ 120#endif /* WINDOWSNT */
120 121
121#include <unistd.h> 122#include <unistd.h>
@@ -125,6 +126,7 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4";
125#include <sysstdio.h> 126#include <sysstdio.h>
126#include <ctype.h> 127#include <ctype.h>
127#include <errno.h> 128#include <errno.h>
129#include <fcntl.h>
128#include <sys/types.h> 130#include <sys/types.h>
129#include <sys/stat.h> 131#include <sys/stat.h>
130#include <binary-io.h> 132#include <binary-io.h>
@@ -336,6 +338,7 @@ static char *absolute_filename (char *, char *);
336static char *absolute_dirname (char *, char *); 338static char *absolute_dirname (char *, char *);
337static bool filename_is_absolute (char *f); 339static bool filename_is_absolute (char *f);
338static void canonicalize_filename (char *); 340static void canonicalize_filename (char *);
341static char *etags_mktmp (void);
339static void linebuffer_init (linebuffer *); 342static void linebuffer_init (linebuffer *);
340static void linebuffer_setlen (linebuffer *, int); 343static void linebuffer_setlen (linebuffer *, int);
341static void *xmalloc (size_t); 344static void *xmalloc (size_t);
@@ -1437,7 +1440,7 @@ process_file_name (char *file, language *lang)
1437 fdesc *fdp; 1440 fdesc *fdp;
1438 compressor *compr; 1441 compressor *compr;
1439 char *compressed_name, *uncompressed_name; 1442 char *compressed_name, *uncompressed_name;
1440 char *ext, *real_name; 1443 char *ext, *real_name, *tmp_name;
1441 int retval; 1444 int retval;
1442 1445
1443 canonicalize_filename (file); 1446 canonicalize_filename (file);
@@ -1522,9 +1525,20 @@ process_file_name (char *file, language *lang)
1522 } 1525 }
1523 if (real_name == compressed_name) 1526 if (real_name == compressed_name)
1524 { 1527 {
1525 char *cmd = concat (compr->command, " ", real_name); 1528 tmp_name = etags_mktmp ();
1526 inf = popen (cmd, "r" FOPEN_BINARY); 1529 if (!tmp_name)
1527 free (cmd); 1530 inf = NULL;
1531 else
1532 {
1533 char *cmd1 = concat (compr->command, " ", real_name);
1534 char *cmd = concat (cmd1, " > ", tmp_name);
1535 free (cmd1);
1536 if (system (cmd) == -1)
1537 inf = NULL;
1538 else
1539 inf = fopen (tmp_name, "r" FOPEN_BINARY);
1540 free (cmd);
1541 }
1528 } 1542 }
1529 else 1543 else
1530 inf = fopen (real_name, "r" FOPEN_BINARY); 1544 inf = fopen (real_name, "r" FOPEN_BINARY);
@@ -1536,10 +1550,12 @@ process_file_name (char *file, language *lang)
1536 1550
1537 process_file (inf, uncompressed_name, lang); 1551 process_file (inf, uncompressed_name, lang);
1538 1552
1553 retval = fclose (inf);
1539 if (real_name == compressed_name) 1554 if (real_name == compressed_name)
1540 retval = pclose (inf); 1555 {
1541 else 1556 remove (tmp_name);
1542 retval = fclose (inf); 1557 free (tmp_name);
1558 }
1543 if (retval < 0) 1559 if (retval < 0)
1544 pfatal (file); 1560 pfatal (file);
1545 1561
@@ -1707,9 +1723,6 @@ find_entries (FILE *inf)
1707 } 1723 }
1708 } 1724 }
1709 1725
1710 /* We rewind here, even if inf may be a pipe. We fail if the
1711 length of the first line is longer than the pipe block size,
1712 which is unlikely. */
1713 rewind (inf); 1726 rewind (inf);
1714 1727
1715 /* Else try to guess the language given the case insensitive file name. */ 1728 /* Else try to guess the language given the case insensitive file name. */
@@ -1734,8 +1747,6 @@ find_entries (FILE *inf)
1734 if (old_last_node == last_node) 1747 if (old_last_node == last_node)
1735 /* No Fortran entries found. Try C. */ 1748 /* No Fortran entries found. Try C. */
1736 { 1749 {
1737 /* We do not tag if rewind fails.
1738 Only the file name will be recorded in the tags file. */
1739 rewind (inf); 1750 rewind (inf);
1740 curfdp->lang = get_language_from_langname (cplusplus ? "c++" : "c"); 1751 curfdp->lang = get_language_from_langname (cplusplus ? "c++" : "c");
1741 find_entries (inf); 1752 find_entries (inf);
@@ -5015,8 +5026,6 @@ TEX_mode (FILE *inf)
5015 TEX_opgrp = '<'; 5026 TEX_opgrp = '<';
5016 TEX_clgrp = '>'; 5027 TEX_clgrp = '>';
5017 } 5028 }
5018 /* If the input file is compressed, inf is a pipe, and rewind may fail.
5019 No attempt is made to correct the situation. */
5020 rewind (inf); 5029 rewind (inf);
5021} 5030}
5022 5031
@@ -6344,6 +6353,51 @@ etags_getcwd (void)
6344 return path; 6353 return path;
6345} 6354}
6346 6355
6356/* Return a newly allocated string containing a name of a temporary file. */
6357static char *
6358etags_mktmp (void)
6359{
6360 const char *tmpdir = getenv ("TMPDIR");
6361 const char *slash = "/";
6362
6363#if MSDOS || defined (DOS_NT)
6364 if (!tmpdir)
6365 tmpdir = getenv ("TEMP");
6366 if (!tmpdir)
6367 tmpdir = getenv ("TMP");
6368 if (!tmpdir)
6369 tmpdir = ".";
6370 if (tmpdir[strlen (tmpdir) - 1] == '/'
6371 || tmpdir[strlen (tmpdir) - 1] == '\\')
6372 slash = "";
6373#else
6374 if (!tmpdir)
6375 tmpdir = "/tmp";
6376 if (tmpdir[strlen (tmpdir) - 1] == '/')
6377 slash = "";
6378#endif
6379
6380 char *templt = concat (tmpdir, slash, "etXXXXXX");
6381 int fd = mkostemp (templt, O_CLOEXEC);
6382 if (fd < 0)
6383 {
6384 free (templt);
6385 templt = NULL;
6386 }
6387 else
6388 close (fd);
6389
6390#if defined (DOS_NT)
6391 /* The file name will be used in shell redirection, so it needs to have
6392 DOS-style backslashes, or else the Windows shell will barf. */
6393 char *p;
6394 for (p = templt; *p; p++)
6395 if (*p == '/')
6396 *p = '\\';
6397#endif
6398 return templt;
6399}
6400
6347/* Return a newly allocated string containing the file name of FILE 6401/* Return a newly allocated string containing the file name of FILE
6348 relative to the absolute directory DIR (which should end with a slash). */ 6402 relative to the absolute directory DIR (which should end with a slash). */
6349static char * 6403static char *