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 } 120