xref: /plan9/sys/src/libc/9sys/dirfstat.c (revision 413564c8148df26d3b2dbdb7785458853a6893f1)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <fcall.h>
43e12c5d1SDavid du Colombier 
59a747e4fSDavid du Colombier enum
63e12c5d1SDavid du Colombier {
79a747e4fSDavid du Colombier 	DIRSIZE	= STATFIXLEN + 16 * 4		/* enough for encoded stat buf + some reasonable strings */
89a747e4fSDavid du Colombier };
93e12c5d1SDavid du Colombier 
109a747e4fSDavid du Colombier Dir*
dirfstat(int fd)119a747e4fSDavid du Colombier dirfstat(int fd)
129a747e4fSDavid du Colombier {
139a747e4fSDavid du Colombier 	Dir *d;
149a747e4fSDavid du Colombier 	uchar *buf;
159a747e4fSDavid du Colombier 	int n, nd, i;
169a747e4fSDavid du Colombier 
179a747e4fSDavid du Colombier 	nd = DIRSIZE;
189a747e4fSDavid du Colombier 	for(i=0; i<2; i++){	/* should work by the second try */
19*413564c8SDavid du Colombier 		d = malloc(sizeof(Dir) + BIT16SZ + nd);
209a747e4fSDavid du Colombier 		if(d == nil)
219a747e4fSDavid du Colombier 			return nil;
229a747e4fSDavid du Colombier 		buf = (uchar*)&d[1];
23*413564c8SDavid du Colombier 		n = fstat(fd, buf, BIT16SZ+nd);
249a747e4fSDavid du Colombier 		if(n < BIT16SZ){
259a747e4fSDavid du Colombier 			free(d);
269a747e4fSDavid du Colombier 			return nil;
279a747e4fSDavid du Colombier 		}
28d9306527SDavid du Colombier 		nd = GBIT16(buf);	/* upper bound on size of Dir + strings */
299a747e4fSDavid du Colombier 		if(nd <= n){
309a747e4fSDavid du Colombier 			convM2D(buf, n, d, (char*)&d[1]);
319a747e4fSDavid du Colombier 			return d;
329a747e4fSDavid du Colombier 		}
33*413564c8SDavid du Colombier 		/* else sizeof(Dir)+BIT16SZ+nd is plenty */
349a747e4fSDavid du Colombier 		free(d);
359a747e4fSDavid du Colombier 	}
369a747e4fSDavid du Colombier 	return nil;
373e12c5d1SDavid du Colombier }
38