aboutsummaryrefslogtreecommitdiffstats
path: root/src/fileio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fileio.c')
-rw-r--r--src/fileio.c183
1 files changed, 100 insertions, 83 deletions
diff --git a/src/fileio.c b/src/fileio.c
index d9c7397c2de..4ba1c5914e8 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -396,13 +396,6 @@ Otherwise return a directory name.
396Given a Unix syntax file name, returns a string ending in slash. */) 396Given a Unix syntax file name, returns a string ending in slash. */)
397 (Lisp_Object filename) 397 (Lisp_Object filename)
398{ 398{
399#ifndef DOS_NT
400 register const char *beg;
401#else
402 register char *beg;
403 Lisp_Object tem_fn;
404#endif
405 register const char *p;
406 Lisp_Object handler; 399 Lisp_Object handler;
407 400
408 CHECK_STRING (filename); 401 CHECK_STRING (filename);
@@ -417,12 +410,8 @@ Given a Unix syntax file name, returns a string ending in slash. */)
417 return STRINGP (handled_name) ? handled_name : Qnil; 410 return STRINGP (handled_name) ? handled_name : Qnil;
418 } 411 }
419 412
420#ifdef DOS_NT 413 char *beg = SSDATA (filename);
421 beg = xlispstrdupa (filename); 414 char const *p = beg + SBYTES (filename);
422#else
423 beg = SSDATA (filename);
424#endif
425 p = beg + SBYTES (filename);
426 415
427 while (p != beg && !IS_DIRECTORY_SEP (p[-1]) 416 while (p != beg && !IS_DIRECTORY_SEP (p[-1])
428#ifdef DOS_NT 417#ifdef DOS_NT
@@ -438,6 +427,11 @@ Given a Unix syntax file name, returns a string ending in slash. */)
438 return Qnil; 427 return Qnil;
439#ifdef DOS_NT 428#ifdef DOS_NT
440 /* Expansion of "c:" to drive and default directory. */ 429 /* Expansion of "c:" to drive and default directory. */
430 Lisp_Object tem_fn;
431 USE_SAFE_ALLOCA;
432 SAFE_ALLOCA_STRING (beg, filename);
433 p = beg + (p - SSDATA (filename));
434
441 if (p[-1] == ':') 435 if (p[-1] == ':')
442 { 436 {
443 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */ 437 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */
@@ -481,6 +475,7 @@ Given a Unix syntax file name, returns a string ending in slash. */)
481 dostounix_filename (beg); 475 dostounix_filename (beg);
482 tem_fn = make_specified_string (beg, -1, p - beg, 0); 476 tem_fn = make_specified_string (beg, -1, p - beg, 0);
483 } 477 }
478 SAFE_FREE ();
484 return tem_fn; 479 return tem_fn;
485#else /* DOS_NT */ 480#else /* DOS_NT */
486 return make_specified_string (beg, -1, p - beg, STRING_MULTIBYTE (filename)); 481 return make_specified_string (beg, -1, p - beg, STRING_MULTIBYTE (filename));
@@ -733,7 +728,7 @@ Lisp_Object
733make_temp_name (Lisp_Object prefix, bool base64_p) 728make_temp_name (Lisp_Object prefix, bool base64_p)
734{ 729{
735 Lisp_Object val, encoded_prefix; 730 Lisp_Object val, encoded_prefix;
736 int len; 731 ptrdiff_t len;
737 printmax_t pid; 732 printmax_t pid;
738 char *p, *data; 733 char *p, *data;
739 char pidbuf[INT_BUFSIZE_BOUND (printmax_t)]; 734 char pidbuf[INT_BUFSIZE_BOUND (printmax_t)];
@@ -847,8 +842,6 @@ probably use `make-temp-file' instead, except in three circumstances:
847 return make_temp_name (prefix, 0); 842 return make_temp_name (prefix, 0);
848} 843}
849 844
850
851
852DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0, 845DEFUN ("expand-file-name", Fexpand_file_name, Sexpand_file_name, 1, 2, 0,
853 doc: /* Convert filename NAME to absolute, and canonicalize it. 846 doc: /* Convert filename NAME to absolute, and canonicalize it.
854Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative 847Second arg DEFAULT-DIRECTORY is directory to start with if NAME is relative
@@ -878,7 +871,9 @@ filesystem tree, not (expand-file-name ".." dirname). */)
878 /* These point to SDATA and need to be careful with string-relocation 871 /* These point to SDATA and need to be careful with string-relocation
879 during GC (via DECODE_FILE). */ 872 during GC (via DECODE_FILE). */
880 char *nm; 873 char *nm;
874 char *nmlim;
881 const char *newdir; 875 const char *newdir;
876 const char *newdirlim;
882 /* This should only point to alloca'd data. */ 877 /* This should only point to alloca'd data. */
883 char *target; 878 char *target;
884 879
@@ -886,10 +881,10 @@ filesystem tree, not (expand-file-name ".." dirname). */)
886 struct passwd *pw; 881 struct passwd *pw;
887#ifdef DOS_NT 882#ifdef DOS_NT
888 int drive = 0; 883 int drive = 0;
889 bool collapse_newdir = 1; 884 bool collapse_newdir = true;
890 bool is_escaped = 0; 885 bool is_escaped = 0;
891#endif /* DOS_NT */ 886#endif /* DOS_NT */
892 ptrdiff_t length; 887 ptrdiff_t length, nbytes;
893 Lisp_Object handler, result, handled_name; 888 Lisp_Object handler, result, handled_name;
894 bool multibyte; 889 bool multibyte;
895 Lisp_Object hdir; 890 Lisp_Object hdir;
@@ -1018,8 +1013,9 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1018 default_directory = Fdowncase (default_directory); 1013 default_directory = Fdowncase (default_directory);
1019#endif 1014#endif
1020 1015
1021 /* Make a local copy of nm[] to protect it from GC in DECODE_FILE below. */ 1016 /* Make a local copy of NAME to protect it from GC in DECODE_FILE below. */
1022 nm = xlispstrdupa (name); 1017 SAFE_ALLOCA_STRING (nm, name);
1018 nmlim = nm + SBYTES (name);
1023 1019
1024#ifdef DOS_NT 1020#ifdef DOS_NT
1025 /* Note if special escape prefix is present, but remove for now. */ 1021 /* Note if special escape prefix is present, but remove for now. */
@@ -1104,7 +1100,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1104 if (IS_DIRECTORY_SEP (nm[1])) 1100 if (IS_DIRECTORY_SEP (nm[1]))
1105 { 1101 {
1106 if (strcmp (nm, SSDATA (name)) != 0) 1102 if (strcmp (nm, SSDATA (name)) != 0)
1107 name = make_specified_string (nm, -1, strlen (nm), multibyte); 1103 name = make_specified_string (nm, -1, nmlim - nm, multibyte);
1108 } 1104 }
1109 else 1105 else
1110#endif 1106#endif
@@ -1115,18 +1111,19 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1115 1111
1116 name = make_specified_string (nm, -1, p - nm, multibyte); 1112 name = make_specified_string (nm, -1, p - nm, multibyte);
1117 temp[0] = DRIVE_LETTER (drive); 1113 temp[0] = DRIVE_LETTER (drive);
1118 name = concat2 (build_string (temp), name); 1114 AUTO_STRING (drive_prefix, temp);
1115 name = concat2 (drive_prefix, name);
1119 } 1116 }
1120#ifdef WINDOWSNT 1117#ifdef WINDOWSNT
1121 if (!NILP (Vw32_downcase_file_names)) 1118 if (!NILP (Vw32_downcase_file_names))
1122 name = Fdowncase (name); 1119 name = Fdowncase (name);
1123#endif 1120#endif
1124 return name;
1125#else /* not DOS_NT */ 1121#else /* not DOS_NT */
1126 if (strcmp (nm, SSDATA (name)) == 0) 1122 if (strcmp (nm, SSDATA (name)) != 0)
1127 return name; 1123 name = make_specified_string (nm, -1, nmlim - nm, multibyte);
1128 return make_specified_string (nm, -1, strlen (nm), multibyte);
1129#endif /* not DOS_NT */ 1124#endif /* not DOS_NT */
1125 SAFE_FREE ();
1126 return name;
1130 } 1127 }
1131 } 1128 }
1132 1129
@@ -1146,7 +1143,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1146 return an absolute name, if the final prefix is not absolute we 1143 return an absolute name, if the final prefix is not absolute we
1147 append it to the current working directory. */ 1144 append it to the current working directory. */
1148 1145
1149 newdir = 0; 1146 newdir = newdirlim = 0;
1150 1147
1151 if (nm[0] == '~') /* prefix ~ */ 1148 if (nm[0] == '~') /* prefix ~ */
1152 { 1149 {
@@ -1156,7 +1153,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1156 Lisp_Object tem; 1153 Lisp_Object tem;
1157 1154
1158 if (!(newdir = egetenv ("HOME"))) 1155 if (!(newdir = egetenv ("HOME")))
1159 newdir = ""; 1156 newdir = newdirlim = "";
1160 nm++; 1157 nm++;
1161 /* `egetenv' may return a unibyte string, which will bite us since 1158 /* `egetenv' may return a unibyte string, which will bite us since
1162 we expect the directory to be multibyte. */ 1159 we expect the directory to be multibyte. */
@@ -1171,13 +1168,15 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1171 else 1168 else
1172#endif 1169#endif
1173 tem = build_string (newdir); 1170 tem = build_string (newdir);
1171 newdirlim = newdir + SBYTES (tem);
1174 if (multibyte && !STRING_MULTIBYTE (tem)) 1172 if (multibyte && !STRING_MULTIBYTE (tem))
1175 { 1173 {
1176 hdir = DECODE_FILE (tem); 1174 hdir = DECODE_FILE (tem);
1177 newdir = SSDATA (hdir); 1175 newdir = SSDATA (hdir);
1176 newdirlim = newdir + SBYTES (hdir);
1178 } 1177 }
1179#ifdef DOS_NT 1178#ifdef DOS_NT
1180 collapse_newdir = 0; 1179 collapse_newdir = false;
1181#endif 1180#endif
1182 } 1181 }
1183 else /* ~user/filename */ 1182 else /* ~user/filename */
@@ -1201,14 +1200,16 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1201 bite us since we expect the directory to be 1200 bite us since we expect the directory to be
1202 multibyte. */ 1201 multibyte. */
1203 tem = build_string (newdir); 1202 tem = build_string (newdir);
1203 newdirlim = newdir + SBYTES (tem);
1204 if (multibyte && !STRING_MULTIBYTE (tem)) 1204 if (multibyte && !STRING_MULTIBYTE (tem))
1205 { 1205 {
1206 hdir = DECODE_FILE (tem); 1206 hdir = DECODE_FILE (tem);
1207 newdir = SSDATA (hdir); 1207 newdir = SSDATA (hdir);
1208 newdirlim = newdir + SBYTES (hdir);
1208 } 1209 }
1209 nm = p; 1210 nm = p;
1210#ifdef DOS_NT 1211#ifdef DOS_NT
1211 collapse_newdir = 0; 1212 collapse_newdir = false;
1212#endif 1213#endif
1213 } 1214 }
1214 1215
@@ -1234,8 +1235,11 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1234 Lisp_Object tem = build_string (adir); 1235 Lisp_Object tem = build_string (adir);
1235 1236
1236 tem = DECODE_FILE (tem); 1237 tem = DECODE_FILE (tem);
1238 newdirlim = adir + SBYTES (tem);
1237 memcpy (adir, SSDATA (tem), SBYTES (tem) + 1); 1239 memcpy (adir, SSDATA (tem), SBYTES (tem) + 1);
1238 } 1240 }
1241 else
1242 newdirlim = adir + strlen (adir);
1239 } 1243 }
1240 if (!adir) 1244 if (!adir)
1241 { 1245 {
@@ -1245,6 +1249,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1245 adir[1] = ':'; 1249 adir[1] = ':';
1246 adir[2] = '/'; 1250 adir[2] = '/';
1247 adir[3] = 0; 1251 adir[3] = 0;
1252 newdirlim = adir + 3;
1248 } 1253 }
1249 newdir = adir; 1254 newdir = adir;
1250 } 1255 }
@@ -1265,6 +1270,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1265 && !newdir) 1270 && !newdir)
1266 { 1271 {
1267 newdir = SSDATA (default_directory); 1272 newdir = SSDATA (default_directory);
1273 newdirlim = newdir + SBYTES (default_directory);
1268#ifdef DOS_NT 1274#ifdef DOS_NT
1269 /* Note if special escape prefix is present, but remove for now. */ 1275 /* Note if special escape prefix is present, but remove for now. */
1270 if (newdir[0] == '/' && newdir[1] == ':') 1276 if (newdir[0] == '/' && newdir[1] == ':')
@@ -1309,12 +1315,15 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1309 } 1315 }
1310 if (!IS_DIRECTORY_SEP (nm[0])) 1316 if (!IS_DIRECTORY_SEP (nm[0]))
1311 { 1317 {
1312 ptrdiff_t newlen = strlen (newdir); 1318 ptrdiff_t nmlen = nmlim - nm;
1313 char *tmp = alloca (newlen + file_name_as_directory_slop 1319 ptrdiff_t newdirlen = newdirlim - newdir;
1314 + strlen (nm) + 1); 1320 char *tmp = alloca (newdirlen + file_name_as_directory_slop
1315 file_name_as_directory (tmp, newdir, newlen, multibyte); 1321 + nmlen + 1);
1316 strcat (tmp, nm); 1322 ptrdiff_t dlen = file_name_as_directory (tmp, newdir, newdirlen,
1323 multibyte);
1324 memcpy (tmp + dlen, nm, nmlen + 1);
1317 nm = tmp; 1325 nm = tmp;
1326 nmlim = nm + dlen + nmlen;
1318 } 1327 }
1319 adir = alloca (adir_size); 1328 adir = alloca (adir_size);
1320 if (drive) 1329 if (drive)
@@ -1329,8 +1338,11 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1329 Lisp_Object tem = build_string (adir); 1338 Lisp_Object tem = build_string (adir);
1330 1339
1331 tem = DECODE_FILE (tem); 1340 tem = DECODE_FILE (tem);
1341 newdirlim = adir + SBYTES (tem);
1332 memcpy (adir, SSDATA (tem), SBYTES (tem) + 1); 1342 memcpy (adir, SSDATA (tem), SBYTES (tem) + 1);
1333 } 1343 }
1344 else
1345 newdirlim = adir + strlen (adir);
1334 newdir = adir; 1346 newdir = adir;
1335 } 1347 }
1336 1348
@@ -1349,35 +1361,32 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1349 if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1]) 1361 if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1])
1350 && !IS_DIRECTORY_SEP (newdir[2])) 1362 && !IS_DIRECTORY_SEP (newdir[2]))
1351 { 1363 {
1352 char *adir = strcpy (alloca (strlen (newdir) + 1), newdir); 1364 char *adir = strcpy (alloca (newdirlim - newdir + 1), newdir);
1353 char *p = adir + 2; 1365 char *p = adir + 2;
1354 while (*p && !IS_DIRECTORY_SEP (*p)) p++; 1366 while (*p && !IS_DIRECTORY_SEP (*p)) p++;
1355 p++; 1367 p++;
1356 while (*p && !IS_DIRECTORY_SEP (*p)) p++; 1368 while (*p && !IS_DIRECTORY_SEP (*p)) p++;
1357 *p = 0; 1369 *p = 0;
1358 newdir = adir; 1370 newdir = adir;
1371 newdirlim = newdir + strlen (adir);
1359 } 1372 }
1360 else 1373 else
1361#endif 1374#endif
1362 newdir = ""; 1375 newdir = newdirlim = "";
1363 } 1376 }
1364 } 1377 }
1365#endif /* DOS_NT */ 1378#endif /* DOS_NT */
1366 1379
1367 if (newdir) 1380 /* Ignore any slash at the end of newdir, unless newdir is
1368 { 1381 just "/" or "//". */
1369 /* Ignore any slash at the end of newdir, unless newdir is 1382 length = newdirlim - newdir;
1370 just "/" or "//". */ 1383 while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
1371 length = strlen (newdir); 1384 && ! (length == 2 && IS_DIRECTORY_SEP (newdir[0])))
1372 while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1]) 1385 length--;
1373 && ! (length == 2 && IS_DIRECTORY_SEP (newdir[0])))
1374 length--;
1375 }
1376 else
1377 length = 0;
1378 1386
1379 /* Now concatenate the directory and name to new space in the stack frame. */ 1387 /* Now concatenate the directory and name to new space in the stack frame. */
1380 tlen = length + file_name_as_directory_slop + strlen (nm) + 1; 1388 tlen = length + file_name_as_directory_slop + (nmlim - nm) + 1;
1389 eassert (tlen > file_name_as_directory_slop + 1);
1381#ifdef DOS_NT 1390#ifdef DOS_NT
1382 /* Reserve space for drive specifier and escape prefix, since either 1391 /* Reserve space for drive specifier and escape prefix, since either
1383 or both may need to be inserted. (The Microsoft x86 compiler 1392 or both may need to be inserted. (The Microsoft x86 compiler
@@ -1388,6 +1397,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1388 target = SAFE_ALLOCA (tlen); 1397 target = SAFE_ALLOCA (tlen);
1389#endif /* not DOS_NT */ 1398#endif /* not DOS_NT */
1390 *target = 0; 1399 *target = 0;
1400 nbytes = 0;
1391 1401
1392 if (newdir) 1402 if (newdir)
1393 { 1403 {
@@ -1405,13 +1415,14 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1405 { 1415 {
1406 memcpy (target, newdir, length); 1416 memcpy (target, newdir, length);
1407 target[length] = 0; 1417 target[length] = 0;
1418 nbytes = length;
1408 } 1419 }
1409 } 1420 }
1410 else 1421 else
1411 file_name_as_directory (target, newdir, length, multibyte); 1422 nbytes = file_name_as_directory (target, newdir, length, multibyte);
1412 } 1423 }
1413 1424
1414 strcat (target, nm); 1425 memcpy (target + nbytes, nm, nmlim - nm + 1);
1415 1426
1416 /* Now canonicalize by removing `//', `/.' and `/foo/..' if they 1427 /* Now canonicalize by removing `//', `/.' and `/foo/..' if they
1417 appear. */ 1428 appear. */
@@ -1717,7 +1728,8 @@ search_embedded_absfilename (char *nm, char *endp)
1717 for (s = p; *s && !IS_DIRECTORY_SEP (*s); s++); 1728 for (s = p; *s && !IS_DIRECTORY_SEP (*s); s++);
1718 if (p[0] == '~' && s > p + 1) /* We've got "/~something/". */ 1729 if (p[0] == '~' && s > p + 1) /* We've got "/~something/". */
1719 { 1730 {
1720 char *o = alloca (s - p + 1); 1731 USE_SAFE_ALLOCA;
1732 char *o = SAFE_ALLOCA (s - p + 1);
1721 struct passwd *pw; 1733 struct passwd *pw;
1722 memcpy (o, p, s - p); 1734 memcpy (o, p, s - p);
1723 o [s - p] = 0; 1735 o [s - p] = 0;
@@ -1728,6 +1740,7 @@ search_embedded_absfilename (char *nm, char *endp)
1728 block_input (); 1740 block_input ();
1729 pw = getpwnam (o + 1); 1741 pw = getpwnam (o + 1);
1730 unblock_input (); 1742 unblock_input ();
1743 SAFE_FREE ();
1731 if (pw) 1744 if (pw)
1732 return p; 1745 return p;
1733 } 1746 }
@@ -1776,7 +1789,8 @@ those `/' is discarded. */)
1776 /* Always work on a copy of the string, in case GC happens during 1789 /* Always work on a copy of the string, in case GC happens during
1777 decode of environment variables, causing the original Lisp_String 1790 decode of environment variables, causing the original Lisp_String
1778 data to be relocated. */ 1791 data to be relocated. */
1779 nm = xlispstrdupa (filename); 1792 USE_SAFE_ALLOCA;
1793 SAFE_ALLOCA_STRING (nm, filename);
1780 1794
1781#ifdef DOS_NT 1795#ifdef DOS_NT
1782 dostounix_filename (nm); 1796 dostounix_filename (nm);
@@ -1790,8 +1804,13 @@ those `/' is discarded. */)
1790 /* Start over with the new string, so we check the file-name-handler 1804 /* Start over with the new string, so we check the file-name-handler
1791 again. Important with filenames like "/home/foo//:/hello///there" 1805 again. Important with filenames like "/home/foo//:/hello///there"
1792 which would substitute to "/:/hello///there" rather than "/there". */ 1806 which would substitute to "/:/hello///there" rather than "/there". */
1793 return Fsubstitute_in_file_name 1807 {
1794 (make_specified_string (p, -1, endp - p, multibyte)); 1808 Lisp_Object result
1809 = (Fsubstitute_in_file_name
1810 (make_specified_string (p, -1, endp - p, multibyte)));
1811 SAFE_FREE ();
1812 return result;
1813 }
1795 1814
1796 /* See if any variables are substituted into the string. */ 1815 /* See if any variables are substituted into the string. */
1797 1816
@@ -1813,6 +1832,7 @@ those `/' is discarded. */)
1813 if (!NILP (Vw32_downcase_file_names)) 1832 if (!NILP (Vw32_downcase_file_names))
1814 filename = Fdowncase (filename); 1833 filename = Fdowncase (filename);
1815#endif 1834#endif
1835 SAFE_FREE ();
1816 return filename; 1836 return filename;
1817 } 1837 }
1818 1838
@@ -1831,14 +1851,14 @@ those `/' is discarded. */)
1831 { 1851 {
1832 Lisp_Object xname = make_specified_string (xnm, -1, x - xnm, multibyte); 1852 Lisp_Object xname = make_specified_string (xnm, -1, x - xnm, multibyte);
1833 1853
1834 xname = Fdowncase (xname); 1854 filename = Fdowncase (xname);
1835 return xname;
1836 } 1855 }
1837 else 1856 else
1838#endif 1857#endif
1839 return (xnm == SSDATA (filename) 1858 if (xnm != SSDATA (filename))
1840 ? filename 1859 filename = make_specified_string (xnm, -1, x - xnm, multibyte);
1841 : make_specified_string (xnm, -1, x - xnm, multibyte)); 1860 SAFE_FREE ();
1861 return filename;
1842} 1862}
1843 1863
1844/* A slightly faster and more convenient way to get 1864/* A slightly faster and more convenient way to get
@@ -2671,7 +2691,10 @@ emacs_readlinkat (int fd, char const *filename)
2671 2691
2672 val = build_unibyte_string (buf); 2692 val = build_unibyte_string (buf);
2673 if (buf[0] == '/' && strchr (buf, ':')) 2693 if (buf[0] == '/' && strchr (buf, ':'))
2674 val = concat2 (build_unibyte_string ("/:"), val); 2694 {
2695 AUTO_STRING (slash_colon, "/:");
2696 val = concat2 (slash_colon, val);
2697 }
2675 if (buf != readlink_buf) 2698 if (buf != readlink_buf)
2676 xfree (buf); 2699 xfree (buf);
2677 val = DECODE_FILE (val); 2700 val = DECODE_FILE (val);
@@ -2765,23 +2788,24 @@ searchable directory. */)
2765 } 2788 }
2766 2789
2767 absname = ENCODE_FILE (absname); 2790 absname = ENCODE_FILE (absname);
2768 return file_accessible_directory_p (SSDATA (absname)) ? Qt : Qnil; 2791 return file_accessible_directory_p (absname) ? Qt : Qnil;
2769} 2792}
2770 2793
2771/* If FILE is a searchable directory or a symlink to a 2794/* If FILE is a searchable directory or a symlink to a
2772 searchable directory, return true. Otherwise return 2795 searchable directory, return true. Otherwise return
2773 false and set errno to an error number. */ 2796 false and set errno to an error number. */
2774bool 2797bool
2775file_accessible_directory_p (char const *file) 2798file_accessible_directory_p (Lisp_Object file)
2776{ 2799{
2777#ifdef DOS_NT 2800#ifdef DOS_NT
2778 /* There's no need to test whether FILE is searchable, as the 2801 /* There's no need to test whether FILE is searchable, as the
2779 searchable/executable bit is invented on DOS_NT platforms. */ 2802 searchable/executable bit is invented on DOS_NT platforms. */
2780 return file_directory_p (file); 2803 return file_directory_p (SSDATA (file));
2781#else 2804#else
2782 /* On POSIXish platforms, use just one system call; this avoids a 2805 /* On POSIXish platforms, use just one system call; this avoids a
2783 race and is typically faster. */ 2806 race and is typically faster. */
2784 ptrdiff_t len = strlen (file); 2807 const char *data = SSDATA (file);
2808 ptrdiff_t len = SBYTES (file);
2785 char const *dir; 2809 char const *dir;
2786 bool ok; 2810 bool ok;
2787 int saved_errno; 2811 int saved_errno;
@@ -2793,15 +2817,15 @@ file_accessible_directory_p (char const *file)
2793 "/" and "//" are distinct on some platforms, whereas "/", "///", 2817 "/" and "//" are distinct on some platforms, whereas "/", "///",
2794 "////", etc. are all equivalent. */ 2818 "////", etc. are all equivalent. */
2795 if (! len) 2819 if (! len)
2796 dir = file; 2820 dir = data;
2797 else 2821 else
2798 { 2822 {
2799 /* Just check for trailing '/' when deciding whether to append '/'. 2823 /* Just check for trailing '/' when deciding whether to append '/'.
2800 That's simpler than testing the two special cases "/" and "//", 2824 That's simpler than testing the two special cases "/" and "//",
2801 and it's a safe optimization here. */ 2825 and it's a safe optimization here. */
2802 char *buf = SAFE_ALLOCA (len + 3); 2826 char *buf = SAFE_ALLOCA (len + 3);
2803 memcpy (buf, file, len); 2827 memcpy (buf, data, len);
2804 strcpy (buf + len, &"/."[file[len - 1] == '/']); 2828 strcpy (buf + len, &"/."[data[len - 1] == '/']);
2805 dir = buf; 2829 dir = buf;
2806 } 2830 }
2807 2831
@@ -3624,13 +3648,14 @@ by calling `format-decode', which see. */)
3624 report_file_error ("Read error", orig_filename); 3648 report_file_error ("Read error", orig_filename);
3625 else if (nread > 0) 3649 else if (nread > 0)
3626 { 3650 {
3651 AUTO_STRING (name, " *code-converting-work*");
3627 struct buffer *prev = current_buffer; 3652 struct buffer *prev = current_buffer;
3628 Lisp_Object workbuf; 3653 Lisp_Object workbuf;
3629 struct buffer *buf; 3654 struct buffer *buf;
3630 3655
3631 record_unwind_current_buffer (); 3656 record_unwind_current_buffer ();
3632 3657
3633 workbuf = Fget_buffer_create (build_string (" *code-converting-work*")); 3658 workbuf = Fget_buffer_create (name);
3634 buf = XBUFFER (workbuf); 3659 buf = XBUFFER (workbuf);
3635 3660
3636 delete_all_overlays (buf); 3661 delete_all_overlays (buf);
@@ -5292,20 +5317,12 @@ If BUF is omitted or nil, it defaults to the current buffer.
5292See Info node `(elisp)Modification Time' for more details. */) 5317See Info node `(elisp)Modification Time' for more details. */)
5293 (Lisp_Object buf) 5318 (Lisp_Object buf)
5294{ 5319{
5295 struct buffer *b; 5320 struct buffer *b = decode_buffer (buf);
5296 struct stat st; 5321 struct stat st;
5297 Lisp_Object handler; 5322 Lisp_Object handler;
5298 Lisp_Object filename; 5323 Lisp_Object filename;
5299 struct timespec mtime; 5324 struct timespec mtime;
5300 5325
5301 if (NILP (buf))
5302 b = current_buffer;
5303 else
5304 {
5305 CHECK_BUFFER (buf);
5306 b = XBUFFER (buf);
5307 }
5308
5309 if (!STRINGP (BVAR (b, filename))) return Qt; 5326 if (!STRINGP (BVAR (b, filename))) return Qt;
5310 if (b->modtime.tv_nsec == UNKNOWN_MODTIME_NSECS) return Qt; 5327 if (b->modtime.tv_nsec == UNKNOWN_MODTIME_NSECS) return Qt;
5311 5328
@@ -5399,7 +5416,7 @@ An argument specifies the modification time value to use
5399static Lisp_Object 5416static Lisp_Object
5400auto_save_error (Lisp_Object error_val) 5417auto_save_error (Lisp_Object error_val)
5401{ 5418{
5402 Lisp_Object args[3], msg; 5419 Lisp_Object msg;
5403 int i; 5420 int i;
5404 struct gcpro gcpro1; 5421 struct gcpro gcpro1;
5405 5422
@@ -5407,10 +5424,10 @@ auto_save_error (Lisp_Object error_val)
5407 5424
5408 ring_bell (XFRAME (selected_frame)); 5425 ring_bell (XFRAME (selected_frame));
5409 5426
5410 args[0] = build_string ("Auto-saving %s: %s"); 5427 AUTO_STRING (format, "Auto-saving %s: %s");
5411 args[1] = BVAR (current_buffer, name); 5428 msg = Fformat (3, ((Lisp_Object [])
5412 args[2] = Ferror_message_string (error_val); 5429 {format, BVAR (current_buffer, name),
5413 msg = Fformat (3, args); 5430 Ferror_message_string (error_val)}));
5414 GCPRO1 (msg); 5431 GCPRO1 (msg);
5415 5432
5416 for (i = 0; i < 3; ++i) 5433 for (i = 0; i < 3; ++i)