-
Notifications
You must be signed in to change notification settings - Fork 0
/
dirlist.c
78 lines (71 loc) · 1.26 KB
/
dirlist.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include "unionfs.h"
static uvlong
hash(char *s)
{
uvlong h;
h = 14695981039346656037ULL;
while(*s++){
h ^= *s;
h *= 1099511628211ULL;
}
return h;
}
static int
seen(Dirlist *dl, char *name)
{
usize probe, omseen, i;
char *n, **oseen;
probe = hash(name) % dl->mseen;
while((n = dl->seen[probe]) != nil){
if(strcmp(n, name) == 0)
return 1;
probe = (probe + 1) % dl->mseen;
}
dl->seen[probe] = name;
dl->nseen++;
if(dl->nseen > dl->mseen / 2){
oseen = dl->seen;
omseen = dl->mseen;
dl->mseen *= 2;
dl->nseen = 0;
dl->seen = emalloc(dl->mseen * sizeof(char*));
for(i = 0; i < omseen; i++)
if(oseen[i] != nil)
seen(dl, oseen[i]);
free(oseen);
}
return 0;
}
void
dirlistfree(Dirlist *dl)
{
if(dl == nil)
return;
free(dl->seen);
free(dl->dirs);
free(dl->all);
free(dl);
}
Dirlist*
dirlist(int fd)
{
long i, j;
Dir *d;
Dirlist *dl;
dl = emalloc(sizeof(Dirlist));
if((dl->nall = dirreadall(fd, &dl->all)) == -1){
free(dl);
return nil;
}
dl->dirs = emalloc((dl->nall + 1) * sizeof(Dir*));
dl->mseen = dl->nall;
dl->seen = emalloc(dl->mseen * sizeof(char*));
for(j = 0, i = 0; d = &dl->all[i], i < dl->nall; i++){
if(seen(dl, d->name))
continue;
dl->dirs[j++] = d;
}
dl->dirs[j] = nil;
dl->ndirs = j;
return dl;
}