1*433d6423SLionel Sambuc /* This file contains the code for performing four system calls relating to
2*433d6423SLionel Sambuc * status and directories.
3*433d6423SLionel Sambuc *
4*433d6423SLionel Sambuc * The entry points into this file are
5*433d6423SLionel Sambuc * do_chdir: perform the CHDIR system call
6*433d6423SLionel Sambuc * do_chroot: perform the CHROOT system call
7*433d6423SLionel Sambuc * do_lstat: perform the LSTAT system call
8*433d6423SLionel Sambuc * do_stat: perform the STAT system call
9*433d6423SLionel Sambuc * do_fstat: perform the FSTAT system call
10*433d6423SLionel Sambuc * do_statvfs: perform the STATVFS1 system call
11*433d6423SLionel Sambuc * do_fstatvfs: perform the FSTATVFS1 system call
12*433d6423SLionel Sambuc * do_getvfsstat: perform the GETVFSSTAT system call
13*433d6423SLionel Sambuc */
14*433d6423SLionel Sambuc
15*433d6423SLionel Sambuc #include "fs.h"
16*433d6423SLionel Sambuc #include <sys/stat.h>
17*433d6423SLionel Sambuc #include <minix/com.h>
18*433d6423SLionel Sambuc #include <minix/u64.h>
19*433d6423SLionel Sambuc #include <string.h>
20*433d6423SLionel Sambuc #include "file.h"
21*433d6423SLionel Sambuc #include "path.h"
22*433d6423SLionel Sambuc #include <minix/vfsif.h>
23*433d6423SLionel Sambuc #include <minix/callnr.h>
24*433d6423SLionel Sambuc #include "vnode.h"
25*433d6423SLionel Sambuc #include "vmnt.h"
26*433d6423SLionel Sambuc
27*433d6423SLionel Sambuc static int change_into(struct vnode **iip, struct vnode *vp);
28*433d6423SLionel Sambuc
29*433d6423SLionel Sambuc /*===========================================================================*
30*433d6423SLionel Sambuc * do_fchdir *
31*433d6423SLionel Sambuc *===========================================================================*/
do_fchdir(void)32*433d6423SLionel Sambuc int do_fchdir(void)
33*433d6423SLionel Sambuc {
34*433d6423SLionel Sambuc /* Change directory on already-opened fd. */
35*433d6423SLionel Sambuc struct filp *rfilp;
36*433d6423SLionel Sambuc int r, rfd;
37*433d6423SLionel Sambuc
38*433d6423SLionel Sambuc rfd = job_m_in.m_lc_vfs_fchdir.fd;
39*433d6423SLionel Sambuc
40*433d6423SLionel Sambuc /* Is the file descriptor valid? */
41*433d6423SLionel Sambuc if ((rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);
42*433d6423SLionel Sambuc r = change_into(&fp->fp_wd, rfilp->filp_vno);
43*433d6423SLionel Sambuc unlock_filp(rfilp);
44*433d6423SLionel Sambuc return(r);
45*433d6423SLionel Sambuc }
46*433d6423SLionel Sambuc
47*433d6423SLionel Sambuc /*===========================================================================*
48*433d6423SLionel Sambuc * do_chdir *
49*433d6423SLionel Sambuc *===========================================================================*/
do_chdir(void)50*433d6423SLionel Sambuc int do_chdir(void)
51*433d6423SLionel Sambuc {
52*433d6423SLionel Sambuc /* Perform the chdir(name) system call.
53*433d6423SLionel Sambuc * syscall might provide 'name' embedded in the message.
54*433d6423SLionel Sambuc */
55*433d6423SLionel Sambuc
56*433d6423SLionel Sambuc int r;
57*433d6423SLionel Sambuc struct vnode *vp;
58*433d6423SLionel Sambuc struct vmnt *vmp;
59*433d6423SLionel Sambuc char fullpath[PATH_MAX];
60*433d6423SLionel Sambuc struct lookup resolve;
61*433d6423SLionel Sambuc
62*433d6423SLionel Sambuc if (copy_path(fullpath, sizeof(fullpath)) != OK)
63*433d6423SLionel Sambuc return(err_code);
64*433d6423SLionel Sambuc
65*433d6423SLionel Sambuc /* Try to open the directory */
66*433d6423SLionel Sambuc lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
67*433d6423SLionel Sambuc resolve.l_vmnt_lock = VMNT_READ;
68*433d6423SLionel Sambuc resolve.l_vnode_lock = VNODE_READ;
69*433d6423SLionel Sambuc if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
70*433d6423SLionel Sambuc
71*433d6423SLionel Sambuc r = change_into(&fp->fp_wd, vp);
72*433d6423SLionel Sambuc
73*433d6423SLionel Sambuc unlock_vnode(vp);
74*433d6423SLionel Sambuc unlock_vmnt(vmp);
75*433d6423SLionel Sambuc put_vnode(vp);
76*433d6423SLionel Sambuc
77*433d6423SLionel Sambuc return(r);
78*433d6423SLionel Sambuc }
79*433d6423SLionel Sambuc
80*433d6423SLionel Sambuc /*===========================================================================*
81*433d6423SLionel Sambuc * do_chroot *
82*433d6423SLionel Sambuc *===========================================================================*/
do_chroot(void)83*433d6423SLionel Sambuc int do_chroot(void)
84*433d6423SLionel Sambuc {
85*433d6423SLionel Sambuc /* Perform the chroot(name) system call.
86*433d6423SLionel Sambuc * syscall might provide 'name' embedded in the message.
87*433d6423SLionel Sambuc */
88*433d6423SLionel Sambuc int r;
89*433d6423SLionel Sambuc struct vnode *vp;
90*433d6423SLionel Sambuc struct vmnt *vmp;
91*433d6423SLionel Sambuc char fullpath[PATH_MAX];
92*433d6423SLionel Sambuc struct lookup resolve;
93*433d6423SLionel Sambuc
94*433d6423SLionel Sambuc if (!super_user) return(EPERM); /* only su may chroot() */
95*433d6423SLionel Sambuc
96*433d6423SLionel Sambuc if (copy_path(fullpath, sizeof(fullpath)) != OK)
97*433d6423SLionel Sambuc return(err_code);
98*433d6423SLionel Sambuc
99*433d6423SLionel Sambuc /* Try to open the directory */
100*433d6423SLionel Sambuc lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
101*433d6423SLionel Sambuc resolve.l_vmnt_lock = VMNT_READ;
102*433d6423SLionel Sambuc resolve.l_vnode_lock = VNODE_READ;
103*433d6423SLionel Sambuc if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
104*433d6423SLionel Sambuc
105*433d6423SLionel Sambuc r = change_into(&fp->fp_rd, vp);
106*433d6423SLionel Sambuc
107*433d6423SLionel Sambuc unlock_vnode(vp);
108*433d6423SLionel Sambuc unlock_vmnt(vmp);
109*433d6423SLionel Sambuc put_vnode(vp);
110*433d6423SLionel Sambuc
111*433d6423SLionel Sambuc return(r);
112*433d6423SLionel Sambuc }
113*433d6423SLionel Sambuc
114*433d6423SLionel Sambuc /*===========================================================================*
115*433d6423SLionel Sambuc * change_into *
116*433d6423SLionel Sambuc *===========================================================================*/
change_into(struct vnode ** result,struct vnode * vp)117*433d6423SLionel Sambuc static int change_into(struct vnode **result, struct vnode *vp)
118*433d6423SLionel Sambuc {
119*433d6423SLionel Sambuc int r;
120*433d6423SLionel Sambuc
121*433d6423SLionel Sambuc if (*result == vp) return(OK); /* Nothing to do */
122*433d6423SLionel Sambuc
123*433d6423SLionel Sambuc /* It must be a directory and also be searchable */
124*433d6423SLionel Sambuc if (!S_ISDIR(vp->v_mode))
125*433d6423SLionel Sambuc r = ENOTDIR;
126*433d6423SLionel Sambuc else
127*433d6423SLionel Sambuc r = forbidden(fp, vp, X_BIT); /* Check if dir is searchable*/
128*433d6423SLionel Sambuc if (r != OK) return(r);
129*433d6423SLionel Sambuc
130*433d6423SLionel Sambuc /* Everything is OK. Make the change. */
131*433d6423SLionel Sambuc put_vnode(*result); /* release the old directory */
132*433d6423SLionel Sambuc dup_vnode(vp);
133*433d6423SLionel Sambuc *result = vp; /* acquire the new one */
134*433d6423SLionel Sambuc return(OK);
135*433d6423SLionel Sambuc }
136*433d6423SLionel Sambuc
137*433d6423SLionel Sambuc /*===========================================================================*
138*433d6423SLionel Sambuc * do_stat *
139*433d6423SLionel Sambuc *===========================================================================*/
do_stat(void)140*433d6423SLionel Sambuc int do_stat(void)
141*433d6423SLionel Sambuc {
142*433d6423SLionel Sambuc /* Perform the stat(name, buf) system call. */
143*433d6423SLionel Sambuc int r;
144*433d6423SLionel Sambuc struct vnode *vp;
145*433d6423SLionel Sambuc struct vmnt *vmp;
146*433d6423SLionel Sambuc char fullpath[PATH_MAX];
147*433d6423SLionel Sambuc struct lookup resolve;
148*433d6423SLionel Sambuc vir_bytes vname1, statbuf;
149*433d6423SLionel Sambuc size_t vname1_length;
150*433d6423SLionel Sambuc
151*433d6423SLionel Sambuc vname1 = job_m_in.m_lc_vfs_stat.name;
152*433d6423SLionel Sambuc vname1_length = job_m_in.m_lc_vfs_stat.len;
153*433d6423SLionel Sambuc statbuf = job_m_in.m_lc_vfs_stat.buf;
154*433d6423SLionel Sambuc
155*433d6423SLionel Sambuc lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
156*433d6423SLionel Sambuc resolve.l_vmnt_lock = VMNT_READ;
157*433d6423SLionel Sambuc resolve.l_vnode_lock = VNODE_READ;
158*433d6423SLionel Sambuc
159*433d6423SLionel Sambuc if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
160*433d6423SLionel Sambuc if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
161*433d6423SLionel Sambuc r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf);
162*433d6423SLionel Sambuc
163*433d6423SLionel Sambuc unlock_vnode(vp);
164*433d6423SLionel Sambuc unlock_vmnt(vmp);
165*433d6423SLionel Sambuc
166*433d6423SLionel Sambuc put_vnode(vp);
167*433d6423SLionel Sambuc return r;
168*433d6423SLionel Sambuc }
169*433d6423SLionel Sambuc
170*433d6423SLionel Sambuc /*===========================================================================*
171*433d6423SLionel Sambuc * do_fstat *
172*433d6423SLionel Sambuc *===========================================================================*/
do_fstat(void)173*433d6423SLionel Sambuc int do_fstat(void)
174*433d6423SLionel Sambuc {
175*433d6423SLionel Sambuc /* Perform the fstat(fd, buf) system call. */
176*433d6423SLionel Sambuc register struct filp *rfilp;
177*433d6423SLionel Sambuc int r, rfd;
178*433d6423SLionel Sambuc vir_bytes statbuf;
179*433d6423SLionel Sambuc
180*433d6423SLionel Sambuc statbuf = job_m_in.m_lc_vfs_fstat.buf;
181*433d6423SLionel Sambuc rfd = job_m_in.m_lc_vfs_fstat.fd;
182*433d6423SLionel Sambuc
183*433d6423SLionel Sambuc /* Is the file descriptor valid? */
184*433d6423SLionel Sambuc if ((rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);
185*433d6423SLionel Sambuc
186*433d6423SLionel Sambuc r = req_stat(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
187*433d6423SLionel Sambuc who_e, statbuf);
188*433d6423SLionel Sambuc
189*433d6423SLionel Sambuc unlock_filp(rfilp);
190*433d6423SLionel Sambuc
191*433d6423SLionel Sambuc return(r);
192*433d6423SLionel Sambuc }
193*433d6423SLionel Sambuc
194*433d6423SLionel Sambuc /*===========================================================================*
195*433d6423SLionel Sambuc * update_statvfs *
196*433d6423SLionel Sambuc *===========================================================================*/
update_statvfs(struct vmnt * vmp,struct statvfs * buf)197*433d6423SLionel Sambuc int update_statvfs(struct vmnt *vmp, struct statvfs *buf)
198*433d6423SLionel Sambuc {
199*433d6423SLionel Sambuc /* Get statistics from a file system, and cache part of the results. */
200*433d6423SLionel Sambuc int r;
201*433d6423SLionel Sambuc
202*433d6423SLionel Sambuc if ((r = req_statvfs(vmp->m_fs_e, buf)) != OK)
203*433d6423SLionel Sambuc return r;
204*433d6423SLionel Sambuc
205*433d6423SLionel Sambuc vmp->m_stats.f_flag = buf->f_flag;
206*433d6423SLionel Sambuc vmp->m_stats.f_bsize = buf->f_bsize;
207*433d6423SLionel Sambuc vmp->m_stats.f_frsize = buf->f_frsize;
208*433d6423SLionel Sambuc vmp->m_stats.f_iosize = buf->f_iosize;
209*433d6423SLionel Sambuc
210*433d6423SLionel Sambuc vmp->m_stats.f_blocks = buf->f_blocks;
211*433d6423SLionel Sambuc vmp->m_stats.f_bfree = buf->f_bfree;
212*433d6423SLionel Sambuc vmp->m_stats.f_bavail = buf->f_bavail;
213*433d6423SLionel Sambuc vmp->m_stats.f_bresvd = buf->f_bresvd;
214*433d6423SLionel Sambuc
215*433d6423SLionel Sambuc vmp->m_stats.f_files = buf->f_files;
216*433d6423SLionel Sambuc vmp->m_stats.f_ffree = buf->f_ffree;
217*433d6423SLionel Sambuc vmp->m_stats.f_favail = buf->f_favail;
218*433d6423SLionel Sambuc vmp->m_stats.f_fresvd = buf->f_fresvd;
219*433d6423SLionel Sambuc
220*433d6423SLionel Sambuc vmp->m_stats.f_syncreads = buf->f_syncreads;
221*433d6423SLionel Sambuc vmp->m_stats.f_syncwrites = buf->f_syncwrites;
222*433d6423SLionel Sambuc
223*433d6423SLionel Sambuc vmp->m_stats.f_asyncreads = buf->f_asyncreads;
224*433d6423SLionel Sambuc vmp->m_stats.f_asyncwrites = buf->f_asyncwrites;
225*433d6423SLionel Sambuc
226*433d6423SLionel Sambuc vmp->m_stats.f_namemax = buf->f_namemax;
227*433d6423SLionel Sambuc
228*433d6423SLionel Sambuc return OK;
229*433d6423SLionel Sambuc }
230*433d6423SLionel Sambuc
231*433d6423SLionel Sambuc /*===========================================================================*
232*433d6423SLionel Sambuc * fill_statvfs *
233*433d6423SLionel Sambuc *===========================================================================*/
fill_statvfs(struct vmnt * vmp,endpoint_t endpt,vir_bytes buf_addr,int flags)234*433d6423SLionel Sambuc static int fill_statvfs(struct vmnt *vmp, endpoint_t endpt, vir_bytes buf_addr,
235*433d6423SLionel Sambuc int flags)
236*433d6423SLionel Sambuc {
237*433d6423SLionel Sambuc /* Fill a statvfs structure in a userspace process. First let the target file
238*433d6423SLionel Sambuc * server fill in most fields, or use the cached copy if ST_NOWAIT is given.
239*433d6423SLionel Sambuc * Then fill in some remaining fields with local information. Finally, copy
240*433d6423SLionel Sambuc * the result to user space.
241*433d6423SLionel Sambuc */
242*433d6423SLionel Sambuc struct statvfs buf;
243*433d6423SLionel Sambuc
244*433d6423SLionel Sambuc if (!(flags & ST_NOWAIT)) {
245*433d6423SLionel Sambuc /* Get fresh statistics from the file system. */
246*433d6423SLionel Sambuc if (update_statvfs(vmp, &buf) != OK)
247*433d6423SLionel Sambuc return EIO;
248*433d6423SLionel Sambuc } else {
249*433d6423SLionel Sambuc /* Use the cached statistics. */
250*433d6423SLionel Sambuc memset(&buf, 0, sizeof(buf));
251*433d6423SLionel Sambuc
252*433d6423SLionel Sambuc buf.f_flag = vmp->m_stats.f_flag;
253*433d6423SLionel Sambuc buf.f_bsize = vmp->m_stats.f_bsize;
254*433d6423SLionel Sambuc buf.f_frsize = vmp->m_stats.f_frsize;
255*433d6423SLionel Sambuc buf.f_iosize = vmp->m_stats.f_iosize;
256*433d6423SLionel Sambuc
257*433d6423SLionel Sambuc buf.f_blocks = vmp->m_stats.f_blocks;
258*433d6423SLionel Sambuc buf.f_bfree = vmp->m_stats.f_bfree;
259*433d6423SLionel Sambuc buf.f_bavail = vmp->m_stats.f_bavail;
260*433d6423SLionel Sambuc buf.f_bresvd = vmp->m_stats.f_bresvd;
261*433d6423SLionel Sambuc
262*433d6423SLionel Sambuc buf.f_files = vmp->m_stats.f_files;
263*433d6423SLionel Sambuc buf.f_ffree = vmp->m_stats.f_ffree;
264*433d6423SLionel Sambuc buf.f_favail = vmp->m_stats.f_favail;
265*433d6423SLionel Sambuc buf.f_fresvd = vmp->m_stats.f_fresvd;
266*433d6423SLionel Sambuc
267*433d6423SLionel Sambuc buf.f_syncreads = vmp->m_stats.f_syncreads;
268*433d6423SLionel Sambuc buf.f_syncwrites = vmp->m_stats.f_syncwrites;
269*433d6423SLionel Sambuc
270*433d6423SLionel Sambuc buf.f_asyncreads = vmp->m_stats.f_asyncreads;
271*433d6423SLionel Sambuc buf.f_asyncwrites = vmp->m_stats.f_asyncwrites;
272*433d6423SLionel Sambuc
273*433d6423SLionel Sambuc buf.f_namemax = vmp->m_stats.f_namemax;
274*433d6423SLionel Sambuc }
275*433d6423SLionel Sambuc
276*433d6423SLionel Sambuc if (vmp->m_flags & VMNT_READONLY)
277*433d6423SLionel Sambuc buf.f_flag |= ST_RDONLY;
278*433d6423SLionel Sambuc
279*433d6423SLionel Sambuc buf.f_fsid = (unsigned long)vmp->m_dev;
280*433d6423SLionel Sambuc buf.f_fsidx.__fsid_val[0] = (long)vmp->m_dev; /* This is what is done on NetBSD */
281*433d6423SLionel Sambuc buf.f_fsidx.__fsid_val[1] = 0; /* Here they convert the FS type name into a number. */
282*433d6423SLionel Sambuc
283*433d6423SLionel Sambuc strlcpy(buf.f_fstypename, vmp->m_fstype, sizeof(buf.f_fstypename));
284*433d6423SLionel Sambuc strlcpy(buf.f_mntonname, vmp->m_mount_path, sizeof(buf.f_mntonname));
285*433d6423SLionel Sambuc strlcpy(buf.f_mntfromname, vmp->m_mount_dev, sizeof(buf.f_mntfromname));
286*433d6423SLionel Sambuc
287*433d6423SLionel Sambuc return sys_datacopy_wrapper(SELF, (vir_bytes) &buf,
288*433d6423SLionel Sambuc endpt, buf_addr, sizeof(buf));
289*433d6423SLionel Sambuc }
290*433d6423SLionel Sambuc
291*433d6423SLionel Sambuc /*===========================================================================*
292*433d6423SLionel Sambuc * do_statvfs *
293*433d6423SLionel Sambuc *===========================================================================*/
do_statvfs(void)294*433d6423SLionel Sambuc int do_statvfs(void)
295*433d6423SLionel Sambuc {
296*433d6423SLionel Sambuc /* Perform the statvfs1(name, buf, flags) system call. */
297*433d6423SLionel Sambuc int r, flags;
298*433d6423SLionel Sambuc struct vnode *vp;
299*433d6423SLionel Sambuc struct vmnt *vmp;
300*433d6423SLionel Sambuc char fullpath[PATH_MAX];
301*433d6423SLionel Sambuc struct lookup resolve;
302*433d6423SLionel Sambuc vir_bytes vname1, statbuf;
303*433d6423SLionel Sambuc size_t vname1_length;
304*433d6423SLionel Sambuc
305*433d6423SLionel Sambuc vname1 = job_m_in.m_lc_vfs_statvfs1.name;
306*433d6423SLionel Sambuc vname1_length = job_m_in.m_lc_vfs_statvfs1.len;
307*433d6423SLionel Sambuc statbuf = job_m_in.m_lc_vfs_statvfs1.buf;
308*433d6423SLionel Sambuc flags = job_m_in.m_lc_vfs_statvfs1.flags;
309*433d6423SLionel Sambuc
310*433d6423SLionel Sambuc lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
311*433d6423SLionel Sambuc resolve.l_vmnt_lock = VMNT_READ;
312*433d6423SLionel Sambuc resolve.l_vnode_lock = VNODE_READ;
313*433d6423SLionel Sambuc
314*433d6423SLionel Sambuc if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
315*433d6423SLionel Sambuc if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
316*433d6423SLionel Sambuc r = fill_statvfs(vp->v_vmnt, who_e, statbuf, flags);
317*433d6423SLionel Sambuc
318*433d6423SLionel Sambuc unlock_vnode(vp);
319*433d6423SLionel Sambuc unlock_vmnt(vmp);
320*433d6423SLionel Sambuc
321*433d6423SLionel Sambuc put_vnode(vp);
322*433d6423SLionel Sambuc return r;
323*433d6423SLionel Sambuc }
324*433d6423SLionel Sambuc
325*433d6423SLionel Sambuc /*===========================================================================*
326*433d6423SLionel Sambuc * do_fstatvfs *
327*433d6423SLionel Sambuc *===========================================================================*/
do_fstatvfs(void)328*433d6423SLionel Sambuc int do_fstatvfs(void)
329*433d6423SLionel Sambuc {
330*433d6423SLionel Sambuc /* Perform the fstatvfs1(fd, buf, flags) system call. */
331*433d6423SLionel Sambuc register struct filp *rfilp;
332*433d6423SLionel Sambuc int r, rfd, flags;
333*433d6423SLionel Sambuc vir_bytes statbuf;
334*433d6423SLionel Sambuc
335*433d6423SLionel Sambuc rfd = job_m_in.m_lc_vfs_statvfs1.fd;
336*433d6423SLionel Sambuc statbuf = job_m_in.m_lc_vfs_statvfs1.buf;
337*433d6423SLionel Sambuc flags = job_m_in.m_lc_vfs_statvfs1.flags;
338*433d6423SLionel Sambuc
339*433d6423SLionel Sambuc /* Is the file descriptor valid? */
340*433d6423SLionel Sambuc if ((rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);
341*433d6423SLionel Sambuc r = fill_statvfs(rfilp->filp_vno->v_vmnt, who_e, statbuf, flags);
342*433d6423SLionel Sambuc
343*433d6423SLionel Sambuc unlock_filp(rfilp);
344*433d6423SLionel Sambuc
345*433d6423SLionel Sambuc return(r);
346*433d6423SLionel Sambuc }
347*433d6423SLionel Sambuc
348*433d6423SLionel Sambuc /*===========================================================================*
349*433d6423SLionel Sambuc * do_getvfsstat *
350*433d6423SLionel Sambuc *===========================================================================*/
do_getvfsstat(void)351*433d6423SLionel Sambuc int do_getvfsstat(void)
352*433d6423SLionel Sambuc {
353*433d6423SLionel Sambuc /* Perform the getvfsstat(buf, bufsize, flags) system call. */
354*433d6423SLionel Sambuc struct vmnt *vmp;
355*433d6423SLionel Sambuc vir_bytes buf;
356*433d6423SLionel Sambuc size_t bufsize;
357*433d6423SLionel Sambuc int r, flags, count, do_lock;
358*433d6423SLionel Sambuc
359*433d6423SLionel Sambuc buf = job_m_in.m_lc_vfs_getvfsstat.buf;
360*433d6423SLionel Sambuc bufsize = job_m_in.m_lc_vfs_getvfsstat.len;
361*433d6423SLionel Sambuc flags = job_m_in.m_lc_vfs_getvfsstat.flags;
362*433d6423SLionel Sambuc
363*433d6423SLionel Sambuc count = 0;
364*433d6423SLionel Sambuc
365*433d6423SLionel Sambuc if (buf != 0) {
366*433d6423SLionel Sambuc /* We only need to lock target file systems if we are going to query
367*433d6423SLionel Sambuc * them. This will only happen if ST_NOWAIT is not given. If we do
368*433d6423SLionel Sambuc * not lock, we rely on the VMNT_CANSTAT flag to protect us from
369*433d6423SLionel Sambuc * concurrent (un)mount operations. Note that procfs relies on
370*433d6423SLionel Sambuc * ST_NOWAIT calls being lock free, as it is a file system itself.
371*433d6423SLionel Sambuc */
372*433d6423SLionel Sambuc do_lock = !(flags & ST_NOWAIT);
373*433d6423SLionel Sambuc
374*433d6423SLionel Sambuc for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
375*433d6423SLionel Sambuc /* If there is no more space, return the count so far. */
376*433d6423SLionel Sambuc if (bufsize < sizeof(struct statvfs))
377*433d6423SLionel Sambuc break;
378*433d6423SLionel Sambuc
379*433d6423SLionel Sambuc /* Lock the file system before checking any fields. */
380*433d6423SLionel Sambuc if (do_lock && (r = lock_vmnt(vmp, VMNT_READ)) != OK)
381*433d6423SLionel Sambuc return r;
382*433d6423SLionel Sambuc
383*433d6423SLionel Sambuc /* Obtain information for this file system, if it is in use and
384*433d6423SLionel Sambuc * can be reported. File systems that are being (un)mounted
385*433d6423SLionel Sambuc * are skipped, as is PFS. The fill call will block only if
386*433d6423SLionel Sambuc * ST_NOWAIT was not given.
387*433d6423SLionel Sambuc */
388*433d6423SLionel Sambuc if (vmp->m_dev != NO_DEV && (vmp->m_flags & VMNT_CANSTAT)) {
389*433d6423SLionel Sambuc if ((r = fill_statvfs(vmp, who_e, buf, flags)) != OK) {
390*433d6423SLionel Sambuc if (do_lock)
391*433d6423SLionel Sambuc unlock_vmnt(vmp);
392*433d6423SLionel Sambuc
393*433d6423SLionel Sambuc return r;
394*433d6423SLionel Sambuc }
395*433d6423SLionel Sambuc
396*433d6423SLionel Sambuc count++;
397*433d6423SLionel Sambuc buf += sizeof(struct statvfs);
398*433d6423SLionel Sambuc bufsize -= sizeof(struct statvfs);
399*433d6423SLionel Sambuc }
400*433d6423SLionel Sambuc
401*433d6423SLionel Sambuc if (do_lock)
402*433d6423SLionel Sambuc unlock_vmnt(vmp);
403*433d6423SLionel Sambuc }
404*433d6423SLionel Sambuc } else {
405*433d6423SLionel Sambuc /* Just report a file system count. No need to lock, as above. */
406*433d6423SLionel Sambuc for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
407*433d6423SLionel Sambuc if (vmp->m_dev != NO_DEV && (vmp->m_flags & VMNT_CANSTAT))
408*433d6423SLionel Sambuc count++;
409*433d6423SLionel Sambuc }
410*433d6423SLionel Sambuc }
411*433d6423SLionel Sambuc
412*433d6423SLionel Sambuc return count;
413*433d6423SLionel Sambuc }
414*433d6423SLionel Sambuc
415*433d6423SLionel Sambuc /*===========================================================================*
416*433d6423SLionel Sambuc * do_lstat *
417*433d6423SLionel Sambuc *===========================================================================*/
do_lstat(void)418*433d6423SLionel Sambuc int do_lstat(void)
419*433d6423SLionel Sambuc {
420*433d6423SLionel Sambuc /* Perform the lstat(name, buf) system call. */
421*433d6423SLionel Sambuc struct vnode *vp;
422*433d6423SLionel Sambuc struct vmnt *vmp;
423*433d6423SLionel Sambuc int r;
424*433d6423SLionel Sambuc char fullpath[PATH_MAX];
425*433d6423SLionel Sambuc struct lookup resolve;
426*433d6423SLionel Sambuc vir_bytes vname1, statbuf;
427*433d6423SLionel Sambuc size_t vname1_length;
428*433d6423SLionel Sambuc
429*433d6423SLionel Sambuc vname1 = job_m_in.m_lc_vfs_stat.name;
430*433d6423SLionel Sambuc vname1_length = job_m_in.m_lc_vfs_stat.len;
431*433d6423SLionel Sambuc statbuf = job_m_in.m_lc_vfs_stat.buf;
432*433d6423SLionel Sambuc
433*433d6423SLionel Sambuc lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp);
434*433d6423SLionel Sambuc resolve.l_vmnt_lock = VMNT_READ;
435*433d6423SLionel Sambuc resolve.l_vnode_lock = VNODE_READ;
436*433d6423SLionel Sambuc
437*433d6423SLionel Sambuc if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
438*433d6423SLionel Sambuc if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
439*433d6423SLionel Sambuc r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf);
440*433d6423SLionel Sambuc
441*433d6423SLionel Sambuc unlock_vnode(vp);
442*433d6423SLionel Sambuc unlock_vmnt(vmp);
443*433d6423SLionel Sambuc
444*433d6423SLionel Sambuc put_vnode(vp);
445*433d6423SLionel Sambuc return(r);
446*433d6423SLionel Sambuc }
447