rsc | 46f7993 | 2005-01-04 21:22:40 +0000 | [diff] [blame] | 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> |
Russ Cox | 382ae73 | 2008-07-04 02:46:05 -0400 | [diff] [blame] | 7 | #include "fsimpl.h" |
rsc | 46f7993 | 2005-01-04 21:22:40 +0000 | [diff] [blame] | 8 | |
| 9 | static long |
Russ Cox | 382ae73 | 2008-07-04 02:46:05 -0400 | [diff] [blame] | 10 | dirpackage(uchar *buf, long ts, Dir **d, int dotu) |
rsc | 46f7993 | 2005-01-04 21:22:40 +0000 | [diff] [blame] | 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]); |
Russ Cox | 382ae73 | 2008-07-04 02:46:05 -0400 | [diff] [blame] | 26 | if(statchecku(&buf[i], m, dotu) < 0) |
rsc | 46f7993 | 2005-01-04 21:22:40 +0000 | [diff] [blame] | 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]); |
Russ Cox | 382ae73 | 2008-07-04 02:46:05 -0400 | [diff] [blame] | 46 | if(nn >= n || convM2Du(&buf[i], m, *d + nn, s, dotu) != m){ |
rsc | 46f7993 | 2005-01-04 21:22:40 +0000 | [diff] [blame] | 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) |
Russ Cox | 382ae73 | 2008-07-04 02:46:05 -0400 | [diff] [blame] | 69 | ts = dirpackage(buf, ts, d, fid->fs->dotu); |
rsc | 46f7993 | 2005-01-04 21:22:40 +0000 | [diff] [blame] | 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 | } |
rsc | f53117f | 2006-06-26 00:06:28 +0000 | [diff] [blame] | 94 | if(ts >= 0){ |
Russ Cox | 382ae73 | 2008-07-04 02:46:05 -0400 | [diff] [blame] | 95 | ts = dirpackage(buf, ts, d, fid->fs->dotu); |
rsc | f53117f | 2006-06-26 00:06:28 +0000 | [diff] [blame] | 96 | if(ts < 0) |
Russ Cox | 382ae73 | 2008-07-04 02:46:05 -0400 | [diff] [blame] | 97 | werrstr("malformed directory contents [dotu=%d]", fid->fs->dotu); |
rsc | f53117f | 2006-06-26 00:06:28 +0000 | [diff] [blame] | 98 | } |
rsc | 46f7993 | 2005-01-04 21:22:40 +0000 | [diff] [blame] | 99 | free(buf); |
| 100 | if(ts == 0 && n < 0) |
| 101 | return -1; |
| 102 | return ts; |
| 103 | } |