Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs
This commit is contained in:
commit
49d6e59717
4 changed files with 100 additions and 70 deletions
141
src/fileio.c
141
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));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
20
src/sysdep.c
20
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. */
|
||||
|
|
Loading…
Add table
Reference in a new issue