| 480 | not to preserve ownership, -1 otherwise. */ |
| 481 | |
| 482 | static int |
| 483 | set_owner (const struct cp_options *x, char const *dst_name, |
| 484 | int dst_dirfd, char const *dst_relname, int dest_desc, |
| 485 | struct stat const *src_sb, bool new_dst, |
| 486 | struct stat const *dst_sb) |
| 487 | { |
| 488 | uid_t uid = src_sb->st_uid; |
| 489 | gid_t gid = src_sb->st_gid; |
| 490 | |
| 491 | /* Naively changing the ownership of an already-existing file before |
| 492 | changing its permissions would create a window of vulnerability if |
| 493 | the file's old permissions are too generous for the new owner and |
| 494 | group. Avoid the window by first changing to a restrictive |
| 495 | temporary mode if necessary. */ |
| 496 | |
| 497 | if (!new_dst && (x->preserve_mode || x->move_mode || x->set_mode)) |
| 498 | { |
| 499 | mode_t old_mode = dst_sb->st_mode; |
| 500 | mode_t new_mode = |
| 501 | (x->preserve_mode || x->move_mode ? src_sb->st_mode : x->mode); |
| 502 | mode_t restrictive_temp_mode = old_mode & new_mode & S_IRWXU; |
| 503 | |
| 504 | if ((USE_ACL |
| 505 | || (old_mode & CHMOD_MODE_BITS |
| 506 | & (~new_mode | S_ISUID | S_ISGID | S_ISVTX))) |
| 507 | && qset_acl (dst_name, dest_desc, restrictive_temp_mode) != 0) |
| 508 | { |
| 509 | if (! owner_failure_ok (x)) |
| 510 | error (0, errno, _("clearing permissions for %s"), |
| 511 | quoteaf (dst_name)); |
| 512 | return -x->require_preserve; |
| 513 | } |
| 514 | } |
| 515 | |
| 516 | if (fchown_or_lchown (dest_desc, dst_dirfd, dst_relname, uid, gid) == 0) |
| 517 | return 1; |
| 518 | |
| 519 | /* The ownership change failed. If the failure merely means we lack |
| 520 | privileges to change owner+group, try to change just the group |
| 521 | and ignore any failure of this. Otherwise, report an error. */ |
| 522 | if (chown_failure_ok (x)) |
| 523 | ignore_value (fchown_or_lchown (dest_desc, dst_dirfd, dst_relname, |
| 524 | -1, gid)); |
| 525 | else |
| 526 | { |
| 527 | error (0, errno, _("failed to preserve ownership for %s"), |
| 528 | quoteaf (dst_name)); |
| 529 | if (x->require_preserve) |
| 530 | return -1; |
| 531 | } |
| 532 | |
| 533 | return 0; |
| 534 | } |
| 535 | |
| 536 | /* Set the st_author field of DEST_DESC to the st_author field of |
| 537 | SRC_SB. If DEST_DESC is undefined (-1), set the st_author field |
no test coverage detected