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

1.1     ! root        1: /*
        !             2:  * Virtio 9p synthetic file system support
        !             3:  *
        !             4:  * Copyright IBM, Corp. 2011
        !             5:  *
        !             6:  * Authors:
        !             7:  *  Malahal Naineni <[email protected]>
        !             8:  *  Aneesh Kumar K.V <[email protected]>
        !             9:  *
        !            10:  * This work is licensed under the terms of the GNU GPL, version 2.  See
        !            11:  * the COPYING file in the top-level directory.
        !            12:  *
        !            13:  */
        !            14: 
        !            15: #include "hw/virtio.h"
        !            16: #include "virtio-9p.h"
        !            17: #include "virtio-9p-xattr.h"
        !            18: #include "fsdev/qemu-fsdev.h"
        !            19: #include "virtio-9p-synth.h"
        !            20: 
        !            21: #include <sys/stat.h>
        !            22: 
        !            23: /* Root node for synth file system */
        !            24: V9fsSynthNode v9fs_synth_root = {
        !            25:     .name = "/",
        !            26:     .actual_attr = {
        !            27:         .mode = 0555 | S_IFDIR,
        !            28:         .nlink = 1,
        !            29:     },
        !            30:     .attr = &v9fs_synth_root.actual_attr,
        !            31: };
        !            32: 
        !            33: static QemuMutex  v9fs_synth_mutex;
        !            34: static int v9fs_synth_node_count;
        !            35: /* set to 1 when the synth fs is ready */
        !            36: static int v9fs_synth_fs;
        !            37: 
        !            38: static V9fsSynthNode *v9fs_add_dir_node(V9fsSynthNode *parent, int mode,
        !            39:                                         const char *name,
        !            40:                                         V9fsSynthNodeAttr *attr, int inode)
        !            41: {
        !            42:     V9fsSynthNode *node;
        !            43: 
        !            44:     /* Add directory type and remove write bits */
        !            45:     mode = ((mode & 0777) | S_IFDIR) & ~(S_IWUSR | S_IWGRP | S_IWOTH);
        !            46:     node = g_malloc0(sizeof(V9fsSynthNode));
        !            47:     if (attr) {
        !            48:         /* We are adding .. or . entries */
        !            49:         node->attr = attr;
        !            50:         node->attr->nlink++;
        !            51:     } else {
        !            52:         node->attr = &node->actual_attr;
        !            53:         node->attr->inode = inode;
        !            54:         node->attr->nlink = 1;
        !            55:         /* We don't allow write to directories */
        !            56:         node->attr->mode   = mode;
        !            57:         node->attr->write = NULL;
        !            58:         node->attr->read  = NULL;
        !            59:     }
        !            60:     node->private = node;
        !            61:     strncpy(node->name, name, sizeof(node->name));
        !            62:     QLIST_INSERT_HEAD_RCU(&parent->child, node, sibling);
        !            63:     return node;
        !            64: }
        !            65: 
        !            66: int qemu_v9fs_synth_mkdir(V9fsSynthNode *parent, int mode,
        !            67:                           const char *name, V9fsSynthNode **result)
        !            68: {
        !            69:     int ret;
        !            70:     V9fsSynthNode *node, *tmp;
        !            71: 
        !            72:     if (!v9fs_synth_fs) {
        !            73:         return EAGAIN;
        !            74:     }
        !            75:     if (!name || (strlen(name) >= NAME_MAX)) {
        !            76:         return EINVAL;
        !            77:     }
        !            78:     if (!parent) {
        !            79:         parent = &v9fs_synth_root;
        !            80:     }
        !            81:     qemu_mutex_lock(&v9fs_synth_mutex);
        !            82:     QLIST_FOREACH(tmp, &parent->child, sibling) {
        !            83:         if (!strcmp(tmp->name, name)) {
        !            84:             ret = EEXIST;
        !            85:             goto err_out;
        !            86:         }
        !            87:     }
        !            88:     /* Add the name */
        !            89:     node = v9fs_add_dir_node(parent, mode, name, NULL, v9fs_synth_node_count++);
        !            90:     v9fs_add_dir_node(node, parent->attr->mode, "..",
        !            91:                       parent->attr, parent->attr->inode);
        !            92:     v9fs_add_dir_node(node, node->attr->mode, ".",
        !            93:                       node->attr, node->attr->inode);
        !            94:     *result = node;
        !            95:     ret = 0;
        !            96: err_out:
        !            97:     qemu_mutex_unlock(&v9fs_synth_mutex);
        !            98:     return ret;
        !            99: }
        !           100: 
        !           101: int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode,
        !           102:                              const char *name, v9fs_synth_read read,
        !           103:                              v9fs_synth_write write, void *arg)
        !           104: {
        !           105:     int ret;
        !           106:     V9fsSynthNode *node, *tmp;
        !           107: 
        !           108:     if (!v9fs_synth_fs) {
        !           109:         return EAGAIN;
        !           110:     }
        !           111:     if (!name || (strlen(name) >= NAME_MAX)) {
        !           112:         return EINVAL;
        !           113:     }
        !           114:     if (!parent) {
        !           115:         parent = &v9fs_synth_root;
        !           116:     }
        !           117: 
        !           118:     qemu_mutex_lock(&v9fs_synth_mutex);
        !           119:     QLIST_FOREACH(tmp, &parent->child, sibling) {
        !           120:         if (!strcmp(tmp->name, name)) {
        !           121:             ret = EEXIST;
        !           122:             goto err_out;
        !           123:         }
        !           124:     }
        !           125:     /* Add file type and remove write bits */
        !           126:     mode = ((mode & 0777) | S_IFREG);
        !           127:     node = g_malloc0(sizeof(V9fsSynthNode));
        !           128:     node->attr         = &node->actual_attr;
        !           129:     node->attr->inode  = v9fs_synth_node_count++;
        !           130:     node->attr->nlink  = 1;
        !           131:     node->attr->read   = read;
        !           132:     node->attr->write  = write;
        !           133:     node->attr->mode   = mode;
        !           134:     node->private      = arg;
        !           135:     strncpy(node->name, name, sizeof(node->name));
        !           136:     QLIST_INSERT_HEAD_RCU(&parent->child, node, sibling);
        !           137:     ret = 0;
        !           138: err_out:
        !           139:     qemu_mutex_unlock(&v9fs_synth_mutex);
        !           140:     return ret;
        !           141: }
        !           142: 
        !           143: static void v9fs_synth_fill_statbuf(V9fsSynthNode *node, struct stat *stbuf)
        !           144: {
        !           145:     stbuf->st_dev = 0;
        !           146:     stbuf->st_ino = node->attr->inode;
        !           147:     stbuf->st_mode = node->attr->mode;
        !           148:     stbuf->st_nlink = node->attr->nlink;
        !           149:     stbuf->st_uid = 0;
        !           150:     stbuf->st_gid = 0;
        !           151:     stbuf->st_rdev = 0;
        !           152:     stbuf->st_size = 0;
        !           153:     stbuf->st_blksize = 0;
        !           154:     stbuf->st_blocks = 0;
        !           155:     stbuf->st_atime = 0;
        !           156:     stbuf->st_mtime = 0;
        !           157:     stbuf->st_ctime = 0;
        !           158: }
        !           159: 
        !           160: static int v9fs_synth_lstat(FsContext *fs_ctx,
        !           161:                             V9fsPath *fs_path, struct stat *stbuf)
        !           162: {
        !           163:     V9fsSynthNode *node = *(V9fsSynthNode **)fs_path->data;
        !           164: 
        !           165:     v9fs_synth_fill_statbuf(node, stbuf);
        !           166:     return 0;
        !           167: }
        !           168: 
        !           169: static int v9fs_synth_fstat(FsContext *fs_ctx, int fid_type,
        !           170:                             V9fsFidOpenState *fs, struct stat *stbuf)
        !           171: {
        !           172:     V9fsSynthOpenState *synth_open = fs->private;
        !           173:     v9fs_synth_fill_statbuf(synth_open->node, stbuf);
        !           174:     return 0;
        !           175: }
        !           176: 
        !           177: static int v9fs_synth_opendir(FsContext *ctx,
        !           178:                              V9fsPath *fs_path, V9fsFidOpenState *fs)
        !           179: {
        !           180:     V9fsSynthOpenState *synth_open;
        !           181:     V9fsSynthNode *node = *(V9fsSynthNode **)fs_path->data;
        !           182: 
        !           183:     synth_open = g_malloc(sizeof(*synth_open));
        !           184:     synth_open->node = node;
        !           185:     node->open_count++;
        !           186:     fs->private = synth_open;
        !           187:     return 0;
        !           188: }
        !           189: 
        !           190: static int v9fs_synth_closedir(FsContext *ctx, V9fsFidOpenState *fs)
        !           191: {
        !           192:     V9fsSynthOpenState *synth_open = fs->private;
        !           193:     V9fsSynthNode *node = synth_open->node;
        !           194: 
        !           195:     node->open_count--;
        !           196:     g_free(synth_open);
        !           197:     fs->private = NULL;
        !           198:     return 0;
        !           199: }
        !           200: 
        !           201: static off_t v9fs_synth_telldir(FsContext *ctx, V9fsFidOpenState *fs)
        !           202: {
        !           203:     V9fsSynthOpenState *synth_open = fs->private;
        !           204:     return synth_open->offset;
        !           205: }
        !           206: 
        !           207: static void v9fs_synth_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
        !           208: {
        !           209:     V9fsSynthOpenState *synth_open = fs->private;
        !           210:     synth_open->offset = off;
        !           211: }
        !           212: 
        !           213: static void v9fs_synth_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
        !           214: {
        !           215:     v9fs_synth_seekdir(ctx, fs, 0);
        !           216: }
        !           217: 
        !           218: static void v9fs_synth_direntry(V9fsSynthNode *node,
        !           219:                                 struct dirent *entry, off_t off)
        !           220: {
        !           221:     strcpy(entry->d_name, node->name);
        !           222:     entry->d_ino = node->attr->inode;
        !           223:     entry->d_off = off + 1;
        !           224: }
        !           225: 
        !           226: static int v9fs_synth_get_dentry(V9fsSynthNode *dir, struct dirent *entry,
        !           227:                                  struct dirent **result, off_t off)
        !           228: {
        !           229:     int i = 0;
        !           230:     V9fsSynthNode *node;
        !           231: 
        !           232:     rcu_read_lock();
        !           233:     QLIST_FOREACH(node, &dir->child, sibling) {
        !           234:         /* This is the off child of the directory */
        !           235:         if (i == off) {
        !           236:             break;
        !           237:         }
        !           238:         i++;
        !           239:     }
        !           240:     rcu_read_unlock();
        !           241:     if (!node) {
        !           242:         /* end of directory */
        !           243:         *result = NULL;
        !           244:         return 0;
        !           245:     }
        !           246:     v9fs_synth_direntry(node, entry, off);
        !           247:     *result = entry;
        !           248:     return 0;
        !           249: }
        !           250: 
        !           251: static int v9fs_synth_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
        !           252:                                 struct dirent *entry, struct dirent **result)
        !           253: {
        !           254:     int ret;
        !           255:     V9fsSynthOpenState *synth_open = fs->private;
        !           256:     V9fsSynthNode *node = synth_open->node;
        !           257:     ret = v9fs_synth_get_dentry(node, entry, result, synth_open->offset);
        !           258:     if (!ret && *result != NULL) {
        !           259:         synth_open->offset++;
        !           260:     }
        !           261:     return ret;
        !           262: }
        !           263: 
        !           264: static int v9fs_synth_open(FsContext *ctx, V9fsPath *fs_path,
        !           265:                            int flags, V9fsFidOpenState *fs)
        !           266: {
        !           267:     V9fsSynthOpenState *synth_open;
        !           268:     V9fsSynthNode *node = *(V9fsSynthNode **)fs_path->data;
        !           269: 
        !           270:     synth_open = g_malloc(sizeof(*synth_open));
        !           271:     synth_open->node = node;
        !           272:     node->open_count++;
        !           273:     fs->private = synth_open;
        !           274:     return 0;
        !           275: }
        !           276: 
        !           277: static int v9fs_synth_open2(FsContext *fs_ctx, V9fsPath *dir_path,
        !           278:                             const char *name, int flags,
        !           279:                             FsCred *credp, V9fsFidOpenState *fs)
        !           280: {
        !           281:     errno = ENOSYS;
        !           282:     return -1;
        !           283: }
        !           284: 
        !           285: static int v9fs_synth_close(FsContext *ctx, V9fsFidOpenState *fs)
        !           286: {
        !           287:     V9fsSynthOpenState *synth_open = fs->private;
        !           288:     V9fsSynthNode *node = synth_open->node;
        !           289: 
        !           290:     node->open_count--;
        !           291:     g_free(synth_open);
        !           292:     fs->private = NULL;
        !           293:     return 0;
        !           294: }
        !           295: 
        !           296: static ssize_t v9fs_synth_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
        !           297:                                   const struct iovec *iov,
        !           298:                                   int iovcnt, off_t offset)
        !           299: {
        !           300:     int i, count = 0, wcount;
        !           301:     V9fsSynthOpenState *synth_open = fs->private;
        !           302:     V9fsSynthNode *node = synth_open->node;
        !           303:     if (!node->attr->write) {
        !           304:         errno = EPERM;
        !           305:         return -1;
        !           306:     }
        !           307:     for (i = 0; i < iovcnt; i++) {
        !           308:         wcount = node->attr->write(iov[i].iov_base, iov[i].iov_len,
        !           309:                                    offset, node->private);
        !           310:         offset += wcount;
        !           311:         count  += wcount;
        !           312:         /* If we wrote less than requested. we are done */
        !           313:         if (wcount < iov[i].iov_len) {
        !           314:             break;
        !           315:         }
        !           316:     }
        !           317:     return count;
        !           318: }
        !           319: 
        !           320: static ssize_t v9fs_synth_preadv(FsContext *ctx, V9fsFidOpenState *fs,
        !           321:                                  const struct iovec *iov,
        !           322:                                  int iovcnt, off_t offset)
        !           323: {
        !           324:     int i, count = 0, rcount;
        !           325:     V9fsSynthOpenState *synth_open = fs->private;
        !           326:     V9fsSynthNode *node = synth_open->node;
        !           327:     if (!node->attr->read) {
        !           328:         errno = EPERM;
        !           329:         return -1;
        !           330:     }
        !           331:     for (i = 0; i < iovcnt; i++) {
        !           332:         rcount = node->attr->read(iov[i].iov_base, iov[i].iov_len,
        !           333:                                   offset, node->private);
        !           334:         offset += rcount;
        !           335:         count  += rcount;
        !           336:         /* If we read less than requested. we are done */
        !           337:         if (rcount < iov[i].iov_len) {
        !           338:             break;
        !           339:         }
        !           340:     }
        !           341:     return count;
        !           342: }
        !           343: 
        !           344: static int v9fs_synth_truncate(FsContext *ctx, V9fsPath *path, off_t offset)
        !           345: {
        !           346:     errno = ENOSYS;
        !           347:     return -1;
        !           348: }
        !           349: 
        !           350: static int v9fs_synth_chmod(FsContext *fs_ctx, V9fsPath *path, FsCred *credp)
        !           351: {
        !           352:     errno = EPERM;
        !           353:     return -1;
        !           354: }
        !           355: 
        !           356: static int v9fs_synth_mknod(FsContext *fs_ctx, V9fsPath *path,
        !           357:                        const char *buf, FsCred *credp)
        !           358: {
        !           359:     errno = EPERM;
        !           360:     return -1;
        !           361: }
        !           362: 
        !           363: static int v9fs_synth_mkdir(FsContext *fs_ctx, V9fsPath *path,
        !           364:                        const char *buf, FsCred *credp)
        !           365: {
        !           366:     errno = EPERM;
        !           367:     return -1;
        !           368: }
        !           369: 
        !           370: static ssize_t v9fs_synth_readlink(FsContext *fs_ctx, V9fsPath *path,
        !           371:                                    char *buf, size_t bufsz)
        !           372: {
        !           373:     errno = ENOSYS;
        !           374:     return -1;
        !           375: }
        !           376: 
        !           377: static int v9fs_synth_symlink(FsContext *fs_ctx, const char *oldpath,
        !           378:                               V9fsPath *newpath, const char *buf, FsCred *credp)
        !           379: {
        !           380:     errno = EPERM;
        !           381:     return -1;
        !           382: }
        !           383: 
        !           384: static int v9fs_synth_link(FsContext *fs_ctx, V9fsPath *oldpath,
        !           385:                            V9fsPath *newpath, const char *buf)
        !           386: {
        !           387:     errno = EPERM;
        !           388:     return -1;
        !           389: }
        !           390: 
        !           391: static int v9fs_synth_rename(FsContext *ctx, const char *oldpath,
        !           392:                              const char *newpath)
        !           393: {
        !           394:     errno = EPERM;
        !           395:     return -1;
        !           396: }
        !           397: 
        !           398: static int v9fs_synth_chown(FsContext *fs_ctx, V9fsPath *path, FsCred *credp)
        !           399: {
        !           400:     errno = EPERM;
        !           401:     return -1;
        !           402: }
        !           403: 
        !           404: static int v9fs_synth_utimensat(FsContext *fs_ctx, V9fsPath *path,
        !           405:                                 const struct timespec *buf)
        !           406: {
        !           407:     errno = EPERM;
        !           408:     return 0;
        !           409: }
        !           410: 
        !           411: static int v9fs_synth_remove(FsContext *ctx, const char *path)
        !           412: {
        !           413:     errno = EPERM;
        !           414:     return -1;
        !           415: }
        !           416: 
        !           417: static int v9fs_synth_fsync(FsContext *ctx, int fid_type,
        !           418:                             V9fsFidOpenState *fs, int datasync)
        !           419: {
        !           420:     errno = ENOSYS;
        !           421:     return 0;
        !           422: }
        !           423: 
        !           424: static int v9fs_synth_statfs(FsContext *s, V9fsPath *fs_path,
        !           425:                              struct statfs *stbuf)
        !           426: {
        !           427:     stbuf->f_type = 0xABCD;
        !           428:     stbuf->f_bsize = 512;
        !           429:     stbuf->f_blocks = 0;
        !           430:     stbuf->f_files = v9fs_synth_node_count;
        !           431:     stbuf->f_namelen = NAME_MAX;
        !           432:     return 0;
        !           433: }
        !           434: 
        !           435: static ssize_t v9fs_synth_lgetxattr(FsContext *ctx, V9fsPath *path,
        !           436:                                     const char *name, void *value, size_t size)
        !           437: {
        !           438:     errno = ENOTSUP;
        !           439:     return -1;
        !           440: }
        !           441: 
        !           442: static ssize_t v9fs_synth_llistxattr(FsContext *ctx, V9fsPath *path,
        !           443:                                      void *value, size_t size)
        !           444: {
        !           445:     errno = ENOTSUP;
        !           446:     return -1;
        !           447: }
        !           448: 
        !           449: static int v9fs_synth_lsetxattr(FsContext *ctx, V9fsPath *path,
        !           450:                                 const char *name, void *value,
        !           451:                                 size_t size, int flags)
        !           452: {
        !           453:     errno = ENOTSUP;
        !           454:     return -1;
        !           455: }
        !           456: 
        !           457: static int v9fs_synth_lremovexattr(FsContext *ctx,
        !           458:                                    V9fsPath *path, const char *name)
        !           459: {
        !           460:     errno = ENOTSUP;
        !           461:     return -1;
        !           462: }
        !           463: 
        !           464: static int v9fs_synth_name_to_path(FsContext *ctx, V9fsPath *dir_path,
        !           465:                                    const char *name, V9fsPath *target)
        !           466: {
        !           467:     V9fsSynthNode *node;
        !           468:     V9fsSynthNode *dir_node;
        !           469: 
        !           470:     /* "." and ".." are not allowed */
        !           471:     if (!strcmp(name, ".") || !strcmp(name, "..")) {
        !           472:         errno = EINVAL;
        !           473:         return -1;
        !           474: 
        !           475:     }
        !           476:     if (!dir_path) {
        !           477:         dir_node = &v9fs_synth_root;
        !           478:     } else {
        !           479:         dir_node = *(V9fsSynthNode **)dir_path->data;
        !           480:     }
        !           481:     if (!strcmp(name, "/")) {
        !           482:         node = dir_node;
        !           483:         goto out;
        !           484:     }
        !           485:     /* search for the name in the childern */
        !           486:     rcu_read_lock();
        !           487:     QLIST_FOREACH(node, &dir_node->child, sibling) {
        !           488:         if (!strcmp(node->name, name)) {
        !           489:             break;
        !           490:         }
        !           491:     }
        !           492:     rcu_read_unlock();
        !           493: 
        !           494:     if (!node) {
        !           495:         errno = ENOENT;
        !           496:         return -1;
        !           497:     }
        !           498: out:
        !           499:     /* Copy the node pointer to fid */
        !           500:     target->data = g_malloc(sizeof(void *));
        !           501:     memcpy(target->data, &node, sizeof(void *));
        !           502:     target->size = sizeof(void *);
        !           503:     return 0;
        !           504: }
        !           505: 
        !           506: static int v9fs_synth_renameat(FsContext *ctx, V9fsPath *olddir,
        !           507:                                const char *old_name, V9fsPath *newdir,
        !           508:                                const char *new_name)
        !           509: {
        !           510:     errno = EPERM;
        !           511:     return -1;
        !           512: }
        !           513: 
        !           514: static int v9fs_synth_unlinkat(FsContext *ctx, V9fsPath *dir,
        !           515:                                const char *name, int flags)
        !           516: {
        !           517:     errno = EPERM;
        !           518:     return -1;
        !           519: }
        !           520: 
        !           521: static int v9fs_synth_init(FsContext *ctx)
        !           522: {
        !           523:     QLIST_INIT(&v9fs_synth_root.child);
        !           524:     qemu_mutex_init(&v9fs_synth_mutex);
        !           525: 
        !           526:     /* Add "." and ".." entries for root */
        !           527:     v9fs_add_dir_node(&v9fs_synth_root, v9fs_synth_root.attr->mode,
        !           528:                       "..", v9fs_synth_root.attr, v9fs_synth_root.attr->inode);
        !           529:     v9fs_add_dir_node(&v9fs_synth_root, v9fs_synth_root.attr->mode,
        !           530:                       ".", v9fs_synth_root.attr, v9fs_synth_root.attr->inode);
        !           531: 
        !           532:     /* Mark the subsystem is ready for use */
        !           533:     v9fs_synth_fs = 1;
        !           534:     return 0;
        !           535: }
        !           536: 
        !           537: FileOperations synth_ops = {
        !           538:     .init         = v9fs_synth_init,
        !           539:     .lstat        = v9fs_synth_lstat,
        !           540:     .readlink     = v9fs_synth_readlink,
        !           541:     .close        = v9fs_synth_close,
        !           542:     .closedir     = v9fs_synth_closedir,
        !           543:     .open         = v9fs_synth_open,
        !           544:     .opendir      = v9fs_synth_opendir,
        !           545:     .rewinddir    = v9fs_synth_rewinddir,
        !           546:     .telldir      = v9fs_synth_telldir,
        !           547:     .readdir_r    = v9fs_synth_readdir_r,
        !           548:     .seekdir      = v9fs_synth_seekdir,
        !           549:     .preadv       = v9fs_synth_preadv,
        !           550:     .pwritev      = v9fs_synth_pwritev,
        !           551:     .chmod        = v9fs_synth_chmod,
        !           552:     .mknod        = v9fs_synth_mknod,
        !           553:     .mkdir        = v9fs_synth_mkdir,
        !           554:     .fstat        = v9fs_synth_fstat,
        !           555:     .open2        = v9fs_synth_open2,
        !           556:     .symlink      = v9fs_synth_symlink,
        !           557:     .link         = v9fs_synth_link,
        !           558:     .truncate     = v9fs_synth_truncate,
        !           559:     .rename       = v9fs_synth_rename,
        !           560:     .chown        = v9fs_synth_chown,
        !           561:     .utimensat    = v9fs_synth_utimensat,
        !           562:     .remove       = v9fs_synth_remove,
        !           563:     .fsync        = v9fs_synth_fsync,
        !           564:     .statfs       = v9fs_synth_statfs,
        !           565:     .lgetxattr    = v9fs_synth_lgetxattr,
        !           566:     .llistxattr   = v9fs_synth_llistxattr,
        !           567:     .lsetxattr    = v9fs_synth_lsetxattr,
        !           568:     .lremovexattr = v9fs_synth_lremovexattr,
        !           569:     .name_to_path = v9fs_synth_name_to_path,
        !           570:     .renameat     = v9fs_synth_renameat,
        !           571:     .unlinkat     = v9fs_synth_unlinkat,
        !           572: };

unix.superglobalmegacorp.com

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