X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/a7188cbf48f30782c7dc1ba70bbb93ef8e37dc13..b4e6aac98543afdfab019339612673561c64f122:/flist.c diff --git a/flist.c b/flist.c index cc7a873d..665fa19f 100644 --- a/flist.c +++ b/flist.c @@ -4,7 +4,7 @@ * Copyright (C) 1996 Andrew Tridgell * Copyright (C) 1996 Paul Mackerras * Copyright (C) 2001, 2002 Martin Pool - * Copyright (C) 2002-2007 Wayne Davison + * Copyright (C) 2002-2008 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 @@ -44,6 +44,8 @@ extern int filesfrom_fd; extern int one_file_system; extern int copy_dirlinks; extern int keep_dirlinks; +extern int preserve_uid; +extern int preserve_gid; extern int preserve_acls; extern int preserve_xattrs; extern int preserve_links; @@ -351,7 +353,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_ static uint32 rdev_major; static uid_t uid; static gid_t gid; - static char *user_name, *group_name; + static const char *user_name, *group_name; static char lastname[MAXPATHLEN]; char fname[MAXPATHLEN]; int first_hlink_ndx = -1; @@ -389,6 +391,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_ /* Initialize starting value of xflags. */ if (protocol_version >= 30 && S_ISDIR(file->mode)) { + dir_count++; if (file->flags & FLAG_CONTENT_DIR) xflags = file->flags & FLAG_TOP_DIR; else if (file->flags & FLAG_IMPLIED_DIR) @@ -421,24 +424,24 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_ } } else if (protocol_version < 28) rdev = MAKEDEV(0, 0); - if (uid_ndx) { + if (preserve_uid) { if ((uid_t)F_OWNER(file) == uid && *lastname) xflags |= XMIT_SAME_UID; else { uid = F_OWNER(file); - if (uid_ndx && !numeric_ids) { + if (!numeric_ids) { user_name = add_uid(uid); if (inc_recurse && user_name) xflags |= XMIT_USER_NAME_FOLLOWS; } } } - if (gid_ndx) { + if (preserve_gid) { if ((gid_t)F_GROUP(file) == gid && *lastname) xflags |= XMIT_SAME_GID; else { gid = F_GROUP(file); - if (gid_ndx && !numeric_ids) { + if (!numeric_ids) { group_name = add_gid(gid); if (inc_recurse && group_name) xflags |= XMIT_GROUP_NAME_FOLLOWS; @@ -521,7 +524,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_ } if (!(xflags & XMIT_SAME_MODE)) write_int(f, to_wire_mode(mode)); - if (uid_ndx && !(xflags & XMIT_SAME_UID)) { + if (preserve_uid && !(xflags & XMIT_SAME_UID)) { if (protocol_version < 30) write_int(f, uid); else { @@ -533,7 +536,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_ } } } - if (gid_ndx && !(xflags & XMIT_SAME_GID)) { + if (preserve_gid && !(xflags & XMIT_SAME_GID)) { if (protocol_version < 30) write_int(f, gid); else { @@ -705,9 +708,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist, file_length = F_LENGTH(first); modtime = first->modtime; mode = first->mode; - if (uid_ndx) + if (preserve_uid) uid = F_OWNER(first); - if (gid_ndx) + if (preserve_gid) gid = F_GROUP(first); if ((preserve_devices && IS_DEVICE(mode)) || (preserve_specials && IS_SPECIAL(mode))) { @@ -744,7 +747,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist, if (chmod_modes && !S_ISLNK(mode)) mode = tweak_mode(mode, chmod_modes); - if (uid_ndx && !(xflags & XMIT_SAME_UID)) { + if (preserve_uid && !(xflags & XMIT_SAME_UID)) { if (protocol_version < 30) uid = (uid_t)read_int(f); else { @@ -755,7 +758,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist, uid = match_uid(uid); } } - if (gid_ndx && !(xflags & XMIT_SAME_GID)) { + if (preserve_gid && !(xflags & XMIT_SAME_GID)) { if (protocol_version < 30) gid = (gid_t)read_int(f); else { @@ -864,9 +867,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist, OPT_EXTRA(file, 0)->unum = (uint32)(file_length >> 32); } file->mode = mode; - if (uid_ndx) + if (preserve_uid) F_OWNER(file) = uid; - if (gid_ndx) { + if (preserve_gid) { F_GROUP(file) = gid; file->flags |= gid_flags; } @@ -1036,9 +1039,15 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, } if (save_errno == ENOENT) { #ifdef SUPPORT_LINKS - /* Avoid "vanished" error if symlink points nowhere. */ - if (copy_links && x_lstat(thisname, &st, NULL) == 0 - && S_ISLNK(st.st_mode)) { + /* When our options tell us to follow a symlink that + * points nowhere, tell the user about the symlink + * instead of giving a "vanished" message. We only + * dereference a symlink if one of the --copy*links + * options was specified, so there's no need for the + * extra lstat() if one of these options isn't on. */ + if ((copy_links || copy_unsafe_links || copy_dirlinks) + && x_lstat(thisname, &st, NULL) == 0 + && S_ISLNK(st.st_mode)) { io_error |= IOERR_GENERAL; rprintf(FERROR_XFER, "symlink has no referent: %s\n", full_fname(thisname)); @@ -1192,9 +1201,9 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, OPT_EXTRA(file, 0)->unum = (uint32)(st.st_size >> 32); } file->mode = st.st_mode; - if (uid_ndx) + if (uid_ndx) /* Check uid_ndx instead of preserve_uid for del support */ F_OWNER(file) = st.st_uid; - if (gid_ndx) + if (gid_ndx) /* Check gid_ndx instead of preserve_gid for del support */ F_GROUP(file) = st.st_gid; if (basename != thisname) @@ -1291,8 +1300,6 @@ static struct file_struct *send_file_name(int f, struct file_list *flist, flist_expand(flist, 1); flist->files[flist->used++] = file; if (f >= 0) { - if (S_ISDIR(file->mode)) - dir_count++; send_file_entry(f, file, flist->used - 1, flist->ndx_start); #ifdef SUPPORT_ACLS if (preserve_acls && !S_ISLNK(file->mode)) { @@ -1526,8 +1533,10 @@ static void send_implied_dirs(int f, struct file_list *flist, char *fname, relnamecache **rnpp; char *slash; int len, need_new_dir; + struct filter_list_struct save_filter_list = filter_list; flags = (flags | FLAG_IMPLIED_DIR) & ~(FLAG_TOP_DIR | FLAG_CONTENT_DIR); + filter_list.head = filter_list.tail = NULL; /* Don't filter implied dirs. */ if (inc_recurse) { if (lastpath_struct && F_PATHNAME(lastpath_struct) == pathname @@ -1569,11 +1578,11 @@ static void send_implied_dirs(int f, struct file_list *flist, char *fname, xfer_dirs = save_xfer_dirs; if (!inc_recurse) - return; + goto done; } if (!lastpath_struct) - return; /* dir must have vanished */ + goto done; /* dir must have vanished */ len = strlen(limit+1); memcpy(&relname_list, F_DIR_RELNAMES_P(lastpath_struct), sizeof relname_list); @@ -1587,6 +1596,9 @@ static void send_implied_dirs(int f, struct file_list *flist, char *fname, out_of_memory("send_implied_dirs"); (*rnpp)->name_type = name_type; strlcpy((*rnpp)->fname, limit+1, len + 1); + +done: + filter_list = save_filter_list; } static void send1extra(int f, struct file_struct *file, struct file_list *flist) @@ -1831,7 +1843,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) } else if (!len || fbuf[len - 1] == '/') { if (len == 2 && fbuf[0] == '.') { /* Turn "./" into just "." rather than "./." */ - fbuf[1] = '\0'; + fbuf[--len] = '\0'; } else { if (len + 1 >= MAXPATHLEN) overflow_exit("send_file_list"); @@ -1975,7 +1987,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) file = send_file_name(f, flist, fbuf, &st, top_flags, ALL_FILTERS); if (inc_recurse) { - if (name_type == DOT_NAME) { + if (name_type == DOT_NAME && file) { if (send_dir_depth < 0) { send_dir_depth = 0; change_local_filter_dir(fbuf, len, send_dir_depth); @@ -2027,7 +2039,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) flist_sort_and_clean(flist, 0); file_total += flist->used; - if (!numeric_ids && !inc_recurse) + if (numeric_ids <= 0 && !inc_recurse) send_id_list(f); /* send the io_error flag */