emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 49d6e59 2/2: Merge branch 'master' of git.sv.gnu.or


From: Michael Albinus
Subject: [Emacs-diffs] master 49d6e59 2/2: Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs
Date: Wed, 2 Aug 2017 05:01:38 -0400 (EDT)

branch: master
commit 49d6e59717ad182487910b863656bb6a11080bcf
Merge: 4207733 1f9f514
Author: Michael Albinus <address@hidden>
Commit: Michael Albinus <address@hidden>

    Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs
---
 src/fileio.c   | 141 +++++++++++++++++++++++++++++----------------------------
 src/filelock.c |   3 ++
 src/lisp.h     |   6 ++-
 src/sysdep.c   |  20 ++++++++
 4 files changed, 100 insertions(+), 70 deletions(-)

diff --git a/src/fileio.c b/src/fileio.c
index 7531214..0264c9f 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2311,6 +2311,7 @@ This is what happens in interactive use with M-x.  */)
 {
   Lisp_Object handler;
   Lisp_Object encoded_file, encoded_newname, symlink_target;
+  int dirp = -1;
 
   symlink_target = encoded_file = encoded_newname = Qnil;
   CHECK_STRING (file);
@@ -2324,8 +2325,8 @@ This is what happens in interactive use with M-x.  */)
       && (NILP (Ffile_name_case_insensitive_p (file))
          || NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname)))))
     {
-      Lisp_Object fname = (NILP (Ffile_directory_p (file))
-                          ? file : Fdirectory_file_name (file));
+      dirp = !NILP (Ffile_directory_p (file));
+      Lisp_Object fname = dirp ? Fdirectory_file_name (file) : file;
       newname = Fexpand_file_name (Ffile_name_nondirectory (fname), newname);
     }
   else
@@ -2343,47 +2344,55 @@ This is what happens in interactive use with M-x.  */)
   encoded_file = ENCODE_FILE (file);
   encoded_newname = ENCODE_FILE (newname);
 
-  /* If the filesystem is case-insensitive and the file names are
-     identical but for the case, don't ask for confirmation: they
-     simply want to change the letter-case of the file name.  */
-  if ((!(file_name_case_insensitive_p (SSDATA (encoded_file)))
-       || NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname))))
-      && ((NILP (ok_if_already_exists) || INTEGERP (ok_if_already_exists))))
-    barf_or_query_if_file_exists (newname, false, "rename to it",
-                                 INTEGERP (ok_if_already_exists), false);
-  if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0)
+  if (renameat_noreplace (AT_FDCWD, SSDATA (encoded_file),
+                         AT_FDCWD, SSDATA (encoded_newname))
+      == 0)
+    return Qnil;
+  int rename_errno = errno;
+
+  if (rename_errno == EEXIST || rename_errno == ENOSYS)
     {
-      int rename_errno = errno;
-      if (rename_errno == EXDEV)
-       {
-          ptrdiff_t count;
-          symlink_target = Ffile_symlink_p (file);
-          if (! NILP (symlink_target))
-            Fmake_symbolic_link (symlink_target, newname,
-                                 NILP (ok_if_already_exists) ? Qnil : Qt);
-         else if (!NILP (Ffile_directory_p (file)))
-           call4 (Qcopy_directory, file, newname, Qt, Qnil);
-         else
-           /* We have already prompted if it was an integer, so don't
-              have copy-file prompt again.  */
-           Fcopy_file (file, newname,
-                       NILP (ok_if_already_exists) ? Qnil : Qt,
-                       Qt, Qt, Qt);
+      /* If the filesystem is case-insensitive and the file names are
+        identical but for the case, don't ask for confirmation: they
+        simply want to change the letter-case of the file name.  */
+      if ((NILP (ok_if_already_exists) || INTEGERP (ok_if_already_exists))
+         && (! file_name_case_insensitive_p (SSDATA (encoded_file))
+             || NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname)))))
+       barf_or_query_if_file_exists (newname, rename_errno == EEXIST,
+                                     "rename to it",
+                                     INTEGERP (ok_if_already_exists), false);
+      if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) == 0)
+       return Qnil;
+      rename_errno = errno;
+      /* Don't prompt again.  */
+      ok_if_already_exists = Qt;
+    }
+  else if (!NILP (ok_if_already_exists))
+    ok_if_already_exists = Qt;
 
