kernel: separate state for trace-deferred syscalls
[minix.git] / lib / libpuffs / open.c
blobd520ac9732f5aa9a5cf2cd6e0349e0eba9fe0beb
1 /* Created (MFS based):
2 * June 2011 (Evgeniy Ivanov)
3 */
5 #include "fs.h"
6 #include <sys/stat.h>
7 #include <string.h>
8 #include <assert.h>
9 #include <minix/com.h>
10 #include <minix/vfsif.h>
12 #include "puffs.h"
13 #include "puffs_priv.h"
16 /*===========================================================================*
17 * fs_create *
18 *===========================================================================*/
19 int fs_create()
21 int r;
22 struct puffs_node *pn_dir;
23 struct puffs_node *pn;
24 mode_t omode;
25 struct puffs_newinfo pni;
26 struct puffs_kcn pkcnp;
27 PUFFS_MAKECRED(pcr, &global_kcred);
28 struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}};
29 struct vattr va;
30 time_t cur_time;
31 int len;
33 if (global_pu->pu_ops.puffs_node_create == NULL) {
34 lpuffs_debug("No puffs_node_create");
35 return(ENFILE);
38 /* Read request message */
39 omode = (mode_t) fs_m_in.REQ_MODE;
40 caller_uid = (uid_t) fs_m_in.REQ_UID;
41 caller_gid = (gid_t) fs_m_in.REQ_GID;
43 /* Copy the last component (i.e., file name) */
44 len = fs_m_in.REQ_PATH_LEN;
45 pcn.pcn_namelen = len - 1;
46 if (pcn.pcn_namelen > NAME_MAX)
47 return(ENAMETOOLONG);
49 err_code = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) fs_m_in.REQ_GRANT,
50 (vir_bytes) 0, (vir_bytes) pcn.pcn_name,
51 (size_t) len);
52 if (err_code != OK) return(err_code);
53 NUL(pcn.pcn_name, len, sizeof(pcn.pcn_name));
55 /* Get last directory pnode (i.e., directory that will hold the new pnode) */
56 if ((pn_dir = puffs_pn_nodewalk(global_pu, 0, &fs_m_in.REQ_INODE_NR)) == NULL)
57 return(ENOENT);
59 memset(&pni, 0, sizeof(pni));
60 pni.pni_cookie = (void** )&pn;
62 cur_time = clock_time();
64 memset(&va, 0, sizeof(va));
65 va.va_type = VREG;
66 va.va_mode = omode;
67 va.va_uid = caller_uid;
68 va.va_gid = caller_gid;
69 va.va_atime.tv_sec = va.va_mtime.tv_sec = va.va_ctime.tv_sec = cur_time;
71 if (buildpath) {
72 r = puffs_path_pcnbuild(global_pu, &pcn, pn_dir);
73 if (r) {
74 lpuffs_debug("pathbuild error\n");
75 return(ENOENT);
79 r = global_pu->pu_ops.puffs_node_create(global_pu, pn_dir, &pni, &pcn, &va);
80 if (buildpath) {
81 if (r) {
82 global_pu->pu_pathfree(global_pu, &pcn.pcn_po_full);
83 } else {
84 struct puffs_node *_pn;
86 _pn = PU_CMAP(global_pu, pn);
87 _pn->pn_po = pcn.pcn_po_full;
91 if (r != OK) {
92 if (r > 0) r = -r;
93 return(r);
96 /* Open pnode */
97 pn->pn_count++;
99 update_times(pn_dir, MTIME | CTIME, cur_time);
101 /* Reply message */
102 fs_m_out.RES_INODE_NR = pn->pn_va.va_fileid;
103 fs_m_out.RES_MODE = pn->pn_va.va_mode;
104 fs_m_out.RES_FILE_SIZE_LO = pn->pn_va.va_size;
106 /* This values are needed for the execution */
107 fs_m_out.RES_UID = pn->pn_va.va_uid;
108 fs_m_out.RES_GID = pn->pn_va.va_gid;
110 return(OK);
114 /*===========================================================================*
115 * fs_mknod *
116 *===========================================================================*/
117 int fs_mknod()
119 int r;
120 struct puffs_node *pn_dir;
121 struct puffs_node *pn;
122 struct puffs_newinfo pni;
123 struct puffs_kcn pkcnp;
124 PUFFS_MAKECRED(pcr, &global_kcred);
125 struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}};
126 struct vattr va;
127 time_t cur_time;
128 int len;
130 if (global_pu->pu_ops.puffs_node_mknod == NULL) {
131 lpuffs_debug("No puffs_node_mknod");
132 return(ENFILE);
135 /* Copy the last component and set up caller's user and group id */
136 len = fs_m_in.REQ_PATH_LEN;
137 pcn.pcn_namelen = len - 1;
138 if (pcn.pcn_namelen > NAME_MAX)
139 return(ENAMETOOLONG);
141 err_code = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) fs_m_in.REQ_GRANT,
142 (vir_bytes) 0, (vir_bytes) pcn.pcn_name,
143 (size_t) len);
144 if (err_code != OK) return(err_code);
145 NUL(pcn.pcn_name, len, sizeof(pcn.pcn_name));
147 caller_uid = (uid_t) fs_m_in.REQ_UID;
148 caller_gid = (gid_t) fs_m_in.REQ_GID;
150 /* Get last directory pnode */
151 if ((pn_dir = puffs_pn_nodewalk(global_pu, 0, &fs_m_in.REQ_INODE_NR)) == NULL)
152 return(ENOENT);
154 memset(&pni, 0, sizeof(pni));
155 pni.pni_cookie = (void** )&pn;
157 cur_time = clock_time();
159 memset(&va, 0, sizeof(va));
160 va.va_type = VDIR;
161 va.va_mode = (mode_t) fs_m_in.REQ_MODE;
162 va.va_uid = caller_uid;
163 va.va_gid = caller_gid;
164 va.va_rdev = (dev_t) fs_m_in.REQ_DEV;
165 va.va_atime.tv_sec = va.va_mtime.tv_sec = va.va_ctime.tv_sec = cur_time;
167 if (buildpath) {
168 if (puffs_path_pcnbuild(global_pu, &pcn, pn_dir) != 0) {
169 lpuffs_debug("pathbuild error\n");
170 return(ENOENT);
174 r = global_pu->pu_ops.puffs_node_mknod(global_pu, pn_dir, &pni, &pcn, &va);
175 if (buildpath) {
176 if (r) {
177 global_pu->pu_pathfree(global_pu, &pcn.pcn_po_full);
178 } else {
179 struct puffs_node *_pn;
181 _pn = PU_CMAP(global_pu, pn);
182 _pn->pn_po = pcn.pcn_po_full;
186 if (r != OK) {
187 if (r > 0) r = -r;
188 return(r);
191 update_times(pn_dir, MTIME | CTIME, cur_time);
193 return(OK);
197 /*===========================================================================*
198 * fs_mkdir *
199 *===========================================================================*/
200 int fs_mkdir()
202 int r;
203 struct puffs_node *pn_dir;
204 struct puffs_node *pn;
205 struct puffs_newinfo pni;
206 struct puffs_kcn pkcnp;
207 PUFFS_MAKECRED(pcr, &global_kcred);
208 struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}};
209 struct vattr va;
210 time_t cur_time;
211 int len;
213 if (global_pu->pu_ops.puffs_node_mkdir == NULL) {
214 lpuffs_debug("No puffs_node_mkdir");
215 return(ENFILE);
218 /* Copy the last component and set up caller's user and group id */
219 len = fs_m_in.REQ_PATH_LEN;
220 pcn.pcn_namelen = len - 1;
221 if (pcn.pcn_namelen > NAME_MAX)
222 return(ENAMETOOLONG);
224 err_code = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) fs_m_in.REQ_GRANT,
225 (vir_bytes) 0, (vir_bytes) pcn.pcn_name,
226 (phys_bytes) len);
227 if (err_code != OK) return(err_code);
228 NUL(pcn.pcn_name, len, sizeof(pcn.pcn_name));
230 caller_uid = (uid_t) fs_m_in.REQ_UID;
231 caller_gid = (gid_t) fs_m_in.REQ_GID;
233 /* Get last directory pnode */
234 if ((pn_dir = puffs_pn_nodewalk(global_pu, 0, &fs_m_in.REQ_INODE_NR)) == NULL)
235 return(ENOENT);
237 cur_time = clock_time();
239 memset(&pni, 0, sizeof(pni));
240 pni.pni_cookie = (void** )&pn;
242 memset(&va, 0, sizeof(va));
243 va.va_type = VDIR;
244 va.va_mode = (mode_t) fs_m_in.REQ_MODE;
245 va.va_uid = caller_uid;
246 va.va_gid = caller_gid;
247 va.va_atime.tv_sec = va.va_mtime.tv_sec = va.va_ctime.tv_sec = cur_time;
249 if (buildpath) {
250 r = puffs_path_pcnbuild(global_pu, &pcn, pn_dir);
251 if (r) {
252 lpuffs_debug("pathbuild error\n");
253 return(ENOENT);
257 r = global_pu->pu_ops.puffs_node_mkdir(global_pu, pn_dir, &pni, &pcn, &va);
258 if (buildpath) {
259 if (r) {
260 global_pu->pu_pathfree(global_pu, &pcn.pcn_po_full);
261 } else {
262 struct puffs_node *_pn;
264 _pn = PU_CMAP(global_pu, pn);
265 _pn->pn_po = pcn.pcn_po_full;
269 if (r != OK) {
270 if (r > 0) r = -r;
271 return(r);
274 update_times(pn_dir, MTIME | CTIME, cur_time);
276 return(OK);
280 /*===========================================================================*
281 * fs_slink *
282 *===========================================================================*/
283 int fs_slink()
285 int r;
286 struct pnode *pn; /* pnode containing symbolic link */
287 struct pnode *pn_dir; /* directory containing link */
288 char target[PATH_MAX + 1]; /* target path */
289 struct puffs_newinfo pni;
290 struct puffs_kcn pkcnp;
291 PUFFS_MAKECRED(pcr, &global_kcred);
292 struct puffs_cn pcn = {&pkcnp, (struct puffs_cred *) __UNCONST(pcr), {0,0,0}};
293 struct vattr va;
294 int len;
296 caller_uid = (uid_t) fs_m_in.REQ_UID;
297 caller_gid = (gid_t) fs_m_in.REQ_GID;
299 /* Copy the link name's last component */
300 len = fs_m_in.REQ_PATH_LEN;
301 pcn.pcn_namelen = len - 1;
302 if (pcn.pcn_namelen > NAME_MAX)
303 return(ENAMETOOLONG);
305 if (fs_m_in.REQ_MEM_SIZE >= PATH_MAX)
306 return(ENAMETOOLONG);
308 r = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) fs_m_in.REQ_GRANT,
309 (vir_bytes) 0, (vir_bytes) pcn.pcn_name,
310 (size_t) len);
311 if (r != OK) return(r);
312 NUL(pcn.pcn_name, len, sizeof(pcn.pcn_name));
314 /* Copy the target path (note that it's not null terminated) */
315 r = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) fs_m_in.REQ_GRANT3,
316 (vir_bytes) 0, (vir_bytes) target,
317 (size_t) fs_m_in.REQ_MEM_SIZE);
318 if (r != OK) return(r);
319 target[fs_m_in.REQ_MEM_SIZE] = '\0';
321 if (strlen(target) != fs_m_in.REQ_MEM_SIZE) {
322 /* This can happen if the user provides a buffer
323 * with a \0 in it. This can cause a lot of trouble
324 * when the symlink is used later. We could just use
325 * the strlen() value, but we want to let the user
326 * know he did something wrong. ENAMETOOLONG doesn't
327 * exactly describe the error, but there is no
328 * ENAMETOOWRONG.
330 return(ENAMETOOLONG);
333 if ((pn_dir = puffs_pn_nodewalk(global_pu, 0, &fs_m_in.REQ_INODE_NR)) == NULL)
334 return(EINVAL);
336 memset(&pni, 0, sizeof(pni));
337 pni.pni_cookie = (void** )&pn;
339 memset(&va, 0, sizeof(va));
340 va.va_type = VLNK;
341 va.va_mode = (mode_t) (I_SYMBOLIC_LINK | RWX_MODES);
342 va.va_uid = caller_uid;
343 va.va_gid = caller_gid;
344 va.va_atime.tv_sec = va.va_mtime.tv_sec = va.va_ctime.tv_sec = clock_time();
346 if (buildpath) {
347 r = puffs_path_pcnbuild(global_pu, &pcn, pn_dir);
348 if (r) {
349 lpuffs_debug("pathbuild error\n");
350 return(ENOENT);
354 r = global_pu->pu_ops.puffs_node_symlink(global_pu, pn_dir, &pni, &pcn, &va, target);
355 if (buildpath) {
356 if (r) {
357 global_pu->pu_pathfree(global_pu, &pcn.pcn_po_full);
358 } else {
359 struct puffs_node *_pn;
361 _pn = PU_CMAP(global_pu, pn);
362 _pn->pn_po = pcn.pcn_po_full;
366 if (r > 0) r = -r;
368 return(r);
372 /*===========================================================================*
373 * fs_inhibread *
374 *===========================================================================*/
375 int fs_inhibread()
377 return(OK);