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 14ebe74f8bSWei Liu #include "9p.h" 15267ae092SWei Liu #include "9p-xattr.h" 1669b15212SStefan Weil #include "fsdev/qemu-fsdev.h" /* local_ops */ 17c494dd6fSAnthony Liguori #include <arpa/inet.h> 18131dcb25SAnthony Liguori #include <pwd.h> 19131dcb25SAnthony Liguori #include <grp.h> 20c494dd6fSAnthony Liguori #include <sys/socket.h> 21c494dd6fSAnthony Liguori #include <sys/un.h> 221de7afc9SPaolo Bonzini #include "qemu/xattr.h" 23*63325b18SGreg Kurz #include "qemu/error-report.h" 242c30dd74SAneesh Kumar K.V #include <libgen.h> 25e06a765eSHarsh Prateek Bora #include <linux/fs.h> 26e06a765eSHarsh Prateek Bora #ifdef CONFIG_LINUX_MAGIC_H 27e06a765eSHarsh Prateek Bora #include <linux/magic.h> 28e06a765eSHarsh Prateek Bora #endif 29e06a765eSHarsh Prateek Bora #include <sys/ioctl.h> 30e06a765eSHarsh Prateek Bora 31e06a765eSHarsh Prateek Bora #ifndef XFS_SUPER_MAGIC 32e06a765eSHarsh Prateek Bora #define XFS_SUPER_MAGIC 0x58465342 33e06a765eSHarsh Prateek Bora #endif 34e06a765eSHarsh Prateek Bora #ifndef EXT2_SUPER_MAGIC 35e06a765eSHarsh Prateek Bora #define EXT2_SUPER_MAGIC 0xEF53 36e06a765eSHarsh Prateek Bora #endif 37e06a765eSHarsh Prateek Bora #ifndef REISERFS_SUPER_MAGIC 38e06a765eSHarsh Prateek Bora #define REISERFS_SUPER_MAGIC 0x52654973 39e06a765eSHarsh Prateek Bora #endif 40e06a765eSHarsh Prateek Bora #ifndef BTRFS_SUPER_MAGIC 41e06a765eSHarsh Prateek Bora #define BTRFS_SUPER_MAGIC 0x9123683E 42e06a765eSHarsh Prateek Bora #endif 43131dcb25SAnthony Liguori 442c30dd74SAneesh Kumar K.V #define VIRTFS_META_DIR ".virtfs_metadata" 452c30dd74SAneesh Kumar K.V 464fa4ce71SChen Gang static char *local_mapped_attr_path(FsContext *ctx, const char *path) 472c30dd74SAneesh Kumar K.V { 481b6f85e2SMichael Tokarev int dirlen; 491b6f85e2SMichael Tokarev const char *name = strrchr(path, '/'); 501b6f85e2SMichael Tokarev if (name) { 511b6f85e2SMichael Tokarev dirlen = name - path; 521b6f85e2SMichael Tokarev ++name; 531b6f85e2SMichael Tokarev } else { 541b6f85e2SMichael Tokarev name = path; 551b6f85e2SMichael Tokarev dirlen = 0; 561b6f85e2SMichael Tokarev } 571b6f85e2SMichael Tokarev return g_strdup_printf("%s/%.*s/%s/%s", ctx->fs_root, 581b6f85e2SMichael Tokarev dirlen, path, VIRTFS_META_DIR, name); 592c30dd74SAneesh Kumar K.V } 602c30dd74SAneesh Kumar K.V 610ceb092eSAneesh Kumar K.V static FILE *local_fopen(const char *path, const char *mode) 620ceb092eSAneesh Kumar K.V { 630ceb092eSAneesh Kumar K.V int fd, o_mode = 0; 640ceb092eSAneesh Kumar K.V FILE *fp; 650ceb092eSAneesh Kumar K.V int flags = O_NOFOLLOW; 660ceb092eSAneesh Kumar K.V /* 670ceb092eSAneesh Kumar K.V * only supports two modes 680ceb092eSAneesh Kumar K.V */ 690ceb092eSAneesh Kumar K.V if (mode[0] == 'r') { 700ceb092eSAneesh Kumar K.V flags |= O_RDONLY; 710ceb092eSAneesh Kumar K.V } else if (mode[0] == 'w') { 720ceb092eSAneesh Kumar K.V flags |= O_WRONLY | O_TRUNC | O_CREAT; 730ceb092eSAneesh Kumar K.V o_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; 740ceb092eSAneesh Kumar K.V } else { 750ceb092eSAneesh Kumar K.V return NULL; 760ceb092eSAneesh Kumar K.V } 770ceb092eSAneesh Kumar K.V fd = open(path, flags, o_mode); 780ceb092eSAneesh Kumar K.V if (fd == -1) { 790ceb092eSAneesh Kumar K.V return NULL; 800ceb092eSAneesh Kumar K.V } 810ceb092eSAneesh Kumar K.V fp = fdopen(fd, mode); 820ceb092eSAneesh Kumar K.V if (!fp) { 830ceb092eSAneesh Kumar K.V close(fd); 840ceb092eSAneesh Kumar K.V } 850ceb092eSAneesh Kumar K.V return fp; 860ceb092eSAneesh Kumar K.V } 870ceb092eSAneesh Kumar K.V 882c30dd74SAneesh Kumar K.V #define ATTR_MAX 100 892c30dd74SAneesh Kumar K.V static void local_mapped_file_attr(FsContext *ctx, const char *path, 902c30dd74SAneesh Kumar K.V struct stat *stbuf) 912c30dd74SAneesh Kumar K.V { 922c30dd74SAneesh Kumar K.V FILE *fp; 932c30dd74SAneesh Kumar K.V char buf[ATTR_MAX]; 944fa4ce71SChen Gang char *attr_path; 952c30dd74SAneesh Kumar K.V 964fa4ce71SChen Gang attr_path = local_mapped_attr_path(ctx, path); 970ceb092eSAneesh Kumar K.V fp = local_fopen(attr_path, "r"); 984fa4ce71SChen Gang g_free(attr_path); 992c30dd74SAneesh Kumar K.V if (!fp) { 1002c30dd74SAneesh Kumar K.V return; 1012c30dd74SAneesh Kumar K.V } 1022c30dd74SAneesh Kumar K.V memset(buf, 0, ATTR_MAX); 1032c30dd74SAneesh Kumar K.V while (fgets(buf, ATTR_MAX, fp)) { 1042c30dd74SAneesh Kumar K.V if (!strncmp(buf, "virtfs.uid", 10)) { 1052c30dd74SAneesh Kumar K.V stbuf->st_uid = atoi(buf+11); 1062c30dd74SAneesh Kumar K.V } else if (!strncmp(buf, "virtfs.gid", 10)) { 1072c30dd74SAneesh Kumar K.V stbuf->st_gid = atoi(buf+11); 1082c30dd74SAneesh Kumar K.V } else if (!strncmp(buf, "virtfs.mode", 11)) { 1092c30dd74SAneesh Kumar K.V stbuf->st_mode = atoi(buf+12); 1102c30dd74SAneesh Kumar K.V } else if (!strncmp(buf, "virtfs.rdev", 11)) { 1112c30dd74SAneesh Kumar K.V stbuf->st_rdev = atoi(buf+12); 1122c30dd74SAneesh Kumar K.V } 1132c30dd74SAneesh Kumar K.V memset(buf, 0, ATTR_MAX); 1142c30dd74SAneesh Kumar K.V } 1152c30dd74SAneesh Kumar K.V fclose(fp); 1162c30dd74SAneesh Kumar K.V } 1172c30dd74SAneesh Kumar K.V 1182289be19SAneesh Kumar K.V static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf) 119131dcb25SAnthony Liguori { 1201237ad76SVenkateswararao Jujjuri (JV) int err; 1214fa4ce71SChen Gang char *buffer; 1222289be19SAneesh Kumar K.V char *path = fs_path->data; 1232289be19SAneesh Kumar K.V 1244fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 1254fa4ce71SChen Gang err = lstat(buffer, stbuf); 1261237ad76SVenkateswararao Jujjuri (JV) if (err) { 1274fa4ce71SChen Gang goto err_out; 1281237ad76SVenkateswararao Jujjuri (JV) } 129b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 1301237ad76SVenkateswararao Jujjuri (JV) /* Actual credentials are part of extended attrs */ 1311237ad76SVenkateswararao Jujjuri (JV) uid_t tmp_uid; 1321237ad76SVenkateswararao Jujjuri (JV) gid_t tmp_gid; 1331237ad76SVenkateswararao Jujjuri (JV) mode_t tmp_mode; 1341237ad76SVenkateswararao Jujjuri (JV) dev_t tmp_dev; 1354fa4ce71SChen Gang if (getxattr(buffer, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) { 136f8ad4a89SAneesh Kumar K.V stbuf->st_uid = le32_to_cpu(tmp_uid); 1371237ad76SVenkateswararao Jujjuri (JV) } 1384fa4ce71SChen Gang if (getxattr(buffer, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) { 139f8ad4a89SAneesh Kumar K.V stbuf->st_gid = le32_to_cpu(tmp_gid); 1401237ad76SVenkateswararao Jujjuri (JV) } 1414fa4ce71SChen Gang if (getxattr(buffer, "user.virtfs.mode", 142faa44e3dSVenkateswararao Jujjuri (JV) &tmp_mode, sizeof(mode_t)) > 0) { 143f8ad4a89SAneesh Kumar K.V stbuf->st_mode = le32_to_cpu(tmp_mode); 1441237ad76SVenkateswararao Jujjuri (JV) } 1454fa4ce71SChen Gang if (getxattr(buffer, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) { 146f8ad4a89SAneesh Kumar K.V stbuf->st_rdev = le64_to_cpu(tmp_dev); 1471237ad76SVenkateswararao Jujjuri (JV) } 1482c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 1492c30dd74SAneesh Kumar K.V local_mapped_file_attr(fs_ctx, path, stbuf); 1501237ad76SVenkateswararao Jujjuri (JV) } 1514fa4ce71SChen Gang 1524fa4ce71SChen Gang err_out: 1534fa4ce71SChen Gang g_free(buffer); 1541237ad76SVenkateswararao Jujjuri (JV) return err; 155131dcb25SAnthony Liguori } 156131dcb25SAnthony Liguori 1572c30dd74SAneesh Kumar K.V static int local_create_mapped_attr_dir(FsContext *ctx, const char *path) 1582c30dd74SAneesh Kumar K.V { 1592c30dd74SAneesh Kumar K.V int err; 1604fa4ce71SChen Gang char *attr_dir; 161d3f8e138SMarkus Armbruster char *tmp_path = g_strdup(path); 1622c30dd74SAneesh Kumar K.V 1634fa4ce71SChen Gang attr_dir = g_strdup_printf("%s/%s/%s", 1642c30dd74SAneesh Kumar K.V ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR); 1652c30dd74SAneesh Kumar K.V 1662c30dd74SAneesh Kumar K.V err = mkdir(attr_dir, 0700); 1672c30dd74SAneesh Kumar K.V if (err < 0 && errno == EEXIST) { 1682c30dd74SAneesh Kumar K.V err = 0; 1692c30dd74SAneesh Kumar K.V } 1704fa4ce71SChen Gang g_free(attr_dir); 171d3f8e138SMarkus Armbruster g_free(tmp_path); 1722c30dd74SAneesh Kumar K.V return err; 1732c30dd74SAneesh Kumar K.V } 1742c30dd74SAneesh Kumar K.V 1752c30dd74SAneesh Kumar K.V static int local_set_mapped_file_attr(FsContext *ctx, 1762c30dd74SAneesh Kumar K.V const char *path, FsCred *credp) 1772c30dd74SAneesh Kumar K.V { 1782c30dd74SAneesh Kumar K.V FILE *fp; 1792c30dd74SAneesh Kumar K.V int ret = 0; 1802c30dd74SAneesh Kumar K.V char buf[ATTR_MAX]; 1814fa4ce71SChen Gang char *attr_path; 1822c30dd74SAneesh Kumar K.V int uid = -1, gid = -1, mode = -1, rdev = -1; 1832c30dd74SAneesh Kumar K.V 1844fa4ce71SChen Gang attr_path = local_mapped_attr_path(ctx, path); 1854fa4ce71SChen Gang fp = local_fopen(attr_path, "r"); 1862c30dd74SAneesh Kumar K.V if (!fp) { 1872c30dd74SAneesh Kumar K.V goto create_map_file; 1882c30dd74SAneesh Kumar K.V } 1892c30dd74SAneesh Kumar K.V memset(buf, 0, ATTR_MAX); 1902c30dd74SAneesh Kumar K.V while (fgets(buf, ATTR_MAX, fp)) { 1912c30dd74SAneesh Kumar K.V if (!strncmp(buf, "virtfs.uid", 10)) { 1922c30dd74SAneesh Kumar K.V uid = atoi(buf+11); 1932c30dd74SAneesh Kumar K.V } else if (!strncmp(buf, "virtfs.gid", 10)) { 1942c30dd74SAneesh Kumar K.V gid = atoi(buf+11); 1952c30dd74SAneesh Kumar K.V } else if (!strncmp(buf, "virtfs.mode", 11)) { 1962c30dd74SAneesh Kumar K.V mode = atoi(buf+12); 1972c30dd74SAneesh Kumar K.V } else if (!strncmp(buf, "virtfs.rdev", 11)) { 1982c30dd74SAneesh Kumar K.V rdev = atoi(buf+12); 1992c30dd74SAneesh Kumar K.V } 2002c30dd74SAneesh Kumar K.V memset(buf, 0, ATTR_MAX); 2012c30dd74SAneesh Kumar K.V } 2022c30dd74SAneesh Kumar K.V fclose(fp); 2032c30dd74SAneesh Kumar K.V goto update_map_file; 2042c30dd74SAneesh Kumar K.V 2052c30dd74SAneesh Kumar K.V create_map_file: 2062c30dd74SAneesh Kumar K.V ret = local_create_mapped_attr_dir(ctx, path); 2072c30dd74SAneesh Kumar K.V if (ret < 0) { 2082c30dd74SAneesh Kumar K.V goto err_out; 2092c30dd74SAneesh Kumar K.V } 2102c30dd74SAneesh Kumar K.V 2112c30dd74SAneesh Kumar K.V update_map_file: 2120ceb092eSAneesh Kumar K.V fp = local_fopen(attr_path, "w"); 2132c30dd74SAneesh Kumar K.V if (!fp) { 2142c30dd74SAneesh Kumar K.V ret = -1; 2152c30dd74SAneesh Kumar K.V goto err_out; 2162c30dd74SAneesh Kumar K.V } 2172c30dd74SAneesh Kumar K.V 2182c30dd74SAneesh Kumar K.V if (credp->fc_uid != -1) { 2192c30dd74SAneesh Kumar K.V uid = credp->fc_uid; 2202c30dd74SAneesh Kumar K.V } 2212c30dd74SAneesh Kumar K.V if (credp->fc_gid != -1) { 2222c30dd74SAneesh Kumar K.V gid = credp->fc_gid; 2232c30dd74SAneesh Kumar K.V } 2242c30dd74SAneesh Kumar K.V if (credp->fc_mode != -1) { 2252c30dd74SAneesh Kumar K.V mode = credp->fc_mode; 2262c30dd74SAneesh Kumar K.V } 2272c30dd74SAneesh Kumar K.V if (credp->fc_rdev != -1) { 2282c30dd74SAneesh Kumar K.V rdev = credp->fc_rdev; 2292c30dd74SAneesh Kumar K.V } 2302c30dd74SAneesh Kumar K.V 2312c30dd74SAneesh Kumar K.V 2322c30dd74SAneesh Kumar K.V if (uid != -1) { 2332c30dd74SAneesh Kumar K.V fprintf(fp, "virtfs.uid=%d\n", uid); 2342c30dd74SAneesh Kumar K.V } 2352c30dd74SAneesh Kumar K.V if (gid != -1) { 2362c30dd74SAneesh Kumar K.V fprintf(fp, "virtfs.gid=%d\n", gid); 2372c30dd74SAneesh Kumar K.V } 2382c30dd74SAneesh Kumar K.V if (mode != -1) { 2392c30dd74SAneesh Kumar K.V fprintf(fp, "virtfs.mode=%d\n", mode); 2402c30dd74SAneesh Kumar K.V } 2412c30dd74SAneesh Kumar K.V if (rdev != -1) { 2422c30dd74SAneesh Kumar K.V fprintf(fp, "virtfs.rdev=%d\n", rdev); 2432c30dd74SAneesh Kumar K.V } 2442c30dd74SAneesh Kumar K.V fclose(fp); 2452c30dd74SAneesh Kumar K.V 2462c30dd74SAneesh Kumar K.V err_out: 2474fa4ce71SChen Gang g_free(attr_path); 2482c30dd74SAneesh Kumar K.V return ret; 2492c30dd74SAneesh Kumar K.V } 2502c30dd74SAneesh Kumar K.V 251758e8e38SVenkateswararao Jujjuri (JV) static int local_set_xattr(const char *path, FsCred *credp) 252131dcb25SAnthony Liguori { 253758e8e38SVenkateswararao Jujjuri (JV) int err; 2542289be19SAneesh Kumar K.V 255758e8e38SVenkateswararao Jujjuri (JV) if (credp->fc_uid != -1) { 256f8ad4a89SAneesh Kumar K.V uint32_t tmp_uid = cpu_to_le32(credp->fc_uid); 257f8ad4a89SAneesh Kumar K.V err = setxattr(path, "user.virtfs.uid", &tmp_uid, sizeof(uid_t), 0); 258758e8e38SVenkateswararao Jujjuri (JV) if (err) { 259758e8e38SVenkateswararao Jujjuri (JV) return err; 260131dcb25SAnthony Liguori } 261131dcb25SAnthony Liguori } 262758e8e38SVenkateswararao Jujjuri (JV) if (credp->fc_gid != -1) { 263f8ad4a89SAneesh Kumar K.V uint32_t tmp_gid = cpu_to_le32(credp->fc_gid); 264f8ad4a89SAneesh Kumar K.V err = setxattr(path, "user.virtfs.gid", &tmp_gid, sizeof(gid_t), 0); 265758e8e38SVenkateswararao Jujjuri (JV) if (err) { 266758e8e38SVenkateswararao Jujjuri (JV) return err; 267131dcb25SAnthony Liguori } 268131dcb25SAnthony Liguori } 269758e8e38SVenkateswararao Jujjuri (JV) if (credp->fc_mode != -1) { 270f8ad4a89SAneesh Kumar K.V uint32_t tmp_mode = cpu_to_le32(credp->fc_mode); 271f8ad4a89SAneesh Kumar K.V err = setxattr(path, "user.virtfs.mode", &tmp_mode, sizeof(mode_t), 0); 272758e8e38SVenkateswararao Jujjuri (JV) if (err) { 273758e8e38SVenkateswararao Jujjuri (JV) return err; 274131dcb25SAnthony Liguori } 275131dcb25SAnthony Liguori } 276758e8e38SVenkateswararao Jujjuri (JV) if (credp->fc_rdev != -1) { 277f8ad4a89SAneesh Kumar K.V uint64_t tmp_rdev = cpu_to_le64(credp->fc_rdev); 278f8ad4a89SAneesh Kumar K.V err = setxattr(path, "user.virtfs.rdev", &tmp_rdev, sizeof(dev_t), 0); 279758e8e38SVenkateswararao Jujjuri (JV) if (err) { 280758e8e38SVenkateswararao Jujjuri (JV) return err; 281131dcb25SAnthony Liguori } 282758e8e38SVenkateswararao Jujjuri (JV) } 283131dcb25SAnthony Liguori return 0; 284131dcb25SAnthony Liguori } 285131dcb25SAnthony Liguori 2864750a96fSVenkateswararao Jujjuri (JV) static int local_post_create_passthrough(FsContext *fs_ctx, const char *path, 2874750a96fSVenkateswararao Jujjuri (JV) FsCred *credp) 2884750a96fSVenkateswararao Jujjuri (JV) { 2894fa4ce71SChen Gang char *buffer; 2902289be19SAneesh Kumar K.V 2914fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 2924fa4ce71SChen Gang if (lchown(buffer, credp->fc_uid, credp->fc_gid) < 0) { 29312848bfcSAneesh Kumar K.V /* 29412848bfcSAneesh Kumar K.V * If we fail to change ownership and if we are 29512848bfcSAneesh Kumar K.V * using security model none. Ignore the error 29612848bfcSAneesh Kumar K.V */ 297b97400caSAneesh Kumar K.V if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) { 2984fa4ce71SChen Gang goto err; 2994750a96fSVenkateswararao Jujjuri (JV) } 30012848bfcSAneesh Kumar K.V } 3012d40564aSM. Mohan Kumar 3024fa4ce71SChen Gang if (chmod(buffer, credp->fc_mode & 07777) < 0) { 3034fa4ce71SChen Gang goto err; 3042d40564aSM. Mohan Kumar } 3054fa4ce71SChen Gang 3064fa4ce71SChen Gang g_free(buffer); 3074750a96fSVenkateswararao Jujjuri (JV) return 0; 3084fa4ce71SChen Gang err: 3094fa4ce71SChen Gang g_free(buffer); 3104fa4ce71SChen Gang return -1; 3114750a96fSVenkateswararao Jujjuri (JV) } 3124750a96fSVenkateswararao Jujjuri (JV) 3132289be19SAneesh Kumar K.V static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path, 314131dcb25SAnthony Liguori char *buf, size_t bufsz) 315131dcb25SAnthony Liguori { 316879c2813SVenkateswararao Jujjuri (JV) ssize_t tsize = -1; 3174fa4ce71SChen Gang char *buffer; 3182289be19SAneesh Kumar K.V char *path = fs_path->data; 3192289be19SAneesh Kumar K.V 3202c30dd74SAneesh Kumar K.V if ((fs_ctx->export_flags & V9FS_SM_MAPPED) || 3212c30dd74SAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) { 322879c2813SVenkateswararao Jujjuri (JV) int fd; 3234fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 3244fa4ce71SChen Gang fd = open(buffer, O_RDONLY | O_NOFOLLOW); 3254fa4ce71SChen Gang g_free(buffer); 326879c2813SVenkateswararao Jujjuri (JV) if (fd == -1) { 327879c2813SVenkateswararao Jujjuri (JV) return -1; 328879c2813SVenkateswararao Jujjuri (JV) } 329879c2813SVenkateswararao Jujjuri (JV) do { 330879c2813SVenkateswararao Jujjuri (JV) tsize = read(fd, (void *)buf, bufsz); 331879c2813SVenkateswararao Jujjuri (JV) } while (tsize == -1 && errno == EINTR); 332879c2813SVenkateswararao Jujjuri (JV) close(fd); 333b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 334b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 3354fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 3364fa4ce71SChen Gang tsize = readlink(buffer, buf, bufsz); 3374fa4ce71SChen Gang g_free(buffer); 338879c2813SVenkateswararao Jujjuri (JV) } 339879c2813SVenkateswararao Jujjuri (JV) return tsize; 340131dcb25SAnthony Liguori } 341131dcb25SAnthony Liguori 342cc720ddbSAneesh Kumar K.V static int local_close(FsContext *ctx, V9fsFidOpenState *fs) 343131dcb25SAnthony Liguori { 344cc720ddbSAneesh Kumar K.V return close(fs->fd); 345131dcb25SAnthony Liguori } 346131dcb25SAnthony Liguori 347cc720ddbSAneesh Kumar K.V static int local_closedir(FsContext *ctx, V9fsFidOpenState *fs) 348131dcb25SAnthony Liguori { 349cc720ddbSAneesh Kumar K.V return closedir(fs->dir); 350131dcb25SAnthony Liguori } 3519f107513SAnthony Liguori 352cc720ddbSAneesh Kumar K.V static int local_open(FsContext *ctx, V9fsPath *fs_path, 353cc720ddbSAneesh Kumar K.V int flags, V9fsFidOpenState *fs) 354a6568fe2SAnthony Liguori { 3554fa4ce71SChen Gang char *buffer; 3562289be19SAneesh Kumar K.V char *path = fs_path->data; 3572289be19SAneesh Kumar K.V 3584fa4ce71SChen Gang buffer = rpath(ctx, path); 3594fa4ce71SChen Gang fs->fd = open(buffer, flags | O_NOFOLLOW); 3604fa4ce71SChen Gang g_free(buffer); 361cc720ddbSAneesh Kumar K.V return fs->fd; 362a6568fe2SAnthony Liguori } 363a6568fe2SAnthony Liguori 364cc720ddbSAneesh Kumar K.V static int local_opendir(FsContext *ctx, 365cc720ddbSAneesh Kumar K.V V9fsPath *fs_path, V9fsFidOpenState *fs) 366a6568fe2SAnthony Liguori { 3674fa4ce71SChen Gang char *buffer; 3682289be19SAneesh Kumar K.V char *path = fs_path->data; 3692289be19SAneesh Kumar K.V 3704fa4ce71SChen Gang buffer = rpath(ctx, path); 3714fa4ce71SChen Gang fs->dir = opendir(buffer); 3724fa4ce71SChen Gang g_free(buffer); 373cc720ddbSAneesh Kumar K.V if (!fs->dir) { 374cc720ddbSAneesh Kumar K.V return -1; 375cc720ddbSAneesh Kumar K.V } 376cc720ddbSAneesh Kumar K.V return 0; 377a6568fe2SAnthony Liguori } 378a6568fe2SAnthony Liguori 379cc720ddbSAneesh Kumar K.V static void local_rewinddir(FsContext *ctx, V9fsFidOpenState *fs) 380a9231555SAnthony Liguori { 3810289a412SStefan Weil rewinddir(fs->dir); 382a9231555SAnthony Liguori } 383a9231555SAnthony Liguori 384cc720ddbSAneesh Kumar K.V static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs) 385a9231555SAnthony Liguori { 386cc720ddbSAneesh Kumar K.V return telldir(fs->dir); 387a9231555SAnthony Liguori } 388a9231555SAnthony Liguori 389cc720ddbSAneesh Kumar K.V static int local_readdir_r(FsContext *ctx, V9fsFidOpenState *fs, 390cc720ddbSAneesh Kumar K.V struct dirent *entry, 3915f524c1eSHarsh Prateek Bora struct dirent **result) 392a9231555SAnthony Liguori { 3932c30dd74SAneesh Kumar K.V int ret; 3942c30dd74SAneesh Kumar K.V 3952c30dd74SAneesh Kumar K.V again: 3962c30dd74SAneesh Kumar K.V ret = readdir_r(fs->dir, entry, result); 397840a1bf2SBastian Blank if (ctx->export_flags & V9FS_SM_MAPPED) { 398840a1bf2SBastian Blank entry->d_type = DT_UNKNOWN; 399840a1bf2SBastian Blank } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 4002c30dd74SAneesh Kumar K.V if (!ret && *result != NULL && 4012c30dd74SAneesh Kumar K.V !strcmp(entry->d_name, VIRTFS_META_DIR)) { 4022c30dd74SAneesh Kumar K.V /* skp the meta data directory */ 4032c30dd74SAneesh Kumar K.V goto again; 4042c30dd74SAneesh Kumar K.V } 405840a1bf2SBastian Blank entry->d_type = DT_UNKNOWN; 4062c30dd74SAneesh Kumar K.V } 4072c30dd74SAneesh Kumar K.V return ret; 408a9231555SAnthony Liguori } 409a9231555SAnthony Liguori 410cc720ddbSAneesh Kumar K.V static void local_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off) 411a9231555SAnthony Liguori { 4120289a412SStefan Weil seekdir(fs->dir, off); 413a9231555SAnthony Liguori } 414a9231555SAnthony Liguori 415cc720ddbSAneesh Kumar K.V static ssize_t local_preadv(FsContext *ctx, V9fsFidOpenState *fs, 416cc720ddbSAneesh Kumar K.V const struct iovec *iov, 41756d15a53SSanchit Garg int iovcnt, off_t offset) 418a9231555SAnthony Liguori { 41956d15a53SSanchit Garg #ifdef CONFIG_PREADV 420cc720ddbSAneesh Kumar K.V return preadv(fs->fd, iov, iovcnt, offset); 42156d15a53SSanchit Garg #else 422cc720ddbSAneesh Kumar K.V int err = lseek(fs->fd, offset, SEEK_SET); 42356d15a53SSanchit Garg if (err == -1) { 42456d15a53SSanchit Garg return err; 42556d15a53SSanchit Garg } else { 426cc720ddbSAneesh Kumar K.V return readv(fs->fd, iov, iovcnt); 427a9231555SAnthony Liguori } 42856d15a53SSanchit Garg #endif 429a9231555SAnthony Liguori } 430a9231555SAnthony Liguori 431cc720ddbSAneesh Kumar K.V static ssize_t local_pwritev(FsContext *ctx, V9fsFidOpenState *fs, 432cc720ddbSAneesh Kumar K.V const struct iovec *iov, 43356d15a53SSanchit Garg int iovcnt, off_t offset) 4348449360cSAnthony Liguori { 435d3ab98e6SAneesh Kumar K.V ssize_t ret 436d3ab98e6SAneesh Kumar K.V ; 43756d15a53SSanchit Garg #ifdef CONFIG_PREADV 438cc720ddbSAneesh Kumar K.V ret = pwritev(fs->fd, iov, iovcnt, offset); 43956d15a53SSanchit Garg #else 440cc720ddbSAneesh Kumar K.V int err = lseek(fs->fd, offset, SEEK_SET); 44156d15a53SSanchit Garg if (err == -1) { 44256d15a53SSanchit Garg return err; 44356d15a53SSanchit Garg } else { 444cc720ddbSAneesh Kumar K.V ret = writev(fs->fd, iov, iovcnt); 4458449360cSAnthony Liguori } 44656d15a53SSanchit Garg #endif 447d3ab98e6SAneesh Kumar K.V #ifdef CONFIG_SYNC_FILE_RANGE 448d3ab98e6SAneesh Kumar K.V if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) { 449d3ab98e6SAneesh Kumar K.V /* 450d3ab98e6SAneesh Kumar K.V * Initiate a writeback. This is not a data integrity sync. 451d3ab98e6SAneesh Kumar K.V * We want to ensure that we don't leave dirty pages in the cache 452d3ab98e6SAneesh Kumar K.V * after write when writeout=immediate is sepcified. 453d3ab98e6SAneesh Kumar K.V */ 454cc720ddbSAneesh Kumar K.V sync_file_range(fs->fd, offset, ret, 455d3ab98e6SAneesh Kumar K.V SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE); 456d3ab98e6SAneesh Kumar K.V } 457d3ab98e6SAneesh Kumar K.V #endif 458d3ab98e6SAneesh Kumar K.V return ret; 45956d15a53SSanchit Garg } 4608449360cSAnthony Liguori 4612289be19SAneesh Kumar K.V static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp) 462c494dd6fSAnthony Liguori { 4634fa4ce71SChen Gang char *buffer; 4644fa4ce71SChen Gang int ret = -1; 4652289be19SAneesh Kumar K.V char *path = fs_path->data; 4662289be19SAneesh Kumar K.V 467b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 4684fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 4694fa4ce71SChen Gang ret = local_set_xattr(buffer, credp); 4704fa4ce71SChen Gang g_free(buffer); 4712c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 4722c30dd74SAneesh Kumar K.V return local_set_mapped_file_attr(fs_ctx, path, credp); 473b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 474b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 4754fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 4764fa4ce71SChen Gang ret = chmod(buffer, credp->fc_mode); 4774fa4ce71SChen Gang g_free(buffer); 478e95ead32SVenkateswararao Jujjuri (JV) } 4794fa4ce71SChen Gang return ret; 480c494dd6fSAnthony Liguori } 481c494dd6fSAnthony Liguori 4822289be19SAneesh Kumar K.V static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path, 4832289be19SAneesh Kumar K.V const char *name, FsCred *credp) 484c494dd6fSAnthony Liguori { 4852289be19SAneesh Kumar K.V char *path; 4861c293312SVenkateswararao Jujjuri (JV) int err = -1; 4871c293312SVenkateswararao Jujjuri (JV) int serrno = 0; 4882289be19SAneesh Kumar K.V V9fsString fullname; 4894ed7b2c3SStefan Weil char *buffer = NULL; 4901c293312SVenkateswararao Jujjuri (JV) 4912289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 4922289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); 4932289be19SAneesh Kumar K.V path = fullname.data; 4942289be19SAneesh Kumar K.V 4951c293312SVenkateswararao Jujjuri (JV) /* Determine the security model */ 496b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 4974fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 4984fa4ce71SChen Gang err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0); 4991c293312SVenkateswararao Jujjuri (JV) if (err == -1) { 5002289be19SAneesh Kumar K.V goto out; 5011c293312SVenkateswararao Jujjuri (JV) } 5024fa4ce71SChen Gang err = local_set_xattr(buffer, credp); 5031c293312SVenkateswararao Jujjuri (JV) if (err == -1) { 5041c293312SVenkateswararao Jujjuri (JV) serrno = errno; 5051c293312SVenkateswararao Jujjuri (JV) goto err_end; 5061c293312SVenkateswararao Jujjuri (JV) } 5072c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 5082c30dd74SAneesh Kumar K.V 5094fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5104fa4ce71SChen Gang err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0); 5112c30dd74SAneesh Kumar K.V if (err == -1) { 5122c30dd74SAneesh Kumar K.V goto out; 5132c30dd74SAneesh Kumar K.V } 5142c30dd74SAneesh Kumar K.V err = local_set_mapped_file_attr(fs_ctx, path, credp); 5152c30dd74SAneesh Kumar K.V if (err == -1) { 5162c30dd74SAneesh Kumar K.V serrno = errno; 5172c30dd74SAneesh Kumar K.V goto err_end; 5182c30dd74SAneesh Kumar K.V } 519b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 520b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 5214fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5224fa4ce71SChen Gang err = mknod(buffer, credp->fc_mode, credp->fc_rdev); 5231c293312SVenkateswararao Jujjuri (JV) if (err == -1) { 5242289be19SAneesh Kumar K.V goto out; 5251c293312SVenkateswararao Jujjuri (JV) } 5261c293312SVenkateswararao Jujjuri (JV) err = local_post_create_passthrough(fs_ctx, path, credp); 5271c293312SVenkateswararao Jujjuri (JV) if (err == -1) { 5281c293312SVenkateswararao Jujjuri (JV) serrno = errno; 5291c293312SVenkateswararao Jujjuri (JV) goto err_end; 5301c293312SVenkateswararao Jujjuri (JV) } 5311c293312SVenkateswararao Jujjuri (JV) } 5322289be19SAneesh Kumar K.V goto out; 5331c293312SVenkateswararao Jujjuri (JV) 5341c293312SVenkateswararao Jujjuri (JV) err_end: 5354fa4ce71SChen Gang remove(buffer); 5361c293312SVenkateswararao Jujjuri (JV) errno = serrno; 5372289be19SAneesh Kumar K.V out: 5384ed7b2c3SStefan Weil g_free(buffer); 5392289be19SAneesh Kumar K.V v9fs_string_free(&fullname); 5401c293312SVenkateswararao Jujjuri (JV) return err; 541c494dd6fSAnthony Liguori } 542c494dd6fSAnthony Liguori 5432289be19SAneesh Kumar K.V static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path, 5442289be19SAneesh Kumar K.V const char *name, FsCred *credp) 545c494dd6fSAnthony Liguori { 5462289be19SAneesh Kumar K.V char *path; 54700ec5c37SVenkateswararao Jujjuri (JV) int err = -1; 54800ec5c37SVenkateswararao Jujjuri (JV) int serrno = 0; 5492289be19SAneesh Kumar K.V V9fsString fullname; 5504ed7b2c3SStefan Weil char *buffer = NULL; 55100ec5c37SVenkateswararao Jujjuri (JV) 5522289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 5532289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); 5542289be19SAneesh Kumar K.V path = fullname.data; 5552289be19SAneesh Kumar K.V 55600ec5c37SVenkateswararao Jujjuri (JV) /* Determine the security model */ 557b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 5584fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5594fa4ce71SChen Gang err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS); 56000ec5c37SVenkateswararao Jujjuri (JV) if (err == -1) { 5612289be19SAneesh Kumar K.V goto out; 56200ec5c37SVenkateswararao Jujjuri (JV) } 56300ec5c37SVenkateswararao Jujjuri (JV) credp->fc_mode = credp->fc_mode|S_IFDIR; 5644fa4ce71SChen Gang err = local_set_xattr(buffer, credp); 56500ec5c37SVenkateswararao Jujjuri (JV) if (err == -1) { 56600ec5c37SVenkateswararao Jujjuri (JV) serrno = errno; 56700ec5c37SVenkateswararao Jujjuri (JV) goto err_end; 56800ec5c37SVenkateswararao Jujjuri (JV) } 5692c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 5704fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5714fa4ce71SChen Gang err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS); 5722c30dd74SAneesh Kumar K.V if (err == -1) { 5732c30dd74SAneesh Kumar K.V goto out; 5742c30dd74SAneesh Kumar K.V } 5752c30dd74SAneesh Kumar K.V credp->fc_mode = credp->fc_mode|S_IFDIR; 5762c30dd74SAneesh Kumar K.V err = local_set_mapped_file_attr(fs_ctx, path, credp); 5772c30dd74SAneesh Kumar K.V if (err == -1) { 5782c30dd74SAneesh Kumar K.V serrno = errno; 5792c30dd74SAneesh Kumar K.V goto err_end; 5802c30dd74SAneesh Kumar K.V } 581b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 582b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 5834fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 5844fa4ce71SChen Gang err = mkdir(buffer, credp->fc_mode); 58500ec5c37SVenkateswararao Jujjuri (JV) if (err == -1) { 5862289be19SAneesh Kumar K.V goto out; 58700ec5c37SVenkateswararao Jujjuri (JV) } 58800ec5c37SVenkateswararao Jujjuri (JV) err = local_post_create_passthrough(fs_ctx, path, credp); 58900ec5c37SVenkateswararao Jujjuri (JV) if (err == -1) { 59000ec5c37SVenkateswararao Jujjuri (JV) serrno = errno; 59100ec5c37SVenkateswararao Jujjuri (JV) goto err_end; 59200ec5c37SVenkateswararao Jujjuri (JV) } 59300ec5c37SVenkateswararao Jujjuri (JV) } 5942289be19SAneesh Kumar K.V goto out; 59500ec5c37SVenkateswararao Jujjuri (JV) 59600ec5c37SVenkateswararao Jujjuri (JV) err_end: 5974fa4ce71SChen Gang remove(buffer); 59800ec5c37SVenkateswararao Jujjuri (JV) errno = serrno; 5992289be19SAneesh Kumar K.V out: 6004ed7b2c3SStefan Weil g_free(buffer); 6012289be19SAneesh Kumar K.V v9fs_string_free(&fullname); 60200ec5c37SVenkateswararao Jujjuri (JV) return err; 603c494dd6fSAnthony Liguori } 604c494dd6fSAnthony Liguori 6058b888272SAneesh Kumar K.V static int local_fstat(FsContext *fs_ctx, int fid_type, 606cc720ddbSAneesh Kumar K.V V9fsFidOpenState *fs, struct stat *stbuf) 607c494dd6fSAnthony Liguori { 6088b888272SAneesh Kumar K.V int err, fd; 6098b888272SAneesh Kumar K.V 6108b888272SAneesh Kumar K.V if (fid_type == P9_FID_DIR) { 6118b888272SAneesh Kumar K.V fd = dirfd(fs->dir); 6128b888272SAneesh Kumar K.V } else { 6138b888272SAneesh Kumar K.V fd = fs->fd; 6148b888272SAneesh Kumar K.V } 6158b888272SAneesh Kumar K.V 6168b888272SAneesh Kumar K.V err = fstat(fd, stbuf); 6171237ad76SVenkateswararao Jujjuri (JV) if (err) { 6181237ad76SVenkateswararao Jujjuri (JV) return err; 6191237ad76SVenkateswararao Jujjuri (JV) } 620b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 6211237ad76SVenkateswararao Jujjuri (JV) /* Actual credentials are part of extended attrs */ 6221237ad76SVenkateswararao Jujjuri (JV) uid_t tmp_uid; 6231237ad76SVenkateswararao Jujjuri (JV) gid_t tmp_gid; 6241237ad76SVenkateswararao Jujjuri (JV) mode_t tmp_mode; 6251237ad76SVenkateswararao Jujjuri (JV) dev_t tmp_dev; 6261237ad76SVenkateswararao Jujjuri (JV) 627f8ad4a89SAneesh Kumar K.V if (fgetxattr(fd, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) { 628f8ad4a89SAneesh Kumar K.V stbuf->st_uid = le32_to_cpu(tmp_uid); 6291237ad76SVenkateswararao Jujjuri (JV) } 630f8ad4a89SAneesh Kumar K.V if (fgetxattr(fd, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) { 631f8ad4a89SAneesh Kumar K.V stbuf->st_gid = le32_to_cpu(tmp_gid); 6321237ad76SVenkateswararao Jujjuri (JV) } 633f8ad4a89SAneesh Kumar K.V if (fgetxattr(fd, "user.virtfs.mode", &tmp_mode, sizeof(mode_t)) > 0) { 634f8ad4a89SAneesh Kumar K.V stbuf->st_mode = le32_to_cpu(tmp_mode); 6351237ad76SVenkateswararao Jujjuri (JV) } 636f8ad4a89SAneesh Kumar K.V if (fgetxattr(fd, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) { 637f8ad4a89SAneesh Kumar K.V stbuf->st_rdev = le64_to_cpu(tmp_dev); 6381237ad76SVenkateswararao Jujjuri (JV) } 6392c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 6402c30dd74SAneesh Kumar K.V errno = EOPNOTSUPP; 6412c30dd74SAneesh Kumar K.V return -1; 6421237ad76SVenkateswararao Jujjuri (JV) } 6431237ad76SVenkateswararao Jujjuri (JV) return err; 644c494dd6fSAnthony Liguori } 645c494dd6fSAnthony Liguori 6462289be19SAneesh Kumar K.V static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, 647cc720ddbSAneesh Kumar K.V int flags, FsCred *credp, V9fsFidOpenState *fs) 648c494dd6fSAnthony Liguori { 6492289be19SAneesh Kumar K.V char *path; 6504750a96fSVenkateswararao Jujjuri (JV) int fd = -1; 6514750a96fSVenkateswararao Jujjuri (JV) int err = -1; 6524750a96fSVenkateswararao Jujjuri (JV) int serrno = 0; 6532289be19SAneesh Kumar K.V V9fsString fullname; 6544ed7b2c3SStefan Weil char *buffer = NULL; 6554750a96fSVenkateswararao Jujjuri (JV) 6560ceb092eSAneesh Kumar K.V /* 6570ceb092eSAneesh Kumar K.V * Mark all the open to not follow symlinks 6580ceb092eSAneesh Kumar K.V */ 6590ceb092eSAneesh Kumar K.V flags |= O_NOFOLLOW; 6600ceb092eSAneesh Kumar K.V 6612289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 6622289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); 6632289be19SAneesh Kumar K.V path = fullname.data; 6642289be19SAneesh Kumar K.V 6654750a96fSVenkateswararao Jujjuri (JV) /* Determine the security model */ 666b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 6674fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 6684fa4ce71SChen Gang fd = open(buffer, flags, SM_LOCAL_MODE_BITS); 6694750a96fSVenkateswararao Jujjuri (JV) if (fd == -1) { 6702289be19SAneesh Kumar K.V err = fd; 6712289be19SAneesh Kumar K.V goto out; 6724750a96fSVenkateswararao Jujjuri (JV) } 6734750a96fSVenkateswararao Jujjuri (JV) credp->fc_mode = credp->fc_mode|S_IFREG; 6744750a96fSVenkateswararao Jujjuri (JV) /* Set cleint credentials in xattr */ 6754fa4ce71SChen Gang err = local_set_xattr(buffer, credp); 6764750a96fSVenkateswararao Jujjuri (JV) if (err == -1) { 6774750a96fSVenkateswararao Jujjuri (JV) serrno = errno; 6784750a96fSVenkateswararao Jujjuri (JV) goto err_end; 6794750a96fSVenkateswararao Jujjuri (JV) } 6802c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 6814fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 6824fa4ce71SChen Gang fd = open(buffer, flags, SM_LOCAL_MODE_BITS); 6832c30dd74SAneesh Kumar K.V if (fd == -1) { 6842c30dd74SAneesh Kumar K.V err = fd; 6852c30dd74SAneesh Kumar K.V goto out; 6862c30dd74SAneesh Kumar K.V } 6872c30dd74SAneesh Kumar K.V credp->fc_mode = credp->fc_mode|S_IFREG; 6882c30dd74SAneesh Kumar K.V /* Set client credentials in .virtfs_metadata directory files */ 6892c30dd74SAneesh Kumar K.V err = local_set_mapped_file_attr(fs_ctx, path, credp); 6902c30dd74SAneesh Kumar K.V if (err == -1) { 6912c30dd74SAneesh Kumar K.V serrno = errno; 6922c30dd74SAneesh Kumar K.V goto err_end; 6932c30dd74SAneesh Kumar K.V } 694b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 695b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 6964fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 6974fa4ce71SChen Gang fd = open(buffer, flags, credp->fc_mode); 6984750a96fSVenkateswararao Jujjuri (JV) if (fd == -1) { 6992289be19SAneesh Kumar K.V err = fd; 7002289be19SAneesh Kumar K.V goto out; 7014750a96fSVenkateswararao Jujjuri (JV) } 7024750a96fSVenkateswararao Jujjuri (JV) err = local_post_create_passthrough(fs_ctx, path, credp); 7034750a96fSVenkateswararao Jujjuri (JV) if (err == -1) { 7044750a96fSVenkateswararao Jujjuri (JV) serrno = errno; 7054750a96fSVenkateswararao Jujjuri (JV) goto err_end; 7064750a96fSVenkateswararao Jujjuri (JV) } 7074750a96fSVenkateswararao Jujjuri (JV) } 7082289be19SAneesh Kumar K.V err = fd; 709cc720ddbSAneesh Kumar K.V fs->fd = fd; 7102289be19SAneesh Kumar K.V goto out; 7114750a96fSVenkateswararao Jujjuri (JV) 7124750a96fSVenkateswararao Jujjuri (JV) err_end: 7134750a96fSVenkateswararao Jujjuri (JV) close(fd); 7144fa4ce71SChen Gang remove(buffer); 7154750a96fSVenkateswararao Jujjuri (JV) errno = serrno; 7162289be19SAneesh Kumar K.V out: 7174ed7b2c3SStefan Weil g_free(buffer); 7182289be19SAneesh Kumar K.V v9fs_string_free(&fullname); 7194750a96fSVenkateswararao Jujjuri (JV) return err; 720c494dd6fSAnthony Liguori } 721c494dd6fSAnthony Liguori 722758e8e38SVenkateswararao Jujjuri (JV) 723879c2813SVenkateswararao Jujjuri (JV) static int local_symlink(FsContext *fs_ctx, const char *oldpath, 7242289be19SAneesh Kumar K.V V9fsPath *dir_path, const char *name, FsCred *credp) 725c494dd6fSAnthony Liguori { 726879c2813SVenkateswararao Jujjuri (JV) int err = -1; 727879c2813SVenkateswararao Jujjuri (JV) int serrno = 0; 7282289be19SAneesh Kumar K.V char *newpath; 7292289be19SAneesh Kumar K.V V9fsString fullname; 7304ed7b2c3SStefan Weil char *buffer = NULL; 731879c2813SVenkateswararao Jujjuri (JV) 7322289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 7332289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); 7342289be19SAneesh Kumar K.V newpath = fullname.data; 7352289be19SAneesh Kumar K.V 736879c2813SVenkateswararao Jujjuri (JV) /* Determine the security model */ 737b97400caSAneesh Kumar K.V if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 738879c2813SVenkateswararao Jujjuri (JV) int fd; 739879c2813SVenkateswararao Jujjuri (JV) ssize_t oldpath_size, write_size; 7404fa4ce71SChen Gang buffer = rpath(fs_ctx, newpath); 7414fa4ce71SChen Gang fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS); 742879c2813SVenkateswararao Jujjuri (JV) if (fd == -1) { 7432289be19SAneesh Kumar K.V err = fd; 7442289be19SAneesh Kumar K.V goto out; 745879c2813SVenkateswararao Jujjuri (JV) } 746879c2813SVenkateswararao Jujjuri (JV) /* Write the oldpath (target) to the file. */ 747f35bde2fSHarsh Prateek Bora oldpath_size = strlen(oldpath); 748879c2813SVenkateswararao Jujjuri (JV) do { 749879c2813SVenkateswararao Jujjuri (JV) write_size = write(fd, (void *)oldpath, oldpath_size); 750879c2813SVenkateswararao Jujjuri (JV) } while (write_size == -1 && errno == EINTR); 751879c2813SVenkateswararao Jujjuri (JV) 752879c2813SVenkateswararao Jujjuri (JV) if (write_size != oldpath_size) { 753879c2813SVenkateswararao Jujjuri (JV) serrno = errno; 754879c2813SVenkateswararao Jujjuri (JV) close(fd); 755879c2813SVenkateswararao Jujjuri (JV) err = -1; 756879c2813SVenkateswararao Jujjuri (JV) goto err_end; 757879c2813SVenkateswararao Jujjuri (JV) } 758879c2813SVenkateswararao Jujjuri (JV) close(fd); 759879c2813SVenkateswararao Jujjuri (JV) /* Set cleint credentials in symlink's xattr */ 760879c2813SVenkateswararao Jujjuri (JV) credp->fc_mode = credp->fc_mode|S_IFLNK; 7614fa4ce71SChen Gang err = local_set_xattr(buffer, credp); 762879c2813SVenkateswararao Jujjuri (JV) if (err == -1) { 763879c2813SVenkateswararao Jujjuri (JV) serrno = errno; 764879c2813SVenkateswararao Jujjuri (JV) goto err_end; 765879c2813SVenkateswararao Jujjuri (JV) } 7662c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 7672c30dd74SAneesh Kumar K.V int fd; 7682c30dd74SAneesh Kumar K.V ssize_t oldpath_size, write_size; 7694fa4ce71SChen Gang buffer = rpath(fs_ctx, newpath); 7704fa4ce71SChen Gang fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS); 7712c30dd74SAneesh Kumar K.V if (fd == -1) { 7722c30dd74SAneesh Kumar K.V err = fd; 7732c30dd74SAneesh Kumar K.V goto out; 7742c30dd74SAneesh Kumar K.V } 7752c30dd74SAneesh Kumar K.V /* Write the oldpath (target) to the file. */ 7762c30dd74SAneesh Kumar K.V oldpath_size = strlen(oldpath); 7772c30dd74SAneesh Kumar K.V do { 7782c30dd74SAneesh Kumar K.V write_size = write(fd, (void *)oldpath, oldpath_size); 7792c30dd74SAneesh Kumar K.V } while (write_size == -1 && errno == EINTR); 7802c30dd74SAneesh Kumar K.V 7812c30dd74SAneesh Kumar K.V if (write_size != oldpath_size) { 7822c30dd74SAneesh Kumar K.V serrno = errno; 7832c30dd74SAneesh Kumar K.V close(fd); 7842c30dd74SAneesh Kumar K.V err = -1; 7852c30dd74SAneesh Kumar K.V goto err_end; 7862c30dd74SAneesh Kumar K.V } 7872c30dd74SAneesh Kumar K.V close(fd); 7882c30dd74SAneesh Kumar K.V /* Set cleint credentials in symlink's xattr */ 7892c30dd74SAneesh Kumar K.V credp->fc_mode = credp->fc_mode|S_IFLNK; 7902c30dd74SAneesh Kumar K.V err = local_set_mapped_file_attr(fs_ctx, newpath, credp); 7912c30dd74SAneesh Kumar K.V if (err == -1) { 7922c30dd74SAneesh Kumar K.V serrno = errno; 7932c30dd74SAneesh Kumar K.V goto err_end; 7942c30dd74SAneesh Kumar K.V } 795b97400caSAneesh Kumar K.V } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 796b97400caSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 7974fa4ce71SChen Gang buffer = rpath(fs_ctx, newpath); 7984fa4ce71SChen Gang err = symlink(oldpath, buffer); 799879c2813SVenkateswararao Jujjuri (JV) if (err) { 8002289be19SAneesh Kumar K.V goto out; 801879c2813SVenkateswararao Jujjuri (JV) } 8024fa4ce71SChen Gang err = lchown(buffer, credp->fc_uid, credp->fc_gid); 803879c2813SVenkateswararao Jujjuri (JV) if (err == -1) { 80412848bfcSAneesh Kumar K.V /* 80512848bfcSAneesh Kumar K.V * If we fail to change ownership and if we are 80612848bfcSAneesh Kumar K.V * using security model none. Ignore the error 80712848bfcSAneesh Kumar K.V */ 808b97400caSAneesh Kumar K.V if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) { 809879c2813SVenkateswararao Jujjuri (JV) serrno = errno; 810879c2813SVenkateswararao Jujjuri (JV) goto err_end; 81112848bfcSAneesh Kumar K.V } else 81212848bfcSAneesh Kumar K.V err = 0; 813879c2813SVenkateswararao Jujjuri (JV) } 814879c2813SVenkateswararao Jujjuri (JV) } 8152289be19SAneesh Kumar K.V goto out; 816879c2813SVenkateswararao Jujjuri (JV) 817879c2813SVenkateswararao Jujjuri (JV) err_end: 8184fa4ce71SChen Gang remove(buffer); 819879c2813SVenkateswararao Jujjuri (JV) errno = serrno; 8202289be19SAneesh Kumar K.V out: 8214ed7b2c3SStefan Weil g_free(buffer); 8222289be19SAneesh Kumar K.V v9fs_string_free(&fullname); 823879c2813SVenkateswararao Jujjuri (JV) return err; 824c494dd6fSAnthony Liguori } 825c494dd6fSAnthony Liguori 8262289be19SAneesh Kumar K.V static int local_link(FsContext *ctx, V9fsPath *oldpath, 8272289be19SAneesh Kumar K.V V9fsPath *dirpath, const char *name) 828c494dd6fSAnthony Liguori { 8292289be19SAneesh Kumar K.V int ret; 8302289be19SAneesh Kumar K.V V9fsString newpath; 8314fa4ce71SChen Gang char *buffer, *buffer1; 832c494dd6fSAnthony Liguori 8332289be19SAneesh Kumar K.V v9fs_string_init(&newpath); 8342289be19SAneesh Kumar K.V v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name); 8352289be19SAneesh Kumar K.V 8364fa4ce71SChen Gang buffer = rpath(ctx, oldpath->data); 8374fa4ce71SChen Gang buffer1 = rpath(ctx, newpath.data); 8384fa4ce71SChen Gang ret = link(buffer, buffer1); 8394fa4ce71SChen Gang g_free(buffer); 8404fa4ce71SChen Gang g_free(buffer1); 8412c30dd74SAneesh Kumar K.V 8422c30dd74SAneesh Kumar K.V /* now link the virtfs_metadata files */ 8432c30dd74SAneesh Kumar K.V if (!ret && (ctx->export_flags & V9FS_SM_MAPPED_FILE)) { 8442c30dd74SAneesh Kumar K.V /* Link the .virtfs_metadata files. Create the metada directory */ 8452c30dd74SAneesh Kumar K.V ret = local_create_mapped_attr_dir(ctx, newpath.data); 8462c30dd74SAneesh Kumar K.V if (ret < 0) { 8472c30dd74SAneesh Kumar K.V goto err_out; 8482c30dd74SAneesh Kumar K.V } 8494fa4ce71SChen Gang buffer = local_mapped_attr_path(ctx, oldpath->data); 8504fa4ce71SChen Gang buffer1 = local_mapped_attr_path(ctx, newpath.data); 8514fa4ce71SChen Gang ret = link(buffer, buffer1); 8524fa4ce71SChen Gang g_free(buffer); 8534fa4ce71SChen Gang g_free(buffer1); 8542c30dd74SAneesh Kumar K.V if (ret < 0 && errno != ENOENT) { 8552c30dd74SAneesh Kumar K.V goto err_out; 8562c30dd74SAneesh Kumar K.V } 8572c30dd74SAneesh Kumar K.V } 8582c30dd74SAneesh Kumar K.V err_out: 8592289be19SAneesh Kumar K.V v9fs_string_free(&newpath); 8602289be19SAneesh Kumar K.V return ret; 861c494dd6fSAnthony Liguori } 862c494dd6fSAnthony Liguori 8632289be19SAneesh Kumar K.V static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size) 8648cf89e00SAnthony Liguori { 8654fa4ce71SChen Gang char *buffer; 8664fa4ce71SChen Gang int ret; 8672289be19SAneesh Kumar K.V char *path = fs_path->data; 8682289be19SAneesh Kumar K.V 8694fa4ce71SChen Gang buffer = rpath(ctx, path); 8704fa4ce71SChen Gang ret = truncate(buffer, size); 8714fa4ce71SChen Gang g_free(buffer); 8724fa4ce71SChen Gang return ret; 8738cf89e00SAnthony Liguori } 8748cf89e00SAnthony Liguori 8758cf89e00SAnthony Liguori static int local_rename(FsContext *ctx, const char *oldpath, 8768cf89e00SAnthony Liguori const char *newpath) 8778cf89e00SAnthony Liguori { 8782c30dd74SAneesh Kumar K.V int err; 8794fa4ce71SChen Gang char *buffer, *buffer1; 8808cf89e00SAnthony Liguori 8812c30dd74SAneesh Kumar K.V if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 8822c30dd74SAneesh Kumar K.V err = local_create_mapped_attr_dir(ctx, newpath); 8832c30dd74SAneesh Kumar K.V if (err < 0) { 8842c30dd74SAneesh Kumar K.V return err; 8852c30dd74SAneesh Kumar K.V } 8862c30dd74SAneesh Kumar K.V /* rename the .virtfs_metadata files */ 8874fa4ce71SChen Gang buffer = local_mapped_attr_path(ctx, oldpath); 8884fa4ce71SChen Gang buffer1 = local_mapped_attr_path(ctx, newpath); 8894fa4ce71SChen Gang err = rename(buffer, buffer1); 8904fa4ce71SChen Gang g_free(buffer); 8914fa4ce71SChen Gang g_free(buffer1); 8922c30dd74SAneesh Kumar K.V if (err < 0 && errno != ENOENT) { 8932c30dd74SAneesh Kumar K.V return err; 8942c30dd74SAneesh Kumar K.V } 8952c30dd74SAneesh Kumar K.V } 8964fa4ce71SChen Gang 8974fa4ce71SChen Gang buffer = rpath(ctx, oldpath); 8984fa4ce71SChen Gang buffer1 = rpath(ctx, newpath); 8994fa4ce71SChen Gang err = rename(buffer, buffer1); 9004fa4ce71SChen Gang g_free(buffer); 9014fa4ce71SChen Gang g_free(buffer1); 9024fa4ce71SChen Gang return err; 9038cf89e00SAnthony Liguori } 9048cf89e00SAnthony Liguori 9052289be19SAneesh Kumar K.V static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp) 9068cf89e00SAnthony Liguori { 9074fa4ce71SChen Gang char *buffer; 9084fa4ce71SChen Gang int ret = -1; 9092289be19SAneesh Kumar K.V char *path = fs_path->data; 9102289be19SAneesh Kumar K.V 911c79ce737SSripathi Kodi if ((credp->fc_uid == -1 && credp->fc_gid == -1) || 91217b1971fSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || 91317b1971fSAneesh Kumar K.V (fs_ctx->export_flags & V9FS_SM_NONE)) { 9144fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 9154fa4ce71SChen Gang ret = lchown(buffer, credp->fc_uid, credp->fc_gid); 9164fa4ce71SChen Gang g_free(buffer); 917b97400caSAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED) { 9184fa4ce71SChen Gang buffer = rpath(fs_ctx, path); 9194fa4ce71SChen Gang ret = local_set_xattr(buffer, credp); 9204fa4ce71SChen Gang g_free(buffer); 9212c30dd74SAneesh Kumar K.V } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { 9222c30dd74SAneesh Kumar K.V return local_set_mapped_file_attr(fs_ctx, path, credp); 923f7613beeSVenkateswararao Jujjuri (JV) } 9244fa4ce71SChen Gang return ret; 9258cf89e00SAnthony Liguori } 9268cf89e00SAnthony Liguori 9272289be19SAneesh Kumar K.V static int local_utimensat(FsContext *s, V9fsPath *fs_path, 92874bc02b2SM. Mohan Kumar const struct timespec *buf) 9298cf89e00SAnthony Liguori { 9304fa4ce71SChen Gang char *buffer; 9314fa4ce71SChen Gang int ret; 9322289be19SAneesh Kumar K.V char *path = fs_path->data; 9332289be19SAneesh Kumar K.V 9344fa4ce71SChen Gang buffer = rpath(s, path); 9354fa4ce71SChen Gang ret = qemu_utimens(buffer, buf); 9364fa4ce71SChen Gang g_free(buffer); 9374fa4ce71SChen Gang return ret; 9388cf89e00SAnthony Liguori } 9398cf89e00SAnthony Liguori 9405bae1900SAnthony Liguori static int local_remove(FsContext *ctx, const char *path) 9415bae1900SAnthony Liguori { 9422c30dd74SAneesh Kumar K.V int err; 9432c30dd74SAneesh Kumar K.V struct stat stbuf; 9444fa4ce71SChen Gang char *buffer; 9452c30dd74SAneesh Kumar K.V 9462c30dd74SAneesh Kumar K.V if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 9474fa4ce71SChen Gang buffer = rpath(ctx, path); 9484fa4ce71SChen Gang err = lstat(buffer, &stbuf); 9494fa4ce71SChen Gang g_free(buffer); 9502c30dd74SAneesh Kumar K.V if (err) { 9512c30dd74SAneesh Kumar K.V goto err_out; 9522c30dd74SAneesh Kumar K.V } 9532c30dd74SAneesh Kumar K.V /* 9542c30dd74SAneesh Kumar K.V * If directory remove .virtfs_metadata contained in the 9552c30dd74SAneesh Kumar K.V * directory 9562c30dd74SAneesh Kumar K.V */ 9572c30dd74SAneesh Kumar K.V if (S_ISDIR(stbuf.st_mode)) { 9584fa4ce71SChen Gang buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, 9594fa4ce71SChen Gang path, VIRTFS_META_DIR); 9602c30dd74SAneesh Kumar K.V err = remove(buffer); 9614fa4ce71SChen Gang g_free(buffer); 9622c30dd74SAneesh Kumar K.V if (err < 0 && errno != ENOENT) { 9632c30dd74SAneesh Kumar K.V /* 9642c30dd74SAneesh Kumar K.V * We didn't had the .virtfs_metadata file. May be file created 9652c30dd74SAneesh Kumar K.V * in non-mapped mode ?. Ignore ENOENT. 9662c30dd74SAneesh Kumar K.V */ 9672c30dd74SAneesh Kumar K.V goto err_out; 9682c30dd74SAneesh Kumar K.V } 9692c30dd74SAneesh Kumar K.V } 9702c30dd74SAneesh Kumar K.V /* 9712c30dd74SAneesh Kumar K.V * Now remove the name from parent directory 9722c30dd74SAneesh Kumar K.V * .virtfs_metadata directory 9732c30dd74SAneesh Kumar K.V */ 9744fa4ce71SChen Gang buffer = local_mapped_attr_path(ctx, path); 9754fa4ce71SChen Gang err = remove(buffer); 9764fa4ce71SChen Gang g_free(buffer); 9772c30dd74SAneesh Kumar K.V if (err < 0 && errno != ENOENT) { 9782c30dd74SAneesh Kumar K.V /* 9792c30dd74SAneesh Kumar K.V * We didn't had the .virtfs_metadata file. May be file created 9802c30dd74SAneesh Kumar K.V * in non-mapped mode ?. Ignore ENOENT. 9812c30dd74SAneesh Kumar K.V */ 9822c30dd74SAneesh Kumar K.V goto err_out; 9832c30dd74SAneesh Kumar K.V } 9842c30dd74SAneesh Kumar K.V } 9854fa4ce71SChen Gang 9864fa4ce71SChen Gang buffer = rpath(ctx, path); 9874fa4ce71SChen Gang err = remove(buffer); 9884fa4ce71SChen Gang g_free(buffer); 9892c30dd74SAneesh Kumar K.V err_out: 9902c30dd74SAneesh Kumar K.V return err; 9915bae1900SAnthony Liguori } 9925bae1900SAnthony Liguori 9938b888272SAneesh Kumar K.V static int local_fsync(FsContext *ctx, int fid_type, 9948b888272SAneesh Kumar K.V V9fsFidOpenState *fs, int datasync) 9958cf89e00SAnthony Liguori { 9968b888272SAneesh Kumar K.V int fd; 9978b888272SAneesh Kumar K.V 9988b888272SAneesh Kumar K.V if (fid_type == P9_FID_DIR) { 9998b888272SAneesh Kumar K.V fd = dirfd(fs->dir); 100049594973SVenkateswararao Jujjuri (JV) } else { 10018b888272SAneesh Kumar K.V fd = fs->fd; 10028b888272SAneesh Kumar K.V } 10038b888272SAneesh Kumar K.V 10048b888272SAneesh Kumar K.V if (datasync) { 10058b888272SAneesh Kumar K.V return qemu_fdatasync(fd); 10068b888272SAneesh Kumar K.V } else { 10078b888272SAneesh Kumar K.V return fsync(fd); 10088cf89e00SAnthony Liguori } 100949594973SVenkateswararao Jujjuri (JV) } 10108cf89e00SAnthony Liguori 10112289be19SAneesh Kumar K.V static int local_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf) 1012be940c87SM. Mohan Kumar { 10134fa4ce71SChen Gang char *buffer; 10144fa4ce71SChen Gang int ret; 10152289be19SAneesh Kumar K.V char *path = fs_path->data; 10162289be19SAneesh Kumar K.V 10174fa4ce71SChen Gang buffer = rpath(s, path); 10184fa4ce71SChen Gang ret = statfs(buffer, stbuf); 10194fa4ce71SChen Gang g_free(buffer); 10204fa4ce71SChen Gang return ret; 1021be940c87SM. Mohan Kumar } 1022be940c87SM. Mohan Kumar 10232289be19SAneesh Kumar K.V static ssize_t local_lgetxattr(FsContext *ctx, V9fsPath *fs_path, 1024fa32ef88SAneesh Kumar K.V const char *name, void *value, size_t size) 1025fa32ef88SAneesh Kumar K.V { 10262289be19SAneesh Kumar K.V char *path = fs_path->data; 10272289be19SAneesh Kumar K.V 1028fc22118dSAneesh Kumar K.V return v9fs_get_xattr(ctx, path, name, value, size); 1029fa32ef88SAneesh Kumar K.V } 1030fa32ef88SAneesh Kumar K.V 10312289be19SAneesh Kumar K.V static ssize_t local_llistxattr(FsContext *ctx, V9fsPath *fs_path, 1032fa32ef88SAneesh Kumar K.V void *value, size_t size) 1033fa32ef88SAneesh Kumar K.V { 10342289be19SAneesh Kumar K.V char *path = fs_path->data; 10352289be19SAneesh Kumar K.V 1036fc22118dSAneesh Kumar K.V return v9fs_list_xattr(ctx, path, value, size); 103761b6c499SAneesh Kumar K.V } 103861b6c499SAneesh Kumar K.V 10392289be19SAneesh Kumar K.V static int local_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name, 104010b468bdSAneesh Kumar K.V void *value, size_t size, int flags) 104110b468bdSAneesh Kumar K.V { 10422289be19SAneesh Kumar K.V char *path = fs_path->data; 10432289be19SAneesh Kumar K.V 1044fc22118dSAneesh Kumar K.V return v9fs_set_xattr(ctx, path, name, value, size, flags); 104510b468bdSAneesh Kumar K.V } 104610b468bdSAneesh Kumar K.V 10472289be19SAneesh Kumar K.V static int local_lremovexattr(FsContext *ctx, V9fsPath *fs_path, 10482289be19SAneesh Kumar K.V const char *name) 10499ed3ef26SAneesh Kumar K.V { 10502289be19SAneesh Kumar K.V char *path = fs_path->data; 10512289be19SAneesh Kumar K.V 1052fc22118dSAneesh Kumar K.V return v9fs_remove_xattr(ctx, path, name); 10539ed3ef26SAneesh Kumar K.V } 10549ed3ef26SAneesh Kumar K.V 10552289be19SAneesh Kumar K.V static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path, 10562289be19SAneesh Kumar K.V const char *name, V9fsPath *target) 10572289be19SAneesh Kumar K.V { 10582289be19SAneesh Kumar K.V if (dir_path) { 10592289be19SAneesh Kumar K.V v9fs_string_sprintf((V9fsString *)target, "%s/%s", 10602289be19SAneesh Kumar K.V dir_path->data, name); 10612289be19SAneesh Kumar K.V } else { 10622289be19SAneesh Kumar K.V v9fs_string_sprintf((V9fsString *)target, "%s", name); 10632289be19SAneesh Kumar K.V } 10642289be19SAneesh Kumar K.V /* Bump the size for including terminating NULL */ 10652289be19SAneesh Kumar K.V target->size++; 10662289be19SAneesh Kumar K.V return 0; 10672289be19SAneesh Kumar K.V } 10682289be19SAneesh Kumar K.V 10692289be19SAneesh Kumar K.V static int local_renameat(FsContext *ctx, V9fsPath *olddir, 10702289be19SAneesh Kumar K.V const char *old_name, V9fsPath *newdir, 10712289be19SAneesh Kumar K.V const char *new_name) 10722289be19SAneesh Kumar K.V { 10732289be19SAneesh Kumar K.V int ret; 10742289be19SAneesh Kumar K.V V9fsString old_full_name, new_full_name; 10752289be19SAneesh Kumar K.V 10762289be19SAneesh Kumar K.V v9fs_string_init(&old_full_name); 10772289be19SAneesh Kumar K.V v9fs_string_init(&new_full_name); 10782289be19SAneesh Kumar K.V 10792289be19SAneesh Kumar K.V v9fs_string_sprintf(&old_full_name, "%s/%s", olddir->data, old_name); 10802289be19SAneesh Kumar K.V v9fs_string_sprintf(&new_full_name, "%s/%s", newdir->data, new_name); 10812289be19SAneesh Kumar K.V 10822289be19SAneesh Kumar K.V ret = local_rename(ctx, old_full_name.data, new_full_name.data); 10832289be19SAneesh Kumar K.V v9fs_string_free(&old_full_name); 10842289be19SAneesh Kumar K.V v9fs_string_free(&new_full_name); 10852289be19SAneesh Kumar K.V return ret; 10862289be19SAneesh Kumar K.V } 10872289be19SAneesh Kumar K.V 10882289be19SAneesh Kumar K.V static int local_unlinkat(FsContext *ctx, V9fsPath *dir, 10892289be19SAneesh Kumar K.V const char *name, int flags) 10902289be19SAneesh Kumar K.V { 10912289be19SAneesh Kumar K.V int ret; 10922289be19SAneesh Kumar K.V V9fsString fullname; 10934fa4ce71SChen Gang char *buffer; 10942c30dd74SAneesh Kumar K.V 10952289be19SAneesh Kumar K.V v9fs_string_init(&fullname); 10962289be19SAneesh Kumar K.V 10972289be19SAneesh Kumar K.V v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name); 10982c30dd74SAneesh Kumar K.V if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 10992c30dd74SAneesh Kumar K.V if (flags == AT_REMOVEDIR) { 11002c30dd74SAneesh Kumar K.V /* 11012c30dd74SAneesh Kumar K.V * If directory remove .virtfs_metadata contained in the 11022c30dd74SAneesh Kumar K.V * directory 11032c30dd74SAneesh Kumar K.V */ 11044fa4ce71SChen Gang buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, 11052c30dd74SAneesh Kumar K.V fullname.data, VIRTFS_META_DIR); 11062c30dd74SAneesh Kumar K.V ret = remove(buffer); 11074fa4ce71SChen Gang g_free(buffer); 11082c30dd74SAneesh Kumar K.V if (ret < 0 && errno != ENOENT) { 11092c30dd74SAneesh Kumar K.V /* 11102c30dd74SAneesh Kumar K.V * We didn't had the .virtfs_metadata file. May be file created 11112c30dd74SAneesh Kumar K.V * in non-mapped mode ?. Ignore ENOENT. 11122c30dd74SAneesh Kumar K.V */ 11132c30dd74SAneesh Kumar K.V goto err_out; 11142c30dd74SAneesh Kumar K.V } 11152c30dd74SAneesh Kumar K.V } 11162c30dd74SAneesh Kumar K.V /* 11172c30dd74SAneesh Kumar K.V * Now remove the name from parent directory 11182c30dd74SAneesh Kumar K.V * .virtfs_metadata directory. 11192c30dd74SAneesh Kumar K.V */ 11204fa4ce71SChen Gang buffer = local_mapped_attr_path(ctx, fullname.data); 11214fa4ce71SChen Gang ret = remove(buffer); 11224fa4ce71SChen Gang g_free(buffer); 11232c30dd74SAneesh Kumar K.V if (ret < 0 && errno != ENOENT) { 11242c30dd74SAneesh Kumar K.V /* 11252c30dd74SAneesh Kumar K.V * We didn't had the .virtfs_metadata file. May be file created 11262c30dd74SAneesh Kumar K.V * in non-mapped mode ?. Ignore ENOENT. 11272c30dd74SAneesh Kumar K.V */ 11282c30dd74SAneesh Kumar K.V goto err_out; 11292c30dd74SAneesh Kumar K.V } 11302c30dd74SAneesh Kumar K.V } 11312c30dd74SAneesh Kumar K.V /* Remove the name finally */ 11324fa4ce71SChen Gang buffer = rpath(ctx, fullname.data); 11334fa4ce71SChen Gang ret = remove(buffer); 11344fa4ce71SChen Gang g_free(buffer); 11352289be19SAneesh Kumar K.V 11362c30dd74SAneesh Kumar K.V err_out: 113775b7931eSChen Gang v9fs_string_free(&fullname); 11382289be19SAneesh Kumar K.V return ret; 11392289be19SAneesh Kumar K.V } 11409ed3ef26SAneesh Kumar K.V 1141e06a765eSHarsh Prateek Bora static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, 1142e06a765eSHarsh Prateek Bora mode_t st_mode, uint64_t *st_gen) 1143e06a765eSHarsh Prateek Bora { 1144ae0f940eSPaolo Bonzini #ifdef FS_IOC_GETVERSION 11450e5fc994SKirill A. Shutemov int err; 1146cc720ddbSAneesh Kumar K.V V9fsFidOpenState fid_open; 1147cc720ddbSAneesh Kumar K.V 1148e06a765eSHarsh Prateek Bora /* 1149e06a765eSHarsh Prateek Bora * Do not try to open special files like device nodes, fifos etc 1150e06a765eSHarsh Prateek Bora * We can get fd for regular files and directories only 1151e06a765eSHarsh Prateek Bora */ 1152e06a765eSHarsh Prateek Bora if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) { 11531a9978a5SKirill A. Shutemov errno = ENOTTY; 11541a9978a5SKirill A. Shutemov return -1; 1155e06a765eSHarsh Prateek Bora } 1156cc720ddbSAneesh Kumar K.V err = local_open(ctx, path, O_RDONLY, &fid_open); 1157cc720ddbSAneesh Kumar K.V if (err < 0) { 1158cc720ddbSAneesh Kumar K.V return err; 1159e06a765eSHarsh Prateek Bora } 1160cc720ddbSAneesh Kumar K.V err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen); 1161cc720ddbSAneesh Kumar K.V local_close(ctx, &fid_open); 1162e06a765eSHarsh Prateek Bora return err; 11630e5fc994SKirill A. Shutemov #else 11640e5fc994SKirill A. Shutemov errno = ENOTTY; 11650e5fc994SKirill A. Shutemov return -1; 11660e5fc994SKirill A. Shutemov #endif 1167e06a765eSHarsh Prateek Bora } 1168e06a765eSHarsh Prateek Bora 11690174fe73SAneesh Kumar K.V static int local_init(FsContext *ctx) 11700174fe73SAneesh Kumar K.V { 11712507718bSAneesh Kumar K.V int err = 0; 1172e06a765eSHarsh Prateek Bora struct statfs stbuf; 1173e06a765eSHarsh Prateek Bora 11742c30dd74SAneesh Kumar K.V if (ctx->export_flags & V9FS_SM_PASSTHROUGH) { 11752c30dd74SAneesh Kumar K.V ctx->xops = passthrough_xattr_ops; 11762c30dd74SAneesh Kumar K.V } else if (ctx->export_flags & V9FS_SM_MAPPED) { 11772c30dd74SAneesh Kumar K.V ctx->xops = mapped_xattr_ops; 11782c30dd74SAneesh Kumar K.V } else if (ctx->export_flags & V9FS_SM_NONE) { 11792c30dd74SAneesh Kumar K.V ctx->xops = none_xattr_ops; 11802c30dd74SAneesh Kumar K.V } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { 11812c30dd74SAneesh Kumar K.V /* 11822c30dd74SAneesh Kumar K.V * xattr operation for mapped-file and passthrough 11832c30dd74SAneesh Kumar K.V * remain same. 11842c30dd74SAneesh Kumar K.V */ 11852c30dd74SAneesh Kumar K.V ctx->xops = passthrough_xattr_ops; 11862c30dd74SAneesh Kumar K.V } 1187c98f1d4aSAneesh Kumar K.V ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT; 11882507718bSAneesh Kumar K.V #ifdef FS_IOC_GETVERSION 11892507718bSAneesh Kumar K.V /* 11902507718bSAneesh Kumar K.V * use ioc_getversion only if the iocl is definied 11912507718bSAneesh Kumar K.V */ 1192e06a765eSHarsh Prateek Bora err = statfs(ctx->fs_root, &stbuf); 1193e06a765eSHarsh Prateek Bora if (!err) { 1194e06a765eSHarsh Prateek Bora switch (stbuf.f_type) { 1195e06a765eSHarsh Prateek Bora case EXT2_SUPER_MAGIC: 1196e06a765eSHarsh Prateek Bora case BTRFS_SUPER_MAGIC: 1197e06a765eSHarsh Prateek Bora case REISERFS_SUPER_MAGIC: 1198e06a765eSHarsh Prateek Bora case XFS_SUPER_MAGIC: 1199e06a765eSHarsh Prateek Bora ctx->exops.get_st_gen = local_ioc_getversion; 1200e06a765eSHarsh Prateek Bora break; 1201e06a765eSHarsh Prateek Bora } 1202e06a765eSHarsh Prateek Bora } 12032507718bSAneesh Kumar K.V #endif 1204e06a765eSHarsh Prateek Bora return err; 12050174fe73SAneesh Kumar K.V } 12060174fe73SAneesh Kumar K.V 120799519f0aSAneesh Kumar K.V static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse) 120899519f0aSAneesh Kumar K.V { 120999519f0aSAneesh Kumar K.V const char *sec_model = qemu_opt_get(opts, "security_model"); 121099519f0aSAneesh Kumar K.V const char *path = qemu_opt_get(opts, "path"); 121199519f0aSAneesh Kumar K.V 121299519f0aSAneesh Kumar K.V if (!sec_model) { 1213*63325b18SGreg Kurz error_report("Security model not specified, local fs needs security model"); 1214*63325b18SGreg Kurz error_printf("valid options are:" 1215*63325b18SGreg Kurz "\tsecurity_model=[passthrough|mapped-xattr|mapped-file|none]\n"); 121699519f0aSAneesh Kumar K.V return -1; 121799519f0aSAneesh Kumar K.V } 121899519f0aSAneesh Kumar K.V 121999519f0aSAneesh Kumar K.V if (!strcmp(sec_model, "passthrough")) { 122099519f0aSAneesh Kumar K.V fse->export_flags |= V9FS_SM_PASSTHROUGH; 12212c30dd74SAneesh Kumar K.V } else if (!strcmp(sec_model, "mapped") || 12222c30dd74SAneesh Kumar K.V !strcmp(sec_model, "mapped-xattr")) { 122399519f0aSAneesh Kumar K.V fse->export_flags |= V9FS_SM_MAPPED; 122499519f0aSAneesh Kumar K.V } else if (!strcmp(sec_model, "none")) { 122599519f0aSAneesh Kumar K.V fse->export_flags |= V9FS_SM_NONE; 12262c30dd74SAneesh Kumar K.V } else if (!strcmp(sec_model, "mapped-file")) { 12272c30dd74SAneesh Kumar K.V fse->export_flags |= V9FS_SM_MAPPED_FILE; 122899519f0aSAneesh Kumar K.V } else { 1229*63325b18SGreg Kurz error_report("Invalid security model %s specified", sec_model); 1230*63325b18SGreg Kurz error_printf("valid options are:" 1231*63325b18SGreg Kurz "\t[passthrough|mapped-xattr|mapped-file|none]\n"); 123299519f0aSAneesh Kumar K.V return -1; 123399519f0aSAneesh Kumar K.V } 123499519f0aSAneesh Kumar K.V 123599519f0aSAneesh Kumar K.V if (!path) { 1236*63325b18SGreg Kurz error_report("fsdev: No path specified"); 123799519f0aSAneesh Kumar K.V return -1; 123899519f0aSAneesh Kumar K.V } 123999519f0aSAneesh Kumar K.V fse->path = g_strdup(path); 124099519f0aSAneesh Kumar K.V 124199519f0aSAneesh Kumar K.V return 0; 124299519f0aSAneesh Kumar K.V } 124399519f0aSAneesh Kumar K.V 12449f107513SAnthony Liguori FileOperations local_ops = { 124599519f0aSAneesh Kumar K.V .parse_opts = local_parse_opts, 12460174fe73SAneesh Kumar K.V .init = local_init, 1247131dcb25SAnthony Liguori .lstat = local_lstat, 1248131dcb25SAnthony Liguori .readlink = local_readlink, 1249131dcb25SAnthony Liguori .close = local_close, 1250131dcb25SAnthony Liguori .closedir = local_closedir, 1251a6568fe2SAnthony Liguori .open = local_open, 1252a6568fe2SAnthony Liguori .opendir = local_opendir, 1253a9231555SAnthony Liguori .rewinddir = local_rewinddir, 1254a9231555SAnthony Liguori .telldir = local_telldir, 12555f524c1eSHarsh Prateek Bora .readdir_r = local_readdir_r, 1256a9231555SAnthony Liguori .seekdir = local_seekdir, 125756d15a53SSanchit Garg .preadv = local_preadv, 125856d15a53SSanchit Garg .pwritev = local_pwritev, 1259c494dd6fSAnthony Liguori .chmod = local_chmod, 1260c494dd6fSAnthony Liguori .mknod = local_mknod, 1261c494dd6fSAnthony Liguori .mkdir = local_mkdir, 1262c494dd6fSAnthony Liguori .fstat = local_fstat, 1263c494dd6fSAnthony Liguori .open2 = local_open2, 1264c494dd6fSAnthony Liguori .symlink = local_symlink, 1265c494dd6fSAnthony Liguori .link = local_link, 12668cf89e00SAnthony Liguori .truncate = local_truncate, 12678cf89e00SAnthony Liguori .rename = local_rename, 12688cf89e00SAnthony Liguori .chown = local_chown, 126974bc02b2SM. Mohan Kumar .utimensat = local_utimensat, 12705bae1900SAnthony Liguori .remove = local_remove, 12718cf89e00SAnthony Liguori .fsync = local_fsync, 1272be940c87SM. Mohan Kumar .statfs = local_statfs, 1273fa32ef88SAneesh Kumar K.V .lgetxattr = local_lgetxattr, 1274fa32ef88SAneesh Kumar K.V .llistxattr = local_llistxattr, 127510b468bdSAneesh Kumar K.V .lsetxattr = local_lsetxattr, 12769ed3ef26SAneesh Kumar K.V .lremovexattr = local_lremovexattr, 12772289be19SAneesh Kumar K.V .name_to_path = local_name_to_path, 12782289be19SAneesh Kumar K.V .renameat = local_renameat, 12792289be19SAneesh Kumar K.V .unlinkat = local_unlinkat, 12809f107513SAnthony Liguori }; 1281