xref: /minix3/minix/lib/libfsdriver/dentry.c (revision 89c9de7d091f384bd4337bd6775fb15c93b8e8c6)
1*89c9de7dSDavid van Moolenbroek 
2*89c9de7dSDavid van Moolenbroek #include "fsdriver.h"
3*89c9de7dSDavid van Moolenbroek #include <sys/dirent.h>
4*89c9de7dSDavid van Moolenbroek 
5*89c9de7dSDavid van Moolenbroek /*
6*89c9de7dSDavid van Moolenbroek  * Initialize a directory entry listing.
7*89c9de7dSDavid van Moolenbroek  */
8*89c9de7dSDavid van Moolenbroek void
fsdriver_dentry_init(struct fsdriver_dentry * __restrict dentry,const struct fsdriver_data * __restrict data,size_t bytes,char * __restrict buf,size_t bufsize)9*89c9de7dSDavid van Moolenbroek fsdriver_dentry_init(struct fsdriver_dentry * __restrict dentry,
10*89c9de7dSDavid van Moolenbroek 	const struct fsdriver_data * __restrict data, size_t bytes,
11*89c9de7dSDavid van Moolenbroek 	char * __restrict buf, size_t bufsize)
12*89c9de7dSDavid van Moolenbroek {
13*89c9de7dSDavid van Moolenbroek 
14*89c9de7dSDavid van Moolenbroek 	dentry->data = data;
15*89c9de7dSDavid van Moolenbroek 	dentry->data_size = bytes;
16*89c9de7dSDavid van Moolenbroek 	dentry->data_off = 0;
17*89c9de7dSDavid van Moolenbroek 	dentry->buf = buf;
18*89c9de7dSDavid van Moolenbroek 	dentry->buf_size = bufsize;
19*89c9de7dSDavid van Moolenbroek 	dentry->buf_off = 0;
20*89c9de7dSDavid van Moolenbroek }
21*89c9de7dSDavid van Moolenbroek 
22*89c9de7dSDavid van Moolenbroek /*
23*89c9de7dSDavid van Moolenbroek  * Add an entry to a directory entry listing.  Return the entry size if it was
24*89c9de7dSDavid van Moolenbroek  * added, zero if no more entries could be added and the listing should stop,
25*89c9de7dSDavid van Moolenbroek  * or an error code in case of an error.
26*89c9de7dSDavid van Moolenbroek  */
27*89c9de7dSDavid van Moolenbroek ssize_t
fsdriver_dentry_add(struct fsdriver_dentry * __restrict dentry,ino_t ino_nr,const char * __restrict name,size_t namelen,unsigned int type)28*89c9de7dSDavid van Moolenbroek fsdriver_dentry_add(struct fsdriver_dentry * __restrict dentry, ino_t ino_nr,
29*89c9de7dSDavid van Moolenbroek 	const char * __restrict name, size_t namelen, unsigned int type)
30*89c9de7dSDavid van Moolenbroek {
31*89c9de7dSDavid van Moolenbroek 	struct dirent *dirent;
32*89c9de7dSDavid van Moolenbroek 	size_t len, used;
33*89c9de7dSDavid van Moolenbroek 	int r;
34*89c9de7dSDavid van Moolenbroek 
35*89c9de7dSDavid van Moolenbroek 	/* We could do several things here, but it should never happen.. */
36*89c9de7dSDavid van Moolenbroek 	if (namelen > MAXNAMLEN)
37*89c9de7dSDavid van Moolenbroek 		panic("fsdriver: directory entry name excessively long");
38*89c9de7dSDavid van Moolenbroek 
39*89c9de7dSDavid van Moolenbroek 	len = _DIRENT_RECLEN(dirent, namelen);
40*89c9de7dSDavid van Moolenbroek 
41*89c9de7dSDavid van Moolenbroek 	if (dentry->data_off + dentry->buf_off + len > dentry->data_size) {
42*89c9de7dSDavid van Moolenbroek 		if (dentry->data_off == 0 && dentry->buf_off == 0)
43*89c9de7dSDavid van Moolenbroek 			return EINVAL;
44*89c9de7dSDavid van Moolenbroek 
45*89c9de7dSDavid van Moolenbroek 		return 0;
46*89c9de7dSDavid van Moolenbroek 	}
47*89c9de7dSDavid van Moolenbroek 
48*89c9de7dSDavid van Moolenbroek 	if (dentry->buf_off + len > dentry->buf_size) {
49*89c9de7dSDavid van Moolenbroek 		if (dentry->buf_off == 0)
50*89c9de7dSDavid van Moolenbroek 			panic("fsdriver: getdents buffer too small");
51*89c9de7dSDavid van Moolenbroek 
52*89c9de7dSDavid van Moolenbroek 		if ((r = fsdriver_copyout(dentry->data, dentry->data_off,
53*89c9de7dSDavid van Moolenbroek 		    dentry->buf, dentry->buf_off)) != OK)
54*89c9de7dSDavid van Moolenbroek 			return r;
55*89c9de7dSDavid van Moolenbroek 
56*89c9de7dSDavid van Moolenbroek 		dentry->data_off += dentry->buf_off;
57*89c9de7dSDavid van Moolenbroek 		dentry->buf_off = 0;
58*89c9de7dSDavid van Moolenbroek 	}
59*89c9de7dSDavid van Moolenbroek 
60*89c9de7dSDavid van Moolenbroek 	dirent = (struct dirent *)&dentry->buf[dentry->buf_off];
61*89c9de7dSDavid van Moolenbroek 	dirent->d_fileno = ino_nr;
62*89c9de7dSDavid van Moolenbroek 	dirent->d_reclen = len;
63*89c9de7dSDavid van Moolenbroek 	dirent->d_namlen = namelen;
64*89c9de7dSDavid van Moolenbroek 	dirent->d_type = type;
65*89c9de7dSDavid van Moolenbroek 	memcpy(dirent->d_name, name, namelen);
66*89c9de7dSDavid van Moolenbroek 
67*89c9de7dSDavid van Moolenbroek 	/*
68*89c9de7dSDavid van Moolenbroek 	 * Null-terminate the name, and zero out any alignment bytes after it,
69*89c9de7dSDavid van Moolenbroek 	 * so as not to leak any data.
70*89c9de7dSDavid van Moolenbroek 	 */
71*89c9de7dSDavid van Moolenbroek 	used = _DIRENT_NAMEOFF(dirent) + namelen;
72*89c9de7dSDavid van Moolenbroek 	if (used >= len)
73*89c9de7dSDavid van Moolenbroek 		panic("fsdriver: inconsistency in dirent record");
74*89c9de7dSDavid van Moolenbroek 	memset(&dirent->d_name[namelen], 0, len - used);
75*89c9de7dSDavid van Moolenbroek 
76*89c9de7dSDavid van Moolenbroek 	dentry->buf_off += len;
77*89c9de7dSDavid van Moolenbroek 
78*89c9de7dSDavid van Moolenbroek 	return len;
79*89c9de7dSDavid van Moolenbroek }
80*89c9de7dSDavid van Moolenbroek 
81*89c9de7dSDavid van Moolenbroek /*
82*89c9de7dSDavid van Moolenbroek  * Finish a directory entry listing operation.  Return the total number of
83*89c9de7dSDavid van Moolenbroek  * bytes copied to the caller, or an error code in case of an error.
84*89c9de7dSDavid van Moolenbroek  */
85*89c9de7dSDavid van Moolenbroek ssize_t
fsdriver_dentry_finish(struct fsdriver_dentry * dentry)86*89c9de7dSDavid van Moolenbroek fsdriver_dentry_finish(struct fsdriver_dentry *dentry)
87*89c9de7dSDavid van Moolenbroek {
88*89c9de7dSDavid van Moolenbroek 	int r;
89*89c9de7dSDavid van Moolenbroek 
90*89c9de7dSDavid van Moolenbroek 	if (dentry->buf_off > 0) {
91*89c9de7dSDavid van Moolenbroek 		if ((r = fsdriver_copyout(dentry->data, dentry->data_off,
92*89c9de7dSDavid van Moolenbroek 		    dentry->buf, dentry->buf_off)) != OK)
93*89c9de7dSDavid van Moolenbroek 			return r;
94*89c9de7dSDavid van Moolenbroek 
95*89c9de7dSDavid van Moolenbroek 		dentry->data_off += dentry->buf_off;
96*89c9de7dSDavid van Moolenbroek 	}
97*89c9de7dSDavid van Moolenbroek 
98*89c9de7dSDavid van Moolenbroek 	return dentry->data_off;
99*89c9de7dSDavid van Moolenbroek }
100