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