Annotation of qemu/hw/9pfs/virtio-9p-proxy.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Virtio 9p Proxy callback
        !             3:  *
        !             4:  * Copyright IBM, Corp. 2011
        !             5:  *
        !             6:  * Authors:
        !             7:  * M. Mohan Kumar <[email protected]>
        !             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: #include <sys/socket.h>
        !            13: #include <sys/un.h>
        !            14: #include "hw/virtio.h"
        !            15: #include "virtio-9p.h"
        !            16: #include "fsdev/qemu-fsdev.h"
        !            17: #include "virtio-9p-proxy.h"
        !            18: 
        !            19: typedef struct V9fsProxy {
        !            20:     int sockfd;
        !            21:     QemuMutex mutex;
        !            22:     struct iovec in_iovec;
        !            23:     struct iovec out_iovec;
        !            24: } V9fsProxy;
        !            25: 
        !            26: /*
        !            27:  * Return received file descriptor on success in *status.
        !            28:  * errno is also returned on *status (which will be < 0)
        !            29:  * return < 0 on transport error.
        !            30:  */
        !            31: static int v9fs_receivefd(int sockfd, int *status)
        !            32: {
        !            33:     struct iovec iov;
        !            34:     struct msghdr msg;
        !            35:     struct cmsghdr *cmsg;
        !            36:     int retval, data, fd;
        !            37:     union MsgControl msg_control;
        !            38: 
        !            39:     iov.iov_base = &data;
        !            40:     iov.iov_len = sizeof(data);
        !            41: 
        !            42:     memset(&msg, 0, sizeof(msg));
        !            43:     msg.msg_iov = &iov;
        !            44:     msg.msg_iovlen = 1;
        !            45:     msg.msg_control = &msg_control;
        !            46:     msg.msg_controllen = sizeof(msg_control);
        !            47: 
        !            48:     do {
        !            49:         retval = recvmsg(sockfd, &msg, 0);
        !            50:     } while (retval < 0 && errno == EINTR);
        !            51:     if (retval <= 0) {
        !            52:         return retval;
        !            53:     }
        !            54:     /*
        !            55:      * data is set to V9FS_FD_VALID, if ancillary data is sent.  If this
        !            56:      * request doesn't need ancillary data (fd) or an error occurred,
        !            57:      * data is set to negative errno value.
        !            58:      */
        !            59:     if (data != V9FS_FD_VALID) {
        !            60:         *status = data;
        !            61:         return 0;
        !            62:     }
        !            63:     /*
        !            64:      * File descriptor (fd) is sent in the ancillary data. Check if we
        !            65:      * indeed received it. One of the reasons to fail to receive it is if
        !            66:      * we exceeded the maximum number of file descriptors!
        !            67:      */
        !            68:     for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
        !            69:         if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
        !            70:             cmsg->cmsg_level != SOL_SOCKET ||
        !            71:             cmsg->cmsg_type != SCM_RIGHTS) {
        !            72:             continue;
        !            73:         }
        !            74:         fd = *((int *)CMSG_DATA(cmsg));
        !            75:         *status = fd;
        !            76:         return 0;
        !            77:     }
        !            78:     *status = -ENFILE;  /* Ancillary data sent but not received */
        !            79:     return 0;
        !            80: }
        !            81: 
        !            82: static ssize_t socket_read(int sockfd, void *buff, size_t size)
        !            83: {
        !            84:     ssize_t retval, total = 0;
        !            85: 
        !            86:     while (size) {
        !            87:         retval = read(sockfd, buff, size);
        !            88:         if (retval == 0) {
        !            89:             return -EIO;
        !            90:         }
        !            91:         if (retval < 0) {
        !            92:             if (errno == EINTR) {
        !            93:                 continue;
        !            94:             }
        !            95:             return -errno;
        !            96:         }
        !            97:         size -= retval;
        !            98:         buff += retval;
        !            99:         total += retval;
        !           100:     }
        !           101:     return total;
        !           102: }
        !           103: 
        !           104: /* Converts proxy_statfs to VFS statfs structure */
        !           105: static void prstatfs_to_statfs(struct statfs *stfs, ProxyStatFS *prstfs)
        !           106: {
        !           107:     memset(stfs, 0, sizeof(*stfs));
        !           108:     stfs->f_type = prstfs->f_type;
        !           109:     stfs->f_bsize = prstfs->f_bsize;
        !           110:     stfs->f_blocks = prstfs->f_blocks;
        !           111:     stfs->f_bfree = prstfs->f_bfree;
        !           112:     stfs->f_bavail = prstfs->f_bavail;
        !           113:     stfs->f_files = prstfs->f_files;
        !           114:     stfs->f_ffree = prstfs->f_ffree;
        !           115:     stfs->f_fsid.__val[0] = prstfs->f_fsid[0] & 0xFFFFFFFFU;
        !           116:     stfs->f_fsid.__val[1] = prstfs->f_fsid[1] >> 32 & 0xFFFFFFFFU;
        !           117:     stfs->f_namelen = prstfs->f_namelen;
        !           118:     stfs->f_frsize = prstfs->f_frsize;
        !           119: }
        !           120: 
        !           121: /* Converts proxy_stat structure to VFS stat structure */
        !           122: static void prstat_to_stat(struct stat *stbuf, ProxyStat *prstat)
        !           123: {
        !           124:    memset(stbuf, 0, sizeof(*stbuf));
        !           125:    stbuf->st_dev = prstat->st_dev;
        !           126:    stbuf->st_ino = prstat->st_ino;
        !           127:    stbuf->st_nlink = prstat->st_nlink;
        !           128:    stbuf->st_mode = prstat->st_mode;
        !           129:    stbuf->st_uid = prstat->st_uid;
        !           130:    stbuf->st_gid = prstat->st_gid;
        !           131:    stbuf->st_rdev = prstat->st_rdev;
        !           132:    stbuf->st_size = prstat->st_size;
        !           133:    stbuf->st_blksize = prstat->st_blksize;
        !           134:    stbuf->st_blocks = prstat->st_blocks;
        !           135:    stbuf->st_atim.tv_sec = prstat->st_atim_sec;
        !           136:    stbuf->st_atim.tv_nsec = prstat->st_atim_nsec;
        !           137:    stbuf->st_mtime = prstat->st_mtim_sec;
        !           138:    stbuf->st_mtim.tv_nsec = prstat->st_mtim_nsec;
        !           139:    stbuf->st_ctime = prstat->st_ctim_sec;
        !           140:    stbuf->st_ctim.tv_nsec = prstat->st_ctim_nsec;
        !           141: }
        !           142: 
        !           143: /*
        !           144:  * Response contains two parts
        !           145:  * {header, data}
        !           146:  * header.type == T_ERROR, data -> -errno
        !           147:  * header.type == T_SUCCESS, data -> response
        !           148:  * size of errno/response is given by header.size
        !           149:  * returns < 0, on transport error. response is
        !           150:  * valid only if status >= 0.
        !           151:  */
        !           152: static int v9fs_receive_response(V9fsProxy *proxy, int type,
        !           153:                                  int *status, void *response)
        !           154: {
        !           155:     int retval;
        !           156:     ProxyHeader header;
        !           157:     struct iovec *reply = &proxy->in_iovec;
        !           158: 
        !           159:     *status = 0;
        !           160:     reply->iov_len = 0;
        !           161:     retval = socket_read(proxy->sockfd, reply->iov_base, PROXY_HDR_SZ);
        !           162:     if (retval < 0) {
        !           163:         return retval;
        !           164:     }
        !           165:     reply->iov_len = PROXY_HDR_SZ;
        !           166:     proxy_unmarshal(reply, 0, "dd", &header.type, &header.size);
        !           167:     /*
        !           168:      * if response size > PROXY_MAX_IO_SZ, read the response but ignore it and
        !           169:      * return -ENOBUFS
        !           170:      */
        !           171:     if (header.size > PROXY_MAX_IO_SZ) {
        !           172:         int count;
        !           173:         while (header.size > 0) {
        !           174:             count = MIN(PROXY_MAX_IO_SZ, header.size);
        !           175:             count = socket_read(proxy->sockfd, reply->iov_base, count);
        !           176:             if (count < 0) {
        !           177:                 return count;
        !           178:             }
        !           179:             header.size -= count;
        !           180:         }
        !           181:         *status = -ENOBUFS;
        !           182:         return 0;
        !           183:     }
        !           184: 
        !           185:     retval = socket_read(proxy->sockfd,
        !           186:                          reply->iov_base + PROXY_HDR_SZ, header.size);
        !           187:     if (retval < 0) {
        !           188:         return retval;
        !           189:     }
        !           190:     reply->iov_len += header.size;
        !           191:     /* there was an error during processing request */
        !           192:     if (header.type == T_ERROR) {
        !           193:         int ret;
        !           194:         ret = proxy_unmarshal(reply, PROXY_HDR_SZ, "d", status);
        !           195:         if (ret < 0) {
        !           196:             *status = ret;
        !           197:         }
        !           198:         return 0;
        !           199:     }
        !           200: 
        !           201:     switch (type) {
        !           202:     case T_LSTAT: {
        !           203:         ProxyStat prstat;
        !           204:         retval = proxy_unmarshal(reply, PROXY_HDR_SZ,
        !           205:                                  "qqqdddqqqqqqqqqq", &prstat.st_dev,
        !           206:                                  &prstat.st_ino, &prstat.st_nlink,
        !           207:                                  &prstat.st_mode, &prstat.st_uid,
        !           208:                                  &prstat.st_gid, &prstat.st_rdev,
        !           209:                                  &prstat.st_size, &prstat.st_blksize,
        !           210:                                  &prstat.st_blocks,
        !           211:                                  &prstat.st_atim_sec, &prstat.st_atim_nsec,
        !           212:                                  &prstat.st_mtim_sec, &prstat.st_mtim_nsec,
        !           213:                                  &prstat.st_ctim_sec, &prstat.st_ctim_nsec);
        !           214:         prstat_to_stat(response, &prstat);
        !           215:         break;
        !           216:     }
        !           217:     case T_STATFS: {
        !           218:         ProxyStatFS prstfs;
        !           219:         retval = proxy_unmarshal(reply, PROXY_HDR_SZ,
        !           220:                                  "qqqqqqqqqqq", &prstfs.f_type,
        !           221:                                  &prstfs.f_bsize, &prstfs.f_blocks,
        !           222:                                  &prstfs.f_bfree, &prstfs.f_bavail,
        !           223:                                  &prstfs.f_files, &prstfs.f_ffree,
        !           224:                                  &prstfs.f_fsid[0], &prstfs.f_fsid[1],
        !           225:                                  &prstfs.f_namelen, &prstfs.f_frsize);
        !           226:         prstatfs_to_statfs(response, &prstfs);
        !           227:         break;
        !           228:     }
        !           229:     case T_READLINK: {
        !           230:         V9fsString target;
        !           231:         v9fs_string_init(&target);
        !           232:         retval = proxy_unmarshal(reply, PROXY_HDR_SZ, "s", &target);
        !           233:         strcpy(response, target.data);
        !           234:         v9fs_string_free(&target);
        !           235:         break;
        !           236:     }
        !           237:     case T_LGETXATTR:
        !           238:     case T_LLISTXATTR: {
        !           239:         V9fsString xattr;
        !           240:         v9fs_string_init(&xattr);
        !           241:         retval = proxy_unmarshal(reply, PROXY_HDR_SZ, "s", &xattr);
        !           242:         memcpy(response, xattr.data, xattr.size);
        !           243:         v9fs_string_free(&xattr);
        !           244:         break;
        !           245:     }
        !           246:     case T_GETVERSION:
        !           247:         proxy_unmarshal(reply, PROXY_HDR_SZ, "q", response);
        !           248:         break;
        !           249:     default:
        !           250:         return -1;
        !           251:     }
        !           252:     if (retval < 0) {
        !           253:         *status  = retval;
        !           254:     }
        !           255:     return 0;
        !           256: }
        !           257: 
        !           258: /*
        !           259:  * return < 0 on transport error.
        !           260:  * *status is valid only if return >= 0
        !           261:  */
        !           262: static int v9fs_receive_status(V9fsProxy *proxy,
        !           263:                                struct iovec *reply, int *status)
        !           264: {
        !           265:     int retval;
        !           266:     ProxyHeader header;
        !           267: 
        !           268:     *status = 0;
        !           269:     reply->iov_len = 0;
        !           270:     retval = socket_read(proxy->sockfd, reply->iov_base, PROXY_HDR_SZ);
        !           271:     if (retval < 0) {
        !           272:         return retval;
        !           273:     }
        !           274:     reply->iov_len = PROXY_HDR_SZ;
        !           275:     proxy_unmarshal(reply, 0, "dd", &header.type, &header.size);
        !           276:     if (header.size != sizeof(int)) {
        !           277:         *status = -ENOBUFS;
        !           278:         return 0;
        !           279:     }
        !           280:     retval = socket_read(proxy->sockfd,
        !           281:                          reply->iov_base + PROXY_HDR_SZ, header.size);
        !           282:     if (retval < 0) {
        !           283:         return retval;
        !           284:     }
        !           285:     reply->iov_len += header.size;
        !           286:     proxy_unmarshal(reply, PROXY_HDR_SZ, "d", status);
        !           287:     return 0;
        !           288: }
        !           289: 
        !           290: /*
        !           291:  * Proxy->header and proxy->request written to socket by QEMU process.
        !           292:  * This request read by proxy helper process
        !           293:  * returns 0 on success and -errno on error
        !           294:  */
        !           295: static int v9fs_request(V9fsProxy *proxy, int type,
        !           296:                         void *response, const char *fmt, ...)
        !           297: {
        !           298:     dev_t rdev;
        !           299:     va_list ap;
        !           300:     int size = 0;
        !           301:     int retval = 0;
        !           302:     uint64_t offset;
        !           303:     ProxyHeader header = { 0, 0};
        !           304:     struct timespec spec[2];
        !           305:     int flags, mode, uid, gid;
        !           306:     V9fsString *name, *value;
        !           307:     V9fsString *path, *oldpath;
        !           308:     struct iovec *iovec = NULL, *reply = NULL;
        !           309: 
        !           310:     qemu_mutex_lock(&proxy->mutex);
        !           311: 
        !           312:     if (proxy->sockfd == -1) {
        !           313:         retval = -EIO;
        !           314:         goto err_out;
        !           315:     }
        !           316:     iovec = &proxy->out_iovec;
        !           317:     reply = &proxy->in_iovec;
        !           318:     va_start(ap, fmt);
        !           319:     switch (type) {
        !           320:     case T_OPEN:
        !           321:         path = va_arg(ap, V9fsString *);
        !           322:         flags = va_arg(ap, int);
        !           323:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sd", path, flags);
        !           324:         if (retval > 0) {
        !           325:             header.size = retval;
        !           326:             header.type = T_OPEN;
        !           327:         }
        !           328:         break;
        !           329:     case T_CREATE:
        !           330:         path = va_arg(ap, V9fsString *);
        !           331:         flags = va_arg(ap, int);
        !           332:         mode = va_arg(ap, int);
        !           333:         uid = va_arg(ap, int);
        !           334:         gid = va_arg(ap, int);
        !           335:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sdddd", path,
        !           336:                                     flags, mode, uid, gid);
        !           337:         if (retval > 0) {
        !           338:             header.size = retval;
        !           339:             header.type = T_CREATE;
        !           340:         }
        !           341:         break;
        !           342:     case T_MKNOD:
        !           343:         path = va_arg(ap, V9fsString *);
        !           344:         mode = va_arg(ap, int);
        !           345:         rdev = va_arg(ap, long int);
        !           346:         uid = va_arg(ap, int);
        !           347:         gid = va_arg(ap, int);
        !           348:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddsdq",
        !           349:                                     uid, gid, path, mode, rdev);
        !           350:         if (retval > 0) {
        !           351:             header.size = retval;
        !           352:             header.type = T_MKNOD;
        !           353:         }
        !           354:         break;
        !           355:     case T_MKDIR:
        !           356:         path = va_arg(ap, V9fsString *);
        !           357:         mode = va_arg(ap, int);
        !           358:         uid = va_arg(ap, int);
        !           359:         gid = va_arg(ap, int);
        !           360:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddsd",
        !           361:                                     uid, gid, path, mode);
        !           362:         if (retval > 0) {
        !           363:             header.size = retval;
        !           364:             header.type = T_MKDIR;
        !           365:         }
        !           366:         break;
        !           367:     case T_SYMLINK:
        !           368:         oldpath = va_arg(ap, V9fsString *);
        !           369:         path = va_arg(ap, V9fsString *);
        !           370:         uid = va_arg(ap, int);
        !           371:         gid = va_arg(ap, int);
        !           372:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddss",
        !           373:                                     uid, gid, oldpath, path);
        !           374:         if (retval > 0) {
        !           375:             header.size = retval;
        !           376:             header.type = T_SYMLINK;
        !           377:         }
        !           378:         break;
        !           379:     case T_LINK:
        !           380:         oldpath = va_arg(ap, V9fsString *);
        !           381:         path = va_arg(ap, V9fsString *);
        !           382:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ss",
        !           383:                                     oldpath, path);
        !           384:         if (retval > 0) {
        !           385:             header.size = retval;
        !           386:             header.type = T_LINK;
        !           387:         }
        !           388:         break;
        !           389:     case T_LSTAT:
        !           390:         path = va_arg(ap, V9fsString *);
        !           391:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path);
        !           392:         if (retval > 0) {
        !           393:             header.size = retval;
        !           394:             header.type = T_LSTAT;
        !           395:         }
        !           396:         break;
        !           397:     case T_READLINK:
        !           398:         path = va_arg(ap, V9fsString *);
        !           399:         size = va_arg(ap, int);
        !           400:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sd", path, size);
        !           401:         if (retval > 0) {
        !           402:             header.size = retval;
        !           403:             header.type = T_READLINK;
        !           404:         }
        !           405:         break;
        !           406:     case T_STATFS:
        !           407:         path = va_arg(ap, V9fsString *);
        !           408:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path);
        !           409:         if (retval > 0) {
        !           410:             header.size = retval;
        !           411:             header.type = T_STATFS;
        !           412:         }
        !           413:         break;
        !           414:     case T_CHMOD:
        !           415:         path = va_arg(ap, V9fsString *);
        !           416:         mode = va_arg(ap, int);
        !           417:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sd", path, mode);
        !           418:         if (retval > 0) {
        !           419:             header.size = retval;
        !           420:             header.type = T_CHMOD;
        !           421:         }
        !           422:         break;
        !           423:     case T_CHOWN:
        !           424:         path = va_arg(ap, V9fsString *);
        !           425:         uid = va_arg(ap, int);
        !           426:         gid = va_arg(ap, int);
        !           427:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sdd", path, uid, gid);
        !           428:         if (retval > 0) {
        !           429:             header.size = retval;
        !           430:             header.type = T_CHOWN;
        !           431:         }
        !           432:         break;
        !           433:     case T_TRUNCATE:
        !           434:         path = va_arg(ap, V9fsString *);
        !           435:         offset = va_arg(ap, uint64_t);
        !           436:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sq", path, offset);
        !           437:         if (retval > 0) {
        !           438:             header.size = retval;
        !           439:             header.type = T_TRUNCATE;
        !           440:         }
        !           441:         break;
        !           442:     case T_UTIME:
        !           443:         path = va_arg(ap, V9fsString *);
        !           444:         spec[0].tv_sec = va_arg(ap, long);
        !           445:         spec[0].tv_nsec = va_arg(ap, long);
        !           446:         spec[1].tv_sec = va_arg(ap, long);
        !           447:         spec[1].tv_nsec = va_arg(ap, long);
        !           448:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sqqqq", path,
        !           449:                                     spec[0].tv_sec, spec[1].tv_nsec,
        !           450:                                     spec[1].tv_sec, spec[1].tv_nsec);
        !           451:         if (retval > 0) {
        !           452:             header.size = retval;
        !           453:             header.type = T_UTIME;
        !           454:         }
        !           455:         break;
        !           456:     case T_RENAME:
        !           457:         oldpath = va_arg(ap, V9fsString *);
        !           458:         path = va_arg(ap, V9fsString *);
        !           459:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ss", oldpath, path);
        !           460:         if (retval > 0) {
        !           461:             header.size = retval;
        !           462:             header.type = T_RENAME;
        !           463:         }
        !           464:         break;
        !           465:     case T_REMOVE:
        !           466:         path = va_arg(ap, V9fsString *);
        !           467:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path);
        !           468:         if (retval > 0) {
        !           469:             header.size = retval;
        !           470:             header.type = T_REMOVE;
        !           471:         }
        !           472:         break;
        !           473:     case T_LGETXATTR:
        !           474:         size = va_arg(ap, int);
        !           475:         path = va_arg(ap, V9fsString *);
        !           476:         name = va_arg(ap, V9fsString *);
        !           477:         retval = proxy_marshal(iovec, PROXY_HDR_SZ,
        !           478:                                     "dss", size, path, name);
        !           479:         if (retval > 0) {
        !           480:             header.size = retval;
        !           481:             header.type = T_LGETXATTR;
        !           482:         }
        !           483:         break;
        !           484:     case T_LLISTXATTR:
        !           485:         size = va_arg(ap, int);
        !           486:         path = va_arg(ap, V9fsString *);
        !           487:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ds", size, path);
        !           488:         if (retval > 0) {
        !           489:             header.size = retval;
        !           490:             header.type = T_LLISTXATTR;
        !           491:         }
        !           492:         break;
        !           493:     case T_LSETXATTR:
        !           494:         path = va_arg(ap, V9fsString *);
        !           495:         name = va_arg(ap, V9fsString *);
        !           496:         value = va_arg(ap, V9fsString *);
        !           497:         size = va_arg(ap, int);
        !           498:         flags = va_arg(ap, int);
        !           499:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sssdd",
        !           500:                                     path, name, value, size, flags);
        !           501:         if (retval > 0) {
        !           502:             header.size = retval;
        !           503:             header.type = T_LSETXATTR;
        !           504:         }
        !           505:         break;
        !           506:     case T_LREMOVEXATTR:
        !           507:         path = va_arg(ap, V9fsString *);
        !           508:         name = va_arg(ap, V9fsString *);
        !           509:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ss", path, name);
        !           510:         if (retval > 0) {
        !           511:             header.size = retval;
        !           512:             header.type = T_LREMOVEXATTR;
        !           513:         }
        !           514:         break;
        !           515:     case T_GETVERSION:
        !           516:         path = va_arg(ap, V9fsString *);
        !           517:         retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path);
        !           518:         if (retval > 0) {
        !           519:             header.size = retval;
        !           520:             header.type = T_GETVERSION;
        !           521:         }
        !           522:         break;
        !           523:     default:
        !           524:         error_report("Invalid type %d\n", type);
        !           525:         retval = -EINVAL;
        !           526:         break;
        !           527:     }
        !           528:     va_end(ap);
        !           529: 
        !           530:     if (retval < 0) {
        !           531:         goto err_out;
        !           532:     }
        !           533: 
        !           534:     /* marshal the header details */
        !           535:     proxy_marshal(iovec, 0, "dd", header.type, header.size);
        !           536:     header.size += PROXY_HDR_SZ;
        !           537: 
        !           538:     retval = qemu_write_full(proxy->sockfd, iovec->iov_base, header.size);
        !           539:     if (retval != header.size) {
        !           540:         goto close_error;
        !           541:     }
        !           542: 
        !           543:     switch (type) {
        !           544:     case T_OPEN:
        !           545:     case T_CREATE:
        !           546:         /*
        !           547:          * A file descriptor is returned as response for
        !           548:          * T_OPEN,T_CREATE on success
        !           549:          */
        !           550:         if (v9fs_receivefd(proxy->sockfd, &retval) < 0) {
        !           551:             goto close_error;
        !           552:         }
        !           553:         break;
        !           554:     case T_MKNOD:
        !           555:     case T_MKDIR:
        !           556:     case T_SYMLINK:
        !           557:     case T_LINK:
        !           558:     case T_CHMOD:
        !           559:     case T_CHOWN:
        !           560:     case T_RENAME:
        !           561:     case T_TRUNCATE:
        !           562:     case T_UTIME:
        !           563:     case T_REMOVE:
        !           564:     case T_LSETXATTR:
        !           565:     case T_LREMOVEXATTR:
        !           566:         if (v9fs_receive_status(proxy, reply, &retval) < 0) {
        !           567:             goto close_error;
        !           568:         }
        !           569:         break;
        !           570:     case T_LSTAT:
        !           571:     case T_READLINK:
        !           572:     case T_STATFS:
        !           573:     case T_GETVERSION:
        !           574:         if (v9fs_receive_response(proxy, type, &retval, response) < 0) {
        !           575:             goto close_error;
        !           576:         }
        !           577:         break;
        !           578:     case T_LGETXATTR:
        !           579:     case T_LLISTXATTR:
        !           580:         if (!size) {
        !           581:             if (v9fs_receive_status(proxy, reply, &retval) < 0) {
        !           582:                 goto close_error;
        !           583:             }
        !           584:         } else {
        !           585:             if (v9fs_receive_response(proxy, type, &retval, response) < 0) {
        !           586:                 goto close_error;
        !           587:             }
        !           588:         }
        !           589:         break;
        !           590:     }
        !           591: 
        !           592: err_out:
        !           593:     qemu_mutex_unlock(&proxy->mutex);
        !           594:     return retval;
        !           595: 
        !           596: close_error:
        !           597:     close(proxy->sockfd);
        !           598:     proxy->sockfd = -1;
        !           599:     qemu_mutex_unlock(&proxy->mutex);
        !           600:     return -EIO;
        !           601: }
        !           602: 
        !           603: static int proxy_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
        !           604: {
        !           605:     int retval;
        !           606:     retval = v9fs_request(fs_ctx->private, T_LSTAT, stbuf, "s", fs_path);
        !           607:     if (retval < 0) {
        !           608:         errno = -retval;
        !           609:         return -1;
        !           610:     }
        !           611:     return retval;
        !           612: }
        !           613: 
        !           614: static ssize_t proxy_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
        !           615:                               char *buf, size_t bufsz)
        !           616: {
        !           617:     int retval;
        !           618:     retval = v9fs_request(fs_ctx->private, T_READLINK, buf, "sd",
        !           619:                           fs_path, bufsz);
        !           620:     if (retval < 0) {
        !           621:         errno = -retval;
        !           622:         return -1;
        !           623:     }
        !           624:     return strlen(buf);
        !           625: }
        !           626: 
        !           627: static int proxy_close(FsContext *ctx, V9fsFidOpenState *fs)
        !           628: {
        !           629:     return close(fs->fd);
        !           630: }
        !           631: 
        !           632: static int proxy_closedir(FsContext *ctx, V9fsFidOpenState *fs)
        !           633: {
        !           634:     return closedir(fs->dir);
        !           635: }
        !           636: 
        !           637: static int proxy_open(FsContext *ctx, V9fsPath *fs_path,
        !           638:                       int flags, V9fsFidOpenState *fs)
        !           639: {
        !           640:     fs->fd = v9fs_request(ctx->private, T_OPEN, NULL, "sd", fs_path, flags);
        !           641:     if (fs->fd < 0) {
        !           642:         errno = -fs->fd;
        !           643:         fs->fd = -1;
        !           644:     }
        !           645:     return fs->fd;
        !           646: }
        !           647: 
        !           648: static int proxy_opendir(FsContext *ctx,
        !           649:                          V9fsPath *fs_path, V9fsFidOpenState *fs)
        !           650: {
        !           651:     int serrno, fd;
        !           652: 
        !           653:     fs->dir = NULL;
        !           654:     fd = v9fs_request(ctx->private, T_OPEN, NULL, "sd", fs_path, O_DIRECTORY);
        !           655:     if (fd < 0) {
        !           656:         errno = -fd;
        !           657:         return -1;
        !           658:     }
        !           659:     fs->dir = fdopendir(fd);
        !           660:     if (!fs->dir) {
        !           661:         serrno = errno;
        !           662:         close(fd);
        !           663:         errno = serrno;
        !           664:         return -1;
        !           665:     }
        !           666:     return 0;
        !           667: }
        !           668: 
        !           669: static void proxy_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
        !           670: {
        !           671:     return rewinddir(fs->dir);
        !           672: }
        !           673: 
        !           674: static off_t proxy_telldir(FsContext *ctx, V9fsFidOpenState *fs)
        !           675: {
        !           676:     return telldir(fs->dir);
        !           677: }
        !           678: 
        !           679: static int proxy_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
        !           680:                            struct dirent *entry,
        !           681:                            struct dirent **result)
        !           682: {
        !           683:     return readdir_r(fs->dir, entry, result);
        !           684: }
        !           685: 
        !           686: static void proxy_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
        !           687: {
        !           688:     return seekdir(fs->dir, off);
        !           689: }
        !           690: 
        !           691: static ssize_t proxy_preadv(FsContext *ctx, V9fsFidOpenState *fs,
        !           692:                             const struct iovec *iov,
        !           693:                             int iovcnt, off_t offset)
        !           694: {
        !           695: #ifdef CONFIG_PREADV
        !           696:     return preadv(fs->fd, iov, iovcnt, offset);
        !           697: #else
        !           698:     int err = lseek(fs->fd, offset, SEEK_SET);
        !           699:     if (err == -1) {
        !           700:         return err;
        !           701:     } else {
        !           702:         return readv(fs->fd, iov, iovcnt);
        !           703:     }
        !           704: #endif
        !           705: }
        !           706: 
        !           707: static ssize_t proxy_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
        !           708:                              const struct iovec *iov,
        !           709:                              int iovcnt, off_t offset)
        !           710: {
        !           711:     ssize_t ret;
        !           712: 
        !           713: #ifdef CONFIG_PREADV
        !           714:     ret = pwritev(fs->fd, iov, iovcnt, offset);
        !           715: #else
        !           716:     int err = lseek(fs->fd, offset, SEEK_SET);
        !           717:     if (err == -1) {
        !           718:         return err;
        !           719:     } else {
        !           720:         ret = writev(fs->fd, iov, iovcnt);
        !           721:     }
        !           722: #endif
        !           723: #ifdef CONFIG_SYNC_FILE_RANGE
        !           724:     if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) {
        !           725:         /*
        !           726:          * Initiate a writeback. This is not a data integrity sync.
        !           727:          * We want to ensure that we don't leave dirty pages in the cache
        !           728:          * after write when writeout=immediate is sepcified.
        !           729:          */
        !           730:         sync_file_range(fs->fd, offset, ret,
        !           731:                         SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE);
        !           732:     }
        !           733: #endif
        !           734:     return ret;
        !           735: }
        !           736: 
        !           737: static int proxy_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
        !           738: {
        !           739:     int retval;
        !           740:     retval = v9fs_request(fs_ctx->private, T_CHMOD, NULL, "sd",
        !           741:                           fs_path, credp->fc_mode);
        !           742:     if (retval < 0) {
        !           743:         errno = -retval;
        !           744:     }
        !           745:     return retval;
        !           746: }
        !           747: 
        !           748: static int proxy_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
        !           749:                        const char *name, FsCred *credp)
        !           750: {
        !           751:     int retval;
        !           752:     V9fsString fullname;
        !           753: 
        !           754:     v9fs_string_init(&fullname);
        !           755:     v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
        !           756: 
        !           757:     retval = v9fs_request(fs_ctx->private, T_MKNOD, NULL, "sdqdd",
        !           758:                           &fullname, credp->fc_mode, credp->fc_rdev,
        !           759:                           credp->fc_uid, credp->fc_gid);
        !           760:     v9fs_string_free(&fullname);
        !           761:     if (retval < 0) {
        !           762:         errno = -retval;
        !           763:         retval = -1;
        !           764:     }
        !           765:     return retval;
        !           766: }
        !           767: 
        !           768: static int proxy_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
        !           769:                        const char *name, FsCred *credp)
        !           770: {
        !           771:     int retval;
        !           772:     V9fsString fullname;
        !           773: 
        !           774:     v9fs_string_init(&fullname);
        !           775:     v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
        !           776: 
        !           777:     retval = v9fs_request(fs_ctx->private, T_MKDIR, NULL, "sddd", &fullname,
        !           778:                           credp->fc_mode, credp->fc_uid, credp->fc_gid);
        !           779:     v9fs_string_free(&fullname);
        !           780:     if (retval < 0) {
        !           781:         errno = -retval;
        !           782:         retval = -1;
        !           783:     }
        !           784:     v9fs_string_free(&fullname);
        !           785:     return retval;
        !           786: }
        !           787: 
        !           788: static int proxy_fstat(FsContext *fs_ctx, int fid_type,
        !           789:                        V9fsFidOpenState *fs, struct stat *stbuf)
        !           790: {
        !           791:     int fd;
        !           792: 
        !           793:     if (fid_type == P9_FID_DIR) {
        !           794:         fd = dirfd(fs->dir);
        !           795:     } else {
        !           796:         fd = fs->fd;
        !           797:     }
        !           798:     return fstat(fd, stbuf);
        !           799: }
        !           800: 
        !           801: static int proxy_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
        !           802:                        int flags, FsCred *credp, V9fsFidOpenState *fs)
        !           803: {
        !           804:     V9fsString fullname;
        !           805: 
        !           806:     v9fs_string_init(&fullname);
        !           807:     v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
        !           808: 
        !           809:     fs->fd = v9fs_request(fs_ctx->private, T_CREATE, NULL, "sdddd",
        !           810:                           &fullname, flags, credp->fc_mode,
        !           811:                           credp->fc_uid, credp->fc_gid);
        !           812:     v9fs_string_free(&fullname);
        !           813:     if (fs->fd < 0) {
        !           814:         errno = -fs->fd;
        !           815:         fs->fd = -1;
        !           816:     }
        !           817:     return fs->fd;
        !           818: }
        !           819: 
        !           820: static int proxy_symlink(FsContext *fs_ctx, const char *oldpath,
        !           821:                          V9fsPath *dir_path, const char *name, FsCred *credp)
        !           822: {
        !           823:     int retval;
        !           824:     V9fsString fullname, target;
        !           825: 
        !           826:     v9fs_string_init(&fullname);
        !           827:     v9fs_string_init(&target);
        !           828: 
        !           829:     v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
        !           830:     v9fs_string_sprintf(&target, "%s", oldpath);
        !           831: 
        !           832:     retval = v9fs_request(fs_ctx->private, T_SYMLINK, NULL, "ssdd",
        !           833:                           &target, &fullname, credp->fc_uid, credp->fc_gid);
        !           834:     v9fs_string_free(&fullname);
        !           835:     v9fs_string_free(&target);
        !           836:     if (retval < 0) {
        !           837:         errno = -retval;
        !           838:         retval = -1;
        !           839:     }
        !           840:     return retval;
        !           841: }
        !           842: 
        !           843: static int proxy_link(FsContext *ctx, V9fsPath *oldpath,
        !           844:                       V9fsPath *dirpath, const char *name)
        !           845: {
        !           846:     int retval;
        !           847:     V9fsString newpath;
        !           848: 
        !           849:     v9fs_string_init(&newpath);
        !           850:     v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name);
        !           851: 
        !           852:     retval = v9fs_request(ctx->private, T_LINK, NULL, "ss", oldpath, &newpath);
        !           853:     v9fs_string_free(&newpath);
        !           854:     if (retval < 0) {
        !           855:         errno = -retval;
        !           856:         retval = -1;
        !           857:     }
        !           858:     return retval;
        !           859: }
        !           860: 
        !           861: static int proxy_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
        !           862: {
        !           863:     int retval;
        !           864: 
        !           865:     retval = v9fs_request(ctx->private, T_TRUNCATE, NULL, "sq", fs_path, size);
        !           866:     if (retval < 0) {
        !           867:         errno = -retval;
        !           868:         return -1;
        !           869:     }
        !           870:     return 0;
        !           871: }
        !           872: 
        !           873: static int proxy_rename(FsContext *ctx, const char *oldpath,
        !           874:                         const char *newpath)
        !           875: {
        !           876:     int retval;
        !           877:     V9fsString oldname, newname;
        !           878: 
        !           879:     v9fs_string_init(&oldname);
        !           880:     v9fs_string_init(&newname);
        !           881: 
        !           882:     v9fs_string_sprintf(&oldname, "%s", oldpath);
        !           883:     v9fs_string_sprintf(&newname, "%s", newpath);
        !           884:     retval = v9fs_request(ctx->private, T_RENAME, NULL, "ss",
        !           885:                           &oldname, &newname);
        !           886:     v9fs_string_free(&oldname);
        !           887:     v9fs_string_free(&newname);
        !           888:     if (retval < 0) {
        !           889:         errno = -retval;
        !           890:     }
        !           891:     return retval;
        !           892: }
        !           893: 
        !           894: static int proxy_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
        !           895: {
        !           896:     int retval;
        !           897:     retval = v9fs_request(fs_ctx->private, T_CHOWN, NULL, "sdd",
        !           898:                           fs_path, credp->fc_uid, credp->fc_gid);
        !           899:     if (retval < 0) {
        !           900:         errno = -retval;
        !           901:     }
        !           902:     return retval;
        !           903: }
        !           904: 
        !           905: static int proxy_utimensat(FsContext *s, V9fsPath *fs_path,
        !           906:                            const struct timespec *buf)
        !           907: {
        !           908:     int retval;
        !           909:     retval = v9fs_request(s->private, T_UTIME, NULL, "sqqqq",
        !           910:                           fs_path,
        !           911:                           buf[0].tv_sec, buf[0].tv_nsec,
        !           912:                           buf[1].tv_sec, buf[1].tv_nsec);
        !           913:     if (retval < 0) {
        !           914:         errno = -retval;
        !           915:     }
        !           916:     return retval;
        !           917: }
        !           918: 
        !           919: static int proxy_remove(FsContext *ctx, const char *path)
        !           920: {
        !           921:     int retval;
        !           922:     V9fsString name;
        !           923:     v9fs_string_init(&name);
        !           924:     v9fs_string_sprintf(&name, "%s", path);
        !           925:     retval = v9fs_request(ctx->private, T_REMOVE, NULL, "s", &name);
        !           926:     v9fs_string_free(&name);
        !           927:     if (retval < 0) {
        !           928:         errno = -retval;
        !           929:     }
        !           930:     return retval;
        !           931: }
        !           932: 
        !           933: static int proxy_fsync(FsContext *ctx, int fid_type,
        !           934:                        V9fsFidOpenState *fs, int datasync)
        !           935: {
        !           936:     int fd;
        !           937: 
        !           938:     if (fid_type == P9_FID_DIR) {
        !           939:         fd = dirfd(fs->dir);
        !           940:     } else {
        !           941:         fd = fs->fd;
        !           942:     }
        !           943: 
        !           944:     if (datasync) {
        !           945:         return qemu_fdatasync(fd);
        !           946:     } else {
        !           947:         return fsync(fd);
        !           948:     }
        !           949: }
        !           950: 
        !           951: static int proxy_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
        !           952: {
        !           953:     int retval;
        !           954:     retval = v9fs_request(s->private, T_STATFS, stbuf, "s", fs_path);
        !           955:     if (retval < 0) {
        !           956:         errno = -retval;
        !           957:         return -1;
        !           958:     }
        !           959:     return retval;
        !           960: }
        !           961: 
        !           962: static ssize_t proxy_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
        !           963:                                const char *name, void *value, size_t size)
        !           964: {
        !           965:     int retval;
        !           966:     V9fsString xname;
        !           967: 
        !           968:     v9fs_string_init(&xname);
        !           969:     v9fs_string_sprintf(&xname, "%s", name);
        !           970:     retval = v9fs_request(ctx->private, T_LGETXATTR, value, "dss", size,
        !           971:                           fs_path, &xname);
        !           972:     v9fs_string_free(&xname);
        !           973:     if (retval < 0) {
        !           974:         errno = -retval;
        !           975:     }
        !           976:     return retval;
        !           977: }
        !           978: 
        !           979: static ssize_t proxy_llistxattr(FsContext *ctx, V9fsPath *fs_path,
        !           980:                                 void *value, size_t size)
        !           981: {
        !           982:     int retval;
        !           983:     retval = v9fs_request(ctx->private, T_LLISTXATTR, value, "ds", size,
        !           984:                         fs_path);
        !           985:     if (retval < 0) {
        !           986:         errno = -retval;
        !           987:     }
        !           988:     return retval;
        !           989: }
        !           990: 
        !           991: static int proxy_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
        !           992:                            void *value, size_t size, int flags)
        !           993: {
        !           994:     int retval;
        !           995:     V9fsString xname, xvalue;
        !           996: 
        !           997:     v9fs_string_init(&xname);
        !           998:     v9fs_string_sprintf(&xname, "%s", name);
        !           999: 
        !          1000:     v9fs_string_init(&xvalue);
        !          1001:     xvalue.size = size;
        !          1002:     xvalue.data = g_malloc(size);
        !          1003:     memcpy(xvalue.data, value, size);
        !          1004: 
        !          1005:     retval = v9fs_request(ctx->private, T_LSETXATTR, value, "sssdd",
        !          1006:                           fs_path, &xname, &xvalue, size, flags);
        !          1007:     v9fs_string_free(&xname);
        !          1008:     v9fs_string_free(&xvalue);
        !          1009:     if (retval < 0) {
        !          1010:         errno = -retval;
        !          1011:     }
        !          1012:     return retval;
        !          1013: }
        !          1014: 
        !          1015: static int proxy_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
        !          1016:                               const char *name)
        !          1017: {
        !          1018:     int retval;
        !          1019:     V9fsString xname;
        !          1020: 
        !          1021:     v9fs_string_init(&xname);
        !          1022:     v9fs_string_sprintf(&xname, "%s", name);
        !          1023:     retval = v9fs_request(ctx->private, T_LREMOVEXATTR, NULL, "ss",
        !          1024:                           fs_path, &xname);
        !          1025:     v9fs_string_free(&xname);
        !          1026:     if (retval < 0) {
        !          1027:         errno = -retval;
        !          1028:     }
        !          1029:     return retval;
        !          1030: }
        !          1031: 
        !          1032: static int proxy_name_to_path(FsContext *ctx, V9fsPath *dir_path,
        !          1033:                               const char *name, V9fsPath *target)
        !          1034: {
        !          1035:     if (dir_path) {
        !          1036:         v9fs_string_sprintf((V9fsString *)target, "%s/%s",
        !          1037:                             dir_path->data, name);
        !          1038:     } else {
        !          1039:         v9fs_string_sprintf((V9fsString *)target, "%s", name);
        !          1040:     }
        !          1041:     /* Bump the size for including terminating NULL */
        !          1042:     target->size++;
        !          1043:     return 0;
        !          1044: }
        !          1045: 
        !          1046: static int proxy_renameat(FsContext *ctx, V9fsPath *olddir,
        !          1047:                           const char *old_name, V9fsPath *newdir,
        !          1048:                           const char *new_name)
        !          1049: {
        !          1050:     int ret;
        !          1051:     V9fsString old_full_name, new_full_name;
        !          1052: 
        !          1053:     v9fs_string_init(&old_full_name);
        !          1054:     v9fs_string_init(&new_full_name);
        !          1055: 
        !          1056:     v9fs_string_sprintf(&old_full_name, "%s/%s", olddir->data, old_name);
        !          1057:     v9fs_string_sprintf(&new_full_name, "%s/%s", newdir->data, new_name);
        !          1058: 
        !          1059:     ret = proxy_rename(ctx, old_full_name.data, new_full_name.data);
        !          1060:     v9fs_string_free(&old_full_name);
        !          1061:     v9fs_string_free(&new_full_name);
        !          1062:     return ret;
        !          1063: }
        !          1064: 
        !          1065: static int proxy_unlinkat(FsContext *ctx, V9fsPath *dir,
        !          1066:                           const char *name, int flags)
        !          1067: {
        !          1068:     int ret;
        !          1069:     V9fsString fullname;
        !          1070:     v9fs_string_init(&fullname);
        !          1071: 
        !          1072:     v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name);
        !          1073:     ret = proxy_remove(ctx, fullname.data);
        !          1074:     v9fs_string_free(&fullname);
        !          1075: 
        !          1076:     return ret;
        !          1077: }
        !          1078: 
        !          1079: static int proxy_ioc_getversion(FsContext *fs_ctx, V9fsPath *path,
        !          1080:                                 mode_t st_mode, uint64_t *st_gen)
        !          1081: {
        !          1082:     int err;
        !          1083: 
        !          1084:     /* Do not try to open special files like device nodes, fifos etc
        !          1085:      * we can get fd for regular files and directories only
        !          1086:      */
        !          1087:     if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) {
        !          1088:         return 0;
        !          1089:     }
        !          1090:     err = v9fs_request(fs_ctx->private, T_GETVERSION, st_gen, "s", path);
        !          1091:     if (err < 0) {
        !          1092:         errno = -err;
        !          1093:         err = -1;
        !          1094:     }
        !          1095:     return err;
        !          1096: }
        !          1097: 
        !          1098: static int connect_namedsocket(const char *path)
        !          1099: {
        !          1100:     int sockfd, size;
        !          1101:     struct sockaddr_un helper;
        !          1102: 
        !          1103:     sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
        !          1104:     if (sockfd < 0) {
        !          1105:         fprintf(stderr, "socket %s\n", strerror(errno));
        !          1106:         return -1;
        !          1107:     }
        !          1108:     strcpy(helper.sun_path, path);
        !          1109:     helper.sun_family = AF_UNIX;
        !          1110:     size = strlen(helper.sun_path) + sizeof(helper.sun_family);
        !          1111:     if (connect(sockfd, (struct sockaddr *)&helper, size) < 0) {
        !          1112:         fprintf(stderr, "socket error\n");
        !          1113:         return -1;
        !          1114:     }
        !          1115: 
        !          1116:     /* remove the socket for security reasons */
        !          1117:     unlink(path);
        !          1118:     return sockfd;
        !          1119: }
        !          1120: 
        !          1121: static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs)
        !          1122: {
        !          1123:     const char *socket = qemu_opt_get(opts, "socket");
        !          1124:     const char *sock_fd = qemu_opt_get(opts, "sock_fd");
        !          1125: 
        !          1126:     if (!socket && !sock_fd) {
        !          1127:         fprintf(stderr, "socket and sock_fd none of the option specified\n");
        !          1128:         return -1;
        !          1129:     }
        !          1130:     if (socket && sock_fd) {
        !          1131:         fprintf(stderr, "Both socket and sock_fd options specified\n");
        !          1132:         return -1;
        !          1133:     }
        !          1134:     if (socket) {
        !          1135:         fs->path = g_strdup(socket);
        !          1136:         fs->export_flags = V9FS_PROXY_SOCK_NAME;
        !          1137:     } else {
        !          1138:         fs->path = g_strdup(sock_fd);
        !          1139:         fs->export_flags = V9FS_PROXY_SOCK_FD;
        !          1140:     }
        !          1141:     return 0;
        !          1142: }
        !          1143: 
        !          1144: static int proxy_init(FsContext *ctx)
        !          1145: {
        !          1146:     V9fsProxy *proxy = g_malloc(sizeof(V9fsProxy));
        !          1147:     int sock_id;
        !          1148: 
        !          1149:     if (ctx->export_flags & V9FS_PROXY_SOCK_NAME) {
        !          1150:         sock_id = connect_namedsocket(ctx->fs_root);
        !          1151:     } else {
        !          1152:         sock_id = atoi(ctx->fs_root);
        !          1153:         if (sock_id < 0) {
        !          1154:             fprintf(stderr, "socket descriptor not initialized\n");
        !          1155:             return -1;
        !          1156:         }
        !          1157:     }
        !          1158:     g_free(ctx->fs_root);
        !          1159: 
        !          1160:     proxy->in_iovec.iov_base  = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
        !          1161:     proxy->in_iovec.iov_len   = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
        !          1162:     proxy->out_iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
        !          1163:     proxy->out_iovec.iov_len  = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
        !          1164: 
        !          1165:     ctx->private = proxy;
        !          1166:     proxy->sockfd = sock_id;
        !          1167:     qemu_mutex_init(&proxy->mutex);
        !          1168: 
        !          1169:     ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
        !          1170:     ctx->exops.get_st_gen = proxy_ioc_getversion;
        !          1171:     return 0;
        !          1172: }
        !          1173: 
        !          1174: FileOperations proxy_ops = {
        !          1175:     .parse_opts   = proxy_parse_opts,
        !          1176:     .init         = proxy_init,
        !          1177:     .lstat        = proxy_lstat,
        !          1178:     .readlink     = proxy_readlink,
        !          1179:     .close        = proxy_close,
        !          1180:     .closedir     = proxy_closedir,
        !          1181:     .open         = proxy_open,
        !          1182:     .opendir      = proxy_opendir,
        !          1183:     .rewinddir    = proxy_rewinddir,
        !          1184:     .telldir      = proxy_telldir,
        !          1185:     .readdir_r    = proxy_readdir_r,
        !          1186:     .seekdir      = proxy_seekdir,
        !          1187:     .preadv       = proxy_preadv,
        !          1188:     .pwritev      = proxy_pwritev,
        !          1189:     .chmod        = proxy_chmod,
        !          1190:     .mknod        = proxy_mknod,
        !          1191:     .mkdir        = proxy_mkdir,
        !          1192:     .fstat        = proxy_fstat,
        !          1193:     .open2        = proxy_open2,
        !          1194:     .symlink      = proxy_symlink,
        !          1195:     .link         = proxy_link,
        !          1196:     .truncate     = proxy_truncate,
        !          1197:     .rename       = proxy_rename,
        !          1198:     .chown        = proxy_chown,
        !          1199:     .utimensat    = proxy_utimensat,
        !          1200:     .remove       = proxy_remove,
        !          1201:     .fsync        = proxy_fsync,
        !          1202:     .statfs       = proxy_statfs,
        !          1203:     .lgetxattr    = proxy_lgetxattr,
        !          1204:     .llistxattr   = proxy_llistxattr,
        !          1205:     .lsetxattr    = proxy_lsetxattr,
        !          1206:     .lremovexattr = proxy_lremovexattr,
        !          1207:     .name_to_path = proxy_name_to_path,
        !          1208:     .renameat     = proxy_renameat,
        !          1209:     .unlinkat     = proxy_unlinkat,
        !          1210: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.