1/* $NetBSD: ibcs2_stat.c,v 1.46 2008/06/24 11:18:15 ad Exp $ */ 2/* 3 * Copyright (c) 1995, 1998 Scott Bartram 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 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 without 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 29#include <sys/cdefs.h> 30__KERNEL_RCSID(0, "$NetBSD: ibcs2_stat.c,v 1.46 2008/06/24 11:18:15 ad Exp $"); 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/namei.h> 35#include <sys/proc.h> 36#include <sys/file.h> 37#include <sys/stat.h> 38#include <sys/filedesc.h> 39#include <sys/ioctl.h> 40#include <sys/kernel.h> 41#include <sys/mount.h> 42#include <sys/vnode.h> 43#include <sys/syscallargs.h> 44#include <sys/vfs_syscalls.h> 45 46#include <compat/ibcs2/ibcs2_types.h> 47#include <compat/ibcs2/ibcs2_fcntl.h> 48#include <compat/ibcs2/ibcs2_signal.h> 49#include <compat/ibcs2/ibcs2_stat.h> 50#include <compat/ibcs2/ibcs2_statfs.h> 51#include <compat/ibcs2/ibcs2_syscallargs.h> 52#include <compat/ibcs2/ibcs2_ustat.h> 53#include <compat/ibcs2/ibcs2_util.h> 54#include <compat/ibcs2/ibcs2_utsname.h> 55 56static void bsd_stat2ibcs_stat(struct stat *, struct ibcs2_stat *); 57static int cvt_statfs(struct statvfs *, void *, int); 58static int cvt_statvfs(struct statvfs *, void *, int); 59 60static void 61bsd_stat2ibcs_stat(struct stat *st, struct ibcs2_stat *st4) 62{ 63 memset(st4, 0, sizeof(*st4)); 64 st4->st_dev = (ibcs2_dev_t)st->st_dev; 65 st4->st_ino = (ibcs2_ino_t)st->st_ino; 66 st4->st_mode = (ibcs2_mode_t)st->st_mode; 67 if (st->st_nlink >= (1 << 15)) 68 st4->st_nlink = (1 << 15) - 1; 69 else 70 st4->st_nlink = (ibcs2_nlink_t)st->st_nlink; 71 st4->st_uid = (ibcs2_uid_t)st->st_uid; 72 st4->st_gid = (ibcs2_gid_t)st->st_gid; 73 st4->st_rdev = (ibcs2_dev_t)st->st_rdev; 74 st4->st_size = (ibcs2_off_t)st->st_size; 75 st4->st_atim = (ibcs2_time_t)st->st_atime; 76 st4->st_mtim = (ibcs2_time_t)st->st_mtime; 77 st4->st_ctim = (ibcs2_time_t)st->st_ctime; 78} 79 80static int 81cvt_statfs(struct statvfs *sp, void *tbuf, int len) 82{ 83 struct ibcs2_statfs ssfs; 84 85 if (len < 0) 86 return (EINVAL); 87 if (len > sizeof(ssfs)) 88 len = sizeof(ssfs); 89 90 memset(&ssfs, 0, sizeof ssfs); 91 ssfs.f_fstyp = 0; 92 ssfs.f_bsize = sp->f_bsize; 93 ssfs.f_frsize = sp->f_frsize; 94 ssfs.f_blocks = sp->f_blocks; 95 ssfs.f_bfree = sp->f_bfree; 96 ssfs.f_files = sp->f_files; 97 ssfs.f_ffree = sp->f_ffree; 98 ssfs.f_fname[0] = 0; 99 ssfs.f_fpack[0] = 0; 100 return copyout((void *)&ssfs, tbuf, len); 101} 102 103static int 104cvt_statvfs(struct statvfs *sp, void *tbuf, int len) 105{ 106 struct ibcs2_statvfs ssvfs; 107 108 if (len < 0) 109 return (EINVAL); 110 if (len > sizeof(ssvfs)) 111 len = sizeof(ssvfs); 112 113 memset(&ssvfs, 0, sizeof ssvfs); 114 ssvfs.f_bsize = sp->f_bsize; 115 ssvfs.f_frsize = sp->f_frsize; 116 ssvfs.f_blocks = sp->f_blocks; 117 ssvfs.f_bfree = sp->f_bfree; 118 ssvfs.f_bavail = sp->f_bavail; 119 ssvfs.f_files = sp->f_files; 120 ssvfs.f_ffree = sp->f_ffree; 121 ssvfs.f_favail = sp->f_favail; 122 ssvfs.f_fsid = sp->f_fsidx.__fsid_val[0]; 123 strncpy(ssvfs.f_basetype, sp->f_fstypename, 15); 124 ssvfs.f_flag = 0; 125 ssvfs.f_namemax = PATH_MAX; 126 ssvfs.f_fstr[0] = 0; 127 return copyout((void *)&ssvfs, tbuf, len); 128} 129 130int 131ibcs2_sys_statfs(struct lwp *l, const struct ibcs2_sys_statfs_args *uap, register_t *retval) 132{ 133 /* { 134 syscallarg(const char *) path; 135 syscallarg(struct ibcs2_statfs *) buf; 136 syscallarg(int) len; 137 syscallarg(int) fstype; 138 } */ 139 struct mount *mp; 140 struct statvfs *sp; 141 int error; 142 struct vnode *vp; 143 144 error = namei_simple_user(SCARG(uap, path), 145 NSM_FOLLOW_TRYEMULROOT, &vp); 146 if (error != 0) 147 return (error); 148 mp = vp->v_mount; 149 sp = &mp->mnt_stat; 150 vrele(vp); 151 if ((error = VFS_STATVFS(mp, sp)) != 0) 152 return (error); 153 sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK; 154 return cvt_statfs(sp, (void *)SCARG(uap, buf), SCARG(uap, len)); 155} 156 157int 158ibcs2_sys_fstatfs(struct lwp *l, const struct ibcs2_sys_fstatfs_args *uap, register_t *retval) 159{ 160 /* { 161 syscallarg(int) fd; 162 syscallarg(struct ibcs2_statfs *) buf; 163 syscallarg(int) len; 164 syscallarg(int) fstype; 165 } */ 166 file_t *fp; 167 struct mount *mp; 168 struct statvfs *sp; 169 int error; 170 171 /* fd_getvnode() will use the descriptor for us */ 172 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 173 return (error); 174 mp = ((struct vnode *)fp->f_data)->v_mount; 175 sp = &mp->mnt_stat; 176 if ((error = VFS_STATVFS(mp, sp)) != 0) 177 goto out; 178 sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK; 179 error = cvt_statfs(sp, (void *)SCARG(uap, buf), SCARG(uap, len)); 180 out: 181 fd_putfile(SCARG(uap, fd)); 182 return (error); 183} 184 185int 186ibcs2_sys_statvfs(struct lwp *l, const struct ibcs2_sys_statvfs_args *uap, register_t *retval) 187{ 188 /* { 189 syscallarg(const char *) path; 190 syscallarg(struct ibcs2_statvfs *) buf; 191 } */ 192 struct mount *mp; 193 struct statvfs *sp; 194 int error; 195 struct vnode *vp; 196 197 error = namei_simple_user(SCARG(uap, path), 198 NSM_FOLLOW_TRYEMULROOT, &vp); 199 if (error != 0) 200 return (error); 201 mp = vp->v_mount; 202 sp = &mp->mnt_stat; 203 vrele(vp); 204 if ((error = VFS_STATVFS(mp, sp)) != 0) 205 return (error); 206 sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK; 207 return cvt_statvfs(sp, (void *)SCARG(uap, buf), 208 sizeof(struct ibcs2_statvfs)); 209} 210 211int 212ibcs2_sys_fstatvfs(struct lwp *l, const struct ibcs2_sys_fstatvfs_args *uap, register_t *retval) 213{ 214 /* { 215 syscallarg(int) fd; 216 syscallarg(struct ibcs2_statvfs *) buf; 217 } */ 218 file_t *fp; 219 struct mount *mp; 220 struct statvfs *sp; 221 int error; 222 223 /* fd_getvnode() will use the descriptor for us */ 224 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 225 return (error); 226 mp = ((struct vnode *)fp->f_data)->v_mount; 227 sp = &mp->mnt_stat; 228 if ((error = VFS_STATVFS(mp, sp)) != 0) 229 goto out; 230 sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK; 231 error = cvt_statvfs(sp, SCARG(uap, buf), sizeof(struct ibcs2_statvfs)); 232 out: 233 fd_putfile(SCARG(uap, fd)); 234 return (error); 235} 236 237int 238ibcs2_sys_stat(struct lwp *l, const struct ibcs2_sys_stat_args *uap, register_t *retval) 239{ 240 /* { 241 syscallarg(const char *) path; 242 syscallarg(struct ibcs2_stat *) st; 243 } */ 244 struct stat sb; 245 struct ibcs2_stat ibcs2_st; 246 int error; 247 248 error = do_sys_stat(SCARG(uap, path), FOLLOW, &sb); 249 if (error != 0) 250 return error; 251 252 bsd_stat2ibcs_stat(&sb, &ibcs2_st); 253 return copyout(&ibcs2_st, SCARG(uap, st), sizeof (ibcs2_st)); 254} 255 256int 257ibcs2_sys_lstat(struct lwp *l, const struct ibcs2_sys_lstat_args *uap, register_t *retval) 258{ 259 /* { 260 syscallarg(const char *) path; 261 syscallarg(struct ibcs2_stat *) st; 262 } */ 263 struct stat sb; 264 struct ibcs2_stat ibcs2_st; 265 int error; 266 267 error = do_sys_stat(SCARG(uap, path), NOFOLLOW, &sb); 268 if (error != 0) 269 return error; 270 271 bsd_stat2ibcs_stat(&sb, &ibcs2_st); 272 return copyout((void *)&ibcs2_st, (void *)SCARG(uap, st), 273 sizeof (ibcs2_st)); 274} 275 276int 277ibcs2_sys_fstat(struct lwp *l, const struct ibcs2_sys_fstat_args *uap, register_t *retval) 278{ 279 /* { 280 syscallarg(int) fd; 281 syscallarg(struct ibcs2_stat *) st; 282 } */ 283 struct stat sb; 284 struct ibcs2_stat ibcs2_st; 285 int error; 286 287 error = do_sys_fstat(SCARG(uap, fd), &sb); 288 if (error != 0) 289 return error; 290 291 bsd_stat2ibcs_stat(&sb, &ibcs2_st); 292 return copyout(&ibcs2_st, SCARG(uap, st), sizeof (ibcs2_st)); 293} 294 295int 296ibcs2_sys_utssys(struct lwp *l, const struct ibcs2_sys_utssys_args *uap, register_t *retval) 297{ 298 /* { 299 syscallarg(int) a1; 300 syscallarg(int) a2; 301 syscallarg(int) flag; 302 } */ 303 304 switch (SCARG(uap, flag)) { 305 case 0: /* uname(struct utsname *) */ 306 { 307 struct ibcs2_utsname sut; 308 309 memset(&sut, 0, ibcs2_utsname_len); 310 memcpy(sut.sysname, ostype, sizeof(sut.sysname) - 1); 311 memcpy(sut.nodename, hostname, sizeof(sut.nodename)); 312 sut.nodename[sizeof(sut.nodename)-1] = '\0'; 313 memcpy(sut.release, osrelease, sizeof(sut.release) - 1); 314 strlcpy(sut.version, "1", sizeof(sut.version)); 315 memcpy(sut.machine, machine, sizeof(sut.machine) - 1); 316 317 return copyout((void *)&sut, (void *)SCARG(uap, a1), 318 ibcs2_utsname_len); 319 } 320 321 case 2: /* ustat(dev_t, struct ustat *) */ 322 { 323 struct ibcs2_ustat xu; 324 325 xu.f_tfree = 20000; /* XXX fixme */ 326 xu.f_tinode = 32000; 327 xu.f_fname[0] = 0; 328 xu.f_fpack[0] = 0; 329 return copyout((void *)&xu, (void *)SCARG(uap, a2), 330 ibcs2_ustat_len); 331 } 332 333 default: 334 return ENOSYS; 335 } 336} 337