Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* fd-based mount test.
0003  *
0004  * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
0005  * Written by David Howells (dhowells@redhat.com)
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 /* Hope -1 isn't a syscall */
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     /* Mount a publically available AFS filesystem */
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 }