added lots of new code...
authorEnrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
Wed, 23 Mar 2005 02:10:23 +0000 (02:10 +0000)
committerEnrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
Wed, 23 Mar 2005 02:10:23 +0000 (02:10 +0000)
git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@1967 94cd875c-1c1d-0410-91d2-eb244daf1a30

util-vserver/src/vhashify-init.hc
util-vserver/src/vhashify.c

index 57611b3..49aa7b1 100644 (file)
@@ -91,6 +91,180 @@ initHashList(HashDirCollection *hash_vec, char const *hashdir)
   return res;
 }
 
+static bool
+initHashMethod(struct HashDirConfiguration *conf, char const *filename)
+{
+  int          fd = open(filename, O_RDONLY);
+  if (fd==-1 && conf->method==0)
+    conf->method = hashFunctionDefault();
+
+  if (fd==-1) {
+    assert(conf->method!=0);
+    if (conf->method==0)      return false;
+    if (global_args->dry_run) return true;     // do not create the file
+    
+    fd = Eopen(filename, O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW, 0644);
+    TEMP_FAILURE_RETRY(write(fd, conf->method->name, strlen(conf->method->name)));
+    TEMP_FAILURE_RETRY(write(fd, "\n", 1));
+  }
+  else {
+    off_t      s  = Elseek(fd, 0, SEEK_END);
+    char       buf[s + 1];
+    Elseek(fd, 0, SEEK_SET);
+
+    conf->method=0;
+
+    if (s>0 && read(fd, buf, s+1)==s) {
+      while (s>0 && (buf[s-1]=='\0' || buf[s-1]=='\n'))
+       --s;
+      buf[s] = '\0';
+
+      conf->method = hashFunctionFind(buf);
+      if (conf->method==0) {
+       WRITE_MSG(2, "Can not find hash-function '");
+       WRITE_STR(2, buf);
+       WRITE_MSG(2, "'\n");
+      }
+    }
+    else
+      WRITE_MSG(2, "Can not read configuration file for hash-method\n");
+  }
+
+  if (conf->method!=0 && conf->method->digestsize*8>HASH_MAXBITS) {
+    WRITE_MSG(2, "Wow... what an huge hash-function. I can not handle so much bits; giving up...\n");
+    conf->method=0;
+  }
+  
+  Eclose(fd);
+  return conf->method!=0;
+}
+
+static bool
+initHashBlocks(struct HashDirConfiguration *conf, char const *filename)
+{
+  int          fd = open(filename, O_RDONLY);
+
+  if (fd==-1) {
+    char               str[sizeof("all,start,middle,end,")] = { [0] = '\0' };
+
+    if (global_args->dry_run) return true;     // do not create the file
+    
+    fd = Eopen(filename, O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW, 0644);
+
+    if (conf->blocks== hshALL)    strcat(str, "all\n");
+    if (conf->blocks & hshSTART)  strcat(str, "start\n");
+    if (conf->blocks & hshMIDDLE) strcat(str, "middle\n");
+    if (conf->blocks & hshEND)    strcat(str, "end\n");
+
+    EwriteAll(fd, str, strlen(str));
+  }
+  else {
+    off_t      s  = Elseek(fd, 0, SEEK_END);
+    char       buf[s + 1];
+    Elseek(fd, 0, SEEK_SET);
+    
+    conf->blocks = hshINVALID;
+      
+    if (s>0 && read(fd, buf, s+1)==s) {
+      char     *tok = buf;
+      char     *sep = "\n,\t ";
+
+      buf[s]       = '\0';
+      conf->blocks = hshALL;
+
+      do {
+       char    *ptr = strsep(&tok, sep);
+
+       if (*ptr=='#') { sep = "\n"; continue; }
+       sep = "\n,\t ";
+       if (*ptr=='\0') continue;
+
+       if      (strcasecmp(ptr, "all")   ==0) conf->blocks  = hshALL;
+       else {
+         if (conf->blocks==hshINVALID) conf->blocks = 0;
+         
+         else if (strcasecmp(ptr, "start") ==0) conf->blocks |= hshSTART;
+         else if (strcasecmp(ptr, "middle")==0) conf->blocks |= hshMIDDLE;
+         else if (strcasecmp(ptr, "end")   ==0) conf->blocks |= hshEND;
+         else {
+           WRITE_MSG(2, "Invalid block descriptor '");
+           WRITE_STR(2, ptr);
+           WRITE_MSG(2, "'\n");
+           conf->blocks = hshINVALID;
+           tok = 0;
+         }
+       }
+      } while (tok!=0);
+    }
+    else
+      WRITE_MSG(2, "Can not read configuration file for hash-blocks\n");
+  }
+
+  Eclose(fd);
+  return conf->blocks!=hshINVALID;
+}
+
+static bool
+initHashBlockSize(struct HashDirConfiguration *conf, char const *filename)
+{
+  if (conf->blocks==hshALL) return true;
+  
+  int          fd = open(filename, O_RDONLY);
+  if (fd==-1) {
+    char               str[sizeof("0x") + sizeof(size_t)*3+2] = {
+      [0] = '0', [1] = 'x'
+    };
+    size_t             len = utilvserver_fmt_xuint(str+2, conf->blocksize);
+
+    if (global_args->dry_run) return true;     // do not create the file
+
+    fd = Eopen(filename, O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW, 0644);
+    EwriteAll(fd, str, len+2);
+  }
+  else {
+    off_t      s  = Elseek(fd, 0, SEEK_END);
+    char       buf[s + 1];
+    Elseek(fd, 0, SEEK_SET);
+
+    conf->blocksize = (size_t)(-1);
+
+    if (s>0 && read(fd, buf, s+1)==s) {
+      char     *errptr;
+      
+      while (s>0 && (buf[s-1]=='\0' || buf[s-1]=='\n'))
+       --s;
+      buf[s] = '\0';
+
+      conf->blocksize = strtol(buf, &errptr, 0);
+      if (errptr==buf || (*errptr!='\0' && *errptr!='\n')) {
+       WRITE_MSG(2, "Failed to parse blocksize '");
+       WRITE_STR(2, buf);
+       WRITE_MSG(2, "'\n");
+       conf->blocksize = (size_t)(-1);
+      }
+    }
+    else
+      WRITE_MSG(2, "Can not read configuration file for hash-blocksize\n");
+  }
+
+  Eclose(fd);
+  return conf->blocksize!=(size_t)(-1);
+}
+
+static bool
+initHashConf(struct HashDirConfiguration *conf, char const *hashdir)
+{
+  size_t               l = strlen(hashdir);
+  char                 tmp[l + MAX(MAX(sizeof("/method"), sizeof("/blocks")),
+                                   sizeof("/blocksize"))];
+
+  memcpy(tmp, hashdir, l);
+
+  return ((strcpy(tmp+l, "/method"),    initHashMethod   (conf, tmp)) &&
+         (strcpy(tmp+l, "/blocks"),    initHashBlocks   (conf, tmp)) &&
+         (strcpy(tmp+l, "/blocksize"), initHashBlockSize(conf, tmp)));
+}
+
 static char *
 searchHashdir(char const *lhs, char const *rhs)
 {
@@ -120,6 +294,11 @@ initModeManually(struct Arguments const UNUSED *args, int argc, char *argv[])
     exit(1);
   }
 
