2010-08-20 05:26:15 +04:00
/***
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 <errno.h>
2015-11-17 00:09:36 +03:00
# include <mntent.h>
2010-08-20 05:26:15 +04:00
# include <string.h>
2015-11-17 02:27:18 +03:00
# include <sys/prctl.h>
2010-08-20 05:26:15 +04:00
# include <sys/stat.h>
# include <sys/wait.h>
2015-11-17 00:09:36 +03:00
# include <unistd.h>
2010-08-20 05:26:15 +04:00
2015-10-26 20:44:13 +03:00
# include "exit-status.h"
2010-08-20 05:26:15 +04:00
# include "log.h"
2015-10-26 20:44:13 +03:00
# include "mount-setup.h"
# include "mount-util.h"
2012-05-07 23:36:12 +04:00
# include "path-util.h"
2015-11-17 02:27:18 +03:00
# include "process-util.h"
2015-05-29 21:14:11 +03:00
# include "signal-util.h"
2015-11-17 02:27:18 +03:00
# include "strv.h"
2015-10-26 20:44:13 +03:00
# include "util.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 [ ] ) {
2015-11-17 02:27:18 +03:00
_cleanup_hashmap_free_free_ Hashmap * pids = NULL ;
2013-10-04 06:13:55 +04:00
_cleanup_endmntent_ FILE * f = NULL ;
2010-08-20 05:26:15 +04:00
struct mntent * me ;
2015-11-17 02:27:18 +03:00
int r ;
2010-08-20 05:26:15 +04:00
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 ) {
2015-11-17 02:27:18 +03:00
if ( errno = = ENOENT ) {
r = 0 ;
goto finish ;
}
2012-04-22 17:33:43 +04:00
2015-11-17 02:27:18 +03:00
r = log_error_errno ( errno , " Failed to open /etc/fstab: %m " ) ;
goto finish ;
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 ) {
2015-11-17 02:27:18 +03:00
r = log_oom ( ) ;
2010-08-20 05:26:15 +04:00
goto finish ;
}
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 ) {
2015-11-17 02:27:18 +03:00
r = log_error_errno ( errno , " Failed to fork: %m " ) ;
goto finish ;
2010-08-20 05:26:15 +04:00
}
if ( pid = = 0 ) {
/* Child */
2015-06-01 00:55:55 +03:00
( void ) reset_all_signal_handlers ( ) ;
( void ) reset_signal_mask ( ) ;
2015-11-17 02:27:18 +03:00
( void ) prctl ( PR_SET_PDEATHSIG , SIGTERM ) ;
2015-06-01 00:55:55 +03:00
2015-11-17 02:27:18 +03:00
execv ( MOUNT_PATH , STRV_MAKE ( MOUNT_PATH , me - > mnt_dir , " -o " , " remount " ) ) ;
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 ) {
2015-11-17 02:27:18 +03:00
r = log_oom ( ) ;
goto finish ;
2011-12-30 18:34:21 +04:00
}
2015-11-17 02:00:32 +03:00
k = hashmap_put ( pids , PID_TO_PTR ( pid ) , s ) ;
2011-12-30 18:34:21 +04:00
if ( k < 0 ) {
2015-11-17 02:27:18 +03:00
free ( s ) ;
r = log_oom ( ) ;
goto finish ;
2010-08-20 05:26:15 +04:00
}
}
2015-11-17 02:27:18 +03:00
r = 0 ;
2010-08-20 05:26:15 +04:00
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 ;
2015-11-17 02:27:18 +03:00
r = log_error_errno ( errno , " waitid() failed: %m " ) ;
goto finish ;
2010-08-20 05:26:15 +04:00
}
2015-11-17 02:00:32 +03:00
s = hashmap_remove ( pids , PID_TO_PTR ( si . si_pid ) ) ;
2011-12-30 18:34:21 +04:00
if ( s ) {
2016-10-10 23:07:30 +03:00
if ( ! is_clean_exit ( si . si_code , si . si_status , EXIT_CLEAN_COMMAND , 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
2015-11-17 02:27:18 +03:00
r = - ENOEXEC ;
2010-08-20 05:26:15 +04:00
}
free ( s ) ;
}
}
finish :
2015-11-17 02:27:18 +03:00
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS ;
2010-08-20 05:26:15 +04:00
}