diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/buffer.c | 3 | ||||
| -rw-r--r-- | src/cmds.c | 11 | ||||
| -rw-r--r-- | src/dired.c | 71 | ||||
| -rw-r--r-- | src/eval.c | 128 | ||||
| -rw-r--r-- | src/fileio.c | 154 | ||||
| -rw-r--r-- | src/filelock.c | 3 | ||||
| -rw-r--r-- | src/gnutls.c | 370 | ||||
| -rw-r--r-- | src/gnutls.h | 5 | ||||
| -rw-r--r-- | src/keyboard.c | 3 | ||||
| -rw-r--r-- | src/lisp.h | 6 | ||||
| -rw-r--r-- | src/minibuf.c | 7 | ||||
| -rw-r--r-- | src/regex.c | 8 | ||||
| -rw-r--r-- | src/regex.h | 2 | ||||
| -rw-r--r-- | src/sysdep.c | 20 |
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. */ |
