summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/buffer.c3
-rw-r--r--src/cmds.c11
-rw-r--r--src/dired.c71
-rw-r--r--src/eval.c128
-rw-r--r--src/fileio.c154
-rw-r--r--src/filelock.c3
-rw-r--r--src/gnutls.c370
-rw-r--r--src/gnutls.h5
-rw-r--r--src/keyboard.c3
-rw-r--r--src/lisp.h6
-rw-r--r--src/minibuf.c7
-rw-r--r--src/regex.c8
-rw-r--r--src/regex.h2
-rw-r--r--src/sysdep.c20
14 files changed, 419 insertions, 372 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 649ddbe1839..0d0f43e937b 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1077,7 +1077,8 @@ is first appended to NAME, to speed up finding a non-existent buffer. */)
CHECK_STRING (name);
- if (!NILP (Fstring_equal (name, ignore)) || NILP (Fget_buffer (name)))
+ if ((!NILP (ignore) && !NILP (Fstring_equal (name, ignore)))
+ || NILP (Fget_buffer (name)))
return name;
if (SREF (name, 0) != ' ') /* See bug#1229. */
diff --git a/src/cmds.c b/src/cmds.c
index 51652d542a8..6f2db8696e9 100644
--- a/src/cmds.c
+++ b/src/cmds.c
@@ -268,9 +268,10 @@ Whichever character you type to run this command is inserted.
The numeric prefix argument N says how many times to repeat the insertion.
Before insertion, `expand-abbrev' is executed if the inserted character does
not have word syntax and the previous character in the buffer does.
-After insertion, the value of `auto-fill-function' is called if the
-`auto-fill-chars' table has a non-nil value for the inserted character.
-At the end, it runs `post-self-insert-hook'. */)
+After insertion, `internal-auto-fill' is called if
+`auto-fill-function' is non-nil and if the `auto-fill-chars' table has
+a non-nil value for the inserted character. At the end, it runs
+`post-self-insert-hook'. */)
(Lisp_Object n)
{
CHECK_NUMBER (n);
@@ -475,7 +476,7 @@ internal_self_insert (int c, EMACS_INT n)
that. Must have the newline in place already so filling and
justification, if any, know where the end is going to be. */
SET_PT_BOTH (PT - 1, PT_BYTE - 1);
- auto_fill_result = call0 (BVAR (current_buffer, auto_fill_function));
+ auto_fill_result = call0 (Qinternal_auto_fill);
/* Test PT < ZV in case the auto-fill-function is strange. */
if (c == '\n' && PT < ZV)
SET_PT_BOTH (PT + 1, PT_BYTE + 1);
@@ -494,6 +495,8 @@ internal_self_insert (int c, EMACS_INT n)
void
syms_of_cmds (void)
{
+ DEFSYM (Qinternal_auto_fill, "internal-auto-fill");
+
DEFSYM (Qundo_auto_amalgamate, "undo-auto-amalgamate");
DEFSYM (Qundo_auto__this_command_amalgamating,
"undo-auto--this-command-amalgamating");
diff --git a/src/dired.c b/src/dired.c
index 5ea00fb8db4..288ba6b1038 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -64,6 +64,21 @@ dirent_namelen (struct dirent *dp)
#endif
}
+#ifndef HAVE_STRUCT_DIRENT_D_TYPE
+enum { DT_UNKNOWN, DT_DIR, DT_LNK };
+#endif
+
+/* Return the file type of DP. */
+static int
+dirent_type (struct dirent *dp)
+{
+#ifdef HAVE_STRUCT_DIRENT_D_TYPE
+ return dp->d_type;
+#else
+ return DT_UNKNOWN;
+#endif
+}
+
static DIR *
open_directory (Lisp_Object dirname, int *fdp)
{
@@ -434,7 +449,7 @@ is matched against file and directory names relative to DIRECTORY. */)
return file_name_completion (file, directory, 1, Qnil);
}
-static int file_name_completion_stat (int, struct dirent *, struct stat *);
+static bool file_name_completion_dirp (int, struct dirent *, ptrdiff_t);
static Lisp_Object
file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
@@ -448,7 +463,6 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
Lisp_Object bestmatch, tem, elt, name;
Lisp_Object encoded_file;
Lisp_Object encoded_dir;
- struct stat st;
bool directoryp;
/* If not INCLUDEALL, exclude files in completion-ignored-extensions as
well as "." and "..". Until shown otherwise, assume we can't exclude
@@ -512,10 +526,21 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
>= 0))
continue;
- if (file_name_completion_stat (fd, dp, &st) < 0)
- continue;
+ switch (dirent_type (dp))
+ {
+ case DT_DIR:
+ directoryp = true;
+ break;
+
+ case DT_LNK: case DT_UNKNOWN:
+ directoryp = file_name_completion_dirp (fd, dp, len);
+ break;
+
+ default:
+ directoryp = false;
+ break;
+ }
- directoryp = S_ISDIR (st.st_mode) != 0;
tem = Qnil;
/* If all_flag is set, always include all.
It would not actually be helpful to the user to ignore any possible
@@ -781,32 +806,18 @@ scmp (const char *s1, const char *s2, ptrdiff_t len)
return len - l;
}
-static int
-file_name_completion_stat (int fd, struct dirent *dp, struct stat *st_addr)
+/* Return true if in the directory FD the directory entry DP, whose
+ string length is LEN, is that of a subdirectory that can be searched. */
+static bool
+file_name_completion_dirp (int fd, struct dirent *dp, ptrdiff_t len)
{
- int value;
-
-#ifdef MSDOS
- /* Some fields of struct stat are *very* expensive to compute on MS-DOS,
- but aren't required here. Avoid computing the following fields:
- st_inode, st_size and st_nlink for directories, and the execute bits
- in st_mode for non-directory files with non-standard extensions. */
-
- unsigned short save_djstat_flags = _djstat_flags;
-
- _djstat_flags = _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
-#endif /* MSDOS */
-
- /* We want to return success if a link points to a nonexistent file,
- but we want to return the status for what the link points to,
- in case it is a directory. */
- value = fstatat (fd, dp->d_name, st_addr, AT_SYMLINK_NOFOLLOW);
- if (value == 0 && S_ISLNK (st_addr->st_mode))
- fstatat (fd, dp->d_name, st_addr, 0);
-#ifdef MSDOS
- _djstat_flags = save_djstat_flags;
-#endif /* MSDOS */
- return value;
+ USE_SAFE_ALLOCA;
+ char *subdir_name = SAFE_ALLOCA (len + 2);
+ memcpy (subdir_name, dp->d_name, len);
+ strcpy (subdir_name + len, "/");
+ bool dirp = faccessat (fd, subdir_name, F_OK, AT_EACCESS) == 0;
+ SAFE_FREE ();
+ return dirp;
}
static char *
diff --git a/src/eval.c b/src/eval.c
index e5900382dee..fe2708b1bbc 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -354,10 +354,11 @@ usage: (or CONDITIONS...) */)
while (CONSP (args))
{
- val = eval_sub (XCAR (args));
+ Lisp_Object arg = XCAR (args);
+ args = XCDR (args);
+ val = eval_sub (arg);
if (!NILP (val))
break;
- args = XCDR (args);
}
return val;
@@ -374,10 +375,11 @@ usage: (and CONDITIONS...) */)
while (CONSP (args))
{
- val = eval_sub (XCAR (args));
+ Lisp_Object arg = XCAR (args);
+ args = XCDR (args);
+ val = eval_sub (arg);
if (NILP (val))
break;
- args = XCDR (args);
}
return val;
@@ -397,7 +399,7 @@ usage: (if COND THEN ELSE...) */)
if (!NILP (cond))
return eval_sub (Fcar (XCDR (args)));
- return Fprogn (XCDR (XCDR (args)));
+ return Fprogn (Fcdr (XCDR (args)));
}
DEFUN ("cond", Fcond, Scond, 0, UNEVALLED, 0,
@@ -439,8 +441,9 @@ usage: (progn BODY...) */)
while (CONSP (body))
{
- val = eval_sub (XCAR (body));
+ Lisp_Object form = XCAR (body);
body = XCDR (body);
+ val = eval_sub (form);
}
return val;
@@ -488,35 +491,26 @@ The return value of the `setq' form is the value of the last VAL.
usage: (setq [SYM VAL]...) */)
(Lisp_Object args)
{
- Lisp_Object val, sym, lex_binding;
+ Lisp_Object val = args, tail = args;
- val = args;
- if (CONSP (args))
+ for (EMACS_INT nargs = 0; CONSP (tail); nargs += 2)
{
- Lisp_Object args_left = args;
- Lisp_Object numargs = Flength (args);
-
- if (XINT (numargs) & 1)
- xsignal2 (Qwrong_number_of_arguments, Qsetq, numargs);
-
- do
- {
- val = eval_sub (Fcar (XCDR (args_left)));
- sym = XCAR (args_left);
-
- /* Like for eval_sub, we do not check declared_special here since
- it's been done when let-binding. */
- if (!NILP (Vinternal_interpreter_environment) /* Mere optimization! */
- && SYMBOLP (sym)
- && !NILP (lex_binding
- = Fassq (sym, Vinternal_interpreter_environment)))
- XSETCDR (lex_binding, val); /* SYM is lexically bound. */
- else
- Fset (sym, val); /* SYM is dynamically bound. */
-
- args_left = Fcdr (XCDR (args_left));
- }
- while (CONSP (args_left));
+ Lisp_Object sym = XCAR (tail), lex_binding;
+ tail = XCDR (tail);
+ if (!CONSP (tail))
+ xsignal2 (Qwrong_number_of_arguments, Qsetq, make_number (nargs + 1));
+ Lisp_Object arg = XCAR (tail);
+ tail = XCDR (tail);
+ val = eval_sub (arg);
+ /* Like for eval_sub, we do not check declared_special here since
+ it's been done when let-binding. */
+ if (!NILP (Vinternal_interpreter_environment) /* Mere optimization! */
+ && SYMBOLP (sym)
+ && !NILP (lex_binding
+ = Fassq (sym, Vinternal_interpreter_environment)))
+ XSETCDR (lex_binding, val); /* SYM is lexically bound. */
+ else
+ Fset (sym, val); /* SYM is dynamically bound. */
}
return val;
@@ -535,7 +529,7 @@ of unexpected results when a quoted object is modified.
usage: (quote ARG) */)
(Lisp_Object args)
{
- if (CONSP (XCDR (args)))
+ if (!NILP (XCDR (args)))
xsignal2 (Qwrong_number_of_arguments, Qquote, Flength (args));
return XCAR (args);
}
@@ -549,7 +543,7 @@ usage: (function ARG) */)
{
Lisp_Object quoted = XCAR (args);
- if (CONSP (XCDR (args)))
+ if (!NILP (XCDR (args)))
xsignal2 (Qwrong_number_of_arguments, Qfunction, Flength (args));
if (!NILP (Vinternal_interpreter_environment)
@@ -734,9 +728,9 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */)
sym = XCAR (args);
tail = XCDR (args);
- if (CONSP (tail))
+ if (!NILP (tail))
{
- if (CONSP (XCDR (tail)) && CONSP (XCDR (XCDR (tail))))
+ if (!NILP (XCDR (tail)) && !NILP (XCDR (XCDR (tail))))
error ("Too many arguments");
tem = Fdefault_boundp (sym);
@@ -803,20 +797,24 @@ usage: (defconst SYMBOL INITVALUE [DOCSTRING]) */)
Lisp_Object sym, tem;
sym = XCAR (args);
- if (CONSP (Fcdr (XCDR (XCDR (args)))))
- error ("Too many arguments");
+ Lisp_Object docstring = Qnil;
+ if (!NILP (XCDR (XCDR (args))))
+ {
+ if (!NILP (XCDR (XCDR (XCDR (args)))))
+ error ("Too many arguments");
+ docstring = XCAR (XCDR (XCDR (args)));
+ }
- tem = eval_sub (Fcar (XCDR (args)));
+ tem = eval_sub (XCAR (XCDR (args)));
if (!NILP (Vpurify_flag))
tem = Fpurecopy (tem);
Fset_default (sym, tem);
XSYMBOL (sym)->declared_special = 1;
- tem = Fcar (XCDR (XCDR (args)));
- if (!NILP (tem))
+ if (!NILP (docstring))
{
if (!NILP (Vpurify_flag))
- tem = Fpurecopy (tem);
- Fput (sym, Qvariable_documentation, tem);
+ docstring = Fpurecopy (docstring);
+ Fput (sym, Qvariable_documentation, docstring);
}
Fput (sym, Qrisky_local_variable, Qt);
LOADHIST_ATTACH (sym);
@@ -844,27 +842,29 @@ Each VALUEFORM can refer to the symbols already bound by this VARLIST.
usage: (let* VARLIST BODY...) */)
(Lisp_Object args)
{
- Lisp_Object varlist, var, val, elt, lexenv;
+ Lisp_Object var, val, elt, lexenv;
ptrdiff_t count = SPECPDL_INDEX ();
lexenv = Vinternal_interpreter_environment;
- for (varlist = XCAR (args); CONSP (varlist); varlist = XCDR (varlist))
+ Lisp_Object varlist = XCAR (args);
+ while (CONSP (varlist))
{
maybe_quit ();
elt = XCAR (varlist);
+ varlist = XCDR (varlist);
if (SYMBOLP (elt))
{
var = elt;
val = Qnil;
}
- else if (! NILP (Fcdr (Fcdr (elt))))
- signal_error ("`let' bindings can have only one value-form", elt);
else
{
var = Fcar (elt);
- val = eval_sub (Fcar (Fcdr (elt)));
+ if (! NILP (Fcdr (XCDR (elt))))
+ signal_error ("`let' bindings can have only one value-form", elt);
+ val = eval_sub (Fcar (XCDR (elt)));
}
if (!NILP (lexenv) && SYMBOLP (var)
@@ -911,33 +911,37 @@ usage: (let VARLIST BODY...) */)
CHECK_LIST (varlist);
/* Make space to hold the values to give the bound variables. */
- elt = Flength (varlist);
- SAFE_ALLOCA_LISP (temps, XFASTINT (elt));
+ EMACS_INT varlist_len = XFASTINT (Flength (varlist));
+ SAFE_ALLOCA_LISP (temps, varlist_len);
+ ptrdiff_t nvars = varlist_len;
/* Compute the values and store them in `temps'. */
- for (argnum = 0; CONSP (varlist); varlist = XCDR (varlist))
+ for (argnum = 0; argnum < nvars && CONSP (varlist); argnum++)
{
maybe_quit ();
elt = XCAR (varlist);
+ varlist = XCDR (varlist);
if (SYMBOLP (elt))
- temps [argnum++] = Qnil;
+ temps[argnum] = Qnil;
else if (! NILP (Fcdr (Fcdr (elt))))
signal_error ("`let' bindings can have only one value-form", elt);
else
- temps [argnum++] = eval_sub (Fcar (Fcdr (elt)));
+ temps[argnum] = eval_sub (Fcar (Fcdr (elt)));
}
+ nvars = argnum;
lexenv = Vinternal_interpreter_environment;
varlist = XCAR (args);
- for (argnum = 0; CONSP (varlist); varlist = XCDR (varlist))
+ for (argnum = 0; argnum < nvars && CONSP (varlist); argnum++)
{
Lisp_Object var;
elt = XCAR (varlist);
+ varlist = XCDR (varlist);
var = SYMBOLP (elt) ? elt : Fcar (elt);
- tem = temps[argnum++];
+ tem = temps[argnum];
if (!NILP (lexenv) && SYMBOLP (var)
&& !XSYMBOL (var)->declared_special
@@ -2135,6 +2139,7 @@ eval_sub (Lisp_Object form)
original_fun = XCAR (form);
original_args = XCDR (form);
+ CHECK_LIST (original_args);
/* This also protects them from gc. */
count = record_in_backtrace (original_fun, &original_args, UNEVALLED);
@@ -2176,15 +2181,16 @@ eval_sub (Lisp_Object form)
SAFE_ALLOCA_LISP (vals, XINT (numargs));
- while (!NILP (args_left))
+ while (CONSP (args_left) && argnum < XINT (numargs))
{
- vals[argnum++] = eval_sub (Fcar (args_left));
- args_left = Fcdr (args_left);
+ Lisp_Object arg = XCAR (args_left);
+ args_left = XCDR (args_left);
+ vals[argnum++] = eval_sub (arg);
}
- set_backtrace_args (specpdl + count, vals, XINT (numargs));
+ set_backtrace_args (specpdl + count, vals, argnum);
- val = (XSUBR (fun)->function.aMANY) (XINT (numargs), vals);
+ val = XSUBR (fun)->function.aMANY (argnum, vals);
check_cons_list ();
lisp_eval_depth--;
diff --git a/src/fileio.c b/src/fileio.c
index a57d50b24e0..db760d9b22d 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2216,7 +2216,7 @@ With a prefix argument, TRASH is nil. */)
encoded_file = ENCODE_FILE (filename);
- if (unlink (SSDATA (encoded_file)) < 0)
+ if (unlink (SSDATA (encoded_file)) != 0 && errno != ENOENT)
report_file_error ("Removing old name", filename);
return Qnil;
}
@@ -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
@@ -2344,46 +2345,69 @@ This is what happens in interactive use with M-x. */)
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)
+ identical but for the case, don't worry whether the destination
+ already exists: the caller simply wants to change the letter-case
+ of the file name. */
+ bool plain_rename
+ = ((!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)))));
+
+ int rename_errno;
+ if (!plain_rename)
{
- int rename_errno = errno;
- if (rename_errno == EXDEV)
+ if (renameat_noreplace (AT_FDCWD, SSDATA (encoded_file),
+ AT_FDCWD, SSDATA (encoded_newname))
+ == 0)
+ return Qnil;
+
+ rename_errno = errno;
+ switch (rename_errno)
{
- 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);
+ case EEXIST: case EINVAL: case ENOSYS:
+ barf_or_query_if_file_exists (newname, rename_errno == EEXIST,
+ "rename to it",
+ INTEGERP (ok_if_already_exists),
+ false);
+ plain_rename = true;
+ break;
+ }
+ }
- count = SPECPDL_INDEX ();
- specbind (Qdelete_by_moving_to_trash, Qnil);
+ if (plain_rename)
+ {
+ 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;
- if (!NILP (Ffile_directory_p (file)) && NILP (symlink_target))
- call2 (Qdelete_directory, file, Qt);
- else
- Fdelete_file (file, Qnil);
- unbind_to (count, Qnil);
- }
+ if (rename_errno != EXDEV)
+ report_file_errno ("Renaming", list2 (file, newname), rename_errno);
+
+ 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 +2449,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 +2510,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 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)
{
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/gnutls.c b/src/gnutls.c
index 59694074e16..188f995979e 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -26,22 +26,36 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "coding.h"
#include "buffer.h"
-#ifdef HAVE_GNUTLS
+#if 0x030014 <= GNUTLS_VERSION_NUMBER
+# define HAVE_GNUTLS_X509_SYSTEM_TRUST
+#endif
-#ifdef WINDOWSNT
-#include <windows.h>
-#include "w32.h"
+/* Although AEAD support started in GnuTLS 3.4.0 and works in 3.5.14,
+ it was broken through at least GnuTLS 3.4.10; see:
+ https://lists.gnu.org/archive/html/emacs-devel/2017-07/msg00992.html
+ The relevant fix seems to have been made in GnuTLS 3.5.1; see:
+ https://gitlab.com/gnutls/gnutls/commit/568935848dd6b82b9315d8b6c529d00e2605e03d
+ So, require 3.5.1. */
+#if 0x030501 <= GNUTLS_VERSION_NUMBER
+# define HAVE_GNUTLS_AEAD
#endif
+#ifdef HAVE_GNUTLS
+
+# ifdef WINDOWSNT
+# include <windows.h>
+# include "w32.h"
+# endif
+
static bool emacs_gnutls_handle_error (gnutls_session_t, int);
static bool gnutls_global_initialized;
static void gnutls_log_function (int, const char *);
static void gnutls_log_function2 (int, const char *, const char *);
-#ifdef HAVE_GNUTLS3
+# ifdef HAVE_GNUTLS3
static void gnutls_audit_log_function (gnutls_session_t, const char *);
-#endif
+# endif
enum extra_peer_verification
{
@@ -49,7 +63,7 @@ enum extra_peer_verification
};
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
DEF_DLL_FN (gnutls_alert_description_t, gnutls_alert_get,
(gnutls_session_t));
@@ -74,12 +88,10 @@ DEF_DLL_FN (int, gnutls_certificate_set_x509_crl_file,
DEF_DLL_FN (int, gnutls_certificate_set_x509_key_file,
(gnutls_certificate_credentials_t, const char *, const char *,
gnutls_x509_crt_fmt_t));
-# if ((GNUTLS_VERSION_MAJOR \
- + (GNUTLS_VERSION_MINOR > 0 || GNUTLS_VERSION_PATCH >= 20)) \
- > 3)
+# ifdef HAVE_GNUTLS_X509_SYSTEM_TRUST
DEF_DLL_FN (int, gnutls_certificate_set_x509_system_trust,
(gnutls_certificate_credentials_t));
-# endif
+# endif
DEF_DLL_FN (int, gnutls_certificate_set_x509_trust_file,
(gnutls_certificate_credentials_t, const char *,
gnutls_x509_crt_fmt_t));
@@ -96,9 +108,9 @@ DEF_DLL_FN (int, gnutls_dh_get_prime_bits, (gnutls_session_t));
DEF_DLL_FN (int, gnutls_error_is_fatal, (int));
DEF_DLL_FN (int, gnutls_global_init, (void));
DEF_DLL_FN (void, gnutls_global_set_log_function, (gnutls_log_func));
-# ifdef HAVE_GNUTLS3
+# ifdef HAVE_GNUTLS3
DEF_DLL_FN (void, gnutls_global_set_audit_log_function, (gnutls_audit_log_func));
-# endif
+# endif
DEF_DLL_FN (void, gnutls_global_set_log_level, (int));
DEF_DLL_FN (int, gnutls_handshake, (gnutls_session_t));
DEF_DLL_FN (int, gnutls_init, (gnutls_session_t *, unsigned int));
@@ -172,14 +184,13 @@ DEF_DLL_FN (const char *, gnutls_cipher_get_name,
DEF_DLL_FN (gnutls_mac_algorithm_t, gnutls_mac_get, (gnutls_session_t));
DEF_DLL_FN (const char *, gnutls_mac_get_name, (gnutls_mac_algorithm_t));
-# ifdef HAVE_GNUTLS3
+# ifdef HAVE_GNUTLS3
DEF_DLL_FN (int, gnutls_rnd, (gnutls_rnd_level_t, void *, size_t));
DEF_DLL_FN (const gnutls_mac_algorithm_t *, gnutls_mac_list, (void));
DEF_DLL_FN (size_t, gnutls_mac_get_nonce_size, (gnutls_mac_algorithm_t));
DEF_DLL_FN (size_t, gnutls_mac_get_key_size, (gnutls_mac_algorithm_t));
DEF_DLL_FN (const gnutls_digest_algorithm_t *, gnutls_digest_list, (void));
DEF_DLL_FN (const char *, gnutls_digest_get_name, (gnutls_digest_algorithm_t));
-# ifdef HAVE_GNUTLS3_CIPHER
DEF_DLL_FN (gnutls_cipher_algorithm_t *, gnutls_cipher_list, (void));
DEF_DLL_FN (int, gnutls_cipher_get_iv_size, (gnutls_cipher_algorithm_t));
DEF_DLL_FN (size_t, gnutls_cipher_get_key_size, (gnutls_cipher_algorithm_t));
@@ -194,7 +205,7 @@ DEF_DLL_FN (int, gnutls_cipher_encrypt2,
DEF_DLL_FN (void, gnutls_cipher_deinit, (gnutls_cipher_hd_t));
DEF_DLL_FN (int, gnutls_cipher_decrypt2,
(gnutls_cipher_hd_t, const void *, size_t, void *, size_t));
-# ifdef HAVE_GNUTLS3_AEAD
+# ifdef HAVE_GNUTLS_AEAD
DEF_DLL_FN (int, gnutls_aead_cipher_init,
(gnutls_aead_cipher_hd_t *, gnutls_cipher_algorithm_t,
const gnutls_datum_t *));
@@ -205,25 +216,20 @@ DEF_DLL_FN (int, gnutls_aead_cipher_encrypt,
DEF_DLL_FN (int, gnutls_aead_cipher_decrypt,
(gnutls_aead_cipher_hd_t, const void *, size_t, const void *,
size_t, size_t, const void *, size_t, void *, size_t *));
-# endif /* HAVE_GNUTLS3_AEAD */
-# ifdef HAVE_GNUTLS3_HMAC
+# endif
DEF_DLL_FN (int, gnutls_hmac_init,
(gnutls_hmac_hd_t *, gnutls_mac_algorithm_t, const void *, size_t));
DEF_DLL_FN (int, gnutls_hmac_get_len, (gnutls_mac_algorithm_t));
DEF_DLL_FN (int, gnutls_hmac, (gnutls_hmac_hd_t, const void *, size_t));
DEF_DLL_FN (void, gnutls_hmac_deinit, (gnutls_hmac_hd_t, void *));
DEF_DLL_FN (void, gnutls_hmac_output, (gnutls_hmac_hd_t, void *));
-# endif /* HAVE_GNUTLS3_HMAC */
-# endif /* HAVE_GNUTLS3_CIPHER */
-# ifdef HAVE_GNUTLS3_DIGEST
DEF_DLL_FN (int, gnutls_hash_init,
(gnutls_hash_hd_t *, gnutls_digest_algorithm_t));
DEF_DLL_FN (int, gnutls_hash_get_len, (gnutls_digest_algorithm_t));
DEF_DLL_FN (int, gnutls_hash, (gnutls_hash_hd_t, const void *, size_t));
DEF_DLL_FN (void, gnutls_hash_deinit, (gnutls_hash_hd_t, void *));
DEF_DLL_FN (void, gnutls_hash_output, (gnutls_hash_hd_t, void *));
-# endif /* HAVE_GNUTLS3_DIGEST */
-# endif /* HAVE_GNUTLS3 */
+# endif /* HAVE_GNUTLS3 */
static bool
@@ -249,11 +255,9 @@ init_gnutls_functions (void)
LOAD_DLL_FN (library, gnutls_certificate_set_verify_flags);
LOAD_DLL_FN (library, gnutls_certificate_set_x509_crl_file);
LOAD_DLL_FN (library, gnutls_certificate_set_x509_key_file);
-# if ((GNUTLS_VERSION_MAJOR \
- + (GNUTLS_VERSION_MINOR > 0 || GNUTLS_VERSION_PATCH >= 20)) \
- > 3)
+# ifdef HAVE_GNUTLS_X509_SYSTEM_TRUST
LOAD_DLL_FN (library, gnutls_certificate_set_x509_system_trust);
-# endif
+# endif
LOAD_DLL_FN (library, gnutls_certificate_set_x509_trust_file);
LOAD_DLL_FN (library, gnutls_certificate_type_get);
LOAD_DLL_FN (library, gnutls_certificate_verify_peers2);
@@ -264,9 +268,9 @@ init_gnutls_functions (void)
LOAD_DLL_FN (library, gnutls_error_is_fatal);
LOAD_DLL_FN (library, gnutls_global_init);
LOAD_DLL_FN (library, gnutls_global_set_log_function);
-# ifdef HAVE_GNUTLS3
+# ifdef HAVE_GNUTLS3
LOAD_DLL_FN (library, gnutls_global_set_audit_log_function);
-# endif
+# endif
LOAD_DLL_FN (library, gnutls_global_set_log_level);
LOAD_DLL_FN (library, gnutls_handshake);
LOAD_DLL_FN (library, gnutls_init);
@@ -309,14 +313,13 @@ init_gnutls_functions (void)
LOAD_DLL_FN (library, gnutls_cipher_get_name);
LOAD_DLL_FN (library, gnutls_mac_get);
LOAD_DLL_FN (library, gnutls_mac_get_name);
-# ifdef HAVE_GNUTLS3
+# ifdef HAVE_GNUTLS3
LOAD_DLL_FN (library, gnutls_rnd);
LOAD_DLL_FN (library, gnutls_mac_list);
LOAD_DLL_FN (library, gnutls_mac_get_nonce_size);
LOAD_DLL_FN (library, gnutls_mac_get_key_size);
LOAD_DLL_FN (library, gnutls_digest_list);
LOAD_DLL_FN (library, gnutls_digest_get_name);
-# ifdef HAVE_GNUTLS3_CIPHER
LOAD_DLL_FN (library, gnutls_cipher_list);
LOAD_DLL_FN (library, gnutls_cipher_get_iv_size);
LOAD_DLL_FN (library, gnutls_cipher_get_key_size);
@@ -327,28 +330,23 @@ init_gnutls_functions (void)
LOAD_DLL_FN (library, gnutls_cipher_encrypt2);
LOAD_DLL_FN (library, gnutls_cipher_deinit);
LOAD_DLL_FN (library, gnutls_cipher_decrypt2);
-# ifdef HAVE_GNUTLS3_AEAD
+# ifdef HAVE_GNUTLS_AEAD
LOAD_DLL_FN (library, gnutls_aead_cipher_init);
LOAD_DLL_FN (library, gnutls_aead_cipher_deinit);
LOAD_DLL_FN (library, gnutls_aead_cipher_encrypt);
LOAD_DLL_FN (library, gnutls_aead_cipher_decrypt);
# endif
-# ifdef HAVE_GNUTLS3_HMAC
LOAD_DLL_FN (library, gnutls_hmac_init);
LOAD_DLL_FN (library, gnutls_hmac_get_len);
LOAD_DLL_FN (library, gnutls_hmac);
LOAD_DLL_FN (library, gnutls_hmac_deinit);
LOAD_DLL_FN (library, gnutls_hmac_output);
-# endif /* HAVE_GNUTLS3_HMAC */
-# endif /* HAVE_GNUTLS3_CIPHER */
-# ifdef HAVE_GNUTLS3_DIGEST
LOAD_DLL_FN (library, gnutls_hash_init);
LOAD_DLL_FN (library, gnutls_hash_get_len);
LOAD_DLL_FN (library, gnutls_hash);
LOAD_DLL_FN (library, gnutls_hash_deinit);
LOAD_DLL_FN (library, gnutls_hash_output);
-# endif
-# endif /* HAVE_GNUTLS3 */
+# endif /* HAVE_GNUTLS3 */
max_log_level = global_gnutls_log_level;
@@ -361,111 +359,105 @@ init_gnutls_functions (void)
return 1;
}
-# define gnutls_alert_get fn_gnutls_alert_get
-# define gnutls_alert_get_name fn_gnutls_alert_get_name
-# define gnutls_anon_allocate_client_credentials fn_gnutls_anon_allocate_client_credentials
-# define gnutls_anon_free_client_credentials fn_gnutls_anon_free_client_credentials
-# define gnutls_bye fn_gnutls_bye
-# define gnutls_certificate_allocate_credentials fn_gnutls_certificate_allocate_credentials
-# define gnutls_certificate_free_credentials fn_gnutls_certificate_free_credentials
-# define gnutls_certificate_get_peers fn_gnutls_certificate_get_peers
-# define gnutls_certificate_set_verify_flags fn_gnutls_certificate_set_verify_flags
-# define gnutls_certificate_set_x509_crl_file fn_gnutls_certificate_set_x509_crl_file
-# define gnutls_certificate_set_x509_key_file fn_gnutls_certificate_set_x509_key_file
-# define gnutls_certificate_set_x509_system_trust fn_gnutls_certificate_set_x509_system_trust
-# define gnutls_certificate_set_x509_trust_file fn_gnutls_certificate_set_x509_trust_file
-# define gnutls_certificate_type_get fn_gnutls_certificate_type_get
-# define gnutls_certificate_verify_peers2 fn_gnutls_certificate_verify_peers2
-# define gnutls_cipher_get fn_gnutls_cipher_get
-# define gnutls_cipher_get_name fn_gnutls_cipher_get_name
-# define gnutls_credentials_set fn_gnutls_credentials_set
-# define gnutls_deinit fn_gnutls_deinit
-# define gnutls_dh_get_prime_bits fn_gnutls_dh_get_prime_bits
-# define gnutls_dh_set_prime_bits fn_gnutls_dh_set_prime_bits
-# define gnutls_error_is_fatal fn_gnutls_error_is_fatal
-# define gnutls_global_init fn_gnutls_global_init
-# define gnutls_global_set_audit_log_function fn_gnutls_global_set_audit_log_function
-# define gnutls_global_set_log_function fn_gnutls_global_set_log_function
-# define gnutls_global_set_log_level fn_gnutls_global_set_log_level
-# define gnutls_handshake fn_gnutls_handshake
-# define gnutls_init fn_gnutls_init
-# define gnutls_kx_get fn_gnutls_kx_get
-# define gnutls_kx_get_name fn_gnutls_kx_get_name
-# define gnutls_mac_get fn_gnutls_mac_get
-# define gnutls_mac_get_name fn_gnutls_mac_get_name
-# define gnutls_pk_algorithm_get_name fn_gnutls_pk_algorithm_get_name
-# define gnutls_pk_bits_to_sec_param fn_gnutls_pk_bits_to_sec_param
-# define gnutls_priority_set_direct fn_gnutls_priority_set_direct
-# define gnutls_protocol_get_name fn_gnutls_protocol_get_name
-# define gnutls_protocol_get_version fn_gnutls_protocol_get_version
-# define gnutls_record_check_pending fn_gnutls_record_check_pending
-# define gnutls_record_recv fn_gnutls_record_recv
-# define gnutls_record_send fn_gnutls_record_send
-# define gnutls_sec_param_get_name fn_gnutls_sec_param_get_name
-# define gnutls_server_name_set fn_gnutls_server_name_set
-# define gnutls_sign_get_name fn_gnutls_sign_get_name
-# define gnutls_strerror fn_gnutls_strerror
-# define gnutls_transport_set_errno fn_gnutls_transport_set_errno
-# define gnutls_transport_set_ptr2 fn_gnutls_transport_set_ptr2
-# define gnutls_transport_set_pull_function fn_gnutls_transport_set_pull_function
-# define gnutls_transport_set_push_function fn_gnutls_transport_set_push_function
-# define gnutls_x509_crt_check_hostname fn_gnutls_x509_crt_check_hostname
-# define gnutls_x509_crt_check_issuer fn_gnutls_x509_crt_check_issuer
-# define gnutls_x509_crt_deinit fn_gnutls_x509_crt_deinit
-# define gnutls_x509_crt_get_activation_time fn_gnutls_x509_crt_get_activation_time
-# define gnutls_x509_crt_get_dn fn_gnutls_x509_crt_get_dn
-# define gnutls_x509_crt_get_expiration_time fn_gnutls_x509_crt_get_expiration_time
-# define gnutls_x509_crt_get_fingerprint fn_gnutls_x509_crt_get_fingerprint
-# define gnutls_x509_crt_get_issuer_dn fn_gnutls_x509_crt_get_issuer_dn
-# define gnutls_x509_crt_get_issuer_unique_id fn_gnutls_x509_crt_get_issuer_unique_id
-# define gnutls_x509_crt_get_key_id fn_gnutls_x509_crt_get_key_id
-# define gnutls_x509_crt_get_pk_algorithm fn_gnutls_x509_crt_get_pk_algorithm
-# define gnutls_x509_crt_get_serial fn_gnutls_x509_crt_get_serial
-# define gnutls_x509_crt_get_signature_algorithm fn_gnutls_x509_crt_get_signature_algorithm
-# define gnutls_x509_crt_get_subject_unique_id fn_gnutls_x509_crt_get_subject_unique_id
-# define gnutls_x509_crt_get_version fn_gnutls_x509_crt_get_version
-# define gnutls_x509_crt_import fn_gnutls_x509_crt_import
-# define gnutls_x509_crt_init fn_gnutls_x509_crt_init
-# ifdef HAVE_GNUTLS3
-# define gnutls_rnd fn_gnutls_rnd
-# define gnutls_mac_list fn_gnutls_mac_list
-# define gnutls_mac_get_nonce_size fn_gnutls_mac_get_nonce_size
-# define gnutls_mac_get_key_size fn_gnutls_mac_get_key_size
-# define gnutls_digest_list fn_gnutls_digest_list
-# define gnutls_digest_get_name fn_gnutls_digest_get_name
-# ifdef HAVE_GNUTLS3_CIPHER
-# define gnutls_cipher_list fn_gnutls_cipher_list
-# define gnutls_cipher_get_iv_size fn_gnutls_cipher_get_iv_size
-# define gnutls_cipher_get_key_size fn_gnutls_cipher_get_key_size
-# define gnutls_cipher_get_block_size fn_gnutls_cipher_get_block_size
-# define gnutls_cipher_get_tag_size fn_gnutls_cipher_get_tag_size
-# define gnutls_cipher_init fn_gnutls_cipher_init
-# define gnutls_cipher_set_iv fn_gnutls_cipher_set_iv
-# define gnutls_cipher_encrypt2 fn_gnutls_cipher_encrypt2
-# define gnutls_cipher_decrypt2 fn_gnutls_cipher_decrypt2
-# define gnutls_cipher_deinit fn_gnutls_cipher_deinit
-# ifdef HAVE_GNUTLS3_AEAD
-# define gnutls_aead_cipher_encrypt fn_gnutls_aead_cipher_encrypt
-# define gnutls_aead_cipher_decrypt fn_gnutls_aead_cipher_decrypt
-# define gnutls_aead_cipher_init fn_gnutls_aead_cipher_init
-# define gnutls_aead_cipher_deinit fn_gnutls_aead_cipher_deinit
-# endif /* HAVE_GNUTLS3_AEAD */
-# ifdef HAVE_GNUTLS3_HMAC
-# define gnutls_hmac_init fn_gnutls_hmac_init
-# define gnutls_hmac_get_len fn_gnutls_hmac_get_len
-# define gnutls_hmac fn_gnutls_hmac
-# define gnutls_hmac_deinit fn_gnutls_hmac_deinit
-# define gnutls_hmac_output fn_gnutls_hmac_output
-# endif /* HAVE_GNUTLS3_HMAC */
-# endif /* HAVE_GNUTLS3_CIPHER */
-# ifdef HAVE_GNUTLS3_DIGEST
-# define gnutls_hash_init fn_gnutls_hash_init
-# define gnutls_hash_get_len fn_gnutls_hash_get_len
-# define gnutls_hash fn_gnutls_hash
-# define gnutls_hash_deinit fn_gnutls_hash_deinit
-# define gnutls_hash_output fn_gnutls_hash_output
-# endif
-# endif /* HAVE_GNUTLS3 */
+# define gnutls_alert_get fn_gnutls_alert_get
+# define gnutls_alert_get_name fn_gnutls_alert_get_name
+# define gnutls_anon_allocate_client_credentials fn_gnutls_anon_allocate_client_credentials
+# define gnutls_anon_free_client_credentials fn_gnutls_anon_free_client_credentials
+# define gnutls_bye fn_gnutls_bye
+# define gnutls_certificate_allocate_credentials fn_gnutls_certificate_allocate_credentials
+# define gnutls_certificate_free_credentials fn_gnutls_certificate_free_credentials
+# define gnutls_certificate_get_peers fn_gnutls_certificate_get_peers
+# define gnutls_certificate_set_verify_flags fn_gnutls_certificate_set_verify_flags
+# define gnutls_certificate_set_x509_crl_file fn_gnutls_certificate_set_x509_crl_file
+# define gnutls_certificate_set_x509_key_file fn_gnutls_certificate_set_x509_key_file
+# define gnutls_certificate_set_x509_system_trust fn_gnutls_certificate_set_x509_system_trust
+# define gnutls_certificate_set_x509_trust_file fn_gnutls_certificate_set_x509_trust_file
+# define gnutls_certificate_type_get fn_gnutls_certificate_type_get
+# define gnutls_certificate_verify_peers2 fn_gnutls_certificate_verify_peers2
+# define gnutls_cipher_get fn_gnutls_cipher_get
+# define gnutls_cipher_get_name fn_gnutls_cipher_get_name
+# define gnutls_credentials_set fn_gnutls_credentials_set
+# define gnutls_deinit fn_gnutls_deinit
+# define gnutls_dh_get_prime_bits fn_gnutls_dh_get_prime_bits
+# define gnutls_dh_set_prime_bits fn_gnutls_dh_set_prime_bits
+# define gnutls_error_is_fatal fn_gnutls_error_is_fatal
+# define gnutls_global_init fn_gnutls_global_init
+# define gnutls_global_set_audit_log_function fn_gnutls_global_set_audit_log_function
+# define gnutls_global_set_log_function fn_gnutls_global_set_log_function
+# define gnutls_global_set_log_level fn_gnutls_global_set_log_level
+# define gnutls_handshake fn_gnutls_handshake
+# define gnutls_init fn_gnutls_init
+# define gnutls_kx_get fn_gnutls_kx_get
+# define gnutls_kx_get_name fn_gnutls_kx_get_name
+# define gnutls_mac_get fn_gnutls_mac_get
+# define gnutls_mac_get_name fn_gnutls_mac_get_name
+# define gnutls_pk_algorithm_get_name fn_gnutls_pk_algorithm_get_name
+# define gnutls_pk_bits_to_sec_param fn_gnutls_pk_bits_to_sec_param
+# define gnutls_priority_set_direct fn_gnutls_priority_set_direct
+# define gnutls_protocol_get_name fn_gnutls_protocol_get_name
+# define gnutls_protocol_get_version fn_gnutls_protocol_get_version
+# define gnutls_record_check_pending fn_gnutls_record_check_pending
+# define gnutls_record_recv fn_gnutls_record_recv
+# define gnutls_record_send fn_gnutls_record_send
+# define gnutls_sec_param_get_name fn_gnutls_sec_param_get_name
+# define gnutls_server_name_set fn_gnutls_server_name_set
+# define gnutls_sign_get_name fn_gnutls_sign_get_name
+# define gnutls_strerror fn_gnutls_strerror
+# define gnutls_transport_set_errno fn_gnutls_transport_set_errno
+# define gnutls_transport_set_ptr2 fn_gnutls_transport_set_ptr2
+# define gnutls_transport_set_pull_function fn_gnutls_transport_set_pull_function
+# define gnutls_transport_set_push_function fn_gnutls_transport_set_push_function
+# define gnutls_x509_crt_check_hostname fn_gnutls_x509_crt_check_hostname
+# define gnutls_x509_crt_check_issuer fn_gnutls_x509_crt_check_issuer
+# define gnutls_x509_crt_deinit fn_gnutls_x509_crt_deinit
+# define gnutls_x509_crt_get_activation_time fn_gnutls_x509_crt_get_activation_time
+# define gnutls_x509_crt_get_dn fn_gnutls_x509_crt_get_dn
+# define gnutls_x509_crt_get_expiration_time fn_gnutls_x509_crt_get_expiration_time
+# define gnutls_x509_crt_get_fingerprint fn_gnutls_x509_crt_get_fingerprint
+# define gnutls_x509_crt_get_issuer_dn fn_gnutls_x509_crt_get_issuer_dn
+# define gnutls_x509_crt_get_issuer_unique_id fn_gnutls_x509_crt_get_issuer_unique_id
+# define gnutls_x509_crt_get_key_id fn_gnutls_x509_crt_get_key_id
+# define gnutls_x509_crt_get_pk_algorithm fn_gnutls_x509_crt_get_pk_algorithm
+# define gnutls_x509_crt_get_serial fn_gnutls_x509_crt_get_serial
+# define gnutls_x509_crt_get_signature_algorithm fn_gnutls_x509_crt_get_signature_algorithm
+# define gnutls_x509_crt_get_subject_unique_id fn_gnutls_x509_crt_get_subject_unique_id
+# define gnutls_x509_crt_get_version fn_gnutls_x509_crt_get_version
+# define gnutls_x509_crt_import fn_gnutls_x509_crt_import
+# define gnutls_x509_crt_init fn_gnutls_x509_crt_init
+# ifdef HAVE_GNUTLS3
+# define gnutls_rnd fn_gnutls_rnd
+# define gnutls_mac_list fn_gnutls_mac_list
+# define gnutls_mac_get_nonce_size fn_gnutls_mac_get_nonce_size
+# define gnutls_mac_get_key_size fn_gnutls_mac_get_key_size
+# define gnutls_digest_list fn_gnutls_digest_list
+# define gnutls_digest_get_name fn_gnutls_digest_get_name
+# define gnutls_cipher_list fn_gnutls_cipher_list
+# define gnutls_cipher_get_iv_size fn_gnutls_cipher_get_iv_size
+# define gnutls_cipher_get_key_size fn_gnutls_cipher_get_key_size
+# define gnutls_cipher_get_block_size fn_gnutls_cipher_get_block_size
+# define gnutls_cipher_get_tag_size fn_gnutls_cipher_get_tag_size
+# define gnutls_cipher_init fn_gnutls_cipher_init
+# define gnutls_cipher_set_iv fn_gnutls_cipher_set_iv
+# define gnutls_cipher_encrypt2 fn_gnutls_cipher_encrypt2
+# define gnutls_cipher_decrypt2 fn_gnutls_cipher_decrypt2
+# define gnutls_cipher_deinit fn_gnutls_cipher_deinit
+# ifdef HAVE_GNUTLS_AEAD
+# define gnutls_aead_cipher_encrypt fn_gnutls_aead_cipher_encrypt
+# define gnutls_aead_cipher_decrypt fn_gnutls_aead_cipher_decrypt
+# define gnutls_aead_cipher_init fn_gnutls_aead_cipher_init
+# define gnutls_aead_cipher_deinit fn_gnutls_aead_cipher_deinit
+# endif
+# define gnutls_hmac_init fn_gnutls_hmac_init
+# define gnutls_hmac_get_len fn_gnutls_hmac_get_len
+# define gnutls_hmac fn_gnutls_hmac
+# define gnutls_hmac_deinit fn_gnutls_hmac_deinit
+# define gnutls_hmac_output fn_gnutls_hmac_output
+# define gnutls_hash_init fn_gnutls_hash_init
+# define gnutls_hash_get_len fn_gnutls_hash_get_len
+# define gnutls_hash fn_gnutls_hash
+# define gnutls_hash_deinit fn_gnutls_hash_deinit
+# define gnutls_hash_output fn_gnutls_hash_output
+# endif /* HAVE_GNUTLS3 */
/* This wrapper is called from fns.c, which doesn't know about the
LOAD_DLL_FN stuff above. */
@@ -475,7 +467,7 @@ w32_gnutls_rnd (gnutls_rnd_level_t level, void *data, size_t len)
return gnutls_rnd (level, data, len);
}
-#endif /* WINDOWSNT */
+# endif /* WINDOWSNT */
/* Report memory exhaustion if ERR is an out-of-memory indication. */
@@ -489,7 +481,7 @@ check_memory_full (int err)
memory_full (0);
}
-#ifdef HAVE_GNUTLS3
+# ifdef HAVE_GNUTLS3
/* Log a simple audit message. */
static void
gnutls_audit_log_function (gnutls_session_t session, const char *string)
@@ -499,7 +491,7 @@ gnutls_audit_log_function (gnutls_session_t session, const char *string)
message ("gnutls.c: [audit] %s", string);
}
}
-#endif
+# endif
/* Log a simple message. */
static void
@@ -552,7 +544,7 @@ gnutls_try_handshake (struct Lisp_Process *proc)
return ret;
}
-#ifndef WINDOWSNT
+# ifndef WINDOWSNT
static int
emacs_gnutls_nonblock_errno (gnutls_transport_ptr_t ptr)
{
@@ -560,13 +552,13 @@ emacs_gnutls_nonblock_errno (gnutls_transport_ptr_t ptr)
switch (err)
{
-# ifdef _AIX
+# ifdef _AIX
/* This is taken from the GnuTLS system_errno function circa 2016;
see <http://savannah.gnu.org/support/?107464>. */
case 0:
errno = EAGAIN;
/* Fall through. */
-# endif
+# endif
case EINPROGRESS:
case ENOTCONN:
return EAGAIN;
@@ -575,7 +567,7 @@ emacs_gnutls_nonblock_errno (gnutls_transport_ptr_t ptr)
return err;
}
}
-#endif /* !WINDOWSNT */
+# endif /* !WINDOWSNT */
static int
emacs_gnutls_handshake (struct Lisp_Process *proc)
@@ -587,7 +579,7 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
if (proc->gnutls_initstage < GNUTLS_STAGE_TRANSPORT_POINTERS_SET)
{
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
/* On W32 we cannot transfer socket handles between different runtime
libraries, so we tell GnuTLS to use our special push/pull
functions. */
@@ -596,7 +588,7 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
(gnutls_transport_ptr_t) proc);
gnutls_transport_set_push_function (state, &emacs_gnutls_push);
gnutls_transport_set_pull_function (state, &emacs_gnutls_pull);
-#else
+# else
/* This is how GnuTLS takes sockets: as file descriptors passed
in. For an Emacs process socket, infd and outfd are the
same but we use this two-argument version for clarity. */
@@ -606,7 +598,7 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
if (proc->is_non_blocking_client)
gnutls_transport_set_errno_function (state,
emacs_gnutls_nonblock_errno);
-#endif
+# endif
proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET;
}
@@ -620,13 +612,13 @@ emacs_gnutls_record_check_pending (gnutls_session_t state)
return gnutls_record_check_pending (state);
}
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
void
emacs_gnutls_transport_set_errno (gnutls_session_t state, int err)
{
gnutls_transport_set_errno (state, err);
}
-#endif
+# endif
ptrdiff_t
emacs_gnutls_write (struct Lisp_Process *proc, const char *buf, ptrdiff_t nbyte)
@@ -732,10 +724,10 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
/* Mostly ignore "The TLS connection was non-properly
terminated" message which just means that the peer closed the
connection. */
-#ifdef HAVE_GNUTLS3
+# ifdef HAVE_GNUTLS3
if (err == GNUTLS_E_PREMATURE_TERMINATION)
level = 3;
-#endif
+# endif
GNUTLS_LOG2 (level, max_log_level, "fatal error:", str);
ret = false;
@@ -1300,7 +1292,7 @@ gnutls_ip_address_p (char *string)
return true;
}
-#if 0
+# if 0
/* Deinitialize global GnuTLS state.
See also `gnutls-global-init'. */
static Lisp_Object
@@ -1313,7 +1305,7 @@ emacs_gnutls_global_deinit (void)
return gnutls_make_error (GNUTLS_E_SUCCESS);
}
-#endif
+# endif
static void ATTRIBUTE_FORMAT_PRINTF (2, 3)
boot_error (struct Lisp_Process *p, const char *m, ...)
@@ -1585,9 +1577,9 @@ one trustfile (usually a CA bundle). */)
if (TYPE_RANGED_INTEGERP (int, loglevel))
{
gnutls_global_set_log_function (gnutls_log_function);
-#ifdef HAVE_GNUTLS3
+# ifdef HAVE_GNUTLS3
gnutls_global_set_audit_log_function (gnutls_audit_log_function);
-#endif
+# endif
gnutls_global_set_log_level (XINT (loglevel));
max_log_level = XINT (loglevel);
XPROCESS (proc)->gnutls_log_level = max_log_level;
@@ -1649,8 +1641,7 @@ one trustfile (usually a CA bundle). */)
int file_format = GNUTLS_X509_FMT_PEM;
Lisp_Object tail;
-#if GNUTLS_VERSION_MAJOR + \
- (GNUTLS_VERSION_MINOR > 0 || GNUTLS_VERSION_PATCH >= 20) > 3
+# ifdef HAVE_GNUTLS_X509_SYSTEM_TRUST
ret = gnutls_certificate_set_x509_system_trust (x509_cred);
if (ret < GNUTLS_E_SUCCESS)
{
@@ -1658,7 +1649,7 @@ one trustfile (usually a CA bundle). */)
GNUTLS_LOG2i (4, max_log_level,
"setting system trust failed with code ", ret);
}
-#endif
+# endif
for (tail = trustfiles; CONSP (tail); tail = XCDR (tail))
{
@@ -1668,12 +1659,12 @@ one trustfile (usually a CA bundle). */)
GNUTLS_LOG2 (1, max_log_level, "setting the trustfile: ",
SSDATA (trustfile));
trustfile = ENCODE_FILE (trustfile);
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
/* Since GnuTLS doesn't support UTF-8 or UTF-16 encoded
file names on Windows, we need to re-encode the file
name using the current ANSI codepage. */
trustfile = ansi_encode_filename (trustfile);
-#endif
+# endif
ret = gnutls_certificate_set_x509_trust_file
(x509_cred,
SSDATA (trustfile),
@@ -1698,9 +1689,9 @@ one trustfile (usually a CA bundle). */)
GNUTLS_LOG2 (1, max_log_level, "setting the CRL file: ",
SSDATA (crlfile));
crlfile = ENCODE_FILE (crlfile);
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
crlfile = ansi_encode_filename (crlfile);
-#endif
+# endif
ret = gnutls_certificate_set_x509_crl_file
(x509_cred, SSDATA (crlfile), file_format);
@@ -1727,10 +1718,10 @@ one trustfile (usually a CA bundle). */)
SSDATA (certfile));
keyfile = ENCODE_FILE (keyfile);
certfile = ENCODE_FILE (certfile);
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
keyfile = ansi_encode_filename (keyfile);
certfile = ansi_encode_filename (certfile);
-#endif
+# endif
ret = gnutls_certificate_set_x509_key_file
(x509_cred, SSDATA (certfile), SSDATA (keyfile), file_format);
@@ -1755,10 +1746,10 @@ one trustfile (usually a CA bundle). */)
GNUTLS_LOG (1, max_log_level, "gnutls_init");
int gnutls_flags = GNUTLS_CLIENT;
-#ifdef GNUTLS_NONBLOCK
+# ifdef GNUTLS_NONBLOCK
if (XPROCESS (proc)->is_non_blocking_client)
gnutls_flags |= GNUTLS_NONBLOCK;
-#endif
+# endif
ret = gnutls_init (&state, gnutls_flags);
XPROCESS (proc)->gnutls_state = state;
if (ret < GNUTLS_E_SUCCESS)
@@ -1852,7 +1843,6 @@ The alist key is the cipher name. */)
{
Lisp_Object ciphers = Qnil;
-#ifdef HAVE_GNUTLS3_CIPHER
const gnutls_cipher_algorithm_t *gciphers = gnutls_cipher_list ();
for (ptrdiff_t pos = 0; gciphers[pos] != 0; pos++)
{
@@ -1886,7 +1876,6 @@ The alist key is the cipher name. */)
ciphers = Fcons (cp, ciphers);
}
-#endif
return ciphers;
}
@@ -1899,7 +1888,7 @@ gnutls_symmetric_aead (bool encrypting, gnutls_cipher_algorithm_t gca,
const char *idata, ptrdiff_t isize,
Lisp_Object aead_auth)
{
-#ifdef HAVE_GNUTLS3_AEAD
+# ifdef HAVE_GNUTLS_AEAD
const char *desc = encrypting ? "encrypt" : "decrypt";
Lisp_Object actual_iv = make_unibyte_string (vdata, vsize);
@@ -1969,10 +1958,10 @@ gnutls_symmetric_aead (bool encrypting, gnutls_cipher_algorithm_t gca,
SAFE_FREE ();
return list2 (output, actual_iv);
-#else
+# else
printmax_t print_gca = gca;
error ("GnuTLS AEAD cipher %"pMd" is invalid or not found", print_gca);
-#endif
+# endif
}
static Lisp_Object
@@ -2181,7 +2170,6 @@ name. */)
(void)
{
Lisp_Object mac_algorithms = Qnil;
-#ifdef HAVE_GNUTLS3_HMAC
const gnutls_mac_algorithm_t *macs = gnutls_mac_list ();
for (ptrdiff_t pos = 0; macs[pos] != 0; pos++)
{
@@ -2204,7 +2192,6 @@ name. */)
make_number (gnutls_mac_get_nonce_size (gma)));
mac_algorithms = Fcons (mp, mac_algorithms);
}
-#endif
return mac_algorithms;
}
@@ -2218,7 +2205,6 @@ method name. */)
(void)
{
Lisp_Object digest_algorithms = Qnil;
-#ifdef HAVE_GNUTLS3_DIGEST
const gnutls_digest_algorithm_t *digests = gnutls_digest_list ();
for (ptrdiff_t pos = 0; digests[pos] != 0; pos++)
{
@@ -2236,7 +2222,6 @@ method name. */)
digest_algorithms = Fcons (mp, digest_algorithms);
}
-#endif
return digest_algorithms;
}
@@ -2423,25 +2408,17 @@ GnuTLS AEAD ciphers : the list will contain `AEAD-ciphers'. */)
# ifdef HAVE_GNUTLS3
capabilities = Fcons (intern("gnutls3"), capabilities);
-
-# ifdef HAVE_GNUTLS3_DIGEST
capabilities = Fcons (intern("digests"), capabilities);
-# endif
-
-# ifdef HAVE_GNUTLS3_CIPHER
capabilities = Fcons (intern("ciphers"), capabilities);
-# ifdef HAVE_GNUTLS3_AEAD
+# ifdef HAVE_GNUTLS_AEAD
capabilities = Fcons (intern("AEAD-ciphers"), capabilities);
-# endif
+# endif
-# ifdef HAVE_GNUTLS3_HMAC
capabilities = Fcons (intern("macs"), capabilities);
-# endif
-# endif /* HAVE_GNUTLS3_CIPHER */
# endif /* HAVE_GNUTLS3 */
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
Lisp_Object found = Fassq (Qgnutls, Vlibrary_cache);
if (CONSP (found))
return XCDR (found);
@@ -2452,15 +2429,10 @@ GnuTLS AEAD ciphers : the list will contain `AEAD-ciphers'. */)
Vlibrary_cache = Fcons (Fcons (Qgnutls, status), Vlibrary_cache);
return status;
}
-#else /* !WINDOWSNT */
+# endif /* WINDOWSNT */
+#endif /* HAVE_GNUTLS */
return capabilities;
-
-#endif /* WINDOWSNT */
-
-#else /* !HAVE_GNUTLS */
- return Qnil;
-#endif /* HAVE_GNUTLS */
}
void
diff --git a/src/gnutls.h b/src/gnutls.h
index 3ec86a8892d..9323cd1aeff 100644
--- a/src/gnutls.h
+++ b/src/gnutls.h
@@ -23,8 +23,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
-#ifdef HAVE_GNUTLS3
-#include <gnutls/crypto.h>
+#if 0x030000 <= GNUTLS_VERSION_NUMBER
+# define HAVE_GNUTLS3
+# include <gnutls/crypto.h>
#endif
#include "lisp.h"
diff --git a/src/keyboard.c b/src/keyboard.c
index 804af85dad9..97069a24acc 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -10168,7 +10168,8 @@ This may include sensitive information such as passwords. */)
file = Fexpand_file_name (file, Qnil);
encfile = ENCODE_FILE (file);
fd = emacs_open (SSDATA (encfile), O_WRONLY | O_CREAT | O_EXCL, 0600);
- if (fd < 0 && errno == EEXIST && unlink (SSDATA (encfile)) == 0)
+ if (fd < 0 && errno == EEXIST
+ && (unlink (SSDATA (encfile)) == 0 || errno == ENOENT))
fd = emacs_open (SSDATA (encfile), O_WRONLY | O_CREAT | O_EXCL, 0600);
dribble = fd < 0 ? 0 : fdopen (fd, "w");
if (dribble == 0)
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);
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/minibuf.c b/src/minibuf.c
index d4128ce01c1..010152930bc 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -497,6 +497,8 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
Fcons (Vminibuffer_history_position,
Fcons (Vminibuffer_history_variable,
minibuf_save_list))))));
+ minibuf_save_list
+ = Fcons (Fthis_command_keys_vector (), minibuf_save_list);
record_unwind_protect_void (read_minibuf_unwind);
minibuf_level++;
@@ -836,6 +838,11 @@ read_minibuf_unwind (void)
Fset_buffer (XWINDOW (window)->contents);
/* Restore prompt, etc, from outer minibuffer level. */
+ Lisp_Object key_vec = Fcar (minibuf_save_list);
+ eassert (VECTORP (key_vec));
+ this_command_key_count = XFASTINT (Flength (key_vec));
+ this_command_keys = key_vec;
+ minibuf_save_list = Fcdr (minibuf_save_list);
minibuf_prompt = Fcar (minibuf_save_list);
minibuf_save_list = Fcdr (minibuf_save_list);
minibuf_prompt_width = XFASTINT (Fcar (minibuf_save_list));
diff --git a/src/regex.c b/src/regex.c
index fb48765c96c..0dbb47309e4 100644
--- a/src/regex.c
+++ b/src/regex.c
@@ -1942,7 +1942,7 @@ struct range_table_work_area
returned. If name is not a valid character class name zero, or RECC_ERROR,
is returned.
- Otherwise, if *strp doesn’t begin with "[:name:]", -1 is returned.
+ Otherwise, if *strp doesn't begin with "[:name:]", -1 is returned.
The function can be used on ASCII and multibyte (UTF-8-encoded) strings.
*/
@@ -1954,8 +1954,8 @@ re_wctype_parse (const unsigned char **strp, unsigned limit)
if (limit < 4 || beg[0] != '[' || beg[1] != ':')
return -1;
- beg += 2; /* skip opening ‘[:’ */
- limit -= 3; /* opening ‘[:’ and half of closing ‘:]’; --limit handles rest */
+ beg += 2; /* skip opening "[:" */
+ limit -= 3; /* opening "[:" and half of closing ":]"; --limit handles rest */
for (it = beg; it[0] != ':' || it[1] != ']'; ++it)
if (!--limit)
return -1;
@@ -1985,7 +1985,7 @@ re_wctype_parse (const unsigned char **strp, unsigned limit)
2 [:cntrl:]
1 [:ff:]
- If you update this list, consider also updating chain of or’ed conditions
+ If you update this list, consider also updating chain of or'ed conditions
in execute_charset function.
*/
diff --git a/src/regex.h b/src/regex.h
index 1d439de259c..5e3a79763ec 100644
--- a/src/regex.h
+++ b/src/regex.h
@@ -21,7 +21,7 @@
#define _REGEX_H 1
#if defined emacs && (defined _REGEX_RE_COMP || defined _LIBC)
-/* We’re not defining re_set_syntax and using a different prototype of
+/* We're not defining re_set_syntax and using a different prototype of
re_compile_pattern when building Emacs so fail compilation early with
a (somewhat helpful) error message when conflict is detected. */
# error "_REGEX_RE_COMP nor _LIBC can be defined if emacs is defined."
diff --git a/src/sysdep.c b/src/sysdep.c
index db99f53299c..9eb733221e4 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)
+{
+#if defined SYS_renameat2 && defined RENAME_NOREPLACE
+ 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. */