Minor restructuring/clarification to get_backup_name.
[rsync/rsync.git] / util.c
diff --git a/util.c b/util.c
index 0cafed6..2c4c571 100644 (file)
--- a/util.c
+++ b/util.c
@@ -32,9 +32,8 @@ extern int relative_paths;
 extern int preserve_xattrs;
 extern char *module_dir;
 extern unsigned int module_dirlen;
-extern mode_t orig_umask;
 extern char *partial_dir;
-extern struct filter_list_struct daemon_filter_list;
+extern filter_rule_list daemon_filter_list;
 
 int sanitize_paths = 0;
 
@@ -123,9 +122,9 @@ NORETURN void overflow_exit(const char *str)
        exit_cleanup(RERR_MALLOC);
 }
 
-int set_modtime(const char *fname, time_t modtime, mode_t mode)
+int set_modtime(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode)
 {
-#if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
+#ifndef CAN_SET_SYMLINK_TIMES
        if (S_ISLNK(mode))
                return 1;
 #endif
@@ -140,20 +139,28 @@ int set_modtime(const char *fname, time_t modtime, mode_t mode)
                return 0;
 
        {
-#ifdef HAVE_UTIMES
+#ifdef HAVE_UTIMENSAT
+               struct timespec t[2];
+               t[0].tv_sec = 0;
+               t[0].tv_nsec = UTIME_NOW;
+               t[1].tv_sec = modtime;
+               t[1].tv_nsec = mod_nsec;
+               if (utimensat(AT_FDCWD, fname, t, AT_SYMLINK_NOFOLLOW) < 0)
+                       return S_ISLNK(mode) && errno == ENOSYS ? 1 : -1;
+               return 0;
+#elif defined HAVE_UTIMES || defined HAVE_LUTIMES
                struct timeval t[2];
                t[0].tv_sec = time(NULL);
                t[0].tv_usec = 0;
                t[1].tv_sec = modtime;
-               t[1].tv_usec = 0;
+               t[1].tv_usec = mod_nsec / 1000;
 # ifdef HAVE_LUTIMES
-               if (S_ISLNK(mode)) {
-                       if (lutimes(fname, t) < 0)
-                               return errno == ENOSYS ? 1 : -1;
-                       return 0;
-               }
-# endif
+               if (lutimes(fname, t) < 0)
+                       return S_ISLNK(mode) && errno == ENOSYS ? 1 : -1;
+               return 0;
+# else
                return utimes(fname, t);
+# endif
 #elif defined HAVE_STRUCT_UTIMBUF
                struct utimbuf tbuf;
                tbuf.actime = time(NULL);
@@ -170,41 +177,79 @@ int set_modtime(const char *fname, time_t modtime, mode_t mode)
        }
 }
 
