update to popt 1.19
[rsync.git] / util1.c
diff --git a/util1.c b/util1.c
index 1cff973ff6e4006edac231a4345946628d48f386..da50ff1e8e457e3722de7d50beb1fd26b409ba31 100644 (file)
--- a/util1.c
+++ b/util1.c
@@ -4,7 +4,7 @@
  * Copyright (C) 1996-2000 Andrew Tridgell
  * Copyright (C) 1996 Paul Mackerras
  * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
- * Copyright (C) 2003-2020 Wayne Davison
+ * Copyright (C) 2003-2022 Wayne Davison
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -31,8 +31,8 @@ extern int do_fsync;
 extern int protect_args;
 extern int modify_window;
 extern int relative_paths;
-extern int preserve_times;
 extern int preserve_xattrs;
+extern int omit_link_times;
 extern int preallocate_files;
 extern char *module_dir;
 extern unsigned int module_dirlen;
@@ -159,8 +159,8 @@ int set_times(const char *fname, STRUCT_STAT *stp)
 
 #include "case_N.h"
                switch_step++;
-               if (preserve_times & PRESERVE_LINK_TIMES) {
-                       preserve_times &= ~PRESERVE_LINK_TIMES;
+               if (!omit_link_times) {
+                       omit_link_times = 1;
                        if (S_ISLNK(stp->st_mode))
                                return 1;
                }
@@ -319,16 +319,48 @@ static int safe_read(int desc, char *ptr, size_t len)
        return n_chars;
 }
 
-/* Copy a file.  If ofd < 0, copy_file unlinks and opens the "dest" file.
- * Otherwise, it just writes to and closes the provided file descriptor.
+/* Remove existing file @dest and reopen, creating a new file with @mode */
+static int unlink_and_reopen(const char *dest, mode_t mode)
+{
+       int ofd;
+
+       if (robust_unlink(dest) && errno != ENOENT) {
+               int save_errno = errno;
+               rsyserr(FERROR_XFER, errno, "unlink %s", full_fname(dest));
+               errno = save_errno;
+               return -1;
+       }
+
+#ifdef SUPPORT_XATTRS
+       if (preserve_xattrs)
+               mode |= S_IWUSR;
+#endif
+       mode &= INITACCESSPERMS;
+       if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0) {
+               int save_errno = errno;
+               rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(dest));
+               errno = save_errno;
+               return -1;
+       }
+       return ofd;
+}
+
+/* Copy contents of file @source to file @dest with mode @mode.
+ *
+ * If @tmpfilefd is < 0, copy_file unlinks @dest and then opens a new
+ * file with name @dest.
+ *
+ * Otherwise, copy_file writes to and closes the provided file
+ * descriptor.
+ *
  * In either case, if --xattrs are being preserved, the dest file will
  * have its xattrs set from the source file.
  *
  * This is used in conjunction with the --temp-dir, --backup, and
  * --copy-dest options. */
-int copy_file(const char *source, const char *dest, int ofd, mode_t mode)
+int copy_file(const char *source, const char *dest, int tmpfilefd, mode_t mode)
 {
-       int ifd;
+       int ifd, ofd;
        char buf[1024 * 8];
        int len;   /* Number of bytes read into `buf'. */
        OFF_T prealloc_len = 0, offset = 0;
@@ -340,23 +372,12 @@ int copy_file(const char *source, const char *dest, int ofd, mode_t mode)
                return -1;
        }
 
-       if (ofd < 0) {
-               if (robust_unlink(dest) && errno != ENOENT) {
-                       int save_errno = errno;
-                       rsyserr(FERROR_XFER, errno, "unlink %s", full_fname(dest));
-                       close(ifd);
-                       errno = save_errno;
-                       return -1;
-               }
-
-#ifdef SUPPORT_XATTRS
-               if (preserve_xattrs)
-                       mode |= S_IWUSR;
-#endif
-               mode &= INITACCESSPERMS;
-               if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0) {
+       if (tmpfilefd >= 0) {
+               ofd = tmpfilefd;
+       } else {
+               ofd = unlink_and_reopen(dest, mode);
+               if (ofd < 0) {
                        int save_errno = errno;
-                       rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(dest));
                        close(ifd);
                        errno = save_errno;
                        return -1;
@@ -1466,12 +1487,19 @@ const char *find_filename_suffix(const char *fn, int fn_len, int *len_ptr)
 
 #define UNIT (1 << 16)
 
-uint32 fuzzy_distance(const char *s1, unsigned len1, const char *s2, unsigned len2)
+uint32 fuzzy_distance(const char *s1, unsigned len1, const char *s2, unsigned len2, uint32 upperlimit)
 {
        uint32 a[MAXPATHLEN], diag, above, left, diag_inc, above_inc, left_inc;
        int32 cost;
        unsigned i1, i2;
 
+       /* Check to see if the Levenshtein distance must be greater than the
+        * upper limit defined by the previously found lowest distance using
+        * the heuristic that the Levenshtein distance is greater than the
+        * difference in length of the two strings */
+       if ((len1 > len2 ? len1 - len2 : len2 - len1) * UNIT > upperlimit)
+               return 0xFFFFU * UNIT + 1;
+
        if (!len1 || !len2) {
                if (!len1) {
                        s1 = s2;