-         count = SPECPDL_INDEX ();
-         specbind (Qdelete_by_moving_to_trash, Qnil);
+  if (rename_errno != EXDEV)
+    report_file_errno ("Renaming", list2 (file, newname), rename_errno);
 
-         if (!NILP (Ffile_directory_p (file)) && NILP (symlink_target))
-           call2 (Qdelete_directory, file, Qt);
-         else
-           Fdelete_file (file, Qnil);
-         unbind_to (count, Qnil);
-       }
+  symlink_target = Ffile_symlink_p (file);
+  if (!NILP (symlink_target))
+    Fmake_symbolic_link (symlink_target, newname, ok_if_already_exists);
+  else
+    {
+      if (dirp < 0)
+       dirp = !NILP (Ffile_directory_p (file));
+      if (dirp)
+       call4 (Qcopy_directory, file, newname, Qt, Qnil);
       else
-       report_file_errno ("Renaming", list2 (file, newname), rename_errno);
+       Fcopy_file (file, newname, ok_if_already_exists, Qt, Qt, Qt);
     }
 
-  return Qnil;
+  ptrdiff_t count = SPECPDL_INDEX ();
+  specbind (Qdelete_by_moving_to_trash, Qnil);
+  if (dirp && NILP (symlink_target))
+    call2 (Qdelete_directory, file, Qt);
+  else
+    Fdelete_file (file, Qnil);
+  return unbind_to (count, Qnil);
 }
 
 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.  */)
   encoded_file = ENCODE_FILE (file);
   encoded_newname = ENCODE_FILE (newname);
 
-  if (NILP (ok_if_already_exists)
-      || INTEGERP (ok_if_already_exists))
-    barf_or_query_if_file_exists (newname, false, "make it a new name",
-                                 INTEGERP (ok_if_already_exists), false);
+  if (link (SSDATA (encoded_file), SSDATA (encoded_newname)) == 0)
+    return Qnil;
 
-  unlink (SSDATA (newname));
-  if (link (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0)
+  if (errno == EEXIST)
     {
-      int link_errno = errno;
-      report_file_errno ("Adding new name", list2 (file, newname), link_errno);
+      if (NILP (ok_if_already_exists)
+         || INTEGERP (ok_if_already_exists))
+       barf_or_query_if_file_exists (newname, true, "make it a new name",
+                                     INTEGERP (ok_if_already_exists), false);
+      unlink (SSDATA (newname));
+      if (link (SSDATA (encoded_file), SSDATA (encoded_newname)) == 0)
+       return Qnil;
     }
 
-  return Qnil;
+  report_file_error ("Adding new name", list2 (file, newname));
 }
 
 DEFUN ("make-symbolic-link", Fmake_symbolic_link, Smake_symbolic_link, 2, 3,
@@ -2484,31 +2495,25 @@ This happens for interactive use with M-x.  */)
   encoded_target = ENCODE_FILE (target);
   encoded_linkname = ENCODE_FILE (linkname);
 
