Dir* _dirfstat(int fd) { Dir *d; uint8_t *buf; int n, nd, i; nd = DIRSIZE; for(i=0; i<2; i++){ /* should work by the second try */ d = malloc(sizeof(Dir) + nd); if(d == nil) return nil; buf = (uint8_t*)&d[1]; n = _FSTAT(fd, buf, nd); if(n < BIT16SZ){ free(d); return nil; } nd = GBIT16(buf); /* size needed to store whole stat buffer */ if(nd <= n){ _convM2D(buf, n, d, (char*)&d[1]); return d; } /* else sizeof(Dir)+nd is plenty */ free(d); } return nil; }
static long dirpackage(uchar *buf, long ts, Dir **d) { char *s; long ss, i, n, nn, m; if(ts == 0){ *d = nil; return 0; } /* * first find number of all stats, check they look like stats, & size all associated strings */ ss = 0; n = 0; for(i = 0; i < ts; i += m){ m = BIT16SZ + GBIT16(&buf[i]); if(statcheck(&buf[i], m) < 0) break; ss += m; n++; } if(i != ts) return -1; *d = malloc(n * sizeof(Dir) + ss); if(*d == nil) return -1; /* * then convert all buffers */ s = (char*)*d + n * sizeof(Dir); nn = 0; for(i = 0; i < ts; i += m){ m = BIT16SZ + GBIT16((uchar*)&buf[i]); if(nn >= n || _convM2D(&buf[i], m, *d + nn, s) != m){ free(*d); return -1; } nn++; s += m; } return nn; }