From a6a72eb98ce7568af1d6bed27e1ad03ea80da772 Mon Sep 17 00:00:00 2001 From: Tomas Korbar Date: Mon, 23 Aug 2021 15:42:52 +0200 Subject: [PATCH 1/3] Eventually add write permission when setting extended attributes When we need to set extended atributes of file which does not allow write then temporarily add write permission and after attributes are set, remove it again. Resolves #208 --- xattrs.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/xattrs.c b/xattrs.c index 508649c00..cd19f0273 100644 --- a/xattrs.c +++ b/xattrs.c @@ -23,6 +23,8 @@ #include "ifuncs.h" #include "inums.h" #include "lib/sysxattrs.h" +#include +#include #ifdef SUPPORT_XATTRS @@ -1056,6 +1058,8 @@ int set_xattr(const char *fname, const struct file_struct *file, const char *fna rsync_xa_list *glst = rsync_xal_l.items; item_list *lst; int ndx; + int added_write_perm = 0; + struct stat current_stat; if (dry_run) return 1; /* FIXME: --dry-run needs to compute this value */ @@ -1084,10 +1088,34 @@ int set_xattr(const char *fname, const struct file_struct *file, const char *fna } #endif + // if target file has not write permission + // then add it temporarily so we can change extended attributes + if (access(fname, W_OK) != 0) { + if (do_stat(fname, ¤t_stat) != 0) { + rsyserr(FERROR_XFER, errno, "set_xattr: was not able to access file %s", + full_fname(fname)); + } + if (current_stat.st_uid == (uid_t)F_OWNER(file)) { + do_chmod(fname, current_stat.st_mode | S_IWUSR); + added_write_perm = 1; + } else if (current_stat.st_gid == (gid_t)F_GROUP(file)) { + do_chmod(fname, current_stat.st_mode | S_IWGRP); + added_write_perm = 1; + } else { + rprintf(FERROR_XFER, "set_xattr: file %s is not accessible for writing", + full_fname(fname)); + } + } + ndx = F_XATTR(file); glst += ndx; lst = &glst->xa_items; - return rsync_xal_set(fname, lst, fnamecmp, sxp); + int return_value = rsync_xal_set(fname, lst, fnamecmp, sxp); + if (added_write_perm) { + // remove the temporary write permission + do_chmod(fname, current_stat.st_mode); + } + return return_value; } #ifdef SUPPORT_ACLS From d9d1916e250cde9549188f0d516ded9cfec90402 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Sun, 26 Sep 2021 15:31:53 -0700 Subject: [PATCH 2/3] Some minor cleanup. --- xattrs.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/xattrs.c b/xattrs.c index cd19f0273..f0b15b61f 100644 --- a/xattrs.c +++ b/xattrs.c @@ -23,8 +23,6 @@ #include "ifuncs.h" #include "inums.h" #include "lib/sysxattrs.h" -#include -#include #ifdef SUPPORT_XATTRS @@ -1057,9 +1055,8 @@ int set_xattr(const char *fname, const struct file_struct *file, const char *fna { rsync_xa_list *glst = rsync_xal_l.items; item_list *lst; - int ndx; - int added_write_perm = 0; - struct stat current_stat; + int ndx, added_write_perm = 0; + STRUCT_STAT current_stat; if (dry_run) return 1; /* FIXME: --dry-run needs to compute this value */ @@ -1088,8 +1085,8 @@ int set_xattr(const char *fname, const struct file_struct *file, const char *fna } #endif - // if target file has not write permission - // then add it temporarily so we can change extended attributes + /* If the target file has not write permission then add it + * temporarily so we can change extended attributes. */ if (access(fname, W_OK) != 0) { if (do_stat(fname, ¤t_stat) != 0) { rsyserr(FERROR_XFER, errno, "set_xattr: was not able to access file %s", @@ -1111,10 +1108,8 @@ int set_xattr(const char *fname, const struct file_struct *file, const char *fna glst += ndx; lst = &glst->xa_items; int return_value = rsync_xal_set(fname, lst, fnamecmp, sxp); - if (added_write_perm) { - // remove the temporary write permission + if (added_write_perm) /* remove the temporary write permission */ do_chmod(fname, current_stat.st_mode); - } return return_value; } From 61e415a2fcd62a1001810931d0a60a351256245b Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Sun, 26 Sep 2021 16:29:41 -0700 Subject: [PATCH 3/3] Simplify the code a bit - Make use of the sxp->st data instead of doing a new stat. - Only try adding S_IWUSR perm since only owner can chmod. - Skip the code if am_root is set. --- xattrs.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/xattrs.c b/xattrs.c index f0b15b61f..3c5491920 100644 --- a/xattrs.c +++ b/xattrs.c @@ -1056,7 +1056,6 @@ int set_xattr(const char *fname, const struct file_struct *file, const char *fna rsync_xa_list *glst = rsync_xal_l.items; item_list *lst; int ndx, added_write_perm = 0; - STRUCT_STAT current_stat; if (dry_run) return 1; /* FIXME: --dry-run needs to compute this value */ @@ -1085,31 +1084,22 @@ int set_xattr(const char *fname, const struct file_struct *file, const char *fna } #endif - /* If the target file has not write permission then add it - * temporarily so we can change extended attributes. */ - if (access(fname, W_OK) != 0) { - if (do_stat(fname, ¤t_stat) != 0) { - rsyserr(FERROR_XFER, errno, "set_xattr: was not able to access file %s", - full_fname(fname)); - } - if (current_stat.st_uid == (uid_t)F_OWNER(file)) { - do_chmod(fname, current_stat.st_mode | S_IWUSR); - added_write_perm = 1; - } else if (current_stat.st_gid == (gid_t)F_GROUP(file)) { - do_chmod(fname, current_stat.st_mode | S_IWGRP); - added_write_perm = 1; - } else { - rprintf(FERROR_XFER, "set_xattr: file %s is not accessible for writing", - full_fname(fname)); - } - } + /* If the target file lacks write permission, we try to add it + * temporarily so we can change the extended attributes. */ + if (!am_root +#ifdef SUPPORT_LINKS + && !S_ISLNK(sxp->st.st_mode) +#endif + && access(fname, W_OK) < 0 + && do_chmod(fname, (sxp->st.st_mode & CHMOD_BITS) | S_IWUSR) == 0) + added_write_perm = 1; ndx = F_XATTR(file); glst += ndx; lst = &glst->xa_items; int return_value = rsync_xal_set(fname, lst, fnamecmp, sxp); if (added_write_perm) /* remove the temporary write permission */ - do_chmod(fname, current_stat.st_mode); + do_chmod(fname, sxp->st.st_mode); return return_value; }