1*ba736c79SDavid van Moolenbroek /* Created (MFS based):
2*ba736c79SDavid van Moolenbroek * February 2010 (Evgeniy Ivanov)
3*ba736c79SDavid van Moolenbroek */
4*ba736c79SDavid van Moolenbroek
5*ba736c79SDavid van Moolenbroek #include "fs.h"
6*ba736c79SDavid van Moolenbroek #include <stddef.h>
7*ba736c79SDavid van Moolenbroek #include <dirent.h>
8*ba736c79SDavid van Moolenbroek #include <sys/param.h>
9*ba736c79SDavid van Moolenbroek
10*ba736c79SDavid van Moolenbroek
11*ba736c79SDavid van Moolenbroek #define GETDENTS_BUFSIZ 4096
12*ba736c79SDavid van Moolenbroek static char getdents_buf[GETDENTS_BUFSIZ];
13*ba736c79SDavid van Moolenbroek
14*ba736c79SDavid van Moolenbroek #define RW_BUFSIZ (128 * 1024)
15*ba736c79SDavid van Moolenbroek static char rw_buf[RW_BUFSIZ];
16*ba736c79SDavid van Moolenbroek
17*ba736c79SDavid van Moolenbroek
18*ba736c79SDavid van Moolenbroek /*===========================================================================*
19*ba736c79SDavid van Moolenbroek * fs_read *
20*ba736c79SDavid van Moolenbroek *===========================================================================*/
fs_read(ino_t ino_nr,struct fsdriver_data * data,size_t bytes,off_t pos,int call)21*ba736c79SDavid van Moolenbroek ssize_t fs_read(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
22*ba736c79SDavid van Moolenbroek off_t pos, int call)
23*ba736c79SDavid van Moolenbroek {
24*ba736c79SDavid van Moolenbroek int r;
25*ba736c79SDavid van Moolenbroek size_t bytes_left, bytes_done;
26*ba736c79SDavid van Moolenbroek struct puffs_node *pn;
27*ba736c79SDavid van Moolenbroek PUFFS_MAKECRED(pcr, &global_kcred);
28*ba736c79SDavid van Moolenbroek
29*ba736c79SDavid van Moolenbroek if ((pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) {
30*ba736c79SDavid van Moolenbroek lpuffs_debug("walk failed...\n");
31*ba736c79SDavid van Moolenbroek return(EINVAL);
32*ba736c79SDavid van Moolenbroek }
33*ba736c79SDavid van Moolenbroek
34*ba736c79SDavid van Moolenbroek if (bytes > sizeof(rw_buf))
35*ba736c79SDavid van Moolenbroek bytes = sizeof(rw_buf);
36*ba736c79SDavid van Moolenbroek bytes_left = bytes;
37*ba736c79SDavid van Moolenbroek
38*ba736c79SDavid van Moolenbroek if (global_pu->pu_ops.puffs_node_read == NULL)
39*ba736c79SDavid van Moolenbroek return(EINVAL);
40*ba736c79SDavid van Moolenbroek
41*ba736c79SDavid van Moolenbroek r = global_pu->pu_ops.puffs_node_read(global_pu, pn, (uint8_t *)rw_buf,
42*ba736c79SDavid van Moolenbroek pos, &bytes_left, pcr, 0);
43*ba736c79SDavid van Moolenbroek if (r) {
44*ba736c79SDavid van Moolenbroek lpuffs_debug("puffs_node_read failed\n");
45*ba736c79SDavid van Moolenbroek return(EINVAL);
46*ba736c79SDavid van Moolenbroek }
47*ba736c79SDavid van Moolenbroek
48*ba736c79SDavid van Moolenbroek bytes_done = bytes - bytes_left;
49*ba736c79SDavid van Moolenbroek
50*ba736c79SDavid van Moolenbroek if (bytes_done > 0) {
51*ba736c79SDavid van Moolenbroek if ((r = fsdriver_copyout(data, 0, rw_buf, bytes_done)) != OK)
52*ba736c79SDavid van Moolenbroek return r;
53*ba736c79SDavid van Moolenbroek update_timens(pn, ATIME, NULL);
54*ba736c79SDavid van Moolenbroek }
55*ba736c79SDavid van Moolenbroek
56*ba736c79SDavid van Moolenbroek return (ssize_t)bytes_done;
57*ba736c79SDavid van Moolenbroek }
58*ba736c79SDavid van Moolenbroek
59*ba736c79SDavid van Moolenbroek
60*ba736c79SDavid van Moolenbroek /*===========================================================================*
61*ba736c79SDavid van Moolenbroek * fs_write *
62*ba736c79SDavid van Moolenbroek *===========================================================================*/
fs_write(ino_t ino_nr,struct fsdriver_data * data,size_t bytes,off_t pos,int call)63*ba736c79SDavid van Moolenbroek ssize_t fs_write(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
64*ba736c79SDavid van Moolenbroek off_t pos, int call)
65*ba736c79SDavid van Moolenbroek {
66*ba736c79SDavid van Moolenbroek int r;
67*ba736c79SDavid van Moolenbroek size_t bytes_left;
68*ba736c79SDavid van Moolenbroek struct puffs_node *pn;
69*ba736c79SDavid van Moolenbroek struct vattr va;
70*ba736c79SDavid van Moolenbroek struct timespec cur_time;
71*ba736c79SDavid van Moolenbroek PUFFS_MAKECRED(pcr, &global_kcred);
72*ba736c79SDavid van Moolenbroek
73*ba736c79SDavid van Moolenbroek if ((pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) {
74*ba736c79SDavid van Moolenbroek lpuffs_debug("walk failed...\n");
75*ba736c79SDavid van Moolenbroek return(EINVAL);
76*ba736c79SDavid van Moolenbroek }
77*ba736c79SDavid van Moolenbroek
78*ba736c79SDavid van Moolenbroek if (bytes > sizeof(rw_buf))
79*ba736c79SDavid van Moolenbroek bytes = sizeof(rw_buf);
80*ba736c79SDavid van Moolenbroek bytes_left = bytes;
81*ba736c79SDavid van Moolenbroek
82*ba736c79SDavid van Moolenbroek /* At first try to change vattr */
83*ba736c79SDavid van Moolenbroek if (global_pu->pu_ops.puffs_node_setattr == NULL)
84*ba736c79SDavid van Moolenbroek return(EINVAL);
85*ba736c79SDavid van Moolenbroek
86*ba736c79SDavid van Moolenbroek (void)clock_time(&cur_time);
87*ba736c79SDavid van Moolenbroek
88*ba736c79SDavid van Moolenbroek puffs_vattr_null(&va);
89*ba736c79SDavid van Moolenbroek if ((u_quad_t)(pos + bytes_left) > pn->pn_va.va_size)
90*ba736c79SDavid van Moolenbroek va.va_size = bytes_left + pos;
91*ba736c79SDavid van Moolenbroek va.va_ctime = va.va_mtime = cur_time;
92*ba736c79SDavid van Moolenbroek va.va_atime = pn->pn_va.va_atime;
93*ba736c79SDavid van Moolenbroek
94*ba736c79SDavid van Moolenbroek r = global_pu->pu_ops.puffs_node_setattr(global_pu, pn, &va, pcr);
95*ba736c79SDavid van Moolenbroek if (r) return(EINVAL);
96*ba736c79SDavid van Moolenbroek
97*ba736c79SDavid van Moolenbroek if ((r = fsdriver_copyin(data, 0, rw_buf, bytes)) != OK)
98*ba736c79SDavid van Moolenbroek return r;
99*ba736c79SDavid van Moolenbroek
100*ba736c79SDavid van Moolenbroek if (global_pu->pu_ops.puffs_node_write == NULL)
101*ba736c79SDavid van Moolenbroek return(EINVAL);
102*ba736c79SDavid van Moolenbroek
103*ba736c79SDavid van Moolenbroek r = global_pu->pu_ops.puffs_node_write(global_pu, pn, (uint8_t *)rw_buf,
104*ba736c79SDavid van Moolenbroek pos, &bytes_left, pcr, 0);
105*ba736c79SDavid van Moolenbroek if (r != OK) return(EINVAL);
106*ba736c79SDavid van Moolenbroek
107*ba736c79SDavid van Moolenbroek return (ssize_t)(bytes - bytes_left);
108*ba736c79SDavid van Moolenbroek }
109*ba736c79SDavid van Moolenbroek
110*ba736c79SDavid van Moolenbroek
111*ba736c79SDavid van Moolenbroek /*===========================================================================*
112*ba736c79SDavid van Moolenbroek * fs_getdents *
113*ba736c79SDavid van Moolenbroek *===========================================================================*/
fs_getdents(ino_t ino_nr,struct fsdriver_data * data,size_t bytes,off_t * pos)114*ba736c79SDavid van Moolenbroek ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
115*ba736c79SDavid van Moolenbroek off_t *pos)
116*ba736c79SDavid van Moolenbroek {
117*ba736c79SDavid van Moolenbroek int r;
118*ba736c79SDavid van Moolenbroek register struct puffs_node *pn;
119*ba736c79SDavid van Moolenbroek size_t buf_left, written;
120*ba736c79SDavid van Moolenbroek struct dirent *dent;
121*ba736c79SDavid van Moolenbroek int eofflag = 0;
122*ba736c79SDavid van Moolenbroek PUFFS_MAKECRED(pcr, &global_kcred);
123*ba736c79SDavid van Moolenbroek
124*ba736c79SDavid van Moolenbroek if ((pn = puffs_pn_nodewalk(global_pu, find_inode_cb, &ino_nr)) == NULL) {
125*ba736c79SDavid van Moolenbroek lpuffs_debug("walk failed...\n");
126*ba736c79SDavid van Moolenbroek return(EINVAL);
127*ba736c79SDavid van Moolenbroek }
128*ba736c79SDavid van Moolenbroek
129*ba736c79SDavid van Moolenbroek if (bytes > sizeof(getdents_buf))
130*ba736c79SDavid van Moolenbroek bytes = sizeof(getdents_buf);
131*ba736c79SDavid van Moolenbroek memset(getdents_buf, 0, sizeof(getdents_buf)); /* Avoid leaking any data */
132*ba736c79SDavid van Moolenbroek
133*ba736c79SDavid van Moolenbroek buf_left = bytes;
134*ba736c79SDavid van Moolenbroek
135*ba736c79SDavid van Moolenbroek dent = (struct dirent*) getdents_buf;
136*ba736c79SDavid van Moolenbroek
137*ba736c79SDavid van Moolenbroek r = global_pu->pu_ops.puffs_node_readdir(global_pu, pn, dent, pos,
138*ba736c79SDavid van Moolenbroek &buf_left, pcr, &eofflag, 0, 0);
139*ba736c79SDavid van Moolenbroek if (r) {
140*ba736c79SDavid van Moolenbroek lpuffs_debug("puffs_node_readdir returned error\n");
141*ba736c79SDavid van Moolenbroek return(EINVAL);
142*ba736c79SDavid van Moolenbroek }
143*ba736c79SDavid van Moolenbroek
144*ba736c79SDavid van Moolenbroek assert(buf_left <= bytes);
145*ba736c79SDavid van Moolenbroek written = bytes - buf_left;
146*ba736c79SDavid van Moolenbroek
147*ba736c79SDavid van Moolenbroek if (written == 0 && !eofflag) {
148*ba736c79SDavid van Moolenbroek lpuffs_debug("The user's buffer is too small\n");
149*ba736c79SDavid van Moolenbroek return(EINVAL);
150*ba736c79SDavid van Moolenbroek }
151*ba736c79SDavid van Moolenbroek
152*ba736c79SDavid van Moolenbroek if (written) {
153*ba736c79SDavid van Moolenbroek if ((r = fsdriver_copyout(data, 0, getdents_buf, written)) != OK)
154*ba736c79SDavid van Moolenbroek return r;
155*ba736c79SDavid van Moolenbroek }
156*ba736c79SDavid van Moolenbroek
157*ba736c79SDavid van Moolenbroek update_timens(pn, ATIME, NULL);
158*ba736c79SDavid van Moolenbroek
159*ba736c79SDavid van Moolenbroek /* The puffs readdir call has already updated the position. */
160*ba736c79SDavid van Moolenbroek return written;
161*ba736c79SDavid van Moolenbroek }
162