Skip to content

Commit 5a46aa7

Browse files
authored
Merge pull request #618 from rezib/fix/symlink
dsync/dcmp: support symlinks targets changes
2 parents f69dae3 + 89e9736 commit 5a46aa7

File tree

4 files changed

+99
-8
lines changed

4 files changed

+99
-8
lines changed

src/common/mfu_util.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,34 @@ int mfu_compare_contents(
996996
return rc;
997997
}
998998

999+
/* compares targets of two symlinks, returns 0 if equal, positive value if
1000+
* different, -1 on error when reading symlink. */
1001+
int mfu_compare_symlinks(
1002+
const char* src_name, /* IN - path name to source file */
1003+
const char* dst_name, /* IN - path name to destination file */
1004+
mfu_file_t* mfu_src_file, /* IN - I/O filesystem functions to use for source */
1005+
mfu_file_t* mfu_dst_file) /* IN - I/O filesystem functions to use for destination */
1006+
{
1007+
char src_target[PATH_MAX + 1], dst_target[PATH_MAX + 1];
1008+
ssize_t readlink_rc = mfu_file_readlink(src_name, src_target, sizeof(src_target) - 1, mfu_src_file);
1009+
if(readlink_rc < 0) {
1010+
MFU_LOG(MFU_LOG_ERR, "Failed to read source link `%s' readlink() (errno=%d %s)",
1011+
src_name, errno, strerror(errno)
1012+
);
1013+
return -1;
1014+
}
1015+
readlink_rc = mfu_file_readlink(dst_name, dst_target, sizeof(dst_target) - 1, mfu_dst_file);
1016+
if(readlink_rc < 0) {
1017+
MFU_LOG(MFU_LOG_ERR, "Failed to read destination link `%s' readlink() (errno=%d %s)",
1018+
dst_name, errno, strerror(errno)
1019+
);
1020+
return -1;
1021+
}
1022+
/* ensure that strings end with NUL */
1023+
src_target[readlink_rc] = dst_target[readlink_rc] = '\0';
1024+
return abs(strcmp(src_target, dst_target));
1025+
}
1026+
9991027
/* uses the lustre api to obtain stripe count and stripe size of a file */
10001028
int mfu_stripe_get(const char *path, uint64_t *stripe_size, uint64_t *stripe_count)
10011029
{

src/common/mfu_util.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,15 @@ int mfu_compare_contents(
266266
mfu_file_t* mfu_dst_file /* IN - I/O filesystem functions to use for destination */
267267
);
268268

269+
/* compares targets of two symlinks, returns 0 if equal, positive value if
270+
* different, -1 on error when reading symlink. */
271+
int mfu_compare_symlinks(
272+
const char* src_name, /* IN - path name to souce file */
273+
const char* dst_name, /* IN - path name to destination file */
274+
mfu_file_t* mfu_src_file, /* IN - I/O filesystem functions to use for source */
275+
mfu_file_t* mfu_dst_file /* IN - I/O filesystem functions to use for destination */
276+
);
277+
269278
/* uses the lustre api to obtain stripe count and stripe size of a file */
270279
int mfu_stripe_get(const char *path, uint64_t *stripe_size, uint64_t *stripe_count);
271280

src/dcmp/dcmp.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,15 +1084,38 @@ static int dcmp_strmap_compare(
10841084
continue;
10851085
}
10861086

1087-
/* for now, we can only compare content of regular files */
1088-
/* TODO: add support for symlinks */
1089-
if (! S_ISREG(dst_mode)) {
1090-
/* not regular file, take them as common content */
1087+
/* for now, we can only compare content of regular files and symlinks */
1088+
if (! S_ISREG(dst_mode) && ! S_ISLNK(dst_mode)) {
1089+
/* not regular file or symlink, take them as common content */
10911090
dcmp_strmap_item_update(src_map, key, DCMPF_CONTENT, DCMPS_COMMON);
10921091
dcmp_strmap_item_update(dst_map, key, DCMPF_CONTENT, DCMPS_COMMON);
10931092
continue;
10941093
}
10951094

1095+
/* For symlinks, compare targets */
1096+
if (S_ISLNK(dst_mode)) {
1097+
const char* src_name = mfu_flist_file_get_name(src_list, src_index);
1098+
const char* dst_name = mfu_flist_file_get_name(dst_list, dst_index);
1099+
int compare_rc = mfu_compare_symlinks(src_name, dst_name, mfu_src_file, mfu_dst_file);
1100+
if (compare_rc == -1) {
1101+
/* we hit an error while reading the symlink */
1102+
rc = -1;
1103+
MFU_LOG(MFU_LOG_ERR,
1104+
"Failed to readlink on %s and/or %s. Assuming contents are different.",
1105+
src_name, dst_name);
1106+
}
1107+
if (!compare_rc) {
1108+
/* update to say contents of the symlinks were found to be the same */
1109+
dcmp_strmap_item_update(src_map, key, DCMPF_CONTENT, DCMPS_COMMON);
1110+
dcmp_strmap_item_update(dst_map, key, DCMPF_CONTENT, DCMPS_COMMON);
1111+
} else {
1112+
/* update to say contents of the symlinks were found to be different */
1113+
dcmp_strmap_item_update(src_map, key, DCMPF_CONTENT, DCMPS_DIFFER);
1114+
dcmp_strmap_item_update(dst_map, key, DCMPF_CONTENT, DCMPS_DIFFER);
1115+
}
1116+
continue;
1117+
}
1118+
10961119
dcmp_state state;
10971120
tmp_rc = dcmp_strmap_item_state(src_map, key, DCMPF_SIZE, &state);
10981121
assert(tmp_rc == 0);

src/dsync/dsync.c

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1751,15 +1751,46 @@ static int dsync_strmap_compare(
17511751
continue;
17521752
}
17531753

1754-
/* for now, we can only compare content of regular files */
1755-
/* TODO: add support for symlinks */
1756-
if (! S_ISREG(dst_mode)) {
1757-
/* not regular file, take them as common content */
1754+
/* for now, we can only compare content of regular files and symlinks */
1755+
if (! S_ISREG(dst_mode) && ! S_ISLNK(dst_mode)) {
1756+
/* not regular file or symlink, take them as common content */
17581757
dsync_strmap_item_update(src_map, key, DCMPF_CONTENT, DCMPS_COMMON);
17591758
dsync_strmap_item_update(dst_map, key, DCMPF_CONTENT, DCMPS_COMMON);
17601759
continue;
17611760
}
17621761

1762+
/* if symlink, check if targets of source and destination files match. If not,
1763+
* mark the files as being different. */
1764+
if (S_ISLNK(dst_mode)) {
1765+
const char* src_name = mfu_flist_file_get_name(src_list, src_index);
1766+
const char* dst_name = mfu_flist_file_get_name(dst_list, dst_index);
1767+
int compare_rc = mfu_compare_symlinks(src_name, dst_name, mfu_src_file, mfu_dst_file);
1768+
if (compare_rc == -1) {
1769+
/* we hit an error while reading the symlink */
1770+
rc = -1;
1771+
MFU_LOG(MFU_LOG_ERR,
1772+
"Failed to readlink on %s and/or %s. Assuming contents are different.",
1773+
src_name, dst_name);
1774+
}
1775+
if (!compare_rc) {
1776+
/* update to say contents of the files were found to be the same */
1777+
dsync_strmap_item_update(src_map, key, DCMPF_CONTENT, DCMPS_COMMON);
1778+
dsync_strmap_item_update(dst_map, key, DCMPF_CONTENT, DCMPS_COMMON);
1779+
} else {
1780+
/* update to say contents of the symlinks were found to be different */
1781+
dsync_strmap_item_update(src_map, key, DCMPF_CONTENT, DCMPS_DIFFER);
1782+
dsync_strmap_item_update(dst_map, key, DCMPF_CONTENT, DCMPS_DIFFER);
1783+
1784+
/* if the destinations are different then we need to remove the file in
1785+
* the dst directory, and replace it with the one in the src directory */
1786+
if (compare_rc > 0 && !options.dry_run) {
1787+
mfu_flist_file_copy(src_list, src_index, src_cp_list);
1788+
mfu_flist_file_copy(dst_list, dst_index, dst_remove_list);
1789+
}
1790+
}
1791+
continue;
1792+
}
1793+
17631794
/* first check whether file sizes match */
17641795
dsync_state state;
17651796
tmp_rc = dsync_strmap_item_state(src_map, key, DCMPF_SIZE, &state);

0 commit comments

Comments
 (0)