vshost-util-vserver

Build script and sources for util-vserver.
git clone https://ccx.te2000.cz/git/vshost-util-vserver
Log | Files | Refs

fstool.c (7144B)


      1 // $Id$    --*- c -*--
      2 
      3 // Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
      4 //  
      5 // This program is free software; you can redistribute it and/or modify
      6 // it under the terms of the GNU General Public License as published by
      7 // the Free Software Foundation; version 2 of the License.
      8 //  
      9 // This program is distributed in the hope that it will be useful,
     10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 // GNU General Public License for more details.
     13 //  
     14 // You should have received a copy of the GNU General Public License
     15 // along with this program; if not, write to the Free Software
     16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     17 
     18 
     19 #ifdef HAVE_CONFIG_H
     20 #  include <config.h>
     21 #endif
     22 
     23 #include "fstool.h"
     24 #include "util.h"
     25 
     26 #include <lib/vserver.h>
     27 
     28 #include <getopt.h>
     29 #include <stdio.h>
     30 #include <stdlib.h>
     31 #include <unistd.h>
     32 #include <dirent.h>
     33 #include <errno.h>
     34 #include <fcntl.h>
     35 
     36 #define ENSC_WRAPPERS_DIRENT	1
     37 #define ENSC_WRAPPERS_FCNTL	1
     38 #define ENSC_WRAPPERS_UNISTD	1
     39 #include <wrappers.h>
     40 
     41 struct Arguments const *		global_args = 0;
     42 
     43 int wrapper_exit_code = 1;
     44 
     45 inline static bool
     46 isSpecialDir(char const *d)
     47 {
     48   return ( (d[0]=='.' && !global_args->do_display_dot) ||
     49 	   (d[0]=='.' && (d[1]=='\0' || (d[1]=='.' && d[2]=='\0'))) );
     50 }
     51 
     52 #define CONCAT_PATHS(LHS, LHS_LEN, RHS)					\
     53   size_t		l_rhs = strlen(RHS);				\
     54   char			new_path[(LHS_LEN) + l_rhs + sizeof("/")];	\
     55   memcpy(new_path, LHS, (LHS_LEN));					\
     56   memcpy(new_path+(LHS_LEN), "/", 1);					\
     57   memcpy(new_path+(LHS_LEN)+1, RHS, l_rhs);				\
     58   new_path[(LHS_LEN)+1+l_rhs] = '\0';
     59 
     60 static uint64_t
     61 iterateFilesystem(char const *path)
     62 {
     63   bool			do_again = false;
     64   size_t		path_len = strlen(path);
     65   uint64_t		err = 0;
     66   struct stat		cur_st;
     67   DIR *			dir = opendir(".");
     68 
     69   if (dir==0) {
     70     perror("opendir()");
     71     return 1;
     72   }
     73 
     74   // show current directory entry first
     75   if (lstat(".", &cur_st)==-1) perror("lstat()");
     76   else err += handleFile(".", path) ? 0 : 1;
     77 
     78   // strip trailing '/'
     79   while (path_len>0 && path[path_len-1]=='/') --path_len;
     80 
     81   // process regular files before directories
     82   for (;;) {
     83     struct dirent	*ent = Ereaddir(dir);
     84     struct stat		st;
     85     
     86     if (ent==0) break;
     87     if (isSpecialDir(ent->d_name)) continue;
     88 
     89     if (lstat(ent->d_name, &st)==-1) {
     90       perror("lstat()");
     91       ++err;
     92       continue;
     93     }
     94 
     95     if (S_ISDIR(st.st_mode) && global_args->do_recurse) {
     96       do_again = true;
     97       continue;
     98     }
     99     
    100     {
    101       CONCAT_PATHS(path, path_len, ent->d_name);
    102       err += handleFile(ent->d_name, new_path) ? 0 : 1;
    103     }
    104   }
    105 
    106   if (do_again) {
    107     int		cur_dir = Eopen(".", O_RDONLY, 0);
    108     rewinddir(dir);
    109 
    110     for (;;) {
    111       struct dirent	*ent = Ereaddir(dir);
    112       struct stat	st;
    113     
    114       if (ent==0) break;
    115       if (isSpecialDir(ent->d_name)) continue;
    116       
    117       if (lstat(ent->d_name, &st)==-1) {
    118 	perror("lstat()");
    119 	++err;
    120 	continue;
    121       }
    122 
    123       if (!S_ISDIR(st.st_mode) ||
    124 	  (global_args->local_fs && st.st_dev!=cur_st.st_dev))
    125 	continue;
    126 
    127       if (safeChdir(ent->d_name, &st)==-1) {
    128 	perror("chdir()");
    129 	++err;
    130 	continue;
    131       }
    132       
    133       {
    134 	CONCAT_PATHS(path, path_len, ent->d_name);
    135 	err += iterateFilesystem(new_path);
    136       }
    137       Efchdir(cur_dir);
    138     }
    139     Eclose(cur_dir);
    140   }
    141 
    142   Eclosedir(dir);
    143 
    144   return err;
    145 }
    146 #undef CONCAT_PATHS
    147 
    148 static uint64_t
    149 processFile(char const *path)
    150 {
    151   struct stat		st;
    152 
    153   if (lstat(path, &st)==-1) {
    154     perror("lstat()");
    155     return 1;
    156   }
    157 
    158   if (S_ISDIR(st.st_mode) && !global_args->do_display_dir) {
    159     int		cur_dir = Eopen(".", O_RDONLY, 0);
    160     uint64_t	ret;
    161     Echdir(path);
    162     ret = iterateFilesystem(path);
    163     Efchdir(cur_dir);
    164     Eclose(cur_dir);
    165     return ret;
    166   }
    167   else
    168     return handleFile(path, path) ? 0 : 1;
    169 }
    170 
    171 int main(int argc, char *argv[])
    172 {
    173   uint64_t		err_cnt = 0;
    174   int			i;
    175   struct Arguments	args = {
    176     .do_recurse		=  false,
    177     .do_display_dot	=  false,
    178     .do_display_dir 	=  false,
    179     .do_mapping		=  true,
    180     .ctx		=  VC_NOCTX,
    181     .is_legacy          =  false,
    182     .do_set             =  false,
    183     .do_unset           =  false,
    184     .local_fs		=  false,
    185     .set_mask           =  0,
    186     .del_mask           =  0,
    187     .no_unified		=  false,
    188   };
    189 
    190   global_args = &args;
    191   while (1) {
    192     int		c = getopt_long(argc, argv, CMDLINE_OPTIONS_SHORT,
    193 				CMDLINE_OPTIONS, 0);
    194     long 	flags;
    195     char	*endptr;
    196     if (c==-1) break;
    197 
    198     switch (c) {
    199       case CMD_HELP		:  showHelp(1, argv[0], 0);
    200       case CMD_VERSION		:  showVersion();
    201       case CMD_IMMU		:  args.set_mask |= VC_IATTR_IMMUTABLE; /*@fallthrough@*/
    202       case CMD_IMMUX		:  args.set_mask |= VC_IATTR_IUNLINK;	break;
    203       case CMD_IMMUTABLE	:  args.set_mask |= VC_IATTR_IMMUTABLE;	break;
    204       case CMD_ADMIN		:  args.set_mask |= VC_IATTR_ADMIN;	break;
    205       case CMD_WATCH		:  args.set_mask |= VC_IATTR_WATCH;	break;
    206       case CMD_HIDE		:  args.set_mask |= VC_IATTR_HIDE;	break;
    207       case CMD_BARRIER		:  args.set_mask |= VC_IATTR_BARRIER;	break;
    208       case CMD_WRITE		:  args.set_mask |= VC_IATTR_WRITE;	break;
    209       case CMD_COW		:  args.set_mask |= VC_IATTR_COW;	break;
    210       case CMD_UNSET_IMMU	:  args.del_mask |= VC_IATTR_IMMUTABLE; /*@fallthrough@*/
    211       case CMD_UNSET_IMMUX	:  args.del_mask |= VC_IATTR_IUNLINK;	break;
    212       case CMD_UNSET_IMMUTABLE	:  args.del_mask |= VC_IATTR_IMMUTABLE;	break;
    213       case CMD_UNSET_ADMIN	:  args.del_mask |= VC_IATTR_ADMIN;	break;
    214       case CMD_UNSET_WATCH	:  args.del_mask |= VC_IATTR_WATCH;	break;
    215       case CMD_UNSET_HIDE	:  args.del_mask |= VC_IATTR_HIDE;	break;
    216       case CMD_UNSET_BARRIER	:  args.del_mask |= VC_IATTR_BARRIER;	break;
    217       case CMD_UNSET_WRITE	:  args.del_mask |= VC_IATTR_WRITE;	break;
    218       case CMD_UNSET_COW	:  args.del_mask |= VC_IATTR_COW;	break;
    219       case CMD_FLAGS		:
    220       case CMD_UNSET_FLAGS	:
    221 	flags = strtoul(optarg, &endptr, 0);
    222 	if ((flags == 0 && errno != 0) || *endptr != '\0') {
    223 	  WRITE_MSG(2, "Invalid flags argument: '");
    224 	  WRITE_STR(2, optarg);
    225 	  WRITE_MSG(2, "'; try '--help' for more information\n");
    226 	  return EXIT_FAILURE;
    227 	}
    228 	if (c == CMD_FLAGS)
    229 	  args.set_mask |= flags;
    230 	else
    231 	  args.del_mask |= flags;
    232         break;
    233       case 'R'			:  args.do_recurse     = true;		break;
    234       case 'a'			:  args.do_display_dot = true;		break;
    235       case 'd'			:  args.do_display_dir = true;		break;
    236       case 'n'			:  args.do_mapping     = false;		break;
    237       case 's'			:  args.do_set         = true;		break;
    238       case 'u'			:  args.do_unset       = true;		break;
    239       case 'c'			:  args.ctx_str        = optarg;	break;
    240       case 'x'			:  args.local_fs       = true;		break;
    241       case 'U'			:  args.no_unified     = true;		break;
    242       default		:
    243 	WRITE_MSG(2, "Try '");
    244 	WRITE_STR(2, argv[0]);
    245 	WRITE_MSG(2, " --help' for more information.\n");
    246 	return EXIT_FAILURE;
    247 	break;
    248     }
    249   }
    250 
    251   fixupParams(&args, argc);
    252 
    253   if (optind==argc)
    254     err_cnt  = processFile(".");
    255   else for (i=optind; i<argc; ++i)
    256     err_cnt += processFile(argv[i]);
    257 
    258   return err_cnt>0 ? EXIT_FAILURE : EXIT_SUCCESS;
    259 }