blob: c2b13882fec774a9d715bd9631c40bb6b07e219e [file] [log] [blame]
rsc46f79932005-01-04 21:22:40 +00001/* Mostly copied from Plan 9's libc. */
2
3#include <u.h>
4#include <libc.h>
5#include <fcall.h>
6#include <9pclient.h>
Russ Cox382ae732008-07-04 02:46:05 -04007#include "fsimpl.h"
rsc46f79932005-01-04 21:22:40 +00008
9static long
Russ Cox382ae732008-07-04 02:46:05 -040010dirpackage(uchar *buf, long ts, Dir **d, int dotu)
rsc46f79932005-01-04 21:22:40 +000011{
12 char *s;
13 long ss, i, n, nn, m;
14
15 *d = nil;
16 if(ts <= 0)
17 return 0;
18
19 /*
20 * first find number of all stats, check they look like stats, & size all associated strings
21 */
22 ss = 0;
23 n = 0;
24 for(i = 0; i < ts; i += m){
25 m = BIT16SZ + GBIT16(&buf[i]);
Russ Cox382ae732008-07-04 02:46:05 -040026 if(statchecku(&buf[i], m, dotu) < 0)
rsc46f79932005-01-04 21:22:40 +000027 break;
28 ss += m;
29 n++;
30 }
31
32 if(i != ts)
33 return -1;
34
35 *d = malloc(n * sizeof(Dir) + ss);
36 if(*d == nil)
37 return -1;
38
39 /*
40 * then convert all buffers
41 */
42 s = (char*)*d + n * sizeof(Dir);
43 nn = 0;
44 for(i = 0; i < ts; i += m){
45 m = BIT16SZ + GBIT16((uchar*)&buf[i]);
Russ Cox382ae732008-07-04 02:46:05 -040046 if(nn >= n || convM2Du(&buf[i], m, *d + nn, s, dotu) != m){
rsc46f79932005-01-04 21:22:40 +000047 free(*d);
48 *d = nil;
49 return -1;
50 }
51 nn++;
52 s += m;
53 }
54
55 return nn;
56}
57
58long
59fsdirread(CFid *fid, Dir **d)
60{
61 uchar *buf;
62 long ts;
63
64 buf = malloc(DIRMAX);
65 if(buf == nil)
66 return -1;
67 ts = fsread(fid, buf, DIRMAX);
68 if(ts >= 0)
Russ Cox382ae732008-07-04 02:46:05 -040069 ts = dirpackage(buf, ts, d, fid->fs->dotu);
rsc46f79932005-01-04 21:22:40 +000070 free(buf);
71 return ts;
72}
73
74long
75fsdirreadall(CFid *fid, Dir **d)
76{
77 uchar *buf, *nbuf;
78 long n, ts;
79
80 buf = nil;
81 ts = 0;
82 for(;;){
83 nbuf = realloc(buf, ts+DIRMAX);
84 if(nbuf == nil){
85 free(buf);
86 return -1;
87 }
88 buf = nbuf;
89 n = fsread(fid, buf+ts, DIRMAX);
90 if(n <= 0)
91 break;
92 ts += n;
93 }
rscf53117f2006-06-26 00:06:28 +000094 if(ts >= 0){
Russ Cox382ae732008-07-04 02:46:05 -040095 ts = dirpackage(buf, ts, d, fid->fs->dotu);
rscf53117f2006-06-26 00:06:28 +000096 if(ts < 0)
Russ Cox382ae732008-07-04 02:46:05 -040097 werrstr("malformed directory contents [dotu=%d]", fid->fs->dotu);
rscf53117f2006-06-26 00:06:28 +000098 }
rsc46f79932005-01-04 21:22:40 +000099 free(buf);
100 if(ts == 0 && n < 0)
101 return -1;
102 return ts;
103}