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 { 439d3ab98e6SAneesh Kumar K.V ssize_t ret 440d3ab98e6SAneesh Kumar K.V ; 44156d15a53SSanchit Garg #ifdef CONFIG_PREADV 442cc720ddbSAneesh Kumar K.V ret = pwritev(fs->fd, iov, iovcnt, offset); 44356d15a53SSanchit Garg #else 444cc720ddbSAneesh Kumar K.V int err = lseek(fs->fd, offset, SEEK_SET); 44556d15a53SSanchit Garg if (err == -1) { 44656d15a53SSanchit Garg return err; 44756d15a53SSanchit Garg } else { 448cc720ddbSAneesh Kumar K.V ret = writev(fs->fd, iov, iovcnt); 4498449360cSAnthony Liguori } 45056d15a53SSanchit Garg #endif 451d3ab98e6SAneesh Kumar K.V #ifdef CONFIG_SYNC_FILE_RANGE 452d3ab98e6SAneesh Kumar K.V if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) { 453d3ab98e6SAneesh Kumar K.V /* 454d3ab98e6SAneesh Kumar K.V * Initiate a writeback. This is not a data integrity sync. 455d3ab98e6SAneesh Kumar K.V * We want to ensure that we don't leave dirty pages in the cache 456d3ab98e6SAneesh Kumar K.V * after write when writeout=immediate is sepcified. 457d3ab98e6SAneesh Kumar K.V */ 458cc720ddbSAneesh Kumar K.V sync_file_range(fs->fd, offset, ret, 459d3ab98e6SAneesh Kumar K.V SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE); 460d3ab98e6SAneesh Kumar K.V } 461d3ab98e6SAneesh Kumar K.V #endif 462d3ab98e6SAneesh Kumar K.V return ret; 46356d15a53SSanchit Garg } 4648449360cSAnthony Liguori 4652289be19SAneesh Kumar K.V static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp) 466c494dd6fSAnthony Liguori { 4674fa4ce71SChen Gang char *buffer; 4684fa4ce71SChen Gang int ret = -1; 4692289be19SAneesh Kumar K.V char *path = fs_path->data; 4702289be19SAneesh Kumar K.V 471b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 4724fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 4734fa4ce71SChen Gang ret = local_set_xattr(buffer, credp); 4744fa4ce71SChen Gang g_free(buffer); 4752c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 4762c30dd74SAneesh Kumar K.V return local_set_mapped_file_attr(fs_ctx, path, credp); 477b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 478b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 4794fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 4804fa4ce71SChen Gang ret = chmod(buffer, credp->fc_mode); 4814fa4ce71SChen Gang g_free(buffer); 482e95ead32SVenkateswararao Jujjuri (JV) } 4834fa4ce71SChen Gang return ret; 484c494dd6fSAnthony Liguori } 485c494dd6fSAnthony Liguori 4862289be19SAneesh Kumar K.V static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path, 4872289be19SAneesh Kumar K.V const char *name, FsCred *credp) 488c494dd6fSAnthony Liguori { 4892289be19SAneesh Kumar K.V char *path; 4901c293312SVenkateswararao Jujjuri (JV) int err = -1; 4911c293312SVenkateswararao Jujjuri (JV) int serrno = 0; 4922289be19SAneesh Kumar K.V V9fsString fullname; 4934ed7b2c3SStefan Weil char *buffer = NULL; 4941c293312SVenkateswararao Jujjuri (JV) 4952289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 4962289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); 4972289be19SAneesh Kumar K.V path = fullname.data; 4982289be19SAneesh Kumar K.V 4991c293312SVenkateswararao Jujjuri (JV) /* Determine the security model */ 500b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 5014fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5024fa4ce71SChen Gang err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0); 5031c293312SVenkateswararao Jujjuri (JV) if (err == -1) { 5042289be19SAneesh Kumar K.V goto out; 5051c293312SVenkateswararao Jujjuri (JV) } 5064fa4ce71SChen Gang err = local_set_xattr(buffer, credp); 5071c293312SVenkateswararao Jujjuri (JV) if (err == -1) { 5081c293312SVenkateswararao Jujjuri (JV) serrno = errno; 5091c293312SVenkateswararao Jujjuri (JV) goto err_end; 5101c293312SVenkateswararao Jujjuri (JV) } 5112c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 5122c30dd74SAneesh Kumar K.V 5134fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5144fa4ce71SChen Gang err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0); 5152c30dd74SAneesh Kumar K.V if (err == -1) { 5162c30dd74SAneesh Kumar K.V goto out; 5172c30dd74SAneesh Kumar K.V } 5182c30dd74SAneesh Kumar K.V err = local_set_mapped_file_attr(fs_ctx, path, credp); 5192c30dd74SAneesh Kumar K.V if (err == -1) { 5202c30dd74SAneesh Kumar K.V serrno = errno; 5212c30dd74SAneesh Kumar K.V goto err_end; 5222c30dd74SAneesh Kumar K.V } 523b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 524b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 5254fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5264fa4ce71SChen Gang err = mknod(buffer, credp->fc_mode, credp->fc_rdev); 5271c293312SVenkateswararao Jujjuri (JV) if (err == -1) { 5282289be19SAneesh Kumar K.V goto out; 5291c293312SVenkateswararao Jujjuri (JV) } 5301c293312SVenkateswararao Jujjuri (JV) err = local_post_create_passthrough(fs_ctx, path, credp); 5311c293312SVenkateswararao Jujjuri (JV) if (err == -1) { 5321c293312SVenkateswararao Jujjuri (JV) serrno = errno; 5331c293312SVenkateswararao Jujjuri (JV) goto err_end; 5341c293312SVenkateswararao Jujjuri (JV) } 5351c293312SVenkateswararao Jujjuri (JV) } 5362289be19SAneesh Kumar K.V goto out; 5371c293312SVenkateswararao Jujjuri (JV) 5381c293312SVenkateswararao Jujjuri (JV) err_end: 5394fa4ce71SChen Gang remove(buffer); 5401c293312SVenkateswararao Jujjuri (JV) errno = serrno; 5412289be19SAneesh Kumar K.V out: 5424ed7b2c3SStefan Weil g_free(buffer); 5432289be19SAneesh Kumar K.V v9fs_string_free(&fullname); 5441c293312SVenkateswararao Jujjuri (JV) return err; 545c494dd6fSAnthony Liguori } 546c494dd6fSAnthony Liguori 5472289be19SAneesh Kumar K.V static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path, 5482289be19SAneesh Kumar K.V const char *name, FsCred *credp) 549c494dd6fSAnthony Liguori { 5502289be19SAneesh Kumar K.V char *path; 55100ec5c37SVenkateswararao Jujjuri (JV) int err = -1; 55200ec5c37SVenkateswararao Jujjuri (JV) int serrno = 0; 5532289be19SAneesh Kumar K.V V9fsString fullname; 5544ed7b2c3SStefan Weil char *buffer = NULL; 55500ec5c37SVenkateswararao Jujjuri (JV) 5562289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 5572289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); 5582289be19SAneesh Kumar K.V path = fullname.data; 5592289be19SAneesh Kumar K.V 56000ec5c37SVenkateswararao Jujjuri (JV) /* Determine the security model */ 561b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 5624fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5634fa4ce71SChen Gang err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS); 56400ec5c37SVenkateswararao Jujjuri (JV) if (err == -1) { 5652289be19SAneesh Kumar K.V goto out; 56600ec5c37SVenkateswararao Jujjuri (JV) } 56700ec5c37SVenkateswararao Jujjuri (JV) credp->fc_mode = credp->fc_mode|S_IFDIR; 5684fa4ce71SChen Gang err = local_set_xattr(buffer, credp); 56900ec5c37SVenkateswararao Jujjuri (JV) if (err == -1) { 57000ec5c37SVenkateswararao Jujjuri (JV) serrno = errno; 57100ec5c37SVenkateswararao Jujjuri (JV) goto err_end; 57200ec5c37SVenkateswararao Jujjuri (JV) } 5732c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 5744fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5754fa4ce71SChen Gang err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS); 5762c30dd74SAneesh Kumar K.V if (err == -1) { 5772c30dd74SAneesh Kumar K.V goto out; 5782c30dd74SAneesh Kumar K.V } 5792c30dd74SAneesh Kumar K.V credp->fc_mode = credp->fc_mode|S_IFDIR; 5802c30dd74SAneesh Kumar K.V err = local_set_mapped_file_attr(fs_ctx, path, credp); 5812c30dd74SAneesh Kumar K.V if (err == -1) { 5822c30dd74SAneesh Kumar K.V serrno = errno; 5832c30dd74SAneesh Kumar K.V goto err_end; 5842c30dd74SAneesh Kumar K.V } 585b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 586b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 5874fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5884fa4ce71SChen Gang err = mkdir(buffer, credp->fc_mode); 58900ec5c37SVenkateswararao Jujjuri (JV) if (err == -1) { 5902289be19SAneesh Kumar K.V goto out; 59100ec5c37SVenkateswararao Jujjuri (JV) } 59200ec5c37SVenkateswararao Jujjuri (JV) err = local_post_create_passthrough(fs_ctx, path, credp); 59300ec5c37SVenkateswararao Jujjuri (JV) if (err == -1) { 59400ec5c37SVenkateswararao Jujjuri (JV) serrno = errno; 59500ec5c37SVenkateswararao Jujjuri (JV) goto err_end; 59600ec5c37SVenkateswararao Jujjuri (JV) } 59700ec5c37SVenkateswararao Jujjuri (JV) } 5982289be19SAneesh Kumar K.V goto out; 59900ec5c37SVenkateswararao Jujjuri (JV) 60000ec5c37SVenkateswararao Jujjuri (JV) err_end: 6014fa4ce71SChen Gang remove(buffer); 60200ec5c37SVenkateswararao Jujjuri (JV) errno = serrno; 6032289be19SAneesh Kumar K.V out: 6044ed7b2c3SStefan Weil g_free(buffer); 6052289be19SAneesh Kumar K.V v9fs_string_free(&fullname); 60600ec5c37SVenkateswararao Jujjuri (JV) return err; 607c494dd6fSAnthony Liguori } 608c494dd6fSAnthony Liguori 6098b888272SAneesh Kumar K.V static int local_fstat(FsContext *fs_ctx, int fid_type, 610cc720ddbSAneesh Kumar K.V V9fsFidOpenState *fs, struct stat *stbuf) 611c494dd6fSAnthony Liguori { 6128b888272SAneesh Kumar K.V int err, fd; 6138b888272SAneesh Kumar K.V 6148b888272SAneesh Kumar K.V if (fid_type == P9_FID_DIR) { 615f314ea4eSGreg Kurz fd = dirfd(fs->dir.stream); 6168b888272SAneesh Kumar K.V } else { 6178b888272SAneesh Kumar K.V fd = fs->fd; 6188b888272SAneesh Kumar K.V } 6198b888272SAneesh Kumar K.V 6208b888272SAneesh Kumar K.V err = fstat(fd, stbuf); 6211237ad76SVenkateswararao Jujjuri (JV) if (err) { 6221237ad76SVenkateswararao Jujjuri (JV) return err; 6231237ad76SVenkateswararao Jujjuri (JV) } 624b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 6251237ad76SVenkateswararao Jujjuri (JV) /* Actual credentials are part of extended attrs */ 6261237ad76SVenkateswararao Jujjuri (JV) uid_t tmp_uid; 6271237ad76SVenkateswararao Jujjuri (JV) gid_t tmp_gid; 6281237ad76SVenkateswararao Jujjuri (JV) mode_t tmp_mode; 6291237ad76SVenkateswararao Jujjuri (JV) dev_t tmp_dev; 6301237ad76SVenkateswararao Jujjuri (JV) 631f8ad4a89SAneesh Kumar K.V if (fgetxattr(fd, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) { 632f8ad4a89SAneesh Kumar K.V stbuf->st_uid = le32_to_cpu(tmp_uid); 6331237ad76SVenkateswararao Jujjuri (JV) } 634f8ad4a89SAneesh Kumar K.V if (fgetxattr(fd, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) { 635f8ad4a89SAneesh Kumar K.V stbuf->st_gid = le32_to_cpu(tmp_gid); 6361237ad76SVenkateswararao Jujjuri (JV) } 637f8ad4a89SAneesh Kumar K.V if (fgetxattr(fd, "user.virtfs.mode", &tmp_mode, sizeof(mode_t)) > 0) { 638f8ad4a89SAneesh Kumar K.V stbuf->st_mode = le32_to_cpu(tmp_mode); 6391237ad76SVenkateswararao Jujjuri (JV) } 640f8ad4a89SAneesh Kumar K.V if (fgetxattr(fd, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) { 641f8ad4a89SAneesh Kumar K.V stbuf->st_rdev = le64_to_cpu(tmp_dev); 6421237ad76SVenkateswararao Jujjuri (JV) } 6432c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 6442c30dd74SAneesh Kumar K.V errno = EOPNOTSUPP; 6452c30dd74SAneesh Kumar K.V return -1; 6461237ad76SVenkateswararao Jujjuri (JV) } 6471237ad76SVenkateswararao Jujjuri (JV) return err; 648c494dd6fSAnthony Liguori } 649c494dd6fSAnthony Liguori 6502289be19SAneesh Kumar K.V static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, 651cc720ddbSAneesh Kumar K.V int flags, FsCred *credp, V9fsFidOpenState *fs) 652c494dd6fSAnthony Liguori { 6532289be19SAneesh Kumar K.V char *path; 6544750a96fSVenkateswararao Jujjuri (JV) int fd = -1; 6554750a96fSVenkateswararao Jujjuri (JV) int err = -1; 6564750a96fSVenkateswararao Jujjuri (JV) int serrno = 0; 6572289be19SAneesh Kumar K.V V9fsString fullname; 6584ed7b2c3SStefan Weil char *buffer = NULL; 6594750a96fSVenkateswararao Jujjuri (JV) 6600ceb092eSAneesh Kumar K.V /* 6610ceb092eSAneesh Kumar K.V * Mark all the open to not follow symlinks 6620ceb092eSAneesh Kumar K.V */ 6630ceb092eSAneesh Kumar K.V flags |= O_NOFOLLOW; 6640ceb092eSAneesh Kumar K.V 6652289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 6662289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); 6672289be19SAneesh Kumar K.V path = fullname.data; 6682289be19SAneesh Kumar K.V 6694750a96fSVenkateswararao Jujjuri (JV) /* Determine the security model */ 670b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 6714fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 6724fa4ce71SChen Gang fd = open(buffer, flags, SM_LOCAL_MODE_BITS); 6734750a96fSVenkateswararao Jujjuri (JV) if (fd == -1) { 6742289be19SAneesh Kumar K.V err = fd; 6752289be19SAneesh Kumar K.V goto out; 6764750a96fSVenkateswararao Jujjuri (JV) } 6774750a96fSVenkateswararao Jujjuri (JV) credp->fc_mode = credp->fc_mode|S_IFREG; 6784750a96fSVenkateswararao Jujjuri (JV) /* Set cleint credentials in xattr */ 6794fa4ce71SChen Gang err = local_set_xattr(buffer, credp); 6804750a96fSVenkateswararao Jujjuri (JV) if (err == -1) { 6814750a96fSVenkateswararao Jujjuri (JV) serrno = errno; 6824750a96fSVenkateswararao Jujjuri (JV) goto err_end; 6834750a96fSVenkateswararao Jujjuri (JV) } 6842c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 6854fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 6864fa4ce71SChen Gang fd = open(buffer, flags, SM_LOCAL_MODE_BITS); 6872c30dd74SAneesh Kumar K.V if (fd == -1) { 6882c30dd74SAneesh Kumar K.V err = fd; 6892c30dd74SAneesh Kumar K.V goto out; 6902c30dd74SAneesh Kumar K.V } 6912c30dd74SAneesh Kumar K.V credp->fc_mode = credp->fc_mode|S_IFREG; 6922c30dd74SAneesh Kumar K.V /* Set client credentials in .virtfs_metadata directory files */ 6932c30dd74SAneesh Kumar K.V err = local_set_mapped_file_attr(fs_ctx, path, credp); 6942c30dd74SAneesh Kumar K.V if (err == -1) { 6952c30dd74SAneesh Kumar K.V serrno = errno; 6962c30dd74SAneesh Kumar K.V goto err_end; 6972c30dd74SAneesh Kumar K.V } 698b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 699b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 7004fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 7014fa4ce71SChen Gang fd = open(buffer, flags, credp->fc_mode); 7024750a96fSVenkateswararao Jujjuri (JV) if (fd == -1) { 7032289be19SAneesh Kumar K.V err = fd; 7042289be19SAneesh Kumar K.V goto out; 7054750a96fSVenkateswararao Jujjuri (JV) } 7064750a96fSVenkateswararao Jujjuri (JV) err = local_post_create_passthrough(fs_ctx, path, credp); 7074750a96fSVenkateswararao Jujjuri (JV) if (err == -1) { 7084750a96fSVenkateswararao Jujjuri (JV) serrno = errno; 7094750a96fSVenkateswararao Jujjuri (JV) goto err_end; 7104750a96fSVenkateswararao Jujjuri (JV) } 7114750a96fSVenkateswararao Jujjuri (JV) } 7122289be19SAneesh Kumar K.V err = fd; 713cc720ddbSAneesh Kumar K.V fs->fd = fd; 7142289be19SAneesh Kumar K.V goto out; 7154750a96fSVenkateswararao Jujjuri (JV) 7164750a96fSVenkateswararao Jujjuri (JV) err_end: 7174750a96fSVenkateswararao Jujjuri (JV) close(fd); 7184fa4ce71SChen Gang remove(buffer); 7194750a96fSVenkateswararao Jujjuri (JV) errno = serrno; 7202289be19SAneesh Kumar K.V out: 7214ed7b2c3SStefan Weil g_free(buffer); 7222289be19SAneesh Kumar K.V v9fs_string_free(&fullname); 7234750a96fSVenkateswararao Jujjuri (JV) return err; 724c494dd6fSAnthony Liguori } 725c494dd6fSAnthony Liguori 726758e8e38SVenkateswararao Jujjuri (JV) 727879c2813SVenkateswararao Jujjuri (JV) static int local_symlink(FsContext *fs_ctx, const char *oldpath, 7282289be19SAneesh Kumar K.V V9fsPath *dir_path, const char *name, FsCred *credp) 729c494dd6fSAnthony Liguori { 730879c2813SVenkateswararao Jujjuri (JV) int err = -1; 731879c2813SVenkateswararao Jujjuri (JV) int serrno = 0; 7322289be19SAneesh Kumar K.V char *newpath; 7332289be19SAneesh Kumar K.V V9fsString fullname; 7344ed7b2c3SStefan Weil char *buffer = NULL; 735879c2813SVenkateswararao Jujjuri (JV) 7362289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 7372289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); 7382289be19SAneesh Kumar K.V newpath = fullname.data; 7392289be19SAneesh Kumar K.V 740879c2813SVenkateswararao Jujjuri (JV) /* Determine the security model */ 741b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 742879c2813SVenkateswararao Jujjuri (JV) int fd; 743879c2813SVenkateswararao Jujjuri (JV) ssize_t oldpath_size, write_size; 7444fa4ce71SChen Gang buffer = rpath(fs_ctx, newpath); 7454fa4ce71SChen Gang fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS); 746879c2813SVenkateswararao Jujjuri (JV) if (fd == -1) { 7472289be19SAneesh Kumar K.V err = fd; 7482289be19SAneesh Kumar K.V goto out; 749879c2813SVenkateswararao Jujjuri (JV) } 750879c2813SVenkateswararao Jujjuri (JV) /* Write the oldpath (target) to the file. */ 751f35bde2fSHarsh Prateek Bora oldpath_size = strlen(oldpath); 752879c2813SVenkateswararao Jujjuri (JV) do { 753879c2813SVenkateswararao Jujjuri (JV) write_size = write(fd, (void *)oldpath, oldpath_size); 754879c2813SVenkateswararao Jujjuri (JV) } while (write_size == -1 && errno == EINTR); 755879c2813SVenkateswararao Jujjuri (JV) 756879c2813SVenkateswararao Jujjuri (JV) if (write_size != oldpath_size) { 757879c2813SVenkateswararao Jujjuri (JV) serrno = errno; 758879c2813SVenkateswararao Jujjuri (JV) close(fd); 759879c2813SVenkateswararao Jujjuri (JV) err = -1; 760879c2813SVenkateswararao Jujjuri (JV) goto err_end; 761879c2813SVenkateswararao Jujjuri (JV) } 762879c2813SVenkateswararao Jujjuri (JV) close(fd); 763879c2813SVenkateswararao Jujjuri (JV) /* Set cleint credentials in symlink's xattr */ 764879c2813SVenkateswararao Jujjuri (JV) credp->fc_mode = credp->fc_mode|S_IFLNK; 7654fa4ce71SChen Gang err = local_set_xattr(buffer, credp); 766879c2813SVenkateswararao Jujjuri (JV) if (err == -1) { 767879c2813SVenkateswararao Jujjuri (JV) serrno = errno; 768879c2813SVenkateswararao Jujjuri (JV) goto err_end; 769879c2813SVenkateswararao Jujjuri (JV) } 7702c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 7712c30dd74SAneesh Kumar K.V int fd; 7722c30dd74SAneesh Kumar K.V ssize_t oldpath_size, write_size; 7734fa4ce71SChen Gang buffer = rpath(fs_ctx, newpath); 7744fa4ce71SChen Gang fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS); 7752c30dd74SAneesh Kumar K.V if (fd == -1) { 7762c30dd74SAneesh Kumar K.V err = fd; 7772c30dd74SAneesh Kumar K.V goto out; 7782c30dd74SAneesh Kumar K.V } 7792c30dd74SAneesh Kumar K.V /* Write the oldpath (target) to the file. */ 7802c30dd74SAneesh Kumar K.V oldpath_size = strlen(oldpath); 7812c30dd74SAneesh Kumar K.V do { 7822c30dd74SAneesh Kumar K.V write_size = write(fd, (void *)oldpath, oldpath_size); 7832c30dd74SAneesh Kumar K.V } while (write_size == -1 && errno == EINTR); 7842c30dd74SAneesh Kumar K.V 7852c30dd74SAneesh Kumar K.V if (write_size != oldpath_size) { 7862c30dd74SAneesh Kumar K.V serrno = errno; 7872c30dd74SAneesh Kumar K.V close(fd); 7882c30dd74SAneesh Kumar K.V err = -1; 7892c30dd74SAneesh Kumar K.V goto err_end; 7902c30dd74SAneesh Kumar K.V } 7912c30dd74SAneesh Kumar K.V close(fd); 7922c30dd74SAneesh Kumar K.V /* Set cleint credentials in symlink's xattr */ 7932c30dd74SAneesh Kumar K.V credp->fc_mode = credp->fc_mode|S_IFLNK; 7942c30dd74SAneesh Kumar K.V err = local_set_mapped_file_attr(fs_ctx, newpath, credp); 7952c30dd74SAneesh Kumar K.V if (err == -1) { 7962c30dd74SAneesh Kumar K.V serrno = errno; 7972c30dd74SAneesh Kumar K.V goto err_end; 7982c30dd74SAneesh Kumar K.V } 799b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 800b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 8014fa4ce71SChen Gang buffer = rpath(fs_ctx, newpath); 8024fa4ce71SChen Gang err = symlink(oldpath, buffer); 803879c2813SVenkateswararao Jujjuri (JV) if (err) { 8042289be19SAneesh Kumar K.V goto out; 805879c2813SVenkateswararao Jujjuri (JV) } 8064fa4ce71SChen Gang err = lchown(buffer, credp->fc_uid, credp->fc_gid); 807879c2813SVenkateswararao Jujjuri (JV) if (err == -1) { 80812848bfcSAneesh Kumar K.V /* 80912848bfcSAneesh Kumar K.V * If we fail to change ownership and if we are 81012848bfcSAneesh Kumar K.V * using security model none. Ignore the error 81112848bfcSAneesh Kumar K.V */ 812b97400caSAneesh Kumar K.V if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) { 813879c2813SVenkateswararao Jujjuri (JV) serrno = errno; 814879c2813SVenkateswararao Jujjuri (JV) goto err_end; 81512848bfcSAneesh Kumar K.V } else 81612848bfcSAneesh Kumar K.V err = 0; 817879c2813SVenkateswararao Jujjuri (JV) } 818879c2813SVenkateswararao Jujjuri (JV) } 8192289be19SAneesh Kumar K.V goto out; 820879c2813SVenkateswararao Jujjuri (JV) 821879c2813SVenkateswararao Jujjuri (JV) err_end: 8224fa4ce71SChen Gang remove(buffer); 823879c2813SVenkateswararao Jujjuri (JV) errno = serrno; 8242289be19SAneesh Kumar K.V out: 8254ed7b2c3SStefan Weil g_free(buffer); 8262289be19SAneesh Kumar K.V v9fs_string_free(&fullname); 827879c2813SVenkateswararao Jujjuri (JV) return err; 828c494dd6fSAnthony Liguori } 829c494dd6fSAnthony Liguori 8302289be19SAneesh Kumar K.V static int local_link(FsContext *ctx, V9fsPath *oldpath, 8312289be19SAneesh Kumar K.V V9fsPath *dirpath, const char *name) 832c494dd6fSAnthony Liguori { 8332289be19SAneesh Kumar K.V int ret; 8342289be19SAneesh Kumar K.V V9fsString newpath; 8354fa4ce71SChen Gang char *buffer, *buffer1; 836c494dd6fSAnthony Liguori 8372289be19SAneesh Kumar K.V v9fs_string_init(&newpath); 8382289be19SAneesh Kumar K.V v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name); 8392289be19SAneesh Kumar K.V 8404fa4ce71SChen Gang buffer = rpath(ctx, oldpath->data); 8414fa4ce71SChen Gang buffer1 = rpath(ctx, newpath.data); 8424fa4ce71SChen Gang ret = link(buffer, buffer1); 8434fa4ce71SChen Gang g_free(buffer); 8444fa4ce71SChen Gang g_free(buffer1); 8452c30dd74SAneesh Kumar K.V 8462c30dd74SAneesh Kumar K.V /* now link the virtfs_metadata files */ 8472c30dd74SAneesh Kumar K.V if (!ret && (ctx->export_flags & V9FS_SM_MAPPED_FILE)) { 8482c30dd74SAneesh Kumar K.V /* Link the .virtfs_metadata files. Create the metada directory */ 8492c30dd74SAneesh Kumar K.V ret = local_create_mapped_attr_dir(ctx, newpath.data); 8502c30dd74SAneesh Kumar K.V if (ret < 0) { 8512c30dd74SAneesh Kumar K.V goto err_out; 8522c30dd74SAneesh Kumar K.V } 8534fa4ce71SChen Gang buffer = local_mapped_attr_path(ctx, oldpath->data); 8544fa4ce71SChen Gang buffer1 = local_mapped_attr_path(ctx, newpath.data); 8554fa4ce71SChen Gang ret = link(buffer, buffer1); 8564fa4ce71SChen Gang g_free(buffer); 8574fa4ce71SChen Gang g_free(buffer1); 8582c30dd74SAneesh Kumar K.V if (ret < 0 && errno != ENOENT) { 8592c30dd74SAneesh Kumar K.V goto err_out; 8602c30dd74SAneesh Kumar K.V } 8612c30dd74SAneesh Kumar K.V } 8622c30dd74SAneesh Kumar K.V err_out: 8632289be19SAneesh Kumar K.V v9fs_string_free(&newpath); 8642289be19SAneesh Kumar K.V return ret; 865c494dd6fSAnthony Liguori } 866c494dd6fSAnthony Liguori 8672289be19SAneesh Kumar K.V static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size) 8688cf89e00SAnthony Liguori { 8694fa4ce71SChen Gang char *buffer; 8704fa4ce71SChen Gang int ret; 8712289be19SAneesh Kumar K.V char *path = fs_path->data; 8722289be19SAneesh Kumar K.V 8734fa4ce71SChen Gang buffer = rpath(ctx, path); 8744fa4ce71SChen Gang ret = truncate(buffer, size); 8754fa4ce71SChen Gang g_free(buffer); 8764fa4ce71SChen Gang return ret; 8778cf89e00SAnthony Liguori } 8788cf89e00SAnthony Liguori 8798cf89e00SAnthony Liguori static int local_rename(FsContext *ctx, const char *oldpath, 8808cf89e00SAnthony Liguori const char *newpath) 8818cf89e00SAnthony Liguori { 8822c30dd74SAneesh Kumar K.V int err; 8834fa4ce71SChen Gang char *buffer, *buffer1; 8848cf89e00SAnthony Liguori 8852c30dd74SAneesh Kumar K.V if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 8862c30dd74SAneesh Kumar K.V err = local_create_mapped_attr_dir(ctx, newpath); 8872c30dd74SAneesh Kumar K.V if (err < 0) { 8882c30dd74SAneesh Kumar K.V return err; 8892c30dd74SAneesh Kumar K.V } 8902c30dd74SAneesh Kumar K.V /* rename the .virtfs_metadata files */ 8914fa4ce71SChen Gang buffer = local_mapped_attr_path(ctx, oldpath); 8924fa4ce71SChen Gang buffer1 = local_mapped_attr_path(ctx, newpath); 8934fa4ce71SChen Gang err = rename(buffer, buffer1); 8944fa4ce71SChen Gang g_free(buffer); 8954fa4ce71SChen Gang g_free(buffer1); 8962c30dd74SAneesh Kumar K.V if (err < 0 && errno != ENOENT) { 8972c30dd74SAneesh Kumar K.V return err; 8982c30dd74SAneesh Kumar K.V } 8992c30dd74SAneesh Kumar K.V } 9004fa4ce71SChen Gang 9014fa4ce71SChen Gang buffer = rpath(ctx, oldpath); 9024fa4ce71SChen Gang buffer1 = rpath(ctx, newpath); 9034fa4ce71SChen Gang err = rename(buffer, buffer1); 9044fa4ce71SChen Gang g_free(buffer); 9054fa4ce71SChen Gang g_free(buffer1); 9064fa4ce71SChen Gang return err; 9078cf89e00SAnthony Liguori } 9088cf89e00SAnthony Liguori 9092289be19SAneesh Kumar K.V static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp) 9108cf89e00SAnthony Liguori { 9114fa4ce71SChen Gang char *buffer; 9124fa4ce71SChen Gang int ret = -1; 9132289be19SAneesh Kumar K.V char *path = fs_path->data; 9142289be19SAneesh Kumar K.V 915c79ce737SSripathi Kodi if ((credp->fc_uid == -1 && credp->fc_gid == -1) || 91617b1971fSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 91717b1971fSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 9184fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 9194fa4ce71SChen Gang ret = lchown(buffer, credp->fc_uid, credp->fc_gid); 9204fa4ce71SChen Gang g_free(buffer); 921b97400caSAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 9224fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 9234fa4ce71SChen Gang ret = local_set_xattr(buffer, credp); 9244fa4ce71SChen Gang g_free(buffer); 9252c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 9262c30dd74SAneesh Kumar K.V return local_set_mapped_file_attr(fs_ctx, path, credp); 927f7613beeSVenkateswararao Jujjuri (JV) } 9284fa4ce71SChen Gang return ret; 9298cf89e00SAnthony Liguori } 9308cf89e00SAnthony Liguori 9312289be19SAneesh Kumar K.V static int local_utimensat(FsContext *s, V9fsPath *fs_path, 93274bc02b2SM. Mohan Kumar const struct timespec *buf) 9338cf89e00SAnthony Liguori { 9344fa4ce71SChen Gang char *buffer; 9354fa4ce71SChen Gang int ret; 9362289be19SAneesh Kumar K.V char *path = fs_path->data; 9372289be19SAneesh Kumar K.V 9384fa4ce71SChen Gang buffer = rpath(s, path); 9394fa4ce71SChen Gang ret = qemu_utimens(buffer, buf); 9404fa4ce71SChen Gang g_free(buffer); 9414fa4ce71SChen Gang return ret; 9428cf89e00SAnthony Liguori } 9438cf89e00SAnthony Liguori 9445bae1900SAnthony Liguori static int local_remove(FsContext *ctx, const char *path) 9455bae1900SAnthony Liguori { 9462c30dd74SAneesh Kumar K.V int err; 9472c30dd74SAneesh Kumar K.V struct stat stbuf; 9484fa4ce71SChen Gang char *buffer; 9492c30dd74SAneesh Kumar K.V 9502c30dd74SAneesh Kumar K.V if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 9514fa4ce71SChen Gang buffer = rpath(ctx, path); 9524fa4ce71SChen Gang err = lstat(buffer, &stbuf); 9534fa4ce71SChen Gang g_free(buffer); 9542c30dd74SAneesh Kumar K.V if (err) { 9552c30dd74SAneesh Kumar K.V goto err_out; 9562c30dd74SAneesh Kumar K.V } 9572c30dd74SAneesh Kumar K.V /* 9582c30dd74SAneesh Kumar K.V * If directory remove .virtfs_metadata contained in the 9592c30dd74SAneesh Kumar K.V * directory 9602c30dd74SAneesh Kumar K.V */ 9612c30dd74SAneesh Kumar K.V if (S_ISDIR(stbuf.st_mode)) { 9624fa4ce71SChen Gang buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, 9634fa4ce71SChen Gang path, VIRTFS_META_DIR); 9642c30dd74SAneesh Kumar K.V err = remove(buffer); 9654fa4ce71SChen Gang g_free(buffer); 9662c30dd74SAneesh Kumar K.V if (err < 0 && errno != ENOENT) { 9672c30dd74SAneesh Kumar K.V /* 9682c30dd74SAneesh Kumar K.V * We didn't had the .virtfs_metadata file. May be file created 9692c30dd74SAneesh Kumar K.V * in non-mapped mode ?. Ignore ENOENT. 9702c30dd74SAneesh Kumar K.V */ 9712c30dd74SAneesh Kumar K.V goto err_out; 9722c30dd74SAneesh Kumar K.V } 9732c30dd74SAneesh Kumar K.V } 9742c30dd74SAneesh Kumar K.V /* 9752c30dd74SAneesh Kumar K.V * Now remove the name from parent directory 9762c30dd74SAneesh Kumar K.V * .virtfs_metadata directory 9772c30dd74SAneesh Kumar K.V */ 9784fa4ce71SChen Gang buffer = local_mapped_attr_path(ctx, path); 9794fa4ce71SChen Gang err = remove(buffer); 9804fa4ce71SChen Gang g_free(buffer); 9812c30dd74SAneesh Kumar K.V if (err < 0 && errno != ENOENT) { 9822c30dd74SAneesh Kumar K.V /* 9832c30dd74SAneesh Kumar K.V * We didn't had the .virtfs_metadata file. May be file created 9842c30dd74SAneesh Kumar K.V * in non-mapped mode ?. Ignore ENOENT. 9852c30dd74SAneesh Kumar K.V */ 9862c30dd74SAneesh Kumar K.V goto err_out; 9872c30dd74SAneesh Kumar K.V } 9882c30dd74SAneesh Kumar K.V } 9894fa4ce71SChen Gang 9904fa4ce71SChen Gang buffer = rpath(ctx, path); 9914fa4ce71SChen Gang err = remove(buffer); 9924fa4ce71SChen Gang g_free(buffer); 9932c30dd74SAneesh Kumar K.V err_out: 9942c30dd74SAneesh Kumar K.V return err; 9955bae1900SAnthony Liguori } 9965bae1900SAnthony Liguori 9978b888272SAneesh Kumar K.V static int local_fsync(FsContext *ctx, int fid_type, 9988b888272SAneesh Kumar K.V V9fsFidOpenState *fs, int datasync) 9998cf89e00SAnthony Liguori { 10008b888272SAneesh Kumar K.V int fd; 10018b888272SAneesh Kumar K.V 10028b888272SAneesh Kumar K.V if (fid_type == P9_FID_DIR) { 1003f314ea4eSGreg Kurz fd = dirfd(fs->dir.stream); 100449594973SVenkateswararao Jujjuri (JV) } else { 10058b888272SAneesh Kumar K.V fd = fs->fd; 10068b888272SAneesh Kumar K.V } 10078b888272SAneesh Kumar K.V 10088b888272SAneesh Kumar K.V if (datasync) { 10098b888272SAneesh Kumar K.V return qemu_fdatasync(fd); 10108b888272SAneesh Kumar K.V } else { 10118b888272SAneesh Kumar K.V return fsync(fd); 10128cf89e00SAnthony Liguori } 101349594973SVenkateswararao Jujjuri (JV) } 10148cf89e00SAnthony Liguori 10152289be19SAneesh Kumar K.V static int local_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf) 1016be940c87SM. Mohan Kumar { 10174fa4ce71SChen Gang char *buffer; 10184fa4ce71SChen Gang int ret; 10192289be19SAneesh Kumar K.V char *path = fs_path->data; 10202289be19SAneesh Kumar K.V 10214fa4ce71SChen Gang buffer = rpath(s, path); 10224fa4ce71SChen Gang ret = statfs(buffer, stbuf); 10234fa4ce71SChen Gang g_free(buffer); 10244fa4ce71SChen Gang return ret; 1025be940c87SM. Mohan Kumar } 1026be940c87SM. Mohan Kumar 10272289be19SAneesh Kumar K.V static ssize_t local_lgetxattr(FsContext *ctx, V9fsPath *fs_path, 1028fa32ef88SAneesh Kumar K.V const char *name, void *value, size_t size) 1029fa32ef88SAneesh Kumar K.V { 10302289be19SAneesh Kumar K.V char *path = fs_path->data; 10312289be19SAneesh Kumar K.V 1032fc22118dSAneesh Kumar K.V return v9fs_get_xattr(ctx, path, name, value, size); 1033fa32ef88SAneesh Kumar K.V } 1034fa32ef88SAneesh Kumar K.V 10352289be19SAneesh Kumar K.V static ssize_t local_llistxattr(FsContext *ctx, V9fsPath *fs_path, 1036fa32ef88SAneesh Kumar K.V void *value, size_t size) 1037fa32ef88SAneesh Kumar K.V { 10382289be19SAneesh Kumar K.V char *path = fs_path->data; 10392289be19SAneesh Kumar K.V 1040fc22118dSAneesh Kumar K.V return v9fs_list_xattr(ctx, path, value, size); 104161b6c499SAneesh Kumar K.V } 104261b6c499SAneesh Kumar K.V 10432289be19SAneesh Kumar K.V static int local_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name, 104410b468bdSAneesh Kumar K.V void *value, size_t size, int flags) 104510b468bdSAneesh Kumar K.V { 10462289be19SAneesh Kumar K.V char *path = fs_path->data; 10472289be19SAneesh Kumar K.V 1048fc22118dSAneesh Kumar K.V return v9fs_set_xattr(ctx, path, name, value, size, flags); 104910b468bdSAneesh Kumar K.V } 105010b468bdSAneesh Kumar K.V 10512289be19SAneesh Kumar K.V static int local_lremovexattr(FsContext *ctx, V9fsPath *fs_path, 10522289be19SAneesh Kumar K.V const char *name) 10539ed3ef26SAneesh Kumar K.V { 10542289be19SAneesh Kumar K.V char *path = fs_path->data; 10552289be19SAneesh Kumar K.V 1056fc22118dSAneesh Kumar K.V return v9fs_remove_xattr(ctx, path, name); 10579ed3ef26SAneesh Kumar K.V } 10589ed3ef26SAneesh Kumar K.V 10592289be19SAneesh Kumar K.V static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path, 10602289be19SAneesh Kumar K.V const char *name, V9fsPath *target) 10612289be19SAneesh Kumar K.V { 10622289be19SAneesh Kumar K.V if (dir_path) { 1063*e3e83f2eSGreg Kurz v9fs_path_sprintf(target, "%s/%s", dir_path->data, name); 10642289be19SAneesh Kumar K.V } else { 1065*e3e83f2eSGreg Kurz v9fs_path_sprintf(target, "%s", name); 10662289be19SAneesh Kumar K.V } 10672289be19SAneesh Kumar K.V return 0; 10682289be19SAneesh Kumar K.V } 10692289be19SAneesh Kumar K.V 10702289be19SAneesh Kumar K.V static int local_renameat(FsContext *ctx, V9fsPath *olddir, 10712289be19SAneesh Kumar K.V const char *old_name, V9fsPath *newdir, 10722289be19SAneesh Kumar K.V const char *new_name) 10732289be19SAneesh Kumar K.V { 10742289be19SAneesh Kumar K.V int ret; 10752289be19SAneesh Kumar K.V V9fsString old_full_name, new_full_name; 10762289be19SAneesh Kumar K.V 10772289be19SAneesh Kumar K.V v9fs_string_init(&old_full_name); 10782289be19SAneesh Kumar K.V v9fs_string_init(&new_full_name); 10792289be19SAneesh Kumar K.V 10802289be19SAneesh Kumar K.V v9fs_string_sprintf(&old_full_name, "%s/%s", olddir->data, old_name); 10812289be19SAneesh Kumar K.V v9fs_string_sprintf(&new_full_name, "%s/%s", newdir->data, new_name); 10822289be19SAneesh Kumar K.V 10832289be19SAneesh Kumar K.V ret = local_rename(ctx, old_full_name.data, new_full_name.data); 10842289be19SAneesh Kumar K.V v9fs_string_free(&old_full_name); 10852289be19SAneesh Kumar K.V v9fs_string_free(&new_full_name); 10862289be19SAneesh Kumar K.V return ret; 10872289be19SAneesh Kumar K.V } 10882289be19SAneesh Kumar K.V 10892289be19SAneesh Kumar K.V static int local_unlinkat(FsContext *ctx, V9fsPath *dir, 10902289be19SAneesh Kumar K.V const char *name, int flags) 10912289be19SAneesh Kumar K.V { 10922289be19SAneesh Kumar K.V int ret; 10932289be19SAneesh Kumar K.V V9fsString fullname; 10944fa4ce71SChen Gang char *buffer; 10952c30dd74SAneesh Kumar K.V 10962289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 10972289be19SAneesh Kumar K.V 10982289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name); 10992c30dd74SAneesh Kumar K.V if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 11002c30dd74SAneesh Kumar K.V if (flags == AT_REMOVEDIR) { 11012c30dd74SAneesh Kumar K.V /* 11022c30dd74SAneesh Kumar K.V * If directory remove .virtfs_metadata contained in the 11032c30dd74SAneesh Kumar K.V * directory 11042c30dd74SAneesh Kumar K.V */ 11054fa4ce71SChen Gang buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, 11062c30dd74SAneesh Kumar K.V fullname.data, VIRTFS_META_DIR); 11072c30dd74SAneesh Kumar K.V ret = remove(buffer); 11084fa4ce71SChen Gang g_free(buffer); 11092c30dd74SAneesh Kumar K.V if (ret < 0 && errno != ENOENT) { 11102c30dd74SAneesh Kumar K.V /* 11112c30dd74SAneesh Kumar K.V * We didn't had the .virtfs_metadata file. May be file created 11122c30dd74SAneesh Kumar K.V * in non-mapped mode ?. Ignore ENOENT. 11132c30dd74SAneesh Kumar K.V */ 11142c30dd74SAneesh Kumar K.V goto err_out; 11152c30dd74SAneesh Kumar K.V } 11162c30dd74SAneesh Kumar K.V } 11172c30dd74SAneesh Kumar K.V /* 11182c30dd74SAneesh Kumar K.V * Now remove the name from parent directory 11192c30dd74SAneesh Kumar K.V * .virtfs_metadata directory. 11202c30dd74SAneesh Kumar K.V */ 11214fa4ce71SChen Gang buffer = local_mapped_attr_path(ctx, fullname.data); 11224fa4ce71SChen Gang ret = remove(buffer); 11234fa4ce71SChen Gang g_free(buffer); 11242c30dd74SAneesh Kumar K.V if (ret < 0 && errno != ENOENT) { 11252c30dd74SAneesh Kumar K.V /* 11262c30dd74SAneesh Kumar K.V * We didn't had the .virtfs_metadata file. May be file created 11272c30dd74SAneesh Kumar K.V * in non-mapped mode ?. Ignore ENOENT. 11282c30dd74SAneesh Kumar K.V */ 11292c30dd74SAneesh Kumar K.V goto err_out; 11302c30dd74SAneesh Kumar K.V } 11312c30dd74SAneesh Kumar K.V } 11322c30dd74SAneesh Kumar K.V /* Remove the name finally */ 11334fa4ce71SChen Gang buffer = rpath(ctx, fullname.data); 11344fa4ce71SChen Gang ret = remove(buffer); 11354fa4ce71SChen Gang g_free(buffer); 11362289be19SAneesh Kumar K.V 11372c30dd74SAneesh Kumar K.V err_out: 113875b7931eSChen Gang v9fs_string_free(&fullname); 11392289be19SAneesh Kumar K.V return ret; 11402289be19SAneesh Kumar K.V } 11419ed3ef26SAneesh Kumar K.V 1142e06a765eSHarsh Prateek Bora static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, 1143e06a765eSHarsh Prateek Bora mode_t st_mode, uint64_t *st_gen) 1144e06a765eSHarsh Prateek Bora { 1145ae0f940eSPaolo Bonzini #ifdef FS_IOC_GETVERSION 11460e5fc994SKirill A. Shutemov int err; 1147cc720ddbSAneesh Kumar K.V V9fsFidOpenState fid_open; 1148cc720ddbSAneesh Kumar K.V 1149e06a765eSHarsh Prateek Bora /* 1150e06a765eSHarsh Prateek Bora * Do not try to open special files like device nodes, fifos etc 1151e06a765eSHarsh Prateek Bora * We can get fd for regular files and directories only 1152e06a765eSHarsh Prateek Bora */ 1153e06a765eSHarsh Prateek Bora if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) { 11541a9978a5SKirill A. Shutemov errno = ENOTTY; 11551a9978a5SKirill A. Shutemov return -1; 1156e06a765eSHarsh Prateek Bora } 1157cc720ddbSAneesh Kumar K.V err = local_open(ctx, path, O_RDONLY, &fid_open); 1158cc720ddbSAneesh Kumar K.V if (err < 0) { 1159cc720ddbSAneesh Kumar K.V return err; 1160e06a765eSHarsh Prateek Bora } 1161cc720ddbSAneesh Kumar K.V err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen); 1162cc720ddbSAneesh Kumar K.V local_close(ctx, &fid_open); 1163e06a765eSHarsh Prateek Bora return err; 11640e5fc994SKirill A. Shutemov #else 11650e5fc994SKirill A. Shutemov errno = ENOTTY; 11660e5fc994SKirill A. Shutemov return -1; 11670e5fc994SKirill A. Shutemov #endif 1168e06a765eSHarsh Prateek Bora } 1169e06a765eSHarsh Prateek Bora 11700174fe73SAneesh Kumar K.V static int local_init(FsContext *ctx) 11710174fe73SAneesh Kumar K.V { 11722507718bSAneesh Kumar K.V int err = 0; 1173e06a765eSHarsh Prateek Bora struct statfs stbuf; 1174e06a765eSHarsh Prateek Bora 11752c30dd74SAneesh Kumar K.V if (ctx->export_flags & V9FS_SM_PASSTHROUGH) { 11762c30dd74SAneesh Kumar K.V ctx->xops = passthrough_xattr_ops; 11772c30dd74SAneesh Kumar K.V } else if (ctx->export_flags & V9FS_SM_MAPPED) { 11782c30dd74SAneesh Kumar K.V ctx->xops = mapped_xattr_ops; 11792c30dd74SAneesh Kumar K.V } else if (ctx->export_flags & V9FS_SM_NONE) { 11802c30dd74SAneesh Kumar K.V ctx->xops = none_xattr_ops; 11812c30dd74SAneesh Kumar K.V } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 11822c30dd74SAneesh Kumar K.V /* 11832c30dd74SAneesh Kumar K.V * xattr operation for mapped-file and passthrough 11842c30dd74SAneesh Kumar K.V * remain same. 11852c30dd74SAneesh Kumar K.V */ 11862c30dd74SAneesh Kumar K.V ctx->xops = passthrough_xattr_ops; 11872c30dd74SAneesh Kumar K.V } 1188c98f1d4aSAneesh Kumar K.V ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT; 11892507718bSAneesh Kumar K.V #ifdef FS_IOC_GETVERSION 11902507718bSAneesh Kumar K.V /* 11912507718bSAneesh Kumar K.V * use ioc_getversion only if the iocl is definied 11922507718bSAneesh Kumar K.V */ 1193e06a765eSHarsh Prateek Bora err = statfs(ctx->fs_root, &stbuf); 1194e06a765eSHarsh Prateek Bora if (!err) { 1195e06a765eSHarsh Prateek Bora switch (stbuf.f_type) { 1196e06a765eSHarsh Prateek Bora case EXT2_SUPER_MAGIC: 1197e06a765eSHarsh Prateek Bora case BTRFS_SUPER_MAGIC: 1198e06a765eSHarsh Prateek Bora case REISERFS_SUPER_MAGIC: 1199e06a765eSHarsh Prateek Bora case XFS_SUPER_MAGIC: 1200e06a765eSHarsh Prateek Bora ctx->exops.get_st_gen = local_ioc_getversion; 1201e06a765eSHarsh Prateek Bora break; 1202e06a765eSHarsh Prateek Bora } 1203e06a765eSHarsh Prateek Bora } 12042507718bSAneesh Kumar K.V #endif 1205e06a765eSHarsh Prateek Bora return err; 12060174fe73SAneesh Kumar K.V } 12070174fe73SAneesh Kumar K.V 120899519f0aSAneesh Kumar K.V static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse) 120999519f0aSAneesh Kumar K.V { 121099519f0aSAneesh Kumar K.V const char *sec_model = qemu_opt_get(opts, "security_model"); 121199519f0aSAneesh Kumar K.V const char *path = qemu_opt_get(opts, "path"); 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 } 124099519f0aSAneesh Kumar K.V fse->path = g_strdup(path); 124199519f0aSAneesh Kumar K.V 124299519f0aSAneesh Kumar K.V return 0; 124399519f0aSAneesh Kumar K.V } 124499519f0aSAneesh Kumar K.V 12459f107513SAnthony Liguori FileOperations local_ops = { 124699519f0aSAneesh Kumar K.V .parse_opts = local_parse_opts, 12470174fe73SAneesh Kumar K.V .init = local_init, 1248131dcb25SAnthony Liguori .lstat = local_lstat, 1249131dcb25SAnthony Liguori .readlink = local_readlink, 1250131dcb25SAnthony Liguori .close = local_close, 1251131dcb25SAnthony Liguori .closedir = local_closedir, 1252a6568fe2SAnthony Liguori .open = local_open, 1253a6568fe2SAnthony Liguori .opendir = local_opendir, 1254a9231555SAnthony Liguori .rewinddir = local_rewinddir, 1255a9231555SAnthony Liguori .telldir = local_telldir, 1256635324e8SGreg Kurz .readdir = local_readdir, 1257a9231555SAnthony Liguori .seekdir = local_seekdir, 125856d15a53SSanchit Garg .preadv = local_preadv, 125956d15a53SSanchit Garg .pwritev = local_pwritev, 1260c494dd6fSAnthony Liguori .chmod = local_chmod, 1261c494dd6fSAnthony Liguori .mknod = local_mknod, 1262c494dd6fSAnthony Liguori .mkdir = local_mkdir, 1263c494dd6fSAnthony Liguori .fstat = local_fstat, 1264c494dd6fSAnthony Liguori .open2 = local_open2, 1265c494dd6fSAnthony Liguori .symlink = local_symlink, 1266c494dd6fSAnthony Liguori .link = local_link, 12678cf89e00SAnthony Liguori .truncate = local_truncate, 12688cf89e00SAnthony Liguori .rename = local_rename, 12698cf89e00SAnthony Liguori .chown = local_chown, 127074bc02b2SM. Mohan Kumar .utimensat = local_utimensat, 12715bae1900SAnthony Liguori .remove = local_remove, 12728cf89e00SAnthony Liguori .fsync = local_fsync, 1273be940c87SM. Mohan Kumar .statfs = local_statfs, 1274fa32ef88SAneesh Kumar K.V .lgetxattr = local_lgetxattr, 1275fa32ef88SAneesh Kumar K.V .llistxattr = local_llistxattr, 127610b468bdSAneesh Kumar K.V .lsetxattr = local_lsetxattr, 12779ed3ef26SAneesh Kumar K.V .lremovexattr = local_lremovexattr, 12782289be19SAneesh Kumar K.V .name_to_path = local_name_to_path, 12792289be19SAneesh Kumar K.V .renameat = local_renameat, 12802289be19SAneesh Kumar K.V .unlinkat = local_unlinkat, 12819f107513SAnthony Liguori }; 1282