Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "lib.h"
2
#include <string.h>
3
#include <stdlib.h>
4
#include "sys9.h"
5
#include "dir.h"
6
 
7
static int
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
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
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
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
}