2010-08-20 05:26:15 +04:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd .
Copyright 2010 Lennart Poettering
systemd is free software ; you can redistribute it and / or modify it
2012-04-12 02:20:58 +04:00
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation ; either version 2.1 of the License , or
2010-08-20 05:26:15 +04:00
( at your option ) any later version .
systemd is distributed in the hope that it will be useful , but
WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
2012-04-12 02:20:58 +04:00
Lesser General Public License for more details .
2010-08-20 05:26:15 +04:00
2012-04-12 02:20:58 +04:00
You should have received a copy of the GNU Lesser General Public License
2010-08-20 05:26:15 +04:00
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
# include <unistd.h>
# include <errno.h>
# include <string.h>
# include <sys/stat.h>
# include <sys/wait.h>
# include <mntent.h>
# include "log.h"
# include "util.h"
2012-05-07 23:36:12 +04:00
# include "path-util.h"
2015-05-29 21:14:11 +03:00
# include "signal-util.h"
2010-08-20 05:26:15 +04:00
# include "mount-setup.h"
2011-01-20 20:22:03 +03:00
# include "exit-status.h"
2010-08-20 05:26:15 +04:00
/* Goes through /etc/fstab and remounts all API file systems, applying
* options that are in / etc / fstab that systemd might not have
* respected */
int main ( int argc , char * argv [ ] ) {
2010-08-31 23:05:54 +04:00
int ret = EXIT_FAILURE ;
2013-10-04 06:13:55 +04:00
_cleanup_endmntent_ FILE * f = NULL ;
2010-08-20 05:26:15 +04:00
struct mntent * me ;
Hashmap * pids = NULL ;
if ( argc > 1 ) {
log_error ( " This program takes no argument. " ) ;
2010-08-31 23:05:54 +04:00
return EXIT_FAILURE ;
2010-08-20 05:26:15 +04:00
}
2012-01-12 08:09:06 +04:00
log_set_target ( LOG_TARGET_AUTO ) ;
2010-08-20 05:26:15 +04:00
log_parse_environment ( ) ;
log_open ( ) ;
2011-08-01 22:52:18 +04:00
umask ( 0022 ) ;
2011-12-30 18:34:21 +04:00
f = setmntent ( " /etc/fstab " , " r " ) ;
if ( ! f ) {
2013-10-04 06:13:55 +04:00
if ( errno = = ENOENT )
return EXIT_SUCCESS ;
2012-04-22 17:33:43 +04:00
2014-11-28 21:29:59 +03:00
log_error_errno ( errno , " Failed to open /etc/fstab: %m " ) ;
2013-10-04 06:13:55 +04:00
return EXIT_FAILURE ;
2010-08-20 05:26:15 +04:00
}
2014-08-13 03:00:18 +04:00
pids = hashmap_new ( NULL ) ;
2011-12-30 18:34:21 +04:00
if ( ! pids ) {
2010-08-20 05:26:15 +04:00
log_error ( " Failed to allocate set " ) ;
goto finish ;
}
2010-08-31 23:05:54 +04:00
ret = EXIT_SUCCESS ;
2010-08-20 05:26:15 +04:00
while ( ( me = getmntent ( f ) ) ) {
pid_t pid ;
int k ;
char * s ;
2012-06-29 18:14:01 +04:00
/* Remount the root fs, /usr and all API VFS */
2012-04-24 18:42:42 +04:00
if ( ! mount_point_is_api ( me - > mnt_dir ) & &
2012-06-29 18:14:01 +04:00
! path_equal ( me - > mnt_dir , " / " ) & &
! path_equal ( me - > mnt_dir , " /usr " ) )
2010-08-20 05:26:15 +04:00
continue ;
log_debug ( " Remounting %s " , me - > mnt_dir ) ;
2011-12-30 18:34:21 +04:00
pid = fork ( ) ;
if ( pid < 0 ) {
2014-11-28 21:29:59 +03:00
log_error_errno ( errno , " Failed to fork: %m " ) ;
2011-12-30 18:34:21 +04:00
ret = EXIT_FAILURE ;
2010-08-20 05:26:15 +04:00
continue ;
}
if ( pid = = 0 ) {
const char * arguments [ 5 ] ;
/* Child */
2015-05-13 16:43:04 +03:00
arguments [ 0 ] = MOUNT_PATH ;
2010-08-20 05:26:15 +04:00
arguments [ 1 ] = me - > mnt_dir ;
arguments [ 2 ] = " -o " ;
arguments [ 3 ] = " remount " ;
arguments [ 4 ] = NULL ;
2015-05-13 16:43:04 +03:00
execv ( MOUNT_PATH , ( char * * ) arguments ) ;
2010-08-20 05:26:15 +04:00
2015-05-13 16:43:04 +03:00
log_error_errno ( errno , " Failed to execute " MOUNT_PATH " : %m " ) ;
2010-08-31 23:05:54 +04:00
_exit ( EXIT_FAILURE ) ;
2010-08-20 05:26:15 +04:00
}
/* Parent */
s = strdup ( me - > mnt_dir ) ;
2011-12-30 18:34:21 +04:00
if ( ! s ) {
2012-07-26 01:55:59 +04:00
log_oom ( ) ;
2011-12-30 18:34:21 +04:00
ret = EXIT_FAILURE ;
continue ;
}
2010-08-20 05:26:15 +04:00
2011-12-30 18:34:21 +04:00
k = hashmap_put ( pids , UINT_TO_PTR ( pid ) , s ) ;
if ( k < 0 ) {
2014-11-28 15:19:16 +03:00
log_error_errno ( k , " Failed to add PID to set: %m " ) ;
2010-08-31 23:05:54 +04:00
ret = EXIT_FAILURE ;
2010-08-20 05:26:15 +04:00
continue ;
}
}
while ( ! hashmap_isempty ( pids ) ) {
2013-03-25 03:59:00 +04:00
siginfo_t si = { } ;
2010-08-20 05:26:15 +04:00
char * s ;
if ( waitid ( P_ALL , 0 , & si , WEXITED ) < 0 ) {
if ( errno = = EINTR )
continue ;
2014-11-28 21:29:59 +03:00
log_error_errno ( errno , " waitid() failed: %m " ) ;
2010-08-31 23:05:54 +04:00
ret = EXIT_FAILURE ;
2010-08-20 05:26:15 +04:00
break ;
}
2011-12-30 18:34:21 +04:00
s = hashmap_remove ( pids , UINT_TO_PTR ( si . si_pid ) ) ;
if ( s ) {
2012-08-13 15:58:01 +04:00
if ( ! is_clean_exit ( si . si_code , si . si_status , NULL ) ) {
2010-08-20 05:26:15 +04:00
if ( si . si_code = = CLD_EXITED )
2015-05-13 16:43:04 +03:00
log_error ( MOUNT_PATH " for %s exited with exit status %i. " , s , si . si_status ) ;
2010-08-20 05:26:15 +04:00
else
2015-05-13 16:43:04 +03:00
log_error ( MOUNT_PATH " for %s terminated by signal %s. " , s , signal_to_string ( si . si_status ) ) ;
2010-08-20 05:26:15 +04:00
2010-08-31 23:05:54 +04:00
ret = EXIT_FAILURE ;
2010-08-20 05:26:15 +04:00
}
free ( s ) ;
}
}
finish :
if ( pids )
hashmap_free_free ( pids ) ;
return ret ;
}