diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 65 | ||||
| -rw-r--r-- | src/callproc.c | 50 | ||||
| -rw-r--r-- | src/dired.c | 4 | ||||
| -rw-r--r-- | src/emacs.c | 2 | ||||
| -rw-r--r-- | src/fileio.c | 144 | ||||
| -rw-r--r-- | src/msdos.c | 6 | ||||
| -rw-r--r-- | src/msdos.h | 2 | ||||
| -rw-r--r-- | src/termcap.c | 2 | ||||
| -rw-r--r-- | src/unexw32.c | 2 | ||||
| -rw-r--r-- | src/w32.c | 23 | ||||
| -rw-r--r-- | src/w32.h | 2 | ||||
| -rw-r--r-- | src/w32fns.c | 2 | ||||
| -rw-r--r-- | src/w32proc.c | 8 |
13 files changed, 194 insertions, 118 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index b4c3195973c..092302d6492 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,68 @@ | |||
| 1 | 2013-02-02 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Avoid file time stamp bug on MS-Windows (Bug#13149). | ||
| 4 | * fileio.c (Fwrite_region): Don't use the heuristic on empty files, | ||
| 5 | as FAT32 doesn't update time stamps when truncating them. | ||
| 6 | Also, check that a file time stamp is not a multiple of 100 ns; | ||
| 7 | this should catch all instances of the problem on MS-Windows, | ||
| 8 | as its native file system resolution is 100 ns or worse, and | ||
| 9 | checking for a non-multiple of 100 ns should impose only a small | ||
| 10 | overhead on systems with ns resolution. | ||
| 11 | |||
| 12 | 2013-02-02 Eli Zaretskii <eliz@gnu.org> | ||
| 13 | |||
| 14 | Avoid encoding file names on MS-Windows when they need to be run | ||
| 15 | through dostounix_filename. | ||
| 16 | * w32.c (normalize_filename): Accept an additional argument | ||
| 17 | MULTIBYTE; if non-zero, traverse the file name by bytes and don't | ||
| 18 | downcase it even if w32-downcase-file-names is non-nil. | ||
| 19 | (dostounix_filename): Accept an additional argument MULTIBYTE and | ||
| 20 | pass it to normalize_filename. | ||
| 21 | (emacs_root_dir): Adjust. | ||
| 22 | |||
| 23 | * msdos.h (dostounix_filename): Adjust prototype. | ||
| 24 | |||
| 25 | * w32.h (dostounix_filename): Adjust prototype. | ||
| 26 | |||
| 27 | * msdos.c (dostounix_filename): Accept an additional argument and | ||
| 28 | ignore it. | ||
| 29 | (init_environment): Adjust callers of dostounix_filename. | ||
| 30 | |||
| 31 | * fileio.c (Ffile_name_directory, file_name_as_directory) | ||
| 32 | (directory_file_name, Fexpand_file_name) | ||
| 33 | (Fsubstitute_in_file_name): [DOS_NT] Adjust call to | ||
| 34 | dostounix_filename. | ||
| 35 | [WINDOWSNT]: Downcase file names if w32-downcase-file-names is | ||
| 36 | non-nil. | ||
| 37 | (Fsubstitute_in_file_name): [DOS_NT] Don't downcase environment | ||
| 38 | variables, as egetenv is case-insensitive for DOS_NT. | ||
| 39 | |||
| 40 | * dired.c (file_name_completion): Don't call Fdirectory_file_name | ||
| 41 | with an encoded file name. | ||
| 42 | |||
| 43 | * w32proc.c (Fw32_short_file_name, Fw32_long_file_name): Adjust | ||
| 44 | calls to dostounix_filename. | ||
| 45 | |||
| 46 | * w32fns.c (Fx_file_dialog): Adjust call to dostounix_filename. | ||
| 47 | |||
| 48 | * unexw32.c (unexec): Adjust call to dostounix_filename. | ||
| 49 | |||
| 50 | * termcap.c (tgetent) [MSDOS]: Adjust call to dostounix_filename. | ||
| 51 | |||
| 52 | * emacs.c (decode_env_path) [DOS_NT]: Adjust call to | ||
| 53 | dostounix_filename. | ||
| 54 | |||
| 55 | * callproc.c (Fcall_process) [MSDOS]: Adjust call to | ||
| 56 | dostounix_filename. | ||
| 57 | |||
| 58 | * callproc.c (Fcall_process): Make sure program name in PATH and | ||
| 59 | new_argv[0] is encoded, if needed. Otherwise, un-encoded string | ||
| 60 | is passed to exec/spawnve, which fails unless the file-name | ||
| 61 | encoding is UTF-8. | ||
| 62 | |||
| 63 | * w32proc.c (sys_spawnve): Make sure escape_char is initialized, | ||
| 64 | even if w32-quote-process-args is nil. | ||
| 65 | |||
| 1 | 2013-02-01 Paul Eggert <eggert@cs.ucla.edu> | 66 | 2013-02-01 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 67 | ||
| 3 | Fix timestamp bug when write-region appends nothing (Bug#13149). | 68 | Fix timestamp bug when write-region appends nothing (Bug#13149). |
diff --git a/src/callproc.c b/src/callproc.c index 5eba3271358..ea79da7ff5a 100644 --- a/src/callproc.c +++ b/src/callproc.c | |||
| @@ -445,28 +445,34 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) | |||
| 445 | path = Fsubstring (path, make_number (2), Qnil); | 445 | path = Fsubstring (path, make_number (2), Qnil); |
| 446 | 446 | ||
| 447 | new_argv = SAFE_ALLOCA ((nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv); | 447 | new_argv = SAFE_ALLOCA ((nargs > 4 ? nargs - 2 : 2) * sizeof *new_argv); |
| 448 | if (nargs > 4) | ||
| 449 | { | ||
| 450 | ptrdiff_t i; | ||
| 451 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; | ||
| 452 | 448 | ||
| 453 | GCPRO5 (infile, buffer, current_dir, path, error_file); | 449 | { |
| 454 | argument_coding.dst_multibyte = 0; | 450 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; |
| 455 | for (i = 4; i < nargs; i++) | 451 | |
| 456 | { | 452 | GCPRO5 (infile, buffer, current_dir, path, error_file); |
| 457 | argument_coding.src_multibyte = STRING_MULTIBYTE (args[i]); | 453 | if (nargs > 4) |
| 458 | if (CODING_REQUIRE_ENCODING (&argument_coding)) | 454 | { |
| 459 | /* We must encode this argument. */ | 455 | ptrdiff_t i; |
| 460 | args[i] = encode_coding_string (&argument_coding, args[i], 1); | 456 | |
| 461 | } | 457 | argument_coding.dst_multibyte = 0; |
| 462 | UNGCPRO; | 458 | for (i = 4; i < nargs; i++) |
| 463 | for (i = 4; i < nargs; i++) | 459 | { |
| 464 | new_argv[i - 3] = SSDATA (args[i]); | 460 | argument_coding.src_multibyte = STRING_MULTIBYTE (args[i]); |
| 465 | new_argv[i - 3] = 0; | 461 | if (CODING_REQUIRE_ENCODING (&argument_coding)) |
| 466 | } | 462 | /* We must encode this argument. */ |
| 467 | else | 463 | args[i] = encode_coding_string (&argument_coding, args[i], 1); |
| 468 | new_argv[1] = 0; | 464 | } |
| 469 | new_argv[0] = SSDATA (path); | 465 | for (i = 4; i < nargs; i++) |
| 466 | new_argv[i - 3] = SSDATA (args[i]); | ||
| 467 | new_argv[i - 3] = 0; | ||
| 468 | } | ||
| 469 | else | ||
| 470 | new_argv[1] = 0; | ||
| 471 | if (STRING_MULTIBYTE (path)) | ||
| 472 | path = ENCODE_FILE (path); | ||
| 473 | new_argv[0] = SSDATA (path); | ||
| 474 | UNGCPRO; | ||
| 475 | } | ||
| 470 | 476 | ||
| 471 | #ifdef MSDOS /* MW, July 1993 */ | 477 | #ifdef MSDOS /* MW, July 1993 */ |
| 472 | 478 | ||
| @@ -481,7 +487,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */) | |||
| 481 | tempfile = alloca (20); | 487 | tempfile = alloca (20); |
| 482 | *tempfile = '\0'; | 488 | *tempfile = '\0'; |
| 483 | } | 489 | } |
| 484 | dostounix_filename (tempfile); | 490 | dostounix_filename (tempfile, 0); |
| 485 | if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/') | 491 | if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/') |
| 486 | strcat (tempfile, "/"); | 492 | strcat (tempfile, "/"); |
| 487 | strcat (tempfile, "detmp.XXX"); | 493 | strcat (tempfile, "detmp.XXX"); |
diff --git a/src/dired.c b/src/dired.c index ed0571fe9fe..0e37568f211 100644 --- a/src/dired.c +++ b/src/dired.c | |||
| @@ -484,9 +484,9 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag, | |||
| 484 | on the encoded file name. */ | 484 | on the encoded file name. */ |
| 485 | encoded_file = STRING_MULTIBYTE (file) ? ENCODE_FILE (file) : file; | 485 | encoded_file = STRING_MULTIBYTE (file) ? ENCODE_FILE (file) : file; |
| 486 | 486 | ||
| 487 | encoded_dir = ENCODE_FILE (dirname); | 487 | encoded_dir = ENCODE_FILE (Fdirectory_file_name (dirname)); |
| 488 | 488 | ||
| 489 | d = open_directory (SSDATA (Fdirectory_file_name (encoded_dir)), &fd); | 489 | d = open_directory (SSDATA (encoded_dir), &fd); |
| 490 | if (!d) | 490 | if (!d) |
| 491 | report_file_error ("Opening directory", Fcons (dirname, Qnil)); | 491 | report_file_error ("Opening directory", Fcons (dirname, Qnil)); |
| 492 | 492 | ||
diff --git a/src/emacs.c b/src/emacs.c index 21c7a7cec03..ff29a042ea0 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -2158,7 +2158,7 @@ decode_env_path (const char *evarname, const char *defalt) | |||
| 2158 | { | 2158 | { |
| 2159 | char *path_copy = alloca (strlen (path) + 1); | 2159 | char *path_copy = alloca (strlen (path) + 1); |
| 2160 | strcpy (path_copy, path); | 2160 | strcpy (path_copy, path); |
| 2161 | dostounix_filename (path_copy); | 2161 | dostounix_filename (path_copy, 0); |
| 2162 | path = path_copy; | 2162 | path = path_copy; |
| 2163 | } | 2163 | } |
| 2164 | #endif | 2164 | #endif |
diff --git a/src/fileio.c b/src/fileio.c index fb6ecfedeb4..e76f2bc2420 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -383,11 +383,13 @@ Given a Unix syntax file name, returns a string ending in slash. */) | |||
| 383 | 383 | ||
| 384 | if (getdefdir (c_toupper (*beg) - 'A' + 1, r)) | 384 | if (getdefdir (c_toupper (*beg) - 'A' + 1, r)) |
| 385 | { | 385 | { |
| 386 | if (!IS_DIRECTORY_SEP (res[strlen (res) - 1])) | 386 | size_t l = strlen (res); |
| 387 | |||
| 388 | if (l > 3 || !IS_DIRECTORY_SEP (res[l - 1])) | ||
| 387 | strcat (res, "/"); | 389 | strcat (res, "/"); |
| 388 | beg = res; | 390 | beg = res; |
| 389 | p = beg + strlen (beg); | 391 | p = beg + strlen (beg); |
| 390 | dostounix_filename (beg); | 392 | dostounix_filename (beg, 0); |
| 391 | tem_fn = make_specified_string (beg, -1, p - beg, | 393 | tem_fn = make_specified_string (beg, -1, p - beg, |
| 392 | STRING_MULTIBYTE (filename)); | 394 | STRING_MULTIBYTE (filename)); |
| 393 | } | 395 | } |
| @@ -397,13 +399,16 @@ Given a Unix syntax file name, returns a string ending in slash. */) | |||
| 397 | } | 399 | } |
| 398 | else if (STRING_MULTIBYTE (filename)) | 400 | else if (STRING_MULTIBYTE (filename)) |
| 399 | { | 401 | { |
| 400 | tem_fn = ENCODE_FILE (make_specified_string (beg, -1, p - beg, 1)); | 402 | tem_fn = make_specified_string (beg, -1, p - beg, 1); |
| 401 | dostounix_filename (SSDATA (tem_fn)); | 403 | dostounix_filename (SSDATA (tem_fn), 1); |
| 402 | tem_fn = DECODE_FILE (tem_fn); | 404 | #ifdef WINDOWSNT |
| 405 | if (!NILP (Vw32_downcase_file_names)) | ||
| 406 | tem_fn = Fdowncase (tem_fn); | ||
| 407 | #endif | ||
| 403 | } | 408 | } |
| 404 | else | 409 | else |
| 405 | { | 410 | { |
| 406 | dostounix_filename (beg); | 411 | dostounix_filename (beg, 0); |
| 407 | tem_fn = make_specified_string (beg, -1, p - beg, 0); | 412 | tem_fn = make_specified_string (beg, -1, p - beg, 0); |
| 408 | } | 413 | } |
| 409 | return tem_fn; | 414 | return tem_fn; |
| @@ -507,17 +512,7 @@ file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen, | |||
| 507 | srclen++; | 512 | srclen++; |
| 508 | } | 513 | } |
| 509 | #ifdef DOS_NT | 514 | #ifdef DOS_NT |
| 510 | if (multibyte) | 515 | dostounix_filename (dst, multibyte); |
| 511 | { | ||
| 512 | Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1); | ||
| 513 | |||
| 514 | tem_fn = ENCODE_FILE (tem_fn); | ||
| 515 | dostounix_filename (SSDATA (tem_fn)); | ||
| 516 | tem_fn = DECODE_FILE (tem_fn); | ||
| 517 | memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1); | ||
| 518 | } | ||
| 519 | else | ||
| 520 | dostounix_filename (dst); | ||
| 521 | #endif | 516 | #endif |
| 522 | return srclen; | 517 | return srclen; |
| 523 | } | 518 | } |
| @@ -552,6 +547,10 @@ For a Unix-syntax file name, just appends a slash. */) | |||
| 552 | error ("Invalid handler in `file-name-handler-alist'"); | 547 | error ("Invalid handler in `file-name-handler-alist'"); |
| 553 | } | 548 | } |
| 554 | 549 | ||
| 550 | #ifdef WINDOWSNT | ||
| 551 | if (!NILP (Vw32_downcase_file_names)) | ||
| 552 | file = Fdowncase (file); | ||
| 553 | #endif | ||
| 555 | buf = alloca (SBYTES (file) + 10); | 554 | buf = alloca (SBYTES (file) + 10); |
| 556 | length = file_name_as_directory (buf, SSDATA (file), SBYTES (file), | 555 | length = file_name_as_directory (buf, SSDATA (file), SBYTES (file), |
| 557 | STRING_MULTIBYTE (file)); | 556 | STRING_MULTIBYTE (file)); |
| @@ -580,17 +579,7 @@ directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte) | |||
| 580 | srclen--; | 579 | srclen--; |
| 581 | } | 580 | } |
| 582 | #ifdef DOS_NT | 581 | #ifdef DOS_NT |
| 583 | if (multibyte) | 582 | dostounix_filename (dst, multibyte); |
| 584 | { | ||
| 585 | Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1); | ||
| 586 | |||
| 587 | tem_fn = ENCODE_FILE (tem_fn); | ||
| 588 | dostounix_filename (SSDATA (tem_fn)); | ||
| 589 | tem_fn = DECODE_FILE (tem_fn); | ||
| 590 | memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1); | ||
| 591 | } | ||
| 592 | else | ||
| 593 | dostounix_filename (dst); | ||
| 594 | #endif | 583 | #endif |
| 595 | return srclen; | 584 | return srclen; |
| 596 | } | 585 | } |
| @@ -625,6 +614,10 @@ In Unix-syntax, this function just removes the final slash. */) | |||
| 625 | error ("Invalid handler in `file-name-handler-alist'"); | 614 | error ("Invalid handler in `file-name-handler-alist'"); |
| 626 | } | 615 | } |
| 627 | 616 | ||
| 617 | #ifdef WINDOWSNT | ||
| 618 | if (!NILP (Vw32_downcase_file_names)) | ||
| 619 | directory = Fdowncase (directory); | ||
| 620 | #endif | ||
| 628 | buf = alloca (SBYTES (directory) + 20); | 621 | buf = alloca (SBYTES (directory) + 20); |
| 629 | length = directory_file_name (buf, SSDATA (directory), SBYTES (directory), | 622 | length = directory_file_name (buf, SSDATA (directory), SBYTES (directory), |
| 630 | STRING_MULTIBYTE (directory)); | 623 | STRING_MULTIBYTE (directory)); |
| @@ -925,6 +918,11 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 925 | } | 918 | } |
| 926 | } | 919 | } |
| 927 | 920 | ||
| 921 | #ifdef WINDOWSNT | ||
| 922 | if (!NILP (Vw32_downcase_file_names)) | ||
| 923 | default_directory = Fdowncase (default_directory); | ||
| 924 | #endif | ||
| 925 | |||
| 928 | /* Make a local copy of nm[] to protect it from GC in DECODE_FILE below. */ | 926 | /* Make a local copy of nm[] to protect it from GC in DECODE_FILE below. */ |
| 929 | nm = alloca (SBYTES (name) + 1); | 927 | nm = alloca (SBYTES (name) + 1); |
| 930 | memcpy (nm, SSDATA (name), SBYTES (name) + 1); | 928 | memcpy (nm, SSDATA (name), SBYTES (name) + 1); |
| @@ -1008,18 +1006,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 1008 | #ifdef DOS_NT | 1006 | #ifdef DOS_NT |
| 1009 | /* Make sure directories are all separated with /, but | 1007 | /* Make sure directories are all separated with /, but |
| 1010 | avoid allocation of a new string when not required. */ | 1008 | avoid allocation of a new string when not required. */ |
| 1011 | if (multibyte) | 1009 | dostounix_filename (nm, multibyte); |
| 1012 | { | ||
| 1013 | Lisp_Object tem_name = make_specified_string (nm, -1, strlen (nm), | ||
| 1014 | multibyte); | ||
| 1015 | |||
| 1016 | tem_name = ENCODE_FILE (tem_name); | ||
| 1017 | dostounix_filename (SSDATA (tem_name)); | ||
| 1018 | tem_name = DECODE_FILE (tem_name); | ||
| 1019 | memcpy (nm, SSDATA (tem_name), SBYTES (tem_name) + 1); | ||
| 1020 | } | ||
| 1021 | else | ||
| 1022 | dostounix_filename (nm); | ||
| 1023 | #ifdef WINDOWSNT | 1010 | #ifdef WINDOWSNT |
| 1024 | if (IS_DIRECTORY_SEP (nm[1])) | 1011 | if (IS_DIRECTORY_SEP (nm[1])) |
| 1025 | { | 1012 | { |
| @@ -1037,6 +1024,10 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 1037 | temp[0] = DRIVE_LETTER (drive); | 1024 | temp[0] = DRIVE_LETTER (drive); |
| 1038 | name = concat2 (build_string (temp), name); | 1025 | name = concat2 (build_string (temp), name); |
| 1039 | } | 1026 | } |
| 1027 | #ifdef WINDOWSNT | ||
| 1028 | if (!NILP (Vw32_downcase_file_names)) | ||
| 1029 | name = Fdowncase (name); | ||
| 1030 | #endif | ||
| 1040 | return name; | 1031 | return name; |
| 1041 | #else /* not DOS_NT */ | 1032 | #else /* not DOS_NT */ |
| 1042 | if (strcmp (nm, SSDATA (name)) == 0) | 1033 | if (strcmp (nm, SSDATA (name)) == 0) |
| @@ -1400,14 +1391,11 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 1400 | target[1] = ':'; | 1391 | target[1] = ':'; |
| 1401 | } | 1392 | } |
| 1402 | result = make_specified_string (target, -1, o - target, multibyte); | 1393 | result = make_specified_string (target, -1, o - target, multibyte); |
| 1403 | if (multibyte) | 1394 | dostounix_filename (SSDATA (result), multibyte); |
| 1404 | { | 1395 | #ifdef WINDOWSNT |
| 1405 | result = ENCODE_FILE (result); | 1396 | if (!NILP (Vw32_downcase_file_names)) |
| 1406 | dostounix_filename (SSDATA (result)); | 1397 | result = Fdowncase (result); |
| 1407 | result = DECODE_FILE (result); | 1398 | #endif |
| 1408 | } | ||
| 1409 | else | ||
| 1410 | dostounix_filename (SSDATA (result)); | ||
| 1411 | #else /* !DOS_NT */ | 1399 | #else /* !DOS_NT */ |
| 1412 | result = make_specified_string (target, -1, o - target, multibyte); | 1400 | result = make_specified_string (target, -1, o - target, multibyte); |
| 1413 | #endif /* !DOS_NT */ | 1401 | #endif /* !DOS_NT */ |
| @@ -1689,24 +1677,8 @@ those `/' is discarded. */) | |||
| 1689 | memcpy (nm, SDATA (filename), SBYTES (filename) + 1); | 1677 | memcpy (nm, SDATA (filename), SBYTES (filename) + 1); |
| 1690 | 1678 | ||
| 1691 | #ifdef DOS_NT | 1679 | #ifdef DOS_NT |
| 1692 | if (multibyte) | 1680 | dostounix_filename (nm, multibyte); |
| 1693 | { | 1681 | substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0); |
| 1694 | Lisp_Object encoded_filename = ENCODE_FILE (filename); | ||
| 1695 | Lisp_Object tem_fn; | ||
| 1696 | |||
| 1697 | dostounix_filename (SDATA (encoded_filename)); | ||
| 1698 | tem_fn = DECODE_FILE (encoded_filename); | ||
| 1699 | nm = alloca (SBYTES (tem_fn) + 1); | ||
| 1700 | memcpy (nm, SDATA (tem_fn), SBYTES (tem_fn) + 1); | ||
| 1701 | substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0); | ||
| 1702 | if (substituted) | ||
| 1703 | filename = tem_fn; | ||
| 1704 | } | ||
| 1705 | else | ||
| 1706 | { | ||
| 1707 | dostounix_filename (nm); | ||
| 1708 | substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0); | ||
| 1709 | } | ||
| 1710 | #endif | 1682 | #endif |
| 1711 | endp = nm + SBYTES (filename); | 1683 | endp = nm + SBYTES (filename); |
| 1712 | 1684 | ||
| @@ -1780,7 +1752,13 @@ those `/' is discarded. */) | |||
| 1780 | } | 1752 | } |
| 1781 | 1753 | ||
| 1782 | if (!substituted) | 1754 | if (!substituted) |
| 1783 | return filename; | 1755 | { |
| 1756 | #ifdef WINDOWSNT | ||
| 1757 | if (!NILP (Vw32_downcase_file_names)) | ||
| 1758 | filename = Fdowncase (filename); | ||
| 1759 | #endif | ||
| 1760 | return filename; | ||
| 1761 | } | ||
| 1784 | 1762 | ||
| 1785 | /* If substitution required, recopy the string and do it. */ | 1763 | /* If substitution required, recopy the string and do it. */ |
| 1786 | /* Make space in stack frame for the new copy. */ | 1764 | /* Make space in stack frame for the new copy. */ |
| @@ -1819,9 +1797,6 @@ those `/' is discarded. */) | |||
| 1819 | target = alloca (s - o + 1); | 1797 | target = alloca (s - o + 1); |
| 1820 | memcpy (target, o, s - o); | 1798 | memcpy (target, o, s - o); |
| 1821 | target[s - o] = 0; | 1799 | target[s - o] = 0; |
| 1822 | #ifdef DOS_NT | ||
| 1823 | strupr (target); /* $home == $HOME etc. */ | ||
| 1824 | #endif /* DOS_NT */ | ||
| 1825 | 1800 | ||
| 1826 | /* Get variable value. */ | 1801 | /* Get variable value. */ |
| 1827 | o = egetenv (target); | 1802 | o = egetenv (target); |
| @@ -1858,6 +1833,16 @@ those `/' is discarded. */) | |||
| 1858 | need to quote some $ to $$ first. */ | 1833 | need to quote some $ to $$ first. */ |
| 1859 | xnm = p; | 1834 | xnm = p; |
| 1860 | 1835 | ||
| 1836 | #ifdef WINDOWSNT | ||
| 1837 | if (!NILP (Vw32_downcase_file_names)) | ||
| 1838 | { | ||
| 1839 | Lisp_Object xname = make_specified_string (xnm, -1, x - xnm, multibyte); | ||
| 1840 | |||
| 1841 | xname = Fdowncase (xname); | ||
| 1842 | return xname; | ||
| 1843 | } | ||
| 1844 | else | ||
| 1845 | #endif | ||
| 1861 | return make_specified_string (xnm, -1, x - xnm, multibyte); | 1846 | return make_specified_string (xnm, -1, x - xnm, multibyte); |
| 1862 | 1847 | ||
| 1863 | badsubst: | 1848 | badsubst: |
| @@ -5035,11 +5020,22 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 5035 | if (fstat (desc1, &st1) == 0 | 5020 | if (fstat (desc1, &st1) == 0 |
| 5036 | && st.st_dev == st1.st_dev && st.st_ino == st1.st_ino) | 5021 | && st.st_dev == st1.st_dev && st.st_ino == st1.st_ino) |
| 5037 | { | 5022 | { |
| 5023 | /* Use the heuristic if it appears to be valid. With neither | ||
| 5024 | O_EXCL nor O_TRUNC, if Emacs happened to write nothing to the | ||
| 5025 | file, the time stamp won't change. Also, some non-POSIX | ||
| 5026 | systems don't update an empty file's time stamp when | ||
| 5027 | truncating it. Finally, file systems with 100 ns or worse | ||
| 5028 | resolution sometimes seem to have bugs: on a system with ns | ||
| 5029 | resolution, checking ns % 100 incorrectly avoids the heuristic | ||
| 5030 | 1% of the time, but the problem should be temporary as we will | ||
| 5031 | try again on the next time stamp. */ | ||
| 5032 | bool use_heuristic | ||
| 5033 | = ((open_flags & (O_EXCL | O_TRUNC)) != 0 | ||
| 5034 | && st.st_size != 0 | ||
| 5035 | && EMACS_NSECS (modtime) % 100 != 0); | ||
| 5036 | |||
| 5038 | EMACS_TIME modtime1 = get_stat_mtime (&st1); | 5037 | EMACS_TIME modtime1 = get_stat_mtime (&st1); |
| 5039 | /* If neither O_EXCL nor O_TRUNC is used, and Emacs happened to | 5038 | if (use_heuristic |
| 5040 | write nothing to the file, the file's time stamp won't change | ||
| 5041 | so it should not be used in this heuristic. */ | ||
| 5042 | if ((open_flags & (O_EXCL | O_TRUNC)) != 0 | ||
| 5043 | && EMACS_TIME_EQ (modtime, modtime1) | 5039 | && EMACS_TIME_EQ (modtime, modtime1) |
| 5044 | && st.st_size == st1.st_size) | 5040 | && st.st_size == st1.st_size) |
| 5045 | { | 5041 | { |
diff --git a/src/msdos.c b/src/msdos.c index 5174bc4dfcd..1b2deaf7478 100644 --- a/src/msdos.c +++ b/src/msdos.c | |||
| @@ -3339,7 +3339,7 @@ void msdos_downcase_filename (unsigned char *); | |||
| 3339 | /* Destructively turn backslashes into slashes. */ | 3339 | /* Destructively turn backslashes into slashes. */ |
| 3340 | 3340 | ||
| 3341 | void | 3341 | void |
| 3342 | dostounix_filename (char *p) | 3342 | dostounix_filename (char *p, int ignore) |
| 3343 | { | 3343 | { |
| 3344 | msdos_downcase_filename (p); | 3344 | msdos_downcase_filename (p); |
| 3345 | 3345 | ||
| @@ -3603,7 +3603,7 @@ init_environment (int argc, char **argv, int skip_args) | |||
| 3603 | if (!s) s = "c:/command.com"; | 3603 | if (!s) s = "c:/command.com"; |
| 3604 | t = alloca (strlen (s) + 1); | 3604 | t = alloca (strlen (s) + 1); |
| 3605 | strcpy (t, s); | 3605 | strcpy (t, s); |
| 3606 | dostounix_filename (t); | 3606 | dostounix_filename (t, 0); |
| 3607 | setenv ("SHELL", t, 0); | 3607 | setenv ("SHELL", t, 0); |
| 3608 | 3608 | ||
| 3609 | /* PATH is also downcased and backslashes mirrored. */ | 3609 | /* PATH is also downcased and backslashes mirrored. */ |
| @@ -3613,7 +3613,7 @@ init_environment (int argc, char **argv, int skip_args) | |||
| 3613 | /* Current directory is always considered part of MsDos's path but it is | 3613 | /* Current directory is always considered part of MsDos's path but it is |
| 3614 | not normally mentioned. Now it is. */ | 3614 | not normally mentioned. Now it is. */ |
| 3615 | strcat (strcpy (t, ".;"), s); | 3615 | strcat (strcpy (t, ".;"), s); |
| 3616 | dostounix_filename (t); /* Not a single file name, but this should work. */ | 3616 | dostounix_filename (t, 0); /* Not a single file name, but this should work. */ |
| 3617 | setenv ("PATH", t, 1); | 3617 | setenv ("PATH", t, 1); |
| 3618 | 3618 | ||
| 3619 | /* In some sense all dos users have root privileges, so... */ | 3619 | /* In some sense all dos users have root privileges, so... */ |
diff --git a/src/msdos.h b/src/msdos.h index 57609d62218..ee0d49464ae 100644 --- a/src/msdos.h +++ b/src/msdos.h | |||
| @@ -29,7 +29,7 @@ void dos_set_window_size (int *, int *); | |||
| 29 | 29 | ||
| 30 | int getdefdir (int, char*); | 30 | int getdefdir (int, char*); |
| 31 | void unixtodos_filename (char *); | 31 | void unixtodos_filename (char *); |
| 32 | void dostounix_filename (char *); | 32 | void dostounix_filename (char *, int); |
| 33 | char *rootrelativepath (char *); | 33 | char *rootrelativepath (char *); |
| 34 | void init_environment (int, char **, int); | 34 | void init_environment (int, char **, int); |
| 35 | void internal_terminal_init (void); | 35 | void internal_terminal_init (void); |
diff --git a/src/termcap.c b/src/termcap.c index 82c2b1fda07..99bbfce27f5 100644 --- a/src/termcap.c +++ b/src/termcap.c | |||
| @@ -393,7 +393,7 @@ tgetent (char *bp, const char *name) | |||
| 393 | if (termcap_name && (*termcap_name == '\\' | 393 | if (termcap_name && (*termcap_name == '\\' |
| 394 | || *termcap_name == '/' | 394 | || *termcap_name == '/' |
| 395 | || termcap_name[1] == ':')) | 395 | || termcap_name[1] == ':')) |
| 396 | dostounix_filename (termcap_name); | 396 | dostounix_filename (termcap_name, 0); |
| 397 | #endif | 397 | #endif |
| 398 | 398 | ||
| 399 | filep = termcap_name && valid_filename_p (termcap_name); | 399 | filep = termcap_name && valid_filename_p (termcap_name); |
diff --git a/src/unexw32.c b/src/unexw32.c index 66071295727..e8b553a87d3 100644 --- a/src/unexw32.c +++ b/src/unexw32.c | |||
| @@ -722,7 +722,7 @@ unexec (const char *new_name, const char *old_name) | |||
| 722 | /* Ignore old_name, and get our actual location from the OS. */ | 722 | /* Ignore old_name, and get our actual location from the OS. */ |
| 723 | if (!GetModuleFileName (NULL, in_filename, MAX_PATH)) | 723 | if (!GetModuleFileName (NULL, in_filename, MAX_PATH)) |
| 724 | abort (); | 724 | abort (); |
| 725 | dostounix_filename (in_filename); | 725 | dostounix_filename (in_filename, 0); |
| 726 | strcpy (out_filename, in_filename); | 726 | strcpy (out_filename, in_filename); |
| 727 | 727 | ||
| 728 | /* Change the base of the output filename to match the requested name. */ | 728 | /* Change the base of the output filename to match the requested name. */ |
| @@ -1598,12 +1598,17 @@ max_filename_mbslen (void) | |||
| 1598 | case path name components to lower case. */ | 1598 | case path name components to lower case. */ |
| 1599 | 1599 | ||
| 1600 | static void | 1600 | static void |
| 1601 | normalize_filename (register char *fp, char path_sep) | 1601 | normalize_filename (register char *fp, char path_sep, int multibyte) |
| 1602 | { | 1602 | { |
| 1603 | char sep; | 1603 | char sep; |
| 1604 | char *elem, *p2; | 1604 | char *elem, *p2; |
| 1605 | int dbcs_p = max_filename_mbslen () > 1; | 1605 | int dbcs_p = max_filename_mbslen () > 1; |
| 1606 | 1606 | ||
| 1607 | /* Multibyte file names are in the Emacs internal representation, so | ||
| 1608 | we can traverse them by bytes with no problems. */ | ||
| 1609 | if (multibyte) | ||
| 1610 | dbcs_p = 0; | ||
| 1611 | |||
| 1607 | /* Always lower-case drive letters a-z, even if the filesystem | 1612 | /* Always lower-case drive letters a-z, even if the filesystem |
| 1608 | preserves case in filenames. | 1613 | preserves case in filenames. |
| 1609 | This is so filenames can be compared by string comparison | 1614 | This is so filenames can be compared by string comparison |
| @@ -1620,7 +1625,7 @@ normalize_filename (register char *fp, char path_sep) | |||
| 1620 | fp += 2; | 1625 | fp += 2; |
| 1621 | } | 1626 | } |
| 1622 | 1627 | ||
| 1623 | if (NILP (Vw32_downcase_file_names)) | 1628 | if (multibyte || NILP (Vw32_downcase_file_names)) |
| 1624 | { | 1629 | { |
| 1625 | while (*fp) | 1630 | while (*fp) |
| 1626 | { | 1631 | { |
| @@ -1668,18 +1673,20 @@ normalize_filename (register char *fp, char path_sep) | |||
| 1668 | } while (*fp); | 1673 | } while (*fp); |
| 1669 | } | 1674 | } |
| 1670 | 1675 | ||
| 1671 | /* Destructively turn backslashes into slashes. */ | 1676 | /* Destructively turn backslashes into slashes. MULTIBYTE non-zero |
| 1677 | means the file name is a multibyte string in Emacs's internal | ||
| 1678 | representation. */ | ||
| 1672 | void | 1679 | void |
| 1673 | dostounix_filename (register char *p) | 1680 | dostounix_filename (register char *p, int multibyte) |
| 1674 | { | 1681 | { |
| 1675 | normalize_filename (p, '/'); | 1682 | normalize_filename (p, '/', multibyte); |
| 1676 | } | 1683 | } |
| 1677 | 1684 | ||
| 1678 | /* Destructively turn slashes into backslashes. */ | 1685 | /* Destructively turn slashes into backslashes. */ |
| 1679 | void | 1686 | void |
| 1680 | unixtodos_filename (register char *p) | 1687 | unixtodos_filename (register char *p) |
| 1681 | { | 1688 | { |
| 1682 | normalize_filename (p, '\\'); | 1689 | normalize_filename (p, '\\', 0); |
| 1683 | } | 1690 | } |
| 1684 | 1691 | ||
| 1685 | /* Remove all CR's that are followed by a LF. | 1692 | /* Remove all CR's that are followed by a LF. |
| @@ -2222,7 +2229,7 @@ emacs_root_dir (void) | |||
| 2222 | emacs_abort (); | 2229 | emacs_abort (); |
| 2223 | strcpy (root_dir, p); | 2230 | strcpy (root_dir, p); |
| 2224 | root_dir[parse_root (root_dir, NULL)] = '\0'; | 2231 | root_dir[parse_root (root_dir, NULL)] = '\0'; |
| 2225 | dostounix_filename (root_dir); | 2232 | dostounix_filename (root_dir, 0); |
| 2226 | return root_dir; | 2233 | return root_dir; |
| 2227 | } | 2234 | } |
| 2228 | 2235 | ||
| @@ -4280,7 +4287,7 @@ fstatat (int fd, char const *name, struct stat *st, int flags) | |||
| 4280 | /* Rely on a hack: an open directory is modeled as file descriptor 0. | 4287 | /* Rely on a hack: an open directory is modeled as file descriptor 0. |
| 4281 | This is good enough for the current usage in Emacs, but is fragile. | 4288 | This is good enough for the current usage in Emacs, but is fragile. |
| 4282 | 4289 | ||
| 4283 | FIXME: Add proper support for fdopendir, fstatatat, readlinkat. | 4290 | FIXME: Add proper support for fdopendir, fstatat, readlinkat. |
| 4284 | Gnulib does this and can serve as a model. */ | 4291 | Gnulib does this and can serve as a model. */ |
| 4285 | char fullname[MAX_PATH]; | 4292 | char fullname[MAX_PATH]; |
| 4286 | 4293 | ||
| @@ -180,7 +180,7 @@ extern void init_environment (char **); | |||
| 180 | extern void check_windows_init_file (void); | 180 | extern void check_windows_init_file (void); |
| 181 | extern void syms_of_ntproc (void); | 181 | extern void syms_of_ntproc (void); |
| 182 | extern void syms_of_ntterm (void); | 182 | extern void syms_of_ntterm (void); |
| 183 | extern void dostounix_filename (register char *); | 183 | extern void dostounix_filename (register char *, int); |
| 184 | extern void unixtodos_filename (register char *); | 184 | extern void unixtodos_filename (register char *); |
| 185 | extern BOOL init_winsock (int load_now); | 185 | extern BOOL init_winsock (int load_now); |
| 186 | extern void srandom (int); | 186 | extern void srandom (int); |
diff --git a/src/w32fns.c b/src/w32fns.c index 6c098cae3a3..0841ad3468e 100644 --- a/src/w32fns.c +++ b/src/w32fns.c | |||
| @@ -6254,7 +6254,7 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */) | |||
| 6254 | /* we get one of the two final 0 bytes for free. */ | 6254 | /* we get one of the two final 0 bytes for free. */ |
| 6255 | 1 + sizeof (wchar_t) * wcslen (filename_buf))); | 6255 | 1 + sizeof (wchar_t) * wcslen (filename_buf))); |
| 6256 | #else /* !NTGUI_UNICODE */ | 6256 | #else /* !NTGUI_UNICODE */ |
| 6257 | dostounix_filename (filename_buf); | 6257 | dostounix_filename (filename_buf, 0); |
| 6258 | filename = DECODE_FILE (build_string (filename_buf)); | 6258 | filename = DECODE_FILE (build_string (filename_buf)); |
| 6259 | #endif /* NTGUI_UNICODE */ | 6259 | #endif /* NTGUI_UNICODE */ |
| 6260 | 6260 | ||
diff --git a/src/w32proc.c b/src/w32proc.c index 0fcb2993020..8bf57602927 100644 --- a/src/w32proc.c +++ b/src/w32proc.c | |||
| @@ -1541,7 +1541,6 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) | |||
| 1541 | child_process *cp; | 1541 | child_process *cp; |
| 1542 | int is_dos_app, is_cygnus_app, is_gui_app; | 1542 | int is_dos_app, is_cygnus_app, is_gui_app; |
| 1543 | int do_quoting = 0; | 1543 | int do_quoting = 0; |
| 1544 | char escape_char; | ||
| 1545 | /* We pass our process ID to our children by setting up an environment | 1544 | /* We pass our process ID to our children by setting up an environment |
| 1546 | variable in their environment. */ | 1545 | variable in their environment. */ |
| 1547 | char ppid_env_var_buffer[64]; | 1546 | char ppid_env_var_buffer[64]; |
| @@ -1554,6 +1553,8 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) | |||
| 1554 | Some extra whitespace characters need quoting in Cygwin programs, | 1553 | Some extra whitespace characters need quoting in Cygwin programs, |
| 1555 | so this list is conditionally modified below. */ | 1554 | so this list is conditionally modified below. */ |
| 1556 | char *sepchars = " \t*?"; | 1555 | char *sepchars = " \t*?"; |
| 1556 | /* This is for native w32 apps; modified below for Cygwin apps. */ | ||
| 1557 | char escape_char = '\\'; | ||
| 1557 | 1558 | ||
| 1558 | /* We don't care about the other modes */ | 1559 | /* We don't care about the other modes */ |
| 1559 | if (mode != _P_NOWAIT) | 1560 | if (mode != _P_NOWAIT) |
| @@ -2557,8 +2558,9 @@ All path elements in FILENAME are converted to their short names. */) | |||
| 2557 | if (GetShortPathName (SDATA (ENCODE_FILE (filename)), shortname, MAX_PATH) == 0) | 2558 | if (GetShortPathName (SDATA (ENCODE_FILE (filename)), shortname, MAX_PATH) == 0) |
| 2558 | return Qnil; | 2559 | return Qnil; |
| 2559 | 2560 | ||
| 2560 | dostounix_filename (shortname); | 2561 | dostounix_filename (shortname, 0); |
| 2561 | 2562 | ||
| 2563 | /* No need to DECODE_FILE, because 8.3 names are pure ASCII. */ | ||
| 2562 | return build_string (shortname); | 2564 | return build_string (shortname); |
| 2563 | } | 2565 | } |
| 2564 | 2566 | ||
| @@ -2585,7 +2587,7 @@ All path elements in FILENAME are converted to their long names. */) | |||
| 2585 | if (!w32_get_long_filename (SDATA (ENCODE_FILE (filename)), longname, MAX_PATH)) | 2587 | if (!w32_get_long_filename (SDATA (ENCODE_FILE (filename)), longname, MAX_PATH)) |
| 2586 | return Qnil; | 2588 | return Qnil; |
| 2587 | 2589 | ||
| 2588 | dostounix_filename (longname); | 2590 | dostounix_filename (longname, 0); |
| 2589 | 2591 | ||
| 2590 | /* If we were passed only a drive, make sure that a slash is not appended | 2592 | /* If we were passed only a drive, make sure that a slash is not appended |
| 2591 | for consistency with directories. Allow for drive mapping via SUBST | 2593 | for consistency with directories. Allow for drive mapping via SUBST |