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; 359*21328e1eSGreg Kurz int fd; 3602289be19SAneesh Kumar K.V 3614fa4ce71SChen Gang buffer = rpath(ctx, path); 362*21328e1eSGreg Kurz fd = open(buffer, flags | O_NOFOLLOW); 3634fa4ce71SChen Gang g_free(buffer); 364*21328e1eSGreg Kurz if (fd == -1) { 365*21328e1eSGreg Kurz return -1; 366*21328e1eSGreg Kurz } 367*21328e1eSGreg Kurz fs->fd = fd; 368cc720ddbSAneesh Kumar K.V return fs->fd; 369a6568fe2SAnthony Liguori } 370a6568fe2SAnthony Liguori 371cc720ddbSAneesh Kumar K.V static int local_opendir(FsContext *ctx, 372cc720ddbSAneesh Kumar K.V V9fsPath *fs_path, V9fsFidOpenState *fs) 373a6568fe2SAnthony Liguori { 3744fa4ce71SChen Gang char *buffer; 3752289be19SAneesh Kumar K.V char *path = fs_path->data; 376*21328e1eSGreg Kurz DIR *stream; 3772289be19SAneesh Kumar K.V 3784fa4ce71SChen Gang buffer = rpath(ctx, path); 379*21328e1eSGreg Kurz stream = opendir(buffer); 3804fa4ce71SChen Gang g_free(buffer); 381*21328e1eSGreg Kurz if (!stream) { 382cc720ddbSAneesh Kumar K.V return -1; 383cc720ddbSAneesh Kumar K.V } 384*21328e1eSGreg Kurz fs->dir.stream = stream; 385cc720ddbSAneesh Kumar K.V return 0; 386a6568fe2SAnthony Liguori } 387a6568fe2SAnthony Liguori 388cc720ddbSAneesh Kumar K.V static void local_rewinddir(FsContext *ctx, V9fsFidOpenState *fs) 389a9231555SAnthony Liguori { 390f314ea4eSGreg Kurz rewinddir(fs->dir.stream); 391a9231555SAnthony Liguori } 392a9231555SAnthony Liguori 393cc720ddbSAneesh Kumar K.V static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs) 394a9231555SAnthony Liguori { 395f314ea4eSGreg Kurz return telldir(fs->dir.stream); 396a9231555SAnthony Liguori } 397a9231555SAnthony Liguori 398635324e8SGreg Kurz static struct dirent *local_readdir(FsContext *ctx, V9fsFidOpenState *fs) 399a9231555SAnthony Liguori { 400635324e8SGreg Kurz struct dirent *entry; 4012c30dd74SAneesh Kumar K.V 4022c30dd74SAneesh Kumar K.V again: 403635324e8SGreg Kurz entry = readdir(fs->dir.stream); 404635324e8SGreg Kurz if (!entry) { 405635324e8SGreg Kurz return NULL; 406635324e8SGreg Kurz } 407635324e8SGreg Kurz 408840a1bf2SBastian Blank if (ctx->export_flags & V9FS_SM_MAPPED) { 409840a1bf2SBastian Blank entry->d_type = DT_UNKNOWN; 410840a1bf2SBastian Blank } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 411635324e8SGreg Kurz if (!strcmp(entry->d_name, VIRTFS_META_DIR)) { 4122c30dd74SAneesh Kumar K.V /* skp the meta data directory */ 4132c30dd74SAneesh Kumar K.V goto again; 4142c30dd74SAneesh Kumar K.V } 415840a1bf2SBastian Blank entry->d_type = DT_UNKNOWN; 4162c30dd74SAneesh Kumar K.V } 417635324e8SGreg Kurz 418635324e8SGreg Kurz return entry; 419a9231555SAnthony Liguori } 420a9231555SAnthony Liguori 421cc720ddbSAneesh Kumar K.V static void local_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off) 422a9231555SAnthony Liguori { 423f314ea4eSGreg Kurz seekdir(fs->dir.stream, off); 424a9231555SAnthony Liguori } 425a9231555SAnthony Liguori 426cc720ddbSAneesh Kumar K.V static ssize_t local_preadv(FsContext *ctx, V9fsFidOpenState *fs, 427cc720ddbSAneesh Kumar K.V const struct iovec *iov, 42856d15a53SSanchit Garg int iovcnt, off_t offset) 429a9231555SAnthony Liguori { 43056d15a53SSanchit Garg #ifdef CONFIG_PREADV 431cc720ddbSAneesh Kumar K.V return preadv(fs->fd, iov, iovcnt, offset); 43256d15a53SSanchit Garg #else 433cc720ddbSAneesh Kumar K.V int err = lseek(fs->fd, offset, SEEK_SET); 43456d15a53SSanchit Garg if (err == -1) { 43556d15a53SSanchit Garg return err; 43656d15a53SSanchit Garg } else { 437cc720ddbSAneesh Kumar K.V return readv(fs->fd, iov, iovcnt); 438a9231555SAnthony Liguori } 43956d15a53SSanchit Garg #endif 440a9231555SAnthony Liguori } 441a9231555SAnthony Liguori 442cc720ddbSAneesh Kumar K.V static ssize_t local_pwritev(FsContext *ctx, V9fsFidOpenState *fs, 443cc720ddbSAneesh Kumar K.V const struct iovec *iov, 44456d15a53SSanchit Garg int iovcnt, off_t offset) 4458449360cSAnthony Liguori { 4466fe76accSGreg Kurz ssize_t ret; 44756d15a53SSanchit Garg #ifdef CONFIG_PREADV 448cc720ddbSAneesh Kumar K.V ret = pwritev(fs->fd, iov, iovcnt, offset); 44956d15a53SSanchit Garg #else 450cc720ddbSAneesh Kumar K.V int err = lseek(fs->fd, offset, SEEK_SET); 45156d15a53SSanchit Garg if (err == -1) { 45256d15a53SSanchit Garg return err; 45356d15a53SSanchit Garg } else { 454cc720ddbSAneesh Kumar K.V ret = writev(fs->fd, iov, iovcnt); 4558449360cSAnthony Liguori } 45656d15a53SSanchit Garg #endif 457d3ab98e6SAneesh Kumar K.V #ifdef CONFIG_SYNC_FILE_RANGE 458d3ab98e6SAneesh Kumar K.V if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) { 459d3ab98e6SAneesh Kumar K.V /* 460d3ab98e6SAneesh Kumar K.V * Initiate a writeback. This is not a data integrity sync. 461d3ab98e6SAneesh Kumar K.V * We want to ensure that we don't leave dirty pages in the cache 462d3ab98e6SAneesh Kumar K.V * after write when writeout=immediate is sepcified. 463d3ab98e6SAneesh Kumar K.V */ 464cc720ddbSAneesh Kumar K.V sync_file_range(fs->fd, offset, ret, 465d3ab98e6SAneesh Kumar K.V SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE); 466d3ab98e6SAneesh Kumar K.V } 467d3ab98e6SAneesh Kumar K.V #endif 468d3ab98e6SAneesh Kumar K.V return ret; 46956d15a53SSanchit Garg } 4708449360cSAnthony Liguori 4712289be19SAneesh Kumar K.V static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp) 472c494dd6fSAnthony Liguori { 4734fa4ce71SChen Gang char *buffer; 4744fa4ce71SChen Gang int ret = -1; 4752289be19SAneesh Kumar K.V char *path = fs_path->data; 4762289be19SAneesh Kumar K.V 477b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 4784fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 4794fa4ce71SChen Gang ret = local_set_xattr(buffer, credp); 4804fa4ce71SChen Gang g_free(buffer); 4812c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 4822c30dd74SAneesh Kumar K.V return local_set_mapped_file_attr(fs_ctx, path, credp); 483b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 484b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 4854fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 4864fa4ce71SChen Gang ret = chmod(buffer, credp->fc_mode); 4874fa4ce71SChen Gang g_free(buffer); 488e95ead32SVenkateswararao Jujjuri (JV) } 4894fa4ce71SChen Gang return ret; 490c494dd6fSAnthony Liguori } 491c494dd6fSAnthony Liguori 4922289be19SAneesh Kumar K.V static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path, 4932289be19SAneesh Kumar K.V const char *name, FsCred *credp) 494c494dd6fSAnthony Liguori { 4952289be19SAneesh Kumar K.V char *path; 4961c293312SVenkateswararao Jujjuri (JV) int err = -1; 4971c293312SVenkateswararao Jujjuri (JV) int serrno = 0; 4982289be19SAneesh Kumar K.V V9fsString fullname; 4994ed7b2c3SStefan Weil char *buffer = NULL; 5001c293312SVenkateswararao Jujjuri (JV) 5012289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 5022289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); 5032289be19SAneesh Kumar K.V path = fullname.data; 5042289be19SAneesh Kumar K.V 5051c293312SVenkateswararao Jujjuri (JV) /* Determine the security model */ 506b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 5074fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5084fa4ce71SChen Gang err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0); 5091c293312SVenkateswararao Jujjuri (JV) if (err == -1) { 5102289be19SAneesh Kumar K.V goto out; 5111c293312SVenkateswararao Jujjuri (JV) } 5124fa4ce71SChen Gang err = local_set_xattr(buffer, credp); 5131c293312SVenkateswararao Jujjuri (JV) if (err == -1) { 5141c293312SVenkateswararao Jujjuri (JV) serrno = errno; 5151c293312SVenkateswararao Jujjuri (JV) goto err_end; 5161c293312SVenkateswararao Jujjuri (JV) } 5172c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 5182c30dd74SAneesh Kumar K.V 5194fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5204fa4ce71SChen Gang err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0); 5212c30dd74SAneesh Kumar K.V if (err == -1) { 5222c30dd74SAneesh Kumar K.V goto out; 5232c30dd74SAneesh Kumar K.V } 5242c30dd74SAneesh Kumar K.V err = local_set_mapped_file_attr(fs_ctx, path, credp); 5252c30dd74SAneesh Kumar K.V if (err == -1) { 5262c30dd74SAneesh Kumar K.V serrno = errno; 5272c30dd74SAneesh Kumar K.V goto err_end; 5282c30dd74SAneesh Kumar K.V } 529b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 530b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 5314fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5324fa4ce71SChen Gang err = mknod(buffer, credp->fc_mode, credp->fc_rdev); 5331c293312SVenkateswararao Jujjuri (JV) if (err == -1) { 5342289be19SAneesh Kumar K.V goto out; 5351c293312SVenkateswararao Jujjuri (JV) } 5361c293312SVenkateswararao Jujjuri (JV) err = local_post_create_passthrough(fs_ctx, path, credp); 5371c293312SVenkateswararao Jujjuri (JV) if (err == -1) { 5381c293312SVenkateswararao Jujjuri (JV) serrno = errno; 5391c293312SVenkateswararao Jujjuri (JV) goto err_end; 5401c293312SVenkateswararao Jujjuri (JV) } 5411c293312SVenkateswararao Jujjuri (JV) } 5422289be19SAneesh Kumar K.V goto out; 5431c293312SVenkateswararao Jujjuri (JV) 5441c293312SVenkateswararao Jujjuri (JV) err_end: 5454fa4ce71SChen Gang remove(buffer); 5461c293312SVenkateswararao Jujjuri (JV) errno = serrno; 5472289be19SAneesh Kumar K.V out: 5484ed7b2c3SStefan Weil g_free(buffer); 5492289be19SAneesh Kumar K.V v9fs_string_free(&fullname); 5501c293312SVenkateswararao Jujjuri (JV) return err; 551c494dd6fSAnthony Liguori } 552c494dd6fSAnthony Liguori 5532289be19SAneesh Kumar K.V static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path, 5542289be19SAneesh Kumar K.V const char *name, FsCred *credp) 555c494dd6fSAnthony Liguori { 5562289be19SAneesh Kumar K.V char *path; 55700ec5c37SVenkateswararao Jujjuri (JV) int err = -1; 55800ec5c37SVenkateswararao Jujjuri (JV) int serrno = 0; 5592289be19SAneesh Kumar K.V V9fsString fullname; 5604ed7b2c3SStefan Weil char *buffer = NULL; 56100ec5c37SVenkateswararao Jujjuri (JV) 5622289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 5632289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); 5642289be19SAneesh Kumar K.V path = fullname.data; 5652289be19SAneesh Kumar K.V 56600ec5c37SVenkateswararao Jujjuri (JV) /* Determine the security model */ 567b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 5684fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5694fa4ce71SChen Gang err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS); 57000ec5c37SVenkateswararao Jujjuri (JV) if (err == -1) { 5712289be19SAneesh Kumar K.V goto out; 57200ec5c37SVenkateswararao Jujjuri (JV) } 57300ec5c37SVenkateswararao Jujjuri (JV) credp->fc_mode = credp->fc_mode|S_IFDIR; 5744fa4ce71SChen Gang err = local_set_xattr(buffer, credp); 57500ec5c37SVenkateswararao Jujjuri (JV) if (err == -1) { 57600ec5c37SVenkateswararao Jujjuri (JV) serrno = errno; 57700ec5c37SVenkateswararao Jujjuri (JV) goto err_end; 57800ec5c37SVenkateswararao Jujjuri (JV) } 5792c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 5804fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5814fa4ce71SChen Gang err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS); 5822c30dd74SAneesh Kumar K.V if (err == -1) { 5832c30dd74SAneesh Kumar K.V goto out; 5842c30dd74SAneesh Kumar K.V } 5852c30dd74SAneesh Kumar K.V credp->fc_mode = credp->fc_mode|S_IFDIR; 5862c30dd74SAneesh Kumar K.V err = local_set_mapped_file_attr(fs_ctx, path, credp); 5872c30dd74SAneesh Kumar K.V if (err == -1) { 5882c30dd74SAneesh Kumar K.V serrno = errno; 5892c30dd74SAneesh Kumar K.V goto err_end; 5902c30dd74SAneesh Kumar K.V } 591b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 592b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 5934fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5944fa4ce71SChen Gang err = mkdir(buffer, credp->fc_mode); 59500ec5c37SVenkateswararao Jujjuri (JV) if (err == -1) { 5962289be19SAneesh Kumar K.V goto out; 59700ec5c37SVenkateswararao Jujjuri (JV) } 59800ec5c37SVenkateswararao Jujjuri (JV) err = local_post_create_passthrough(fs_ctx, path, credp); 59900ec5c37SVenkateswararao Jujjuri (JV) if (err == -1) { 60000ec5c37SVenkateswararao Jujjuri (JV) serrno = errno; 60100ec5c37SVenkateswararao Jujjuri (JV) goto err_end; 60200ec5c37SVenkateswararao Jujjuri (JV) } 60300ec5c37SVenkateswararao Jujjuri (JV) } 6042289be19SAneesh Kumar K.V goto out; 60500ec5c37SVenkateswararao Jujjuri (JV) 60600ec5c37SVenkateswararao Jujjuri (JV) err_end: 6074fa4ce71SChen Gang remove(buffer); 60800ec5c37SVenkateswararao Jujjuri (JV) errno = serrno; 6092289be19SAneesh Kumar K.V out: 6104ed7b2c3SStefan Weil g_free(buffer); 6112289be19SAneesh Kumar K.V v9fs_string_free(&fullname); 61200ec5c37SVenkateswararao Jujjuri (JV) return err; 613c494dd6fSAnthony Liguori } 614c494dd6fSAnthony Liguori 6158b888272SAneesh Kumar K.V static int local_fstat(FsContext *fs_ctx, int fid_type, 616cc720ddbSAneesh Kumar K.V V9fsFidOpenState *fs, struct stat *stbuf) 617c494dd6fSAnthony Liguori { 6188b888272SAneesh Kumar K.V int err, fd; 6198b888272SAneesh Kumar K.V 6208b888272SAneesh Kumar K.V if (fid_type == P9_FID_DIR) { 621f314ea4eSGreg Kurz fd = dirfd(fs->dir.stream); 6228b888272SAneesh Kumar K.V } else { 6238b888272SAneesh Kumar K.V fd = fs->fd; 6248b888272SAneesh Kumar K.V } 6258b888272SAneesh Kumar K.V 6268b888272SAneesh Kumar K.V err = fstat(fd, stbuf); 6271237ad76SVenkateswararao Jujjuri (JV) if (err) { 6281237ad76SVenkateswararao Jujjuri (JV) return err; 6291237ad76SVenkateswararao Jujjuri (JV) } 630b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 6311237ad76SVenkateswararao Jujjuri (JV) /* Actual credentials are part of extended attrs */ 6321237ad76SVenkateswararao Jujjuri (JV) uid_t tmp_uid; 6331237ad76SVenkateswararao Jujjuri (JV) gid_t tmp_gid; 6341237ad76SVenkateswararao Jujjuri (JV) mode_t tmp_mode; 6351237ad76SVenkateswararao Jujjuri (JV) dev_t tmp_dev; 6361237ad76SVenkateswararao Jujjuri (JV) 637f8ad4a89SAneesh Kumar K.V if (fgetxattr(fd, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) { 638f8ad4a89SAneesh Kumar K.V stbuf->st_uid = le32_to_cpu(tmp_uid); 6391237ad76SVenkateswararao Jujjuri (JV) } 640f8ad4a89SAneesh Kumar K.V if (fgetxattr(fd, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) { 641f8ad4a89SAneesh Kumar K.V stbuf->st_gid = le32_to_cpu(tmp_gid); 6421237ad76SVenkateswararao Jujjuri (JV) } 643f8ad4a89SAneesh Kumar K.V if (fgetxattr(fd, "user.virtfs.mode", &tmp_mode, sizeof(mode_t)) > 0) { 644f8ad4a89SAneesh Kumar K.V stbuf->st_mode = le32_to_cpu(tmp_mode); 6451237ad76SVenkateswararao Jujjuri (JV) } 646f8ad4a89SAneesh Kumar K.V if (fgetxattr(fd, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) { 647f8ad4a89SAneesh Kumar K.V stbuf->st_rdev = le64_to_cpu(tmp_dev); 6481237ad76SVenkateswararao Jujjuri (JV) } 6492c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 6502c30dd74SAneesh Kumar K.V errno = EOPNOTSUPP; 6512c30dd74SAneesh Kumar K.V return -1; 6521237ad76SVenkateswararao Jujjuri (JV) } 6531237ad76SVenkateswararao Jujjuri (JV) return err; 654c494dd6fSAnthony Liguori } 655c494dd6fSAnthony Liguori 6562289be19SAneesh Kumar K.V static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, 657cc720ddbSAneesh Kumar K.V int flags, FsCred *credp, V9fsFidOpenState *fs) 658c494dd6fSAnthony Liguori { 6592289be19SAneesh Kumar K.V char *path; 6604750a96fSVenkateswararao Jujjuri (JV) int fd = -1; 6614750a96fSVenkateswararao Jujjuri (JV) int err = -1; 6624750a96fSVenkateswararao Jujjuri (JV) int serrno = 0; 6632289be19SAneesh Kumar K.V V9fsString fullname; 6644ed7b2c3SStefan Weil char *buffer = NULL; 6654750a96fSVenkateswararao Jujjuri (JV) 6660ceb092eSAneesh Kumar K.V /* 6670ceb092eSAneesh Kumar K.V * Mark all the open to not follow symlinks 6680ceb092eSAneesh Kumar K.V */ 6690ceb092eSAneesh Kumar K.V flags |= O_NOFOLLOW; 6700ceb092eSAneesh Kumar K.V 6712289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 6722289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); 6732289be19SAneesh Kumar K.V path = fullname.data; 6742289be19SAneesh Kumar K.V 6754750a96fSVenkateswararao Jujjuri (JV) /* Determine the security model */ 676b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 6774fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 6784fa4ce71SChen Gang fd = open(buffer, flags, SM_LOCAL_MODE_BITS); 6794750a96fSVenkateswararao Jujjuri (JV) if (fd == -1) { 6802289be19SAneesh Kumar K.V err = fd; 6812289be19SAneesh Kumar K.V goto out; 6824750a96fSVenkateswararao Jujjuri (JV) } 6834750a96fSVenkateswararao Jujjuri (JV) credp->fc_mode = credp->fc_mode|S_IFREG; 6844750a96fSVenkateswararao Jujjuri (JV) /* Set cleint credentials in xattr */ 6854fa4ce71SChen Gang err = local_set_xattr(buffer, credp); 6864750a96fSVenkateswararao Jujjuri (JV) if (err == -1) { 6874750a96fSVenkateswararao Jujjuri (JV) serrno = errno; 6884750a96fSVenkateswararao Jujjuri (JV) goto err_end; 6894750a96fSVenkateswararao Jujjuri (JV) } 6902c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 6914fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 6924fa4ce71SChen Gang fd = open(buffer, flags, SM_LOCAL_MODE_BITS); 6932c30dd74SAneesh Kumar K.V if (fd == -1) { 6942c30dd74SAneesh Kumar K.V err = fd; 6952c30dd74SAneesh Kumar K.V goto out; 6962c30dd74SAneesh Kumar K.V } 6972c30dd74SAneesh Kumar K.V credp->fc_mode = credp->fc_mode|S_IFREG; 6982c30dd74SAneesh Kumar K.V /* Set client credentials in .virtfs_metadata directory files */ 6992c30dd74SAneesh Kumar K.V err = local_set_mapped_file_attr(fs_ctx, path, credp); 7002c30dd74SAneesh Kumar K.V if (err == -1) { 7012c30dd74SAneesh Kumar K.V serrno = errno; 7022c30dd74SAneesh Kumar K.V goto err_end; 7032c30dd74SAneesh Kumar K.V } 704b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 705b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 7064fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 7074fa4ce71SChen Gang fd = open(buffer, flags, credp->fc_mode); 7084750a96fSVenkateswararao Jujjuri (JV) if (fd == -1) { 7092289be19SAneesh Kumar K.V err = fd; 7102289be19SAneesh Kumar K.V goto out; 7114750a96fSVenkateswararao Jujjuri (JV) } 7124750a96fSVenkateswararao Jujjuri (JV) err = local_post_create_passthrough(fs_ctx, path, credp); 7134750a96fSVenkateswararao Jujjuri (JV) if (err == -1) { 7144750a96fSVenkateswararao Jujjuri (JV) serrno = errno; 7154750a96fSVenkateswararao Jujjuri (JV) goto err_end; 7164750a96fSVenkateswararao Jujjuri (JV) } 7174750a96fSVenkateswararao Jujjuri (JV) } 7182289be19SAneesh Kumar K.V err = fd; 719cc720ddbSAneesh Kumar K.V fs->fd = fd; 7202289be19SAneesh Kumar K.V goto out; 7214750a96fSVenkateswararao Jujjuri (JV) 7224750a96fSVenkateswararao Jujjuri (JV) err_end: 7234750a96fSVenkateswararao Jujjuri (JV) close(fd); 7244fa4ce71SChen Gang remove(buffer); 7254750a96fSVenkateswararao Jujjuri (JV) errno = serrno; 7262289be19SAneesh Kumar K.V out: 7274ed7b2c3SStefan Weil g_free(buffer); 7282289be19SAneesh Kumar K.V v9fs_string_free(&fullname); 7294750a96fSVenkateswararao Jujjuri (JV) return err; 730c494dd6fSAnthony Liguori } 731c494dd6fSAnthony Liguori 732758e8e38SVenkateswararao Jujjuri (JV) 733879c2813SVenkateswararao Jujjuri (JV) static int local_symlink(FsContext *fs_ctx, const char *oldpath, 7342289be19SAneesh Kumar K.V V9fsPath *dir_path, const char *name, FsCred *credp) 735c494dd6fSAnthony Liguori { 736879c2813SVenkateswararao Jujjuri (JV) int err = -1; 737879c2813SVenkateswararao Jujjuri (JV) int serrno = 0; 7382289be19SAneesh Kumar K.V char *newpath; 7392289be19SAneesh Kumar K.V V9fsString fullname; 7404ed7b2c3SStefan Weil char *buffer = NULL; 741879c2813SVenkateswararao Jujjuri (JV) 7422289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 7432289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); 7442289be19SAneesh Kumar K.V newpath = fullname.data; 7452289be19SAneesh Kumar K.V 746879c2813SVenkateswararao Jujjuri (JV) /* Determine the security model */ 747b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 748879c2813SVenkateswararao Jujjuri (JV) int fd; 749879c2813SVenkateswararao Jujjuri (JV) ssize_t oldpath_size, write_size; 7504fa4ce71SChen Gang buffer = rpath(fs_ctx, newpath); 7514fa4ce71SChen Gang fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS); 752879c2813SVenkateswararao Jujjuri (JV) if (fd == -1) { 7532289be19SAneesh Kumar K.V err = fd; 7542289be19SAneesh Kumar K.V goto out; 755879c2813SVenkateswararao Jujjuri (JV) } 756879c2813SVenkateswararao Jujjuri (JV) /* Write the oldpath (target) to the file. */ 757f35bde2fSHarsh Prateek Bora oldpath_size = strlen(oldpath); 758879c2813SVenkateswararao Jujjuri (JV) do { 759879c2813SVenkateswararao Jujjuri (JV) write_size = write(fd, (void *)oldpath, oldpath_size); 760879c2813SVenkateswararao Jujjuri (JV) } while (write_size == -1 && errno == EINTR); 761879c2813SVenkateswararao Jujjuri (JV) 762879c2813SVenkateswararao Jujjuri (JV) if (write_size != oldpath_size) { 763879c2813SVenkateswararao Jujjuri (JV) serrno = errno; 764879c2813SVenkateswararao Jujjuri (JV) close(fd); 765879c2813SVenkateswararao Jujjuri (JV) err = -1; 766879c2813SVenkateswararao Jujjuri (JV) goto err_end; 767879c2813SVenkateswararao Jujjuri (JV) } 768879c2813SVenkateswararao Jujjuri (JV) close(fd); 769879c2813SVenkateswararao Jujjuri (JV) /* Set cleint credentials in symlink's xattr */ 770879c2813SVenkateswararao Jujjuri (JV) credp->fc_mode = credp->fc_mode|S_IFLNK; 7714fa4ce71SChen Gang err = local_set_xattr(buffer, credp); 772879c2813SVenkateswararao Jujjuri (JV) if (err == -1) { 773879c2813SVenkateswararao Jujjuri (JV) serrno = errno; 774879c2813SVenkateswararao Jujjuri (JV) goto err_end; 775879c2813SVenkateswararao Jujjuri (JV) } 7762c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 7772c30dd74SAneesh Kumar K.V int fd; 7782c30dd74SAneesh Kumar K.V ssize_t oldpath_size, write_size; 7794fa4ce71SChen Gang buffer = rpath(fs_ctx, newpath); 7804fa4ce71SChen Gang fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS); 7812c30dd74SAneesh Kumar K.V if (fd == -1) { 7822c30dd74SAneesh Kumar K.V err = fd; 7832c30dd74SAneesh Kumar K.V goto out; 7842c30dd74SAneesh Kumar K.V } 7852c30dd74SAneesh Kumar K.V /* Write the oldpath (target) to the file. */ 7862c30dd74SAneesh Kumar K.V oldpath_size = strlen(oldpath); 7872c30dd74SAneesh Kumar K.V do { 7882c30dd74SAneesh Kumar K.V write_size = write(fd, (void *)oldpath, oldpath_size); 7892c30dd74SAneesh Kumar K.V } while (write_size == -1 && errno == EINTR); 7902c30dd74SAneesh Kumar K.V 7912c30dd74SAneesh Kumar K.V if (write_size != oldpath_size) { 7922c30dd74SAneesh Kumar K.V serrno = errno; 7932c30dd74SAneesh Kumar K.V close(fd); 7942c30dd74SAneesh Kumar K.V err = -1; 7952c30dd74SAneesh Kumar K.V goto err_end; 7962c30dd74SAneesh Kumar K.V } 7972c30dd74SAneesh Kumar K.V close(fd); 7982c30dd74SAneesh Kumar K.V /* Set cleint credentials in symlink's xattr */ 7992c30dd74SAneesh Kumar K.V credp->fc_mode = credp->fc_mode|S_IFLNK; 8002c30dd74SAneesh Kumar K.V err = local_set_mapped_file_attr(fs_ctx, newpath, credp); 8012c30dd74SAneesh Kumar K.V if (err == -1) { 8022c30dd74SAneesh Kumar K.V serrno = errno; 8032c30dd74SAneesh Kumar K.V goto err_end; 8042c30dd74SAneesh Kumar K.V } 805b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 806b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 8074fa4ce71SChen Gang buffer = rpath(fs_ctx, newpath); 8084fa4ce71SChen Gang err = symlink(oldpath, buffer); 809879c2813SVenkateswararao Jujjuri (JV) if (err) { 8102289be19SAneesh Kumar K.V goto out; 811879c2813SVenkateswararao Jujjuri (JV) } 8124fa4ce71SChen Gang err = lchown(buffer, credp->fc_uid, credp->fc_gid); 813879c2813SVenkateswararao Jujjuri (JV) if (err == -1) { 81412848bfcSAneesh Kumar K.V /* 81512848bfcSAneesh Kumar K.V * If we fail to change ownership and if we are 81612848bfcSAneesh Kumar K.V * using security model none. Ignore the error 81712848bfcSAneesh Kumar K.V */ 818b97400caSAneesh Kumar K.V if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) { 819879c2813SVenkateswararao Jujjuri (JV) serrno = errno; 820879c2813SVenkateswararao Jujjuri (JV) goto err_end; 82112848bfcSAneesh Kumar K.V } else 82212848bfcSAneesh Kumar K.V err = 0; 823879c2813SVenkateswararao Jujjuri (JV) } 824879c2813SVenkateswararao Jujjuri (JV) } 8252289be19SAneesh Kumar K.V goto out; 826879c2813SVenkateswararao Jujjuri (JV) 827879c2813SVenkateswararao Jujjuri (JV) err_end: 8284fa4ce71SChen Gang remove(buffer); 829879c2813SVenkateswararao Jujjuri (JV) errno = serrno; 8302289be19SAneesh Kumar K.V out: 8314ed7b2c3SStefan Weil g_free(buffer); 8322289be19SAneesh Kumar K.V v9fs_string_free(&fullname); 833879c2813SVenkateswararao Jujjuri (JV) return err; 834c494dd6fSAnthony Liguori } 835c494dd6fSAnthony Liguori 8362289be19SAneesh Kumar K.V static int local_link(FsContext *ctx, V9fsPath *oldpath, 8372289be19SAneesh Kumar K.V V9fsPath *dirpath, const char *name) 838c494dd6fSAnthony Liguori { 8392289be19SAneesh Kumar K.V int ret; 8402289be19SAneesh Kumar K.V V9fsString newpath; 8414fa4ce71SChen Gang char *buffer, *buffer1; 842c494dd6fSAnthony Liguori 8432289be19SAneesh Kumar K.V v9fs_string_init(&newpath); 8442289be19SAneesh Kumar K.V v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name); 8452289be19SAneesh Kumar K.V 8464fa4ce71SChen Gang buffer = rpath(ctx, oldpath->data); 8474fa4ce71SChen Gang buffer1 = rpath(ctx, newpath.data); 8484fa4ce71SChen Gang ret = link(buffer, buffer1); 8494fa4ce71SChen Gang g_free(buffer); 8504fa4ce71SChen Gang g_free(buffer1); 8512c30dd74SAneesh Kumar K.V 8522c30dd74SAneesh Kumar K.V /* now link the virtfs_metadata files */ 8532c30dd74SAneesh Kumar K.V if (!ret && (ctx->export_flags & V9FS_SM_MAPPED_FILE)) { 8542c30dd74SAneesh Kumar K.V /* Link the .virtfs_metadata files. Create the metada directory */ 8552c30dd74SAneesh Kumar K.V ret = local_create_mapped_attr_dir(ctx, newpath.data); 8562c30dd74SAneesh Kumar K.V if (ret < 0) { 8572c30dd74SAneesh Kumar K.V goto err_out; 8582c30dd74SAneesh Kumar K.V } 8594fa4ce71SChen Gang buffer = local_mapped_attr_path(ctx, oldpath->data); 8604fa4ce71SChen Gang buffer1 = local_mapped_attr_path(ctx, newpath.data); 8614fa4ce71SChen Gang ret = link(buffer, buffer1); 8624fa4ce71SChen Gang g_free(buffer); 8634fa4ce71SChen Gang g_free(buffer1); 8642c30dd74SAneesh Kumar K.V if (ret < 0 && errno != ENOENT) { 8652c30dd74SAneesh Kumar K.V goto err_out; 8662c30dd74SAneesh Kumar K.V } 8672c30dd74SAneesh Kumar K.V } 8682c30dd74SAneesh Kumar K.V err_out: 8692289be19SAneesh Kumar K.V v9fs_string_free(&newpath); 8702289be19SAneesh Kumar K.V return ret; 871c494dd6fSAnthony Liguori } 872c494dd6fSAnthony Liguori 8732289be19SAneesh Kumar K.V static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size) 8748cf89e00SAnthony Liguori { 8754fa4ce71SChen Gang char *buffer; 8764fa4ce71SChen Gang int ret; 8772289be19SAneesh Kumar K.V char *path = fs_path->data; 8782289be19SAneesh Kumar K.V 8794fa4ce71SChen Gang buffer = rpath(ctx, path); 8804fa4ce71SChen Gang ret = truncate(buffer, size); 8814fa4ce71SChen Gang g_free(buffer); 8824fa4ce71SChen Gang return ret; 8838cf89e00SAnthony Liguori } 8848cf89e00SAnthony Liguori 8858cf89e00SAnthony Liguori static int local_rename(FsContext *ctx, const char *oldpath, 8868cf89e00SAnthony Liguori const char *newpath) 8878cf89e00SAnthony Liguori { 8882c30dd74SAneesh Kumar K.V int err; 8894fa4ce71SChen Gang char *buffer, *buffer1; 8908cf89e00SAnthony Liguori 8912c30dd74SAneesh Kumar K.V if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 8922c30dd74SAneesh Kumar K.V err = local_create_mapped_attr_dir(ctx, newpath); 8932c30dd74SAneesh Kumar K.V if (err < 0) { 8942c30dd74SAneesh Kumar K.V return err; 8952c30dd74SAneesh Kumar K.V } 8962c30dd74SAneesh Kumar K.V /* rename the .virtfs_metadata files */ 8974fa4ce71SChen Gang buffer = local_mapped_attr_path(ctx, oldpath); 8984fa4ce71SChen Gang buffer1 = local_mapped_attr_path(ctx, newpath); 8994fa4ce71SChen Gang err = rename(buffer, buffer1); 9004fa4ce71SChen Gang g_free(buffer); 9014fa4ce71SChen Gang g_free(buffer1); 9022c30dd74SAneesh Kumar K.V if (err < 0 && errno != ENOENT) { 9032c30dd74SAneesh Kumar K.V return err; 9042c30dd74SAneesh Kumar K.V } 9052c30dd74SAneesh Kumar K.V } 9064fa4ce71SChen Gang 9074fa4ce71SChen Gang buffer = rpath(ctx, oldpath); 9084fa4ce71SChen Gang buffer1 = rpath(ctx, newpath); 9094fa4ce71SChen Gang err = rename(buffer, buffer1); 9104fa4ce71SChen Gang g_free(buffer); 9114fa4ce71SChen Gang g_free(buffer1); 9124fa4ce71SChen Gang return err; 9138cf89e00SAnthony Liguori } 9148cf89e00SAnthony Liguori 9152289be19SAneesh Kumar K.V static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp) 9168cf89e00SAnthony Liguori { 9174fa4ce71SChen Gang char *buffer; 9184fa4ce71SChen Gang int ret = -1; 9192289be19SAneesh Kumar K.V char *path = fs_path->data; 9202289be19SAneesh Kumar K.V 921c79ce737SSripathi Kodi if ((credp->fc_uid == -1 && credp->fc_gid == -1) || 92217b1971fSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 92317b1971fSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 9244fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 9254fa4ce71SChen Gang ret = lchown(buffer, credp->fc_uid, credp->fc_gid); 9264fa4ce71SChen Gang g_free(buffer); 927b97400caSAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 9284fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 9294fa4ce71SChen Gang ret = local_set_xattr(buffer, credp); 9304fa4ce71SChen Gang g_free(buffer); 9312c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 9322c30dd74SAneesh Kumar K.V return local_set_mapped_file_attr(fs_ctx, path, credp); 933f7613beeSVenkateswararao Jujjuri (JV) } 9344fa4ce71SChen Gang return ret; 9358cf89e00SAnthony Liguori } 9368cf89e00SAnthony Liguori 9372289be19SAneesh Kumar K.V static int local_utimensat(FsContext *s, V9fsPath *fs_path, 93874bc02b2SM. Mohan Kumar const struct timespec *buf) 9398cf89e00SAnthony Liguori { 9404fa4ce71SChen Gang char *buffer; 9414fa4ce71SChen Gang int ret; 9422289be19SAneesh Kumar K.V char *path = fs_path->data; 9432289be19SAneesh Kumar K.V 9444fa4ce71SChen Gang buffer = rpath(s, path); 9454fa4ce71SChen Gang ret = qemu_utimens(buffer, buf); 9464fa4ce71SChen Gang g_free(buffer); 9474fa4ce71SChen Gang return ret; 9488cf89e00SAnthony Liguori } 9498cf89e00SAnthony Liguori 9505bae1900SAnthony Liguori static int local_remove(FsContext *ctx, const char *path) 9515bae1900SAnthony Liguori { 9522c30dd74SAneesh Kumar K.V int err; 9532c30dd74SAneesh Kumar K.V struct stat stbuf; 9544fa4ce71SChen Gang char *buffer; 9552c30dd74SAneesh Kumar K.V 9562c30dd74SAneesh Kumar K.V if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 9574fa4ce71SChen Gang buffer = rpath(ctx, path); 9584fa4ce71SChen Gang err = lstat(buffer, &stbuf); 9594fa4ce71SChen Gang g_free(buffer); 9602c30dd74SAneesh Kumar K.V if (err) { 9612c30dd74SAneesh Kumar K.V goto err_out; 9622c30dd74SAneesh Kumar K.V } 9632c30dd74SAneesh Kumar K.V /* 9642c30dd74SAneesh Kumar K.V * If directory remove .virtfs_metadata contained in the 9652c30dd74SAneesh Kumar K.V * directory 9662c30dd74SAneesh Kumar K.V */ 9672c30dd74SAneesh Kumar K.V if (S_ISDIR(stbuf.st_mode)) { 9684fa4ce71SChen Gang buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, 9694fa4ce71SChen Gang path, VIRTFS_META_DIR); 9702c30dd74SAneesh Kumar K.V err = remove(buffer); 9714fa4ce71SChen Gang g_free(buffer); 9722c30dd74SAneesh Kumar K.V if (err < 0 && errno != ENOENT) { 9732c30dd74SAneesh Kumar K.V /* 9742c30dd74SAneesh Kumar K.V * We didn't had the .virtfs_metadata file. May be file created 9752c30dd74SAneesh Kumar K.V * in non-mapped mode ?. Ignore ENOENT. 9762c30dd74SAneesh Kumar K.V */ 9772c30dd74SAneesh Kumar K.V goto err_out; 9782c30dd74SAneesh Kumar K.V } 9792c30dd74SAneesh Kumar K.V } 9802c30dd74SAneesh Kumar K.V /* 9812c30dd74SAneesh Kumar K.V * Now remove the name from parent directory 9822c30dd74SAneesh Kumar K.V * .virtfs_metadata directory 9832c30dd74SAneesh Kumar K.V */ 9844fa4ce71SChen Gang buffer = local_mapped_attr_path(ctx, path); 9854fa4ce71SChen Gang err = remove(buffer); 9864fa4ce71SChen Gang g_free(buffer); 9872c30dd74SAneesh Kumar K.V if (err < 0 && errno != ENOENT) { 9882c30dd74SAneesh Kumar K.V /* 9892c30dd74SAneesh Kumar K.V * We didn't had the .virtfs_metadata file. May be file created 9902c30dd74SAneesh Kumar K.V * in non-mapped mode ?. Ignore ENOENT. 9912c30dd74SAneesh Kumar K.V */ 9922c30dd74SAneesh Kumar K.V goto err_out; 9932c30dd74SAneesh Kumar K.V } 9942c30dd74SAneesh Kumar K.V } 9954fa4ce71SChen Gang 9964fa4ce71SChen Gang buffer = rpath(ctx, path); 9974fa4ce71SChen Gang err = remove(buffer); 9984fa4ce71SChen Gang g_free(buffer); 9992c30dd74SAneesh Kumar K.V err_out: 10002c30dd74SAneesh Kumar K.V return err; 10015bae1900SAnthony Liguori } 10025bae1900SAnthony Liguori 10038b888272SAneesh Kumar K.V static int local_fsync(FsContext *ctx, int fid_type, 10048b888272SAneesh Kumar K.V V9fsFidOpenState *fs, int datasync) 10058cf89e00SAnthony Liguori { 10068b888272SAneesh Kumar K.V int fd; 10078b888272SAneesh Kumar K.V 10088b888272SAneesh Kumar K.V if (fid_type == P9_FID_DIR) { 1009f314ea4eSGreg Kurz fd = dirfd(fs->dir.stream); 101049594973SVenkateswararao Jujjuri (JV) } else { 10118b888272SAneesh Kumar K.V fd = fs->fd; 10128b888272SAneesh Kumar K.V } 10138b888272SAneesh Kumar K.V 10148b888272SAneesh Kumar K.V if (datasync) { 10158b888272SAneesh Kumar K.V return qemu_fdatasync(fd); 10168b888272SAneesh Kumar K.V } else { 10178b888272SAneesh Kumar K.V return fsync(fd); 10188cf89e00SAnthony Liguori } 101949594973SVenkateswararao Jujjuri (JV) } 10208cf89e00SAnthony Liguori 10212289be19SAneesh Kumar K.V static int local_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf) 1022be940c87SM. Mohan Kumar { 10234fa4ce71SChen Gang char *buffer; 10244fa4ce71SChen Gang int ret; 10252289be19SAneesh Kumar K.V char *path = fs_path->data; 10262289be19SAneesh Kumar K.V 10274fa4ce71SChen Gang buffer = rpath(s, path); 10284fa4ce71SChen Gang ret = statfs(buffer, stbuf); 10294fa4ce71SChen Gang g_free(buffer); 10304fa4ce71SChen Gang return ret; 1031be940c87SM. Mohan Kumar } 1032be940c87SM. Mohan Kumar 10332289be19SAneesh Kumar K.V static ssize_t local_lgetxattr(FsContext *ctx, V9fsPath *fs_path, 1034fa32ef88SAneesh Kumar K.V const char *name, void *value, size_t size) 1035fa32ef88SAneesh Kumar K.V { 10362289be19SAneesh Kumar K.V char *path = fs_path->data; 10372289be19SAneesh Kumar K.V 1038fc22118dSAneesh Kumar K.V return v9fs_get_xattr(ctx, path, name, value, size); 1039fa32ef88SAneesh Kumar K.V } 1040fa32ef88SAneesh Kumar K.V 10412289be19SAneesh Kumar K.V static ssize_t local_llistxattr(FsContext *ctx, V9fsPath *fs_path, 1042fa32ef88SAneesh Kumar K.V void *value, size_t size) 1043fa32ef88SAneesh Kumar K.V { 10442289be19SAneesh Kumar K.V char *path = fs_path->data; 10452289be19SAneesh Kumar K.V 1046fc22118dSAneesh Kumar K.V return v9fs_list_xattr(ctx, path, value, size); 104761b6c499SAneesh Kumar K.V } 104861b6c499SAneesh Kumar K.V 10492289be19SAneesh Kumar K.V static int local_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name, 105010b468bdSAneesh Kumar K.V void *value, size_t size, int flags) 105110b468bdSAneesh Kumar K.V { 10522289be19SAneesh Kumar K.V char *path = fs_path->data; 10532289be19SAneesh Kumar K.V 1054fc22118dSAneesh Kumar K.V return v9fs_set_xattr(ctx, path, name, value, size, flags); 105510b468bdSAneesh Kumar K.V } 105610b468bdSAneesh Kumar K.V 10572289be19SAneesh Kumar K.V static int local_lremovexattr(FsContext *ctx, V9fsPath *fs_path, 10582289be19SAneesh Kumar K.V const char *name) 10599ed3ef26SAneesh Kumar K.V { 10602289be19SAneesh Kumar K.V char *path = fs_path->data; 10612289be19SAneesh Kumar K.V 1062fc22118dSAneesh Kumar K.V return v9fs_remove_xattr(ctx, path, name); 10639ed3ef26SAneesh Kumar K.V } 10649ed3ef26SAneesh Kumar K.V 10652289be19SAneesh Kumar K.V static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path, 10662289be19SAneesh Kumar K.V const char *name, V9fsPath *target) 10672289be19SAneesh Kumar K.V { 10682289be19SAneesh Kumar K.V if (dir_path) { 1069e3e83f2eSGreg Kurz v9fs_path_sprintf(target, "%s/%s", dir_path->data, name); 10702289be19SAneesh Kumar K.V } else { 1071e3e83f2eSGreg Kurz v9fs_path_sprintf(target, "%s", name); 10722289be19SAneesh Kumar K.V } 10732289be19SAneesh Kumar K.V return 0; 10742289be19SAneesh Kumar K.V } 10752289be19SAneesh Kumar K.V 10762289be19SAneesh Kumar K.V static int local_renameat(FsContext *ctx, V9fsPath *olddir, 10772289be19SAneesh Kumar K.V const char *old_name, V9fsPath *newdir, 10782289be19SAneesh Kumar K.V const char *new_name) 10792289be19SAneesh Kumar K.V { 10802289be19SAneesh Kumar K.V int ret; 10812289be19SAneesh Kumar K.V V9fsString old_full_name, new_full_name; 10822289be19SAneesh Kumar K.V 10832289be19SAneesh Kumar K.V v9fs_string_init(&old_full_name); 10842289be19SAneesh Kumar K.V v9fs_string_init(&new_full_name); 10852289be19SAneesh Kumar K.V 10862289be19SAneesh Kumar K.V v9fs_string_sprintf(&old_full_name, "%s/%s", olddir->data, old_name); 10872289be19SAneesh Kumar K.V v9fs_string_sprintf(&new_full_name, "%s/%s", newdir->data, new_name); 10882289be19SAneesh Kumar K.V 10892289be19SAneesh Kumar K.V ret = local_rename(ctx, old_full_name.data, new_full_name.data); 10902289be19SAneesh Kumar K.V v9fs_string_free(&old_full_name); 10912289be19SAneesh Kumar K.V v9fs_string_free(&new_full_name); 10922289be19SAneesh Kumar K.V return ret; 10932289be19SAneesh Kumar K.V } 10942289be19SAneesh Kumar K.V 10952289be19SAneesh Kumar K.V static int local_unlinkat(FsContext *ctx, V9fsPath *dir, 10962289be19SAneesh Kumar K.V const char *name, int flags) 10972289be19SAneesh Kumar K.V { 10982289be19SAneesh Kumar K.V int ret; 10992289be19SAneesh Kumar K.V V9fsString fullname; 11004fa4ce71SChen Gang char *buffer; 11012c30dd74SAneesh Kumar K.V 11022289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 11032289be19SAneesh Kumar K.V 11042289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name); 11052c30dd74SAneesh Kumar K.V if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 11062c30dd74SAneesh Kumar K.V if (flags == AT_REMOVEDIR) { 11072c30dd74SAneesh Kumar K.V /* 11082c30dd74SAneesh Kumar K.V * If directory remove .virtfs_metadata contained in the 11092c30dd74SAneesh Kumar K.V * directory 11102c30dd74SAneesh Kumar K.V */ 11114fa4ce71SChen Gang buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, 11122c30dd74SAneesh Kumar K.V fullname.data, VIRTFS_META_DIR); 11132c30dd74SAneesh Kumar K.V ret = remove(buffer); 11144fa4ce71SChen Gang g_free(buffer); 11152c30dd74SAneesh Kumar K.V if (ret < 0 && errno != ENOENT) { 11162c30dd74SAneesh Kumar K.V /* 11172c30dd74SAneesh Kumar K.V * We didn't had the .virtfs_metadata file. May be file created 11182c30dd74SAneesh Kumar K.V * in non-mapped mode ?. Ignore ENOENT. 11192c30dd74SAneesh Kumar K.V */ 11202c30dd74SAneesh Kumar K.V goto err_out; 11212c30dd74SAneesh Kumar K.V } 11222c30dd74SAneesh Kumar K.V } 11232c30dd74SAneesh Kumar K.V /* 11242c30dd74SAneesh Kumar K.V * Now remove the name from parent directory 11252c30dd74SAneesh Kumar K.V * .virtfs_metadata directory. 11262c30dd74SAneesh Kumar K.V */ 11274fa4ce71SChen Gang buffer = local_mapped_attr_path(ctx, fullname.data); 11284fa4ce71SChen Gang ret = remove(buffer); 11294fa4ce71SChen Gang g_free(buffer); 11302c30dd74SAneesh Kumar K.V if (ret < 0 && errno != ENOENT) { 11312c30dd74SAneesh Kumar K.V /* 11322c30dd74SAneesh Kumar K.V * We didn't had the .virtfs_metadata file. May be file created 11332c30dd74SAneesh Kumar K.V * in non-mapped mode ?. Ignore ENOENT. 11342c30dd74SAneesh Kumar K.V */ 11352c30dd74SAneesh Kumar K.V goto err_out; 11362c30dd74SAneesh Kumar K.V } 11372c30dd74SAneesh Kumar K.V } 11382c30dd74SAneesh Kumar K.V /* Remove the name finally */ 11394fa4ce71SChen Gang buffer = rpath(ctx, fullname.data); 11404fa4ce71SChen Gang ret = remove(buffer); 11414fa4ce71SChen Gang g_free(buffer); 11422289be19SAneesh Kumar K.V 11432c30dd74SAneesh Kumar K.V err_out: 114475b7931eSChen Gang v9fs_string_free(&fullname); 11452289be19SAneesh Kumar K.V return ret; 11462289be19SAneesh Kumar K.V } 11479ed3ef26SAneesh Kumar K.V 1148e06a765eSHarsh Prateek Bora static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, 1149e06a765eSHarsh Prateek Bora mode_t st_mode, uint64_t *st_gen) 1150e06a765eSHarsh Prateek Bora { 1151ae0f940eSPaolo Bonzini #ifdef FS_IOC_GETVERSION 11520e5fc994SKirill A. Shutemov int err; 1153cc720ddbSAneesh Kumar K.V V9fsFidOpenState fid_open; 1154cc720ddbSAneesh Kumar K.V 1155e06a765eSHarsh Prateek Bora /* 1156e06a765eSHarsh Prateek Bora * Do not try to open special files like device nodes, fifos etc 1157e06a765eSHarsh Prateek Bora * We can get fd for regular files and directories only 1158e06a765eSHarsh Prateek Bora */ 1159e06a765eSHarsh Prateek Bora if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) { 11601a9978a5SKirill A. Shutemov errno = ENOTTY; 11611a9978a5SKirill A. Shutemov return -1; 1162e06a765eSHarsh Prateek Bora } 1163cc720ddbSAneesh Kumar K.V err = local_open(ctx, path, O_RDONLY, &fid_open); 1164cc720ddbSAneesh Kumar K.V if (err < 0) { 1165cc720ddbSAneesh Kumar K.V return err; 1166e06a765eSHarsh Prateek Bora } 1167cc720ddbSAneesh Kumar K.V err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen); 1168cc720ddbSAneesh Kumar K.V local_close(ctx, &fid_open); 1169e06a765eSHarsh Prateek Bora return err; 11700e5fc994SKirill A. Shutemov #else 11710e5fc994SKirill A. Shutemov errno = ENOTTY; 11720e5fc994SKirill A. Shutemov return -1; 11730e5fc994SKirill A. Shutemov #endif 1174e06a765eSHarsh Prateek Bora } 1175e06a765eSHarsh Prateek Bora 11760174fe73SAneesh Kumar K.V static int local_init(FsContext *ctx) 11770174fe73SAneesh Kumar K.V { 1178e06a765eSHarsh Prateek Bora struct statfs stbuf; 1179e06a765eSHarsh Prateek Bora 118000c90bd1SGreg Kurz #ifdef FS_IOC_GETVERSION 118100c90bd1SGreg Kurz /* 118200c90bd1SGreg Kurz * use ioc_getversion only if the ioctl is definied 118300c90bd1SGreg Kurz */ 118400c90bd1SGreg Kurz if (statfs(ctx->fs_root, &stbuf) < 0) { 118500c90bd1SGreg Kurz return -1; 118600c90bd1SGreg Kurz } 118700c90bd1SGreg Kurz switch (stbuf.f_type) { 118800c90bd1SGreg Kurz case EXT2_SUPER_MAGIC: 118900c90bd1SGreg Kurz case BTRFS_SUPER_MAGIC: 119000c90bd1SGreg Kurz case REISERFS_SUPER_MAGIC: 119100c90bd1SGreg Kurz case XFS_SUPER_MAGIC: 119200c90bd1SGreg Kurz ctx->exops.get_st_gen = local_ioc_getversion; 119300c90bd1SGreg Kurz break; 119400c90bd1SGreg Kurz } 119500c90bd1SGreg Kurz #endif 119600c90bd1SGreg Kurz 11972c30dd74SAneesh Kumar K.V if (ctx->export_flags & V9FS_SM_PASSTHROUGH) { 11982c30dd74SAneesh Kumar K.V ctx->xops = passthrough_xattr_ops; 11992c30dd74SAneesh Kumar K.V } else if (ctx->export_flags & V9FS_SM_MAPPED) { 12002c30dd74SAneesh Kumar K.V ctx->xops = mapped_xattr_ops; 12012c30dd74SAneesh Kumar K.V } else if (ctx->export_flags & V9FS_SM_NONE) { 12022c30dd74SAneesh Kumar K.V ctx->xops = none_xattr_ops; 12032c30dd74SAneesh Kumar K.V } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 12042c30dd74SAneesh Kumar K.V /* 12052c30dd74SAneesh Kumar K.V * xattr operation for mapped-file and passthrough 12062c30dd74SAneesh Kumar K.V * remain same. 12072c30dd74SAneesh Kumar K.V */ 12082c30dd74SAneesh Kumar K.V ctx->xops = passthrough_xattr_ops; 12092c30dd74SAneesh Kumar K.V } 1210c98f1d4aSAneesh Kumar K.V ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT; 121100c90bd1SGreg Kurz 121200c90bd1SGreg Kurz return 0; 12130174fe73SAneesh Kumar K.V } 12140174fe73SAneesh Kumar K.V 121599519f0aSAneesh Kumar K.V static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse) 121699519f0aSAneesh Kumar K.V { 121799519f0aSAneesh Kumar K.V const char *sec_model = qemu_opt_get(opts, "security_model"); 121899519f0aSAneesh Kumar K.V const char *path = qemu_opt_get(opts, "path"); 121999519f0aSAneesh Kumar K.V 122099519f0aSAneesh Kumar K.V if (!sec_model) { 122163325b18SGreg Kurz error_report("Security model not specified, local fs needs security model"); 122263325b18SGreg Kurz error_printf("valid options are:" 122363325b18SGreg Kurz "\tsecurity_model=[passthrough|mapped-xattr|mapped-file|none]\n"); 122499519f0aSAneesh Kumar K.V return -1; 122599519f0aSAneesh Kumar K.V } 122699519f0aSAneesh Kumar K.V 122799519f0aSAneesh Kumar K.V if (!strcmp(sec_model, "passthrough")) { 122899519f0aSAneesh Kumar K.V fse->export_flags |= V9FS_SM_PASSTHROUGH; 12292c30dd74SAneesh Kumar K.V } else if (!strcmp(sec_model, "mapped") || 12302c30dd74SAneesh Kumar K.V !strcmp(sec_model, "mapped-xattr")) { 123199519f0aSAneesh Kumar K.V fse->export_flags |= V9FS_SM_MAPPED; 123299519f0aSAneesh Kumar K.V } else if (!strcmp(sec_model, "none")) { 123399519f0aSAneesh Kumar K.V fse->export_flags |= V9FS_SM_NONE; 12342c30dd74SAneesh Kumar K.V } else if (!strcmp(sec_model, "mapped-file")) { 12352c30dd74SAneesh Kumar K.V fse->export_flags |= V9FS_SM_MAPPED_FILE; 123699519f0aSAneesh Kumar K.V } else { 123763325b18SGreg Kurz error_report("Invalid security model %s specified", sec_model); 123863325b18SGreg Kurz error_printf("valid options are:" 123963325b18SGreg Kurz "\t[passthrough|mapped-xattr|mapped-file|none]\n"); 124099519f0aSAneesh Kumar K.V return -1; 124199519f0aSAneesh Kumar K.V } 124299519f0aSAneesh Kumar K.V 124399519f0aSAneesh Kumar K.V if (!path) { 124463325b18SGreg Kurz error_report("fsdev: No path specified"); 124599519f0aSAneesh Kumar K.V return -1; 124699519f0aSAneesh Kumar K.V } 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