diff options
| author | Michael Albinus | 2017-08-02 11:01:05 +0200 |
|---|---|---|
| committer | Michael Albinus | 2017-08-02 11:01:05 +0200 |
| commit | 49d6e59717ad182487910b863656bb6a11080bcf (patch) | |
| tree | 50e78797cbeb8b243ac3773237ea33dd3725df44 /src | |
| parent | 4207733f4aefd17fd06e7820775d4c2359daba87 (diff) | |
| parent | 1f9f514e7c2ba41b0954d0141f99652f6a53a107 (diff) | |
| download | emacs-49d6e59717ad182487910b863656bb6a11080bcf.tar.gz emacs-49d6e59717ad182487910b863656bb6a11080bcf.zip | |
Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs
Diffstat (limited to 'src')
| -rw-r--r-- | src/fileio.c | 141 | ||||
| -rw-r--r-- | src/filelock.c | 3 | ||||
| -rw-r--r-- | src/lisp.h | 6 | ||||
| -rw-r--r-- | src/sysdep.c | 20 |
4 files changed, 100 insertions, 70 deletions
diff --git a/src/fileio.c b/src/fileio.c index 7531214fe45..0264c9fa1d8 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -2311,6 +2311,7 @@ This is what happens in interactive use with M-x. */) | |||
| 2311 | { | 2311 | { |
| 2312 | Lisp_Object handler; | 2312 | Lisp_Object handler; |
| 2313 | Lisp_Object encoded_file, encoded_newname, symlink_target; | 2313 | Lisp_Object encoded_file, encoded_newname, symlink_target; |
| 2314 | int dirp = -1; | ||
| 2314 | 2315 | ||
| 2315 | symlink_target = encoded_file = encoded_newname = Qnil; | 2316 | symlink_target = encoded_file = encoded_newname = Qnil; |
| 2316 | CHECK_STRING (file); | 2317 | CHECK_STRING (file); |
| @@ -2324,8 +2325,8 @@ This is what happens in interactive use with M-x. */) | |||
| 2324 | && (NILP (Ffile_name_case_insensitive_p (file)) | 2325 | && (NILP (Ffile_name_case_insensitive_p (file)) |
| 2325 | || NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname))))) | 2326 | || NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname))))) |
| 2326 | { | 2327 | { |
| 2327 | Lisp_Object fname = (NILP (Ffile_directory_p (file)) | 2328 | dirp = !NILP (Ffile_directory_p (file)); |
| 2328 | ? file : Fdirectory_file_name (file)); | 2329 | Lisp_Object fname = dirp ? Fdirectory_file_name (file) : file; |
| 2329 | newname = Fexpand_file_name (Ffile_name_nondirectory (fname), newname); | 2330 | newname = Fexpand_file_name (Ffile_name_nondirectory (fname), newname); |
| 2330 | } | 2331 | } |
| 2331 | else | 2332 | else |
| @@ -2343,47 +2344,55 @@ This is what happens in interactive use with M-x. */) | |||
| 2343 | encoded_file = ENCODE_FILE (file); | 2344 | encoded_file = ENCODE_FILE (file); |
| 2344 | encoded_newname = ENCODE_FILE (newname); | 2345 | encoded_newname = ENCODE_FILE (newname); |
| 2345 | 2346 | ||
| 2346 | /* If the filesystem is case-insensitive and the file names are | 2347 | if (renameat_noreplace (AT_FDCWD, SSDATA (encoded_file), |
| 2347 | identical but for the case, don't ask for confirmation: they | 2348 | AT_FDCWD, SSDATA (encoded_newname)) |
| 2348 | simply want to change the letter-case of the file name. */ | 2349 | == 0) |
| 2349 | if ((!(file_name_case_insensitive_p (SSDATA (encoded_file))) | 2350 | return Qnil; |
| 2350 | || NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname)))) | 2351 | int rename_errno = errno; |
| 2351 | && ((NILP (ok_if_already_exists) || INTEGERP (ok_if_already_exists)))) | 2352 | |
| 2352 | barf_or_query_if_file_exists (newname, false, "rename to it", | 2353 | if (rename_errno == EEXIST || rename_errno == ENOSYS) |
| 2353 | INTEGERP (ok_if_already_exists), false); | ||
| 2354 | if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0) | ||
| 2355 | { | 2354 | { |
| 2356 | int rename_errno = errno; | 2355 | /* If the filesystem is case-insensitive and the file names are |
| 2357 | if (rename_errno == EXDEV) | 2356 | identical but for the case, don't ask for confirmation: they |
| 2358 | { | 2357 | simply want to change the letter-case of the file name. */ |
| 2359 | ptrdiff_t count; | 2358 | if ((NILP (ok_if_already_exists) || INTEGERP (ok_if_already_exists)) |
| 2360 | symlink_target = Ffile_symlink_p (file); | 2359 | && (! file_name_case_insensitive_p (SSDATA (encoded_file)) |
| 2361 | if (! NILP (symlink_target)) | 2360 | || NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname))))) |
| 2362 | Fmake_symbolic_link (symlink_target, newname, | 2361 | barf_or_query_if_file_exists (newname, rename_errno == EEXIST, |
| 2363 | NILP (ok_if_already_exists) ? Qnil : Qt); | 2362 | "rename to it", |
| 2364 | else if (!NILP (Ffile_directory_p (file))) | 2363 | INTEGERP (ok_if_already_exists), false); |
| 2365 | call4 (Qcopy_directory, file, newname, Qt, Qnil); | 2364 | if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) == 0) |
| 2366 | else | 2365 | return Qnil; |
| 2367 | /* We have already prompted if it was an integer, so don't | 2366 | rename_errno = errno; |
| 2368 | have copy-file prompt again. */ | 2367 | /* Don't prompt again. */ |
| 2369 | Fcopy_file (file, newname, | 2368 | ok_if_already_exists = Qt; |
| 2370 | NILP (ok_if_already_exists) ? Qnil : Qt, | 2369 | } |
| 2371 | Qt, Qt, Qt); | 2370 | else if (!NILP (ok_if_already_exists)) |
| 2371 | ok_if_already_exists = Qt; | ||
| 2372 | 2372 | ||
| 2373 | count = SPECPDL_INDEX (); | 2373 | if (rename_errno != EXDEV) |
| 2374 | specbind (Qdelete_by_moving_to_trash, Qnil); | 2374 | report_file_errno ("Renaming", list2 (file, newname), rename_errno); |
| 2375 | 2375 | ||
| 2376 | if (!NILP (Ffile_directory_p (file)) && NILP (symlink_target)) | 2376 | symlink_target = Ffile_symlink_p (file); |
| 2377 | call2 (Qdelete_directory, file, Qt); | 2377 | if (!NILP (symlink_target)) |
| 2378 | else | 2378 | Fmake_symbolic_link (symlink_target, newname, ok_if_already_exists); |
| 2379 | Fdelete_file (file, Qnil); | 2379 | else |
| 2380 | unbind_to (count, Qnil); | 2380 | { |
| 2381 | } | 2381 | if (dirp < 0) |
| 2382 | dirp = !NILP (Ffile_directory_p (file)); | ||
| 2383 | if (dirp) | ||
| 2384 | call4 (Qcopy_directory, file, newname, Qt, Qnil); | ||
| 2382 | else | 2385 | else |
| 2383 | report_file_errno ("Renaming", list2 (file, newname), rename_errno); | 2386 | Fcopy_file (file, newname, ok_if_already_exists, Qt, Qt, Qt); |
| 2384 | } | 2387 | } |
| 2385 | 2388 | ||
| 2386 | return Qnil; | 2389 | ptrdiff_t count = SPECPDL_INDEX (); |
| 2390 | specbind (Qdelete_by_moving_to_trash, Qnil); | ||
| 2391 | if (dirp && NILP (symlink_target)) | ||
| 2392 | call2 (Qdelete_directory, file, Qt); | ||
| 2393 | else | ||
| 2394 | Fdelete_file (file, Qnil); | ||
| 2395 | return unbind_to (count, Qnil); | ||
| 2387 | } | 2396 | } |
| 2388 | 2397 | ||
| 2389 | DEFUN ("add-name-to-file", Fadd_name_to_file, Sadd_name_to_file, 2, 3, | 2398 | DEFUN ("add-name-to-file", Fadd_name_to_file, Sadd_name_to_file, 2, 3, |
| @@ -2425,19 +2434,21 @@ This is what happens in interactive use with M-x. */) | |||
| 2425 | encoded_file = ENCODE_FILE (file); | 2434 | encoded_file = ENCODE_FILE (file); |
| 2426 | encoded_newname = ENCODE_FILE (newname); | 2435 | encoded_newname = ENCODE_FILE (newname); |
| 2427 | 2436 | ||
| 2428 | if (NILP (ok_if_already_exists) | 2437 | if (link (SSDATA (encoded_file), SSDATA (encoded_newname)) == 0) |
| 2429 | || INTEGERP (ok_if_already_exists)) | 2438 | return Qnil; |
| 2430 | barf_or_query_if_file_exists (newname, false, "make it a new name", | ||
| 2431 | INTEGERP (ok_if_already_exists), false); | ||
| 2432 | 2439 | ||
| 2433 | unlink (SSDATA (newname)); | 2440 | if (errno == EEXIST) |
| 2434 | if (link (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0) | ||
| 2435 | { | 2441 | { |
| 2436 | int link_errno = errno; | 2442 | if (NILP (ok_if_already_exists) |
| 2437 | report_file_errno ("Adding new name", list2 (file, newname), link_errno); | 2443 | || INTEGERP (ok_if_already_exists)) |
| 2444 | barf_or_query_if_file_exists (newname, true, "make it a new name", | ||
| 2445 | INTEGERP (ok_if_already_exists), false); | ||
| 2446 | unlink (SSDATA (newname)); | ||
| 2447 | if (link (SSDATA (encoded_file), SSDATA (encoded_newname)) == 0) | ||
| 2448 | return Qnil; | ||
| 2438 | } | 2449 | } |
| 2439 | 2450 | ||
| 2440 | return Qnil; | 2451 | report_file_error ("Adding new name", list2 (file, newname)); |
| 2441 | } | 2452 | } |
| 2442 | 2453 | ||
| 2443 | DEFUN ("make-symbolic-link", Fmake_symbolic_link, Smake_symbolic_link, 2, 3, | 2454 | DEFUN ("make-symbolic-link", Fmake_symbolic_link, Smake_symbolic_link, 2, 3, |
| @@ -2484,31 +2495,25 @@ This happens for interactive use with M-x. */) | |||
| 2484 | encoded_target = ENCODE_FILE (target); | 2495 | encoded_target = ENCODE_FILE (target); |
| 2485 | encoded_linkname = ENCODE_FILE (linkname); | 2496 | encoded_linkname = ENCODE_FILE (linkname); |
| 2486 | 2497 | ||
| 2487 | if (NILP (ok_if_already_exists) | 2498 | if (symlink (SSDATA (encoded_target), SSDATA (encoded_linkname)) == 0) |
| 2488 | || INTEGERP (ok_if_already_exists)) | 2499 | return Qnil; |
| 2489 | barf_or_query_if_file_exists (linkname, false, "make it a link", | ||
| 2490 | INTEGERP (ok_if_already_exists), false); | ||
| 2491 | if (symlink (SSDATA (encoded_target), SSDATA (encoded_linkname)) < 0) | ||
| 2492 | { | ||
| 2493 | /* If we didn't complain already, silently delete existing file. */ | ||
| 2494 | int symlink_errno; | ||
| 2495 | if (errno == EEXIST) | ||
| 2496 | { | ||
| 2497 | unlink (SSDATA (encoded_linkname)); | ||
| 2498 | if (symlink (SSDATA (encoded_target), SSDATA (encoded_linkname)) | ||
| 2499 | >= 0) | ||
| 2500 | return Qnil; | ||
| 2501 | } | ||
| 2502 | if (errno == ENOSYS) | ||
| 2503 | xsignal1 (Qfile_error, | ||
| 2504 | build_string ("Symbolic links are not supported")); | ||
| 2505 | 2500 | ||
| 2506 | symlink_errno = errno; | 2501 | if (errno == ENOSYS) |
| 2507 | report_file_errno ("Making symbolic link", list2 (target, linkname), | 2502 | xsignal1 (Qfile_error, |
| 2508 | symlink_errno); | 2503 | build_string ("Symbolic links are not supported")); |
| 2504 | |||
| 2505 | if (errno == EEXIST) | ||
| 2506 | { | ||
| 2507 | if (NILP (ok_if_already_exists) | ||
| 2508 | || INTEGERP (ok_if_already_exists)) | ||
| 2509 | barf_or_query_if_file_exists (linkname, true, "make it a link", | ||
| 2510 | INTEGERP (ok_if_already_exists), false); | ||
| 2511 | unlink (SSDATA (encoded_linkname)); | ||
| 2512 | if (symlink (SSDATA (encoded_target), SSDATA (encoded_linkname)) == 0) | ||
| 2513 | return Qnil; | ||
| 2509 | } | 2514 | } |
| 2510 | 2515 | ||
| 2511 | return Qnil; | 2516 | report_file_error ("Making symbolic link", list2 (target, linkname)); |
| 2512 | } | 2517 | } |
| 2513 | 2518 | ||
| 2514 | 2519 | ||
diff --git a/src/filelock.c b/src/filelock.c index bfa1d63d833..dd8cb28c425 100644 --- a/src/filelock.c +++ b/src/filelock.c | |||
| @@ -339,6 +339,9 @@ rename_lock_file (char const *old, char const *new, bool force) | |||
| 339 | { | 339 | { |
| 340 | struct stat st; | 340 | struct stat st; |
| 341 | 341 | ||
| 342 | int r = renameat_noreplace (AT_FDCWD, old, AT_FDCWD, new); | ||
| 343 | if (! (r < 0 && errno == ENOSYS)) | ||
| 344 | return r; | ||
| 342 | if (link (old, new) == 0) | 345 | if (link (old, new) == 0) |
| 343 | return unlink (old) == 0 || errno == ENOENT ? 0 : -1; | 346 | return unlink (old) == 0 || errno == ENOENT ? 0 : -1; |
| 344 | if (errno != ENOSYS && errno != LINKS_MIGHT_NOT_WORK) | 347 | if (errno != ENOSYS && errno != LINKS_MIGHT_NOT_WORK) |
diff --git a/src/lisp.h b/src/lisp.h index cffaf954b3b..4de6fc85ec1 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -4298,13 +4298,15 @@ extern ptrdiff_t emacs_write (int, void const *, ptrdiff_t); | |||
| 4298 | extern ptrdiff_t emacs_write_sig (int, void const *, ptrdiff_t); | 4298 | extern ptrdiff_t emacs_write_sig (int, void const *, ptrdiff_t); |
| 4299 | extern ptrdiff_t emacs_write_quit (int, void const *, ptrdiff_t); | 4299 | extern ptrdiff_t emacs_write_quit (int, void const *, ptrdiff_t); |
| 4300 | extern void emacs_perror (char const *); | 4300 | extern void emacs_perror (char const *); |
| 4301 | extern int renameat_noreplace (int, char const *, int, char const *); | ||
| 4302 | extern int str_collate (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); | ||
| 4301 | 4303 | ||
| 4302 | extern void unlock_all_files (void); | 4304 | /* Defined in filelock.c. */ |
| 4303 | extern void lock_file (Lisp_Object); | 4305 | extern void lock_file (Lisp_Object); |
| 4304 | extern void unlock_file (Lisp_Object); | 4306 | extern void unlock_file (Lisp_Object); |
| 4307 | extern void unlock_all_files (void); | ||
| 4305 | extern void unlock_buffer (struct buffer *); | 4308 | extern void unlock_buffer (struct buffer *); |
| 4306 | extern void syms_of_filelock (void); | 4309 | extern void syms_of_filelock (void); |
| 4307 | extern int str_collate (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); | ||
| 4308 | 4310 | ||
| 4309 | /* Defined in sound.c. */ | 4311 | /* Defined in sound.c. */ |
| 4310 | extern void syms_of_sound (void); | 4312 | extern void syms_of_sound (void); |
diff --git a/src/sysdep.c b/src/sysdep.c index db99f53299c..22446b25d16 100644 --- a/src/sysdep.c +++ b/src/sysdep.c | |||
| @@ -37,6 +37,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 37 | #include "sysselect.h" | 37 | #include "sysselect.h" |
| 38 | #include "blockinput.h" | 38 | #include "blockinput.h" |
| 39 | 39 | ||
| 40 | #ifdef HAVE_LINUX_FS_H | ||
| 41 | # include <linux/fs.h> | ||
| 42 | # include <sys/syscall.h> | ||
| 43 | #endif | ||
| 44 | |||
| 40 | #if defined DARWIN_OS || defined __FreeBSD__ | 45 | #if defined DARWIN_OS || defined __FreeBSD__ |
| 41 | # include <sys/sysctl.h> | 46 | # include <sys/sysctl.h> |
| 42 | #endif | 47 | #endif |
| @@ -2678,6 +2683,21 @@ set_file_times (int fd, const char *filename, | |||
| 2678 | timespec[1] = mtime; | 2683 | timespec[1] = mtime; |
| 2679 | return fdutimens (fd, filename, timespec); | 2684 | return fdutimens (fd, filename, timespec); |
| 2680 | } | 2685 | } |
| 2686 | |||
| 2687 | /* Rename directory SRCFD's entry SRC to directory DSTFD's entry DST. | ||
| 2688 | This is like renameat except that it fails if DST already exists, | ||
| 2689 | or if this operation is not supported atomically. Return 0 if | ||
| 2690 | successful, -1 (setting errno) otherwise. */ | ||
| 2691 | int | ||
| 2692 | renameat_noreplace (int srcfd, char const *src, int dstfd, char const *dst) | ||
| 2693 | { | ||
| 2694 | #ifdef SYS_renameat2 | ||
| 2695 | return syscall (SYS_renameat2, srcfd, src, dstfd, dst, RENAME_NOREPLACE); | ||
| 2696 | #else | ||
| 2697 | errno = ENOSYS; | ||
| 2698 | return -1; | ||
| 2699 | #endif | ||
| 2700 | } | ||
| 2681 | 2701 | ||
| 2682 | /* Like strsignal, except async-signal-safe, and this function typically | 2702 | /* Like strsignal, except async-signal-safe, and this function typically |
| 2683 | returns a string in the C locale rather than the current locale. */ | 2703 | returns a string in the C locale rather than the current locale. */ |