1 /* $OpenBSD: vfs_syscalls_25.c,v 1.12 2006/06/25 15:01:53 sturm Exp $ */
2
3 /*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)vfs_syscalls.c 8.28 (Berkeley) 12/10/94
37 */
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/namei.h>
42 #include <sys/filedesc.h>
43 #include <sys/kernel.h>
44 #include <sys/file.h>
45 #include <sys/vnode.h>
46 #include <sys/mount.h>
47 #include <sys/proc.h>
48 #include <sys/uio.h>
49 #include <sys/dirent.h>
50
51 #include <sys/syscallargs.h>
52
53 void statfs_to_ostatfs(struct proc *, struct mount *, struct statfs *, struct ostatfs *);
54
55 /*
56 * Convert struct statfs -> struct ostatfs
57 */
58 void
59 statfs_to_ostatfs(p, mp, sp, osp)
60 struct proc *p;
61 struct mount *mp;
62 struct statfs *sp;
63 struct ostatfs *osp;
64 {
65 #ifdef COMPAT_43
66 osp->f_type = mp->mnt_vfc->vfc_typenum;
67 #else
68 osp->f_type = 0;
69 #endif
70 osp->f_flags = mp->mnt_flag & 0xffff;
71 osp->f_bsize = sp->f_bsize;
72 osp->f_iosize = sp->f_iosize;
73 osp->f_blocks = sp->f_blocks;
74 osp->f_bfree = sp->f_bfree;
75 osp->f_bavail = sp->f_bavail;
76 osp->f_files = sp->f_files;
77 osp->f_ffree = sp->f_ffree;
78 /* Don't let non-root see filesystem id (for NFS security) */
79 if (suser(p, 0))
80 osp->f_fsid.val[0] = osp->f_fsid.val[1] = 0;
81 else
82 bcopy(&sp->f_fsid, &osp->f_fsid, sizeof(osp->f_fsid));
83 osp->f_owner = sp->f_owner;
84 osp->f_syncwrites = sp->f_syncwrites;
85 osp->f_asyncwrites = sp->f_asyncwrites;
86 bcopy(sp->f_fstypename, osp->f_fstypename, MFSNAMELEN);
87 bcopy(sp->f_mntonname, osp->f_mntonname, MNAMELEN);
88 bcopy(sp->f_mntfromname, osp->f_mntfromname, MNAMELEN);
89 }
90
91 /*
92 * Get filesystem statistics.
93 */
94 /* ARGSUSED */
95 int
96 compat_25_sys_statfs(p, v, retval)
97 struct proc *p;
98 void *v;
99 register_t *retval;
100 {
101 register struct compat_25_sys_statfs_args /* {
102 syscallarg(char *) path;
103 syscallarg(struct ostatfs *) buf;
104 } */ *uap = v;
105 register struct mount *mp;
106 register struct statfs *sp;
107 struct ostatfs osb;
108 int error;
109 struct nameidata nd;
110
111 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
112 if ((error = namei(&nd)) != 0)
113 return (error);
114 mp = nd.ni_vp->v_mount;
115 sp = &mp->mnt_stat;
116 vrele(nd.ni_vp);
117 if ((error = VFS_STATFS(mp, sp, p)) != 0)
118 return (error);
119
120 statfs_to_ostatfs(p, mp, sp, &osb);
121 return (copyout((caddr_t)&osb, (caddr_t)SCARG(uap, buf), sizeof(osb)));
122 }
123
124 /*
125 * Get filesystem statistics.
126 */
127 /* ARGSUSED */
128 int
129 compat_25_sys_fstatfs(p, v, retval)
130 struct proc *p;
131 void *v;
132 register_t *retval;
133 {
134 struct compat_25_sys_fstatfs_args /* {
135 syscallarg(int) fd;
136 syscallarg(struct ostatfs *) buf;
137 } */ *uap = v;
138 struct file *fp;
139 struct mount *mp;
140 struct statfs *sp;
141 struct ostatfs osb;
142 int error;
143
144 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
145 return (error);
146 mp = ((struct vnode *)fp->f_data)->v_mount;
147 sp = &mp->mnt_stat;
148 error = VFS_STATFS(mp, sp, p);
149 FRELE(fp);
150 if (error)
151 return (error);
152
153 statfs_to_ostatfs(p, mp, sp, &osb);
154 return (copyout((caddr_t)&osb, (caddr_t)SCARG(uap, buf), sizeof(osb)));
155 }
156
157 /*
158 * Get statistics on all filesystems.
159 */
160 int
161 compat_25_sys_getfsstat(p, v, retval)
162 struct proc *p;
163 void *v;
164 register_t *retval;
165 {
166 register struct compat_25_sys_getfsstat_args /* {
167 syscallarg(struct ostatfs *) buf;
168 syscallarg(long) bufsize;
169 syscallarg(int) flags;
170 } */ *uap = v;
171 register struct mount *mp, *nmp;
172 register struct statfs *sp;
173 struct ostatfs osb;
174 caddr_t sfsp;
175 long count, maxcount;
176 int error, flags = SCARG(uap, flags);
177
178 maxcount = SCARG(uap, bufsize) / sizeof(struct ostatfs);
179 sfsp = (caddr_t)SCARG(uap, buf);
180 count = 0;
181
182 for (mp = CIRCLEQ_FIRST(&mountlist); mp != CIRCLEQ_END(&mountlist);
183 mp = nmp) {
184 if (vfs_busy(mp, VB_READ|VB_NOWAIT)) {
185 nmp = CIRCLEQ_NEXT(mp, mnt_list);
186 continue;
187 }
188 if (sfsp && count < maxcount) {
189 sp = &mp->mnt_stat;
190
191 /* Refresh stats unless MNT_NOWAIT is specified */
192 if (flags != MNT_NOWAIT &&
193 flags != MNT_LAZY &&
194 (flags == MNT_WAIT ||
195 flags == 0) &&
196 (error = VFS_STATFS(mp, sp, p))) {
197 nmp = CIRCLEQ_NEXT(mp, mnt_list);
198 vfs_unbusy(mp);
199 continue;
200 }
201
202 statfs_to_ostatfs(p, mp, sp, &osb);
203 error = copyout((caddr_t)&osb, sfsp, sizeof(osb));
204 if (error) {
205 vfs_unbusy(mp);
206 return (error);
207 }
208 sfsp += sizeof(osb);
209 }
210 count++;
211 nmp = CIRCLEQ_NEXT(mp, mnt_list);
212 vfs_unbusy(mp);
213 }
214
215 if (sfsp && count > maxcount)
216 *retval = maxcount;
217 else
218 *retval = count;
219
220 return (0);
221 }