Skip to content

Commit 8115e8b

Browse files
committed
dsync/dcmp: support symlinks targets changes
Update dsync and dcmp to detect a symlinks targets changes. In this case, the symlinks are reported to be different by dcmp and are updated by dsync. Note this works for dsync both with or without c, --contents. New function mfu_compare_symlinks() is introduced in library API to factorize the logic for all commands. Signed-off-by: Rémi Palancher <[email protected]>
1 parent 4581ec5 commit 8115e8b

File tree

4 files changed

+92
-14
lines changed

4 files changed

+92
-14
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, negative or positive
1000+
* value if 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 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, negative or positive
270+
* value if 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: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,15 +1084,30 @@ 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+
if (mfu_compare_symlinks(mfu_flist_file_get_name(src_list, src_index),
1098+
mfu_flist_file_get_name(dst_list, dst_index),
1099+
mfu_src_file, mfu_dst_file) == 0) {
1100+
/* update to say contents of the symlinks were found to be the same */
1101+
dcmp_strmap_item_update(src_map, key, DCMPF_CONTENT, DCMPS_COMMON);
1102+
dcmp_strmap_item_update(dst_map, key, DCMPF_CONTENT, DCMPS_COMMON);
1103+
} else {
1104+
/* update to say contents of the symlinks were found to be different */
1105+
dcmp_strmap_item_update(src_map, key, DCMPF_CONTENT, DCMPS_DIFFER);
1106+
dcmp_strmap_item_update(dst_map, key, DCMPF_CONTENT, DCMPS_DIFFER);
1107+
}
1108+
continue;
1109+
}
1110+
10961111
dcmp_state state;
10971112
tmp_rc = dcmp_strmap_item_state(src_map, key, DCMPF_SIZE, &state);
10981113
assert(tmp_rc == 0);

