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