custom message type for VM_INFO
[minix3.git] / lib / libpuffs / read.c
blob84ee644b64dbb33ff5255a3aca5efb2f1e8dc68f
1 /* Created (MFS based):
2 * February 2010 (Evgeniy Ivanov)
3 */
5 #include "fs.h"
6 #include <stddef.h>
7 #include <string.h>
8 #include <stdlib.h>
9 #include <dirent.h>
10 #include <minix/com.h>
11 #include <minix/u64.h>
12 #include <minix/vfsif.h>
13 #include <assert.h>
14 #include <sys/param.h>
16 #include "puffs.h"
17 #include "puffs_priv.h"
20 #define GETDENTS_BUFSIZ 4096
21 static char getdents_buf[GETDENTS_BUFSIZ];
23 #define RW_BUFSIZ (128 << 10)
24 static char rw_buf[RW_BUFSIZ];
27 /*===========================================================================*
28 * fs_readwrite *
29 *===========================================================================*/
30 int fs_readwrite(void)
32 int r = OK, rw_flag;
33 cp_grant_id_t gid;
34 off_t pos;
35 size_t nrbytes, bytes_left, bytes_done = 0;
36 struct puffs_node *pn;
37 struct vattr va;
38 PUFFS_MAKECRED(pcr, &global_kcred);
40 if ((pn = puffs_pn_nodewalk(global_pu, 0, &fs_m_in.m_vfs_fs_readwrite.inode)) == NULL) {
41 lpuffs_debug("walk failed...\n");
42 return(EINVAL);
45 /* Get the values from the request message */
46 rw_flag = (fs_m_in.m_type == REQ_READ ? READING : WRITING);
47 gid = fs_m_in.m_vfs_fs_readwrite.grant;
48 pos = fs_m_in.m_vfs_fs_readwrite.seek_pos;
49 nrbytes = bytes_left = fs_m_in.m_vfs_fs_readwrite.nbytes;
51 if (nrbytes > RW_BUFSIZ)
52 nrbytes = bytes_left = RW_BUFSIZ;
54 memset(getdents_buf, '\0', GETDENTS_BUFSIZ); /* Avoid leaking any data */
56 if (rw_flag == READING) {
57 if (global_pu->pu_ops.puffs_node_read == NULL)
58 return(EINVAL);
60 r = global_pu->pu_ops.puffs_node_read(global_pu, pn, (uint8_t *)rw_buf,
61 pos, &bytes_left, pcr, 0);
62 if (r) {
63 lpuffs_debug("puffs_node_read failed\n");
64 return(EINVAL);
67 bytes_done = nrbytes - bytes_left;
68 if (bytes_done) {
69 r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) 0,
70 (vir_bytes) rw_buf, bytes_done);
71 update_timens(pn, ATIME, NULL);
73 } else if (rw_flag == WRITING) {
74 /* At first try to change vattr */
75 if (global_pu->pu_ops.puffs_node_setattr == NULL)
76 return(EINVAL);
78 puffs_vattr_null(&va);
79 if ((u_quad_t)(pos + bytes_left) > pn->pn_va.va_size)
80 va.va_size = bytes_left + pos;
81 va.va_ctime = va.va_mtime = clock_timespec();
82 va.va_atime = pn->pn_va.va_atime;
84 r = global_pu->pu_ops.puffs_node_setattr(global_pu, pn, &va, pcr);
85 if (r) return(EINVAL);
87 r = sys_safecopyfrom(VFS_PROC_NR, gid, (vir_bytes) 0,
88 (vir_bytes) rw_buf, nrbytes);
89 if (r != OK) return(EINVAL);
91 if (global_pu->pu_ops.puffs_node_write == NULL)
92 return(EINVAL);
94 r = global_pu->pu_ops.puffs_node_write(global_pu, pn, (uint8_t *)rw_buf,
95 pos, &bytes_left, pcr, 0);
96 bytes_done = nrbytes - bytes_left;
99 if (r != OK) return(EINVAL);
101 fs_m_out.m_fs_vfs_readwrite.seek_pos = pos + bytes_done;
102 fs_m_out.m_fs_vfs_readwrite.nbytes = bytes_done;
104 return(r);
108 /*===========================================================================*
109 * fs_breadwrite *
110 *===========================================================================*/
111 int fs_breadwrite(void)
113 /* We do not support breads/writes */
114 panic("bread write requested, but FS doesn't support it!\n");
115 return(OK);
119 /*===========================================================================*
120 * fs_getdents *
121 *===========================================================================*/
122 int fs_getdents(void)
124 int r;
125 register struct puffs_node *pn;
126 ino_t ino;
127 cp_grant_id_t gid;
128 size_t size, buf_left;
129 off_t pos;
130 struct dirent *dent;
131 int eofflag = 0;
132 size_t written;
133 PUFFS_MAKECRED(pcr, &global_kcred);
135 ino = fs_m_in.m_vfs_fs_getdents.inode;
136 gid = fs_m_in.m_vfs_fs_getdents.grant;
137 size = buf_left = fs_m_in.m_vfs_fs_getdents.mem_size;
138 pos = fs_m_in.m_vfs_fs_getdents.seek_pos;
140 if ((pn = puffs_pn_nodewalk(global_pu, 0, &ino)) == NULL) {
141 lpuffs_debug("walk failed...\n");
142 return(EINVAL);
145 if (GETDENTS_BUFSIZ < size)
146 size = buf_left = GETDENTS_BUFSIZ;
147 memset(getdents_buf, '\0', GETDENTS_BUFSIZ); /* Avoid leaking any data */
149 dent = (struct dirent*) getdents_buf;
151 r = global_pu->pu_ops.puffs_node_readdir(global_pu, pn, dent, &pos,
152 &buf_left, pcr, &eofflag, 0, 0);
153 if (r) {
154 lpuffs_debug("puffs_node_readdir returned error\n");
155 return(EINVAL);
158 assert(buf_left <= size);
159 written = size - buf_left;
161 if (written == 0 && !eofflag) {
162 lpuffs_debug("The user's buffer is too small\n");
163 return(EINVAL);
166 if (written) {
167 r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) 0,
168 (vir_bytes) getdents_buf, written);
169 if (r != OK) return(r);
172 update_timens(pn, ATIME, NULL);
174 fs_m_out.m_fs_vfs_getdents.nbytes = written;
175 fs_m_out.m_fs_vfs_getdents.seek_pos = pos;
177 return(OK);