diff options
| author | Jason Rumney | 2009-03-24 14:14:53 +0000 |
|---|---|---|
| committer | Jason Rumney | 2009-03-24 14:14:53 +0000 |
| commit | 58aec0d679ff3c5f56ea384702f9a23fecccfe33 (patch) | |
| tree | 748208a0b9fae639fbd17f5597e221513d910172 | |
| parent | 5e5b7cb12c7caf9a4d6cd996372dc925aedf8e82 (diff) | |
| download | emacs-58aec0d679ff3c5f56ea384702f9a23fecccfe33.tar.gz emacs-58aec0d679ff3c5f56ea384702f9a23fecccfe33.zip | |
(Fsubstitute_in_file_name): Always work on a copy.
Calculate total size precisely. Decode environment variables
before substituting. (Bug#38)
| -rw-r--r-- | src/ChangeLog | 6 | ||||
| -rw-r--r-- | src/fileio.c | 53 |
2 files changed, 39 insertions, 20 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 7389c561f82..dc0fbd183d1 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,9 @@ | |||
| 1 | 2009-03-24 Jason Rumney <jasonr@gnu.org> | ||
| 2 | |||
| 3 | * fileio.c (Fsubstitute_in_file_name): Always work on a copy. | ||
| 4 | Calculate total size precisely. Decode environment variables | ||
| 5 | before substituting. (Bug#38) | ||
| 6 | |||
| 1 | 2009-03-24 Kenichi Handa <handa@m17n.org> | 7 | 2009-03-24 Kenichi Handa <handa@m17n.org> |
| 2 | 8 | ||
| 3 | * font.c (find_font_encoding): Return Qnil for unsupported | 9 | * font.c (find_font_encoding): Return Qnil for unsupported |
diff --git a/src/fileio.c b/src/fileio.c index ae64be4ba03..4f3573b02d7 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -1629,11 +1629,14 @@ those `/' is discarded. */) | |||
| 1629 | unsigned char *target = NULL; | 1629 | unsigned char *target = NULL; |
| 1630 | int total = 0; | 1630 | int total = 0; |
| 1631 | int substituted = 0; | 1631 | int substituted = 0; |
| 1632 | int multibyte; | ||
| 1632 | unsigned char *xnm; | 1633 | unsigned char *xnm; |
| 1633 | Lisp_Object handler; | 1634 | Lisp_Object handler; |
| 1634 | 1635 | ||
| 1635 | CHECK_STRING (filename); | 1636 | CHECK_STRING (filename); |
| 1636 | 1637 | ||
| 1638 | multibyte = STRING_MULTIBYTE (filename); | ||
| 1639 | |||
| 1637 | /* If the file name has special constructs in it, | 1640 | /* If the file name has special constructs in it, |
| 1638 | call the corresponding file handler. */ | 1641 | call the corresponding file handler. */ |
| 1639 | handler = Ffind_file_name_handler (filename, Qsubstitute_in_file_name); | 1642 | handler = Ffind_file_name_handler (filename, Qsubstitute_in_file_name); |
| @@ -1641,8 +1644,11 @@ those `/' is discarded. */) | |||
| 1641 | return call2 (handler, Qsubstitute_in_file_name, filename); | 1644 | return call2 (handler, Qsubstitute_in_file_name, filename); |
| 1642 | 1645 | ||
| 1643 | nm = SDATA (filename); | 1646 | nm = SDATA (filename); |
| 1644 | #ifdef DOS_NT | 1647 | /* Always work on a copy of the string, in case GC happens during |
| 1648 | decode of environment variables, causing the original Lisp_String | ||
| 1649 | data to be relocated. */ | ||
| 1645 | nm = strcpy (alloca (strlen (nm) + 1), nm); | 1650 | nm = strcpy (alloca (strlen (nm) + 1), nm); |
| 1651 | #ifdef DOS_NT | ||
| 1646 | CORRECT_DIR_SEPS (nm); | 1652 | CORRECT_DIR_SEPS (nm); |
| 1647 | substituted = (strcmp (nm, SDATA (filename)) != 0); | 1653 | substituted = (strcmp (nm, SDATA (filename)) != 0); |
| 1648 | #endif | 1654 | #endif |
| @@ -1655,9 +1661,7 @@ those `/' is discarded. */) | |||
| 1655 | again. Important with filenames like "/home/foo//:/hello///there" | 1661 | again. Important with filenames like "/home/foo//:/hello///there" |
| 1656 | which whould substitute to "/:/hello///there" rather than "/there". */ | 1662 | which whould substitute to "/:/hello///there" rather than "/there". */ |
| 1657 | return Fsubstitute_in_file_name | 1663 | return Fsubstitute_in_file_name |
| 1658 | (make_specified_string (p, -1, endp - p, | 1664 | (make_specified_string (p, -1, endp - p, multibyte)); |
| 1659 | STRING_MULTIBYTE (filename))); | ||
| 1660 | |||
| 1661 | 1665 | ||
| 1662 | /* See if any variables are substituted into the string | 1666 | /* See if any variables are substituted into the string |
| 1663 | and find the total length of their values in `total' */ | 1667 | and find the total length of their values in `total' */ |
| @@ -1703,8 +1707,16 @@ those `/' is discarded. */) | |||
| 1703 | /* Get variable value */ | 1707 | /* Get variable value */ |
| 1704 | o = (unsigned char *) egetenv (target); | 1708 | o = (unsigned char *) egetenv (target); |
| 1705 | if (o) | 1709 | if (o) |
| 1706 | { /* Eight-bit chars occupy upto 2 bytes in multibyte. */ | 1710 | { |
| 1707 | total += strlen (o) * (STRING_MULTIBYTE (filename) ? 2 : 1); | 1711 | /* Don't try to guess a maximum length - UTF8 can use up to |
| 1712 | four bytes per character. This code is unlikely to run | ||
| 1713 | in a situation that requires performance, so decoding the | ||
| 1714 | env variables twice should be acceptable. Note that | ||
| 1715 | decoding may cause a garbage collect. */ | ||
| 1716 | Lisp_Object orig, decoded; | ||
| 1717 | orig = make_unibyte_string (o, strlen (o)); | ||
| 1718 | decoded = DECODE_FILE (orig); | ||
| 1719 | total += SBYTES (decoded); | ||
| 1708 | substituted = 1; | 1720 | substituted = 1; |
| 1709 | } | 1721 | } |
| 1710 | else if (*p == '}') | 1722 | else if (*p == '}') |
| @@ -1762,21 +1774,22 @@ those `/' is discarded. */) | |||
| 1762 | *x++ = '$'; | 1774 | *x++ = '$'; |
| 1763 | strcpy (x, target); x+= strlen (target); | 1775 | strcpy (x, target); x+= strlen (target); |
| 1764 | } | 1776 | } |
| 1765 | else if (STRING_MULTIBYTE (filename)) | ||
| 1766 | { | ||
| 1767 | /* If the original string is multibyte, | ||
| 1768 | convert what we substitute into multibyte. */ | ||
| 1769 | while (*o) | ||
| 1770 | { | ||
| 1771 | int c = *o++; | ||
| 1772 | c = unibyte_char_to_multibyte (c); | ||
| 1773 | x += CHAR_STRING (c, x); | ||
| 1774 | } | ||
| 1775 | } | ||
| 1776 | else | 1777 | else |
| 1777 | { | 1778 | { |
| 1778 | strcpy (x, o); | 1779 | Lisp_Object orig, decoded; |
| 1779 | x += strlen (o); | 1780 | int orig_length, decoded_length; |
| 1781 | orig_length = strlen (o); | ||
| 1782 | orig = make_unibyte_string (o, orig_length); | ||
| 1783 | decoded = DECODE_FILE (orig); | ||
| 1784 | decoded_length = SBYTES (decoded); | ||
| 1785 | strncpy (x, SDATA (decoded), decoded_length); | ||
| 1786 | x += decoded_length; | ||
| 1787 | |||
| 1788 | /* If environment variable needed decoding, return value | ||
| 1789 | needs to be multibyte. */ | ||
| 1790 | if (decoded_length != orig_length | ||
| 1791 | || strncmp (SDATA (decoded), o, orig_length)) | ||
| 1792 | multibyte = 1; | ||
| 1780 | } | 1793 | } |
| 1781 | } | 1794 | } |
| 1782 | 1795 | ||
| @@ -1789,7 +1802,7 @@ those `/' is discarded. */) | |||
| 1789 | need to quote some $ to $$ first. */ | 1802 | need to quote some $ to $$ first. */ |
| 1790 | xnm = p; | 1803 | xnm = p; |
| 1791 | 1804 | ||
| 1792 | return make_specified_string (xnm, -1, x - xnm, STRING_MULTIBYTE (filename)); | 1805 | return make_specified_string (xnm, -1, x - xnm, multibyte); |
| 1793 | 1806 | ||
| 1794 | badsubst: | 1807 | badsubst: |
| 1795 | error ("Bad format environment-variable substitution"); | 1808 | error ("Bad format environment-variable substitution"); |