#include #include #include #include #include #include #include #include #include #include #include "mstorage.h" #include #include #include #include mstorage_t idx; char* map; int compar(const void* a,const void* b) { int i; if ((i=strcmp(map+*(uint32*)a,map+*(uint32*)b))) return i; else return *(uint32*)b-*(uint32*)a; } int compari(const void* a,const void* b) { int i; if ((i=strcasecmp(map+*(uint32*)a,map+*(uint32*)b))) return i; else return *(uint32*)b-*(uint32*)a; } uint32 hash(const unsigned char* c,unsigned long keylen) { unsigned long h=0; unsigned long i; for (i=0; i3) { if (strchr(argv[3],'i')) ignorecase=1; if (strchr(argv[3],'f')) fastindex=1; if (strchr(argv[3],'h')) mode=HASHTABLE; if (strchr(argv[3],'u')) onlywithpassword=1; } if (mode!=HASHTABLE && onlywithpassword) die(111,"u only implemented with h\n"); if (onlywithpassword && strcmp(lookfor,"dn")) die(111,"u only works if attribute is dn\n"); if (onlywithpassword) lookfor="userPassword"; map=(char*)mmap_read(filename,&filelen); if (!map) diesys(111,"Could not open \"",filename,"\""); uint32_unpack(map,&magic); if (magic!=0xfefe1da9) die(111,"File format not recognized (invalid magic)!\n"); uint32_unpack(map+4,&attribute_count); uint32_unpack(map+2*4,&record_count); uint32_unpack(map+3*4,&indices_offset); uint32_unpack(map+4*4,&size_of_string_table); { unsigned int i; const char* x=map+5*4+size_of_string_table; wanted=casesensitive=dn=objectClass=0; for (i=0; i2; --j) { uint32_unpack(x,&k); if (k==wanted) { uint32_unpack(x+4,&k); mstorage_add(&idx,(char*)&k,4); if (fastindex) mstorage_add(&idx,(char*)&i,4); ++counted; } x+=8; } } } buffer_putulong(buffer_1,counted); buffer_putsflush(buffer_1," entries to be sorted..."); if (ignorecase) qsort(idx.root,counted,4*(fastindex+1),compari); else qsort(idx.root,counted,4*(fastindex+1),compar); buffer_putsflush(buffer_1," done.\n"); munmap(map,filelen); { int fd=open(filename,O_RDWR); if (fd<0) diesys(111,"Could not re-open database file read-write"); ftruncate(fd,filelen+3*4+counted*4*(fastindex+1)); map=mmap(0,filelen+(counted+3)*4*(fastindex+1),PROT_WRITE,MAP_SHARED,fd,0); if (map==(char*)-1) diesys(111,"Could not mmap database file read-write"); uint32_pack(map+casesensitive,ignorecase); uint32_pack(map+filelen,fastindex); uint32_pack(map+filelen+4,filelen+3*4+counted*4*(fastindex+1)); uint32_pack(map+filelen+8,wanted); { char* x=map+filelen+12; unsigned long i; for (i=0; i2; --j) { uint32_unpack(x,&k); if (k==wanted) ++counted; x+=8; } } } if (!counted) die(111,"attribute does not occur?!"); y=malloc(counted*sizeof(struct node)); if (!y) die(111,"out of memory"); x=map+5*4+size_of_string_table+attribute_count*8; for (cur=i=0; i2; --j) { uint32_unpack(x,&k); if (k==wanted) { if (onlywithpassword) { uint32_unpack(x-8,&k); y[cur].recnum=i; y[cur].hashcode=hashmapped(k,ignorecase); ++cur; } else { y[cur].recnum=i; y[cur].hashcode=hashmapped(k,ignorecase); ++cur; } } x+=8; } } } buffer_putulong(buffer_1,counted); buffer_putsflush(buffer_1," entries hashed; looking for hash table size with least collisions..."); i=counted; if (!(i&1)) ++i; maxtabsize=counted+counted/8; tab=malloc(maxtabsize*sizeof(struct htentry)); if (!tab) die(111,"out of memory"); if (maxtabsize > 100) { maxcoll=nmaxcoll=nmincoll=0; mincoll=-1; for (; i1) ++k; if (tab[l].count==2) ++chains; } if (k>maxcoll) { nmaxcoll=i; maxcoll=k; cmaxcoll=chains; } if (k1) indexsize+=(tab[j].count+1)*4; free(y); munmap(map,filelen); { int fd=open(filename,O_RDWR); char* dest,* x,* z; if (fd<0) diesys(111,"Could not re-open database file read-write"); ftruncate(fd,filelen+indexsize); map=mmap(0,filelen+indexsize,PROT_WRITE,MAP_SHARED,fd,0); if (map==(char*)-1) diesys(111,"Could not mmap database file read-write"); uint32_pack(map+casesensitive,ignorecase); dest=map+filelen; uint32_pack(dest,3); /* index type 3 == hash table */ uint32_pack(dest+4,filelen+indexsize); /* offset of next index */ if (onlywithpassword) uint32_pack(dest+2*4,dn); /* indexed attribute */ else uint32_pack(dest+2*4,wanted); /* indexed attribute */ uint32_pack(dest+3*4,maxtabsize); /* hash table size in uint32s */ x=dest+4*4; z=x+maxtabsize*4; // printf("hashtab starts at %lu, has %u entries, ends at %lu\n",x-map,maxtabsize,z-map); for (j=0; j1) { uint32 k; uint32_pack(x,filelen+(z-dest)); x+=4; uint32_pack(z,tab[j].count); z+=4; // printf("tab[%u] = [",j); for (k=0; k