2019-05-20 20:08:01 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2018-11-02 02:36:32 +03:00
/* fd-based mount test.
*
* Copyright ( C ) 2017 Red Hat , Inc . All Rights Reserved .
* Written by David Howells ( dhowells @ redhat . com )
*/
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <errno.h>
# include <fcntl.h>
# include <sys/prctl.h>
# include <sys/wait.h>
# include <linux/mount.h>
# include <linux/unistd.h>
# define E(x) do { if ((x) == -1) { perror(#x); exit(1); } } while(0)
static void check_messages ( int fd )
{
char buf [ 4096 ] ;
int err , n ;
err = errno ;
for ( ; ; ) {
n = read ( fd , buf , sizeof ( buf ) ) ;
if ( n < 0 )
break ;
n - = 2 ;
switch ( buf [ 0 ] ) {
case ' e ' :
fprintf ( stderr , " Error: %*.*s \n " , n , n , buf + 2 ) ;
break ;
case ' w ' :
fprintf ( stderr , " Warning: %*.*s \n " , n , n , buf + 2 ) ;
break ;
case ' i ' :
fprintf ( stderr , " Info: %*.*s \n " , n , n , buf + 2 ) ;
break ;
}
}
errno = err ;
}
static __attribute__ ( ( noreturn ) )
void mount_error ( int fd , const char * s )
{
check_messages ( fd ) ;
fprintf ( stderr , " %s: %m \n " , s ) ;
exit ( 1 ) ;
}
/* Hope -1 isn't a syscall */
# ifndef __NR_fsopen
# define __NR_fsopen -1
# endif
# ifndef __NR_fsmount
# define __NR_fsmount -1
# endif
# ifndef __NR_fsconfig
# define __NR_fsconfig -1
# endif
# ifndef __NR_move_mount
# define __NR_move_mount -1
# endif
static inline int fsopen ( const char * fs_name , unsigned int flags )
{
return syscall ( __NR_fsopen , fs_name , flags ) ;
}
static inline int fsmount ( int fsfd , unsigned int flags , unsigned int ms_flags )
{
return syscall ( __NR_fsmount , fsfd , flags , ms_flags ) ;
}
static inline int fsconfig ( int fsfd , unsigned int cmd ,
const char * key , const void * val , int aux )
{
return syscall ( __NR_fsconfig , fsfd , cmd , key , val , aux ) ;
}
static inline int move_mount ( int from_dfd , const char * from_pathname ,
int to_dfd , const char * to_pathname ,
unsigned int flags )
{
return syscall ( __NR_move_mount ,
from_dfd , from_pathname ,
to_dfd , to_pathname , flags ) ;
}
# define E_fsconfig(fd, cmd, key, val, aux) \
do { \
if ( fsconfig ( fd , cmd , key , val , aux ) = = - 1 ) \
mount_error ( fd , key ? : " create " ) ; \
} while ( 0 )
int main ( int argc , char * argv [ ] )
{
int fsfd , mfd ;
/* Mount a publically available AFS filesystem */
fsfd = fsopen ( " afs " , 0 ) ;
if ( fsfd = = - 1 ) {
perror ( " fsopen " ) ;
exit ( 1 ) ;
}
E_fsconfig ( fsfd , FSCONFIG_SET_STRING , " source " , " #grand.central.org:root.cell. " , 0 ) ;
E_fsconfig ( fsfd , FSCONFIG_CMD_CREATE , NULL , NULL , 0 ) ;
mfd = fsmount ( fsfd , 0 , MOUNT_ATTR_RDONLY ) ;
if ( mfd < 0 )
mount_error ( fsfd , " fsmount " ) ;
E ( close ( fsfd ) ) ;
if ( move_mount ( mfd , " " , AT_FDCWD , " /mnt " , MOVE_MOUNT_F_EMPTY_PATH ) < 0 ) {
perror ( " move_mount " ) ;
exit ( 1 ) ;
}
E ( close ( mfd ) ) ;
exit ( 0 ) ;
}