@@ -31,6 +31,7 @@
#define P9_CMD_ERROR 107
#define P9_CMD_WALK 110
#define P9_CMD_OPEN 112
+#define P9_CMD_CREATE 114
#define P9_CMD_CLUNK 120
/* P9 protocol open flags. */
@@ -41,6 +42,12 @@
#define P9_OTRUNC 0x10 /* or'ed in, truncate file first */
#define P9_OREMOVE 0x40 /* or'ed in, remove file after clunk */
+/* P9 protocol create permission masks. */
+#define P9_CREATE_PERM_DIR 0x80000000
+#define P9_CREATE_PERM_NOTSUPP 0x03b00000 /* link, symlink, ... */
+#define P9_CREATE_PERM_DIR_MASK 0777
+#define P9_CREATE_PERM_FILE_MASK 0666
+
#define P9_MIN_MSIZE 2048
#define P9_VERSION "9P2000.u"
#define P9_WALK_MAXELEM 16
@@ -944,6 +951,154 @@ static void p9_open(struct ring *ring, struct p9_header *hdr)
fill_buffer(ring, hdr->cmd + 1, hdr->tag, "QU", &qid, &iounit);
}
+static void p9_create(struct ring *ring, struct p9_header *hdr)
+{
+ device *device = ring->device;
+ uint32_t fid;
+ unsigned int name_off;
+ uint32_t perm;
+ uint8_t mode;
+ unsigned int ext_off;
+ struct p9_fid *fidp;
+ struct p9_fid *new_fidp;
+ char *path;
+ struct stat st;
+ struct p9_qid qid;
+ uint32_t iounit;
+ int flags;
+ int ret;
+
+ ret = fill_data(ring, "USUbS", &fid, &name_off, &perm, &mode, &ext_off);
+ if ( ret != 5 )
+ {
+ p9_error(ring, hdr->tag, EINVAL);
+ return;
+ }
+
+ if ( !name_ok(ring->str + name_off) )
+ {
+ p9_error(ring, hdr->tag, ENOENT);
+ return;
+ }
+
+ if ( perm & P9_CREATE_PERM_NOTSUPP )
+ {
+ p9_error(ring, hdr->tag, EINVAL);
+ return;
+ }
+
+ fidp = get_fid_ref(device, fid);
+ if ( !fidp || fidp->opened )
+ {
+ free_fid(device, fidp);
+ p9_error(ring, hdr->tag, EINVAL);
+ return;
+ }
+ if ( stat(fidp->path, &st) < 0 )
+ {
+ free_fid(device, fidp);
+ p9_error(ring, hdr->tag, errno);
+ return;
+ }
+
+ path = malloc(strlen(fidp->path) + strlen(ring->str + name_off) + 2 -
+ strlen(device->host_path));
+ if ( !path )
+ {
+ free_fid(device, fidp);
+ p9_error(ring, hdr->tag, ENOMEM);
+ return;
+ }
+ sprintf(path, "%s/%s", fidp->path + strlen(device->host_path),
+ ring->str + name_off);
+ new_fidp = alloc_fid_mem(device, fid, path);
+ free(path);
+ if ( !new_fidp )
+ {
+ free_fid(device, fidp);
+ p9_error(ring, hdr->tag, ENOMEM);
+ return;
+ }
+
+ pthread_mutex_lock(&device->fid_mutex);
+
+ new_fidp->ref = fidp->ref;
+
+ if ( perm & P9_CREATE_PERM_DIR )
+ {
+ perm &= P9_CREATE_PERM_DIR_MASK & st.st_mode;
+ if ( mode != P9_OREAD )
+ {
+ p9_error(ring, hdr->tag, EINVAL);
+ free(new_fidp);
+ goto err;
+ }
+ if ( mkdir(new_fidp->path, perm) < 0 )
+ {
+ p9_error(ring, hdr->tag, errno);
+ free(new_fidp);
+ goto err;
+ }
+
+ XEN_TAILQ_REMOVE(&device->fids, fidp, list);
+ XEN_TAILQ_INSERT_HEAD(&device->fids, new_fidp, list);
+ free(fidp);
+ fidp = new_fidp;
+
+ fidp->data = opendir(fidp->path);
+ if ( !fidp->data )
+ {
+ p9_error(ring, hdr->tag, errno);
+ goto err;
+ }
+ fidp->fd = dirfd(fidp->data);
+ }
+ else
+ {
+ flags = open_flags_from_mode(mode);
+ if ( flags < 0 )
+ {
+ p9_error(ring, hdr->tag, EINVAL);
+ free(new_fidp);
+ goto err;
+ }
+ flags |= perm & P9_CREATE_PERM_FILE_MASK & st.st_mode;
+
+ XEN_TAILQ_REMOVE(&device->fids, fidp, list);
+ XEN_TAILQ_INSERT_HEAD(&device->fids, new_fidp, list);
+ free(fidp);
+ fidp = new_fidp;
+
+ fidp->fd = creat(fidp->path, flags);
+ if ( fidp->fd < 0 )
+ {
+ p9_error(ring, hdr->tag, errno);
+ goto err;
+ }
+ }
+
+ if ( stat(fidp->path, &st) < 0 )
+ {
+ p9_error(ring, hdr->tag, errno);
+ goto err;
+ }
+ fill_qid(fidp->path, &qid, &st);
+ iounit = get_iounit(ring, &st);
+ fidp->opened = true;
+ fidp->mode = mode;
+
+ pthread_mutex_unlock(&device->fid_mutex);
+
+ fill_buffer(ring, hdr->cmd + 1, hdr->tag, "QU", &qid, &iounit);
+
+ return;
+
+ err:
+ pthread_mutex_unlock(&device->fid_mutex);
+
+ free_fid(device, fidp);
+}
+
static void p9_clunk(struct ring *ring, struct p9_header *hdr)
{
device *device = ring->device;
@@ -1052,6 +1207,10 @@ void *io_thread(void *arg)
p9_open(ring, &hdr);
break;
+ case P9_CMD_CREATE:
+ p9_create(ring, &hdr);
+ break;
+
case P9_CMD_CLUNK:
p9_clunk(ring, &hdr);
break;
Add the create request of the 9pfs protocol. Signed-off-by: Juergen Gross <jgross@suse.com> --- V2: - set permissions correctly (Jason Andryuk) --- tools/xen-9pfsd/io.c | 159 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+)