1 /* 2 * Virtio 9p 3 * 4 * Copyright IBM, Corp. 2010 5 * 6 * Authors: 7 * Gautham R Shenoy <ego@in.ibm.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2. See 10 * the COPYING file in the top-level directory. 11 * 12 */ 13 #include <stdio.h> 14 #include <string.h> 15 #include "qemu-fsdev.h" 16 #include "qemu-queue.h" 17 #include "osdep.h" 18 #include "qemu-common.h" 19 #include "qemu-config.h" 20 21 static QTAILQ_HEAD(FsDriverEntry_head, FsDriverListEntry) fsdriver_entries = 22 QTAILQ_HEAD_INITIALIZER(fsdriver_entries); 23 24 static FsDriverTable FsDrivers[] = { 25 { .name = "local", .ops = &local_ops}, 26 #ifdef CONFIG_OPEN_BY_HANDLE 27 { .name = "handle", .ops = &handle_ops}, 28 #endif 29 { .name = "synth", .ops = &synth_ops}, 30 }; 31 32 int qemu_fsdev_add(QemuOpts *opts) 33 { 34 struct FsDriverListEntry *fsle; 35 int i; 36 const char *fsdev_id = qemu_opts_id(opts); 37 const char *fsdriver = qemu_opt_get(opts, "fsdriver"); 38 const char *path = qemu_opt_get(opts, "path"); 39 const char *sec_model = qemu_opt_get(opts, "security_model"); 40 const char *writeout = qemu_opt_get(opts, "writeout"); 41 bool ro = qemu_opt_get_bool(opts, "readonly", 0); 42 43 if (!fsdev_id) { 44 fprintf(stderr, "fsdev: No id specified\n"); 45 return -1; 46 } 47 48 if (fsdriver) { 49 for (i = 0; i < ARRAY_SIZE(FsDrivers); i++) { 50 if (strcmp(FsDrivers[i].name, fsdriver) == 0) { 51 break; 52 } 53 } 54 55 if (i == ARRAY_SIZE(FsDrivers)) { 56 fprintf(stderr, "fsdev: fsdriver %s not found\n", fsdriver); 57 return -1; 58 } 59 } else { 60 fprintf(stderr, "fsdev: No fsdriver specified\n"); 61 return -1; 62 } 63 64 if (!strcmp(fsdriver, "local") && !sec_model) { 65 fprintf(stderr, "security model not specified, " 66 "local fs needs security model\nvalid options are:" 67 "\tsecurity_model=[passthrough|mapped|none]\n"); 68 return -1; 69 } 70 71 if (strcmp(fsdriver, "local") && sec_model) { 72 fprintf(stderr, "only local fs driver needs security model\n"); 73 return -1; 74 } 75 76 if (!path) { 77 fprintf(stderr, "fsdev: No path specified.\n"); 78 return -1; 79 } 80 81 fsle = g_malloc(sizeof(*fsle)); 82 83 fsle->fse.fsdev_id = g_strdup(fsdev_id); 84 fsle->fse.path = g_strdup(path); 85 fsle->fse.ops = FsDrivers[i].ops; 86 fsle->fse.export_flags = 0; 87 if (writeout) { 88 if (!strcmp(writeout, "immediate")) { 89 fsle->fse.export_flags |= V9FS_IMMEDIATE_WRITEOUT; 90 } 91 } 92 if (ro) { 93 fsle->fse.export_flags |= V9FS_RDONLY; 94 } else { 95 fsle->fse.export_flags &= ~V9FS_RDONLY; 96 } 97 98 if (strcmp(fsdriver, "local")) { 99 goto done; 100 } 101 102 if (!strcmp(sec_model, "passthrough")) { 103 fsle->fse.export_flags |= V9FS_SM_PASSTHROUGH; 104 } else if (!strcmp(sec_model, "mapped")) { 105 fsle->fse.export_flags |= V9FS_SM_MAPPED; 106 } else if (!strcmp(sec_model, "none")) { 107 fsle->fse.export_flags |= V9FS_SM_NONE; 108 } else { 109 fprintf(stderr, "Invalid security model %s specified, valid options are" 110 "\n\t [passthrough|mapped|none]\n", sec_model); 111 return -1; 112 } 113 done: 114 QTAILQ_INSERT_TAIL(&fsdriver_entries, fsle, next); 115 return 0; 116 } 117 118 FsDriverEntry *get_fsdev_fsentry(char *id) 119 { 120 if (id) { 121 struct FsDriverListEntry *fsle; 122 123 QTAILQ_FOREACH(fsle, &fsdriver_entries, next) { 124 if (strcmp(fsle->fse.fsdev_id, id) == 0) { 125 return &fsle->fse; 126 } 127 } 128 } 129 return NULL; 130 } 131 132 static void fsdev_register_config(void) 133 { 134 qemu_add_opts(&qemu_fsdev_opts); 135 qemu_add_opts(&qemu_virtfs_opts); 136 } 137 machine_init(fsdev_register_config); 138 139