--- db.c 2004-10-04 11:29:29.000000000 +0300 +++ db.c 2004-10-04 11:26:14.000000000 +0300 @@ -132,26 +132,63 @@ struct dirent *ent = NULL; struct stat sbuf; char path[PATH_MAX]; - char name[256]; + int path_len = 0; + char *name = NULL; char *ptr = NULL; int found = 0; + /* hash table for caching directory names */ + static strhash_t* htable = NULL; + + if (!htable) + htable = new_strhash(951); + + snprintf(path, PATH_MAX, "%s/", db->path); + path_len = strlen(path); + if(target != NULL) { /* search for a specific package (by name only) */ + + /* See if we have the path cached. */ + strcat(path, target); + if (strhash_isin(htable, path)) { + struct dirent* pkgdir; + pkginfo_t* pkg; + + /* db_read() wants 'struct dirent' so lets give it one. + * Actually it only uses the d_name field. */ + + MALLOC(pkgdir, sizeof(struct dirent)); + strcpy(pkgdir->d_name, strhash_get(htable, path)); + + pkg = db_read(db, pkgdir, inforeq); + free(pkgdir); + return pkg; + } + path[path_len] = '\0'; + + /* OK the entry was not in cache, so lets look for it manually. */ + rewinddir(db->dir); ent = readdir(db->dir); + while(!found && ent != NULL) { if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { ent = readdir(db->dir); continue; } - strncpy(name, ent->d_name, 255); + /* stat the entry, make sure it's a directory */ - snprintf(path, PATH_MAX, "%s/%s", db->path, name); + path[path_len] = '\0'; + strncat(path, ent->d_name, PATH_MAX - path_len); + if(stat(path, &sbuf) || !S_ISDIR(sbuf.st_mode)) { ent = readdir(db->dir); continue; } + + name = path + path_len; + /* truncate the string at the second-to-last hyphen, */ /* which will give us the package name */ if((ptr = rindex(name, '-'))) { @@ -177,8 +214,11 @@ if(ent == NULL) { return(NULL); } + /* stat the entry, make sure it's a directory */ - snprintf(path, PATH_MAX, "%s/%s", db->path, ent->d_name); + path[path_len] = '\0'; + strncat(path, ent->d_name, PATH_MAX - path_len); + if(!stat(path, &sbuf) && S_ISDIR(sbuf.st_mode)) { isdir = 1; } @@ -186,6 +226,25 @@ isdir = 0; continue; } + + name = path + path_len; + + if((ptr = rindex(name, '-'))) { + *ptr = '\0'; + } + if((ptr = rindex(name, '-'))) { + *ptr = '\0'; + } + + /* Add entries like: + * + * key: /var/lib/pacman/extra/xrally + * data: xrally-1.1.1-1 + */ + + if (!strhash_isin(htable, path)) { + strhash_add(htable, strdup(path), strdup(ent->d_name)); + } } } return(db_read(db, ent, inforeq)); --- strhash.h 2004-10-04 11:41:12.000000000 +0300 +++ strhash.h 2004-10-04 10:22:05.000000000 +0300 @@ -36,6 +36,7 @@ struct strhash_elmt_s { char *key; + char *data; strhash_elmt_t *next; }; @@ -54,8 +55,9 @@ strhash_t *new_strhash(size_t hsize); void free_strhash(strhash_t *hash); void clear_strhash(strhash_t *hash); -void strhash_add(strhash_t *hash, char *key); +void strhash_add(strhash_t *hash, char *key, char *data); int strhash_isin(strhash_t *hash, char* key); +char* strhash_get(strhash_t *hash, char* key); int strhash_collide_count(strhash_t *hash); unsigned long strhash_pjw(char *key); --- strhash.c 2004-10-04 11:41:12.000000000 +0300 +++ strhash.c 2004-10-04 10:23:37.000000000 +0300 @@ -39,7 +39,7 @@ strhash_add_list(strhash_t *hash, PMList* list) { for(; list; list = list->next) - strhash_add(hash, list->data); + strhash_add(hash, list->data, NULL); } strhash_t * @@ -102,13 +102,14 @@ } void -strhash_add(strhash_t *hash, char *key) +strhash_add(strhash_t *hash, char *key, char *data) { strhash_elmt_t *elmt; unsigned long hcode; MALLOC(elmt, sizeof (strhash_elmt_t)); elmt->key = key; + elmt->data = data; hcode = hash->hash(key) % hash->size; elmt->next = hash->htable[hcode]; @@ -135,6 +136,21 @@ return 0; } +char* +strhash_get(strhash_t *hash, char* key) +{ + strhash_elmt_t *elmt; + + elmt = hash->htable[hash->hash(key) % hash->size]; + for (; elmt; elmt = elmt->next) + { + if (!strcmp(key, elmt->key)) + return elmt->data; + } + + return NULL; +} + /* ** fast hash function samples */