Home | History | Annotate | Download | only in syscall
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
     27 /*	  All Rights Reserved  	*/
     28 
     29 /*
     30  * Portions of this source code were derived from Berkeley 4.3 BSD
     31  * under license from the Regents of the University of California.
     32  */
     33 
     34 #pragma ident	"@(#)statfs.c	1.12	06/05/17 SMI"
     35 
     36 #include <sys/inttypes.h>
     37 #include <sys/types.h>
     38 #include <sys/t_lock.h>
     39 #include <sys/param.h>
     40 #include <sys/errno.h>
     41 #include <sys/fstyp.h>
     42 #include <sys/systm.h>
     43 #include <sys/vfs.h>
     44 #include <sys/statfs.h>
     45 #include <sys/vnode.h>
     46 #include <sys/file.h>
     47 #include <sys/cmn_err.h>
     48 #include <sys/debug.h>
     49 #include <sys/pathname.h>
     50 
     51 #include <vm/page.h>
     52 #include <fs/fs_subr.h>
     53 
     54 #if defined(_SYSCALL32_IMPL) || defined(_ILP32)
     55 
     56 /*
     57  * statfs(2) and fstatfs(2) have been replaced by statvfs(2) and
     58  * fstatvfs(2) and will be removed from the system in a near-future
     59  * release.
     60  *
     61  * Supported here purely for 32-bit compatibility.
     62  */
     63 
     64 static int cstatfs(struct vfs *, struct statfs32 *, int);
     65 
     66 int
     67 statfs32(char *fname, struct statfs32 *sbp, int32_t len, int32_t fstyp)
     68 {
     69 	vnode_t *vp;
     70 	int error;
     71 	int estale_retry = 0;
     72 
     73 lookup:
     74 	if (error = lookupname(fname, UIO_USERSPACE, FOLLOW, NULLVPP, &vp)) {
     75 		if ((error == ESTALE) && fs_need_estale_retry(estale_retry++))
     76 			goto lookup;
     77 		return (set_errno(error));
     78 	}
     79 	if (fstyp != 0)
     80 		error = EINVAL;
     81 	else
     82 		error = cstatfs(vp->v_vfsp, sbp, len);
     83 	VN_RELE(vp);
     84 	if (error) {
     85 		if ((error == ESTALE) && fs_need_estale_retry(estale_retry++))
     86 			goto lookup;
     87 		return (set_errno(error));
     88 	}
     89 	return (0);
     90 }
     91 
     92 int
     93 fstatfs32(int32_t fdes, struct statfs32 *sbp, int32_t len, int32_t fstyp)
     94 {
     95 	struct file *fp;
     96 	int error;
     97 
     98 	if (fstyp != 0)
     99 		return (set_errno(EINVAL));
    100 	if ((fp = getf(fdes)) == NULL)
    101 		return (set_errno(EBADF));
    102 	error = cstatfs(fp->f_vnode->v_vfsp, sbp, len);
    103 	releasef(fdes);
    104 	if (error)
    105 		return (set_errno(error));
    106 	return (0);
    107 }
    108 
    109 /*
    110  * Common routine for fstatfs and statfs.
    111  */
    112 static int
    113 cstatfs(struct vfs *vfsp, struct statfs32 *sbp, int len)
    114 {
    115 	struct statfs32 sfs;
    116 	struct statvfs64 svfs;
    117 	int error, i;
    118 	char *cp, *cp2;
    119 	struct vfssw *vswp;
    120 
    121 	if (len < 0 || len > sizeof (struct statfs))
    122 		return (EINVAL);
    123 	if (error = VFS_STATVFS(vfsp, &svfs))
    124 		return (error);
    125 
    126 	if (svfs.f_blocks > UINT32_MAX || svfs.f_bfree > UINT32_MAX ||
    127 	    svfs.f_files > UINT32_MAX || svfs.f_ffree > UINT32_MAX)
    128 	    return (EOVERFLOW);
    129 	/*
    130 	 * Map statvfs fields into the old statfs structure.
    131 	 */
    132 	bzero(&sfs, sizeof (sfs));
    133 	sfs.f_bsize = svfs.f_bsize;
    134 	sfs.f_frsize = (svfs.f_frsize == svfs.f_bsize) ? 0 : svfs.f_frsize;
    135 	sfs.f_blocks = svfs.f_blocks * (svfs.f_frsize / 512);
    136 	sfs.f_bfree = svfs.f_bfree * (svfs.f_frsize / 512);
    137 	sfs.f_files = svfs.f_files;
    138 	sfs.f_ffree = svfs.f_ffree;
    139 
    140 	cp = svfs.f_fstr;
    141 	cp2 = sfs.f_fname;
    142 	i = 0;
    143 	while (i++ < sizeof (sfs.f_fname))
    144 		if (*cp != '\0')
    145 			*cp2++ = *cp++;
    146 		else
    147 			*cp2++ = '\0';
    148 	while (*cp != '\0' &&
    149 	    i++ < (sizeof (svfs.f_fstr) - sizeof (sfs.f_fpack)))
    150 		cp++;
    151 	(void) strncpy(sfs.f_fpack, cp + 1, sizeof (sfs.f_fpack));
    152 	if ((vswp = vfs_getvfssw(svfs.f_basetype)) == NULL)
    153 		sfs.f_fstyp = 0;
    154 	else {
    155 		sfs.f_fstyp = vswp - vfssw;
    156 		vfs_unrefvfssw(vswp);
    157 	}
    158 
    159 	if (copyout(&sfs, sbp, len))
    160 		return (EFAULT);
    161 
    162 	return (0);
    163 }
    164 
    165 #endif	/* _SYSCALL32_IMPL || _ILP32 */
    166