+  if (!initHashConf(&global_info.hash_conf, args->hash_dir)) {
+    WRITE_MSG(2, "failed to initialize hash-configuration\n");
+    exit(1);
+  }
+  
   global_info.hash_dirs_max_size = initHashList(&global_info.hash_dirs,
                                                args->hash_dir);
   MatchList_initManually(&global_info.dst_list, 0, strdup(argv[0]), argv[1]);
@@ -157,6 +336,11 @@ initModeVserver(struct Arguments const UNUSED *args, int argc, char *argv[])
     exit(1);
   }
 
+  if (!initHashConf(&global_info.hash_conf, hashdir)) {
+    WRITE_MSG(2, "failed to initialize hash-configuration\n");
+    exit(1);
+  }
+  
   global_info.hash_dirs_max_size = initHashList(&global_info.hash_dirs, hashdir);
 
   free(const_cast(char *)(hashdir));
index 7d2b072..dc6d904 100644 (file)
 #define ENSC_WRAPPERS_UNISTD    1
 #define ENSC_WRAPPERS_FCNTL     1
 #define ENSC_WRAPPERS_DIRENT    1
+#define ENSC_WRAPPERS_IO       1
 #include <wrappers.h>
 
 
 #define HASH_BLOCKSIZE         0x10000000u
 #define HASH_MINSIZE           0x10
