19f107513SAnthony Liguori /* 2f00d4f59SWei Liu * 9p Posix callback 39f107513SAnthony Liguori * 49f107513SAnthony Liguori * Copyright IBM, Corp. 2010 59f107513SAnthony Liguori * 69f107513SAnthony Liguori * Authors: 79f107513SAnthony Liguori * Anthony Liguori <aliguori@us.ibm.com> 89f107513SAnthony Liguori * 99f107513SAnthony Liguori * This work is licensed under the terms of the GNU GPL, version 2. See 109f107513SAnthony Liguori * the COPYING file in the top-level directory. 119f107513SAnthony Liguori * 129f107513SAnthony Liguori */ 13873c3213SStefan Weil 14fbc04127SPeter Maydell #include "qemu/osdep.h" 15ebe74f8bSWei Liu #include "9p.h" 16267ae092SWei Liu #include "9p-xattr.h" 1769b15212SStefan Weil #include "fsdev/qemu-fsdev.h" /* local_ops */ 18c494dd6fSAnthony Liguori #include <arpa/inet.h> 19131dcb25SAnthony Liguori #include <pwd.h> 20131dcb25SAnthony Liguori #include <grp.h> 21c494dd6fSAnthony Liguori #include <sys/socket.h> 22c494dd6fSAnthony Liguori #include <sys/un.h> 231de7afc9SPaolo Bonzini #include "qemu/xattr.h" 24f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 2563325b18SGreg Kurz #include "qemu/error-report.h" 262c30dd74SAneesh Kumar K.V #include <libgen.h> 27e06a765eSHarsh Prateek Bora #include <linux/fs.h> 28e06a765eSHarsh Prateek Bora #ifdef CONFIG_LINUX_MAGIC_H 29e06a765eSHarsh Prateek Bora #include <linux/magic.h> 30e06a765eSHarsh Prateek Bora #endif 31e06a765eSHarsh Prateek Bora #include <sys/ioctl.h> 32e06a765eSHarsh Prateek Bora 33e06a765eSHarsh Prateek Bora #ifndef XFS_SUPER_MAGIC 34e06a765eSHarsh Prateek Bora #define XFS_SUPER_MAGIC 0x58465342 35e06a765eSHarsh Prateek Bora #endif 36e06a765eSHarsh Prateek Bora #ifndef EXT2_SUPER_MAGIC 37e06a765eSHarsh Prateek Bora #define EXT2_SUPER_MAGIC 0xEF53 38e06a765eSHarsh Prateek Bora #endif 39e06a765eSHarsh Prateek Bora #ifndef REISERFS_SUPER_MAGIC 40e06a765eSHarsh Prateek Bora #define REISERFS_SUPER_MAGIC 0x52654973 41e06a765eSHarsh Prateek Bora #endif 42e06a765eSHarsh Prateek Bora #ifndef BTRFS_SUPER_MAGIC 43e06a765eSHarsh Prateek Bora #define BTRFS_SUPER_MAGIC 0x9123683E 44e06a765eSHarsh Prateek Bora #endif 45131dcb25SAnthony Liguori 462c30dd74SAneesh Kumar K.V #define VIRTFS_META_DIR ".virtfs_metadata" 472c30dd74SAneesh Kumar K.V 484fa4ce71SChen Gang static char *local_mapped_attr_path(FsContext *ctx, const char *path) 492c30dd74SAneesh Kumar K.V { 501b6f85e2SMichael Tokarev int dirlen; 511b6f85e2SMichael Tokarev const char *name = strrchr(path, '/'); 521b6f85e2SMichael Tokarev if (name) { 531b6f85e2SMichael Tokarev dirlen = name - path; 541b6f85e2SMichael Tokarev ++name; 551b6f85e2SMichael Tokarev } else { 561b6f85e2SMichael Tokarev name = path; 571b6f85e2SMichael Tokarev dirlen = 0; 581b6f85e2SMichael Tokarev } 591b6f85e2SMichael Tokarev return g_strdup_printf("%s/%.*s/%s/%s", ctx->fs_root, 601b6f85e2SMichael Tokarev dirlen, path, VIRTFS_META_DIR, name); 612c30dd74SAneesh Kumar K.V } 622c30dd74SAneesh Kumar K.V 630ceb092eSAneesh Kumar K.V static FILE *local_fopen(const char *path, const char *mode) 640ceb092eSAneesh Kumar K.V { 650ceb092eSAneesh Kumar K.V int fd, o_mode = 0; 660ceb092eSAneesh Kumar K.V FILE *fp; 670ceb092eSAneesh Kumar K.V int flags = O_NOFOLLOW; 680ceb092eSAneesh Kumar K.V /* 690ceb092eSAneesh Kumar K.V * only supports two modes 700ceb092eSAneesh Kumar K.V */ 710ceb092eSAneesh Kumar K.V if (mode[0] == 'r') { 720ceb092eSAneesh Kumar K.V flags |= O_RDONLY; 730ceb092eSAneesh Kumar K.V } else if (mode[0] == 'w') { 740ceb092eSAneesh Kumar K.V flags |= O_WRONLY | O_TRUNC | O_CREAT; 750ceb092eSAneesh Kumar K.V o_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; 760ceb092eSAneesh Kumar K.V } else { 770ceb092eSAneesh Kumar K.V return NULL; 780ceb092eSAneesh Kumar K.V } 790ceb092eSAneesh Kumar K.V fd = open(path, flags, o_mode); 800ceb092eSAneesh Kumar K.V if (fd == -1) { 810ceb092eSAneesh Kumar K.V return NULL; 820ceb092eSAneesh Kumar K.V } 830ceb092eSAneesh Kumar K.V fp = fdopen(fd, mode); 840ceb092eSAneesh Kumar K.V if (!fp) { 850ceb092eSAneesh Kumar K.V close(fd); 860ceb092eSAneesh Kumar K.V } 870ceb092eSAneesh Kumar K.V return fp; 880ceb092eSAneesh Kumar K.V } 890ceb092eSAneesh Kumar K.V 902c30dd74SAneesh Kumar K.V #define ATTR_MAX 100 912c30dd74SAneesh Kumar K.V static void local_mapped_file_attr(FsContext *ctx, const char *path, 922c30dd74SAneesh Kumar K.V struct stat *stbuf) 932c30dd74SAneesh Kumar K.V { 942c30dd74SAneesh Kumar K.V FILE *fp; 952c30dd74SAneesh Kumar K.V char buf[ATTR_MAX]; 964fa4ce71SChen Gang char *attr_path; 972c30dd74SAneesh Kumar K.V 984fa4ce71SChen Gang attr_path = local_mapped_attr_path(ctx, path); 990ceb092eSAneesh Kumar K.V fp = local_fopen(attr_path, "r"); 1004fa4ce71SChen Gang g_free(attr_path); 1012c30dd74SAneesh Kumar K.V if (!fp) { 1022c30dd74SAneesh Kumar K.V return; 1032c30dd74SAneesh Kumar K.V } 1042c30dd74SAneesh Kumar K.V memset(buf, 0, ATTR_MAX); 1052c30dd74SAneesh Kumar K.V while (fgets(buf, ATTR_MAX, fp)) { 1062c30dd74SAneesh Kumar K.V if (!strncmp(buf, "virtfs.uid", 10)) { 1072c30dd74SAneesh Kumar K.V stbuf->st_uid = atoi(buf+11); 1082c30dd74SAneesh Kumar K.V } else if (!strncmp(buf, "virtfs.gid", 10)) { 1092c30dd74SAneesh Kumar K.V stbuf->st_gid = atoi(buf+11); 1102c30dd74SAneesh Kumar K.V } else if (!strncmp(buf, "virtfs.mode", 11)) { 1112c30dd74SAneesh Kumar K.V stbuf->st_mode = atoi(buf+12); 1122c30dd74SAneesh Kumar K.V } else if (!strncmp(buf, "virtfs.rdev", 11)) { 1132c30dd74SAneesh Kumar K.V stbuf->st_rdev = atoi(buf+12); 1142c30dd74SAneesh Kumar K.V } 1152c30dd74SAneesh Kumar K.V memset(buf, 0, ATTR_MAX); 1162c30dd74SAneesh Kumar K.V } 1172c30dd74SAneesh Kumar K.V fclose(fp); 1182c30dd74SAneesh Kumar K.V } 1192c30dd74SAneesh Kumar K.V 1202289be19SAneesh Kumar K.V static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf) 121131dcb25SAnthony Liguori { 1221237ad76SVenkateswararao Jujjuri (JV) int err; 1234fa4ce71SChen Gang char *buffer; 1242289be19SAneesh Kumar K.V char *path = fs_path->data; 1252289be19SAneesh Kumar K.V 1264fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 1274fa4ce71SChen Gang err = lstat(buffer, stbuf); 1281237ad76SVenkateswararao Jujjuri (JV) if (err) { 1294fa4ce71SChen Gang goto err_out; 1301237ad76SVenkateswararao Jujjuri (JV) } 131b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 1321237ad76SVenkateswararao Jujjuri (JV) /* Actual credentials are part of extended attrs */ 1331237ad76SVenkateswararao Jujjuri (JV) uid_t tmp_uid; 1341237ad76SVenkateswararao Jujjuri (JV) gid_t tmp_gid; 1351237ad76SVenkateswararao Jujjuri (JV) mode_t tmp_mode; 1361237ad76SVenkateswararao Jujjuri (JV) dev_t tmp_dev; 1374fa4ce71SChen Gang if (getxattr(buffer, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) { 138f8ad4a89SAneesh Kumar K.V stbuf->st_uid = le32_to_cpu(tmp_uid); 1391237ad76SVenkateswararao Jujjuri (JV) } 1404fa4ce71SChen Gang if (getxattr(buffer, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) { 141f8ad4a89SAneesh Kumar K.V stbuf->st_gid = le32_to_cpu(tmp_gid); 1421237ad76SVenkateswararao Jujjuri (JV) } 1434fa4ce71SChen Gang if (getxattr(buffer, "user.virtfs.mode", 144faa44e3dSVenkateswararao Jujjuri (JV) &tmp_mode, sizeof(mode_t)) > 0) { 145f8ad4a89SAneesh Kumar K.V stbuf->st_mode = le32_to_cpu(tmp_mode); 1461237ad76SVenkateswararao Jujjuri (JV) } 1474fa4ce71SChen Gang if (getxattr(buffer, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) { 148f8ad4a89SAneesh Kumar K.V stbuf->st_rdev = le64_to_cpu(tmp_dev); 1491237ad76SVenkateswararao Jujjuri (JV) } 1502c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 1512c30dd74SAneesh Kumar K.V local_mapped_file_attr(fs_ctx, path, stbuf); 1521237ad76SVenkateswararao Jujjuri (JV) } 1534fa4ce71SChen Gang 1544fa4ce71SChen Gang err_out: 1554fa4ce71SChen Gang g_free(buffer); 1561237ad76SVenkateswararao Jujjuri (JV) return err; 157131dcb25SAnthony Liguori } 158131dcb25SAnthony Liguori 1592c30dd74SAneesh Kumar K.V static int local_create_mapped_attr_dir(FsContext *ctx, const char *path) 1602c30dd74SAneesh Kumar K.V { 1612c30dd74SAneesh Kumar K.V int err; 1624fa4ce71SChen Gang char *attr_dir; 163d3f8e138SMarkus Armbruster char *tmp_path = g_strdup(path); 1642c30dd74SAneesh Kumar K.V 1654fa4ce71SChen Gang attr_dir = g_strdup_printf("%s/%s/%s", 1662c30dd74SAneesh Kumar K.V ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR); 1672c30dd74SAneesh Kumar K.V 1682c30dd74SAneesh Kumar K.V err = mkdir(attr_dir, 0700); 1692c30dd74SAneesh Kumar K.V if (err < 0 && errno == EEXIST) { 1702c30dd74SAneesh Kumar K.V err = 0; 1712c30dd74SAneesh Kumar K.V } 1724fa4ce71SChen Gang g_free(attr_dir); 173d3f8e138SMarkus Armbruster g_free(tmp_path); 1742c30dd74SAneesh Kumar K.V return err; 1752c30dd74SAneesh Kumar K.V } 1762c30dd74SAneesh Kumar K.V 1772c30dd74SAneesh Kumar K.V static int local_set_mapped_file_attr(FsContext *ctx, 1782c30dd74SAneesh Kumar K.V const char *path, FsCred *credp) 1792c30dd74SAneesh Kumar K.V { 1802c30dd74SAneesh Kumar K.V FILE *fp; 1812c30dd74SAneesh Kumar K.V int ret = 0; 1822c30dd74SAneesh Kumar K.V char buf[ATTR_MAX]; 1834fa4ce71SChen Gang char *attr_path; 1842c30dd74SAneesh Kumar K.V int uid = -1, gid = -1, mode = -1, rdev = -1; 1852c30dd74SAneesh Kumar K.V 1864fa4ce71SChen Gang attr_path = local_mapped_attr_path(ctx, path); 1874fa4ce71SChen Gang fp = local_fopen(attr_path, "r"); 1882c30dd74SAneesh Kumar K.V if (!fp) { 1892c30dd74SAneesh Kumar K.V goto create_map_file; 1902c30dd74SAneesh Kumar K.V } 1912c30dd74SAneesh Kumar K.V memset(buf, 0, ATTR_MAX); 1922c30dd74SAneesh Kumar K.V while (fgets(buf, ATTR_MAX, fp)) { 1932c30dd74SAneesh Kumar K.V if (!strncmp(buf, "virtfs.uid", 10)) { 1942c30dd74SAneesh Kumar K.V uid = atoi(buf+11); 1952c30dd74SAneesh Kumar K.V } else if (!strncmp(buf, "virtfs.gid", 10)) { 1962c30dd74SAneesh Kumar K.V gid = atoi(buf+11); 1972c30dd74SAneesh Kumar K.V } else if (!strncmp(buf, "virtfs.mode", 11)) { 1982c30dd74SAneesh Kumar K.V mode = atoi(buf+12); 1992c30dd74SAneesh Kumar K.V } else if (!strncmp(buf, "virtfs.rdev", 11)) { 2002c30dd74SAneesh Kumar K.V rdev = atoi(buf+12); 2012c30dd74SAneesh Kumar K.V } 2022c30dd74SAneesh Kumar K.V memset(buf, 0, ATTR_MAX); 2032c30dd74SAneesh Kumar K.V } 2042c30dd74SAneesh Kumar K.V fclose(fp); 2052c30dd74SAneesh Kumar K.V goto update_map_file; 2062c30dd74SAneesh Kumar K.V 2072c30dd74SAneesh Kumar K.V create_map_file: 2082c30dd74SAneesh Kumar K.V ret = local_create_mapped_attr_dir(ctx, path); 2092c30dd74SAneesh Kumar K.V if (ret < 0) { 2102c30dd74SAneesh Kumar K.V goto err_out; 2112c30dd74SAneesh Kumar K.V } 2122c30dd74SAneesh Kumar K.V 2132c30dd74SAneesh Kumar K.V update_map_file: 2140ceb092eSAneesh Kumar K.V fp = local_fopen(attr_path, "w"); 2152c30dd74SAneesh Kumar K.V if (!fp) { 2162c30dd74SAneesh Kumar K.V ret = -1; 2172c30dd74SAneesh Kumar K.V goto err_out; 2182c30dd74SAneesh Kumar K.V } 2192c30dd74SAneesh Kumar K.V 2202c30dd74SAneesh Kumar K.V if (credp->fc_uid != -1) { 2212c30dd74SAneesh Kumar K.V uid = credp->fc_uid; 2222c30dd74SAneesh Kumar K.V } 2232c30dd74SAneesh Kumar K.V if (credp->fc_gid != -1) { 2242c30dd74SAneesh Kumar K.V gid = credp->fc_gid; 2252c30dd74SAneesh Kumar K.V } 2262c30dd74SAneesh Kumar K.V if (credp->fc_mode != -1) { 2272c30dd74SAneesh Kumar K.V mode = credp->fc_mode; 2282c30dd74SAneesh Kumar K.V } 2292c30dd74SAneesh Kumar K.V if (credp->fc_rdev != -1) { 2302c30dd74SAneesh Kumar K.V rdev = credp->fc_rdev; 2312c30dd74SAneesh Kumar K.V } 2322c30dd74SAneesh Kumar K.V 2332c30dd74SAneesh Kumar K.V 2342c30dd74SAneesh Kumar K.V if (uid != -1) { 2352c30dd74SAneesh Kumar K.V fprintf(fp, "virtfs.uid=%d\n", uid); 2362c30dd74SAneesh Kumar K.V } 2372c30dd74SAneesh Kumar K.V if (gid != -1) { 2382c30dd74SAneesh Kumar K.V fprintf(fp, "virtfs.gid=%d\n", gid); 2392c30dd74SAneesh Kumar K.V } 2402c30dd74SAneesh Kumar K.V if (mode != -1) { 2412c30dd74SAneesh Kumar K.V fprintf(fp, "virtfs.mode=%d\n", mode); 2422c30dd74SAneesh Kumar K.V } 2432c30dd74SAneesh Kumar K.V if (rdev != -1) { 2442c30dd74SAneesh Kumar K.V fprintf(fp, "virtfs.rdev=%d\n", rdev); 2452c30dd74SAneesh Kumar K.V } 2462c30dd74SAneesh Kumar K.V fclose(fp); 2472c30dd74SAneesh Kumar K.V 2482c30dd74SAneesh Kumar K.V err_out: 2494fa4ce71SChen Gang g_free(attr_path); 2502c30dd74SAneesh Kumar K.V return ret; 2512c30dd74SAneesh Kumar K.V } 2522c30dd74SAneesh Kumar K.V 253758e8e38SVenkateswararao Jujjuri (JV) static int local_set_xattr(const char *path, FsCred *credp) 254131dcb25SAnthony Liguori { 255758e8e38SVenkateswararao Jujjuri (JV) int err; 2562289be19SAneesh Kumar K.V 257758e8e38SVenkateswararao Jujjuri (JV) if (credp->fc_uid != -1) { 258f8ad4a89SAneesh Kumar K.V uint32_t tmp_uid = cpu_to_le32(credp->fc_uid); 259f8ad4a89SAneesh Kumar K.V err = setxattr(path, "user.virtfs.uid", &tmp_uid, sizeof(uid_t), 0); 260758e8e38SVenkateswararao Jujjuri (JV) if (err) { 261758e8e38SVenkateswararao Jujjuri (JV) return err; 262131dcb25SAnthony Liguori } 263131dcb25SAnthony Liguori } 264758e8e38SVenkateswararao Jujjuri (JV) if (credp->fc_gid != -1) { 265f8ad4a89SAneesh Kumar K.V uint32_t tmp_gid = cpu_to_le32(credp->fc_gid); 266f8ad4a89SAneesh Kumar K.V err = setxattr(path, "user.virtfs.gid", &tmp_gid, sizeof(gid_t), 0); 267758e8e38SVenkateswararao Jujjuri (JV) if (err) { 268758e8e38SVenkateswararao Jujjuri (JV) return err; 269131dcb25SAnthony Liguori } 270131dcb25SAnthony Liguori } 271758e8e38SVenkateswararao Jujjuri (JV) if (credp->fc_mode != -1) { 272f8ad4a89SAneesh Kumar K.V uint32_t tmp_mode = cpu_to_le32(credp->fc_mode); 273f8ad4a89SAneesh Kumar K.V err = setxattr(path, "user.virtfs.mode", &tmp_mode, sizeof(mode_t), 0); 274758e8e38SVenkateswararao Jujjuri (JV) if (err) { 275758e8e38SVenkateswararao Jujjuri (JV) return err; 276131dcb25SAnthony Liguori } 277131dcb25SAnthony Liguori } 278758e8e38SVenkateswararao Jujjuri (JV) if (credp->fc_rdev != -1) { 279f8ad4a89SAneesh Kumar K.V uint64_t tmp_rdev = cpu_to_le64(credp->fc_rdev); 280f8ad4a89SAneesh Kumar K.V err = setxattr(path, "user.virtfs.rdev", &tmp_rdev, sizeof(dev_t), 0); 281758e8e38SVenkateswararao Jujjuri (JV) if (err) { 282758e8e38SVenkateswararao Jujjuri (JV) return err; 283131dcb25SAnthony Liguori } 284758e8e38SVenkateswararao Jujjuri (JV) } 285131dcb25SAnthony Liguori return 0; 286131dcb25SAnthony Liguori } 287131dcb25SAnthony Liguori 2884750a96fSVenkateswararao Jujjuri (JV) static int local_post_create_passthrough(FsContext *fs_ctx, const char *path, 2894750a96fSVenkateswararao Jujjuri (JV) FsCred *credp) 2904750a96fSVenkateswararao Jujjuri (JV) { 2914fa4ce71SChen Gang char *buffer; 2922289be19SAneesh Kumar K.V 2934fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 2944fa4ce71SChen Gang if (lchown(buffer, credp->fc_uid, credp->fc_gid) < 0) { 29512848bfcSAneesh Kumar K.V /* 29612848bfcSAneesh Kumar K.V * If we fail to change ownership and if we are 29712848bfcSAneesh Kumar K.V * using security model none. Ignore the error 29812848bfcSAneesh Kumar K.V */ 299b97400caSAneesh Kumar K.V if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) { 3004fa4ce71SChen Gang goto err; 3014750a96fSVenkateswararao Jujjuri (JV) } 30212848bfcSAneesh Kumar K.V } 3032d40564aSM. Mohan Kumar 3044fa4ce71SChen Gang if (chmod(buffer, credp->fc_mode & 07777) < 0) { 3054fa4ce71SChen Gang goto err; 3062d40564aSM. Mohan Kumar } 3074fa4ce71SChen Gang 3084fa4ce71SChen Gang g_free(buffer); 3094750a96fSVenkateswararao Jujjuri (JV) return 0; 3104fa4ce71SChen Gang err: 3114fa4ce71SChen Gang g_free(buffer); 3124fa4ce71SChen Gang return -1; 3134750a96fSVenkateswararao Jujjuri (JV) } 3144750a96fSVenkateswararao Jujjuri (JV) 3152289be19SAneesh Kumar K.V static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path, 316131dcb25SAnthony Liguori char *buf, size_t bufsz) 317131dcb25SAnthony Liguori { 318879c2813SVenkateswararao Jujjuri (JV) ssize_t tsize = -1; 3194fa4ce71SChen Gang char *buffer; 3202289be19SAneesh Kumar K.V char *path = fs_path->data; 3212289be19SAneesh Kumar K.V 3222c30dd74SAneesh Kumar K.V if ((fs_ctx->export_flags & V9FS_SM_MAPPED) || 3232c30dd74SAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) { 324879c2813SVenkateswararao Jujjuri (JV) int fd; 3254fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 3264fa4ce71SChen Gang fd = open(buffer, O_RDONLY | O_NOFOLLOW); 3274fa4ce71SChen Gang g_free(buffer); 328879c2813SVenkateswararao Jujjuri (JV) if (fd == -1) { 329879c2813SVenkateswararao Jujjuri (JV) return -1; 330879c2813SVenkateswararao Jujjuri (JV) } 331879c2813SVenkateswararao Jujjuri (JV) do { 332879c2813SVenkateswararao Jujjuri (JV) tsize = read(fd, (void *)buf, bufsz); 333879c2813SVenkateswararao Jujjuri (JV) } while (tsize == -1 && errno == EINTR); 334879c2813SVenkateswararao Jujjuri (JV) close(fd); 335b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 336b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 3374fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 3384fa4ce71SChen Gang tsize = readlink(buffer, buf, bufsz); 3394fa4ce71SChen Gang g_free(buffer); 340879c2813SVenkateswararao Jujjuri (JV) } 341879c2813SVenkateswararao Jujjuri (JV) return tsize; 342131dcb25SAnthony Liguori } 343131dcb25SAnthony Liguori 344cc720ddbSAneesh Kumar K.V static int local_close(FsContext *ctx, V9fsFidOpenState *fs) 345131dcb25SAnthony Liguori { 346cc720ddbSAneesh Kumar K.V return close(fs->fd); 347131dcb25SAnthony Liguori } 348131dcb25SAnthony Liguori 349cc720ddbSAneesh Kumar K.V static int local_closedir(FsContext *ctx, V9fsFidOpenState *fs) 350131dcb25SAnthony Liguori { 351f314ea4eSGreg Kurz return closedir(fs->dir.stream); 352131dcb25SAnthony Liguori } 3539f107513SAnthony Liguori 354cc720ddbSAneesh Kumar K.V static int local_open(FsContext *ctx, V9fsPath *fs_path, 355cc720ddbSAneesh Kumar K.V int flags, V9fsFidOpenState *fs) 356a6568fe2SAnthony Liguori { 3574fa4ce71SChen Gang char *buffer; 3582289be19SAneesh Kumar K.V char *path = fs_path->data; 3592289be19SAneesh Kumar K.V 3604fa4ce71SChen Gang buffer = rpath(ctx, path); 3614fa4ce71SChen Gang fs->fd = open(buffer, flags | O_NOFOLLOW); 3624fa4ce71SChen Gang g_free(buffer); 363cc720ddbSAneesh Kumar K.V return fs->fd; 364a6568fe2SAnthony Liguori } 365a6568fe2SAnthony Liguori 366cc720ddbSAneesh Kumar K.V static int local_opendir(FsContext *ctx, 367cc720ddbSAneesh Kumar K.V V9fsPath *fs_path, V9fsFidOpenState *fs) 368a6568fe2SAnthony Liguori { 3694fa4ce71SChen Gang char *buffer; 3702289be19SAneesh Kumar K.V char *path = fs_path->data; 3712289be19SAneesh Kumar K.V 3724fa4ce71SChen Gang buffer = rpath(ctx, path); 373f314ea4eSGreg Kurz fs->dir.stream = opendir(buffer); 3744fa4ce71SChen Gang g_free(buffer); 375f314ea4eSGreg Kurz if (!fs->dir.stream) { 376cc720ddbSAneesh Kumar K.V return -1; 377cc720ddbSAneesh Kumar K.V } 378cc720ddbSAneesh Kumar K.V return 0; 379a6568fe2SAnthony Liguori } 380a6568fe2SAnthony Liguori 381cc720ddbSAneesh Kumar K.V static void local_rewinddir(FsContext *ctx, V9fsFidOpenState *fs) 382a9231555SAnthony Liguori { 383f314ea4eSGreg Kurz rewinddir(fs->dir.stream); 384a9231555SAnthony Liguori } 385a9231555SAnthony Liguori 386cc720ddbSAneesh Kumar K.V static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs) 387a9231555SAnthony Liguori { 388f314ea4eSGreg Kurz return telldir(fs->dir.stream); 389a9231555SAnthony Liguori } 390a9231555SAnthony Liguori 391635324e8SGreg Kurz static struct dirent *local_readdir(FsContext *ctx, V9fsFidOpenState *fs) 392a9231555SAnthony Liguori { 393635324e8SGreg Kurz struct dirent *entry; 3942c30dd74SAneesh Kumar K.V 3952c30dd74SAneesh Kumar K.V again: 396635324e8SGreg Kurz entry = readdir(fs->dir.stream); 397635324e8SGreg Kurz if (!entry) { 398635324e8SGreg Kurz return NULL; 399635324e8SGreg Kurz } 400635324e8SGreg Kurz 401840a1bf2SBastian Blank if (ctx->export_flags & V9FS_SM_MAPPED) { 402840a1bf2SBastian Blank entry->d_type = DT_UNKNOWN; 403840a1bf2SBastian Blank } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 404635324e8SGreg Kurz if (!strcmp(entry->d_name, VIRTFS_META_DIR)) { 4052c30dd74SAneesh Kumar K.V /* skp the meta data directory */ 4062c30dd74SAneesh Kumar K.V goto again; 4072c30dd74SAneesh Kumar K.V } 408840a1bf2SBastian Blank entry->d_type = DT_UNKNOWN; 4092c30dd74SAneesh Kumar K.V } 410635324e8SGreg Kurz 411635324e8SGreg Kurz return entry; 412a9231555SAnthony Liguori } 413a9231555SAnthony Liguori 414cc720ddbSAneesh Kumar K.V static void local_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off) 415a9231555SAnthony Liguori { 416f314ea4eSGreg Kurz seekdir(fs->dir.stream, off); 417a9231555SAnthony Liguori } 418a9231555SAnthony Liguori 419cc720ddbSAneesh Kumar K.V static ssize_t local_preadv(FsContext *ctx, V9fsFidOpenState *fs, 420cc720ddbSAneesh Kumar K.V const struct iovec *iov, 42156d15a53SSanchit Garg int iovcnt, off_t offset) 422a9231555SAnthony Liguori { 42356d15a53SSanchit Garg #ifdef CONFIG_PREADV 424cc720ddbSAneesh Kumar K.V return preadv(fs->fd, iov, iovcnt, offset); 42556d15a53SSanchit Garg #else 426cc720ddbSAneesh Kumar K.V int err = lseek(fs->fd, offset, SEEK_SET); 42756d15a53SSanchit Garg if (err == -1) { 42856d15a53SSanchit Garg return err; 42956d15a53SSanchit Garg } else { 430cc720ddbSAneesh Kumar K.V return readv(fs->fd, iov, iovcnt); 431a9231555SAnthony Liguori } 43256d15a53SSanchit Garg #endif 433a9231555SAnthony Liguori } 434a9231555SAnthony Liguori 435cc720ddbSAneesh Kumar K.V static ssize_t local_pwritev(FsContext *ctx, V9fsFidOpenState *fs, 436cc720ddbSAneesh Kumar K.V const struct iovec *iov, 43756d15a53SSanchit Garg int iovcnt, off_t offset) 4388449360cSAnthony Liguori { 4396fe76accSGreg Kurz ssize_t ret; 44056d15a53SSanchit Garg #ifdef CONFIG_PREADV 441cc720ddbSAneesh Kumar K.V ret = pwritev(fs->fd, iov, iovcnt, offset); 44256d15a53SSanchit Garg #else 443cc720ddbSAneesh Kumar K.V int err = lseek(fs->fd, offset, SEEK_SET); 44456d15a53SSanchit Garg if (err == -1) { 44556d15a53SSanchit Garg return err; 44656d15a53SSanchit Garg } else { 447cc720ddbSAneesh Kumar K.V ret = writev(fs->fd, iov, iovcnt); 4488449360cSAnthony Liguori } 44956d15a53SSanchit Garg #endif 450d3ab98e6SAneesh Kumar K.V #ifdef CONFIG_SYNC_FILE_RANGE 451d3ab98e6SAneesh Kumar K.V if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) { 452d3ab98e6SAneesh Kumar K.V /* 453d3ab98e6SAneesh Kumar K.V * Initiate a writeback. This is not a data integrity sync. 454d3ab98e6SAneesh Kumar K.V * We want to ensure that we don't leave dirty pages in the cache 455d3ab98e6SAneesh Kumar K.V * after write when writeout=immediate is sepcified. 456d3ab98e6SAneesh Kumar K.V */ 457cc720ddbSAneesh Kumar K.V sync_file_range(fs->fd, offset, ret, 458d3ab98e6SAneesh Kumar K.V SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE); 459d3ab98e6SAneesh Kumar K.V } 460d3ab98e6SAneesh Kumar K.V #endif 461d3ab98e6SAneesh Kumar K.V return ret; 46256d15a53SSanchit Garg } 4638449360cSAnthony Liguori 4642289be19SAneesh Kumar K.V static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp) 465c494dd6fSAnthony Liguori { 4664fa4ce71SChen Gang char *buffer; 4674fa4ce71SChen Gang int ret = -1; 4682289be19SAneesh Kumar K.V char *path = fs_path->data; 4692289be19SAneesh Kumar K.V 470b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 4714fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 4724fa4ce71SChen Gang ret = local_set_xattr(buffer, credp); 4734fa4ce71SChen Gang g_free(buffer); 4742c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 4752c30dd74SAneesh Kumar K.V return local_set_mapped_file_attr(fs_ctx, path, credp); 476b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 477b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 4784fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 4794fa4ce71SChen Gang ret = chmod(buffer, credp->fc_mode); 4804fa4ce71SChen Gang g_free(buffer); 481e95ead32SVenkateswararao Jujjuri (JV) } 4824fa4ce71SChen Gang return ret; 483c494dd6fSAnthony Liguori } 484c494dd6fSAnthony Liguori 4852289be19SAneesh Kumar K.V static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path, 4862289be19SAneesh Kumar K.V const char *name, FsCred *credp) 487c494dd6fSAnthony Liguori { 4882289be19SAneesh Kumar K.V char *path; 4891c293312SVenkateswararao Jujjuri (JV) int err = -1; 4901c293312SVenkateswararao Jujjuri (JV) int serrno = 0; 4912289be19SAneesh Kumar K.V V9fsString fullname; 4924ed7b2c3SStefan Weil char *buffer = NULL; 4931c293312SVenkateswararao Jujjuri (JV) 4942289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 4952289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); 4962289be19SAneesh Kumar K.V path = fullname.data; 4972289be19SAneesh Kumar K.V 4981c293312SVenkateswararao Jujjuri (JV) /* Determine the security model */ 499b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 5004fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5014fa4ce71SChen Gang err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0); 5021c293312SVenkateswararao Jujjuri (JV) if (err == -1) { 5032289be19SAneesh Kumar K.V goto out; 5041c293312SVenkateswararao Jujjuri (JV) } 5054fa4ce71SChen Gang err = local_set_xattr(buffer, credp); 5061c293312SVenkateswararao Jujjuri (JV) if (err == -1) { 5071c293312SVenkateswararao Jujjuri (JV) serrno = errno; 5081c293312SVenkateswararao Jujjuri (JV) goto err_end; 5091c293312SVenkateswararao Jujjuri (JV) } 5102c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 5112c30dd74SAneesh Kumar K.V 5124fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5134fa4ce71SChen Gang err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0); 5142c30dd74SAneesh Kumar K.V if (err == -1) { 5152c30dd74SAneesh Kumar K.V goto out; 5162c30dd74SAneesh Kumar K.V } 5172c30dd74SAneesh Kumar K.V err = local_set_mapped_file_attr(fs_ctx, path, credp); 5182c30dd74SAneesh Kumar K.V if (err == -1) { 5192c30dd74SAneesh Kumar K.V serrno = errno; 5202c30dd74SAneesh Kumar K.V goto err_end; 5212c30dd74SAneesh Kumar K.V } 522b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 523b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 5244fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5254fa4ce71SChen Gang err = mknod(buffer, credp->fc_mode, credp->fc_rdev); 5261c293312SVenkateswararao Jujjuri (JV) if (err == -1) { 5272289be19SAneesh Kumar K.V goto out; 5281c293312SVenkateswararao Jujjuri (JV) } 5291c293312SVenkateswararao Jujjuri (JV) err = local_post_create_passthrough(fs_ctx, path, credp); 5301c293312SVenkateswararao Jujjuri (JV) if (err == -1) { 5311c293312SVenkateswararao Jujjuri (JV) serrno = errno; 5321c293312SVenkateswararao Jujjuri (JV) goto err_end; 5331c293312SVenkateswararao Jujjuri (JV) } 5341c293312SVenkateswararao Jujjuri (JV) } 5352289be19SAneesh Kumar K.V goto out; 5361c293312SVenkateswararao Jujjuri (JV) 5371c293312SVenkateswararao Jujjuri (JV) err_end: 5384fa4ce71SChen Gang remove(buffer); 5391c293312SVenkateswararao Jujjuri (JV) errno = serrno; 5402289be19SAneesh Kumar K.V out: 5414ed7b2c3SStefan Weil g_free(buffer); 5422289be19SAneesh Kumar K.V v9fs_string_free(&fullname); 5431c293312SVenkateswararao Jujjuri (JV) return err; 544c494dd6fSAnthony Liguori } 545c494dd6fSAnthony Liguori 5462289be19SAneesh Kumar K.V static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path, 5472289be19SAneesh Kumar K.V const char *name, FsCred *credp) 548c494dd6fSAnthony Liguori { 5492289be19SAneesh Kumar K.V char *path; 55000ec5c37SVenkateswararao Jujjuri (JV) int err = -1; 55100ec5c37SVenkateswararao Jujjuri (JV) int serrno = 0; 5522289be19SAneesh Kumar K.V V9fsString fullname; 5534ed7b2c3SStefan Weil char *buffer = NULL; 55400ec5c37SVenkateswararao Jujjuri (JV) 5552289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 5562289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); 5572289be19SAneesh Kumar K.V path = fullname.data; 5582289be19SAneesh Kumar K.V 55900ec5c37SVenkateswararao Jujjuri (JV) /* Determine the security model */ 560b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 5614fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5624fa4ce71SChen Gang err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS); 56300ec5c37SVenkateswararao Jujjuri (JV) if (err == -1) { 5642289be19SAneesh Kumar K.V goto out; 56500ec5c37SVenkateswararao Jujjuri (JV) } 56600ec5c37SVenkateswararao Jujjuri (JV) credp->fc_mode = credp->fc_mode|S_IFDIR; 5674fa4ce71SChen Gang err = local_set_xattr(buffer, credp); 56800ec5c37SVenkateswararao Jujjuri (JV) if (err == -1) { 56900ec5c37SVenkateswararao Jujjuri (JV) serrno = errno; 57000ec5c37SVenkateswararao Jujjuri (JV) goto err_end; 57100ec5c37SVenkateswararao Jujjuri (JV) } 5722c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 5734fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5744fa4ce71SChen Gang err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS); 5752c30dd74SAneesh Kumar K.V if (err == -1) { 5762c30dd74SAneesh Kumar K.V goto out; 5772c30dd74SAneesh Kumar K.V } 5782c30dd74SAneesh Kumar K.V credp->fc_mode = credp->fc_mode|S_IFDIR; 5792c30dd74SAneesh Kumar K.V err = local_set_mapped_file_attr(fs_ctx, path, credp); 5802c30dd74SAneesh Kumar K.V if (err == -1) { 5812c30dd74SAneesh Kumar K.V serrno = errno; 5822c30dd74SAneesh Kumar K.V goto err_end; 5832c30dd74SAneesh Kumar K.V } 584b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 585b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 5864fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5874fa4ce71SChen Gang err = mkdir(buffer, credp->fc_mode); 58800ec5c37SVenkateswararao Jujjuri (JV) if (err == -1) { 5892289be19SAneesh Kumar K.V goto out; 59000ec5c37SVenkateswararao Jujjuri (JV) } 59100ec5c37SVenkateswararao Jujjuri (JV) err = local_post_create_passthrough(fs_ctx, path, credp); 59200ec5c37SVenkateswararao Jujjuri (JV) if (err == -1) { 59300ec5c37SVenkateswararao Jujjuri (JV) serrno = errno; 59400ec5c37SVenkateswararao Jujjuri (JV) goto err_end; 59500ec5c37SVenkateswararao Jujjuri (JV) } 59600ec5c37SVenkateswararao Jujjuri (JV) } 5972289be19SAneesh Kumar K.V goto out; 59800ec5c37SVenkateswararao Jujjuri (JV) 59900ec5c37SVenkateswararao Jujjuri (JV) err_end: 6004fa4ce71SChen Gang remove(buffer); 60100ec5c37SVenkateswararao Jujjuri (JV) errno = serrno; 6022289be19SAneesh Kumar K.V out: 6034ed7b2c3SStefan Weil g_free(buffer); 6042289be19SAneesh Kumar K.V v9fs_string_free(&fullname); 60500ec5c37SVenkateswararao Jujjuri (JV) return err; 606c494dd6fSAnthony Liguori } 607c494dd6fSAnthony Liguori 6088b888272SAneesh Kumar K.V static int local_fstat(FsContext *fs_ctx, int fid_type, 609cc720ddbSAneesh Kumar K.V V9fsFidOpenState *fs, struct stat *stbuf) 610c494dd6fSAnthony Liguori { 6118b888272SAneesh Kumar K.V int err, fd; 6128b888272SAneesh Kumar K.V 6138b888272SAneesh Kumar K.V if (fid_type == P9_FID_DIR) { 614f314ea4eSGreg Kurz fd = dirfd(fs->dir.stream); 6158b888272SAneesh Kumar K.V } else { 6168b888272SAneesh Kumar K.V fd = fs->fd; 6178b888272SAneesh Kumar K.V } 6188b888272SAneesh Kumar K.V 6198b888272SAneesh Kumar K.V err = fstat(fd, stbuf); 6201237ad76SVenkateswararao Jujjuri (JV) if (err) { 6211237ad76SVenkateswararao Jujjuri (JV) return err; 6221237ad76SVenkateswararao Jujjuri (JV) } 623b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 6241237ad76SVenkateswararao Jujjuri (JV) /* Actual credentials are part of extended attrs */ 6251237ad76SVenkateswararao Jujjuri (JV) uid_t tmp_uid; 6261237ad76SVenkateswararao Jujjuri (JV) gid_t tmp_gid; 6271237ad76SVenkateswararao Jujjuri (JV) mode_t tmp_mode; 6281237ad76SVenkateswararao Jujjuri (JV) dev_t tmp_dev; 6291237ad76SVenkateswararao Jujjuri (JV) 630f8ad4a89SAneesh Kumar K.V if (fgetxattr(fd, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) { 631f8ad4a89SAneesh Kumar K.V stbuf->st_uid = le32_to_cpu(tmp_uid); 6321237ad76SVenkateswararao Jujjuri (JV) } 633f8ad4a89SAneesh Kumar K.V if (fgetxattr(fd, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) { 634f8ad4a89SAneesh Kumar K.V stbuf->st_gid = le32_to_cpu(tmp_gid); 6351237ad76SVenkateswararao Jujjuri (JV) } 636f8ad4a89SAneesh Kumar K.V if (fgetxattr(fd, "user.virtfs.mode", &tmp_mode, sizeof(mode_t)) > 0) { 637f8ad4a89SAneesh Kumar K.V stbuf->st_mode = le32_to_cpu(tmp_mode); 6381237ad76SVenkateswararao Jujjuri (JV) } 639f8ad4a89SAneesh Kumar K.V if (fgetxattr(fd, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) { 640f8ad4a89SAneesh Kumar K.V stbuf->st_rdev = le64_to_cpu(tmp_dev); 6411237ad76SVenkateswararao Jujjuri (JV) } 6422c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 6432c30dd74SAneesh Kumar K.V errno = EOPNOTSUPP; 6442c30dd74SAneesh Kumar K.V return -1; 6451237ad76SVenkateswararao Jujjuri (JV) } 6461237ad76SVenkateswararao Jujjuri (JV) return err; 647c494dd6fSAnthony Liguori } 648c494dd6fSAnthony Liguori 6492289be19SAneesh Kumar K.V static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, 650cc720ddbSAneesh Kumar K.V int flags, FsCred *credp, V9fsFidOpenState *fs) 651c494dd6fSAnthony Liguori { 6522289be19SAneesh Kumar K.V char *path; 6534750a96fSVenkateswararao Jujjuri (JV) int fd = -1; 6544750a96fSVenkateswararao Jujjuri (JV) int err = -1; 6554750a96fSVenkateswararao Jujjuri (JV) int serrno = 0; 6562289be19SAneesh Kumar K.V V9fsString fullname; 6574ed7b2c3SStefan Weil char *buffer = NULL; 6584750a96fSVenkateswararao Jujjuri (JV) 6590ceb092eSAneesh Kumar K.V /* 6600ceb092eSAneesh Kumar K.V * Mark all the open to not follow symlinks 6610ceb092eSAneesh Kumar K.V */ 6620ceb092eSAneesh Kumar K.V flags |= O_NOFOLLOW; 6630ceb092eSAneesh Kumar K.V 6642289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 6652289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); 6662289be19SAneesh Kumar K.V path = fullname.data; 6672289be19SAneesh Kumar K.V 6684750a96fSVenkateswararao Jujjuri (JV) /* Determine the security model */ 669b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 6704fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 6714fa4ce71SChen Gang fd = open(buffer, flags, SM_LOCAL_MODE_BITS); 6724750a96fSVenkateswararao Jujjuri (JV) if (fd == -1) { 6732289be19SAneesh Kumar K.V err = fd; 6742289be19SAneesh Kumar K.V goto out; 6754750a96fSVenkateswararao Jujjuri (JV) } 6764750a96fSVenkateswararao Jujjuri (JV) credp->fc_mode = credp->fc_mode|S_IFREG; 6774750a96fSVenkateswararao Jujjuri (JV) /* Set cleint credentials in xattr */ 6784fa4ce71SChen Gang err = local_set_xattr(buffer, credp); 6794750a96fSVenkateswararao Jujjuri (JV) if (err == -1) { 6804750a96fSVenkateswararao Jujjuri (JV) serrno = errno; 6814750a96fSVenkateswararao Jujjuri (JV) goto err_end; 6824750a96fSVenkateswararao Jujjuri (JV) } 6832c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 6844fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 6854fa4ce71SChen Gang fd = open(buffer, flags, SM_LOCAL_MODE_BITS); 6862c30dd74SAneesh Kumar K.V if (fd == -1) { 6872c30dd74SAneesh Kumar K.V err = fd; 6882c30dd74SAneesh Kumar K.V goto out; 6892c30dd74SAneesh Kumar K.V } 6902c30dd74SAneesh Kumar K.V credp->fc_mode = credp->fc_mode|S_IFREG; 6912c30dd74SAneesh Kumar K.V /* Set client credentials in .virtfs_metadata directory files */ 6922c30dd74SAneesh Kumar K.V err = local_set_mapped_file_attr(fs_ctx, path, credp); 6932c30dd74SAneesh Kumar K.V if (err == -1) { 6942c30dd74SAneesh Kumar K.V serrno = errno; 6952c30dd74SAneesh Kumar K.V goto err_end; 6962c30dd74SAneesh Kumar K.V } 697b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 698b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 6994fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 7004fa4ce71SChen Gang fd = open(buffer, flags, credp->fc_mode); 7014750a96fSVenkateswararao Jujjuri (JV) if (fd == -1) { 7022289be19SAneesh Kumar K.V err = fd; 7032289be19SAneesh Kumar K.V goto out; 7044750a96fSVenkateswararao Jujjuri (JV) } 7054750a96fSVenkateswararao Jujjuri (JV) err = local_post_create_passthrough(fs_ctx, path, credp); 7064750a96fSVenkateswararao Jujjuri (JV) if (err == -1) { 7074750a96fSVenkateswararao Jujjuri (JV) serrno = errno; 7084750a96fSVenkateswararao Jujjuri (JV) goto err_end; 7094750a96fSVenkateswararao Jujjuri (JV) } 7104750a96fSVenkateswararao Jujjuri (JV) } 7112289be19SAneesh Kumar K.V err = fd; 712cc720ddbSAneesh Kumar K.V fs->fd = fd; 7132289be19SAneesh Kumar K.V goto out; 7144750a96fSVenkateswararao Jujjuri (JV) 7154750a96fSVenkateswararao Jujjuri (JV) err_end: 7164750a96fSVenkateswararao Jujjuri (JV) close(fd); 7174fa4ce71SChen Gang remove(buffer); 7184750a96fSVenkateswararao Jujjuri (JV) errno = serrno; 7192289be19SAneesh Kumar K.V out: 7204ed7b2c3SStefan Weil g_free(buffer); 7212289be19SAneesh Kumar K.V v9fs_string_free(&fullname); 7224750a96fSVenkateswararao Jujjuri (JV) return err; 723c494dd6fSAnthony Liguori } 724c494dd6fSAnthony Liguori 725758e8e38SVenkateswararao Jujjuri (JV) 726879c2813SVenkateswararao Jujjuri (JV) static int local_symlink(FsContext *fs_ctx, const char *oldpath, 7272289be19SAneesh Kumar K.V V9fsPath *dir_path, const char *name, FsCred *credp) 728c494dd6fSAnthony Liguori { 729879c2813SVenkateswararao Jujjuri (JV) int err = -1; 730879c2813SVenkateswararao Jujjuri (JV) int serrno = 0; 7312289be19SAneesh Kumar K.V char *newpath; 7322289be19SAneesh Kumar K.V V9fsString fullname; 7334ed7b2c3SStefan Weil char *buffer = NULL; 734879c2813SVenkateswararao Jujjuri (JV) 7352289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 7362289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); 7372289be19SAneesh Kumar K.V newpath = fullname.data; 7382289be19SAneesh Kumar K.V 739879c2813SVenkateswararao Jujjuri (JV) /* Determine the security model */ 740b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 741879c2813SVenkateswararao Jujjuri (JV) int fd; 742879c2813SVenkateswararao Jujjuri (JV) ssize_t oldpath_size, write_size; 7434fa4ce71SChen Gang buffer = rpath(fs_ctx, newpath); 7444fa4ce71SChen Gang fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS); 745879c2813SVenkateswararao Jujjuri (JV) if (fd == -1) { 7462289be19SAneesh Kumar K.V err = fd; 7472289be19SAneesh Kumar K.V goto out; 748879c2813SVenkateswararao Jujjuri (JV) } 749879c2813SVenkateswararao Jujjuri (JV) /* Write the oldpath (target) to the file. */ 750f35bde2fSHarsh Prateek Bora oldpath_size = strlen(oldpath); 751879c2813SVenkateswararao Jujjuri (JV) do { 752879c2813SVenkateswararao Jujjuri (JV) write_size = write(fd, (void *)oldpath, oldpath_size); 753879c2813SVenkateswararao Jujjuri (JV) } while (write_size == -1 && errno == EINTR); 754879c2813SVenkateswararao Jujjuri (JV) 755879c2813SVenkateswararao Jujjuri (JV) if (write_size != oldpath_size) { 756879c2813SVenkateswararao Jujjuri (JV) serrno = errno; 757879c2813SVenkateswararao Jujjuri (JV) close(fd); 758879c2813SVenkateswararao Jujjuri (JV) err = -1; 759879c2813SVenkateswararao Jujjuri (JV) goto err_end; 760879c2813SVenkateswararao Jujjuri (JV) } 761879c2813SVenkateswararao Jujjuri (JV) close(fd); 762879c2813SVenkateswararao Jujjuri (JV) /* Set cleint credentials in symlink's xattr */ 763879c2813SVenkateswararao Jujjuri (JV) credp->fc_mode = credp->fc_mode|S_IFLNK; 7644fa4ce71SChen Gang err = local_set_xattr(buffer, credp); 765879c2813SVenkateswararao Jujjuri (JV) if (err == -1) { 766879c2813SVenkateswararao Jujjuri (JV) serrno = errno; 767879c2813SVenkateswararao Jujjuri (JV) goto err_end; 768879c2813SVenkateswararao Jujjuri (JV) } 7692c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 7702c30dd74SAneesh Kumar K.V int fd; 7712c30dd74SAneesh Kumar K.V ssize_t oldpath_size, write_size; 7724fa4ce71SChen Gang buffer = rpath(fs_ctx, newpath); 7734fa4ce71SChen Gang fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS); 7742c30dd74SAneesh Kumar K.V if (fd == -1) { 7752c30dd74SAneesh Kumar K.V err = fd; 7762c30dd74SAneesh Kumar K.V goto out; 7772c30dd74SAneesh Kumar K.V } 7782c30dd74SAneesh Kumar K.V /* Write the oldpath (target) to the file. */ 7792c30dd74SAneesh Kumar K.V oldpath_size = strlen(oldpath); 7802c30dd74SAneesh Kumar K.V do { 7812c30dd74SAneesh Kumar K.V write_size = write(fd, (void *)oldpath, oldpath_size); 7822c30dd74SAneesh Kumar K.V } while (write_size == -1 && errno == EINTR); 7832c30dd74SAneesh Kumar K.V 7842c30dd74SAneesh Kumar K.V if (write_size != oldpath_size) { 7852c30dd74SAneesh Kumar K.V serrno = errno; 7862c30dd74SAneesh Kumar K.V close(fd); 7872c30dd74SAneesh Kumar K.V err = -1; 7882c30dd74SAneesh Kumar K.V goto err_end; 7892c30dd74SAneesh Kumar K.V } 7902c30dd74SAneesh Kumar K.V close(fd); 7912c30dd74SAneesh Kumar K.V /* Set cleint credentials in symlink's xattr */ 7922c30dd74SAneesh Kumar K.V credp->fc_mode = credp->fc_mode|S_IFLNK; 7932c30dd74SAneesh Kumar K.V err = local_set_mapped_file_attr(fs_ctx, newpath, credp); 7942c30dd74SAneesh Kumar K.V if (err == -1) { 7952c30dd74SAneesh Kumar K.V serrno = errno; 7962c30dd74SAneesh Kumar K.V goto err_end; 7972c30dd74SAneesh Kumar K.V } 798b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 799b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 8004fa4ce71SChen Gang buffer = rpath(fs_ctx, newpath); 8014fa4ce71SChen Gang err = symlink(oldpath, buffer); 802879c2813SVenkateswararao Jujjuri (JV) if (err) { 8032289be19SAneesh Kumar K.V goto out; 804879c2813SVenkateswararao Jujjuri (JV) } 8054fa4ce71SChen Gang err = lchown(buffer, credp->fc_uid, credp->fc_gid); 806879c2813SVenkateswararao Jujjuri (JV) if (err == -1) { 80712848bfcSAneesh Kumar K.V /* 80812848bfcSAneesh Kumar K.V * If we fail to change ownership and if we are 80912848bfcSAneesh Kumar K.V * using security model none. Ignore the error 81012848bfcSAneesh Kumar K.V */ 811b97400caSAneesh Kumar K.V if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) { 812879c2813SVenkateswararao Jujjuri (JV) serrno = errno; 813879c2813SVenkateswararao Jujjuri (JV) goto err_end; 81412848bfcSAneesh Kumar K.V } else 81512848bfcSAneesh Kumar K.V err = 0; 816879c2813SVenkateswararao Jujjuri (JV) } 817879c2813SVenkateswararao Jujjuri (JV) } 8182289be19SAneesh Kumar K.V goto out; 819879c2813SVenkateswararao Jujjuri (JV) 820879c2813SVenkateswararao Jujjuri (JV) err_end: 8214fa4ce71SChen Gang remove(buffer); 822879c2813SVenkateswararao Jujjuri (JV) errno = serrno; 8232289be19SAneesh Kumar K.V out: 8244ed7b2c3SStefan Weil g_free(buffer); 8252289be19SAneesh Kumar K.V v9fs_string_free(&fullname); 826879c2813SVenkateswararao Jujjuri (JV) return err; 827c494dd6fSAnthony Liguori } 828c494dd6fSAnthony Liguori 8292289be19SAneesh Kumar K.V static int local_link(FsContext *ctx, V9fsPath *oldpath, 8302289be19SAneesh Kumar K.V V9fsPath *dirpath, const char *name) 831c494dd6fSAnthony Liguori { 8322289be19SAneesh Kumar K.V int ret; 8332289be19SAneesh Kumar K.V V9fsString newpath; 8344fa4ce71SChen Gang char *buffer, *buffer1; 835c494dd6fSAnthony Liguori 8362289be19SAneesh Kumar K.V v9fs_string_init(&newpath); 8372289be19SAneesh Kumar K.V v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name); 8382289be19SAneesh Kumar K.V 8394fa4ce71SChen Gang buffer = rpath(ctx, oldpath->data); 8404fa4ce71SChen Gang buffer1 = rpath(ctx, newpath.data); 8414fa4ce71SChen Gang ret = link(buffer, buffer1); 8424fa4ce71SChen Gang g_free(buffer); 8434fa4ce71SChen Gang g_free(buffer1); 8442c30dd74SAneesh Kumar K.V 8452c30dd74SAneesh Kumar K.V /* now link the virtfs_metadata files */ 8462c30dd74SAneesh Kumar K.V if (!ret && (ctx->export_flags & V9FS_SM_MAPPED_FILE)) { 8472c30dd74SAneesh Kumar K.V /* Link the .virtfs_metadata files. Create the metada directory */ 8482c30dd74SAneesh Kumar K.V ret = local_create_mapped_attr_dir(ctx, newpath.data); 8492c30dd74SAneesh Kumar K.V if (ret < 0) { 8502c30dd74SAneesh Kumar K.V goto err_out; 8512c30dd74SAneesh Kumar K.V } 8524fa4ce71SChen Gang buffer = local_mapped_attr_path(ctx, oldpath->data); 8534fa4ce71SChen Gang buffer1 = local_mapped_attr_path(ctx, newpath.data); 8544fa4ce71SChen Gang ret = link(buffer, buffer1); 8554fa4ce71SChen Gang g_free(buffer); 8564fa4ce71SChen Gang g_free(buffer1); 8572c30dd74SAneesh Kumar K.V if (ret < 0 && errno != ENOENT) { 8582c30dd74SAneesh Kumar K.V goto err_out; 8592c30dd74SAneesh Kumar K.V } 8602c30dd74SAneesh Kumar K.V } 8612c30dd74SAneesh Kumar K.V err_out: 8622289be19SAneesh Kumar K.V v9fs_string_free(&newpath); 8632289be19SAneesh Kumar K.V return ret; 864c494dd6fSAnthony Liguori } 865c494dd6fSAnthony Liguori 8662289be19SAneesh Kumar K.V static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size) 8678cf89e00SAnthony Liguori { 8684fa4ce71SChen Gang char *buffer; 8694fa4ce71SChen Gang int ret; 8702289be19SAneesh Kumar K.V char *path = fs_path->data; 8712289be19SAneesh Kumar K.V 8724fa4ce71SChen Gang buffer = rpath(ctx, path); 8734fa4ce71SChen Gang ret = truncate(buffer, size); 8744fa4ce71SChen Gang g_free(buffer); 8754fa4ce71SChen Gang return ret; 8768cf89e00SAnthony Liguori } 8778cf89e00SAnthony Liguori 8788cf89e00SAnthony Liguori static int local_rename(FsContext *ctx, const char *oldpath, 8798cf89e00SAnthony Liguori const char *newpath) 8808cf89e00SAnthony Liguori { 8812c30dd74SAneesh Kumar K.V int err; 8824fa4ce71SChen Gang char *buffer, *buffer1; 8838cf89e00SAnthony Liguori 8842c30dd74SAneesh Kumar K.V if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 8852c30dd74SAneesh Kumar K.V err = local_create_mapped_attr_dir(ctx, newpath); 8862c30dd74SAneesh Kumar K.V if (err < 0) { 8872c30dd74SAneesh Kumar K.V return err; 8882c30dd74SAneesh Kumar K.V } 8892c30dd74SAneesh Kumar K.V /* rename the .virtfs_metadata files */ 8904fa4ce71SChen Gang buffer = local_mapped_attr_path(ctx, oldpath); 8914fa4ce71SChen Gang buffer1 = local_mapped_attr_path(ctx, newpath); 8924fa4ce71SChen Gang err = rename(buffer, buffer1); 8934fa4ce71SChen Gang g_free(buffer); 8944fa4ce71SChen Gang g_free(buffer1); 8952c30dd74SAneesh Kumar K.V if (err < 0 && errno != ENOENT) { 8962c30dd74SAneesh Kumar K.V return err; 8972c30dd74SAneesh Kumar K.V } 8982c30dd74SAneesh Kumar K.V } 8994fa4ce71SChen Gang 9004fa4ce71SChen Gang buffer = rpath(ctx, oldpath); 9014fa4ce71SChen Gang buffer1 = rpath(ctx, newpath); 9024fa4ce71SChen Gang err = rename(buffer, buffer1); 9034fa4ce71SChen Gang g_free(buffer); 9044fa4ce71SChen Gang g_free(buffer1); 9054fa4ce71SChen Gang return err; 9068cf89e00SAnthony Liguori } 9078cf89e00SAnthony Liguori 9082289be19SAneesh Kumar K.V static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp) 9098cf89e00SAnthony Liguori { 9104fa4ce71SChen Gang char *buffer; 9114fa4ce71SChen Gang int ret = -1; 9122289be19SAneesh Kumar K.V char *path = fs_path->data; 9132289be19SAneesh Kumar K.V 914c79ce737SSripathi Kodi if ((credp->fc_uid == -1 && credp->fc_gid == -1) || 91517b1971fSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 91617b1971fSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 9174fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 9184fa4ce71SChen Gang ret = lchown(buffer, credp->fc_uid, credp->fc_gid); 9194fa4ce71SChen Gang g_free(buffer); 920b97400caSAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 9214fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 9224fa4ce71SChen Gang ret = local_set_xattr(buffer, credp); 9234fa4ce71SChen Gang g_free(buffer); 9242c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 9252c30dd74SAneesh Kumar K.V return local_set_mapped_file_attr(fs_ctx, path, credp); 926f7613beeSVenkateswararao Jujjuri (JV) } 9274fa4ce71SChen Gang return ret; 9288cf89e00SAnthony Liguori } 9298cf89e00SAnthony Liguori 9302289be19SAneesh Kumar K.V static int local_utimensat(FsContext *s, V9fsPath *fs_path, 93174bc02b2SM. Mohan Kumar const struct timespec *buf) 9328cf89e00SAnthony Liguori { 9334fa4ce71SChen Gang char *buffer; 9344fa4ce71SChen Gang int ret; 9352289be19SAneesh Kumar K.V char *path = fs_path->data; 9362289be19SAneesh Kumar K.V 9374fa4ce71SChen Gang buffer = rpath(s, path); 9384fa4ce71SChen Gang ret = qemu_utimens(buffer, buf); 9394fa4ce71SChen Gang g_free(buffer); 9404fa4ce71SChen Gang return ret; 9418cf89e00SAnthony Liguori } 9428cf89e00SAnthony Liguori 9435bae1900SAnthony Liguori static int local_remove(FsContext *ctx, const char *path) 9445bae1900SAnthony Liguori { 9452c30dd74SAneesh Kumar K.V int err; 9462c30dd74SAneesh Kumar K.V struct stat stbuf; 9474fa4ce71SChen Gang char *buffer; 9482c30dd74SAneesh Kumar K.V 9492c30dd74SAneesh Kumar K.V if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 9504fa4ce71SChen Gang buffer = rpath(ctx, path); 9514fa4ce71SChen Gang err = lstat(buffer, &stbuf); 9524fa4ce71SChen Gang g_free(buffer); 9532c30dd74SAneesh Kumar K.V if (err) { 9542c30dd74SAneesh Kumar K.V goto err_out; 9552c30dd74SAneesh Kumar K.V } 9562c30dd74SAneesh Kumar K.V /* 9572c30dd74SAneesh Kumar K.V * If directory remove .virtfs_metadata contained in the 9582c30dd74SAneesh Kumar K.V * directory 9592c30dd74SAneesh Kumar K.V */ 9602c30dd74SAneesh Kumar K.V if (S_ISDIR(stbuf.st_mode)) { 9614fa4ce71SChen Gang buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, 9624fa4ce71SChen Gang path, VIRTFS_META_DIR); 9632c30dd74SAneesh Kumar K.V err = remove(buffer); 9644fa4ce71SChen Gang g_free(buffer); 9652c30dd74SAneesh Kumar K.V if (err < 0 && errno != ENOENT) { 9662c30dd74SAneesh Kumar K.V /* 9672c30dd74SAneesh Kumar K.V * We didn't had the .virtfs_metadata file. May be file created 9682c30dd74SAneesh Kumar K.V * in non-mapped mode ?. Ignore ENOENT. 9692c30dd74SAneesh Kumar K.V */ 9702c30dd74SAneesh Kumar K.V goto err_out; 9712c30dd74SAneesh Kumar K.V } 9722c30dd74SAneesh Kumar K.V } 9732c30dd74SAneesh Kumar K.V /* 9742c30dd74SAneesh Kumar K.V * Now remove the name from parent directory 9752c30dd74SAneesh Kumar K.V * .virtfs_metadata directory 9762c30dd74SAneesh Kumar K.V */ 9774fa4ce71SChen Gang buffer = local_mapped_attr_path(ctx, path); 9784fa4ce71SChen Gang err = remove(buffer); 9794fa4ce71SChen Gang g_free(buffer); 9802c30dd74SAneesh Kumar K.V if (err < 0 && errno != ENOENT) { 9812c30dd74SAneesh Kumar K.V /* 9822c30dd74SAneesh Kumar K.V * We didn't had the .virtfs_metadata file. May be file created 9832c30dd74SAneesh Kumar K.V * in non-mapped mode ?. Ignore ENOENT. 9842c30dd74SAneesh Kumar K.V */ 9852c30dd74SAneesh Kumar K.V goto err_out; 9862c30dd74SAneesh Kumar K.V } 9872c30dd74SAneesh Kumar K.V } 9884fa4ce71SChen Gang 9894fa4ce71SChen Gang buffer = rpath(ctx, path); 9904fa4ce71SChen Gang err = remove(buffer); 9914fa4ce71SChen Gang g_free(buffer); 9922c30dd74SAneesh Kumar K.V err_out: 9932c30dd74SAneesh Kumar K.V return err; 9945bae1900SAnthony Liguori } 9955bae1900SAnthony Liguori 9968b888272SAneesh Kumar K.V static int local_fsync(FsContext *ctx, int fid_type, 9978b888272SAneesh Kumar K.V V9fsFidOpenState *fs, int datasync) 9988cf89e00SAnthony Liguori { 9998b888272SAneesh Kumar K.V int fd; 10008b888272SAneesh Kumar K.V 10018b888272SAneesh Kumar K.V if (fid_type == P9_FID_DIR) { 1002f314ea4eSGreg Kurz fd = dirfd(fs->dir.stream); 100349594973SVenkateswararao Jujjuri (JV) } else { 10048b888272SAneesh Kumar K.V fd = fs->fd; 10058b888272SAneesh Kumar K.V } 10068b888272SAneesh Kumar K.V 10078b888272SAneesh Kumar K.V if (datasync) { 10088b888272SAneesh Kumar K.V return qemu_fdatasync(fd); 10098b888272SAneesh Kumar K.V } else { 10108b888272SAneesh Kumar K.V return fsync(fd); 10118cf89e00SAnthony Liguori } 101249594973SVenkateswararao Jujjuri (JV) } 10138cf89e00SAnthony Liguori 10142289be19SAneesh Kumar K.V static int local_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf) 1015be940c87SM. Mohan Kumar { 10164fa4ce71SChen Gang char *buffer; 10174fa4ce71SChen Gang int ret; 10182289be19SAneesh Kumar K.V char *path = fs_path->data; 10192289be19SAneesh Kumar K.V 10204fa4ce71SChen Gang buffer = rpath(s, path); 10214fa4ce71SChen Gang ret = statfs(buffer, stbuf); 10224fa4ce71SChen Gang g_free(buffer); 10234fa4ce71SChen Gang return ret; 1024be940c87SM. Mohan Kumar } 1025be940c87SM. Mohan Kumar 10262289be19SAneesh Kumar K.V static ssize_t local_lgetxattr(FsContext *ctx, V9fsPath *fs_path, 1027fa32ef88SAneesh Kumar K.V const char *name, void *value, size_t size) 1028fa32ef88SAneesh Kumar K.V { 10292289be19SAneesh Kumar K.V char *path = fs_path->data; 10302289be19SAneesh Kumar K.V 1031fc22118dSAneesh Kumar K.V return v9fs_get_xattr(ctx, path, name, value, size); 1032fa32ef88SAneesh Kumar K.V } 1033fa32ef88SAneesh Kumar K.V 10342289be19SAneesh Kumar K.V static ssize_t local_llistxattr(FsContext *ctx, V9fsPath *fs_path, 1035fa32ef88SAneesh Kumar K.V void *value, size_t size) 1036fa32ef88SAneesh Kumar K.V { 10372289be19SAneesh Kumar K.V char *path = fs_path->data; 10382289be19SAneesh Kumar K.V 1039fc22118dSAneesh Kumar K.V return v9fs_list_xattr(ctx, path, value, size); 104061b6c499SAneesh Kumar K.V } 104161b6c499SAneesh Kumar K.V 10422289be19SAneesh Kumar K.V static int local_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name, 104310b468bdSAneesh Kumar K.V void *value, size_t size, int flags) 104410b468bdSAneesh Kumar K.V { 10452289be19SAneesh Kumar K.V char *path = fs_path->data; 10462289be19SAneesh Kumar K.V 1047fc22118dSAneesh Kumar K.V return v9fs_set_xattr(ctx, path, name, value, size, flags); 104810b468bdSAneesh Kumar K.V } 104910b468bdSAneesh Kumar K.V 10502289be19SAneesh Kumar K.V static int local_lremovexattr(FsContext *ctx, V9fsPath *fs_path, 10512289be19SAneesh Kumar K.V const char *name) 10529ed3ef26SAneesh Kumar K.V { 10532289be19SAneesh Kumar K.V char *path = fs_path->data; 10542289be19SAneesh Kumar K.V 1055fc22118dSAneesh Kumar K.V return v9fs_remove_xattr(ctx, path, name); 10569ed3ef26SAneesh Kumar K.V } 10579ed3ef26SAneesh Kumar K.V 10582289be19SAneesh Kumar K.V static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path, 10592289be19SAneesh Kumar K.V const char *name, V9fsPath *target) 10602289be19SAneesh Kumar K.V { 10612289be19SAneesh Kumar K.V if (dir_path) { 1062e3e83f2eSGreg Kurz v9fs_path_sprintf(target, "%s/%s", dir_path->data, name); 10632289be19SAneesh Kumar K.V } else { 1064e3e83f2eSGreg Kurz v9fs_path_sprintf(target, "%s", name); 10652289be19SAneesh Kumar K.V } 10662289be19SAneesh Kumar K.V return 0; 10672289be19SAneesh Kumar K.V } 10682289be19SAneesh Kumar K.V 10692289be19SAneesh Kumar K.V static int local_renameat(FsContext *ctx, V9fsPath *olddir, 10702289be19SAneesh Kumar K.V const char *old_name, V9fsPath *newdir, 10712289be19SAneesh Kumar K.V const char *new_name) 10722289be19SAneesh Kumar K.V { 10732289be19SAneesh Kumar K.V int ret; 10742289be19SAneesh Kumar K.V V9fsString old_full_name, new_full_name; 10752289be19SAneesh Kumar K.V 10762289be19SAneesh Kumar K.V v9fs_string_init(&old_full_name); 10772289be19SAneesh Kumar K.V v9fs_string_init(&new_full_name); 10782289be19SAneesh Kumar K.V 10792289be19SAneesh Kumar K.V v9fs_string_sprintf(&old_full_name, "%s/%s", olddir->data, old_name); 10802289be19SAneesh Kumar K.V v9fs_string_sprintf(&new_full_name, "%s/%s", newdir->data, new_name); 10812289be19SAneesh Kumar K.V 10822289be19SAneesh Kumar K.V ret = local_rename(ctx, old_full_name.data, new_full_name.data); 10832289be19SAneesh Kumar K.V v9fs_string_free(&old_full_name); 10842289be19SAneesh Kumar K.V v9fs_string_free(&new_full_name); 10852289be19SAneesh Kumar K.V return ret; 10862289be19SAneesh Kumar K.V } 10872289be19SAneesh Kumar K.V 10882289be19SAneesh Kumar K.V static int local_unlinkat(FsContext *ctx, V9fsPath *dir, 10892289be19SAneesh Kumar K.V const char *name, int flags) 10902289be19SAneesh Kumar K.V { 10912289be19SAneesh Kumar K.V int ret; 10922289be19SAneesh Kumar K.V V9fsString fullname; 10934fa4ce71SChen Gang char *buffer; 10942c30dd74SAneesh Kumar K.V 10952289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 10962289be19SAneesh Kumar K.V 10972289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name); 10982c30dd74SAneesh Kumar K.V if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 10992c30dd74SAneesh Kumar K.V if (flags == AT_REMOVEDIR) { 11002c30dd74SAneesh Kumar K.V /* 11012c30dd74SAneesh Kumar K.V * If directory remove .virtfs_metadata contained in the 11022c30dd74SAneesh Kumar K.V * directory 11032c30dd74SAneesh Kumar K.V */ 11044fa4ce71SChen Gang buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, 11052c30dd74SAneesh Kumar K.V fullname.data, VIRTFS_META_DIR); 11062c30dd74SAneesh Kumar K.V ret = remove(buffer); 11074fa4ce71SChen Gang g_free(buffer); 11082c30dd74SAneesh Kumar K.V if (ret < 0 && errno != ENOENT) { 11092c30dd74SAneesh Kumar K.V /* 11102c30dd74SAneesh Kumar K.V * We didn't had the .virtfs_metadata file. May be file created 11112c30dd74SAneesh Kumar K.V * in non-mapped mode ?. Ignore ENOENT. 11122c30dd74SAneesh Kumar K.V */ 11132c30dd74SAneesh Kumar K.V goto err_out; 11142c30dd74SAneesh Kumar K.V } 11152c30dd74SAneesh Kumar K.V } 11162c30dd74SAneesh Kumar K.V /* 11172c30dd74SAneesh Kumar K.V * Now remove the name from parent directory 11182c30dd74SAneesh Kumar K.V * .virtfs_metadata directory. 11192c30dd74SAneesh Kumar K.V */ 11204fa4ce71SChen Gang buffer = local_mapped_attr_path(ctx, fullname.data); 11214fa4ce71SChen Gang ret = remove(buffer); 11224fa4ce71SChen Gang g_free(buffer); 11232c30dd74SAneesh Kumar K.V if (ret < 0 && errno != ENOENT) { 11242c30dd74SAneesh Kumar K.V /* 11252c30dd74SAneesh Kumar K.V * We didn't had the .virtfs_metadata file. May be file created 11262c30dd74SAneesh Kumar K.V * in non-mapped mode ?. Ignore ENOENT. 11272c30dd74SAneesh Kumar K.V */ 11282c30dd74SAneesh Kumar K.V goto err_out; 11292c30dd74SAneesh Kumar K.V } 11302c30dd74SAneesh Kumar K.V } 11312c30dd74SAneesh Kumar K.V /* Remove the name finally */ 11324fa4ce71SChen Gang buffer = rpath(ctx, fullname.data); 11334fa4ce71SChen Gang ret = remove(buffer); 11344fa4ce71SChen Gang g_free(buffer); 11352289be19SAneesh Kumar K.V 11362c30dd74SAneesh Kumar K.V err_out: 113775b7931eSChen Gang v9fs_string_free(&fullname); 11382289be19SAneesh Kumar K.V return ret; 11392289be19SAneesh Kumar K.V } 11409ed3ef26SAneesh Kumar K.V 1141e06a765eSHarsh Prateek Bora static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, 1142e06a765eSHarsh Prateek Bora mode_t st_mode, uint64_t *st_gen) 1143e06a765eSHarsh Prateek Bora { 1144ae0f940eSPaolo Bonzini #ifdef FS_IOC_GETVERSION 11450e5fc994SKirill A. Shutemov int err; 1146cc720ddbSAneesh Kumar K.V V9fsFidOpenState fid_open; 1147cc720ddbSAneesh Kumar K.V 1148e06a765eSHarsh Prateek Bora /* 1149e06a765eSHarsh Prateek Bora * Do not try to open special files like device nodes, fifos etc 1150e06a765eSHarsh Prateek Bora * We can get fd for regular files and directories only 1151e06a765eSHarsh Prateek Bora */ 1152e06a765eSHarsh Prateek Bora if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) { 11531a9978a5SKirill A. Shutemov errno = ENOTTY; 11541a9978a5SKirill A. Shutemov return -1; 1155e06a765eSHarsh Prateek Bora } 1156cc720ddbSAneesh Kumar K.V err = local_open(ctx, path, O_RDONLY, &fid_open); 1157cc720ddbSAneesh Kumar K.V if (err < 0) { 1158cc720ddbSAneesh Kumar K.V return err; 1159e06a765eSHarsh Prateek Bora } 1160cc720ddbSAneesh Kumar K.V err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen); 1161cc720ddbSAneesh Kumar K.V local_close(ctx, &fid_open); 1162e06a765eSHarsh Prateek Bora return err; 11630e5fc994SKirill A. Shutemov #else 11640e5fc994SKirill A. Shutemov errno = ENOTTY; 11650e5fc994SKirill A. Shutemov return -1; 11660e5fc994SKirill A. Shutemov #endif 1167e06a765eSHarsh Prateek Bora } 1168e06a765eSHarsh Prateek Bora 11690174fe73SAneesh Kumar K.V static int local_init(FsContext *ctx) 11700174fe73SAneesh Kumar K.V { 11712507718bSAneesh Kumar K.V int err = 0; 1172e06a765eSHarsh Prateek Bora struct statfs stbuf; 1173e06a765eSHarsh Prateek Bora 11742c30dd74SAneesh Kumar K.V if (ctx->export_flags & V9FS_SM_PASSTHROUGH) { 11752c30dd74SAneesh Kumar K.V ctx->xops = passthrough_xattr_ops; 11762c30dd74SAneesh Kumar K.V } else if (ctx->export_flags & V9FS_SM_MAPPED) { 11772c30dd74SAneesh Kumar K.V ctx->xops = mapped_xattr_ops; 11782c30dd74SAneesh Kumar K.V } else if (ctx->export_flags & V9FS_SM_NONE) { 11792c30dd74SAneesh Kumar K.V ctx->xops = none_xattr_ops; 11802c30dd74SAneesh Kumar K.V } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 11812c30dd74SAneesh Kumar K.V /* 11822c30dd74SAneesh Kumar K.V * xattr operation for mapped-file and passthrough 11832c30dd74SAneesh Kumar K.V * remain same. 11842c30dd74SAneesh Kumar K.V */ 11852c30dd74SAneesh Kumar K.V ctx->xops = passthrough_xattr_ops; 11862c30dd74SAneesh Kumar K.V } 1187c98f1d4aSAneesh Kumar K.V ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT; 11882507718bSAneesh Kumar K.V #ifdef FS_IOC_GETVERSION 11892507718bSAneesh Kumar K.V /* 11902507718bSAneesh Kumar K.V * use ioc_getversion only if the iocl is definied 11912507718bSAneesh Kumar K.V */ 1192e06a765eSHarsh Prateek Bora err = statfs(ctx->fs_root, &stbuf); 1193e06a765eSHarsh Prateek Bora if (!err) { 1194e06a765eSHarsh Prateek Bora switch (stbuf.f_type) { 1195e06a765eSHarsh Prateek Bora case EXT2_SUPER_MAGIC: 1196e06a765eSHarsh Prateek Bora case BTRFS_SUPER_MAGIC: 1197e06a765eSHarsh Prateek Bora case REISERFS_SUPER_MAGIC: 1198e06a765eSHarsh Prateek Bora case XFS_SUPER_MAGIC: 1199e06a765eSHarsh Prateek Bora ctx->exops.get_st_gen = local_ioc_getversion; 1200e06a765eSHarsh Prateek Bora break; 1201e06a765eSHarsh Prateek Bora } 1202e06a765eSHarsh Prateek Bora } 12032507718bSAneesh Kumar K.V #endif 1204e06a765eSHarsh Prateek Bora return err; 12050174fe73SAneesh Kumar K.V } 12060174fe73SAneesh Kumar K.V 120799519f0aSAneesh Kumar K.V static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse) 120899519f0aSAneesh Kumar K.V { 120999519f0aSAneesh Kumar K.V const char *sec_model = qemu_opt_get(opts, "security_model"); 121099519f0aSAneesh Kumar K.V const char *path = qemu_opt_get(opts, "path"); 1211*b8bbdb88SPradeep Jagadeesh Error *err = NULL; 121299519f0aSAneesh Kumar K.V 121399519f0aSAneesh Kumar K.V if (!sec_model) { 121463325b18SGreg Kurz error_report("Security model not specified, local fs needs security model"); 121563325b18SGreg Kurz error_printf("valid options are:" 121663325b18SGreg Kurz "\tsecurity_model=[passthrough|mapped-xattr|mapped-file|none]\n"); 121799519f0aSAneesh Kumar K.V return -1; 121899519f0aSAneesh Kumar K.V } 121999519f0aSAneesh Kumar K.V 122099519f0aSAneesh Kumar K.V if (!strcmp(sec_model, "passthrough")) { 122199519f0aSAneesh Kumar K.V fse->export_flags |= V9FS_SM_PASSTHROUGH; 12222c30dd74SAneesh Kumar K.V } else if (!strcmp(sec_model, "mapped") || 12232c30dd74SAneesh Kumar K.V !strcmp(sec_model, "mapped-xattr")) { 122499519f0aSAneesh Kumar K.V fse->export_flags |= V9FS_SM_MAPPED; 122599519f0aSAneesh Kumar K.V } else if (!strcmp(sec_model, "none")) { 122699519f0aSAneesh Kumar K.V fse->export_flags |= V9FS_SM_NONE; 12272c30dd74SAneesh Kumar K.V } else if (!strcmp(sec_model, "mapped-file")) { 12282c30dd74SAneesh Kumar K.V fse->export_flags |= V9FS_SM_MAPPED_FILE; 122999519f0aSAneesh Kumar K.V } else { 123063325b18SGreg Kurz error_report("Invalid security model %s specified", sec_model); 123163325b18SGreg Kurz error_printf("valid options are:" 123263325b18SGreg Kurz "\t[passthrough|mapped-xattr|mapped-file|none]\n"); 123399519f0aSAneesh Kumar K.V return -1; 123499519f0aSAneesh Kumar K.V } 123599519f0aSAneesh Kumar K.V 123699519f0aSAneesh Kumar K.V if (!path) { 123763325b18SGreg Kurz error_report("fsdev: No path specified"); 123899519f0aSAneesh Kumar K.V return -1; 123999519f0aSAneesh Kumar K.V } 1240*b8bbdb88SPradeep Jagadeesh 1241*b8bbdb88SPradeep Jagadeesh fsdev_throttle_parse_opts(opts, &fse->fst, &err); 1242*b8bbdb88SPradeep Jagadeesh if (err) { 1243*b8bbdb88SPradeep Jagadeesh error_reportf_err(err, "Throttle configuration is not valid: "); 1244*b8bbdb88SPradeep Jagadeesh return -1; 1245*b8bbdb88SPradeep Jagadeesh } 1246*b8bbdb88SPradeep Jagadeesh 124799519f0aSAneesh Kumar K.V fse->path = g_strdup(path); 124899519f0aSAneesh Kumar K.V 124999519f0aSAneesh Kumar K.V return 0; 125099519f0aSAneesh Kumar K.V } 125199519f0aSAneesh Kumar K.V 12529f107513SAnthony Liguori FileOperations local_ops = { 125399519f0aSAneesh Kumar K.V .parse_opts = local_parse_opts, 12540174fe73SAneesh Kumar K.V .init = local_init, 1255131dcb25SAnthony Liguori .lstat = local_lstat, 1256131dcb25SAnthony Liguori .readlink = local_readlink, 1257131dcb25SAnthony Liguori .close = local_close, 1258131dcb25SAnthony Liguori .closedir = local_closedir, 1259a6568fe2SAnthony Liguori .open = local_open, 1260a6568fe2SAnthony Liguori .opendir = local_opendir, 1261a9231555SAnthony Liguori .rewinddir = local_rewinddir, 1262a9231555SAnthony Liguori .telldir = local_telldir, 1263635324e8SGreg Kurz .readdir = local_readdir, 1264a9231555SAnthony Liguori .seekdir = local_seekdir, 126556d15a53SSanchit Garg .preadv = local_preadv, 126656d15a53SSanchit Garg .pwritev = local_pwritev, 1267c494dd6fSAnthony Liguori .chmod = local_chmod, 1268c494dd6fSAnthony Liguori .mknod = local_mknod, 1269c494dd6fSAnthony Liguori .mkdir = local_mkdir, 1270c494dd6fSAnthony Liguori .fstat = local_fstat, 1271c494dd6fSAnthony Liguori .open2 = local_open2, 1272c494dd6fSAnthony Liguori .symlink = local_symlink, 1273c494dd6fSAnthony Liguori .link = local_link, 12748cf89e00SAnthony Liguori .truncate = local_truncate, 12758cf89e00SAnthony Liguori .rename = local_rename, 12768cf89e00SAnthony Liguori .chown = local_chown, 127774bc02b2SM. Mohan Kumar .utimensat = local_utimensat, 12785bae1900SAnthony Liguori .remove = local_remove, 12798cf89e00SAnthony Liguori .fsync = local_fsync, 1280be940c87SM. Mohan Kumar .statfs = local_statfs, 1281fa32ef88SAneesh Kumar K.V .lgetxattr = local_lgetxattr, 1282fa32ef88SAneesh Kumar K.V .llistxattr = local_llistxattr, 128310b468bdSAneesh Kumar K.V .lsetxattr = local_lsetxattr, 12849ed3ef26SAneesh Kumar K.V .lremovexattr = local_lremovexattr, 12852289be19SAneesh Kumar K.V .name_to_path = local_name_to_path, 12862289be19SAneesh Kumar K.V .renameat = local_renameat, 12872289be19SAneesh Kumar K.V .unlinkat = local_unlinkat, 12889f107513SAnthony Liguori }; 1289