1 /*-
2 * Copyright (c) 1994-1995 Søren Schmidt
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer
10 * in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software withough specific prior written permission
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $FreeBSD: src/sys/i386/linux/linux_stats.c,v 1.5.4.2 1999/09/05 08:14:19 peter Exp $
29 */
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/dirent.h>
34 #include <sys/file.h>
35 #include <sys/filedesc.h>
36 #include <sys/proc.h>
37 #include <sys/mount.h>
38 #include <sys/namei.h>
39 #include <sys/socketvar.h>
40 #include <sys/stat.h>
41 #include <sys/vnode.h>
42 #include <sys/pipe.h>
43
44 #include <i386/linux/linux.h>
45 #include <i386/linux/linux_proto.h>
46 #include <i386/linux/linux_util.h>
47
48 struct linux_newstat {
49 unsigned short stat_dev;
50 unsigned short __pad1;
51 unsigned long stat_ino;
52 unsigned short stat_mode;
53 unsigned short stat_nlink;
54 unsigned short stat_uid;
55 unsigned short stat_gid;
56 unsigned short stat_rdev;
57 unsigned short __pad2;
58 unsigned long stat_size;
59 unsigned long stat_blksize;
60 unsigned long stat_blocks;
61 unsigned long stat_atime;
62 unsigned long __unused1;
63 unsigned long stat_mtime;
64 unsigned long __unused2;
65 unsigned long stat_ctime;
66 unsigned long __unused3;
67 unsigned long __unused4;
68 unsigned long __unused5;
69 };
70
71
72 static int
73 newstat_copyout(struct stat *buf, void *ubuf)
74 {
75 struct linux_newstat tbuf;
76
77 tbuf.stat_dev = (buf->st_dev & 0xff) | ((buf->st_dev & 0xff00)<<10);
78 tbuf.stat_ino = buf->st_ino;
79 tbuf.stat_mode = buf->st_mode;
80 tbuf.stat_nlink = buf->st_nlink;
81 tbuf.stat_uid = buf->st_uid;
82 tbuf.stat_gid = buf->st_gid;
83 tbuf.stat_rdev = buf->st_rdev;
84 tbuf.stat_size = buf->st_size;
85 tbuf.stat_atime = buf->st_atime;
86 tbuf.stat_mtime = buf->st_mtime;
87 tbuf.stat_ctime = buf->st_ctime;
88 tbuf.stat_blksize = buf->st_blksize;
89 tbuf.stat_blocks = buf->st_blocks;
90 return copyout(&tbuf, ubuf, sizeof(tbuf));
91 }
92
93 int
94 linux_newstat(struct proc *p, struct linux_newstat_args *args, int *retval)
95 {
96 struct stat buf;
97 struct nameidata nd;
98 int error;
99 caddr_t sg;
100
101 sg = stackgap_init();
102 CHECKALTEXIST(p, &sg, args->path);
103
104 #ifdef DEBUG
105 printf("Linux-emul(%d): newstat(%s, *)\n", p->p_pid, args->path);
106 #endif
107 NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_USERSPACE, args->path, p);
108 error = namei(&nd);
109 if (!error) {
110 error = vn_stat(nd.ni_vp, &buf, p);
111 vput(nd.ni_vp);
112 }
113 if (!error)
114 error = newstat_copyout(&buf, args->buf);
115 return error;
116 }
117
118 /*
119 * Get file status; this version does not follow links.
120 */
121 int
122 linux_newlstat(p, uap, retval)
123 struct proc *p;
124 struct linux_newlstat_args *uap;
125 int *retval;
126 {
127 int error;
128 struct vnode *vp, *dvp;
129 struct stat sb, sb1;
130 struct nameidata nd;
131 caddr_t sg;
132
133 sg = stackgap_init();
134 CHECKALTEXIST(p, &sg, uap->path);
135
136 #ifdef DEBUG
137 printf("Linux-emul(%d): newlstat(%s, *)\n", p->p_pid, uap->path);
138 #endif
139 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
140 uap->path, p);
141 error = namei(&nd);
142 if (error)
143 return (error);
144 /*
145 * For symbolic links, always return the attributes of its
146 * containing directory, except for mode, size, and links.
147 */
148 vp = nd.ni_vp;
149 dvp = nd.ni_dvp;
150 if (vp->v_type != VLNK) {
151 if (dvp == vp)
152 vrele(dvp);
153 else
154 vput(dvp);
155 error = vn_stat(vp, &sb, p);
156 vput(vp);
157 if (error)
158 return (error);
159 } else {
160 error = vn_stat(dvp, &sb, p);
161 vput(dvp);
162 if (error) {
163 vput(vp);
164 return (error);
165 }
166 error = vn_stat(vp, &sb1, p);
167 vput(vp);
168 if (error)
169 return (error);
170 sb.st_mode &= ~S_IFDIR;
171 sb.st_mode |= S_IFLNK;
172 sb.st_nlink = sb1.st_nlink;
173 sb.st_size = sb1.st_size;
174 sb.st_blocks = sb1.st_blocks;
175 }
176 error = newstat_copyout(&sb, uap->buf);
177 return (error);
178 }
179
180 int
181 linux_newfstat(struct proc *p, struct linux_newfstat_args *args, int *retval)
182 {
183 struct filedesc *fdp = p->p_fd;
184 struct file *fp;
185 struct stat buf;
186 int error;
187
188 #ifdef DEBUG
189 printf("Linux-emul(%d): newfstat(%d, *)\n", p->p_pid, args->fd);
190 #endif
191 if ((unsigned)args->fd >= fdp->fd_nfiles
192 || (fp = fdp->fd_ofiles[args->fd]) == NULL)
193 return EBADF;
194 switch (fp->f_type) {
195 case DTYPE_FIFO:
196 case DTYPE_VNODE:
197 error = vn_stat((struct vnode *)fp->f_data, &buf, p);
198 break;
199 case DTYPE_SOCKET:
200 error = soo_stat((struct socket *)fp->f_data, &buf);
201 break;
202 case DTYPE_PIPE:
203 error = pipe_stat((struct pipe *)fp->f_data, &buf);
204 break;
205 default:
206 panic("LINUX newfstat");
207 }
208 if (!error)
209 error = newstat_copyout(&buf, args->buf);
210 return error;
211 }
212
213 struct linux_statfs_buf {
214 long ftype;
215 long fbsize;
216 long fblocks;
217 long fbfree;
218 long fbavail;
219 long ffiles;
220 long fffree;
221 linux_fsid_t ffsid;
222 long fnamelen;
223 long fspare[6];
224 };
225
226 int
227 linux_statfs(struct proc *p, struct linux_statfs_args *args, int *retval)
228 {
229 struct mount *mp;
230 struct nameidata *ndp;
231 struct statfs *bsd_statfs;
232 struct nameidata nd;
233 struct linux_statfs_buf linux_statfs_buf;
234 int error;
235 caddr_t sg;
236
237 sg = stackgap_init();
238 CHECKALTEXIST(p, &sg, args->path);
239
240 #ifdef DEBUG
241 printf("Linux-emul(%d): statfs(%s, *)\n", p->p_pid, args->path);
242 #endif
243 ndp = &nd;
244 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args->path, curproc);
245 if (error = namei(ndp))
246 return error;
247 mp = ndp->ni_vp->v_mount;
248 bsd_statfs = &mp->mnt_stat;
249 vrele(ndp->ni_vp);
250 if (error = VFS_STATFS(mp, bsd_statfs, p))
251 return error;
252 bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
253 linux_statfs_buf.ftype = bsd_statfs->f_type;
254 linux_statfs_buf.fbsize = bsd_statfs->f_bsize;
255 linux_statfs_buf.fblocks = bsd_statfs->f_blocks;
256 linux_statfs_buf.fbfree = bsd_statfs->f_bfree;
257 linux_statfs_buf.fbavail = bsd_statfs->f_bavail;
258 linux_statfs_buf.fffree = bsd_statfs->f_ffree;
259 linux_statfs_buf.ffiles = bsd_statfs->f_files;
260 linux_statfs_buf.ffsid.val[0] = bsd_statfs->f_fsid.val[0];
261 linux_statfs_buf.ffsid.val[1] = bsd_statfs->f_fsid.val[1];
262 linux_statfs_buf.fnamelen = MAXNAMLEN;
263 return copyout((caddr_t)&linux_statfs_buf, (caddr_t)args->buf,
264 sizeof(struct linux_statfs_buf));
265 }
266
267 int
268 linux_fstatfs(struct proc *p, struct linux_fstatfs_args *args, int *retval)
269 {
270 struct file *fp;
271 struct mount *mp;
272 struct statfs *bsd_statfs;
273 struct linux_statfs_buf linux_statfs_buf;
274 int error;
275
276 #ifdef DEBUG
277 printf("Linux-emul(%d): fstatfs(%d, *)\n", p->p_pid, args->fd);
278 #endif
279 if (error = getvnode(p->p_fd, args->fd, &fp))
280 return error;
281 mp = ((struct vnode *)fp->f_data)->v_mount;
282 bsd_statfs = &mp->mnt_stat;
283 if (error = VFS_STATFS(mp, bsd_statfs, p))
284 return error;
285 bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
286 linux_statfs_buf.ftype = bsd_statfs->f_type;
287 linux_statfs_buf.fbsize = bsd_statfs->f_bsize;
288 linux_statfs_buf.fblocks = bsd_statfs->f_blocks;
289 linux_statfs_buf.fbfree = bsd_statfs->f_bfree;
290 linux_statfs_buf.fbavail = bsd_statfs->f_bavail;
291 linux_statfs_buf.fffree = bsd_statfs->f_ffree;
292 linux_statfs_buf.ffiles = bsd_statfs->f_files;
293 linux_statfs_buf.ffsid.val[0] = bsd_statfs->f_fsid.val[0];
294 linux_statfs_buf.ffsid.val[1] = bsd_statfs->f_fsid.val[1];
295 linux_statfs_buf.fnamelen = MAXNAMLEN;
296 return copyout((caddr_t)&linux_statfs_buf, (caddr_t)args->buf,
297 sizeof(struct linux_statfs_buf));
298 }
Cache object: 50398062cb51af8d5c507417b926124f
|