vshost-util-vserver

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

vhashify-init.hc (9279B)


      1 // $Id$    --*- c -*--
      2 
      3 // Copyright (C) 2005 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 #include "pathconfig.h"
     19 #include "lib_internal/util-dotfile.h"
     20 
     21 #include <sys/param.h>
     22 
     23 static UNUSED void
     24 freeHashList(HashDirCollection *hash_vec)
     25 {
     26   for (struct HashDirInfo *itm = Vector_begin(hash_vec);
     27        itm!=Vector_end(hash_vec);
     28        ++itm) {
     29     free(const_cast(char *)(itm->path.d));
     30   }
     31 
     32   Vector_free(hash_vec);
     33 }
     34 
     35 static size_t
     36 initHashList(HashDirCollection *hash_vec, char const *hashdir)
     37 {
     38   int		cur_dir = Eopen(".", O_RDONLY|O_DIRECTORY, 0);
     39   Echdir(hashdir);
     40   
     41   DIR		*d      = Eopendir(".");
     42   struct dirent	*ep;
     43   size_t	l   = strlen(hashdir);
     44   size_t	res = 0;
     45 
     46   while ((ep=readdir(d)) != 0) {
     47     struct stat		st;
     48 
     49     if (isDotfile(ep->d_name) ||
     50 	stat(ep->d_name, &st)==-1 || !S_ISDIR(st.st_mode))
     51       continue;
     52 
     53     if (HashDirInfo_findDevice(hash_vec, st.st_dev)!=0) {
     54       WRITE_MSG(2, "Duplicate hash-dir entry '");
     55       WRITE_STR(2, ep->d_name);
     56       WRITE_MSG(2, "' found\n");
     57       continue;
     58     }
     59 
     60     char		*full_path = Emalloc(l + strlen(ep->d_name) + 3);
     61     char		*ptr       = full_path + l;
     62 
     63     memcpy(full_path, hashdir, l);
     64     while (ptr>full_path && ptr[-1]=='/') --ptr;
     65     *ptr++ = '/';
     66     strcpy(ptr, ep->d_name);
     67     strcat(ptr, "/");	// append a trailing '/'
     68 
     69 
     70     struct HashDirInfo	tmp = {
     71       .device  = st.st_dev,
     72       .path    = { full_path, strlen(full_path) },
     73     };
     74 
     75     res = MAX(res, tmp.path.l);
     76     
     77     memcpy(Vector_pushback(hash_vec), &tmp, sizeof tmp);
     78   }
     79 
     80   if (Vector_count(hash_vec)==0) {
     81     WRITE_MSG(2, "Could not find a place for the hashified files at '");
     82     WRITE_STR(2, hashdir);
     83     WRITE_MSG(2, "'.\n");
     84     exit(wrapper_exit_code);
     85   }
     86 
     87   Eclosedir(d);
     88   Efchdir(cur_dir);
     89   Eclose(cur_dir);
     90 
     91   return res;
     92 }
     93 
     94 static bool
     95 initHashMethod(struct HashDirConfiguration *conf, char const *filename)
     96 {
     97   int		fd = open(filename, O_RDONLY);
     98   if (fd==-1 && conf->method==0)
     99     conf->method = ensc_crypto_hash_get_default();
    100 
    101   if (fd==-1) {
    102     char const	*hash_name;
    103     assert(conf->method!=0);
    104     if (conf->method==0)      return false;
    105     if (global_args->dry_run) return true;	// do not create the file
    106 
    107     fd = Eopen(filename, O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW, 0644);
    108 
    109     hash_name = ensc_crypto_hash_get_name(conf->method);
    110     TEMP_FAILURE_RETRY(write(fd, hash_name, strlen(hash_name)));
    111     TEMP_FAILURE_RETRY(write(fd, "\n", 1));
    112   }
    113   else {
    114     off_t	s  = Elseek(fd, 0, SEEK_END);
    115     char	buf[s + 1];
    116     Elseek(fd, 0, SEEK_SET);
    117 
    118     conf->method=0;
    119 
    120     if (s>0 && read(fd, buf, s+1)==s) {
    121       while (s>0 && (buf[s-1]=='\0' || buf[s-1]=='\n'))
    122 	--s;
    123       buf[s] = '\0';
    124 
    125       conf->method = ensc_crypto_hash_find(buf);
    126       if (conf->method==0) {
    127 	WRITE_MSG(2, "Can not find hash-function '");
    128 	WRITE_STR(2, buf);
    129 	WRITE_MSG(2, "'\n");
    130       }
    131     }
    132     else
    133       WRITE_MSG(2, "Can not read configuration file for hash-method\n");
    134   }
    135 
    136   if (conf->method!=0 && ensc_crypto_hash_get_digestsize(conf->method)*8>HASH_MAXBITS) {
    137     WRITE_MSG(2, "Wow... what an huge hash-function. I can not handle so much bits; giving up...\n");
    138     conf->method=0;
    139   }
    140   
    141   Eclose(fd);
    142   return conf->method!=0;
    143 }
    144 
    145 static bool
    146 initHashBlocks(struct HashDirConfiguration *conf, char const *filename)
    147 {
    148   int		fd = open(filename, O_RDONLY);
    149 
    150   if (fd==-1) {
    151     char		str[sizeof("all,start,middle,end,")] = { [0] = '\0' };
    152 
    153     if (global_args->dry_run) return true;	// do not create the file
    154     
    155     fd = Eopen(filename, O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW, 0644);
    156 
    157     if (conf->blocks== hshALL)    strcat(str, "all\n");
    158     if (conf->blocks & hshSTART)  strcat(str, "start\n");
    159     if (conf->blocks & hshMIDDLE) strcat(str, "middle\n");
    160     if (conf->blocks & hshEND)    strcat(str, "end\n");
    161 
    162     EwriteAll(fd, str, strlen(str));
    163   }
    164   else {
    165     off_t	s  = Elseek(fd, 0, SEEK_END);
    166     char	buf[s + 1];
    167     Elseek(fd, 0, SEEK_SET);
    168     
    169     conf->blocks = hshINVALID;
    170       
    171     if (s>0 && read(fd, buf, s+1)==s) {
    172       char	*tok = buf;
    173       char	*sep = "\n,\t ";
    174 
    175       buf[s]       = '\0';
    176       conf->blocks = hshALL;
    177 
    178       do {
    179 	char	*ptr = strsep(&tok, sep);
    180 
    181 	if (*ptr=='#') { sep = "\n"; continue; }
    182 	sep = "\n,\t ";
    183 	if (*ptr=='\0') continue;
    184 
    185 	if      (strcasecmp(ptr, "all")   ==0) conf->blocks  = hshALL;
    186 	else {
    187 	  if (conf->blocks==hshINVALID) conf->blocks = 0;
    188 	  
    189 	  else if (strcasecmp(ptr, "start") ==0) conf->blocks |= hshSTART;
    190 	  else if (strcasecmp(ptr, "middle")==0) conf->blocks |= hshMIDDLE;
    191 	  else if (strcasecmp(ptr, "end")   ==0) conf->blocks |= hshEND;
    192 	  else {
    193 	    WRITE_MSG(2, "Invalid block descriptor '");
    194 	    WRITE_STR(2, ptr);
    195 	    WRITE_MSG(2, "'\n");
    196 	    conf->blocks = hshINVALID;
    197 	    tok = 0;
    198 	  }
    199 	}
    200       } while (tok!=0);
    201     }
    202     else
    203       WRITE_MSG(2, "Can not read configuration file for hash-blocks\n");
    204   }
    205 
    206   Eclose(fd);
    207   return conf->blocks!=hshINVALID;
    208 }
    209 
    210 static bool
    211 initHashBlockSize(struct HashDirConfiguration *conf, char const *filename)
    212 {
    213   if (conf->blocks==hshALL) return true;
    214   
    215   int		fd = open(filename, O_RDONLY);
    216   if (fd==-1) {
    217     char		str[sizeof("0x") + sizeof(size_t)*3+2] = {
    218       [0] = '0', [1] = 'x'
    219     };
    220     size_t		len = utilvserver_fmt_xuint(str+2, conf->blocksize);
    221 
    222     if (global_args->dry_run) return true;	// do not create the file
    223 
    224     fd = Eopen(filename, O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW, 0644);
    225     EwriteAll(fd, str, len+2);
    226   }
    227   else {
    228     off_t	s  = Elseek(fd, 0, SEEK_END);
    229     char	buf[s + 1];
    230     Elseek(fd, 0, SEEK_SET);
    231 
    232     conf->blocksize = (size_t)(-1);
    233 
    234     if (s>0 && read(fd, buf, s+1)==s) {
    235       char	*errptr;
    236       
    237       while (s>0 && (buf[s-1]=='\0' || buf[s-1]=='\n'))
    238 	--s;
    239       buf[s] = '\0';
    240 
    241       conf->blocksize = strtol(buf, &errptr, 0);
    242       if (errptr==buf || (*errptr!='\0' && *errptr!='\n')) {
    243 	WRITE_MSG(2, "Failed to parse blocksize '");
    244 	WRITE_STR(2, buf);
    245 	WRITE_MSG(2, "'\n");
    246 	conf->blocksize = (size_t)(-1);
    247       }
    248     }
    249     else
    250       WRITE_MSG(2, "Can not read configuration file for hash-blocksize\n");
    251   }
    252 
    253   Eclose(fd);
    254   return conf->blocksize!=(size_t)(-1);
    255 }
    256 
    257 static bool
    258 initHashConf(struct HashDirConfiguration *conf, char const *hashdir)
    259 {
    260   size_t		l = strlen(hashdir);
    261   char			tmp[l + MAX(MAX(sizeof("/method"), sizeof("/blocks")),
    262 				    sizeof("/blocksize"))];
    263 
    264   memcpy(tmp, hashdir, l);
    265 
    266   return ((strcpy(tmp+l, "/method"),    initHashMethod   (conf, tmp)) &&
    267 	  (strcpy(tmp+l, "/blocks"),    initHashBlocks   (conf, tmp)) &&
    268 	  (strcpy(tmp+l, "/blocksize"), initHashBlockSize(conf, tmp)));
    269 }
    270 
    271 static char *
    272 searchHashdir(char const *lhs, char const *rhs)
    273 {
    274   size_t	l1  = strlen(lhs);
    275   size_t	l2  = rhs ? strlen(rhs) : 0;
    276   char *	res = Emalloc(l1 + l2 + 1);
    277   struct stat	st;
    278 
    279   strcpy(res, lhs);
    280   if (rhs) strcat(res, rhs);
    281 
    282   if (stat(res, &st)==-1 || !S_ISDIR(st.st_mode)) {
    283     free(res);
    284     res = 0;
    285   }
    286 
    287   return res;
    288 }
    289 
    290 static void
    291 initModeManually(struct Arguments const UNUSED *args, int argc, char *argv[])
    292 {
    293   assert(args->hash_dir!=0);
    294   
    295   if (argc<2) {
    296     WRITE_MSG(2, "No exclude list specified\n");
    297     exit(1);
    298   }
    299 
    300   if (!initHashConf(&global_info.hash_conf, args->hash_dir)) {
    301     WRITE_MSG(2, "failed to initialize hash-configuration\n");
    302     exit(1);
    303   }
    304   
    305   global_info.hash_dirs_max_size = initHashList(&global_info.hash_dirs,
    306 						args->hash_dir);
    307   MatchList_initManually(&global_info.dst_list, 0, strdup(argv[0]), argv[1]);
    308 }
    309 
    310 static void
    311 initModeVserver(struct Arguments const UNUSED *args, int argc, char *argv[])
    312 {
    313   char const				*hashdir   = args->hash_dir;
    314   struct MatchVserverInfo		vserver = {
    315     .name        = argv[0],
    316     .use_pkgmgmt = true
    317   };
    318 
    319   if (!MatchVserverInfo_init(&vserver)) {
    320     WRITE_MSG(2, "Failed to initialize unification for vserver\n");
    321     exit(1);
    322   }
    323 
    324   if (argc!=1) {
    325     WRITE_MSG(2, "More than one vserver is not supported\n");
    326     exit(1);
    327   }
    328 
    329   if (!MatchList_initByVserver(&global_info.dst_list, &vserver)) {
    330     WRITE_MSG(2, "unification not configured for this vserver\n");
    331     exit(1);
    332   }
    333 
    334   if (hashdir==0) hashdir = searchHashdir(vserver.appdir.d, "/hash");
    335   if (hashdir==0) hashdir = searchHashdir(CONFDIR "/.defaults/apps/vunify/hash", 0);
    336 
    337   if (hashdir==0) {
    338     WRITE_MSG(2, "no hash-directory configured for this vserver.\n");
    339     exit(1);
    340   }
    341 
    342   if (!initHashConf(&global_info.hash_conf, hashdir)) {
    343     WRITE_MSG(2, "failed to initialize hash-configuration\n");
    344     exit(1);
    345   }
    346   
    347   global_info.hash_dirs_max_size = initHashList(&global_info.hash_dirs, hashdir);
    348 
    349   free(const_cast(char *)(hashdir));
    350   MatchVserverInfo_free(&vserver);
    351 }
    352