src/dsync/dsync.c

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,7 @@ static int dsync_strmap_compare_data(
882882
/* get chunk size for copying files (just hard-coded for now) */
883883
uint64_t chunk_size = copy_opts->chunk_size;
884884

885-
/* get the linked list of file chunks for the src and dest */
885+
/* get the linked list of regular file chunks for the src and dest */
886886
mfu_file_chunk* src_head = mfu_file_chunk_list_alloc(src_compare_list, chunk_size);
887887
mfu_file_chunk* dst_head = mfu_file_chunk_list_alloc(dst_compare_list, chunk_size);
888888

@@ -963,8 +963,18 @@ static int dsync_strmap_compare_data(
963963
/* ignore prefix portion of path to use as key */
964964
name += strlen_prefix;
965965

966-
/* get comparison results for this item */
967-
int flag = results[i];
966+
mfu_filetype type = mfu_flist_file_get_type(src_compare_list, i);
967+
int flag = 0;
968+
if (type == MFU_TYPE_LINK) {
969+
/* symlinks have not been compared above, their targets are compared now */
970+
flag = mfu_compare_symlinks(mfu_flist_file_get_name(src_compare_list, i),
971+
mfu_flist_file_get_name(dst_compare_list, i),
972+
mfu_src_file, mfu_dst_file);
973+
} else {
974+
/* get comparison results for this regular file */
975+
flag = results[i];
976+
}
977+
968978

969979
/* set flag in strmap to record status of file */
970980
if (flag != 0) {
@@ -973,7 +983,7 @@ static int dsync_strmap_compare_data(
973983
dsync_strmap_item_update(dst_map, name, DCMPF_CONTENT, DCMPS_DIFFER);
974984

975985
/* mark file to be deleted from destination, copied from source */
976-
if (use_hardlinks) {
986+
if (use_hardlinks || type == MFU_TYPE_LINK) {
977987
mfu_flist_file_copy(dst_compare_list, i, dst_remove_list);
978988
mfu_flist_file_copy(src_compare_list, i, src_cp_list);
979989
}
@@ -1171,7 +1181,9 @@ static int dsync_strmap_compare_lite(
11711181
mfu_flist dst_remove_list,
11721182
strmap* dst_map,
11731183
size_t strlen_prefix,
1174-
bool use_hardlinks)
1184+
bool use_hardlinks,
1185+
mfu_file_t* mfu_src_file,
1186+
mfu_file_t* mfu_dst_file)
11751187
{
11761188
/* assume we'll succeed */
11771189
int rc = 0;
@@ -1184,6 +1196,7 @@ static int dsync_strmap_compare_lite(
11841196
for (idx = 0; idx < size; idx++) {
11851197
/* lookup name of file based on id to send to strmap updata call */
11861198
const char* name = mfu_flist_file_get_name(src_compare_list, idx);
1199+
const mfu_filetype type = mfu_flist_file_get_type(src_compare_list, idx);
11871200

11881201
/* ignore prefix portion of path to use as key */
11891202
name += strlen_prefix;
@@ -1211,6 +1224,20 @@ static int dsync_strmap_compare_lite(
12111224
mfu_flist_file_copy(dst_compare_list, idx, dst_remove_list);
12121225
mfu_flist_file_copy(src_compare_list, idx, src_cp_list);
12131226
}
1227+
/* if symlink, check if targets of source and destination files match. If not, mark the
1228+
* files as being different. */
1229+
} else if (type == MFU_TYPE_LINK) {
1230+
if (mfu_compare_symlinks(mfu_flist_file_get_name(src_compare_list, idx),
1231+
mfu_flist_file_get_name(dst_compare_list, idx),
1232+
mfu_src_file, mfu_dst_file) == 0) {
1233+
/* update to say contents of the files were found to be the same */
1234+
dsync_strmap_item_update(src_map, name, DCMPF_CONTENT, DCMPS_COMMON);
1235+
dsync_strmap_item_update(dst_map, name, DCMPF_CONTENT, DCMPS_COMMON);
1236+
} else {
1237+
/* update to say contents of the symlinks were found to be different */
1238+
dsync_strmap_item_update(src_map, name, DCMPF_CONTENT, DCMPS_DIFFER);
1239+
dsync_strmap_item_update(dst_map, name, DCMPF_CONTENT, DCMPS_DIFFER);
1240+
}
12141241
} else {
12151242
/* update to say contents of the files were found to be the same */
12161243
dsync_strmap_item_update(src_map, name, DCMPF_CONTENT, DCMPS_COMMON);
@@ -1748,10 +1775,9 @@ static int dsync_strmap_compare(
17481775
continue;
17491776
}
17501777

1751-
/* for now, we can only compare content of regular files */
1752-
/* TODO: add support for symlinks */
1753-
if (! S_ISREG(dst_mode)) {
1754-
/* not regular file, take them as common content */
1778+
/* for now, we can only compare content of regular files and symlinks */
1779+
if (! S_ISREG(dst_mode) && !S_ISLNK(dst_mode)) {
1780+
/* not regular file or symlink, take them as common content */
17551781
dsync_strmap_item_update(src_map, key, DCMPF_CONTENT, DCMPS_COMMON);
17561782
dsync_strmap_item_update(dst_map, key, DCMPF_CONTENT, DCMPS_COMMON);
17571783
continue;
@@ -1832,7 +1858,7 @@ static int dsync_strmap_compare(
18321858
* adds files to remove and copy lists if different */
18331859
tmp_rc = dsync_strmap_compare_lite(src_compare_list, src_cp_list, dst_same_list,
18341860
src_map, dst_compare_list, dst_remove_list, dst_map,
1835-
strlen_prefix, use_hardlinks
1861+
strlen_prefix, use_hardlinks, mfu_src_file, mfu_dst_file
18361862
);
18371863
if (tmp_rc < 0) {
18381864
rc = -1;

0 commit comments

Comments
 (0)