-/* This creates a new directory with default permissions.  Since there
- * might be some directory-default permissions affecting this, we can't
- * force the permissions directly using the original umask and mkdir(). */
+/* This creates a new directory with default permissions.  Now that we
+ * leave the original umask set, we can just mkdir with mode 777. */
 int mkdir_defmode(char *fname)
 {
-       int ret;
-
-       umask(orig_umask);
-       ret = do_mkdir(fname, ACCESSPERMS);
-       umask(0);
-
-       return ret;
+       return do_mkdir(fname, ACCESSPERMS);
 }
 
 /* Create any necessary directories in fname.  Any missing directories are
- * created with default permissions. */
-int create_directory_path(char *fname)
+ * created with default permissions.  Returns < 0 on error, or the number
+ * of directories created. */
+int make_path(char *fname, int flags)
 {
-       char *p;
+       char *end, *p;
        int ret = 0;
 
-       while (*fname == '/')
-               fname++;
-       while (strncmp(fname, "./", 2) == 0)
+       if (flags & MKP_SKIP_SLASH) {
+               while (*fname == '/')
+                       fname++;
+       }
+
+       while (*fname == '.' && fname[1] == '/')
                fname += 2;
 
-       umask(orig_umask);
-       p = fname;
-       while ((p = strchr(p,'/')) != NULL) {
-               *p = '\0';
-               if (do_mkdir(fname, ACCESSPERMS) < 0 && errno != EEXIST)
-                   ret = -1;
-               *p++ = '/';
+       if (flags & MKP_DROP_NAME) {
+               end = strrchr(fname, '/');
+               if (!end)
+                       return 0;
+               *end = '\0';
+       } else
+               end = fname + strlen(fname);
+
+       /* Try to find an existing dir, starting from the deepest dir. */
+       for (p = end; ; ) {
+               if (do_mkdir(fname, ACCESSPERMS) == 0) {
+                       ret++;
+                       break;
+               }
+               if (errno != ENOENT) {
+                       if (errno != EEXIST)
+                               ret = -ret - 1;
+                       break;
+               }
+               while (1) {
+                       if (p == fname) {
+                               ret = -ret - 1;
+                               goto double_break;
+                       }
+                       if (*--p == '/') {
+                               if (p == fname) {
+                                       ret = -ret - 1; /* impossible... */
+                                       goto double_break;
+                               }
+                               *p = '\0';
+                               break;
+                       }
+               }
        }
-       umask(0);
+  double_break:
+
+       /* Make all the dirs that we didn't find on the way here. */
+       while (p != end) {
+               *p = '/';
+               p += strlen(p);
+               if (ret < 0) /* Skip mkdir on error, but keep restoring the path. */
+                       continue;
+               if (do_mkdir(fname, ACCESSPERMS) < 0)
+                       ret = -ret - 1;
+               else
+                       ret++;
+       }
+
+       if (flags & MKP_DROP_NAME)
+               *end = '/';
 
        return ret;
 }
@@ -270,8 +315,7 @@ static int safe_read(int desc, char *ptr, size_t len)
  *
  * 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 create_bak_dir)
+int copy_file(const char *source, const char *dest, int ofd, mode_t mode)
 {
        int ifd;
        char buf[1024 * 8];
@@ -293,19 +337,11 @@ int copy_file(const char *source, const char *dest, int ofd,
                }
 
                if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0) {
-                       int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
-                       if (create_bak_dir && errno == ENOENT && make_bak_dir(dest) == 0) {
-                               if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)
-                                       save_errno = errno ? errno : save_errno;
-                               else
-                                       save_errno = 0;
-                       }
-                       if (save_errno) {
-                               rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(dest));
-                               close(ifd);
-                               errno = save_errno;
-                               return -1;
-                       }
+                       int save_errno = errno;
+                       rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(dest));
+                       close(ifd);
+                       errno = save_errno;
+                       return -1;
                }
        }
 
@@ -440,7 +476,7 @@ int robust_rename(const char *from, const char *to, const char *partialptr,
                                        return -2;
                                to = partialptr;
                        }
-                       if (copy_file(from, to, -1, mode, 0) != 0)
+                       if (copy_file(from, to, -1, mode) != 0)
                                return -2;
                        do_unlink(from);
                        return 1;
@@ -494,30 +530,6 @@ void kill_all(int sig)
        }
 }
 
-/** Turn a user name into a uid */
-int name_to_uid(const char *name, uid_t *uid_p)
-{
-       struct passwd *pass;
-       if (!name || !*name)
-               return 0;
-       if (!(pass = getpwnam(name)))
-               return 0;
-       *uid_p = pass->pw_uid;
-       return 1;
-}
-
-/** Turn a group name into a gid */
-int name_to_gid(const char *name, gid_t *gid_p)
-{
-       struct group *grp;
-       if (!name || !*name)
-               return 0;
-       if (!(grp = getgrnam(name)))
-               return 0;
-       *gid_p = grp->gr_gid;
-       return 1;
-}
-
 /** Lock a byte range in a open file */
 int lock_range(int fd, int offset, int len)
 {
@@ -1411,11 +1423,11 @@ const char *find_filename_suffix(const char *fn, int fn_len, int *len_ptr)
 
 #define UNIT (1 << 16)
 
-uint32 fuzzy_distance(const char *s1, int len1, const char *s2, int len2)
+uint32 fuzzy_distance(const char *s1, unsigned len1, const char *s2, unsigned len2)
 {
        uint32 a[MAXPATHLEN], diag, above, left, diag_inc, above_inc, left_inc;
        int32 cost;
-       int i1, i2;
+       unsigned i1, i2;
 
        if (!len1 || !len2) {
                if (!len1) {