Message ID | 1268730920-14584-4-git-send-email-aneesh.kumar@linux.vnet.ibm.com |
---|---|
State | New |
Headers | show |
On 03/16/2010 04:15 AM, Aneesh Kumar K.V wrote: > From: Anthony Liguori<aliguori@us.ibm.com> > > [jvrao@linux.vnet.ibm.com: Added qemu_vasprintf] > > Signed-off-by: Anthony Liguori<aliguori@us.ibm.com> > Signed-off-by: Aneesh Kumar K.V<aneesh.kumar@linux.vnet.ibm.com> > --- > Makefile.target | 2 +- > hw/virtio-9p-local.c | 84 +++++++++++++++++++++++++++ > hw/virtio-9p.c | 155 +++++++++++++++++++++++++++++++++++++++++++++++--- > hw/virtio-9p.h | 33 +++++++++++ > qemu-common.h | 1 + > qemu-malloc.c | 5 ++ > 6 files changed, 270 insertions(+), 10 deletions(-) > create mode 100644 hw/virtio-9p-local.c > > diff --git a/Makefile.target b/Makefile.target > index 33f9fcb..97f32a9 100644 > --- a/Makefile.target > +++ b/Makefile.target > @@ -172,7 +172,7 @@ obj-y = vl.o async.o monitor.o pci.o pci_host.o pcie_host.o machine.o gdbstub.o > # virtio has to be here due to weird dependency between PCI and virtio-net. > # need to fix this properly > obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o virtio-serial-bus.o > -obj-y += virtio-9p.o virtio-9p-debug.o > +obj-y += virtio-9p.o virtio-9p-debug.o virtio-9p-local.o > obj-y += rwhandler.o > obj-$(CONFIG_KVM) += kvm.o kvm-all.o > obj-$(CONFIG_ISA_MMIO) += isa_mmio.o > diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c > new file mode 100644 > index 0000000..1d2523b > --- /dev/null > +++ b/hw/virtio-9p-local.c > This should be a logically separate patch. > @@ -0,0 +1,84 @@ > +/* > + * Virtio 9p Posix callback > + * > + * Copyright IBM, Corp. 2010 > + * > + * Authors: > + * Anthony Liguori<aliguori@us.ibm.com> > + * > + * This work is licensed under the terms of the GNU GPL, version 2. See > + * the COPYING file in the top-level directory. > + * > + */ > +#include "virtio.h" > +#include "pc.h" > +#include "qemu_socket.h" > +#include "virtio-9p.h" > +#include<sys/uio.h> > +#include<arpa/inet.h> > +#include<assert.h> > +#include<pwd.h> > +#include<grp.h> > +#include<sys/socket.h> > +#include<sys/un.h> > These headers are almost certainly going to break the build on windows. Some care is needed here. > + > +static const char *base_path; > + > +static const char *rpath(const char *path) > +{ > + /* FIXME: so wrong... */ > + static char buffer[4096]; > + snprintf(buffer, sizeof(buffer), "%s/%s", base_path, path); > + return buffer; > +} > + > +static int local_lstat(void *opaque, const char *path, struct stat *stbuf) > +{ > + return lstat(rpath(path), stbuf); > +} > + > +static int local_setuid(void *opaque, uid_t uid) > +{ > + struct passwd *pw; > + gid_t groups[33]; > + int ngroups; > + static uid_t cur_uid = -1; > + > + if (cur_uid == uid) > + return 0; > + > + if (setreuid(0, 0)) > + return -1; > + > + pw = getpwuid(uid); > + if (pw == NULL) > + return -1; > + > + ngroups = 33; > + if (getgrouplist(pw->pw_name, pw->pw_gid, groups,&ngroups) == -1) > + return -1; > + > + if (setgroups(ngroups, groups)) > + return -1; > + > + if (setregid(-1, pw->pw_gid)) > + return -1; > + > + if (setreuid(-1, uid)) > + return -1; > + > + cur_uid = uid; > + > + return 0; > +} > + > +static V9fsPosixFileOperations ops = { > + .lstat = local_lstat, > + .setuid = local_setuid, > +}; > + > +V9fsPosixFileOperations *virtio_9p_init_local(const char *path) > +{ > + base_path = path; > + return&ops; > +} > diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c > index 53b3d78..fdff589 100644 > --- a/hw/virtio-9p.c > +++ b/hw/virtio-9p.c > @@ -82,6 +82,7 @@ typedef struct V9fsState > V9fsPDU pdus[MAX_REQ]; > V9fsPDU *free_pdu; > V9fsFidState *fid_list; > + V9fsPosixFileOperations *ops; > char *root; > uid_t uid; > } V9fsState; > @@ -91,6 +92,123 @@ int debug_9p_pdu = 1; > > extern void pprint_pdu(V9fsPDU *pdu); > > +static int posix_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf) > +{ > + return s->ops->lstat(s->ops->opaque, path->data, stbuf); > +} > + > +static int posix_setuid(V9fsState *s, uid_t uid) > +{ > + return s->ops->setuid(s->ops->opaque, uid); > +} > + > +static void v9fs_string_free(V9fsString *str) > +{ > + qemu_free(str->data); > + str->data = NULL; > + str->size = 0; > +} > + > +static void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...) > +{ > + va_list ap; > + int err; > + > + v9fs_string_free(str); > + > + va_start(ap, fmt); > + err = qemu_vasprintf(&str->data, fmt, ap); > + BUG_ON(err == -1); > + va_end(ap); > + > + str->size = err; > +} > + > +static V9fsFidState *lookup_fid(V9fsState *s, int32_t fid) > +{ > + V9fsFidState *f; > + > + for (f = s->fid_list; f; f = f->next) { > + if (f->fid == fid) { > + posix_setuid(s, f->uid); > + return f; > + } > + } > + > + return NULL; > +} > + > +static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid) > +{ > + V9fsFidState *f; > + > + f = lookup_fid(s, fid); > + if (f) > + return NULL; > + > + f = qemu_mallocz(sizeof(V9fsFidState)); > + BUG_ON(f == NULL); > + > + f->fid = fid; > + f->fd = -1; > + f->dir = NULL; > + > + f->next = s->fid_list; > + s->fid_list = f; > + > + return f; > +} > + > +#define P9_QID_TYPE_DIR 0x80 > +#define P9_QID_TYPE_SYMLINK 0x02 > + > +#define P9_STAT_MODE_DIR 0x80000000 > +#define P9_STAT_MODE_APPEND 0x40000000 > +#define P9_STAT_MODE_EXCL 0x20000000 > +#define P9_STAT_MODE_MOUNT 0x10000000 > +#define P9_STAT_MODE_AUTH 0x08000000 > +#define P9_STAT_MODE_TMP 0x04000000 > +#define P9_STAT_MODE_SYMLINK 0x02000000 > +#define P9_STAT_MODE_LINK 0x01000000 > +#define P9_STAT_MODE_DEVICE 0x00800000 > +#define P9_STAT_MODE_NAMED_PIPE 0x00200000 > +#define P9_STAT_MODE_SOCKET 0x00100000 > +#define P9_STAT_MODE_SETUID 0x00080000 > +#define P9_STAT_MODE_SETGID 0x00040000 > +#define P9_STAT_MODE_SETVTX 0x00010000 > + > +#define P9_STAT_MODE_SPECIAL (P9_STAT_MODE_NAMED_PIPE | \ > + P9_STAT_MODE_SYMLINK | \ > + P9_STAT_MODE_LINK | \ > + P9_STAT_MODE_DEVICE) > + > + > +/* This is the algorithm from ufs in spfs */ > +static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp) > +{ > + size_t size; > + > + size = MIN(sizeof(stbuf->st_ino), sizeof(qidp->path)); > + memcpy(&qidp->path,&stbuf->st_ino, size); > + qidp->version = stbuf->st_mtime ^ (stbuf->st_size<< 8); > + qidp->type = 0; > + if (S_ISDIR(stbuf->st_mode)) > + qidp->type |= P9_QID_TYPE_DIR; > + if (S_ISLNK(stbuf->st_mode)) > + qidp->type |= P9_QID_TYPE_SYMLINK; > +} > + > +static void fid_to_qid(V9fsState *s, V9fsFidState *fidp, V9fsQID *qidp) > +{ > + struct stat stbuf; > + int err; > + > + err = posix_lstat(s,&fidp->path,&stbuf); > + BUG_ON(err == -1); > + > + stat_to_qid(&stbuf, qidp); > +} > + > static V9fsPDU *alloc_pdu(V9fsState *s) > { > V9fsPDU *pdu = NULL; > @@ -111,13 +229,6 @@ static void free_pdu(V9fsState *s, V9fsPDU *pdu) > } > } > > -static void v9fs_string_free(V9fsString *str) > -{ > - free(str->data); > - str->data = NULL; > - str->size = 0; > -} > - > static size_t pdu_unpack(void *dst, V9fsPDU *pdu, size_t offset, size_t size) > { > struct iovec *sg = pdu->elem.out_sg; > @@ -378,8 +489,33 @@ static void v9fs_version(V9fsState *s, V9fsPDU *pdu) > > static void v9fs_attach(V9fsState *s, V9fsPDU *pdu) > { > - if (debug_9p_pdu) > - pprint_pdu(pdu); > + int32_t fid, afid, n_uname; > + V9fsString uname, aname; > + V9fsFidState *fidp; > + V9fsQID qid; > + size_t offset = 7; > + ssize_t err; > + > + pdu_unmarshal(pdu, offset, "ddssd",&fid,&afid,&uname,&aname,&n_uname); > + > + fidp = alloc_fid(s, fid); > + if (fidp == NULL) { > + err = -EINVAL; > + goto out; > + } > + > + fidp->uid = n_uname; > + > + v9fs_string_sprintf(&fidp->path, "%s", s->root); > + fid_to_qid(s, fidp,&qid); > + > + offset += pdu_marshal(pdu, offset, "Q",&qid); > + > + err = offset; > +out: > + complete_pdu(s, pdu, err); > + v9fs_string_free(&uname); > + v9fs_string_free(&aname); > } > > static void v9fs_stat(V9fsState *s, V9fsPDU *pdu) > @@ -528,6 +664,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, const char *path) > BUG_ON(s->root == NULL); > s->uid = -1; > > + s->ops = virtio_9p_init_local(path); > s->vdev.get_features = virtio_9p_get_features; > > return&s->vdev; > diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h > index 2aa67d0..8e15bf0 100644 > --- a/hw/virtio-9p.h > +++ b/hw/virtio-9p.h > @@ -66,5 +66,38 @@ struct V9fsPDU > V9fsPDU *next; > }; > > +typedef struct V9fsPosixFileOpertions > +{ > + int (*lstat)(void *, const char *, struct stat *); > + ssize_t (*readlink)(void *, const char *, char *, size_t); > + int (*chmod)(void *, const char *, mode_t); > + int (*chown)(void *, const char *, uid_t, gid_t); > + int (*mknod)(void *, const char *, mode_t, dev_t); > + int (*mksock)(void *, const char *); > + int (*utime)(void *, const char *, const struct utimbuf *); > + int (*remove)(void *, const char *); > + int (*symlink)(void *, const char *, const char *); > + int (*link)(void *, const char *, const char *); > + int (*setuid)(void *, uid_t); > + int (*close)(void *, int); > + int (*closedir)(void *, DIR *); > + DIR *(*opendir)(void *, const char *); > + int (*open)(void *, const char *, int); > + int (*open2)(void *, const char *, int, mode_t); > + void (*rewinddir)(void *, DIR *); > + off_t (*telldir)(void *, DIR *); > + struct dirent *(*readdir)(void *, DIR *); > + void (*seekdir)(void *, DIR *, off_t); > + ssize_t (*readv)(void *, int, const struct iovec *, int); > + ssize_t (*writev)(void *, int, const struct iovec *, int); > + off_t (*lseek)(void *, int, off_t, int); > + int (*mkdir)(void *, const char *, mode_t); > + int (*fstat)(void *, int, struct stat *); > + int (*rename)(void *, const char *, const char *); > + int (*truncate)(void *, const char *, off_t); > + void *opaque; > +} V9fsPosixFileOperations; > + > +V9fsPosixFileOperations *virtio_9p_init_local(const char *path); > > #endif > diff --git a/qemu-common.h b/qemu-common.h > index 805be1a..ebe7088 100644 > --- a/qemu-common.h > +++ b/qemu-common.h > @@ -159,6 +159,7 @@ void *qemu_mallocz(size_t size); > void qemu_free(void *ptr); > char *qemu_strdup(const char *str); > char *qemu_strndup(const char *str, size_t size); > +int qemu_vasprintf(char **strp, const char *fmt, va_list ap); > > void *get_mmap_addr(unsigned long size); > > diff --git a/qemu-malloc.c b/qemu-malloc.c > index 6cdc5de..d6de067 100644 > --- a/qemu-malloc.c > +++ b/qemu-malloc.c > @@ -98,3 +98,8 @@ char *qemu_strndup(const char *str, size_t size) > > return memcpy(new, str, size); > } > + > +int qemu_vasprintf(char **strp, const char *fmt, va_list ap) > +{ > + return vasprintf(strp, fmt, ap); > +} > asprintf() is not universally available so it cannot be wrapped this naively. Regards, Anthony Liguori
Anthony Liguori wrote: > On 03/16/2010 04:15 AM, Aneesh Kumar K.V wrote: >> From: Anthony Liguori<aliguori@us.ibm.com> >> >> [jvrao@linux.vnet.ibm.com: Added qemu_vasprintf] >> >> Signed-off-by: Anthony Liguori<aliguori@us.ibm.com> >> Signed-off-by: Aneesh Kumar K.V<aneesh.kumar@linux.vnet.ibm.com> >> --- >> Makefile.target | 2 +- >> hw/virtio-9p-local.c | 84 +++++++++++++++++++++++++++ >> hw/virtio-9p.c | 155 >> +++++++++++++++++++++++++++++++++++++++++++++++--- >> hw/virtio-9p.h | 33 +++++++++++ >> qemu-common.h | 1 + >> qemu-malloc.c | 5 ++ >> 6 files changed, 270 insertions(+), 10 deletions(-) >> create mode 100644 hw/virtio-9p-local.c >> >> diff --git a/Makefile.target b/Makefile.target >> index 33f9fcb..97f32a9 100644 >> --- a/Makefile.target >> +++ b/Makefile.target >> @@ -172,7 +172,7 @@ obj-y = vl.o async.o monitor.o pci.o pci_host.o >> pcie_host.o machine.o gdbstub.o >> # virtio has to be here due to weird dependency between PCI and >> virtio-net. >> # need to fix this properly >> obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o >> virtio-serial-bus.o >> -obj-y += virtio-9p.o virtio-9p-debug.o >> +obj-y += virtio-9p.o virtio-9p-debug.o virtio-9p-local.o >> obj-y += rwhandler.o >> obj-$(CONFIG_KVM) += kvm.o kvm-all.o >> obj-$(CONFIG_ISA_MMIO) += isa_mmio.o >> diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c >> new file mode 100644 >> index 0000000..1d2523b >> --- /dev/null >> +++ b/hw/virtio-9p-local.c >> > > This should be a logically separate patch. > >> @@ -0,0 +1,84 @@ >> +/* >> + * Virtio 9p Posix callback >> + * >> + * Copyright IBM, Corp. 2010 >> + * >> + * Authors: >> + * Anthony Liguori<aliguori@us.ibm.com> >> + * >> + * This work is licensed under the terms of the GNU GPL, version 2. See >> + * the COPYING file in the top-level directory. >> + * >> + */ >> +#include "virtio.h" >> +#include "pc.h" >> +#include "qemu_socket.h" >> +#include "virtio-9p.h" >> +#include<sys/uio.h> >> +#include<arpa/inet.h> >> +#include<assert.h> >> +#include<pwd.h> >> +#include<grp.h> >> +#include<sys/socket.h> >> +#include<sys/un.h> >> > > These headers are almost certainly going to break the build on windows. > Some care is needed here. > >> + >> +static const char *base_path; >> + >> +static const char *rpath(const char *path) >> +{ >> + /* FIXME: so wrong... */ >> + static char buffer[4096]; >> + snprintf(buffer, sizeof(buffer), "%s/%s", base_path, path); >> + return buffer; >> +} >> + >> +static int local_lstat(void *opaque, const char *path, struct stat >> *stbuf) >> +{ >> + return lstat(rpath(path), stbuf); >> +} >> + >> +static int local_setuid(void *opaque, uid_t uid) >> +{ >> + struct passwd *pw; >> + gid_t groups[33]; >> + int ngroups; >> + static uid_t cur_uid = -1; >> + >> + if (cur_uid == uid) >> + return 0; >> + >> + if (setreuid(0, 0)) >> + return -1; >> + >> + pw = getpwuid(uid); >> + if (pw == NULL) >> + return -1; >> + >> + ngroups = 33; >> + if (getgrouplist(pw->pw_name, pw->pw_gid, groups,&ngroups) == -1) >> + return -1; >> + >> + if (setgroups(ngroups, groups)) >> + return -1; >> + >> + if (setregid(-1, pw->pw_gid)) >> + return -1; >> + >> + if (setreuid(-1, uid)) >> + return -1; >> + >> + cur_uid = uid; >> + >> + return 0; >> +} >> + >> +static V9fsPosixFileOperations ops = { >> + .lstat = local_lstat, >> + .setuid = local_setuid, >> +}; >> + >> +V9fsPosixFileOperations *virtio_9p_init_local(const char *path) >> +{ >> + base_path = path; >> + return&ops; >> +} >> diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c >> index 53b3d78..fdff589 100644 >> --- a/hw/virtio-9p.c >> +++ b/hw/virtio-9p.c >> @@ -82,6 +82,7 @@ typedef struct V9fsState >> V9fsPDU pdus[MAX_REQ]; >> V9fsPDU *free_pdu; >> V9fsFidState *fid_list; >> + V9fsPosixFileOperations *ops; >> char *root; >> uid_t uid; >> } V9fsState; >> @@ -91,6 +92,123 @@ int debug_9p_pdu = 1; >> >> extern void pprint_pdu(V9fsPDU *pdu); >> >> +static int posix_lstat(V9fsState *s, V9fsString *path, struct stat >> *stbuf) >> +{ >> + return s->ops->lstat(s->ops->opaque, path->data, stbuf); >> +} >> + >> +static int posix_setuid(V9fsState *s, uid_t uid) >> +{ >> + return s->ops->setuid(s->ops->opaque, uid); >> +} >> + >> +static void v9fs_string_free(V9fsString *str) >> +{ >> + qemu_free(str->data); >> + str->data = NULL; >> + str->size = 0; >> +} >> + >> +static void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...) >> +{ >> + va_list ap; >> + int err; >> + >> + v9fs_string_free(str); >> + >> + va_start(ap, fmt); >> + err = qemu_vasprintf(&str->data, fmt, ap); >> + BUG_ON(err == -1); >> + va_end(ap); >> + >> + str->size = err; >> +} >> + >> +static V9fsFidState *lookup_fid(V9fsState *s, int32_t fid) >> +{ >> + V9fsFidState *f; >> + >> + for (f = s->fid_list; f; f = f->next) { >> + if (f->fid == fid) { >> + posix_setuid(s, f->uid); >> + return f; >> + } >> + } >> + >> + return NULL; >> +} >> + >> +static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid) >> +{ >> + V9fsFidState *f; >> + >> + f = lookup_fid(s, fid); >> + if (f) >> + return NULL; >> + >> + f = qemu_mallocz(sizeof(V9fsFidState)); >> + BUG_ON(f == NULL); >> + >> + f->fid = fid; >> + f->fd = -1; >> + f->dir = NULL; >> + >> + f->next = s->fid_list; >> + s->fid_list = f; >> + >> + return f; >> +} >> + >> +#define P9_QID_TYPE_DIR 0x80 >> +#define P9_QID_TYPE_SYMLINK 0x02 >> + >> +#define P9_STAT_MODE_DIR 0x80000000 >> +#define P9_STAT_MODE_APPEND 0x40000000 >> +#define P9_STAT_MODE_EXCL 0x20000000 >> +#define P9_STAT_MODE_MOUNT 0x10000000 >> +#define P9_STAT_MODE_AUTH 0x08000000 >> +#define P9_STAT_MODE_TMP 0x04000000 >> +#define P9_STAT_MODE_SYMLINK 0x02000000 >> +#define P9_STAT_MODE_LINK 0x01000000 >> +#define P9_STAT_MODE_DEVICE 0x00800000 >> +#define P9_STAT_MODE_NAMED_PIPE 0x00200000 >> +#define P9_STAT_MODE_SOCKET 0x00100000 >> +#define P9_STAT_MODE_SETUID 0x00080000 >> +#define P9_STAT_MODE_SETGID 0x00040000 >> +#define P9_STAT_MODE_SETVTX 0x00010000 >> + >> +#define P9_STAT_MODE_SPECIAL (P9_STAT_MODE_NAMED_PIPE | \ >> + P9_STAT_MODE_SYMLINK | \ >> + P9_STAT_MODE_LINK | \ >> + P9_STAT_MODE_DEVICE) >> + >> + >> +/* This is the algorithm from ufs in spfs */ >> +static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp) >> +{ >> + size_t size; >> + >> + size = MIN(sizeof(stbuf->st_ino), sizeof(qidp->path)); >> + memcpy(&qidp->path,&stbuf->st_ino, size); >> + qidp->version = stbuf->st_mtime ^ (stbuf->st_size<< 8); >> + qidp->type = 0; >> + if (S_ISDIR(stbuf->st_mode)) >> + qidp->type |= P9_QID_TYPE_DIR; >> + if (S_ISLNK(stbuf->st_mode)) >> + qidp->type |= P9_QID_TYPE_SYMLINK; >> +} >> + >> +static void fid_to_qid(V9fsState *s, V9fsFidState *fidp, V9fsQID *qidp) >> +{ >> + struct stat stbuf; >> + int err; >> + >> + err = posix_lstat(s,&fidp->path,&stbuf); >> + BUG_ON(err == -1); >> + >> + stat_to_qid(&stbuf, qidp); >> +} >> + >> static V9fsPDU *alloc_pdu(V9fsState *s) >> { >> V9fsPDU *pdu = NULL; >> @@ -111,13 +229,6 @@ static void free_pdu(V9fsState *s, V9fsPDU *pdu) >> } >> } >> >> -static void v9fs_string_free(V9fsString *str) >> -{ >> - free(str->data); >> - str->data = NULL; >> - str->size = 0; >> -} >> - >> static size_t pdu_unpack(void *dst, V9fsPDU *pdu, size_t offset, >> size_t size) >> { >> struct iovec *sg = pdu->elem.out_sg; >> @@ -378,8 +489,33 @@ static void v9fs_version(V9fsState *s, V9fsPDU *pdu) >> >> static void v9fs_attach(V9fsState *s, V9fsPDU *pdu) >> { >> - if (debug_9p_pdu) >> - pprint_pdu(pdu); >> + int32_t fid, afid, n_uname; >> + V9fsString uname, aname; >> + V9fsFidState *fidp; >> + V9fsQID qid; >> + size_t offset = 7; >> + ssize_t err; >> + >> + pdu_unmarshal(pdu, offset, >> "ddssd",&fid,&afid,&uname,&aname,&n_uname); >> + >> + fidp = alloc_fid(s, fid); >> + if (fidp == NULL) { >> + err = -EINVAL; >> + goto out; >> + } >> + >> + fidp->uid = n_uname; >> + >> + v9fs_string_sprintf(&fidp->path, "%s", s->root); >> + fid_to_qid(s, fidp,&qid); >> + >> + offset += pdu_marshal(pdu, offset, "Q",&qid); >> + >> + err = offset; >> +out: >> + complete_pdu(s, pdu, err); >> + v9fs_string_free(&uname); >> + v9fs_string_free(&aname); >> } >> >> static void v9fs_stat(V9fsState *s, V9fsPDU *pdu) >> @@ -528,6 +664,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, >> const char *path) >> BUG_ON(s->root == NULL); >> s->uid = -1; >> >> + s->ops = virtio_9p_init_local(path); >> s->vdev.get_features = virtio_9p_get_features; >> >> return&s->vdev; >> diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h >> index 2aa67d0..8e15bf0 100644 >> --- a/hw/virtio-9p.h >> +++ b/hw/virtio-9p.h >> @@ -66,5 +66,38 @@ struct V9fsPDU >> V9fsPDU *next; >> }; >> >> +typedef struct V9fsPosixFileOpertions >> +{ >> + int (*lstat)(void *, const char *, struct stat *); >> + ssize_t (*readlink)(void *, const char *, char *, size_t); >> + int (*chmod)(void *, const char *, mode_t); >> + int (*chown)(void *, const char *, uid_t, gid_t); >> + int (*mknod)(void *, const char *, mode_t, dev_t); >> + int (*mksock)(void *, const char *); >> + int (*utime)(void *, const char *, const struct utimbuf *); >> + int (*remove)(void *, const char *); >> + int (*symlink)(void *, const char *, const char *); >> + int (*link)(void *, const char *, const char *); >> + int (*setuid)(void *, uid_t); >> + int (*close)(void *, int); >> + int (*closedir)(void *, DIR *); >> + DIR *(*opendir)(void *, const char *); >> + int (*open)(void *, const char *, int); >> + int (*open2)(void *, const char *, int, mode_t); >> + void (*rewinddir)(void *, DIR *); >> + off_t (*telldir)(void *, DIR *); >> + struct dirent *(*readdir)(void *, DIR *); >> + void (*seekdir)(void *, DIR *, off_t); >> + ssize_t (*readv)(void *, int, const struct iovec *, int); >> + ssize_t (*writev)(void *, int, const struct iovec *, int); >> + off_t (*lseek)(void *, int, off_t, int); >> + int (*mkdir)(void *, const char *, mode_t); >> + int (*fstat)(void *, int, struct stat *); >> + int (*rename)(void *, const char *, const char *); >> + int (*truncate)(void *, const char *, off_t); >> + void *opaque; >> +} V9fsPosixFileOperations; >> + >> +V9fsPosixFileOperations *virtio_9p_init_local(const char *path); >> >> #endif >> diff --git a/qemu-common.h b/qemu-common.h >> index 805be1a..ebe7088 100644 >> --- a/qemu-common.h >> +++ b/qemu-common.h >> @@ -159,6 +159,7 @@ void *qemu_mallocz(size_t size); >> void qemu_free(void *ptr); >> char *qemu_strdup(const char *str); >> char *qemu_strndup(const char *str, size_t size); >> +int qemu_vasprintf(char **strp, const char *fmt, va_list ap); >> >> void *get_mmap_addr(unsigned long size); >> >> diff --git a/qemu-malloc.c b/qemu-malloc.c >> index 6cdc5de..d6de067 100644 >> --- a/qemu-malloc.c >> +++ b/qemu-malloc.c >> @@ -98,3 +98,8 @@ char *qemu_strndup(const char *str, size_t size) >> >> return memcpy(new, str, size); >> } >> + >> +int qemu_vasprintf(char **strp, const char *fmt, va_list ap) >> +{ >> + return vasprintf(strp, fmt, ap); >> +} >> > > asprintf() is not universally available so it cannot be wrapped this > naively. Is there a way to find out what is generally available..and what is not? I know QEMU need to work with different OSes, do we have OS specific plug-ins to address these OS specific/dependent calls? Thanks, JV > > Regards, > > Anthony Liguori > > >
Anthony Liguori wrote: > On 03/16/2010 04:15 AM, Aneesh Kumar K.V wrote: >> From: Anthony Liguori<aliguori@us.ibm.com> >> >> [jvrao@linux.vnet.ibm.com: Added qemu_vasprintf] >> >> Signed-off-by: Anthony Liguori<aliguori@us.ibm.com> >> Signed-off-by: Aneesh Kumar K.V<aneesh.kumar@linux.vnet.ibm.com> >> --- >> Makefile.target | 2 +- >> hw/virtio-9p-local.c | 84 +++++++++++++++++++++++++++ >> hw/virtio-9p.c | 155 >> +++++++++++++++++++++++++++++++++++++++++++++++--- >> hw/virtio-9p.h | 33 +++++++++++ >> qemu-common.h | 1 + >> qemu-malloc.c | 5 ++ >> 6 files changed, 270 insertions(+), 10 deletions(-) >> create mode 100644 hw/virtio-9p-local.c >> >> diff --git a/Makefile.target b/Makefile.target >> index 33f9fcb..97f32a9 100644 >> --- a/Makefile.target >> +++ b/Makefile.target >> @@ -172,7 +172,7 @@ obj-y = vl.o async.o monitor.o pci.o pci_host.o >> pcie_host.o machine.o gdbstub.o >> # virtio has to be here due to weird dependency between PCI and >> virtio-net. >> # need to fix this properly >> obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o >> virtio-serial-bus.o >> -obj-y += virtio-9p.o virtio-9p-debug.o >> +obj-y += virtio-9p.o virtio-9p-debug.o virtio-9p-local.o >> obj-y += rwhandler.o >> obj-$(CONFIG_KVM) += kvm.o kvm-all.o >> obj-$(CONFIG_ISA_MMIO) += isa_mmio.o >> diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c >> new file mode 100644 >> index 0000000..1d2523b >> --- /dev/null >> +++ b/hw/virtio-9p-local.c >> > > This should be a logically separate patch. > >> @@ -0,0 +1,84 @@ >> +/* >> + * Virtio 9p Posix callback >> + * >> + * Copyright IBM, Corp. 2010 >> + * >> + * Authors: >> + * Anthony Liguori<aliguori@us.ibm.com> >> + * >> + * This work is licensed under the terms of the GNU GPL, version 2. See >> + * the COPYING file in the top-level directory. >> + * >> + */ >> +#include "virtio.h" >> +#include "pc.h" >> +#include "qemu_socket.h" >> +#include "virtio-9p.h" >> +#include<sys/uio.h> >> +#include<arpa/inet.h> >> +#include<assert.h> >> +#include<pwd.h> >> +#include<grp.h> >> +#include<sys/socket.h> >> +#include<sys/un.h> >> > > These headers are almost certainly going to break the build on windows. > Some care is needed here. I don't think we are going to build this on Windows. Will it be OK if we make changes to Makefile so that it is valid only on Linux? Thanks, JV > >> + >> +static const char *base_path; >> + >> +static const char *rpath(const char *path) >> +{ >> + /* FIXME: so wrong... */ >> + static char buffer[4096]; >> + snprintf(buffer, sizeof(buffer), "%s/%s", base_path, path); >> + return buffer; >> +} >> + >> +static int local_lstat(void *opaque, const char *path, struct stat >> *stbuf) >> +{ >> + return lstat(rpath(path), stbuf); >> +} >> + >> +static int local_setuid(void *opaque, uid_t uid) >> +{ >> + struct passwd *pw; >> + gid_t groups[33]; >> + int ngroups; >> + static uid_t cur_uid = -1; >> + >> + if (cur_uid == uid) >> + return 0; >> + >> + if (setreuid(0, 0)) >> + return -1; >> + >> + pw = getpwuid(uid); >> + if (pw == NULL) >> + return -1; >> + >> + ngroups = 33; >> + if (getgrouplist(pw->pw_name, pw->pw_gid, groups,&ngroups) == -1) >> + return -1; >> + >> + if (setgroups(ngroups, groups)) >> + return -1; >> + >> + if (setregid(-1, pw->pw_gid)) >> + return -1; >> + >> + if (setreuid(-1, uid)) >> + return -1; >> + >> + cur_uid = uid; >> + >> + return 0; >> +} >> + >> +static V9fsPosixFileOperations ops = { >> + .lstat = local_lstat, >> + .setuid = local_setuid, >> +}; >> + >> +V9fsPosixFileOperations *virtio_9p_init_local(const char *path) >> +{ >> + base_path = path; >> + return&ops; >> +} >> diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c >> index 53b3d78..fdff589 100644 >> --- a/hw/virtio-9p.c >> +++ b/hw/virtio-9p.c >> @@ -82,6 +82,7 @@ typedef struct V9fsState >> V9fsPDU pdus[MAX_REQ]; >> V9fsPDU *free_pdu; >> V9fsFidState *fid_list; >> + V9fsPosixFileOperations *ops; >> char *root; >> uid_t uid; >> } V9fsState; >> @@ -91,6 +92,123 @@ int debug_9p_pdu = 1; >> >> extern void pprint_pdu(V9fsPDU *pdu); >> >> +static int posix_lstat(V9fsState *s, V9fsString *path, struct stat >> *stbuf) >> +{ >> + return s->ops->lstat(s->ops->opaque, path->data, stbuf); >> +} >> + >> +static int posix_setuid(V9fsState *s, uid_t uid) >> +{ >> + return s->ops->setuid(s->ops->opaque, uid); >> +} >> + >> +static void v9fs_string_free(V9fsString *str) >> +{ >> + qemu_free(str->data); >> + str->data = NULL; >> + str->size = 0; >> +} >> + >> +static void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...) >> +{ >> + va_list ap; >> + int err; >> + >> + v9fs_string_free(str); >> + >> + va_start(ap, fmt); >> + err = qemu_vasprintf(&str->data, fmt, ap); >> + BUG_ON(err == -1); >> + va_end(ap); >> + >> + str->size = err; >> +} >> + >> +static V9fsFidState *lookup_fid(V9fsState *s, int32_t fid) >> +{ >> + V9fsFidState *f; >> + >> + for (f = s->fid_list; f; f = f->next) { >> + if (f->fid == fid) { >> + posix_setuid(s, f->uid); >> + return f; >> + } >> + } >> + >> + return NULL; >> +} >> + >> +static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid) >> +{ >> + V9fsFidState *f; >> + >> + f = lookup_fid(s, fid); >> + if (f) >> + return NULL; >> + >> + f = qemu_mallocz(sizeof(V9fsFidState)); >> + BUG_ON(f == NULL); >> + >> + f->fid = fid; >> + f->fd = -1; >> + f->dir = NULL; >> + >> + f->next = s->fid_list; >> + s->fid_list = f; >> + >> + return f; >> +} >> + >> +#define P9_QID_TYPE_DIR 0x80 >> +#define P9_QID_TYPE_SYMLINK 0x02 >> + >> +#define P9_STAT_MODE_DIR 0x80000000 >> +#define P9_STAT_MODE_APPEND 0x40000000 >> +#define P9_STAT_MODE_EXCL 0x20000000 >> +#define P9_STAT_MODE_MOUNT 0x10000000 >> +#define P9_STAT_MODE_AUTH 0x08000000 >> +#define P9_STAT_MODE_TMP 0x04000000 >> +#define P9_STAT_MODE_SYMLINK 0x02000000 >> +#define P9_STAT_MODE_LINK 0x01000000 >> +#define P9_STAT_MODE_DEVICE 0x00800000 >> +#define P9_STAT_MODE_NAMED_PIPE 0x00200000 >> +#define P9_STAT_MODE_SOCKET 0x00100000 >> +#define P9_STAT_MODE_SETUID 0x00080000 >> +#define P9_STAT_MODE_SETGID 0x00040000 >> +#define P9_STAT_MODE_SETVTX 0x00010000 >> + >> +#define P9_STAT_MODE_SPECIAL (P9_STAT_MODE_NAMED_PIPE | \ >> + P9_STAT_MODE_SYMLINK | \ >> + P9_STAT_MODE_LINK | \ >> + P9_STAT_MODE_DEVICE) >> + >> + >> +/* This is the algorithm from ufs in spfs */ >> +static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp) >> +{ >> + size_t size; >> + >> + size = MIN(sizeof(stbuf->st_ino), sizeof(qidp->path)); >> + memcpy(&qidp->path,&stbuf->st_ino, size); >> + qidp->version = stbuf->st_mtime ^ (stbuf->st_size<< 8); >> + qidp->type = 0; >> + if (S_ISDIR(stbuf->st_mode)) >> + qidp->type |= P9_QID_TYPE_DIR; >> + if (S_ISLNK(stbuf->st_mode)) >> + qidp->type |= P9_QID_TYPE_SYMLINK; >> +} >> + >> +static void fid_to_qid(V9fsState *s, V9fsFidState *fidp, V9fsQID *qidp) >> +{ >> + struct stat stbuf; >> + int err; >> + >> + err = posix_lstat(s,&fidp->path,&stbuf); >> + BUG_ON(err == -1); >> + >> + stat_to_qid(&stbuf, qidp); >> +} >> + >> static V9fsPDU *alloc_pdu(V9fsState *s) >> { >> V9fsPDU *pdu = NULL; >> @@ -111,13 +229,6 @@ static void free_pdu(V9fsState *s, V9fsPDU *pdu) >> } >> } >> >> -static void v9fs_string_free(V9fsString *str) >> -{ >> - free(str->data); >> - str->data = NULL; >> - str->size = 0; >> -} >> - >> static size_t pdu_unpack(void *dst, V9fsPDU *pdu, size_t offset, >> size_t size) >> { >> struct iovec *sg = pdu->elem.out_sg; >> @@ -378,8 +489,33 @@ static void v9fs_version(V9fsState *s, V9fsPDU *pdu) >> >> static void v9fs_attach(V9fsState *s, V9fsPDU *pdu) >> { >> - if (debug_9p_pdu) >> - pprint_pdu(pdu); >> + int32_t fid, afid, n_uname; >> + V9fsString uname, aname; >> + V9fsFidState *fidp; >> + V9fsQID qid; >> + size_t offset = 7; >> + ssize_t err; >> + >> + pdu_unmarshal(pdu, offset, >> "ddssd",&fid,&afid,&uname,&aname,&n_uname); >> + >> + fidp = alloc_fid(s, fid); >> + if (fidp == NULL) { >> + err = -EINVAL; >> + goto out; >> + } >> + >> + fidp->uid = n_uname; >> + >> + v9fs_string_sprintf(&fidp->path, "%s", s->root); >> + fid_to_qid(s, fidp,&qid); >> + >> + offset += pdu_marshal(pdu, offset, "Q",&qid); >> + >> + err = offset; >> +out: >> + complete_pdu(s, pdu, err); >> + v9fs_string_free(&uname); >> + v9fs_string_free(&aname); >> } >> >> static void v9fs_stat(V9fsState *s, V9fsPDU *pdu) >> @@ -528,6 +664,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, >> const char *path) >> BUG_ON(s->root == NULL); >> s->uid = -1; >> >> + s->ops = virtio_9p_init_local(path); >> s->vdev.get_features = virtio_9p_get_features; >> >> return&s->vdev; >> diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h >> index 2aa67d0..8e15bf0 100644 >> --- a/hw/virtio-9p.h >> +++ b/hw/virtio-9p.h >> @@ -66,5 +66,38 @@ struct V9fsPDU >> V9fsPDU *next; >> }; >> >> +typedef struct V9fsPosixFileOpertions >> +{ >> + int (*lstat)(void *, const char *, struct stat *); >> + ssize_t (*readlink)(void *, const char *, char *, size_t); >> + int (*chmod)(void *, const char *, mode_t); >> + int (*chown)(void *, const char *, uid_t, gid_t); >> + int (*mknod)(void *, const char *, mode_t, dev_t); >> + int (*mksock)(void *, const char *); >> + int (*utime)(void *, const char *, const struct utimbuf *); >> + int (*remove)(void *, const char *); >> + int (*symlink)(void *, const char *, const char *); >> + int (*link)(void *, const char *, const char *); >> + int (*setuid)(void *, uid_t); >> + int (*close)(void *, int); >> + int (*closedir)(void *, DIR *); >> + DIR *(*opendir)(void *, const char *); >> + int (*open)(void *, const char *, int); >> + int (*open2)(void *, const char *, int, mode_t); >> + void (*rewinddir)(void *, DIR *); >> + off_t (*telldir)(void *, DIR *); >> + struct dirent *(*readdir)(void *, DIR *); >> + void (*seekdir)(void *, DIR *, off_t); >> + ssize_t (*readv)(void *, int, const struct iovec *, int); >> + ssize_t (*writev)(void *, int, const struct iovec *, int); >> + off_t (*lseek)(void *, int, off_t, int); >> + int (*mkdir)(void *, const char *, mode_t); >> + int (*fstat)(void *, int, struct stat *); >> + int (*rename)(void *, const char *, const char *); >> + int (*truncate)(void *, const char *, off_t); >> + void *opaque; >> +} V9fsPosixFileOperations; >> + >> +V9fsPosixFileOperations *virtio_9p_init_local(const char *path); >> >> #endif >> diff --git a/qemu-common.h b/qemu-common.h >> index 805be1a..ebe7088 100644 >> --- a/qemu-common.h >> +++ b/qemu-common.h >> @@ -159,6 +159,7 @@ void *qemu_mallocz(size_t size); >> void qemu_free(void *ptr); >> char *qemu_strdup(const char *str); >> char *qemu_strndup(const char *str, size_t size); >> +int qemu_vasprintf(char **strp, const char *fmt, va_list ap); >> >> void *get_mmap_addr(unsigned long size); >> >> diff --git a/qemu-malloc.c b/qemu-malloc.c >> index 6cdc5de..d6de067 100644 >> --- a/qemu-malloc.c >> +++ b/qemu-malloc.c >> @@ -98,3 +98,8 @@ char *qemu_strndup(const char *str, size_t size) >> >> return memcpy(new, str, size); >> } >> + >> +int qemu_vasprintf(char **strp, const char *fmt, va_list ap) >> +{ >> + return vasprintf(strp, fmt, ap); >> +} >> > > asprintf() is not universally available so it cannot be wrapped this > naively. > > Regards, > > Anthony Liguori > > >
diff --git a/Makefile.target b/Makefile.target index 33f9fcb..97f32a9 100644 --- a/Makefile.target +++ b/Makefile.target @@ -172,7 +172,7 @@ obj-y = vl.o async.o monitor.o pci.o pci_host.o pcie_host.o machine.o gdbstub.o # virtio has to be here due to weird dependency between PCI and virtio-net. # need to fix this properly obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-pci.o virtio-serial-bus.o -obj-y += virtio-9p.o virtio-9p-debug.o +obj-y += virtio-9p.o virtio-9p-debug.o virtio-9p-local.o obj-y += rwhandler.o obj-$(CONFIG_KVM) += kvm.o kvm-all.o obj-$(CONFIG_ISA_MMIO) += isa_mmio.o diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c new file mode 100644 index 0000000..1d2523b --- /dev/null +++ b/hw/virtio-9p-local.c @@ -0,0 +1,84 @@ +/* + * Virtio 9p Posix callback + * + * Copyright IBM, Corp. 2010 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ +#include "virtio.h" +#include "pc.h" +#include "qemu_socket.h" +#include "virtio-9p.h" +#include <sys/uio.h> +#include <arpa/inet.h> +#include <assert.h> +#include <pwd.h> +#include <grp.h> +#include <sys/socket.h> +#include <sys/un.h> + +static const char *base_path; + +static const char *rpath(const char *path) +{ + /* FIXME: so wrong... */ + static char buffer[4096]; + snprintf(buffer, sizeof(buffer), "%s/%s", base_path, path); + return buffer; +} + +static int local_lstat(void *opaque, const char *path, struct stat *stbuf) +{ + return lstat(rpath(path), stbuf); +} + +static int local_setuid(void *opaque, uid_t uid) +{ + struct passwd *pw; + gid_t groups[33]; + int ngroups; + static uid_t cur_uid = -1; + + if (cur_uid == uid) + return 0; + + if (setreuid(0, 0)) + return -1; + + pw = getpwuid(uid); + if (pw == NULL) + return -1; + + ngroups = 33; + if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups) == -1) + return -1; + + if (setgroups(ngroups, groups)) + return -1; + + if (setregid(-1, pw->pw_gid)) + return -1; + + if (setreuid(-1, uid)) + return -1; + + cur_uid = uid; + + return 0; +} + +static V9fsPosixFileOperations ops = { + .lstat = local_lstat, + .setuid = local_setuid, +}; + +V9fsPosixFileOperations *virtio_9p_init_local(const char *path) +{ + base_path = path; + return &ops; +} diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c index 53b3d78..fdff589 100644 --- a/hw/virtio-9p.c +++ b/hw/virtio-9p.c @@ -82,6 +82,7 @@ typedef struct V9fsState V9fsPDU pdus[MAX_REQ]; V9fsPDU *free_pdu; V9fsFidState *fid_list; + V9fsPosixFileOperations *ops; char *root; uid_t uid; } V9fsState; @@ -91,6 +92,123 @@ int debug_9p_pdu = 1; extern void pprint_pdu(V9fsPDU *pdu); +static int posix_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf) +{ + return s->ops->lstat(s->ops->opaque, path->data, stbuf); +} + +static int posix_setuid(V9fsState *s, uid_t uid) +{ + return s->ops->setuid(s->ops->opaque, uid); +} + +static void v9fs_string_free(V9fsString *str) +{ + qemu_free(str->data); + str->data = NULL; + str->size = 0; +} + +static void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...) +{ + va_list ap; + int err; + + v9fs_string_free(str); + + va_start(ap, fmt); + err = qemu_vasprintf(&str->data, fmt, ap); + BUG_ON(err == -1); + va_end(ap); + + str->size = err; +} + +static V9fsFidState *lookup_fid(V9fsState *s, int32_t fid) +{ + V9fsFidState *f; + + for (f = s->fid_list; f; f = f->next) { + if (f->fid == fid) { + posix_setuid(s, f->uid); + return f; + } + } + + return NULL; +} + +static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid) +{ + V9fsFidState *f; + + f = lookup_fid(s, fid); + if (f) + return NULL; + + f = qemu_mallocz(sizeof(V9fsFidState)); + BUG_ON(f == NULL); + + f->fid = fid; + f->fd = -1; + f->dir = NULL; + + f->next = s->fid_list; + s->fid_list = f; + + return f; +} + +#define P9_QID_TYPE_DIR 0x80 +#define P9_QID_TYPE_SYMLINK 0x02 + +#define P9_STAT_MODE_DIR 0x80000000 +#define P9_STAT_MODE_APPEND 0x40000000 +#define P9_STAT_MODE_EXCL 0x20000000 +#define P9_STAT_MODE_MOUNT 0x10000000 +#define P9_STAT_MODE_AUTH 0x08000000 +#define P9_STAT_MODE_TMP 0x04000000 +#define P9_STAT_MODE_SYMLINK 0x02000000 +#define P9_STAT_MODE_LINK 0x01000000 +#define P9_STAT_MODE_DEVICE 0x00800000 +#define P9_STAT_MODE_NAMED_PIPE 0x00200000 +#define P9_STAT_MODE_SOCKET 0x00100000 +#define P9_STAT_MODE_SETUID 0x00080000 +#define P9_STAT_MODE_SETGID 0x00040000 +#define P9_STAT_MODE_SETVTX 0x00010000 + +#define P9_STAT_MODE_SPECIAL (P9_STAT_MODE_NAMED_PIPE | \ + P9_STAT_MODE_SYMLINK | \ + P9_STAT_MODE_LINK | \ + P9_STAT_MODE_DEVICE) + + +/* This is the algorithm from ufs in spfs */ +static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp) +{ + size_t size; + + size = MIN(sizeof(stbuf->st_ino), sizeof(qidp->path)); + memcpy(&qidp->path, &stbuf->st_ino, size); + qidp->version = stbuf->st_mtime ^ (stbuf->st_size << 8); + qidp->type = 0; + if (S_ISDIR(stbuf->st_mode)) + qidp->type |= P9_QID_TYPE_DIR; + if (S_ISLNK(stbuf->st_mode)) + qidp->type |= P9_QID_TYPE_SYMLINK; +} + +static void fid_to_qid(V9fsState *s, V9fsFidState *fidp, V9fsQID *qidp) +{ + struct stat stbuf; + int err; + + err = posix_lstat(s, &fidp->path, &stbuf); + BUG_ON(err == -1); + + stat_to_qid(&stbuf, qidp); +} + static V9fsPDU *alloc_pdu(V9fsState *s) { V9fsPDU *pdu = NULL; @@ -111,13 +229,6 @@ static void free_pdu(V9fsState *s, V9fsPDU *pdu) } } -static void v9fs_string_free(V9fsString *str) -{ - free(str->data); - str->data = NULL; - str->size = 0; -} - static size_t pdu_unpack(void *dst, V9fsPDU *pdu, size_t offset, size_t size) { struct iovec *sg = pdu->elem.out_sg; @@ -378,8 +489,33 @@ static void v9fs_version(V9fsState *s, V9fsPDU *pdu) static void v9fs_attach(V9fsState *s, V9fsPDU *pdu) { - if (debug_9p_pdu) - pprint_pdu(pdu); + int32_t fid, afid, n_uname; + V9fsString uname, aname; + V9fsFidState *fidp; + V9fsQID qid; + size_t offset = 7; + ssize_t err; + + pdu_unmarshal(pdu, offset, "ddssd", &fid, &afid, &uname, &aname, &n_uname); + + fidp = alloc_fid(s, fid); + if (fidp == NULL) { + err = -EINVAL; + goto out; + } + + fidp->uid = n_uname; + + v9fs_string_sprintf(&fidp->path, "%s", s->root); + fid_to_qid(s, fidp, &qid); + + offset += pdu_marshal(pdu, offset, "Q", &qid); + + err = offset; +out: + complete_pdu(s, pdu, err); + v9fs_string_free(&uname); + v9fs_string_free(&aname); } static void v9fs_stat(V9fsState *s, V9fsPDU *pdu) @@ -528,6 +664,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, const char *path) BUG_ON(s->root == NULL); s->uid = -1; + s->ops = virtio_9p_init_local(path); s->vdev.get_features = virtio_9p_get_features; return &s->vdev; diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h index 2aa67d0..8e15bf0 100644 --- a/hw/virtio-9p.h +++ b/hw/virtio-9p.h @@ -66,5 +66,38 @@ struct V9fsPDU V9fsPDU *next; }; +typedef struct V9fsPosixFileOpertions +{ + int (*lstat)(void *, const char *, struct stat *); + ssize_t (*readlink)(void *, const char *, char *, size_t); + int (*chmod)(void *, const char *, mode_t); + int (*chown)(void *, const char *, uid_t, gid_t); + int (*mknod)(void *, const char *, mode_t, dev_t); + int (*mksock)(void *, const char *); + int (*utime)(void *, const char *, const struct utimbuf *); + int (*remove)(void *, const char *); + int (*symlink)(void *, const char *, const char *); + int (*link)(void *, const char *, const char *); + int (*setuid)(void *, uid_t); + int (*close)(void *, int); + int (*closedir)(void *, DIR *); + DIR *(*opendir)(void *, const char *); + int (*open)(void *, const char *, int); + int (*open2)(void *, const char *, int, mode_t); + void (*rewinddir)(void *, DIR *); + off_t (*telldir)(void *, DIR *); + struct dirent *(*readdir)(void *, DIR *); + void (*seekdir)(void *, DIR *, off_t); + ssize_t (*readv)(void *, int, const struct iovec *, int); + ssize_t (*writev)(void *, int, const struct iovec *, int); + off_t (*lseek)(void *, int, off_t, int); + int (*mkdir)(void *, const char *, mode_t); + int (*fstat)(void *, int, struct stat *); + int (*rename)(void *, const char *, const char *); + int (*truncate)(void *, const char *, off_t); + void *opaque; +} V9fsPosixFileOperations; + +V9fsPosixFileOperations *virtio_9p_init_local(const char *path); #endif diff --git a/qemu-common.h b/qemu-common.h index 805be1a..ebe7088 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -159,6 +159,7 @@ void *qemu_mallocz(size_t size); void qemu_free(void *ptr); char *qemu_strdup(const char *str); char *qemu_strndup(const char *str, size_t size); +int qemu_vasprintf(char **strp, const char *fmt, va_list ap); void *get_mmap_addr(unsigned long size); diff --git a/qemu-malloc.c b/qemu-malloc.c index 6cdc5de..d6de067 100644 --- a/qemu-malloc.c +++ b/qemu-malloc.c @@ -98,3 +98,8 @@ char *qemu_strndup(const char *str, size_t size) return memcpy(new, str, size); } + +int qemu_vasprintf(char **strp, const char *fmt, va_list ap) +{ + return vasprintf(strp, fmt, ap); +}