char* pack_stat(struct stat *stbuf, char *buffer) { uint32_t mode = stbuf->st_mode; uint64_t size = stbuf->st_size; uint64_t atime = stbuf->st_atime; uint64_t mtime = stbuf->st_mtime; uint64_t ctime = stbuf->st_ctime; uint32_t nlink = stbuf->st_nlink; uint32_t blocks = stbuf->st_blocks; uint64_t ino = stbuf->st_ino; pack_32(&blocks, pack_32(&nlink, pack_64(&ctime, pack_64(&mtime, pack_64(&atime, pack_64(&size, pack_32(&mode, pack_64(&ino, buffer )))))))); #ifdef RFS_DEBUG dump(buffer, STAT_BLOCK_SIZE); #endif return buffer + STAT_BLOCK_SIZE; }
int _rfs_link(struct rfs_instance *instance, const char *path, const char *target) { if (instance->sendrecv.socket == -1) { return -ECONNABORTED; } uint32_t path_len = strlen(path) + 1; unsigned target_len = strlen(target) + 1; unsigned overall_size = sizeof(path_len) + path_len + target_len; struct rfs_command cmd = { cmd_link, overall_size }; char *buffer = malloc(cmd.data_len); pack(target, target_len, pack(path, path_len, pack_32(&path_len, buffer ))); send_token_t token = { 0 }; if (do_send(&instance->sendrecv, queue_data(buffer, overall_size, queue_cmd(&cmd, &token))) < 0) { free(buffer); return -ECONNABORTED; } free(buffer); struct rfs_answer ans = { 0 }; if (rfs_receive_answer(&instance->sendrecv, &ans) == -1) { return -ECONNABORTED; } if (ans.command != cmd_link || ans.data_len != 0) { return cleanup_badmsg(instance, &ans); } if (ans.ret == 0) { delete_from_cache(&instance->attr_cache, path); } return ans.ret == -1 ? -ans.ret_errno : ans.ret; }
inline void packet(char* buff, size_t* buff_n, bool pack) { pack_u8(&attribute_group, buff, buff_n, pack); pack_u8(&attribute_type, buff, buff_n, pack); pack_32(&value, buff, buff_n, pack); }
int _rfs_create(struct rfs_instance *instance, const char *path, mode_t mode, int flags, uint64_t *desc) { if (instance->sendrecv.socket == -1) { return -ECONNABORTED; } unsigned path_len = strlen(path) + 1; uint32_t fmode = mode; uint16_t fi_flags = rfs_file_flags(flags); if ((fmode & 0777) == 0) { fmode |= 0600; } unsigned overall_size = sizeof(fmode) + sizeof(fi_flags) + path_len; struct rfs_command cmd = { cmd_create, overall_size }; char *buffer = malloc(cmd.data_len); pack(path, path_len, pack_16(&fi_flags, pack_32(&fmode, buffer ))); send_token_t token = { 0 }; if (do_send(&instance->sendrecv, queue_data(buffer, overall_size, queue_cmd(&cmd, &token))) < 0) { free(buffer); return -ECONNABORTED; } free(buffer); struct rfs_answer ans = { 0 }; if (rfs_receive_answer(&instance->sendrecv, &ans) == -1) { return -ECONNABORTED; } if (ans.command != cmd_create) { return cleanup_badmsg(instance, &ans); } if (ans.ret == 0) { uint64_t handle = (uint64_t)(-1); if (ans.data_len != sizeof(handle)) { return cleanup_badmsg(instance, &ans); } if (rfs_receive_data(&instance->sendrecv, &handle, ans.data_len) == -1) { return -ECONNABORTED; } *desc = ntohll(handle); /* add file to open list, but without O_CREAT flag to just reopen file * on connection resume */ resume_add_file_to_open_list(&instance->resume.open_files, path, (flags & ~O_CREAT), *desc); } return (ans.ret == 0 ? 0 : -ans.ret_errno); }