|
|
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: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.