|
18 | 18 | #include <time.h> /* asctime / localtime */
|
19 | 19 | #include <regex.h>
|
20 | 20 |
|
| 21 | +#if DCOPY_USE_XATTRS |
| 22 | +#include <linux/fs.h> |
| 23 | +#endif |
| 24 | + |
21 | 25 | #ifdef HAVE_LIBATTR
|
22 | 26 | #include <attr/libattr.h>
|
23 | 27 | #endif /* HAVE_LIBATTR */
|
@@ -261,6 +265,66 @@ static int mfu_copy_close_file(
|
261 | 265 | return rc;
|
262 | 266 | }
|
263 | 267 |
|
| 268 | +static int mfu_copy_projid( |
| 269 | + const char* src_path, |
| 270 | + const char* dest_path) |
| 271 | +{ |
| 272 | + int rc = 0; |
| 273 | + struct stat st; |
| 274 | + /* check whether the src is symlink */ |
| 275 | + if (lstat(src_path, &st)) { |
| 276 | + MFU_LOG(MFU_LOG_ERR, "lstat failed: `%s' errno=%d (%s)", src_path, errno, strerror(errno)); |
| 277 | + goto xattr_fin; |
| 278 | + } |
| 279 | + if (S_ISLNK(st.st_mode)) { |
| 280 | + goto xattr_fin; |
| 281 | + } |
| 282 | + /* open the src */ |
| 283 | + int src_fd = open(src_path, O_RDONLY); |
| 284 | + if (src_fd < 0) { |
| 285 | + MFU_LOG(MFU_LOG_ERR, "open failed: `%s' errno=%d (%s)", src_path, errno, strerror(errno)); |
| 286 | + rc = -1; |
| 287 | + goto xattr_fin; |
| 288 | + } |
| 289 | + /* open the dest */ |
| 290 | + int dest_fd = open(dest_path, O_RDONLY); |
| 291 | + if (dest_fd < 0) { |
| 292 | + MFU_LOG(MFU_LOG_ERR, "open failed: `%s' errno=%d (%s)", dest_path, errno, strerror(errno)); |
| 293 | + rc = -1; |
| 294 | + goto xattr_close_src; |
| 295 | + } |
| 296 | + struct fsxattr src_attr; |
| 297 | + /* get src's xattr */ |
| 298 | + rc = ioctl(src_fd, FS_IOC_FSGETXATTR, &src_attr); |
| 299 | + if (rc != 0) { |
| 300 | + MFU_LOG(MFU_LOG_ERR, "ioctl(FS_IOC_FSGETXATTR) failed: `%s' errno=%d (%s)", src_path, errno, strerror(errno)); |
| 301 | + goto xattr_close_dest; |
| 302 | + } |
| 303 | + struct fsxattr dest_attr; |
| 304 | + /* get dest's xattr */ |
| 305 | + rc = ioctl(dest_fd, FS_IOC_FSGETXATTR, &dest_attr); |
| 306 | + if (rc != 0) { |
| 307 | + MFU_LOG(MFU_LOG_ERR, "ioctl(FS_IOC_FSGETXATTR) failed: `%s' errno=%d (%s)", dest_path, errno, strerror(errno)); |
| 308 | + goto xattr_close_dest; |
| 309 | + } |
| 310 | + dest_attr.fsx_projid = src_attr.fsx_projid; |
| 311 | + dest_attr.fsx_xflags = (dest_attr.fsx_xflags & ~FS_XFLAG_PROJINHERIT) | |
| 312 | + (src_attr.fsx_xflags & FS_XFLAG_PROJINHERIT); |
| 313 | + /* set dest's xattr */ |
| 314 | + rc = ioctl(dest_fd, FS_IOC_FSSETXATTR, &dest_attr); |
| 315 | + if (rc != 0) { |
| 316 | + MFU_LOG(MFU_LOG_ERR, "ioctl(FS_IOC_FSSETXATTR) failed: `%s' errno=%d (%s)", dest_path, errno, strerror(errno)); |
| 317 | + } |
| 318 | +xattr_close_dest: |
| 319 | + /* close dest */ |
| 320 | + close(dest_fd); |
| 321 | +xattr_close_src: |
| 322 | + /* close src */ |
| 323 | + close(src_fd); |
| 324 | +xattr_fin: |
| 325 | + return rc; |
| 326 | +} |
| 327 | + |
264 | 328 | /* copy all extended attributes from op->operand to dest_path,
|
265 | 329 | * returns 0 on success and -1 on failure */
|
266 | 330 | static int mfu_copy_xattrs(
|
@@ -443,6 +507,13 @@ static int mfu_copy_xattrs(
|
443 | 507 | mfu_free(&list);
|
444 | 508 | list_bufsize = 0;
|
445 | 509 |
|
| 510 | + rc = mfu_copy_projid(src_path, dest_path); |
| 511 | + if (rc) { |
| 512 | + MFU_LOG(MFU_LOG_ERR, "Failed to copy projid from src_path=%s to dest_path=%s (errno=%d %s)", |
| 513 | + src_path, dest_path, errno, strerror(errno) |
| 514 | + ); |
| 515 | + } |
| 516 | + |
446 | 517 | #endif /* DCOPY_USE_XATTR */
|
447 | 518 |
|
448 | 519 | return rc;
|
|
0 commit comments