From: Enrico Scholz Date: Wed, 23 Mar 2005 02:10:23 +0000 (+0000) Subject: added lots of new code... X-Git-Tag: IPSENTINEL_VERSION_0_12~27 X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=82bdb8b586cc5db5f016017f66e69d177d6baf9e;p=util-vserver.git added lots of new code... git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@1967 94cd875c-1c1d-0410-91d2-eb244daf1a30 --- diff --git a/util-vserver/src/vhashify-init.hc b/util-vserver/src/vhashify-init.hc index 57611b3..49aa7b1 100644 --- a/util-vserver/src/vhashify-init.hc +++ b/util-vserver/src/vhashify-init.hc @@ -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)); diff --git a/util-vserver/src/vhashify.c b/util-vserver/src/vhashify.c index 7d2b072..dc6d904 100644 --- a/util-vserver/src/vhashify.c +++ b/util-vserver/src/vhashify.c @@ -48,11 +48,14 @@ #define ENSC_WRAPPERS_UNISTD 1 #define ENSC_WRAPPERS_FCNTL 1 #define ENSC_WRAPPERS_DIRENT 1 +#define ENSC_WRAPPERS_IO 1 #include #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+10) 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");