xref: /plan9/sys/src/ape/lib/ap/plan9/dirread.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
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