1 /**	$MirOS: src/sys/compat/openbsd/openbsd_stat35.c,v 1.1.7.1 2005/03/06 16:33:43 tg Exp $ */
2 /*	$OpenBSD: vfs_syscalls_35.c,v 1.3 2004/07/14 18:57:57 millert Exp $	*/
3 
4 /*
5  * Copyright (c) 1989, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  * (c) UNIX System Laboratories, Inc.
8  * All or some portions of this file are derived from material licensed
9  * to the University of California by American Telephone and Telegraph
10  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
11  * the permission of UNIX System Laboratories, Inc.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *	@(#)vfs_syscalls.c	8.28 (Berkeley) 12/10/94
38  */
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/filedesc.h>
43 #include <sys/kernel.h>
44 #include <sys/proc.h>
45 #include <sys/file.h>
46 #include <sys/vnode.h>
47 #include <sys/namei.h>
48 #include <sys/dirent.h>
49 #include <sys/socket.h>
50 #include <sys/socketvar.h>
51 #include <sys/stat.h>
52 
53 #include <sys/mount.h>
54 #include <compat/common/compat_util.h>
55 #include <compat/common/kern_gen.h>
56 #include <compat/openbsd/compat_openbsd.h>
57 #include <compat/openbsd/openbsd_syscallargs.h>
58 
59 struct stat35 {
60 	dev_t	  st_dev;		/* inode's device */
61 	ino_t	  st_ino;		/* inode's number */
62 	u_int16_t  st_mode;		/* inode protection mode */
63 	u_int16_t  st_nlink;		/* number of hard links */
64 	uid_t	  st_uid;		/* user ID of the file's owner */
65 	gid_t	  st_gid;		/* group ID of the file's group */
66 	dev_t	  st_rdev;		/* device type */
67 	struct	timespec_compat st_atimespec;	/* time of last access */
68 	struct	timespec_compat st_mtimespec;	/* time of last data modification */
69 	struct	timespec_compat st_ctimespec;	/* time of last file status change */
70 	off_t	  st_size;		/* file size, in bytes */
71 	int64_t	  st_blocks;		/* blocks allocated for file */
72 	u_int32_t st_blksize;		/* optimal blocksize for I/O */
73 	u_int32_t st_flags;		/* user defined flags for file */
74 	u_int32_t st_gen;		/* file generation number */
75 	int32_t	  st_lspare;
76 	int64_t	  st_qspare[2];
77 };
78 
79 #if defined(COMPAT_OPENBSD)
80 static void cvtstat(struct stat *, struct stat35 *);
81 
82 /*
83  * Convert from a new to an old stat structure.
84  */
85 static void
cvtstat(struct stat * st,struct stat35 * ost)86 cvtstat(struct stat *st, struct stat35 *ost)
87 {
88 
89 	ost->st_dev = st->st_dev;
90 	ost->st_ino = st->st_ino;
91 	ost->st_mode = st->st_mode & 0xffff;
92 	ost->st_nlink = st->st_nlink & 0xffff;
93 	ost->st_uid = st->st_uid;
94 	ost->st_gid = st->st_gid;
95 	ost->st_rdev = st->st_rdev;
96 	ost->st_atimespec.tv_sec = __BOUNDLONG(st->st_atimespec.tv_sec);
97 	ost->st_atimespec.tv_nsec = st->st_atimespec.tv_nsec;
98 	ost->st_mtimespec.tv_sec = __BOUNDLONG(st->st_mtimespec.tv_sec);
99 	ost->st_mtimespec.tv_nsec = st->st_mtimespec.tv_nsec;
100 	ost->st_ctimespec.tv_sec = __BOUNDLONG(st->st_ctimespec.tv_sec);
101 	ost->st_ctimespec.tv_nsec = st->st_ctimespec.tv_nsec;
102 	ost->st_size = st->st_size;
103 	ost->st_blocks = st->st_blocks;
104 	ost->st_blksize = st->st_blksize;
105 	ost->st_flags = st->st_flags;
106 	ost->st_gen = st->st_gen;
107 }
108 
109 /*
110  * Get file status; this version follows links.
111  */
112 /* ARGSUSED */
113 int
compat_35_sys_stat(struct proc * p,void * v,register_t * retval)114 compat_35_sys_stat(struct proc *p, void *v, register_t *retval)
115 {
116 	struct compat_35_sys_stat_args /* {
117 		syscallarg(char *) path;
118 		syscallarg(struct stat35 *) ub;
119 	} */ *uap = v;
120 	struct stat sb;
121 	struct stat35 osb;
122 	int error;
123 	struct nameidata nd;
124 	caddr_t sg = stackgap_init(p->p_emul);
125 
126 	OPENBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
127 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
128 	    SCARG(uap, path), p);
129 	if ((error = namei(&nd)) != 0)
130 		return (error);
131 	error = vn_stat(nd.ni_vp, &sb, p);
132 	vput(nd.ni_vp);
133 	if (error)
134 		return (error);
135 	/* Don't let non-root see generation numbers (for NFS security) */
136 	if (suser(p, 0))
137 		sb.st_gen = 0;
138 	cvtstat(&sb, &osb);
139 	error = copyout(&osb, SCARG(uap, ub), sizeof(osb));
140 	return (error);
141 }
142 
143 /*
144  * Get file status; this version does not follow links.
145  */
146 /* ARGSUSED */
147 int
compat_35_sys_lstat(struct proc * p,void * v,register_t * retval)148 compat_35_sys_lstat(struct proc *p, void *v, register_t *retval)
149 {
150 	struct compat_35_sys_lstat_args /* {
151 		syscallarg(char *) path;
152 		syscallarg(struct stat35 *) ub;
153 	} */ *uap = v;
154 	struct stat sb;
155 	struct stat35 osb;
156 	int error;
157 	struct nameidata nd;
158 	caddr_t sg = stackgap_init(p->p_emul);
159 
160 	OPENBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
161 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
162 	    SCARG(uap, path), p);
163 	if ((error = namei(&nd)) != 0)
164 		return (error);
165 	error = vn_stat(nd.ni_vp, &sb, p);
166 	vput(nd.ni_vp);
167 	if (error)
168 		return (error);
169 	/* Don't let non-root see generation numbers (for NFS security) */
170 	if (suser(p, 0))
171 		sb.st_gen = 0;
172 	cvtstat(&sb, &osb);
173 	error = copyout(&osb, SCARG(uap, ub), sizeof(osb));
174 	return (error);
175 }
176 
177 /*
178  * Return status information about a file descriptor.
179  */
180 /* ARGSUSED */
181 int
compat_35_sys_fstat(struct proc * p,void * v,register_t * retval)182 compat_35_sys_fstat(struct proc *p, void *v, register_t *retval)
183 {
184 	struct compat_35_sys_fstat_args /* {
185 		syscallarg(int) fd;
186 		syscallarg(struct stat35 *) sb;
187 	} */ *uap = v;
188 	int fd = SCARG(uap, fd);
189 	struct filedesc *fdp = p->p_fd;
190 	struct file *fp;
191 	struct stat ub;
192 	struct stat35 oub;
193 	int error;
194 
195 	if ((fp = fd_getfile(fdp, fd)) == NULL)
196 		return (EBADF);
197 	FREF(fp);
198 	error = (*fp->f_ops->fo_stat)(fp, &ub, p);
199 	FRELE(fp);
200 	if (error == 0) {
201 		/* Don't let non-root see generation numbers
202 		   (for NFS security) */
203 		if (suser(p, 0))
204 			ub.st_gen = 0;
205 		cvtstat(&ub, &oub);
206 		error = copyout(&oub, SCARG(uap, sb), sizeof(oub));
207 	}
208 	return (error);
209 }
210 
211 /* ARGSUSED */
212 int
compat_35_sys_fhstat(struct proc * p,void * v,register_t * retval)213 compat_35_sys_fhstat(struct proc *p, void *v, register_t *retval)
214 {
215 	struct compat_35_sys_fhstat_args /* {
216 		syscallarg(const fhandle_t *) fhp;
217 		syscallarg(struct stat35 *) sb;
218 	} */ *uap = v;
219 	struct stat ub;
220 	struct stat35 oub;
221 	int error;
222 	fhandle_t fh;
223 	struct mount *mp;
224 	struct vnode *vp;
225 
226 	/*
227 	 * Must be super user
228 	 */
229 	if ((error = suser(p, 0)))
230 		return (error);
231 
232 	if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
233 		return (error);
234 
235 	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
236 		return (ESTALE);
237 	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
238 		return (error);
239 	error = vn_stat(vp, &ub, p);
240 	vput(vp);
241 	if (error)
242 		return (error);
243 	cvtstat(&ub, &oub);
244 	error = copyout(&oub, SCARG(uap, sb), sizeof(oub));
245 	return (error);
246 }
247 #endif /* def COMPAT_OPENBSD */
248