minor fixes for safecopy & safemap tests
[minix.git] / servers / vfs / stadir.c
blob3d1c367b9b16256d140826545f7b2e0f7b51fd45
1 /* This file contains the code for performing four system calls relating to
2 * status and directories.
4 * The entry points into this file are
5 * do_chdir: perform the CHDIR system call
6 * do_chroot: perform the CHROOT system call
7 * do_lstat: perform the LSTAT system call
8 * do_stat: perform the STAT system call
9 * do_fstat: perform the FSTAT system call
10 * do_fstatfs: perform the FSTATFS system call
11 * do_statvfs: perform the STATVFS system call
12 * do_fstatvfs: perform the FSTATVFS system call
15 #include "fs.h"
16 #include <sys/stat.h>
17 #include <sys/statfs.h>
18 #include <minix/com.h>
19 #include <minix/u64.h>
20 #include <string.h>
21 #include "file.h"
22 #include "fproc.h"
23 #include "path.h"
24 #include "param.h"
25 #include <minix/vfsif.h>
26 #include <minix/callnr.h>
27 #include "vnode.h"
28 #include "vmnt.h"
30 static int change_into(struct vnode **iip, struct vnode *vp);
32 /*===========================================================================*
33 * do_fchdir *
34 *===========================================================================*/
35 int do_fchdir()
37 /* Change directory on already-opened fd. */
38 struct filp *rfilp;
39 int r, rfd;
41 rfd = job_m_in.fd;
43 /* Is the file descriptor valid? */
44 if ((rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);
45 r = change_into(&fp->fp_wd, rfilp->filp_vno);
46 unlock_filp(rfilp);
47 return(r);
50 /*===========================================================================*
51 * do_chdir *
52 *===========================================================================*/
53 int do_chdir()
55 /* Perform the chdir(name) system call.
56 * syscall might provide 'name' embedded in the message.
59 int r;
60 struct vnode *vp;
61 struct vmnt *vmp;
62 char fullpath[PATH_MAX];
63 struct lookup resolve;
64 vir_bytes vname;
65 size_t vname_length;
67 vname = (vir_bytes) job_m_in.name;
68 vname_length = (size_t) job_m_in.name_length;
70 if (copy_name(vname_length, fullpath) != OK) {
71 /* Direct copy failed, try fetching from user space */
72 if (fetch_name(vname, vname_length, fullpath) != OK)
73 return(err_code);
76 /* Try to open the directory */
77 lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
78 resolve.l_vmnt_lock = VMNT_READ;
79 resolve.l_vnode_lock = VNODE_READ;
80 if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
82 r = change_into(&fp->fp_wd, vp);
84 unlock_vnode(vp);
85 unlock_vmnt(vmp);
86 put_vnode(vp);
88 return(r);
91 /*===========================================================================*
92 * do_chroot *
93 *===========================================================================*/
94 int do_chroot()
96 /* Perform the chroot(name) system call.
97 * syscall might provide 'name' embedded in the message.
99 int r;
100 struct vnode *vp;
101 struct vmnt *vmp;
102 char fullpath[PATH_MAX];
103 struct lookup resolve;
104 vir_bytes vname;
105 size_t vname_length;
107 vname = (vir_bytes) job_m_in.name;
108 vname_length = (size_t) job_m_in.name_length;
110 if (!super_user) return(EPERM); /* only su may chroot() */
112 if (copy_name(vname_length, fullpath) != OK) {
113 /* Direct copy failed, try fetching from user space */
114 if (fetch_name(vname, vname_length, fullpath) != OK)
115 return(err_code);
118 /* Try to open the directory */
119 lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
120 resolve.l_vmnt_lock = VMNT_READ;
121 resolve.l_vnode_lock = VNODE_READ;
122 if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
124 r = change_into(&fp->fp_rd, vp);
126 unlock_vnode(vp);
127 unlock_vmnt(vmp);
128 put_vnode(vp);
130 return(r);
133 /*===========================================================================*
134 * change_into *
135 *===========================================================================*/
136 static int change_into(struct vnode **result, struct vnode *vp)
138 int r;
140 if (*result == vp) return(OK); /* Nothing to do */
142 /* It must be a directory and also be searchable */
143 if (!S_ISDIR(vp->v_mode))
144 r = ENOTDIR;
145 else
146 r = forbidden(fp, vp, X_BIT); /* Check if dir is searchable*/
147 if (r != OK) return(r);
149 /* Everything is OK. Make the change. */
150 put_vnode(*result); /* release the old directory */
151 dup_vnode(vp);
152 *result = vp; /* acquire the new one */
153 return(OK);
156 /*===========================================================================*
157 * do_stat *
158 *===========================================================================*/
159 int do_stat()
161 /* Perform the stat(name, buf) system call. */
162 int r;
163 struct vnode *vp;
164 struct vmnt *vmp;
165 char fullpath[PATH_MAX];
166 struct lookup resolve;
167 int old_stat = 0;
168 vir_bytes vname1, statbuf;
169 size_t vname1_length;
171 vname1 = (vir_bytes) job_m_in.name1;
172 vname1_length = (size_t) job_m_in.name1_length;
173 statbuf = (vir_bytes) job_m_in.m1_p2;
175 lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
176 resolve.l_vmnt_lock = VMNT_READ;
177 resolve.l_vnode_lock = VNODE_READ;
179 if (job_call_nr == PREV_STAT)
180 old_stat = 1;
182 if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
183 if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
184 r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf, old_stat);
186 unlock_vnode(vp);
187 unlock_vmnt(vmp);
189 put_vnode(vp);
190 return r;
193 /*===========================================================================*
194 * do_fstat *
195 *===========================================================================*/
196 int do_fstat()
198 /* Perform the fstat(fd, buf) system call. */
199 register struct filp *rfilp;
200 int r, old_stat = 0, rfd;
201 vir_bytes statbuf;
203 statbuf = (vir_bytes) job_m_in.buffer;
204 rfd = job_m_in.fd;
206 if (job_call_nr == PREV_FSTAT)
207 old_stat = 1;
209 /* Is the file descriptor valid? */
210 if ((rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);
212 r = req_stat(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
213 who_e, statbuf, old_stat);
215 unlock_filp(rfilp);
217 return(r);
220 /*===========================================================================*
221 * do_fstatfs *
222 *===========================================================================*/
223 int do_fstatfs()
225 /* Perform the fstatfs(fd, buf) system call. */
226 struct filp *rfilp;
227 int r, rfd;
228 vir_bytes statbuf;
230 rfd = job_m_in.fd;
231 statbuf = (vir_bytes) job_m_in.buffer;
233 /* Is the file descriptor valid? */
234 if( (rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);
236 r = req_fstatfs(rfilp->filp_vno->v_fs_e, who_e, statbuf);
238 unlock_filp(rfilp);
240 return(r);
243 /*===========================================================================*
244 * do_statvfs *
245 *===========================================================================*/
246 int do_statvfs()
248 /* Perform the stat(name, buf) system call. */
249 int r;
250 struct vnode *vp;
251 struct vmnt *vmp;
252 char fullpath[PATH_MAX];
253 struct lookup resolve;
254 vir_bytes vname1, statbuf;
255 size_t vname1_length;
257 vname1 = (vir_bytes) job_m_in.name1;
258 vname1_length = (size_t) job_m_in.name1_length;
259 statbuf = (vir_bytes) job_m_in.name2;
261 lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
262 resolve.l_vmnt_lock = VMNT_READ;
263 resolve.l_vnode_lock = VNODE_READ;
265 if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
266 if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
267 r = req_statvfs(vp->v_fs_e, who_e, statbuf);
269 unlock_vnode(vp);
270 unlock_vmnt(vmp);
272 put_vnode(vp);
273 return r;
276 /*===========================================================================*
277 * do_fstatvfs *
278 *===========================================================================*/
279 int do_fstatvfs()
281 /* Perform the fstat(fd, buf) system call. */
282 register struct filp *rfilp;
283 int r, rfd;
284 vir_bytes statbuf;
286 rfd = job_m_in.fd;
287 statbuf = (vir_bytes) job_m_in.name2;
289 /* Is the file descriptor valid? */
290 if ((rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);
291 r = req_statvfs(rfilp->filp_vno->v_fs_e, who_e, statbuf);
293 unlock_filp(rfilp);
295 return(r);
298 /*===========================================================================*
299 * do_lstat *
300 *===========================================================================*/
301 int do_lstat()
303 /* Perform the lstat(name, buf) system call. */
304 struct vnode *vp;
305 struct vmnt *vmp;
306 int r;
307 char fullpath[PATH_MAX];
308 struct lookup resolve;
309 int old_stat = 0;
310 vir_bytes vname1, statbuf;
311 size_t vname1_length;
313 vname1 = (vir_bytes) job_m_in.name1;
314 vname1_length = (size_t) job_m_in.name1_length;
315 statbuf = (vir_bytes) job_m_in.name2;
317 lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp);
318 resolve.l_vmnt_lock = VMNT_READ;
319 resolve.l_vnode_lock = VNODE_READ;
321 if (job_call_nr == PREV_LSTAT)
322 old_stat = 1;
323 if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
324 if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
325 r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf, old_stat);
327 unlock_vnode(vp);
328 unlock_vmnt(vmp);
330 put_vnode(vp);
331 return(r);