1 #include <u.h>
2 #include <libc.h>
3 #include <fcall.h>
4
5 static
6 long
dirpackage(uchar * buf,long ts,Dir ** d)7 dirpackage(uchar *buf, long ts, Dir **d)
8 {
9 char *s;
10 long ss, i, n, nn, m;
11
12 *d = nil;
13 if(ts <= 0)
14 return 0;
15
16 /*
17 * first find number of all stats, check they look like stats, & size all associated strings
18 */
19 ss = 0;
20 n = 0;
21 for(i = 0; i < ts; i += m){
22 m = BIT16SZ + GBIT16(&buf[i]);
23 if(statcheck(&buf[i], m) < 0)
24 break;
25 ss += m;
26 n++;
27 }
28
29 if(i != ts)
30 return -1;
31
32 *d = malloc(n * sizeof(Dir) + ss);
33 if(*d == nil)
34 return -1;
35
36 /*
37 * then convert all buffers
38 */
39 s = (char*)*d + n * sizeof(Dir);
40 nn = 0;
41 for(i = 0; i < ts; i += m){
42 m = BIT16SZ + GBIT16((uchar*)&buf[i]);
43 if(nn >= n || convM2D(&buf[i], m, *d + nn, s) != m){
44 free(*d);
45 *d = nil;
46 return -1;
47 }
48 nn++;
49 s += m;
50 }
51
52 return nn;
53 }
54
55 long
dirread(int fd,Dir ** d)56 dirread(int fd, Dir **d)
57 {
58 uchar *buf;
59 long ts;
60
61 buf = malloc(DIRMAX);
62 if(buf == nil)
63 return -1;
64 ts = read(fd, buf, DIRMAX);
65 if(ts >= 0)
66 ts = dirpackage(buf, ts, d);
67 free(buf);
68 return ts;
69 }
70
71 long
dirreadall(int fd,Dir ** d)72 dirreadall(int fd, Dir **d)
73 {
74 uchar *buf, *nbuf;
75 long n, ts;
76
77 buf = nil;
78 ts = 0;
79 for(;;){
80 nbuf = realloc(buf, ts+DIRMAX);
81 if(nbuf == nil){
82 free(buf);
83 return -1;
84 }
85 buf = nbuf;
86 n = read(fd, buf+ts, DIRMAX);
87 if(n <= 0)
88 break;
89 ts += n;
90 }
91 if(ts >= 0)
92 ts = dirpackage(buf, ts, d);
93 free(buf);
94 if(ts == 0 && n < 0)
95 return -1;
96 return ts;
97 }
98