test-fsmount.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /* fd-based mount test.
  3. *
  4. * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
  5. * Written by David Howells (dhowells@redhat.com)
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <unistd.h>
  10. #include <errno.h>
  11. #include <fcntl.h>
  12. #include <sys/prctl.h>
  13. #include <sys/wait.h>
  14. #include <linux/mount.h>
  15. #include <linux/unistd.h>
  16. #define E(x) do { if ((x) == -1) { perror(#x); exit(1); } } while(0)
  17. static void check_messages(int fd)
  18. {
  19. char buf[4096];
  20. int err, n;
  21. err = errno;
  22. for (;;) {
  23. n = read(fd, buf, sizeof(buf));
  24. if (n < 0)
  25. break;
  26. n -= 2;
  27. switch (buf[0]) {
  28. case 'e':
  29. fprintf(stderr, "Error: %*.*s\n", n, n, buf + 2);
  30. break;
  31. case 'w':
  32. fprintf(stderr, "Warning: %*.*s\n", n, n, buf + 2);
  33. break;
  34. case 'i':
  35. fprintf(stderr, "Info: %*.*s\n", n, n, buf + 2);
  36. break;
  37. }
  38. }
  39. errno = err;
  40. }
  41. static __attribute__((noreturn))
  42. void mount_error(int fd, const char *s)
  43. {
  44. check_messages(fd);
  45. fprintf(stderr, "%s: %m\n", s);
  46. exit(1);
  47. }
  48. /* Hope -1 isn't a syscall */
  49. #ifndef __NR_fsopen
  50. #define __NR_fsopen -1
  51. #endif
  52. #ifndef __NR_fsmount
  53. #define __NR_fsmount -1
  54. #endif
  55. #ifndef __NR_fsconfig
  56. #define __NR_fsconfig -1
  57. #endif
  58. #ifndef __NR_move_mount
  59. #define __NR_move_mount -1
  60. #endif
  61. static inline int fsopen(const char *fs_name, unsigned int flags)
  62. {
  63. return syscall(__NR_fsopen, fs_name, flags);
  64. }
  65. static inline int fsmount(int fsfd, unsigned int flags, unsigned int ms_flags)
  66. {
  67. return syscall(__NR_fsmount, fsfd, flags, ms_flags);
  68. }
  69. static inline int fsconfig(int fsfd, unsigned int cmd,
  70. const char *key, const void *val, int aux)
  71. {
  72. return syscall(__NR_fsconfig, fsfd, cmd, key, val, aux);
  73. }
  74. static inline int move_mount(int from_dfd, const char *from_pathname,
  75. int to_dfd, const char *to_pathname,
  76. unsigned int flags)
  77. {
  78. return syscall(__NR_move_mount,
  79. from_dfd, from_pathname,
  80. to_dfd, to_pathname, flags);
  81. }
  82. #define E_fsconfig(fd, cmd, key, val, aux) \
  83. do { \
  84. if (fsconfig(fd, cmd, key, val, aux) == -1) \
  85. mount_error(fd, key ?: "create"); \
  86. } while (0)
  87. int main(int argc, char *argv[])
  88. {
  89. int fsfd, mfd;
  90. /* Mount a publically available AFS filesystem */
  91. fsfd = fsopen("afs", 0);
  92. if (fsfd == -1) {
  93. perror("fsopen");
  94. exit(1);
  95. }
  96. E_fsconfig(fsfd, FSCONFIG_SET_STRING, "source", "#grand.central.org:root.cell.", 0);
  97. E_fsconfig(fsfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0);
  98. mfd = fsmount(fsfd, 0, MOUNT_ATTR_RDONLY);
  99. if (mfd < 0)
  100. mount_error(fsfd, "fsmount");
  101. E(close(fsfd));
  102. if (move_mount(mfd, "", AT_FDCWD, "/mnt", MOVE_MOUNT_F_EMPTY_PATH) < 0) {
  103. perror("move_mount");
  104. exit(1);
  105. }
  106. E(close(mfd));
  107. exit(0);
  108. }