+#define HASH_MAXBITS           256             // we have to take care about
+                                               // max filename-length...
 
 #if HASH_MINSIZE<=0
 #  error HASH_MINSIZE must be not '0'
@@ -82,13 +85,23 @@ CMDLINE_OPTIONS[] = {
   { 0,0,0,0 }
 };
 
-  // SHA1, grouped by 4 digits + hash-collision counter + 2* '/' + NULL
-typedef char                   HashPath[160/4 + (160/4/4) + sizeof(unsigned int)*2 + 3];
+  // hash digest grouped by 2 digits + hash-collision counter + 2* '/' + NULL
+typedef char                   HashPath[HASH_MAXBITS/4 + (HASH_MAXBITS/4/2) +
+                                        sizeof(unsigned int)*2 + 3];
+
+struct HashDirConfiguration
+{
+    hashFunction const                         *method;
+    enum { hshALL=0, hshSTART = 1, hshMIDDLE=2,
+          hshEND = 4, hshINVALID = -1 }        blocks;
+    size_t                                     blocksize;
+};
 
 struct WalkdownInfo
 {
     PathInfo                   state;
     struct MatchList           dst_list;
+    struct HashDirConfiguration        hash_conf;
     HashDirCollection          hash_dirs;
     size_t                     hash_dirs_max_size;
 
@@ -97,9 +110,14 @@ struct WalkdownInfo
 
 int                            wrapper_exit_code = 1;
 struct Arguments const         *global_args;
-struct WalkdownInfo            global_info;
 static struct SkipReason       skip_reason;
 
+struct WalkdownInfo            global_info = {
+  .hash_conf = { .method     = 0,
+                .blocks     = hshALL,
+                .blocksize  = 0x10000 }
+};
+
 #include "vhashify-init.hc"
 
 int Global_getVerbosity() {
@@ -241,9 +259,10 @@ convertDigest(HashPath d_path)
   for (size_t in=0;
        out+1<sizeof(HashPath)-(sizeof(unsigned int)*2 + 2) && in<d_size;
        ++in) {
-    if (in%2 == 0 && in>0) d_path[out++]='/';
-    d_path[out++] = HEX_DIGIT[digest[in] >>    4];
-    d_path[out++] = HEX_DIGIT[digest[in] &  0x0f];
+    if ((in+254)%(in<=2 ? 1 : 256) == 0 && in>0)
+      d_path[out++]='/';
+    d_path[out++]  = HEX_DIGIT[digest[in] >>    4];
+    d_path[out++]  = HEX_DIGIT[digest[in] &  0x0f];
   }
   d_path[out++] = '\0';
   
@@ -399,7 +418,7 @@ resolveCollisions(char *result, PathInfo const *root, HashPath d_path,
   char                 buf[sizeof(int)*2 + 1];
   size_t               len;
 
-  *ptr++             = '/';
+  *ptr++             = '-';
   *ptr               = '\0';
   ptr[sizeof(int)*2] = '\0';
 
@@ -627,11 +646,6 @@ int main(int argc, char *argv[])
 
   Vector_init(&global_info.hash_dirs, sizeof(struct HashDirInfo));
 
-  if (hashFunctionContextInit(&global_info.hash_context,
-                             hashFunctionDefault())==-1)
-    return EXIT_FAILURE;
-
-
   global_args = &args;
   while (1) {
     int                c = getopt_long(argc, argv, "+nv",
@@ -673,6 +687,12 @@ int main(int argc, char *argv[])
     default            :  assert(false); return EXIT_FAILURE;
   };
 
+  if (hashFunctionContextInit(&global_info.hash_context,
+                             global_info.hash_conf.method)==-1) {
+    WRITE_MSG(2, "Failed to initialize hash-context\n");
+    return EXIT_FAILURE;
+  }
+
   if (Global_getVerbosity()>=1)
     WRITE_MSG(1, "Starting to traverse directories...\n");