aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2020-08-28 22:37:29 -0700
committerPaul Eggert2020-08-28 22:41:45 -0700
commit7d5807277ff614a337c7e4530bb8d0e0188c189b (patch)
tree7ac086b1c501ee1328baa51c9a1a436bcbda5633 /src
parent2b59cfaaa35283900f28d755d34b5049c5c67603 (diff)
downloademacs-7d5807277ff614a337c7e4530bb8d0e0188c189b.tar.gz
emacs-7d5807277ff614a337c7e4530bb8d0e0188c189b.zip
Revert recent expand-file-name changes if DOS_NT
* src/fileio.c (Fexpand_file_name): Restore pre-August-26 behavior, if DOS_NT. This should fix the recently-introduced expand-file-name bugs on DOS_NT (Bug#26911).
Diffstat (limited to 'src')
-rw-r--r--src/fileio.c66
1 files changed, 57 insertions, 9 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 66010b68783..c91af36fdf6 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -1372,6 +1372,14 @@ the root directory. */)
1372 1372
1373 length = newdirlim - newdir; 1373 length = newdirlim - newdir;
1374 1374
1375#ifdef DOS_NT
1376 /* Ignore any slash at the end of newdir, unless newdir is
1377 just "/" or "//". */
1378 while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
1379 && ! (length == 2 && IS_DIRECTORY_SEP (newdir[0])))
1380 length--;
1381#endif
1382
1375 /* Now concatenate the directory and name to new space in the stack frame. */ 1383 /* Now concatenate the directory and name to new space in the stack frame. */
1376 tlen = length + file_name_as_directory_slop + (nmlim - nm) + 1; 1384 tlen = length + file_name_as_directory_slop + (nmlim - nm) + 1;
1377 eassert (tlen >= file_name_as_directory_slop + 1); 1385 eassert (tlen >= file_name_as_directory_slop + 1);
@@ -1388,22 +1396,40 @@ the root directory. */)
1388 1396
1389 if (newdir) 1397 if (newdir)
1390 { 1398 {
1391 if (!collapse_newdir) 1399#ifndef DOS_NT
1400 bool treat_as_absolute = !collapse_newdir;
1401#else
1402 bool treat_as_absolute = !nm[0] || IS_DIRECTORY_SEP (nm[0]);
1403#endif
1404 if (treat_as_absolute)
1392 { 1405 {
1393 /* With ~ or ~user, leave NEWDIR as-is to avoid transforming 1406#ifdef DOS_NT
1394 it from a symlink (or a regular file!) into a directory. */ 1407 /* If newdir is effectively "C:/", then the drive letter will have
1395 memcpy (target, newdir, length); 1408 been stripped and newdir will be "/". Concatenating with an
1396 nbytes = length; 1409 absolute directory in nm produces "//", which will then be
1410 incorrectly treated as a network share. Ignore newdir in
1411 this case (keeping the drive letter). */
1412 if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0])
1413 && newdir[1] == '\0'))
1414#endif
1415 {
1416 /* With ~ or ~user, leave NEWDIR as-is to avoid transforming
1417 it from a symlink (or a regular file!) into a directory. */
1418 memcpy (target, newdir, length);
1419 nbytes = length;
1420 }
1397 } 1421 }
1398 else 1422 else
1399 nbytes = file_name_as_directory (target, newdir, length, multibyte); 1423 nbytes = file_name_as_directory (target, newdir, length, multibyte);
1400 1424
1425#ifndef DOS_NT
1401 /* If TARGET ends in a directory separator, omit leading 1426 /* If TARGET ends in a directory separator, omit leading
1402 directory separators from NM so that concatenating a TARGET "/" 1427 directory separators from NM so that concatenating a TARGET "/"
1403 to an NM "/foo" does not result in the incorrect "//foo". */ 1428 to an NM "/foo" does not result in the incorrect "//foo". */
1404 if (nbytes && IS_DIRECTORY_SEP (target[nbytes - 1])) 1429 if (nbytes && IS_DIRECTORY_SEP (target[nbytes - 1]))
1405 while (IS_DIRECTORY_SEP (nm[0])) 1430 while (IS_DIRECTORY_SEP (nm[0]))
1406 nm++; 1431 nm++;
1432#endif
1407 } 1433 }
1408 1434
1409 memcpy (target + nbytes, nm, nmlim - nm + 1); 1435 memcpy (target + nbytes, nm, nmlim - nm + 1);
@@ -1420,6 +1446,7 @@ the root directory. */)
1420 { 1446 {
1421 *o++ = *p++; 1447 *o++ = *p++;
1422 } 1448 }
1449#ifndef DOS_NT
1423 else if (p[1] == '.' && IS_DIRECTORY_SEP (p[2])) 1450 else if (p[1] == '.' && IS_DIRECTORY_SEP (p[2]))
1424 { 1451 {
1425 /* Replace "/./" with "/". */ 1452 /* Replace "/./" with "/". */
@@ -1432,6 +1459,18 @@ the root directory. */)
1432 *o++ = *p; 1459 *o++ = *p;
1433 p += 2; 1460 p += 2;
1434 } 1461 }
1462#else
1463 else if (p[1] == '.'
1464 && (IS_DIRECTORY_SEP (p[2])
1465 || p[2] == 0))
1466 {
1467 /* If "/." is the entire filename, keep the "/". Otherwise,
1468 just delete the whole "/.". */
1469 if (o == target && p[2] == '\0')
1470 *o++ = *p;
1471 p += 2;
1472 }
1473#endif
1435 else if (p[1] == '.' && p[2] == '.' 1474 else if (p[1] == '.' && p[2] == '.'
1436 /* `/../' is the "superroot" on certain file systems. 1475 /* `/../' is the "superroot" on certain file systems.
1437 Turned off on DOS_NT systems because they have no 1476 Turned off on DOS_NT systems because they have no
@@ -1445,9 +1484,7 @@ the root directory. */)
1445#endif 1484#endif
1446 && (IS_DIRECTORY_SEP (p[3]) || p[3] == 0)) 1485 && (IS_DIRECTORY_SEP (p[3]) || p[3] == 0))
1447 { 1486 {
1448#ifdef WINDOWSNT 1487#ifndef DOS_NT
1449 char *prev_o = o;
1450#endif
1451 while (o != target) 1488 while (o != target)
1452 { 1489 {
1453 o--; 1490 o--;
@@ -1459,11 +1496,22 @@ the root directory. */)
1459 break; 1496 break;
1460 } 1497 }
1461 } 1498 }
1462#ifdef WINDOWSNT 1499#else
1500# ifdef WINDOWSNT
1501 char *prev_o = o;
1502# endif
1503 while (o != target && (--o, !IS_DIRECTORY_SEP (*o)))
1504 continue;
1505# ifdef WINDOWSNT
1463 /* Don't go below server level in UNC filenames. */ 1506 /* Don't go below server level in UNC filenames. */
1464 if (o == target + 1 && IS_DIRECTORY_SEP (*o) 1507 if (o == target + 1 && IS_DIRECTORY_SEP (*o)
1465 && IS_DIRECTORY_SEP (*target)) 1508 && IS_DIRECTORY_SEP (*target))
1466 o = prev_o; 1509 o = prev_o;
1510 else
1511# endif
1512 /* Keep initial / only if this is the whole name. */
1513 if (o == target && IS_ANY_SEP (*o) && p[3] == 0)
1514 ++o;
1467#endif 1515#endif
1468 p += 3; 1516 p += 3;
1469 } 1517 }