Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A few cleanups around symlinks #337

Merged
merged 3 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libcomposefs/lcfs-writer-erofs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1746,7 +1746,7 @@ static struct lcfs_node_s *lcfs_build_node_from_image(struct lcfs_image_data *da

memcpy(name_buf, tail_data, file_size);
name_buf[file_size] = 0;
if (lcfs_node_set_payload(node, name_buf) < 0)
if (lcfs_node_set_symlink_payload(node, name_buf) < 0)
return NULL;

} else if (type == S_IFREG && file_size != 0 && erofs_inode_is_flat(cino)) {
Expand Down
38 changes: 37 additions & 1 deletion libcomposefs/lcfs-writer.c
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,7 @@ struct lcfs_node_s *lcfs_load_node_from_file(int dirfd, const char *fname,
return NULL;

target[r] = '\0';
r = lcfs_node_set_payload(ret, target);
r = lcfs_node_set_symlink_payload(ret, target);
if (r < 0)
return NULL;
}
Expand Down Expand Up @@ -917,6 +917,33 @@ int lcfs_node_set_payload(struct lcfs_node_s *node, const char *payload)
return 0;
}

int lcfs_node_set_symlink_payload(struct lcfs_node_s *node, const char *payload)
{
// Caller must have ensured this
assert((node->inode.st_mode & S_IFMT) == S_IFLNK);
// Symlink target must be non-empty
if (payload == NULL || !*payload) {
errno = EINVAL;
return -1;
}
// Call the "raw" API for setting payloads, which also verifies
// maximum length.
if (lcfs_node_set_payload(node, payload) < 0) {
return -1;
}
// We must have set a payload now
assert(node->payload);
// Historically we accept any arbitrary data in the dumpfile
// for the file size for symlink, and end up ignoring it
// ultimately when we write the EROFS. However previously
// it was pretty confusing as the in-memory node data
// could have a bogus size. If somehow the inode state claimed
// something else for size, let's always replace it with the symlink
// length which is canonical.
node->inode.st_size = strlen(node->payload);
return 0;
}

const char *lcfs_node_get_payload(struct lcfs_node_s *node)
{
return node->payload;
Expand Down Expand Up @@ -989,6 +1016,15 @@ void lcfs_node_set_mode(struct lcfs_node_s *node, uint32_t mode)
node->inode.st_mode = mode;
}

int lcfs_node_try_set_mode(struct lcfs_node_s *node, uint32_t mode)
{
if (lcfs_validate_mode(mode) < 0) {
return -1;
}
node->inode.st_mode = mode;
return 0;
}

uint32_t lcfs_node_get_uid(struct lcfs_node_s *node)
{
return node->inode.st_uid;
Expand Down
3 changes: 3 additions & 0 deletions libcomposefs/lcfs-writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ LCFS_EXTERN const char *lcfs_node_get_xattr_name(struct lcfs_node_s *node,
size_t index);

LCFS_EXTERN int lcfs_node_set_payload(struct lcfs_node_s *node, const char *payload);
LCFS_EXTERN int lcfs_node_set_symlink_payload(struct lcfs_node_s *node,
const char *payload);
LCFS_EXTERN const char *lcfs_node_get_payload(struct lcfs_node_s *node);

LCFS_EXTERN int lcfs_node_set_content(struct lcfs_node_s *node,
Expand All @@ -131,6 +133,7 @@ LCFS_EXTERN struct lcfs_node_s *lcfs_node_get_hardlink_target(struct lcfs_node_s
LCFS_EXTERN bool lcfs_node_dirp(struct lcfs_node_s *node);
LCFS_EXTERN uint32_t lcfs_node_get_mode(struct lcfs_node_s *node);
LCFS_EXTERN void lcfs_node_set_mode(struct lcfs_node_s *node, uint32_t mode);
LCFS_EXTERN int lcfs_node_try_set_mode(struct lcfs_node_s *node, uint32_t mode);
LCFS_EXTERN uint32_t lcfs_node_get_uid(struct lcfs_node_s *node);
LCFS_EXTERN void lcfs_node_set_uid(struct lcfs_node_s *node, uint32_t uid);
LCFS_EXTERN uint32_t lcfs_node_get_gid(struct lcfs_node_s *node);
Expand Down
20 changes: 12 additions & 8 deletions tools/mkcomposefs.c
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,10 @@ static char *tree_from_dump_line(dump_info *info, const char *line, size_t line_
if (node == NULL) {
oom();
}
lcfs_node_set_mode(node, mode);
if (lcfs_node_try_set_mode(node, mode) < 0) {
return make_error("Invalid mode %o", (unsigned int)mode);
}
unsigned int type = mode & S_IFMT;

err = tree_add_node(info, path, node);
if (err)
Expand Down Expand Up @@ -507,21 +510,22 @@ static char *tree_from_dump_line(dump_info *info, const char *line, size_t line_
if (digest == NULL && err)
return err;

lcfs_node_set_mode(node, mode);
lcfs_node_set_size(node, size);
if (type != S_IFLNK)
lcfs_node_set_size(node, size);
lcfs_node_set_nlink(node, nlink);
lcfs_node_set_uid(node, uid);
lcfs_node_set_gid(node, gid);
lcfs_node_set_rdev64(node, rdev);
lcfs_node_set_mtime(node, &mtime);
// Validate that symlinks are non-empty
if ((mode & S_IFMT) == S_IFLNK) {
if (payload == NULL) {
return make_error("Invalid empty symlink");
if (type == S_IFLNK) {
if (lcfs_node_set_symlink_payload(node, payload) < 0) {
return make_error("Invalid symlink");
}
} else {
if (lcfs_node_set_payload(node, payload) < 0)
return make_error("Invalid payload");
}
if (lcfs_node_set_payload(node, payload) < 0)
return make_error("Invalid payload");
if (content) {
ret = lcfs_node_set_content(node, (uint8_t *)content, size);
if (ret < 0)
Expand Down
Loading