xref: /minix3/minix/servers/vfs/stadir.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
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