diff options
author | Erik Troan <ewt@redhat.com> | 2001-02-10 00:44:59 +0000 |
---|---|---|
committer | Erik Troan <ewt@redhat.com> | 2001-02-10 00:44:59 +0000 |
commit | 5cfc4859f52f9aec1a94919f251bf6032e3be534 (patch) | |
tree | 2abc3b38f8c8f9cfcfd0ba62a10d2d1c534ade44 /utils | |
parent | a2d421d00db7b203e6a4ce79475c3ae51a772684 (diff) | |
download | anaconda-5cfc4859f52f9aec1a94919f251bf6032e3be534.tar.gz anaconda-5cfc4859f52f9aec1a94919f251bf6032e3be534.tar.xz anaconda-5cfc4859f52f9aec1a94919f251bf6032e3be534.zip |
use two part header lists
Diffstat (limited to 'utils')
-rw-r--r-- | utils/Makefile | 4 | ||||
-rw-r--r-- | utils/genhdlist.c | 194 | ||||
-rw-r--r-- | utils/hash.c | 201 | ||||
-rw-r--r-- | utils/hash.h | 28 |
4 files changed, 417 insertions, 10 deletions
diff --git a/utils/Makefile b/utils/Makefile index 677ab31c7..c81cd8f4e 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -25,8 +25,8 @@ moddeps: moddeps.o ../isys/modutils/util/libutil.a \ ../isys/modutils/obj/libobj.a -lrpm -lrpmio -lbz2 -lz -lpopt -genhdlist: genhdlist.c - $(CC) $(LDFLAGS) $(CFLAGS) -o genhdlist genhdlist.c -lrpm -lrpmio \ +genhdlist: genhdlist.c hash.c + $(CC) $(LDFLAGS) $(CFLAGS) -o genhdlist genhdlist.c hash.c -lrpm -lrpmio \ -lbz2 -lz -lpopt -ldb-3.1 -ldb1 depends: diff --git a/utils/genhdlist.c b/utils/genhdlist.c index f7ec22428..898ce167d 100644 --- a/utils/genhdlist.c +++ b/utils/genhdlist.c @@ -11,14 +11,19 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <rpm/misc.h> #include <sys/stat.h> #include <sys/types.h> +#include <time.h> #include <unistd.h> +#include "hash.h" + #define FILENAME_TAG 1000000 #define FILESIZE_TAG 1000001 #define CDNUM_TAG 1000002 #define ORDER_TAG 1000003 +#define MATCHER_TAG 1000004 struct onePackageInfo { char * name; @@ -36,10 +41,18 @@ int pkgInfoCmp(const void * a, const void * b) { return strcmp(one->arch, two->arch); } +int tagsInList2[] = { + RPMTAG_FILESIZES, RPMTAG_FILEMODES, RPMTAG_FILEMD5S, RPMTAG_FILELINKTOS, + RPMTAG_FILEFLAGS, RPMTAG_FILELANGS, + RPMTAG_DIRNAMES, RPMTAG_DIRINDEXES, RPMTAG_BASENAMES, + -1 +}; + struct onePackageInfo * pkgList; int pkgListItems = 0; int pkgListAlloced = 0; char ** depOrder = NULL; +hashTable requireTable; /* mmmm... linear search */ int getOrder (char * fn) @@ -64,12 +77,82 @@ int getOrder (char * fn) return -1; } -int onePass(FD_t outfd, const char * dirName, int cdNum) { +int onePrePass(const char * dirName) { + struct dirent * ent; + DIR * dir; + char * subdir = alloca(strlen(dirName) + 20); + FD_t fd; + int rc; + Header h; + int isSource; + char ** requires; + int c; + + sprintf(subdir, "%s/RedHat/RPMS", dirName); + + dir = opendir(subdir); + if (!dir) { + fprintf(stderr,"error opening directory %s: %s\n", subdir, + strerror(errno)); + return 1; + } + + chdir(subdir); + + errno = 0; + ent = readdir(dir); + if (errno) { + perror("readdir"); + return 1; + } + + while (ent) { + int i = strlen (ent->d_name); + + if (i > 4 && strcasecmp (&ent->d_name [i - 4], ".rpm") == 0) { + fd = Fopen(ent->d_name, "r"); + + if (!fd) { + perror("open"); + exit(1); + } + + rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL); + + if (!rc) { + if (headerGetEntry(h, RPMTAG_REQUIRENAME, NULL, + (void **) &requires, &c)) { + while (c--) + if (*requires[c] == '/') + htAddToTable(requireTable, requires[c], "."); + } + + headerFree(h); + /* XXX free requires */ + } + + Fclose(fd); + } + + errno = 0; + ent = readdir(dir); + if (errno) { + perror("readdir"); + return 1; + } + } + + closedir(dir); + + return 0; +} + +int onePass(FD_t outfd, FD_t out2fd, const char * dirName, int cdNum) { FD_t fd; struct dirent * ent; char * subdir = alloca(strlen(dirName) + 20); int errno; - Header h, nh; + Header h, nh, h2; int isSource, rc; int_32 size; DIR * dir; @@ -77,7 +160,11 @@ int onePass(FD_t outfd, const char * dirName, int cdNum) { int_32 * fileSizes; int fileCount; int order = -1; - + char ** newFileList, ** fileNames; + uint_32 * newFileFlags, * fileFlags; + int newFileListCount; + int marker = time(NULL); /* good enough counter; we'll increment it */ + sprintf(subdir, "%s/RedHat/RPMS", dirName); dir = opendir(subdir); @@ -207,11 +294,79 @@ int onePass(FD_t outfd, const char * dirName, int cdNum) { &order, 1); } + expandFilelist(h); + newFileList = NULL; + if (headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, + (void **) &fileNames, &fileCount)) { + headerGetEntry(h, RPMTAG_FILEFLAGS, NULL, + (void **) &fileFlags, NULL); + + newFileList = malloc(sizeof(*newFileList) * fileCount); + newFileFlags = malloc(sizeof(*newFileList) * fileCount); + newFileListCount = 0; + + for (i = 0; i < fileCount; i++) { + if (htInTable(requireTable, fileNames[i], ".")) { + newFileList[newFileListCount] = strdup(fileNames[i]); + newFileFlags[newFileListCount] = fileFlags[i]; + newFileListCount++; + } + } + + if (!newFileListCount) { + free(newFileList); + free(newFileFlags); + newFileList = NULL; + } + + /* XXX free fileNames */ + } + compressFilelist(h); + + h2 = headerNew(); + for (i = 0; tagsInList2[i] > -1; i++) { + int_32 type, c; + void * p; + + if (headerGetEntry(h, tagsInList2[i], &type, &p, &c)) { + headerAddEntry(h2, tagsInList2[i], type, p, c); + headerRemoveEntry(h, tagsInList2[i]); + } + + /* XXX need to headerFreeData */ + } + + if (newFileList) { + headerAddEntry(h, RPMTAG_OLDFILENAMES, + RPM_STRING_ARRAY_TYPE, + newFileList, newFileListCount); + headerAddEntry(h, RPMTAG_FILEFLAGS, + RPM_INT32_TYPE, + &newFileFlags, newFileListCount); + + compressFilelist(h); + while (newFileListCount--) { + printf("f: %s\n", newFileList[newFileListCount]); + free(newFileList[newFileListCount]); + } + free(newFileList); + free(newFileFlags); + newFileList = NULL; + } + + headerAddEntry(h, MATCHER_TAG, RPM_INT32_TYPE, &marker, 1); + headerAddEntry(h2, MATCHER_TAG, RPM_INT32_TYPE, &marker, 1); + marker++; + nh = headerCopy (h); headerWrite(outfd, nh, HEADER_MAGIC_YES); + headerWrite(out2fd, h2, HEADER_MAGIC_YES); + headerFree(h); headerFree(nh); + headerFree(h2); } + Fclose(fd); } @@ -235,13 +390,14 @@ static void usage(void) { int main(int argc, const char ** argv) { char buf[300]; - FD_t outfd; + FD_t outfd, out2fd; int cdNum = -1; const char ** args; int doNumber = 0; int rc; int i; char * hdListFile = NULL; + char * hdListFile2 = NULL; char * depOrderFile = NULL; poptContext optCon; struct poptOption options[] = { @@ -302,6 +458,8 @@ int main(int argc, const char ** argv) { numpkgs++; } } + + requireTable = htNewTable(1000); if (!hdListFile) { strcpy(buf, args[0]); @@ -310,10 +468,21 @@ int main(int argc, const char ** argv) { } unlink(hdListFile); + + hdListFile2 = malloc(strlen(hdListFile) + 2); + sprintf(hdListFile2, "%s2", hdListFile); outfd = Fopen(hdListFile, "w"); if (!outfd) { - fprintf(stderr,"error creating file %s: %s\n", buf, strerror(errno)); + fprintf(stderr,"error creating file %s: %s\n", hdListFile, + strerror(errno)); + return 1; + } + + out2fd = Fopen(hdListFile2, "w"); + if (!out2fd) { + fprintf(stderr,"error creating file %s: %s\n", hdListFile2, + strerror(errno)); return 1; } @@ -325,14 +494,23 @@ int main(int argc, const char ** argv) { /* exit(1); */ /* } */ - while (args[0]) { - if (onePass(outfd, args[0], cdNum)) + i = 0; + while (args[i]) { + if (onePrePass(args[i])) + return 1; + i++; + } + + i = 0; + while (args[i]) { + if (onePass(outfd, out2fd, args[i], cdNum)) return 1; if (doNumber) cdNum++; - args++; + i++; } Fclose(outfd); + Fclose(out2fd); poptFreeContext(optCon); diff --git a/utils/hash.c b/utils/hash.c new file mode 100644 index 000000000..2bc6e0bf2 --- /dev/null +++ b/utils/hash.c @@ -0,0 +1,201 @@ +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> + +#include "hash.h" + +#define CHUNK 1 + +struct filePath { + char * dir; + char * base; +} ; + +struct bucket { + struct filePath * data; + int allocated; + int firstFree; /* as in data[firstFree] */ +}; + +struct hash_table { + int size; + int entries; + int overHead; + struct bucket *bucket; +}; + +struct hash_table *htNewTable(int size) +{ + struct hash_table *res; + int i = 0; + + res = malloc(sizeof(struct hash_table)); + res->bucket = malloc(sizeof(struct bucket) * size); + res->size = size; + res->entries = 0; + res->overHead = sizeof(struct bucket) * size + CHUNK * sizeof(char *); + + while (i < size) { + res->bucket[i].data = malloc(CHUNK * sizeof(*res->bucket[i].data)); + res->bucket[i].allocated = CHUNK; + res->bucket[i].firstFree = 0; + i++; + } + + return res; +} + +void htFreeHashTable(struct hash_table *ht) +{ + struct bucket * b; + int item; + + b = ht->bucket; + while (ht->size--) { + for (item = 0; item < b->firstFree; item++) { + free(b->data[item].dir); + free(b->data[item].base); + } + free(b->data); + b++; + } + free(ht->bucket); + free(ht); +} + +void htHashStats(struct hash_table *t) +{ + int i = 0; + int empty = 0; + + while (i < t->size) { + if (t->bucket[i].firstFree != 0) { + /*printf("Bucket %d used %d\n", i, t->bucket[i].firstFree);*/ + } else { + empty++; + } + i++; + } + + printf("Total Buckets : %d\n", t->size); + printf("Empty Buckets : %d\n", empty); + printf("Total Entries : %d\n", t->entries); + printf("Total Overhead: %d\n", t->overHead); + printf("Avergage Depth: %f\n", (double)t->entries / (double)t->size); +} + +static unsigned int htHashStrings(const char *s, const char *t) +{ + unsigned int res = 0; + + while (*s) + res = ((res<<1) + (int)(*(s++))); + while (*t) + res = ((res<<1) + (int)(*(t++))); + + return res; +} + +/* returns bucket # containing item, or -1 */ +static int in_table_aux(struct hash_table *t, int hash, const char * dir, + const char * base) +{ + int x; + + x = 0; + while (x < t->bucket[hash].firstFree) { + if (! strcmp(t->bucket[hash].data[x].dir, dir) && + ! strcmp(t->bucket[hash].data[x].base, base)) { + return x; + } + x++; + } + + return -1; +} + +int htInTable(struct hash_table *t, const char * dir, const char * base) +{ + int hash; + + hash = htHashStrings(dir, base) % t->size; + + if (in_table_aux(t, hash, dir, base) == -1) + return 0; + return 1; +} + +void htAddToTable(struct hash_table *t, const char * dir, const char * base) +{ + static int hash = 1; + + if (!dir || !base) + return; + + hash = htHashStrings(dir, base) % t->size; + if (in_table_aux(t, hash, dir, base) != -1) + return; + + if (t->bucket[hash].firstFree == t->bucket[hash].allocated) { + t->bucket[hash].allocated += CHUNK; + t->bucket[hash].data = + realloc(t->bucket[hash].data, + t->bucket[hash].allocated * sizeof(*(t->bucket->data))); + /*printf("Bucket %d grew to %d\n", hash, t->bucket[hash].allocated);*/ + t->overHead += sizeof(char *) * CHUNK; + } + /*printf("In bucket %d, item %d\n", hash, t->bucket[hash].firstFree);*/ + t->bucket[hash].data[t->bucket[hash].firstFree].dir = strdup(dir); + t->bucket[hash].data[t->bucket[hash].firstFree++].base = strdup(base); + t->entries++; +} + +void htRemoveFromTable(struct hash_table *t, const char * dir, + const char * base) { + int hash; + int item; + int last; + + hash = htHashStrings(dir, base) % t->size; + if ((item = in_table_aux(t, hash, dir, base)) == -1) { + return; + } + + free(t->bucket[hash].data[item].dir); + free(t->bucket[hash].data[item].base); + + last = --t->bucket[hash].firstFree; + t->bucket[hash].data[item] = t->bucket[hash].data[last]; +} + +int htNumEntries(struct hash_table *t) { + return t->entries; +} + +void htIterStart(htIterator * iter) { + iter->bucket = 0; + iter->item = -1; +} + +int htIterGetNext(struct hash_table * t, htIterator * iter, + const char ** dir, const char ** base) { + iter->item++; + + while (iter->bucket < t->size) { + if (iter->item < t->bucket[iter->bucket].firstFree) { + *dir = t->bucket[iter->bucket].data[iter->item].dir; + *base = t->bucket[iter->bucket].data[iter->item].base; + + return 1; + } + + iter->item++; + if (iter->item >= t->bucket[iter->bucket].firstFree) { + iter->bucket++; + iter->item = 0; + } + } + + return 0; +} diff --git a/utils/hash.h b/utils/hash.h new file mode 100644 index 000000000..954ad3bf4 --- /dev/null +++ b/utils/hash.h @@ -0,0 +1,28 @@ +#ifndef H_HASH +#define H_HASH + +struct hash_table; +typedef struct hash_table * hashTable; + +struct ht_iterator { + int bucket; + int item; +}; + +typedef struct ht_iterator htIterator; + +struct hash_table *htNewTable(int size); +void htFreeHashTable(struct hash_table *ht); +int htInTable(struct hash_table *t, const char * dir, const char * base); +void htAddToTable(struct hash_table *t, const char * dir, const char * base); +void htPrintHashStats(struct hash_table *t); +int htNumEntries(struct hash_table *t); +void htRemoveFromTable(struct hash_table *t, const char * dir, + const char * base); + +/* these use static storage */ +void htIterStart(htIterator * iter); +int htIterGetNext(struct hash_table * t, htIterator * iter, + const char ** dir, const char ** base); + +#endif |