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