dirread.c (1545B)
1 /* Mostly copied from Plan 9's libc. */ 2 3 #include <u.h> 4 #include <libc.h> 5 #include <fcall.h> 6 #include <9pclient.h> 7 #include "fsimpl.h" 8 9 static long 10 dirpackage(uchar *buf, long ts, Dir **d) 11 { 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]); 26 if(statcheck(&buf[i], m) < 0) 27 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]); 46 if(nn >= n || convM2D(&buf[i], m, *d + nn, s) != m){ 47 free(*d); 48 *d = nil; 49 return -1; 50 } 51 nn++; 52 s += m; 53 } 54 55 return nn; 56 } 57 58 long 59 fsdirread(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) 69 ts = dirpackage(buf, ts, d); 70 free(buf); 71 return ts; 72 } 73 74 long 75 fsdirreadall(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 } 94 if(ts >= 0){ 95 ts = dirpackage(buf, ts, d); 96 if(ts < 0) 97 werrstr("malformed directory contents"); 98 } 99 free(buf); 100 if(ts == 0 && n < 0) 101 return -1; 102 return ts; 103 }