Annotation of qemu/hw/9pfs/virtio-9p-handle.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Virtio 9p handle callback
                      3:  *
                      4:  * Copyright IBM, Corp. 2011
                      5:  *
                      6:  * Authors:
                      7:  *    Aneesh Kumar K.V <[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:  */
                     13: 
                     14: #include "hw/virtio.h"
                     15: #include "virtio-9p.h"
                     16: #include "virtio-9p-xattr.h"
                     17: #include <arpa/inet.h>
                     18: #include <pwd.h>
                     19: #include <grp.h>
                     20: #include <sys/socket.h>
                     21: #include <sys/un.h>
                     22: #include "qemu-xattr.h"
                     23: #include <unistd.h>
                     24: #include <linux/fs.h>
                     25: #ifdef CONFIG_LINUX_MAGIC_H
                     26: #include <linux/magic.h>
                     27: #endif
                     28: #include <sys/ioctl.h>
                     29: 
                     30: #ifndef XFS_SUPER_MAGIC
                     31: #define XFS_SUPER_MAGIC  0x58465342
                     32: #endif
                     33: #ifndef EXT2_SUPER_MAGIC
                     34: #define EXT2_SUPER_MAGIC 0xEF53
                     35: #endif
                     36: #ifndef REISERFS_SUPER_MAGIC
                     37: #define REISERFS_SUPER_MAGIC 0x52654973
                     38: #endif
                     39: #ifndef BTRFS_SUPER_MAGIC
                     40: #define BTRFS_SUPER_MAGIC 0x9123683E
                     41: #endif
                     42: 
                     43: struct handle_data {
                     44:     int mountfd;
                     45:     int handle_bytes;
                     46: };
                     47: 
                     48: static inline int name_to_handle(int dirfd, const char *name,
                     49:                                  struct file_handle *fh, int *mnt_id, int flags)
                     50: {
                     51:     return name_to_handle_at(dirfd, name, fh, mnt_id, flags);
                     52: }
                     53: 
                     54: static inline int open_by_handle(int mountfd, const char *fh, int flags)
                     55: {
                     56:     return open_by_handle_at(mountfd, (struct file_handle *)fh, flags);
                     57: }
                     58: 
                     59: static int handle_update_file_cred(int dirfd, const char *name, FsCred *credp)
                     60: {
                     61:     int fd, ret;
                     62:     fd = openat(dirfd, name, O_NONBLOCK | O_NOFOLLOW);;
                     63:     if (fd < 0) {
                     64:         return fd;
                     65:     }
                     66:     ret = fchmod(fd, credp->fc_mode & 07777);
                     67:     if (ret < 0) {
                     68:         goto err_out;
                     69:     }
                     70:     ret = fchownat(fd, "", credp->fc_uid, credp->fc_gid, AT_EMPTY_PATH);
                     71: err_out:
                     72:     close(fd);
                     73:     return ret;
                     74: }
                     75: 
                     76: 
                     77: static int handle_lstat(FsContext *fs_ctx, V9fsPath *fs_path,
                     78:                         struct stat *stbuf)
                     79: {
                     80:     int fd, ret;
                     81:     struct handle_data *data = (struct handle_data *)fs_ctx->private;
                     82: 
                     83:     fd = open_by_handle(data->mountfd, fs_path->data, O_PATH);
                     84:     if (fd < 0) {
                     85:         return fd;
                     86:     }
                     87:     ret = fstatat(fd, "", stbuf, AT_EMPTY_PATH);
                     88:     close(fd);
                     89:     return ret;
                     90: }
                     91: 
                     92: static ssize_t handle_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
                     93:                                char *buf, size_t bufsz)
                     94: {
                     95:     int fd, ret;
                     96:     struct handle_data *data = (struct handle_data *)fs_ctx->private;
                     97: 
                     98:     fd = open_by_handle(data->mountfd, fs_path->data, O_PATH);
                     99:     if (fd < 0) {
                    100:         return fd;
                    101:     }
                    102:     ret = readlinkat(fd, "", buf, bufsz);
                    103:     close(fd);
                    104:     return ret;
                    105: }
                    106: 
                    107: static int handle_close(FsContext *ctx, V9fsFidOpenState *fs)
                    108: {
                    109:     return close(fs->fd);
                    110: }
                    111: 
                    112: static int handle_closedir(FsContext *ctx, V9fsFidOpenState *fs)
                    113: {
                    114:     return closedir(fs->dir);
                    115: }
                    116: 
                    117: static int handle_open(FsContext *ctx, V9fsPath *fs_path,
                    118:                        int flags, V9fsFidOpenState *fs)
                    119: {
                    120:     struct handle_data *data = (struct handle_data *)ctx->private;
                    121: 
                    122:     fs->fd = open_by_handle(data->mountfd, fs_path->data, flags);
                    123:     return fs->fd;
                    124: }
                    125: 
                    126: static int handle_opendir(FsContext *ctx,
                    127:                           V9fsPath *fs_path, V9fsFidOpenState *fs)
                    128: {
                    129:     int ret;
                    130:     ret = handle_open(ctx, fs_path, O_DIRECTORY, fs);
                    131:     if (ret < 0) {
                    132:         return -1;
                    133:     }
                    134:     fs->dir = fdopendir(ret);
                    135:     if (!fs->dir) {
                    136:         return -1;
                    137:     }
                    138:     return 0;
                    139: }
                    140: 
                    141: static void handle_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
                    142: {
                    143:     return rewinddir(fs->dir);
                    144: }
                    145: 
                    146: static off_t handle_telldir(FsContext *ctx, V9fsFidOpenState *fs)
                    147: {
                    148:     return telldir(fs->dir);
                    149: }
                    150: 
                    151: static int handle_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
                    152:                             struct dirent *entry,
                    153:                             struct dirent **result)
                    154: {
                    155:     return readdir_r(fs->dir, entry, result);
                    156: }
                    157: 
                    158: static void handle_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
                    159: {
                    160:     return seekdir(fs->dir, off);
                    161: }
                    162: 
                    163: static ssize_t handle_preadv(FsContext *ctx, V9fsFidOpenState *fs,
                    164:                              const struct iovec *iov,
                    165:                              int iovcnt, off_t offset)
                    166: {
                    167: #ifdef CONFIG_PREADV
                    168:     return preadv(fs->fd, iov, iovcnt, offset);
                    169: #else
                    170:     int err = lseek(fs->fd, offset, SEEK_SET);
                    171:     if (err == -1) {
                    172:         return err;
                    173:     } else {
                    174:         return readv(fs->fd, iov, iovcnt);
                    175:     }
                    176: #endif
                    177: }
                    178: 
                    179: static ssize_t handle_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
                    180:                               const struct iovec *iov,
                    181:                               int iovcnt, off_t offset)
                    182: {
                    183:     ssize_t ret;
                    184: #ifdef CONFIG_PREADV
                    185:     ret = pwritev(fs->fd, iov, iovcnt, offset);
                    186: #else
                    187:     int err = lseek(fs->fd, offset, SEEK_SET);
                    188:     if (err == -1) {
                    189:         return err;
                    190:     } else {
                    191:         ret = writev(fs->fd, iov, iovcnt);
                    192:     }
                    193: #endif
                    194: #ifdef CONFIG_SYNC_FILE_RANGE
                    195:     if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) {
                    196:         /*
                    197:          * Initiate a writeback. This is not a data integrity sync.
                    198:          * We want to ensure that we don't leave dirty pages in the cache
                    199:          * after write when writeout=immediate is sepcified.
                    200:          */
                    201:         sync_file_range(fs->fd, offset, ret,
                    202:                         SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE);
                    203:     }
                    204: #endif
                    205:     return ret;
                    206: }
                    207: 
                    208: static int handle_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
                    209: {
                    210:     int fd, ret;
                    211:     struct handle_data *data = (struct handle_data *)fs_ctx->private;
                    212: 
                    213:     fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
                    214:     if (fd < 0) {
                    215:         return fd;
                    216:     }
                    217:     ret = fchmod(fd, credp->fc_mode);
                    218:     close(fd);
                    219:     return ret;
                    220: }
                    221: 
                    222: static int handle_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
                    223:                        const char *name, FsCred *credp)
                    224: {
                    225:     int dirfd, ret;
                    226:     struct handle_data *data = (struct handle_data *)fs_ctx->private;
                    227: 
                    228:     dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
                    229:     if (dirfd < 0) {
                    230:         return dirfd;
                    231:     }
                    232:     ret = mknodat(dirfd, name, credp->fc_mode, credp->fc_rdev);
                    233:     if (!ret) {
                    234:         ret = handle_update_file_cred(dirfd, name, credp);
                    235:     }
                    236:     close(dirfd);
                    237:     return ret;
                    238: }
                    239: 
                    240: static int handle_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
                    241:                        const char *name, FsCred *credp)
                    242: {
                    243:     int dirfd, ret;
                    244:     struct handle_data *data = (struct handle_data *)fs_ctx->private;
                    245: 
                    246:     dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
                    247:     if (dirfd < 0) {
                    248:         return dirfd;
                    249:     }
                    250:     ret = mkdirat(dirfd, name, credp->fc_mode);
                    251:     if (!ret) {
                    252:         ret = handle_update_file_cred(dirfd, name, credp);
                    253:     }
                    254:     close(dirfd);
                    255:     return ret;
                    256: }
                    257: 
                    258: static int handle_fstat(FsContext *fs_ctx, int fid_type,
                    259:                         V9fsFidOpenState *fs, struct stat *stbuf)
                    260: {
                    261:     int fd;
                    262: 
                    263:     if (fid_type == P9_FID_DIR) {
                    264:         fd = dirfd(fs->dir);
                    265:     } else {
                    266:         fd = fs->fd;
                    267:     }
                    268:     return fstat(fd, stbuf);
                    269: }
                    270: 
                    271: static int handle_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
                    272:                         int flags, FsCred *credp, V9fsFidOpenState *fs)
                    273: {
                    274:     int ret;
                    275:     int dirfd, fd;
                    276:     struct handle_data *data = (struct handle_data *)fs_ctx->private;
                    277: 
                    278:     dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
                    279:     if (dirfd < 0) {
                    280:         return dirfd;
                    281:     }
                    282:     fd = openat(dirfd, name, flags | O_NOFOLLOW, credp->fc_mode);
                    283:     if (fd >= 0) {
                    284:         ret = handle_update_file_cred(dirfd, name, credp);
                    285:         if (ret < 0) {
                    286:             close(fd);
                    287:             fd = ret;
                    288:         } else {
                    289:             fs->fd = fd;
                    290:         }
                    291:     }
                    292:     close(dirfd);
                    293:     return fd;
                    294: }
                    295: 
                    296: 
                    297: static int handle_symlink(FsContext *fs_ctx, const char *oldpath,
                    298:                           V9fsPath *dir_path, const char *name, FsCred *credp)
                    299: {
                    300:     int fd, dirfd, ret;
                    301:     struct handle_data *data = (struct handle_data *)fs_ctx->private;
                    302: 
                    303:     dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
                    304:     if (dirfd < 0) {
                    305:         return dirfd;
                    306:     }
                    307:     ret = symlinkat(oldpath, dirfd, name);
                    308:     if (!ret) {
                    309:         fd = openat(dirfd, name, O_PATH | O_NOFOLLOW);
                    310:         if (fd < 0) {
                    311:             ret = fd;
                    312:             goto err_out;
                    313:         }
                    314:         ret = fchownat(fd, "", credp->fc_uid, credp->fc_gid, AT_EMPTY_PATH);
                    315:         close(fd);
                    316:     }
                    317: err_out:
                    318:     close(dirfd);
                    319:     return ret;
                    320: }
                    321: 
                    322: static int handle_link(FsContext *ctx, V9fsPath *oldpath,
                    323:                        V9fsPath *dirpath, const char *name)
                    324: {
                    325:     int oldfd, newdirfd, ret;
                    326:     struct handle_data *data = (struct handle_data *)ctx->private;
                    327: 
                    328:     oldfd = open_by_handle(data->mountfd, oldpath->data, O_PATH);
                    329:     if (oldfd < 0) {
                    330:         return oldfd;
                    331:     }
                    332:     newdirfd = open_by_handle(data->mountfd, dirpath->data, O_PATH);
                    333:     if (newdirfd < 0) {
                    334:         close(oldfd);
                    335:         return newdirfd;
                    336:     }
                    337:     ret = linkat(oldfd, "", newdirfd, name, AT_EMPTY_PATH);
                    338:     close(newdirfd);
                    339:     close(oldfd);
                    340:     return ret;
                    341: }
                    342: 
                    343: static int handle_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
                    344: {
                    345:     int fd, ret;
                    346:     struct handle_data *data = (struct handle_data *)ctx->private;
                    347: 
                    348:     fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK | O_WRONLY);
                    349:     if (fd < 0) {
                    350:         return fd;
                    351:     }
                    352:     ret = ftruncate(fd, size);
                    353:     close(fd);
                    354:     return ret;
                    355: }
                    356: 
                    357: static int handle_rename(FsContext *ctx, const char *oldpath,
                    358:                          const char *newpath)
                    359: {
                    360:     errno = EOPNOTSUPP;
                    361:     return -1;
                    362: }
                    363: 
                    364: static int handle_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
                    365: {
                    366:     int fd, ret;
                    367:     struct handle_data *data = (struct handle_data *)fs_ctx->private;
                    368: 
                    369:     fd = open_by_handle(data->mountfd, fs_path->data, O_PATH);
                    370:     if (fd < 0) {
                    371:         return fd;
                    372:     }
                    373:     ret = fchownat(fd, "", credp->fc_uid, credp->fc_gid, AT_EMPTY_PATH);
                    374:     close(fd);
                    375:     return ret;
                    376: }
                    377: 
                    378: static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path,
                    379:                             const struct timespec *buf)
                    380: {
                    381:     int ret;
                    382: #ifdef CONFIG_UTIMENSAT
                    383:     int fd;
                    384:     struct handle_data *data = (struct handle_data *)ctx->private;
                    385: 
                    386:     fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
                    387:     if (fd < 0) {
                    388:         return fd;
                    389:     }
                    390:     ret = futimens(fd, buf);
                    391:     close(fd);
                    392: #else
                    393:     ret = -1;
                    394:     errno = ENOSYS;
                    395: #endif
                    396:     return ret;
                    397: }
                    398: 
                    399: static int handle_remove(FsContext *ctx, const char *path)
                    400: {
                    401:     errno = EOPNOTSUPP;
                    402:     return -1;
                    403: }
                    404: 
                    405: static int handle_fsync(FsContext *ctx, int fid_type,
                    406:                         V9fsFidOpenState *fs, int datasync)
                    407: {
                    408:     int fd;
                    409: 
                    410:     if (fid_type == P9_FID_DIR) {
                    411:         fd = dirfd(fs->dir);
                    412:     } else {
                    413:         fd = fs->fd;
                    414:     }
                    415: 
                    416:     if (datasync) {
                    417:         return qemu_fdatasync(fd);
                    418:     } else {
                    419:         return fsync(fd);
                    420:     }
                    421: }
                    422: 
                    423: static int handle_statfs(FsContext *ctx, V9fsPath *fs_path,
                    424:                          struct statfs *stbuf)
                    425: {
                    426:     int fd, ret;
                    427:     struct handle_data *data = (struct handle_data *)ctx->private;
                    428: 
                    429:     fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
                    430:     if (fd < 0) {
                    431:         return fd;
                    432:     }
                    433:     ret = fstatfs(fd, stbuf);
                    434:     close(fd);
                    435:     return ret;
                    436: }
                    437: 
                    438: static ssize_t handle_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
                    439:                                 const char *name, void *value, size_t size)
                    440: {
                    441:     int fd, ret;
                    442:     struct handle_data *data = (struct handle_data *)ctx->private;
                    443: 
                    444:     fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
                    445:     if (fd < 0) {
                    446:         return fd;
                    447:     }
                    448:     ret = fgetxattr(fd, name, value, size);
                    449:     close(fd);
                    450:     return ret;
                    451: }
                    452: 
                    453: static ssize_t handle_llistxattr(FsContext *ctx, V9fsPath *fs_path,
                    454:                                  void *value, size_t size)
                    455: {
                    456:     int fd, ret;
                    457:     struct handle_data *data = (struct handle_data *)ctx->private;
                    458: 
                    459:     fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
                    460:     if (fd < 0) {
                    461:         return fd;
                    462:     }
                    463:     ret = flistxattr(fd, value, size);
                    464:     close(fd);
                    465:     return ret;
                    466: }
                    467: 
                    468: static int handle_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
                    469:                             void *value, size_t size, int flags)
                    470: {
                    471:     int fd, ret;
                    472:     struct handle_data *data = (struct handle_data *)ctx->private;
                    473: 
                    474:     fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
                    475:     if (fd < 0) {
                    476:         return fd;
                    477:     }
                    478:     ret = fsetxattr(fd, name, value, size, flags);
                    479:     close(fd);
                    480:     return ret;
                    481: }
                    482: 
                    483: static int handle_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
                    484:                                const char *name)
                    485: {
                    486:     int fd, ret;
                    487:     struct handle_data *data = (struct handle_data *)ctx->private;
                    488: 
                    489:     fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
                    490:     if (fd < 0) {
                    491:         return fd;
                    492:     }
                    493:     ret = fremovexattr(fd, name);
                    494:     close(fd);
                    495:     return ret;
                    496: }
                    497: 
                    498: static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
                    499:                               const char *name, V9fsPath *target)
                    500: {
                    501:     char buffer[PATH_MAX];
                    502:     struct file_handle *fh;
                    503:     int dirfd, ret, mnt_id;
                    504:     struct handle_data *data = (struct handle_data *)ctx->private;
                    505: 
                    506:     /* "." and ".." are not allowed */
                    507:     if (!strcmp(name, ".") || !strcmp(name, "..")) {
                    508:         errno = EINVAL;
                    509:         return -1;
                    510: 
                    511:     }
                    512:     if (dir_path) {
                    513:         dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
                    514:     } else {
                    515:         /* relative to export root */
                    516:         dirfd = open(rpath(ctx, ".", buffer), O_DIRECTORY);
                    517:     }
                    518:     if (dirfd < 0) {
                    519:         return dirfd;
                    520:     }
                    521:     fh = g_malloc(sizeof(struct file_handle) + data->handle_bytes);
                    522:     fh->handle_bytes = data->handle_bytes;
                    523:     /* add a "./" at the begining of the path */
                    524:     snprintf(buffer, PATH_MAX, "./%s", name);
                    525:     /* flag = 0 imply don't follow symlink */
                    526:     ret = name_to_handle(dirfd, buffer, fh, &mnt_id, 0);
                    527:     if (!ret) {
                    528:         target->data = (char *)fh;
                    529:         target->size = sizeof(struct file_handle) + data->handle_bytes;
                    530:     } else {
                    531:         g_free(fh);
                    532:     }
                    533:     close(dirfd);
                    534:     return ret;
                    535: }
                    536: 
                    537: static int handle_renameat(FsContext *ctx, V9fsPath *olddir,
                    538:                            const char *old_name, V9fsPath *newdir,
                    539:                            const char *new_name)
                    540: {
                    541:     int olddirfd, newdirfd, ret;
                    542:     struct handle_data *data = (struct handle_data *)ctx->private;
                    543: 
                    544:     olddirfd = open_by_handle(data->mountfd, olddir->data, O_PATH);
                    545:     if (olddirfd < 0) {
                    546:         return olddirfd;
                    547:     }
                    548:     newdirfd = open_by_handle(data->mountfd, newdir->data, O_PATH);
                    549:     if (newdirfd < 0) {
                    550:         close(olddirfd);
                    551:         return newdirfd;
                    552:     }
                    553:     ret = renameat(olddirfd, old_name, newdirfd, new_name);
                    554:     close(newdirfd);
                    555:     close(olddirfd);
                    556:     return ret;
                    557: }
                    558: 
                    559: static int handle_unlinkat(FsContext *ctx, V9fsPath *dir,
                    560:                            const char *name, int flags)
                    561: {
                    562:     int dirfd, ret;
                    563:     struct handle_data *data = (struct handle_data *)ctx->private;
                    564:     int rflags;
                    565: 
                    566:     dirfd = open_by_handle(data->mountfd, dir->data, O_PATH);
                    567:     if (dirfd < 0) {
                    568:         return dirfd;
                    569:     }
                    570: 
                    571:     rflags = 0;
                    572:     if (flags & P9_DOTL_AT_REMOVEDIR) {
                    573:         rflags |= AT_REMOVEDIR;
                    574:     }
                    575: 
                    576:     ret = unlinkat(dirfd, name, rflags);
                    577: 
                    578:     close(dirfd);
                    579:     return ret;
                    580: }
                    581: 
                    582: static int handle_ioc_getversion(FsContext *ctx, V9fsPath *path,
                    583:                                  mode_t st_mode, uint64_t *st_gen)
                    584: {
                    585:     int err;
                    586:     V9fsFidOpenState fid_open;
                    587: 
                    588:     /*
                    589:      * Do not try to open special files like device nodes, fifos etc
                    590:      * We can get fd for regular files and directories only
                    591:      */
                    592:     if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) {
                    593:             return 0;
                    594:     }
                    595:     err = handle_open(ctx, path, O_RDONLY, &fid_open);
                    596:     if (err < 0) {
                    597:         return err;
                    598:     }
                    599:     err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen);
                    600:     handle_close(ctx, &fid_open);
                    601:     return err;
                    602: }
                    603: 
                    604: static int handle_init(FsContext *ctx)
                    605: {
                    606:     int ret, mnt_id;
                    607:     struct statfs stbuf;
                    608:     struct file_handle fh;
                    609:     struct handle_data *data = g_malloc(sizeof(struct handle_data));
                    610: 
                    611:     data->mountfd = open(ctx->fs_root, O_DIRECTORY);
                    612:     if (data->mountfd < 0) {
                    613:         ret = data->mountfd;
                    614:         goto err_out;
                    615:     }
                    616:     ret = statfs(ctx->fs_root, &stbuf);
                    617:     if (!ret) {
                    618:         switch (stbuf.f_type) {
                    619:         case EXT2_SUPER_MAGIC:
                    620:         case BTRFS_SUPER_MAGIC:
                    621:         case REISERFS_SUPER_MAGIC:
                    622:         case XFS_SUPER_MAGIC:
                    623:             ctx->exops.get_st_gen = handle_ioc_getversion;
                    624:             break;
                    625:         }
                    626:     }
                    627:     memset(&fh, 0, sizeof(struct file_handle));
                    628:     ret = name_to_handle(data->mountfd, ".", &fh, &mnt_id, 0);
                    629:     if (ret && errno == EOVERFLOW) {
                    630:         data->handle_bytes = fh.handle_bytes;
                    631:         ctx->private = data;
                    632:         ret = 0;
                    633:         goto out;
                    634:     }
                    635:     /* we got 0 byte handle ? */
                    636:     ret = -1;
                    637:     close(data->mountfd);
                    638: err_out:
                    639:     g_free(data);
                    640: out:
                    641:     return ret;
                    642: }
                    643: 
                    644: FileOperations handle_ops = {
                    645:     .init         = handle_init,
                    646:     .lstat        = handle_lstat,
                    647:     .readlink     = handle_readlink,
                    648:     .close        = handle_close,
                    649:     .closedir     = handle_closedir,
                    650:     .open         = handle_open,
                    651:     .opendir      = handle_opendir,
                    652:     .rewinddir    = handle_rewinddir,
                    653:     .telldir      = handle_telldir,
                    654:     .readdir_r    = handle_readdir_r,
                    655:     .seekdir      = handle_seekdir,
                    656:     .preadv       = handle_preadv,
                    657:     .pwritev      = handle_pwritev,
                    658:     .chmod        = handle_chmod,
                    659:     .mknod        = handle_mknod,
                    660:     .mkdir        = handle_mkdir,
                    661:     .fstat        = handle_fstat,
                    662:     .open2        = handle_open2,
                    663:     .symlink      = handle_symlink,
                    664:     .link         = handle_link,
                    665:     .truncate     = handle_truncate,
                    666:     .rename       = handle_rename,
                    667:     .chown        = handle_chown,
                    668:     .utimensat    = handle_utimensat,
                    669:     .remove       = handle_remove,
                    670:     .fsync        = handle_fsync,
                    671:     .statfs       = handle_statfs,
                    672:     .lgetxattr    = handle_lgetxattr,
                    673:     .llistxattr   = handle_llistxattr,
                    674:     .lsetxattr    = handle_lsetxattr,
                    675:     .lremovexattr = handle_lremovexattr,
                    676:     .name_to_path = handle_name_to_path,
                    677:     .renameat     = handle_renameat,
                    678:     .unlinkat     = handle_unlinkat,
                    679: };

unix.superglobalmegacorp.com

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