static int do_readlink(struct iovec *iovec, struct iovec *out_iovec) { char *buffer; int size, retval; V9fsString target, path; v9fs_string_init(&path); retval = proxy_unmarshal(iovec, PROXY_HDR_SZ, "sd", &path, &size); if (retval < 0) { v9fs_string_free(&path); return retval; } buffer = g_malloc(size); v9fs_string_init(&target); retval = readlink(path.data, buffer, size - 1); if (retval > 0) { buffer[retval] = '\0'; v9fs_string_sprintf(&target, "%s", buffer); retval = proxy_marshal(out_iovec, PROXY_HDR_SZ, "s", &target); } else { retval = -errno; } g_free(buffer); v9fs_string_free(&target); v9fs_string_free(&path); return retval; }
/* * create other filesystem objects and send 0 on success * return -errno on error */ static int do_create_others(int type, struct iovec *iovec) { dev_t rdev; int retval = 0; int offset = PROXY_HDR_SZ; V9fsString oldpath, path; int mode, uid, gid, cur_uid, cur_gid; v9fs_string_init(&path); v9fs_string_init(&oldpath); cur_uid = geteuid(); cur_gid = getegid(); retval = proxy_unmarshal(iovec, offset, "dd", &uid, &gid); if (retval < 0) { return retval; } offset += retval; retval = setfsugid(uid, gid); if (retval < 0) { retval = -errno; goto err_out; } switch (type) { case T_MKNOD: retval = proxy_unmarshal(iovec, offset, "sdq", &path, &mode, &rdev); if (retval < 0) { goto err_out; } retval = mknod(path.data, mode, rdev); break; case T_MKDIR: retval = proxy_unmarshal(iovec, offset, "sd", &path, &mode); if (retval < 0) { goto err_out; } retval = mkdir(path.data, mode); break; case T_SYMLINK: retval = proxy_unmarshal(iovec, offset, "ss", &oldpath, &path); if (retval < 0) { goto err_out; } retval = symlink(oldpath.data, path.data); break; } if (retval < 0) { retval = -errno; } err_out: v9fs_string_free(&path); v9fs_string_free(&oldpath); setfsugid(cur_uid, cur_gid); return retval; }
static int do_getxattr(int type, struct iovec *iovec, struct iovec *out_iovec) { int size = 0, offset, retval; V9fsString path, name, xattr; v9fs_string_init(&xattr); v9fs_string_init(&path); retval = proxy_unmarshal(iovec, PROXY_HDR_SZ, "ds", &size, &path); if (retval < 0) { return retval; } offset = PROXY_HDR_SZ + retval; if (size) { xattr.data = g_malloc(size); xattr.size = size; } switch (type) { case T_LGETXATTR: v9fs_string_init(&name); retval = proxy_unmarshal(iovec, offset, "s", &name); if (retval > 0) { retval = lgetxattr(path.data, name.data, xattr.data, size); if (retval < 0) { retval = -errno; } else { xattr.size = retval; } } v9fs_string_free(&name); break; case T_LLISTXATTR: retval = llistxattr(path.data, xattr.data, size); if (retval < 0) { retval = -errno; } else { xattr.size = retval; } break; } if (retval < 0) { goto err_out; } if (!size) { proxy_marshal(out_iovec, PROXY_HDR_SZ, "d", retval); retval = sizeof(retval); } else { retval = proxy_marshal(out_iovec, PROXY_HDR_SZ, "s", &xattr); } err_out: v9fs_string_free(&xattr); v9fs_string_free(&path); return retval; }
static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, FsCred *credp) { char *path; int err = -1; int serrno = 0; V9fsString fullname; char *buffer = NULL; v9fs_string_init(&fullname); v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); path = fullname.data; /* Determine the security model */ if (fs_ctx->export_flags & V9FS_SM_MAPPED) { buffer = rpath(fs_ctx, path); err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0); if (err == -1) { goto out; } err = local_set_xattr(buffer, credp); if (err == -1) { serrno = errno; goto err_end; } } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { buffer = rpath(fs_ctx, path); err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0); if (err == -1) { goto out; } err = local_set_mapped_file_attr(fs_ctx, path, credp); if (err == -1) { serrno = errno; goto err_end; } } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || (fs_ctx->export_flags & V9FS_SM_NONE)) { buffer = rpath(fs_ctx, path); err = mknod(buffer, credp->fc_mode, credp->fc_rdev); if (err == -1) { goto out; } err = local_post_create_passthrough(fs_ctx, path, credp); if (err == -1) { serrno = errno; goto err_end; } } goto out; err_end: remove(buffer); errno = serrno; out: g_free(buffer); v9fs_string_free(&fullname); return err; }
static int local_link(FsContext *ctx, V9fsPath *oldpath, V9fsPath *dirpath, const char *name) { int ret; V9fsString newpath; char buffer[PATH_MAX], buffer1[PATH_MAX]; v9fs_string_init(&newpath); v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name); ret = link(rpath(ctx, oldpath->data, buffer), rpath(ctx, newpath.data, buffer1)); /* now link the virtfs_metadata files */ if (!ret && (ctx->export_flags & V9FS_SM_MAPPED_FILE)) { /* Link the .virtfs_metadata files. Create the metada directory */ ret = local_create_mapped_attr_dir(ctx, newpath.data); if (ret < 0) { goto err_out; } ret = link(local_mapped_attr_path(ctx, oldpath->data, buffer), local_mapped_attr_path(ctx, newpath.data, buffer1)); if (ret < 0 && errno != ENOENT) { goto err_out; } } err_out: v9fs_string_free(&newpath); return ret; }
/* * create a file and send fd on success * return -errno on error */ static int do_create(struct iovec *iovec) { int ret; V9fsString path; int flags, mode, uid, gid, cur_uid, cur_gid; v9fs_string_init(&path); ret = proxy_unmarshal(iovec, PROXY_HDR_SZ, "sdddd", &path, &flags, &mode, &uid, &gid); if (ret < 0) { goto unmarshal_err_out; } cur_uid = geteuid(); cur_gid = getegid(); ret = setfsugid(uid, gid); if (ret < 0) { /* * On failure reset back to the * old uid/gid */ ret = -errno; goto err_out; } ret = open(path.data, flags, mode); if (ret < 0) { LOGV("%s: Could not open file: %s", __func__, path.data); ret = -errno; } err_out: setfsugid(cur_uid, cur_gid); unmarshal_err_out: v9fs_string_free(&path); return ret; }
/* * create a file and send fd on success * return -errno on error */ static int do_create(struct iovec *iovec) { int ret; V9fsString path; int flags, mode, uid, gid, cur_uid, cur_gid; v9fs_string_init(&path); ret = proxy_unmarshal(iovec, PROXY_HDR_SZ, "sdddd", &path, &flags, &mode, &uid, &gid); if (ret < 0) { goto unmarshal_err_out; } ret = setugid(uid, gid, &cur_uid, &cur_gid); if (ret < 0) { goto unmarshal_err_out; } ret = open(path.data, flags, mode); if (ret < 0) { ret = -errno; } resetugid(cur_uid, cur_gid); unmarshal_err_out: v9fs_string_free(&path); return ret; }
static int local_renameat(FsContext *ctx, V9fsPath *olddir, const char *old_name, V9fsPath *newdir, const char *new_name) { int ret; V9fsString old_full_name, new_full_name; v9fs_string_init(&old_full_name); v9fs_string_init(&new_full_name); v9fs_string_sprintf(&old_full_name, "%s/%s", olddir->data, old_name); v9fs_string_sprintf(&new_full_name, "%s/%s", newdir->data, new_name); ret = local_rename(ctx, old_full_name.data, new_full_name.data); v9fs_string_free(&old_full_name); v9fs_string_free(&new_full_name); return ret; }
static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, int flags, FsCred *credp, V9fsFidOpenState *fs) { char *path; int fd = -1; int err = -1; int serrno = 0; V9fsString fullname; char buffer[PATH_MAX]; v9fs_string_init(&fullname); v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); path = fullname.data; /* Determine the security model */ if (fs_ctx->export_flags & V9FS_SM_MAPPED) { fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS); if (fd == -1) { err = fd; goto out; } credp->fc_mode = credp->fc_mode|S_IFREG; /* Set cleint credentials in xattr */ err = local_set_xattr(rpath(fs_ctx, path, buffer), credp); if (err == -1) { serrno = errno; goto err_end; } } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || (fs_ctx->export_flags & V9FS_SM_NONE)) { fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode); if (fd == -1) { err = fd; goto out; } err = local_post_create_passthrough(fs_ctx, path, credp); if (err == -1) { serrno = errno; goto err_end; } } err = fd; fs->fd = fd; goto out; err_end: close(fd); remove(rpath(fs_ctx, path, buffer)); errno = serrno; out: v9fs_string_free(&fullname); return err; }
/* * Gets stat/statfs information and packs in out_iovec structure * on success returns number of bytes packed in out_iovec struture * otherwise returns -errno */ static int do_stat(int type, struct iovec *iovec, struct iovec *out_iovec) { int retval; V9fsString path; ProxyStat pr_stat; ProxyStatFS pr_stfs; struct stat st_buf; struct statfs stfs_buf; v9fs_string_init(&path); retval = proxy_unmarshal(iovec, PROXY_HDR_SZ, "s", &path); if (retval < 0) { return retval; } switch (type) { case T_LSTAT: retval = lstat(path.data, &st_buf); if (retval < 0) { retval = -errno; } else { stat_to_prstat(&pr_stat, &st_buf); retval = proxy_marshal(out_iovec, PROXY_HDR_SZ, "qqqdddqqqqqqqqqq", pr_stat.st_dev, pr_stat.st_ino, pr_stat.st_nlink, pr_stat.st_mode, pr_stat.st_uid, pr_stat.st_gid, pr_stat.st_rdev, pr_stat.st_size, pr_stat.st_blksize, pr_stat.st_blocks, pr_stat.st_atim_sec, pr_stat.st_atim_nsec, pr_stat.st_mtim_sec, pr_stat.st_mtim_nsec, pr_stat.st_ctim_sec, pr_stat.st_ctim_nsec); } break; case T_STATFS: retval = statfs(path.data, &stfs_buf); if (retval < 0) { retval = -errno; } else { statfs_to_prstatfs(&pr_stfs, &stfs_buf); retval = proxy_marshal(out_iovec, PROXY_HDR_SZ, "qqqqqqqqqqq", pr_stfs.f_type, pr_stfs.f_bsize, pr_stfs.f_blocks, pr_stfs.f_bfree, pr_stfs.f_bavail, pr_stfs.f_files, pr_stfs.f_ffree, pr_stfs.f_fsid[0], pr_stfs.f_fsid[1], pr_stfs.f_namelen, pr_stfs.f_frsize); } break; } v9fs_string_free(&path); return retval; }
static int local_unlinkat(FsContext *ctx, V9fsPath *dir, const char *name, int flags) { int ret; V9fsString fullname; char *buffer; v9fs_string_init(&fullname); v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name); if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { if (flags == AT_REMOVEDIR) { /* * If directory remove .virtfs_metadata contained in the * directory */ buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, fullname.data, VIRTFS_META_DIR); ret = remove(buffer); g_free(buffer); if (ret < 0 && errno != ENOENT) { /* * We didn't had the .virtfs_metadata file. May be file created * in non-mapped mode ?. Ignore ENOENT. */ goto err_out; } } /* * Now remove the name from parent directory * .virtfs_metadata directory. */ buffer = local_mapped_attr_path(ctx, fullname.data); ret = remove(buffer); g_free(buffer); if (ret < 0 && errno != ENOENT) { /* * We didn't had the .virtfs_metadata file. May be file created * in non-mapped mode ?. Ignore ENOENT. */ goto err_out; } } /* Remove the name finally */ buffer = rpath(ctx, fullname.data); ret = remove(buffer); g_free(buffer); err_out: v9fs_string_free(&fullname); return ret; }
static int local_unlinkat(FsContext *ctx, V9fsPath *dir, const char *name, int flags) { int ret; V9fsString fullname; char buffer[PATH_MAX]; v9fs_string_init(&fullname); v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name); ret = remove(rpath(ctx, fullname.data, buffer)); v9fs_string_free(&fullname); return ret; }
static int local_link(FsContext *ctx, V9fsPath *oldpath, V9fsPath *dirpath, const char *name) { int ret; V9fsString newpath; char buffer[PATH_MAX], buffer1[PATH_MAX]; v9fs_string_init(&newpath); v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name); ret = link(rpath(ctx, oldpath->data, buffer), rpath(ctx, newpath.data, buffer1)); v9fs_string_free(&newpath); return ret; }
static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, FsCred *credp) { char *path; int err = -1; int serrno = 0; V9fsString fullname; char buffer[PATH_MAX]; v9fs_string_init(&fullname); v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); path = fullname.data; /* Determine the security model */ if (fs_ctx->export_flags & V9FS_SM_MAPPED) { err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS); if (err == -1) { goto out; } credp->fc_mode = credp->fc_mode|S_IFDIR; err = local_set_xattr(rpath(fs_ctx, path, buffer), credp); if (err == -1) { serrno = errno; goto err_end; } } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || (fs_ctx->export_flags & V9FS_SM_NONE)) { err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode); if (err == -1) { goto out; } err = local_post_create_passthrough(fs_ctx, path, credp); if (err == -1) { serrno = errno; goto err_end; } } goto out; err_end: remove(rpath(fs_ctx, path, buffer)); errno = serrno; out: v9fs_string_free(&fullname); return err; }
/* * open a file and send fd on success * return -errno on error */ static int do_open(struct iovec *iovec) { int flags, ret; V9fsString path; v9fs_string_init(&path); ret = proxy_unmarshal(iovec, PROXY_HDR_SZ, "sd", &path, &flags); if (ret < 0) { goto err_out; } ret = open(path.data, flags); if (ret < 0) { ret = -errno; } err_out: v9fs_string_free(&path); return ret; }
static int local_symlink(FsContext *fs_ctx, const char *oldpath, V9fsPath *dir_path, const char *name, FsCred *credp) { int err = -1; int serrno = 0; char *newpath; V9fsString fullname; char buffer[PATH_MAX]; v9fs_string_init(&fullname); v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); newpath = fullname.data; /* Determine the security model */ if (fs_ctx->export_flags & V9FS_SM_MAPPED) { int fd; ssize_t oldpath_size, write_size; fd = open(rpath(fs_ctx, newpath, buffer), O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS); if (fd == -1) { err = fd; goto out; } /* Write the oldpath (target) to the file. */ oldpath_size = strlen(oldpath); do { write_size = write(fd, (void *)oldpath, oldpath_size); } while (write_size == -1 && errno == EINTR); if (write_size != oldpath_size) { serrno = errno; close(fd); err = -1; goto err_end; } close(fd); /* Set cleint credentials in symlink's xattr */ credp->fc_mode = credp->fc_mode|S_IFLNK; err = local_set_xattr(rpath(fs_ctx, newpath, buffer), credp); if (err == -1) { serrno = errno; goto err_end; } } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { int fd; ssize_t oldpath_size, write_size; fd = open(rpath(fs_ctx, newpath, buffer), O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS); if (fd == -1) { err = fd; goto out; } /* Write the oldpath (target) to the file. */ oldpath_size = strlen(oldpath); do { write_size = write(fd, (void *)oldpath, oldpath_size); } while (write_size == -1 && errno == EINTR); if (write_size != oldpath_size) { serrno = errno; close(fd); err = -1; goto err_end; } close(fd); /* Set cleint credentials in symlink's xattr */ credp->fc_mode = credp->fc_mode|S_IFLNK; err = local_set_mapped_file_attr(fs_ctx, newpath, credp); if (err == -1) { serrno = errno; goto err_end; } } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || (fs_ctx->export_flags & V9FS_SM_NONE)) { err = symlink(oldpath, rpath(fs_ctx, newpath, buffer)); if (err) { goto out; } err = lchown(rpath(fs_ctx, newpath, buffer), credp->fc_uid, credp->fc_gid); if (err == -1) { /* * If we fail to change ownership and if we are * using security model none. Ignore the error */ if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) { serrno = errno; goto err_end; } else err = 0; } } goto out; err_end: remove(rpath(fs_ctx, newpath, buffer)); errno = serrno; out: v9fs_string_free(&fullname); return err; }
/* * Response contains two parts * {header, data} * header.type == T_ERROR, data -> -errno * header.type == T_SUCCESS, data -> response * size of errno/response is given by header.size * returns < 0, on transport error. response is * valid only if status >= 0. */ static int v9fs_receive_response(V9fsProxy *proxy, int type, int *status, void *response) { int retval; ProxyHeader header; struct iovec *reply = &proxy->in_iovec; *status = 0; reply->iov_len = 0; retval = socket_read(proxy->sockfd, reply->iov_base, PROXY_HDR_SZ); if (retval < 0) { return retval; } reply->iov_len = PROXY_HDR_SZ; proxy_unmarshal(reply, 0, "dd", &header.type, &header.size); /* * if response size > PROXY_MAX_IO_SZ, read the response but ignore it and * return -ENOBUFS */ if (header.size > PROXY_MAX_IO_SZ) { int count; while (header.size > 0) { count = MIN(PROXY_MAX_IO_SZ, header.size); count = socket_read(proxy->sockfd, reply->iov_base, count); if (count < 0) { return count; } header.size -= count; } *status = -ENOBUFS; return 0; } retval = socket_read(proxy->sockfd, reply->iov_base + PROXY_HDR_SZ, header.size); if (retval < 0) { return retval; } reply->iov_len += header.size; /* there was an error during processing request */ if (header.type == T_ERROR) { int ret; ret = proxy_unmarshal(reply, PROXY_HDR_SZ, "d", status); if (ret < 0) { *status = ret; } return 0; } switch (type) { case T_LSTAT: { ProxyStat prstat; retval = proxy_unmarshal(reply, PROXY_HDR_SZ, "qqqdddqqqqqqqqqq", &prstat.st_dev, &prstat.st_ino, &prstat.st_nlink, &prstat.st_mode, &prstat.st_uid, &prstat.st_gid, &prstat.st_rdev, &prstat.st_size, &prstat.st_blksize, &prstat.st_blocks, &prstat.st_atim_sec, &prstat.st_atim_nsec, &prstat.st_mtim_sec, &prstat.st_mtim_nsec, &prstat.st_ctim_sec, &prstat.st_ctim_nsec); prstat_to_stat(response, &prstat); break; } case T_STATFS: { ProxyStatFS prstfs; retval = proxy_unmarshal(reply, PROXY_HDR_SZ, "qqqqqqqqqqq", &prstfs.f_type, &prstfs.f_bsize, &prstfs.f_blocks, &prstfs.f_bfree, &prstfs.f_bavail, &prstfs.f_files, &prstfs.f_ffree, &prstfs.f_fsid[0], &prstfs.f_fsid[1], &prstfs.f_namelen, &prstfs.f_frsize); prstatfs_to_statfs(response, &prstfs); break; } case T_READLINK: { V9fsString target; v9fs_string_init(&target); retval = proxy_unmarshal(reply, PROXY_HDR_SZ, "s", &target); strcpy(response, target.data); v9fs_string_free(&target); break; } case T_LGETXATTR: case T_LLISTXATTR: { V9fsString xattr; v9fs_string_init(&xattr); retval = proxy_unmarshal(reply, PROXY_HDR_SZ, "s", &xattr); memcpy(response, xattr.data, xattr.size); v9fs_string_free(&xattr); break; } case T_GETVERSION: proxy_unmarshal(reply, PROXY_HDR_SZ, "q", response); break; default: return -1; } if (retval < 0) { *status = retval; } return 0; }
static int process_requests(int sock) { int flags; int size = 0; int retval = 0; uint64_t offset; ProxyHeader header; int mode, uid, gid; V9fsString name, value; struct timespec spec[2]; V9fsString oldpath, path; struct iovec in_iovec, out_iovec; in_iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ); in_iovec.iov_len = PROXY_MAX_IO_SZ + PROXY_HDR_SZ; out_iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ); out_iovec.iov_len = PROXY_MAX_IO_SZ + PROXY_HDR_SZ; while (1) { /* * initialize the header type, so that we send * response to proper request type. */ header.type = 0; retval = read_request(sock, &in_iovec, &header); if (retval < 0) { goto err_out; } switch (header.type) { case T_OPEN: retval = do_open(&in_iovec); break; case T_CREATE: retval = do_create(&in_iovec); break; case T_MKNOD: case T_MKDIR: case T_SYMLINK: retval = do_create_others(header.type, &in_iovec); break; case T_LINK: v9fs_string_init(&path); v9fs_string_init(&oldpath); retval = proxy_unmarshal(&in_iovec, PROXY_HDR_SZ, "ss", &oldpath, &path); if (retval > 0) { retval = link(oldpath.data, path.data); if (retval < 0) { retval = -errno; } } v9fs_string_free(&oldpath); v9fs_string_free(&path); break; case T_LSTAT: case T_STATFS: retval = do_stat(header.type, &in_iovec, &out_iovec); break; case T_READLINK: retval = do_readlink(&in_iovec, &out_iovec); break; case T_CHMOD: v9fs_string_init(&path); retval = proxy_unmarshal(&in_iovec, PROXY_HDR_SZ, "sd", &path, &mode); if (retval > 0) { retval = chmod(path.data, mode); if (retval < 0) { retval = -errno; } } v9fs_string_free(&path); break; case T_CHOWN: v9fs_string_init(&path); retval = proxy_unmarshal(&in_iovec, PROXY_HDR_SZ, "sdd", &path, &uid, &gid); if (retval > 0) { retval = lchown(path.data, uid, gid); if (retval < 0) { retval = -errno; } } v9fs_string_free(&path); break; case T_TRUNCATE: v9fs_string_init(&path); retval = proxy_unmarshal(&in_iovec, PROXY_HDR_SZ, "sq", &path, &offset); if (retval > 0) { retval = truncate(path.data, offset); if (retval < 0) { retval = -errno; } } v9fs_string_free(&path); break; case T_UTIME: v9fs_string_init(&path); retval = proxy_unmarshal(&in_iovec, PROXY_HDR_SZ, "sqqqq", &path, &spec[0].tv_sec, &spec[0].tv_nsec, &spec[1].tv_sec, &spec[1].tv_nsec); if (retval > 0) { retval = utimensat(AT_FDCWD, path.data, spec, AT_SYMLINK_NOFOLLOW); if (retval < 0) { retval = -errno; } } v9fs_string_free(&path); break; case T_RENAME: v9fs_string_init(&path); v9fs_string_init(&oldpath); retval = proxy_unmarshal(&in_iovec, PROXY_HDR_SZ, "ss", &oldpath, &path); if (retval > 0) { retval = rename(oldpath.data, path.data); if (retval < 0) { retval = -errno; } } v9fs_string_free(&oldpath); v9fs_string_free(&path); break; case T_REMOVE: v9fs_string_init(&path); retval = proxy_unmarshal(&in_iovec, PROXY_HDR_SZ, "s", &path); if (retval > 0) { retval = remove(path.data); if (retval < 0) { retval = -errno; } } v9fs_string_free(&path); break; case T_LGETXATTR: case T_LLISTXATTR: retval = do_getxattr(header.type, &in_iovec, &out_iovec); break; case T_LSETXATTR: v9fs_string_init(&path); v9fs_string_init(&name); v9fs_string_init(&value); retval = proxy_unmarshal(&in_iovec, PROXY_HDR_SZ, "sssdd", &path, &name, &value, &size, &flags); if (retval > 0) { retval = lsetxattr(path.data, name.data, value.data, size, flags); if (retval < 0) { retval = -errno; } } v9fs_string_free(&path); v9fs_string_free(&name); v9fs_string_free(&value); break; case T_LREMOVEXATTR: v9fs_string_init(&path); v9fs_string_init(&name); retval = proxy_unmarshal(&in_iovec, PROXY_HDR_SZ, "ss", &path, &name); if (retval > 0) { retval = lremovexattr(path.data, name.data); if (retval < 0) { retval = -errno; } } v9fs_string_free(&path); v9fs_string_free(&name); break; case T_GETVERSION: retval = do_getversion(&in_iovec, &out_iovec); break; default: goto err_out; break; } if (process_reply(sock, header.type, &out_iovec, retval) < 0) { goto err_out; } } err_out: g_free(in_iovec.iov_base); g_free(out_iovec.iov_base); return -1; }
static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, int flags, FsCred *credp, V9fsFidOpenState *fs) { char *path; int fd = -1; int err = -1; int serrno = 0; V9fsString fullname; char *buffer; /* * Mark all the open to not follow symlinks */ flags |= O_NOFOLLOW; v9fs_string_init(&fullname); v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); path = fullname.data; /* Determine the security model */ if (fs_ctx->export_flags & V9FS_SM_MAPPED) { buffer = rpath(fs_ctx, path); fd = open(buffer, flags, SM_LOCAL_MODE_BITS); if (fd == -1) { g_free(buffer); err = fd; goto out; } credp->fc_mode = credp->fc_mode|S_IFREG; /* Set cleint credentials in xattr */ err = local_set_xattr(buffer, credp); if (err == -1) { serrno = errno; goto err_end; } } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { buffer = rpath(fs_ctx, path); fd = open(buffer, flags, SM_LOCAL_MODE_BITS); if (fd == -1) { g_free(buffer); err = fd; goto out; } credp->fc_mode = credp->fc_mode|S_IFREG; /* Set client credentials in .virtfs_metadata directory files */ err = local_set_mapped_file_attr(fs_ctx, path, credp); if (err == -1) { serrno = errno; goto err_end; } } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || (fs_ctx->export_flags & V9FS_SM_NONE)) { buffer = rpath(fs_ctx, path); fd = open(buffer, flags, credp->fc_mode); if (fd == -1) { g_free(buffer); err = fd; goto out; } err = local_post_create_passthrough(fs_ctx, path, credp); if (err == -1) { serrno = errno; goto err_end; } } err = fd; fs->fd = fd; goto out; err_end: close(fd); remove(buffer); errno = serrno; g_free(buffer); out: v9fs_string_free(&fullname); return err; }