xref: /minix3/minix/lib/libpuffs/read.c (revision ba736c796854b82e29da17267614db0a449419db)
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