Given a fname, this sets extended access ACL entries, the default ACL (for a * dir), and the regular mode bits on the file. Call this with fname set to * NULL to just check if the ACL is different. * * If the ACL operation has a side-effect of changing the file's mode, the * sxp->st.st_mode value will be changed to match. * * Returns 0 for an unchanged ACL, 1 for changed, -1 for failed. */
| 1011 | * |
| 1012 | * Returns 0 for an unchanged ACL, 1 for changed, -1 for failed. */ |
| 1013 | int set_acl(const char *fname, const struct file_struct *file, stat_x *sxp, mode_t new_mode) |
| 1014 | { |
| 1015 | int changed = 0; |
| 1016 | int32 ndx; |
| 1017 | BOOL eq; |
| 1018 | |
| 1019 | if (!dry_run && (read_only || list_only)) { |
| 1020 | errno = EROFS; |
| 1021 | return -1; |
| 1022 | } |
| 1023 | |
| 1024 | ndx = F_ACL(file); |
| 1025 | if (ndx >= 0 && (size_t)ndx < access_acl_list.count) { |
| 1026 | acl_duo *duo_item = access_acl_list.items; |
| 1027 | duo_item += ndx; |
| 1028 | eq = sxp->acc_acl |
| 1029 | && rsync_acl_equal_enough(sxp->acc_acl, &duo_item->racl, new_mode); |
| 1030 | if (!eq) { |
| 1031 | changed = 1; |
| 1032 | if (!dry_run && fname |
| 1033 | && set_rsync_acl(fname, duo_item, SMB_ACL_TYPE_ACCESS, |
| 1034 | sxp, new_mode) < 0) |
| 1035 | return -1; |
| 1036 | } |
| 1037 | } |
| 1038 | |
| 1039 | if (!S_ISDIR(new_mode)) |
| 1040 | return changed; |
| 1041 | |
| 1042 | ndx = F_DIR_DEFACL(file); |
| 1043 | if (ndx >= 0 && (size_t)ndx < default_acl_list.count) { |
| 1044 | acl_duo *duo_item = default_acl_list.items; |
| 1045 | duo_item += ndx; |
| 1046 | eq = sxp->def_acl && rsync_acl_equal(sxp->def_acl, &duo_item->racl); |
| 1047 | if (!eq) { |
| 1048 | changed = 1; |
| 1049 | if (!dry_run && fname |
| 1050 | && set_rsync_acl(fname, duo_item, SMB_ACL_TYPE_DEFAULT, |
| 1051 | sxp, new_mode) < 0) |
| 1052 | return -1; |
| 1053 | } |
| 1054 | } |
| 1055 | |
| 1056 | return changed; |
| 1057 | } |
| 1058 | |
| 1059 | /* Non-incremental recursion needs to convert all the received IDs. |
| 1060 | * This is done in a single pass after receiving the whole file-list. */ |
no test coverage detected