diff options
| author | Stefan Monnier | 2005-03-28 21:31:14 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2005-03-28 21:31:14 +0000 |
| commit | c70a4df6d2e683a591e7487c7940f7f18f5af65e (patch) | |
| tree | 25a5032be73981721a11d5ee95e67cefeea3028b /src | |
| parent | f60a6f87ff45773b0d1737ef8d8d2b83269e34a6 (diff) | |
| download | emacs-c70a4df6d2e683a591e7487c7940f7f18f5af65e.tar.gz emacs-c70a4df6d2e683a591e7487c7940f7f18f5af65e.zip | |
(Fexpand_file_name): Use IS_DEVICE_SEP.
(file_name_absolute_p): New fun, extracted from Ffile_name_absolute_p.
(Ffile_name_absolute_p): Use it.
(search_embedded_absfilename): New fun, extracted from Fsubstitute_in_file_name.
Use file_name_absolute_p. Free the pw data after use.
(Fsubstitute_in_file_name): Use it.
After cutting a prefix, re-check file-name-handler.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 11 | ||||
| -rw-r--r-- | src/fileio.c | 179 |
2 files changed, 99 insertions, 91 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 4ea174bdc60..1a5561160d0 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | 2005-03-28 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * fileio.c (Fexpand_file_name): Use IS_DEVICE_SEP. | ||
| 4 | (file_name_absolute_p): New fun, extracted from Ffile_name_absolute_p. | ||
| 5 | (Ffile_name_absolute_p): Use it. | ||
| 6 | (search_embedded_absfilename): New fun, extracted from | ||
| 7 | Fsubstitute_in_file_name. Use file_name_absolute_p. | ||
| 8 | Free the pw data after use. | ||
| 9 | (Fsubstitute_in_file_name): Use it. | ||
| 10 | After cutting a prefix, re-check file-name-handler. | ||
| 11 | |||
| 1 | 2005-03-26 Lennart Borgman <lennart.borgman.073@student.lu.se> | 12 | 2005-03-26 Lennart Borgman <lennart.borgman.073@student.lu.se> |
| 2 | 13 | ||
| 3 | * w32term.h (x_output): add focus_state. | 14 | * w32term.h (x_output): add focus_state. |
diff --git a/src/fileio.c b/src/fileio.c index dbbcace1212..58efa38c254 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -1014,7 +1014,7 @@ probably use `make-temp-file' instead, except in three circumstances: | |||
| 1014 | DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0, | 1014 | DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0, |
| 1015 | doc: /* Convert filename NAME to absolute, and canonicalize it. | 1015 | doc: /* Convert filename NAME to absolute, and canonicalize it. |
| 1016 | Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative | 1016 | Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative |
| 1017 | (does not start with slash); if DEFAULT-DIRECTORY is nil or missing, | 1017 | \(does not start with slash); if DEFAULT-DIRECTORY is nil or missing, |
| 1018 | the current buffer's value of default-directory is used. | 1018 | the current buffer's value of default-directory is used. |
| 1019 | File name components that are `.' are removed, and | 1019 | File name components that are `.' are removed, and |
| 1020 | so are file name components followed by `..', along with the `..' itself; | 1020 | so are file name components followed by `..', along with the `..' itself; |
| @@ -1464,7 +1464,7 @@ See also the function `substitute-in-file-name'. */) | |||
| 1464 | indirectly by prepending newdir to nm if necessary, and using | 1464 | indirectly by prepending newdir to nm if necessary, and using |
| 1465 | cwd (or the wd of newdir's drive) as the new newdir. */ | 1465 | cwd (or the wd of newdir's drive) as the new newdir. */ |
| 1466 | 1466 | ||
| 1467 | if (IS_DRIVE (newdir[0]) && newdir[1] == ':') | 1467 | if (IS_DRIVE (newdir[0]) && IS_DEVICE_SEP (newdir[1])) |
| 1468 | { | 1468 | { |
| 1469 | drive = newdir[0]; | 1469 | drive = newdir[0]; |
| 1470 | newdir += 2; | 1470 | newdir += 2; |
| @@ -1487,7 +1487,7 @@ See also the function `substitute-in-file-name'. */) | |||
| 1487 | } | 1487 | } |
| 1488 | 1488 | ||
| 1489 | /* Strip off drive name from prefix, if present. */ | 1489 | /* Strip off drive name from prefix, if present. */ |
| 1490 | if (IS_DRIVE (newdir[0]) && newdir[1] == ':') | 1490 | if (IS_DRIVE (newdir[0]) && IS_DEVICE_SEP (newdir[1])) |
| 1491 | { | 1491 | { |
| 1492 | drive = newdir[0]; | 1492 | drive = newdir[0]; |
| 1493 | newdir += 2; | 1493 | newdir += 2; |
| @@ -1721,7 +1721,7 @@ See also the function `substitute-in-file-name'. */) | |||
| 1721 | DEAFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0, | 1721 | DEAFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0, |
| 1722 | "Convert FILENAME to absolute, and canonicalize it.\n\ | 1722 | "Convert FILENAME to absolute, and canonicalize it.\n\ |
| 1723 | Second arg DEFAULT is directory to start with if FILENAME is relative\n\ | 1723 | Second arg DEFAULT is directory to start with if FILENAME is relative\n\ |
| 1724 | (does not start with slash); if DEFAULT is nil or missing,\n\ | 1724 | \(does not start with slash); if DEFAULT is nil or missing,\n\ |
| 1725 | the current buffer's value of default-directory is used.\n\ | 1725 | the current buffer's value of default-directory is used.\n\ |
| 1726 | Filenames containing `.' or `..' as components are simplified;\n\ | 1726 | Filenames containing `.' or `..' as components are simplified;\n\ |
| 1727 | initial `~/' expands to your home directory.\n\ | 1727 | initial `~/' expands to your home directory.\n\ |
| @@ -2040,6 +2040,75 @@ See also the function `substitute-in-file-name'.") | |||
| 2040 | } | 2040 | } |
| 2041 | #endif | 2041 | #endif |
| 2042 | 2042 | ||
| 2043 | /* If /~ or // appears, discard everything through first slash. */ | ||
| 2044 | static int | ||
| 2045 | file_name_absolute_p (filename) | ||
| 2046 | const unsigned char *filename; | ||
| 2047 | { | ||
| 2048 | return | ||
| 2049 | (IS_DIRECTORY_SEP (*filename) || *filename == '~' | ||
| 2050 | #ifdef VMS | ||
| 2051 | /* ??? This criterion is probably wrong for '<'. */ | ||
| 2052 | || index (filename, ':') || index (filename, '<') | ||
| 2053 | || (*filename == '[' && (filename[1] != '-' | ||
| 2054 | || (filename[2] != '.' && filename[2] != ']')) | ||
| 2055 | && filename[1] != '.') | ||
| 2056 | #endif /* VMS */ | ||
| 2057 | #ifdef DOS_NT | ||
| 2058 | || (IS_DRIVE (*filename) && IS_DEVICE_SEP (filename[1]) | ||
| 2059 | && IS_DIRECTORY_SEP (filename[2])) | ||
| 2060 | #endif | ||
| 2061 | ); | ||
| 2062 | } | ||
| 2063 | |||
| 2064 | static unsigned char * | ||
| 2065 | search_embedded_absfilename (nm, endp) | ||
| 2066 | unsigned char *nm, *endp; | ||
| 2067 | { | ||
| 2068 | unsigned char *p, *s; | ||
| 2069 | |||
| 2070 | for (p = nm + 1; p < endp; p++) | ||
| 2071 | { | ||
| 2072 | if ((0 | ||
| 2073 | #ifdef VMS | ||
| 2074 | || p[-1] == ':' || p[-1] == ']' || p[-1] == '>' | ||
| 2075 | #endif /* VMS */ | ||
| 2076 | || IS_DIRECTORY_SEP (p[-1])) | ||
| 2077 | && file_name_absolute_p (p) | ||
| 2078 | #if defined (APOLLO) || defined (WINDOWSNT) || defined(CYGWIN) | ||
| 2079 | /* // at start of file name is meaningful in Apollo, | ||
| 2080 | WindowsNT and Cygwin systems. */ | ||
| 2081 | && !(IS_DIRECTORY_SEP (p[0]) && p - 1 != nm) | ||
| 2082 | #endif /* not (APOLLO || WINDOWSNT || CYGWIN) */ | ||
| 2083 | ) | ||
| 2084 | { | ||
| 2085 | for (s = p; *s && (!IS_DIRECTORY_SEP (*s) | ||
| 2086 | #ifdef VMS | ||
| 2087 | && *s != ':' | ||
| 2088 | #endif /* VMS */ | ||
| 2089 | ); s++); | ||
| 2090 | if (p[0] == '~' && s > p + 1) /* we've got "/~something/" */ | ||
| 2091 | { | ||
| 2092 | unsigned char *o = alloca (s - p + 1); | ||
| 2093 | struct passwd *pw; | ||
| 2094 | bcopy (p, o, s - p); | ||
| 2095 | o [s - p] = 0; | ||
| 2096 | |||
| 2097 | /* If we have ~user and `user' exists, discard | ||
| 2098 | everything up to ~. But if `user' does not exist, leave | ||
| 2099 | ~user alone, it might be a literal file name. */ | ||
| 2100 | if ((pw = getpwnam (o + 1))) | ||
| 2101 | return p; | ||
| 2102 | else | ||
| 2103 | xfree (pw); | ||
| 2104 | } | ||
| 2105 | else | ||
| 2106 | return p; | ||
| 2107 | } | ||
| 2108 | } | ||
| 2109 | return NULL; | ||
| 2110 | } | ||
| 2111 | |||
| 2043 | DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name, | 2112 | DEFUN ("substitute-in-file-name", Fsubstitute_in_file_name, |
| 2044 | Ssubstitute_in_file_name, 1, 1, 0, | 2113 | Ssubstitute_in_file_name, 1, 1, 0, |
| 2045 | doc: /* Substitute environment variables referred to in FILENAME. | 2114 | doc: /* Substitute environment variables referred to in FILENAME. |
| @@ -2061,7 +2130,6 @@ duplicates what `expand-file-name' does. */) | |||
| 2061 | int total = 0; | 2130 | int total = 0; |
| 2062 | int substituted = 0; | 2131 | int substituted = 0; |
| 2063 | unsigned char *xnm; | 2132 | unsigned char *xnm; |
| 2064 | struct passwd *pw; | ||
| 2065 | Lisp_Object handler; | 2133 | Lisp_Object handler; |
| 2066 | 2134 | ||
| 2067 | CHECK_STRING (filename); | 2135 | CHECK_STRING (filename); |
| @@ -2081,61 +2149,17 @@ duplicates what `expand-file-name' does. */) | |||
| 2081 | endp = nm + SBYTES (filename); | 2149 | endp = nm + SBYTES (filename); |
| 2082 | 2150 | ||
| 2083 | /* If /~ or // appears, discard everything through first slash. */ | 2151 | /* If /~ or // appears, discard everything through first slash. */ |
| 2084 | 2152 | p = search_embedded_absfilename (nm, endp); | |
| 2085 | for (p = nm; p != endp; p++) | 2153 | if (p) |
| 2086 | { | 2154 | /* Start over with the new string, so we check the file-name-handler |
| 2087 | if ((p[0] == '~' | 2155 | again. Important with filenames like "/home/foo//:/hello///there" |
| 2088 | #if defined (APOLLO) || defined (WINDOWSNT) || defined(CYGWIN) | 2156 | which whould substitute to "/:/hello///there" rather than "/there". */ |
| 2089 | /* // at start of file name is meaningful in Apollo, | 2157 | return Fsubstitute_in_file_name |
| 2090 | WindowsNT and Cygwin systems. */ | 2158 | (make_specified_string (p, -1, endp - p, |
| 2091 | || (IS_DIRECTORY_SEP (p[0]) && p - 1 != nm) | 2159 | STRING_MULTIBYTE (filename))); |
| 2092 | #else /* not (APOLLO || WINDOWSNT || CYGWIN) */ | ||
| 2093 | || IS_DIRECTORY_SEP (p[0]) | ||
| 2094 | #endif /* not (APOLLO || WINDOWSNT || CYGWIN) */ | ||
| 2095 | ) | ||
| 2096 | && p != nm | ||
| 2097 | && (0 | ||
| 2098 | #ifdef VMS | ||
| 2099 | || p[-1] == ':' || p[-1] == ']' || p[-1] == '>' | ||
| 2100 | #endif /* VMS */ | ||
| 2101 | || IS_DIRECTORY_SEP (p[-1]))) | ||
| 2102 | { | ||
| 2103 | for (s = p; *s && (!IS_DIRECTORY_SEP (*s) | ||
| 2104 | #ifdef VMS | ||
| 2105 | && *s != ':' | ||
| 2106 | #endif /* VMS */ | ||
| 2107 | ); s++); | ||
| 2108 | if (p[0] == '~' && s > p + 1) /* we've got "/~something/" */ | ||
| 2109 | { | ||
| 2110 | o = (unsigned char *) alloca (s - p + 1); | ||
| 2111 | bcopy ((char *) p, o, s - p); | ||
| 2112 | o [s - p] = 0; | ||
| 2113 | |||
| 2114 | pw = (struct passwd *) getpwnam (o + 1); | ||
| 2115 | } | ||
| 2116 | /* If we have ~/ or ~user and `user' exists, discard | ||
| 2117 | everything up to ~. But if `user' does not exist, leave | ||
| 2118 | ~user alone, it might be a literal file name. */ | ||
| 2119 | if (IS_DIRECTORY_SEP (p[0]) || s == p + 1 || pw) | ||
| 2120 | { | ||
| 2121 | nm = p; | ||
| 2122 | substituted = 1; | ||
| 2123 | } | ||
| 2124 | } | ||
| 2125 | #ifdef DOS_NT | ||
| 2126 | /* see comment in expand-file-name about drive specifiers */ | ||
| 2127 | else if (IS_DRIVE (p[0]) && p[1] == ':' | ||
| 2128 | && p > nm && IS_DIRECTORY_SEP (p[-1])) | ||
| 2129 | { | ||
| 2130 | nm = p; | ||
| 2131 | substituted = 1; | ||
| 2132 | } | ||
| 2133 | #endif /* DOS_NT */ | ||
| 2134 | } | ||
| 2135 | 2160 | ||
| 2136 | #ifdef VMS | 2161 | #ifdef VMS |
| 2137 | return make_specified_string (nm, -1, strlen (nm), | 2162 | return filename; |
| 2138 | STRING_MULTIBYTE (filename)); | ||
| 2139 | #else | 2163 | #else |
| 2140 | 2164 | ||
| 2141 | /* See if any variables are substituted into the string | 2165 | /* See if any variables are substituted into the string |
| @@ -2261,22 +2285,11 @@ duplicates what `expand-file-name' does. */) | |||
| 2261 | *x = 0; | 2285 | *x = 0; |
| 2262 | 2286 | ||
| 2263 | /* If /~ or // appears, discard everything through first slash. */ | 2287 | /* If /~ or // appears, discard everything through first slash. */ |
| 2264 | 2288 | while ((p = search_embedded_absfilename (xnm, x))) | |
| 2265 | for (p = xnm; p != x; p++) | 2289 | /* This time we do not start over because we've already expanded envvars |
| 2266 | if ((p[0] == '~' | 2290 | and replaced $$ with $. Maybe we should start over as well, but we'd |
| 2267 | #if defined (APOLLO) || defined (WINDOWSNT) || defined(CYGWIN) | 2291 | need to quote some $ to $$ first. */ |
| 2268 | || (IS_DIRECTORY_SEP (p[0]) && p - 1 != xnm) | 2292 | xnm = p; |
| 2269 | #else /* not (APOLLO || WINDOWSNT || CYGWIN) */ | ||
| 2270 | || IS_DIRECTORY_SEP (p[0]) | ||
| 2271 | #endif /* not (APOLLO || WINDOWSNT || CYGWIN) */ | ||
| 2272 | ) | ||
| 2273 | && p != xnm && IS_DIRECTORY_SEP (p[-1])) | ||
| 2274 | xnm = p; | ||
| 2275 | #ifdef DOS_NT | ||
| 2276 | else if (IS_DRIVE (p[0]) && p[1] == ':' | ||
| 2277 | && p > xnm && IS_DIRECTORY_SEP (p[-1])) | ||
| 2278 | xnm = p; | ||
| 2279 | #endif | ||
| 2280 | 2293 | ||
| 2281 | return make_specified_string (xnm, -1, x - xnm, STRING_MULTIBYTE (filename)); | 2294 | return make_specified_string (xnm, -1, x - xnm, STRING_MULTIBYTE (filename)); |
| 2282 | 2295 | ||
| @@ -2959,24 +2972,8 @@ On Unix, this is a name starting with a `/' or a `~'. */) | |||
| 2959 | (filename) | 2972 | (filename) |
| 2960 | Lisp_Object filename; | 2973 | Lisp_Object filename; |
| 2961 | { | 2974 | { |
| 2962 | const unsigned char *ptr; | ||
| 2963 | |||
| 2964 | CHECK_STRING (filename); | 2975 | CHECK_STRING (filename); |
| 2965 | ptr = SDATA (filename); | 2976 | return file_name_absolute_p (SDATA (filename)) ? Qt : Qnil; |
| 2966 | if (IS_DIRECTORY_SEP (*ptr) || *ptr == '~' | ||
| 2967 | #ifdef VMS | ||
| 2968 | /* ??? This criterion is probably wrong for '<'. */ | ||
| 2969 | || index (ptr, ':') || index (ptr, '<') | ||
| 2970 | || (*ptr == '[' && (ptr[1] != '-' || (ptr[2] != '.' && ptr[2] != ']')) | ||
| 2971 | && ptr[1] != '.') | ||
| 2972 | #endif /* VMS */ | ||
| 2973 | #ifdef DOS_NT | ||
| 2974 | || (IS_DRIVE (*ptr) && ptr[1] == ':' && IS_DIRECTORY_SEP (ptr[2])) | ||
| 2975 | #endif | ||
| 2976 | ) | ||
| 2977 | return Qt; | ||
| 2978 | else | ||
| 2979 | return Qnil; | ||
| 2980 | } | 2977 | } |
| 2981 | 2978 | ||
| 2982 | /* Return nonzero if file FILENAME exists and can be executed. */ | 2979 | /* Return nonzero if file FILENAME exists and can be executed. */ |