0001
0002
0003
0004
0005
0006
0007
0008 #include <stdio.h>
0009 #include <stdlib.h>
0010 #include <unistd.h>
0011 #include <errno.h>
0012 #include <fcntl.h>
0013 #include <sys/prctl.h>
0014 #include <sys/wait.h>
0015 #include <linux/mount.h>
0016 #include <linux/unistd.h>
0017
0018 #define E(x) do { if ((x) == -1) { perror(#x); exit(1); } } while(0)
0019
0020 static void check_messages(int fd)
0021 {
0022 char buf[4096];
0023 int err, n;
0024
0025 err = errno;
0026
0027 for (;;) {
0028 n = read(fd, buf, sizeof(buf));
0029 if (n < 0)
0030 break;
0031 n -= 2;
0032
0033 switch (buf[0]) {
0034 case 'e':
0035 fprintf(stderr, "Error: %*.*s\n", n, n, buf + 2);
0036 break;
0037 case 'w':
0038 fprintf(stderr, "Warning: %*.*s\n", n, n, buf + 2);
0039 break;
0040 case 'i':
0041 fprintf(stderr, "Info: %*.*s\n", n, n, buf + 2);
0042 break;
0043 }
0044 }
0045
0046 errno = err;
0047 }
0048
0049 static __attribute__((noreturn))
0050 void mount_error(int fd, const char *s)
0051 {
0052 check_messages(fd);
0053 fprintf(stderr, "%s: %m\n", s);
0054 exit(1);
0055 }
0056
0057
0058 #ifndef __NR_fsopen
0059 #define __NR_fsopen -1
0060 #endif
0061 #ifndef __NR_fsmount
0062 #define __NR_fsmount -1
0063 #endif
0064 #ifndef __NR_fsconfig
0065 #define __NR_fsconfig -1
0066 #endif
0067 #ifndef __NR_move_mount
0068 #define __NR_move_mount -1
0069 #endif
0070
0071
0072 static inline int fsopen(const char *fs_name, unsigned int flags)
0073 {
0074 return syscall(__NR_fsopen, fs_name, flags);
0075 }
0076
0077 static inline int fsmount(int fsfd, unsigned int flags, unsigned int ms_flags)
0078 {
0079 return syscall(__NR_fsmount, fsfd, flags, ms_flags);
0080 }
0081
0082 static inline int fsconfig(int fsfd, unsigned int cmd,
0083 const char *key, const void *val, int aux)
0084 {
0085 return syscall(__NR_fsconfig, fsfd, cmd, key, val, aux);
0086 }
0087
0088 static inline int move_mount(int from_dfd, const char *from_pathname,
0089 int to_dfd, const char *to_pathname,
0090 unsigned int flags)
0091 {
0092 return syscall(__NR_move_mount,
0093 from_dfd, from_pathname,
0094 to_dfd, to_pathname, flags);
0095 }
0096
0097 #define E_fsconfig(fd, cmd, key, val, aux) \
0098 do { \
0099 if (fsconfig(fd, cmd, key, val, aux) == -1) \
0100 mount_error(fd, key ?: "create"); \
0101 } while (0)
0102
0103 int main(int argc, char *argv[])
0104 {
0105 int fsfd, mfd;
0106
0107
0108 fsfd = fsopen("afs", 0);
0109 if (fsfd == -1) {
0110 perror("fsopen");
0111 exit(1);
0112 }
0113
0114 E_fsconfig(fsfd, FSCONFIG_SET_STRING, "source", "#grand.central.org:root.cell.", 0);
0115 E_fsconfig(fsfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0);
0116
0117 mfd = fsmount(fsfd, 0, MOUNT_ATTR_RDONLY);
0118 if (mfd < 0)
0119 mount_error(fsfd, "fsmount");
0120 E(close(fsfd));
0121
0122 if (move_mount(mfd, "", AT_FDCWD, "/mnt", MOVE_MOUNT_F_EMPTY_PATH) < 0) {
0123 perror("move_mount");
0124 exit(1);
0125 }
0126
0127 E(close(mfd));
0128 exit(0);
0129 }