diff options
| author | Eli Zaretskii | 2015-05-23 11:35:45 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2015-05-23 11:35:45 +0300 |
| commit | 1f83c3e52480d35b0970d5db95e565f31686d227 (patch) | |
| tree | 42fd9e23b5bfec403e2e5f636e604f64b208bc20 /lib-src | |
| parent | b8e18b63a3270090469b1092dea9520bb2c9a435 (diff) | |
| download | emacs-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.c | 82 |
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 *); | |||
| 336 | static char *absolute_dirname (char *, char *); | 338 | static char *absolute_dirname (char *, char *); |
| 337 | static bool filename_is_absolute (char *f); | 339 | static bool filename_is_absolute (char *f); |
| 338 | static void canonicalize_filename (char *); | 340 | static void canonicalize_filename (char *); |
| 341 | static char *etags_mktmp (void); | ||
| 339 | static void linebuffer_init (linebuffer *); | 342 | static void linebuffer_init (linebuffer *); |
| 340 | static void linebuffer_setlen (linebuffer *, int); | 343 | static void linebuffer_setlen (linebuffer *, int); |
| 341 | static void *xmalloc (size_t); | 344 | static 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. */ | ||
| 6357 | static char * | ||
| 6358 | etags_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). */ |
| 6349 | static char * | 6403 | static char * |