-  if (NILP (ok_if_already_exists)
-      || INTEGERP (ok_if_already_exists))
-    barf_or_query_if_file_exists (linkname, false, "make it a link",
-                                 INTEGERP (ok_if_already_exists), false);
-  if (symlink (SSDATA (encoded_target), SSDATA (encoded_linkname)) < 0)
-    {
-      /* If we didn't complain already, silently delete existing file.  */
-      int symlink_errno;
-      if (errno == EEXIST)
-       {
-         unlink (SSDATA (encoded_linkname));
-         if (symlink (SSDATA (encoded_target), SSDATA (encoded_linkname))
-             >= 0)
-           return Qnil;
-       }
-      if (errno == ENOSYS)
-       xsignal1 (Qfile_error,
-                 build_string ("Symbolic links are not supported"));
+  if (symlink (SSDATA (encoded_target), SSDATA (encoded_linkname)) == 0)
+    return Qnil;
 
-      symlink_errno = errno;
-      report_file_errno ("Making symbolic link", list2 (target, linkname),
-                        symlink_errno);
+  if (errno == ENOSYS)
+    xsignal1 (Qfile_error,
+             build_string ("Symbolic links are not supported"));
+
+  if (errno == EEXIST)
+    {
+      if (NILP (ok_if_already_exists)
+         || INTEGERP (ok_if_already_exists))
+       barf_or_query_if_file_exists (linkname, true, "make it a link",
+                                     INTEGERP (ok_if_already_exists), false);
+      unlink (SSDATA (encoded_linkname));
+      if (symlink (SSDATA (encoded_target), SSDATA (encoded_linkname)) == 0)
+       return Qnil;
     }
 
-  return Qnil;
+  report_file_error ("Making symbolic link", list2 (target, linkname));
 }
 
 
diff --git a/src/filelock.c b/src/filelock.c
index bfa1d63..dd8cb28 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -339,6 +339,9 @@ rename_lock_file (char const *old, char const *new, bool 
force)
     {
       struct stat st;
 
+      int r = renameat_noreplace (AT_FDCWD, old, AT_FDCWD, new);
+      if (! (r < 0 && errno == ENOSYS))
+       return r;
       if (link (old, new) == 0)
        return unlink (old) == 0 || errno == ENOENT ? 0 : -1;
       if (errno != ENOSYS && errno != LINKS_MIGHT_NOT_WORK)
diff --git a/src/lisp.h b/src/lisp.h
index cffaf95..4de6fc8 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4298,13 +4298,15 @@ extern ptrdiff_t emacs_write (int, void const *, 
ptrdiff_t);
 extern ptrdiff_t emacs_write_sig (int, void const *, ptrdiff_t);
 extern ptrdiff_t emacs_write_quit (int, void const *, ptrdiff_t);
 extern void emacs_perror (char const *);
+extern int renameat_noreplace (int, char const *, int, char const *);
+extern int str_collate (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
 
-extern void unlock_all_files (void);
+/* Defined in filelock.c.  */
 extern void lock_file (Lisp_Object);
 extern void unlock_file (Lisp_Object);
+extern void unlock_all_files (void);
 extern void unlock_buffer (struct buffer *);
 extern void syms_of_filelock (void);
-extern int str_collate (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
 
 /* Defined in sound.c.  */
 extern void syms_of_sound (void);
diff --git a/src/sysdep.c b/src/sysdep.c
index db99f53..22446b2 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/>.  */
 #include "sysselect.h"
 #include "blockinput.h"
 
+#ifdef HAVE_LINUX_FS_H
+# include <linux/fs.h>
+# include <sys/syscall.h>
+#endif
+
 #if defined DARWIN_OS || defined __FreeBSD__
 # include <sys/sysctl.h>
 #endif
@@ -2678,6 +2683,21 @@ set_file_times (int fd, const char *filename,
   timespec[1] = mtime;
   return fdutimens (fd, filename, timespec);
 }
+
+/* Rename directory SRCFD's entry SRC to directory DSTFD's entry DST.
+   This is like renameat except that it fails if DST already exists,
+   or if this operation is not supported atomically.  Return 0 if
+   successful, -1 (setting errno) otherwise.  */
+int
+renameat_noreplace (int srcfd, char const *src, int dstfd, char const *dst)
+{
+#ifdef SYS_renameat2
+  return syscall (SYS_renameat2, srcfd, src, dstfd, dst, RENAME_NOREPLACE);
+#else
+  errno = ENOSYS;
+  return -1;
+#endif
+}
 
 /* Like strsignal, except async-signal-safe, and this function typically
    returns a string in the C locale rather than the current locale.  */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]