diff options
| author | Paul Eggert | 2020-08-28 22:37:29 -0700 |
|---|---|---|
| committer | Paul Eggert | 2020-08-28 22:41:45 -0700 |
| commit | 7d5807277ff614a337c7e4530bb8d0e0188c189b (patch) | |
| tree | 7ac086b1c501ee1328baa51c9a1a436bcbda5633 /src | |
| parent | 2b59cfaaa35283900f28d755d34b5049c5c67603 (diff) | |
| download | emacs-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.c | 66 |
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 | } |