Annotation of qemu/hw/9pfs/virtio-9p-handle.c, revision 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.