| 368 | when done. */ |
| 369 | |
| 370 | static bool |
| 371 | re_protect (char const *const_dst_name, char const *dst_src_name, |
| 372 | int dst_dirfd, char const *dst_relname, |
| 373 | struct dir_attr *attr_list, const struct cp_options *x) |
| 374 | { |
| 375 | char *dst_name; /* A copy of CONST_DST_NAME we can change. */ |
| 376 | |
| 377 | ASSIGN_STRDUPA (dst_name, const_dst_name); |
| 378 | |
| 379 | /* The suffix of DST_NAME that is a copy of the source file name, |
| 380 | possibly truncated to name a parent directory. */ |
| 381 | char const *src_name = dst_name + (dst_src_name - const_dst_name); |
| 382 | |
| 383 | /* Likewise, but with any leading '/'s skipped. */ |
| 384 | char const *relname = dst_name + (dst_relname - const_dst_name); |
| 385 | |
| 386 | for (struct dir_attr *p = attr_list; p; p = p->next) |
| 387 | { |
| 388 | dst_name[p->slash_offset] = '\0'; |
| 389 | |
| 390 | /* Adjust the times (and if possible, ownership) for the copy. |
| 391 | chown turns off set[ug]id bits for non-root, |
| 392 | so do the chmod last. */ |
| 393 | |
| 394 | if (x->preserve_timestamps) |
| 395 | { |
| 396 | struct timespec timespec[2] = { get_stat_atime (&p->st), |
| 397 | get_stat_mtime (&p->st) }; |
| 398 | |
| 399 | if (utimensat (dst_dirfd, relname, timespec, 0)) |
| 400 | { |
| 401 | error (0, errno, _("failed to preserve times for %s"), |
| 402 | quoteaf (dst_name)); |
| 403 | return false; |
| 404 | } |
| 405 | } |
| 406 | |
| 407 | if (x->preserve_ownership) |
| 408 | { |
| 409 | if (lchownat (dst_dirfd, relname, p->st.st_uid, p->st.st_gid) |
| 410 | != 0) |
| 411 | { |
| 412 | if (! chown_failure_ok (x)) |
| 413 | { |
| 414 | error (0, errno, _("failed to preserve ownership for %s"), |
| 415 | quoteaf (dst_name)); |
| 416 | return false; |
| 417 | } |
| 418 | /* Failing to preserve ownership is OK. Still, try to preserve |
| 419 | the group, but ignore the possible error. */ |
| 420 | ignore_value (lchownat (dst_dirfd, relname, -1, p->st.st_gid)); |
| 421 | } |
| 422 | } |
| 423 | |
| 424 | if (x->preserve_mode) |
| 425 | { |
| 426 | if (xcopy_acl (src_name, -1, dst_name, -1, p->st.st_mode) != 0) |
| 427 | return false; |
no test coverage detected