X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/719985cb9ce1d4866c47b155194a3968ae58541a..1c3344a105f656a45f6b46e1710c3fc4ab862a9a:/hlink.c diff --git a/hlink.c b/hlink.c index 9919e924..f52c0edd 100644 --- a/hlink.c +++ b/hlink.c @@ -4,12 +4,11 @@ * Copyright (C) 1996 Andrew Tridgell * Copyright (C) 1996 Paul Mackerras * Copyright (C) 2002 Martin Pool - * Copyright (C) 2004, 2005, 2006 Wayne Davison + * Copyright (C) 2004-2007 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -27,18 +26,19 @@ extern int verbose; extern int dry_run; extern int do_xfers; extern int link_dest; +extern int preserve_acls; extern int make_backups; extern int protocol_version; extern int remove_source_files; extern int stdout_format_has_i; extern int maybe_ATTRS_REPORT; extern char *basis_dir[]; -extern struct file_list *the_file_list; +extern struct file_list *cur_flist; #ifdef SUPPORT_HARD_LINKS #define HASH_LOAD_LIMIT(size) ((size)*3/4) -#define FPTR(i) (the_file_list->files[i]) +#define FPTR(i) (cur_flist->files[i]) struct ihash_table { int32 size; @@ -251,10 +251,10 @@ void match_hard_links(void) int i, ndx_count = 0; int32 *ndx_list; - if (!(ndx_list = new_array(int32, the_file_list->count))) + if (!(ndx_list = new_array(int32, cur_flist->count))) out_of_memory("match_hard_links"); - for (i = 0; i < the_file_list->count; i++) { + for (i = 0; i < cur_flist->count; i++) { if (F_IS_HLINKED(FPTR(i))) ndx_list[ndx_count++] = i; } @@ -268,15 +268,15 @@ void match_hard_links(void) } static int maybe_hard_link(struct file_struct *file, int ndx, - const char *fname, int statret, STRUCT_STAT *stp, + const char *fname, int statret, statx *sxp, const char *oldname, STRUCT_STAT *old_stp, const char *realname, int itemizing, enum logcode code) { if (statret == 0) { - if (stp->st_dev == old_stp->st_dev - && stp->st_ino == old_stp->st_ino) { + if (sxp->st.st_dev == old_stp->st_dev + && sxp->st.st_ino == old_stp->st_ino) { if (itemizing) { - itemize(file, ndx, statret, stp, + itemize(fname, file, ndx, statret, sxp, ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, 0, ""); } @@ -285,7 +285,7 @@ static int maybe_hard_link(struct file_struct *file, int ndx, file->flags |= FLAG_HLINK_DONE; return 0; } - if (make_backups) { + if (make_backups > 0) { if (!make_backup(fname)) return -1; } else if (robust_unlink(fname)) { @@ -297,7 +297,7 @@ static int maybe_hard_link(struct file_struct *file, int ndx, if (hard_link_one(file, fname, oldname, 0)) { if (itemizing) { - itemize(file, ndx, statret, stp, + itemize(fname, file, ndx, statret, sxp, ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, 0, realname); } @@ -311,7 +311,7 @@ static int maybe_hard_link(struct file_struct *file, int ndx, /* Only called if FLAG_HLINKED is set and FLAG_HLINK_FIRST is not. Returns: * 0 = process the file, 1 = skip the file, -1 = error occurred. */ int hard_link_check(struct file_struct *file, int ndx, const char *fname, - int statret, STRUCT_STAT *stp, int itemizing, + int statret, statx *sxp, int itemizing, enum logcode code) { STRUCT_STAT prev_st; @@ -322,13 +322,13 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname, /* Is the previous link is not complete yet? */ if (!(prev_file->flags & FLAG_HLINK_DONE)) { /* Is the previous link being transferred? */ - if (prev_file->flags & FLAG_SENT) { + if (prev_file->flags & FLAG_FILE_SENT) { /* Add ourselves to the list of files that will be * updated when the transfer completes, and mark * ourself as waiting for the transfer. */ F_HL_PREV(file) = F_HL_PREV(prev_file); F_HL_PREV(prev_file) = ndx; - file->flags |= FLAG_SENT; + file->flags |= FLAG_FILE_SENT; return 1; } return 0; @@ -362,18 +362,20 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname, if (statret < 0 && basis_dir[0] != NULL) { /* If we match an alt-dest item, we don't output this as a change. */ char cmpbuf[MAXPATHLEN]; - STRUCT_STAT alt_st; + statx alt_sx; int j = 0; +#ifdef SUPPORT_ACLS + alt_sx.acc_acl = alt_sx.def_acl = NULL; +#endif do { pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname); - if (link_stat(cmpbuf, &alt_st, 0) < 0) + if (link_stat(cmpbuf, &alt_sx.st, 0) < 0) continue; if (link_dest) { - if (prev_st.st_dev != alt_st.st_dev - || prev_st.st_ino != alt_st.st_ino) + if (prev_st.st_dev != alt_sx.st.st_dev + || prev_st.st_ino != alt_sx.st.st_ino) continue; statret = 1; - *stp = alt_st; if (verbose < 2 || !stdout_format_has_i) { itemizing = 0; code = FNONE; @@ -382,16 +384,32 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname, } break; } - if (!unchanged_file(cmpbuf, file, &alt_st)) + if (!unchanged_file(cmpbuf, file, &alt_sx.st)) continue; statret = 1; - *stp = alt_st; - if (unchanged_attrs(file, &alt_st)) + if (unchanged_attrs(cmpbuf, file, &alt_sx)) break; } while (basis_dir[++j] != NULL); + if (statret == 1) { + sxp->st = alt_sx.st; +#ifdef SUPPORT_ACLS + if (preserve_acls && !S_ISLNK(file->mode)) { + if (!ACL_READY(*sxp)) + get_acl(cmpbuf, sxp); + else { + sxp->acc_acl = alt_sx.acc_acl; + sxp->def_acl = alt_sx.def_acl; + } + } +#endif + } +#ifdef SUPPORT_ACLS + else if (preserve_acls) + free_acl(&alt_sx); +#endif } - if (maybe_hard_link(file, ndx, fname, statret, stp, prev_name, &prev_st, + if (maybe_hard_link(file, ndx, fname, statret, sxp, prev_name, &prev_st, realname, itemizing, code) < 0) return -1; @@ -426,7 +444,8 @@ void finish_hard_link(struct file_struct *file, const char *fname, STRUCT_STAT *stp, int itemizing, enum logcode code, int alt_dest) { - STRUCT_STAT st, prev_st; + statx prev_sx; + STRUCT_STAT st; char alt_name[MAXPATHLEN], *prev_name; const char *our_name; int prev_statret, ndx, prev_ndx = F_HL_PREV(file); @@ -450,14 +469,24 @@ void finish_hard_link(struct file_struct *file, const char *fname, } else our_name = fname; +#ifdef SUPPORT_ACLS + prev_sx.acc_acl = prev_sx.def_acl = NULL; +#endif + while ((ndx = prev_ndx) >= 0) { + int val; file = FPTR(ndx); file->flags = (file->flags & ~FLAG_HLINK_FIRST) | FLAG_HLINK_DONE; prev_ndx = F_HL_PREV(file); prev_name = f_name(file, NULL); - prev_statret = link_stat(prev_name, &prev_st, 0); - if (maybe_hard_link(file, ndx, prev_name, prev_statret, &prev_st, - our_name, stp, fname, itemizing, code) < 0) + prev_statret = link_stat(prev_name, &prev_sx.st, 0); + val = maybe_hard_link(file, ndx, prev_name, prev_statret, &prev_sx, + our_name, stp, fname, itemizing, code); +#ifdef SUPPORT_ACLS + if (preserve_acls) + free_acl(&prev_sx); +#endif + if (val < 0) continue; if (remove_source_files == 1 && do_xfers) send_msg_int(MSG_SUCCESS, ndx);