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