17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*dd29fa4aSprabahar * Common Development and Distribution License (the "License"). 6*dd29fa4aSprabahar * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*dd29fa4aSprabahar * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 277c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD 317c478bd9Sstevel@tonic-gate * under license from the Regents of the University of California. 327c478bd9Sstevel@tonic-gate */ 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate /* 377c478bd9Sstevel@tonic-gate * Get file attribute information through a file name or a file descriptor. 387c478bd9Sstevel@tonic-gate */ 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate #include <sys/param.h> 417c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h> 427c478bd9Sstevel@tonic-gate #include <sys/types.h> 437c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 447c478bd9Sstevel@tonic-gate #include <sys/cred.h> 457c478bd9Sstevel@tonic-gate #include <sys/systm.h> 467c478bd9Sstevel@tonic-gate #include <sys/errno.h> 477c478bd9Sstevel@tonic-gate #include <sys/fcntl.h> 487c478bd9Sstevel@tonic-gate #include <sys/pathname.h> 497c478bd9Sstevel@tonic-gate #include <sys/stat.h> 507c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 517c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 527c478bd9Sstevel@tonic-gate #include <sys/mode.h> 537c478bd9Sstevel@tonic-gate #include <sys/file.h> 547c478bd9Sstevel@tonic-gate #include <sys/proc.h> 557c478bd9Sstevel@tonic-gate #include <sys/uio.h> 567c478bd9Sstevel@tonic-gate #include <sys/debug.h> 577c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 587c478bd9Sstevel@tonic-gate #include <c2/audit.h> 59*dd29fa4aSprabahar #include <fs/fs_subr.h> 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate /* 627c478bd9Sstevel@tonic-gate * Get the vp to be stated and the cred to be used for the call 637c478bd9Sstevel@tonic-gate * to VOP_GETATTR 647c478bd9Sstevel@tonic-gate */ 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate /* 677c478bd9Sstevel@tonic-gate * nmflag has the following values 687c478bd9Sstevel@tonic-gate * 697c478bd9Sstevel@tonic-gate * 1 - Always do lookup. i.e. stat, lstat. 707c478bd9Sstevel@tonic-gate * 2 - Name is optional i.e. fstatat 717c478bd9Sstevel@tonic-gate * 0 - Don't lookup name, vp is in file_p. i.e. fstat 727c478bd9Sstevel@tonic-gate * 737c478bd9Sstevel@tonic-gate */ 747c478bd9Sstevel@tonic-gate static int 757c478bd9Sstevel@tonic-gate cstatat_getvp(int fd, char *name, int nmflag, 767c478bd9Sstevel@tonic-gate int follow, vnode_t **vp, cred_t **cred) 777c478bd9Sstevel@tonic-gate { 787c478bd9Sstevel@tonic-gate vnode_t *startvp; 797c478bd9Sstevel@tonic-gate file_t *fp; 807c478bd9Sstevel@tonic-gate int error; 817c478bd9Sstevel@tonic-gate cred_t *cr; 82*dd29fa4aSprabahar int estale_retry = 0; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate *vp = NULL; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate /* 877c478bd9Sstevel@tonic-gate * Only return EFAULT for fstatat when fd == AT_FDCWD && name == NULL 887c478bd9Sstevel@tonic-gate */ 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate if (fd == AT_FDCWD) { 917c478bd9Sstevel@tonic-gate if (name != NULL || nmflag != 2) { 927c478bd9Sstevel@tonic-gate startvp = NULL; 937c478bd9Sstevel@tonic-gate cr = CRED(); 947c478bd9Sstevel@tonic-gate crhold(cr); 957c478bd9Sstevel@tonic-gate } else 967c478bd9Sstevel@tonic-gate return (EFAULT); 977c478bd9Sstevel@tonic-gate } else { 987c478bd9Sstevel@tonic-gate char startchar; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate if (nmflag == 1 || (nmflag == 2 && name != NULL)) { 1017c478bd9Sstevel@tonic-gate if (copyin(name, &startchar, sizeof (char))) 1027c478bd9Sstevel@tonic-gate return (EFAULT); 1037c478bd9Sstevel@tonic-gate } else { 1047c478bd9Sstevel@tonic-gate startchar = '\0'; 1057c478bd9Sstevel@tonic-gate } 1067c478bd9Sstevel@tonic-gate if (startchar != '/' || nmflag == 0) { 1077c478bd9Sstevel@tonic-gate if ((fp = getf(fd)) == NULL) { 1087c478bd9Sstevel@tonic-gate return (EBADF); 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate startvp = fp->f_vnode; 1117c478bd9Sstevel@tonic-gate cr = fp->f_cred; 1127c478bd9Sstevel@tonic-gate crhold(cr); 1137c478bd9Sstevel@tonic-gate VN_HOLD(startvp); 1147c478bd9Sstevel@tonic-gate releasef(fd); 1157c478bd9Sstevel@tonic-gate } else { 1167c478bd9Sstevel@tonic-gate startvp = NULL; 1177c478bd9Sstevel@tonic-gate cr = CRED(); 1187c478bd9Sstevel@tonic-gate crhold(cr); 1197c478bd9Sstevel@tonic-gate } 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate *cred = cr; 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate #ifdef C2_AUDIT 1247c478bd9Sstevel@tonic-gate if (audit_active) 1257c478bd9Sstevel@tonic-gate audit_setfsat_path(1); 1267c478bd9Sstevel@tonic-gate #endif /* C2_AUDIT */ 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate if (nmflag == 1 || (nmflag == 2 && name != NULL)) { 1307c478bd9Sstevel@tonic-gate lookup: 1317c478bd9Sstevel@tonic-gate if (error = lookupnameat(name, UIO_USERSPACE, follow, NULLVPP, 1327c478bd9Sstevel@tonic-gate vp, startvp)) { 133*dd29fa4aSprabahar if ((error == ESTALE) && 134*dd29fa4aSprabahar fs_need_estale_retry(estale_retry++)) 1357c478bd9Sstevel@tonic-gate goto lookup; 1367c478bd9Sstevel@tonic-gate if (startvp != NULL) 1377c478bd9Sstevel@tonic-gate VN_RELE(startvp); 1387c478bd9Sstevel@tonic-gate crfree(cr); 1397c478bd9Sstevel@tonic-gate return (error); 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate if (startvp != NULL) 1427c478bd9Sstevel@tonic-gate VN_RELE(startvp); 1437c478bd9Sstevel@tonic-gate } else { 1447c478bd9Sstevel@tonic-gate *vp = startvp; 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate return (0); 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate /* 1517c478bd9Sstevel@tonic-gate * Native syscall interfaces: 1527c478bd9Sstevel@tonic-gate * 1537c478bd9Sstevel@tonic-gate * N-bit kernel, N-bit applications, N-bit file offsets 1547c478bd9Sstevel@tonic-gate */ 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate static int cstatat(int, char *, int, struct stat *, int, int); 1577c478bd9Sstevel@tonic-gate static int cstat(vnode_t *vp, struct stat *, int, cred_t *); 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate int 1607c478bd9Sstevel@tonic-gate stat(char *fname, struct stat *sb) 1617c478bd9Sstevel@tonic-gate { 1627c478bd9Sstevel@tonic-gate return (cstatat(AT_FDCWD, fname, 1, sb, 0, ATTR_REAL)); 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate int 1667c478bd9Sstevel@tonic-gate lstat(char *fname, struct stat *sb) 1677c478bd9Sstevel@tonic-gate { 1687c478bd9Sstevel@tonic-gate return (cstatat(AT_FDCWD, fname, 1, sb, AT_SYMLINK_NOFOLLOW, 0)); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate /* 1727c478bd9Sstevel@tonic-gate * fstat can and should be fast, do an inline implementation here. 1737c478bd9Sstevel@tonic-gate */ 1747c478bd9Sstevel@tonic-gate #define FSTAT_BODY(fd, sb, statfn) \ 1757c478bd9Sstevel@tonic-gate { \ 1767c478bd9Sstevel@tonic-gate file_t *fp; \ 1777c478bd9Sstevel@tonic-gate int error; \ 1787c478bd9Sstevel@tonic-gate \ 1797c478bd9Sstevel@tonic-gate if ((fp = getf(fd)) == NULL) \ 1807c478bd9Sstevel@tonic-gate return (set_errno(EBADF)); \ 1817c478bd9Sstevel@tonic-gate if (audit_active) \ 1827c478bd9Sstevel@tonic-gate audit_setfsat_path(1); \ 1837c478bd9Sstevel@tonic-gate error = statfn(fp->f_vnode, sb, 0, fp->f_cred); \ 1847c478bd9Sstevel@tonic-gate releasef(fd); \ 1857c478bd9Sstevel@tonic-gate if (error) \ 1867c478bd9Sstevel@tonic-gate return (set_errno(error)); \ 1877c478bd9Sstevel@tonic-gate return (0); \ 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate int 1917c478bd9Sstevel@tonic-gate fstat(int fd, struct stat *sb) 1927c478bd9Sstevel@tonic-gate { 1937c478bd9Sstevel@tonic-gate FSTAT_BODY(fd, sb, cstat) 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate int 1977c478bd9Sstevel@tonic-gate fstatat(int fd, char *name, struct stat *sb, int flags) 1987c478bd9Sstevel@tonic-gate { 1997c478bd9Sstevel@tonic-gate return (cstatat(fd, name, 2, sb, flags, 0)); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__i386_COMPAT) 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate /* 2057c478bd9Sstevel@tonic-gate * Handle all the "extended" stat operations in the same way; 2067c478bd9Sstevel@tonic-gate * validate the version, then call the real handler. 2077c478bd9Sstevel@tonic-gate */ 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate #define XSTAT_BODY(ver, f, s, fn) \ 2107c478bd9Sstevel@tonic-gate return (ver != _STAT_VER ? set_errno(EINVAL) : fn(f, s)); 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate #endif /* __i386 || __i386_COMPAT */ 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate #if defined(__i386) 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate /* 2177c478bd9Sstevel@tonic-gate * Syscalls for i386 applications that issue {,l,f}xstat() directly 2187c478bd9Sstevel@tonic-gate */ 2197c478bd9Sstevel@tonic-gate int 2207c478bd9Sstevel@tonic-gate xstat(int version, char *fname, struct stat *sb) 2217c478bd9Sstevel@tonic-gate { 2227c478bd9Sstevel@tonic-gate XSTAT_BODY(version, fname, sb, stat) 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate int 2267c478bd9Sstevel@tonic-gate lxstat(int version, char *fname, struct stat *sb) 2277c478bd9Sstevel@tonic-gate { 2287c478bd9Sstevel@tonic-gate XSTAT_BODY(version, fname, sb, lstat) 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate int 2327c478bd9Sstevel@tonic-gate fxstat(int version, int fd, struct stat *sb) 2337c478bd9Sstevel@tonic-gate { 2347c478bd9Sstevel@tonic-gate XSTAT_BODY(version, fd, sb, fstat) 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate #endif /* __i386 */ 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate /* 2407c478bd9Sstevel@tonic-gate * Common code for stat(), lstat(), and fstat(). 2417c478bd9Sstevel@tonic-gate * (32-bit kernel, 32-bit applications, 32-bit files) 2427c478bd9Sstevel@tonic-gate * (64-bit kernel, 64-bit applications, 64-bit files) 2437c478bd9Sstevel@tonic-gate */ 2447c478bd9Sstevel@tonic-gate static int 2457c478bd9Sstevel@tonic-gate cstat(vnode_t *vp, struct stat *ubp, int flag, cred_t *cr) 2467c478bd9Sstevel@tonic-gate { 2477c478bd9Sstevel@tonic-gate struct vfssw *vswp; 2487c478bd9Sstevel@tonic-gate struct stat sb; 2497c478bd9Sstevel@tonic-gate vattr_t vattr; 2507c478bd9Sstevel@tonic-gate int error; 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate vattr.va_mask = AT_STAT | AT_NBLOCKS | AT_BLKSIZE | AT_SIZE; 2537c478bd9Sstevel@tonic-gate if ((error = VOP_GETATTR(vp, &vattr, flag, cr)) != 0) 2547c478bd9Sstevel@tonic-gate return (error); 2557c478bd9Sstevel@tonic-gate #ifdef _ILP32 2567c478bd9Sstevel@tonic-gate /* 2577c478bd9Sstevel@tonic-gate * (32-bit kernel, 32-bit applications, 32-bit files) 2587c478bd9Sstevel@tonic-gate * NOTE: 32-bit kernel maintains a 64-bit unsigend va_size. 2597c478bd9Sstevel@tonic-gate * 2607c478bd9Sstevel@tonic-gate * st_size of devices (VBLK and VCHR special files) is a special case. 2617c478bd9Sstevel@tonic-gate * POSIX does not define size behavior for special files, so the 2627c478bd9Sstevel@tonic-gate * following Solaris specific behavior is not a violation. Solaris 2637c478bd9Sstevel@tonic-gate * returns the size of the device. 2647c478bd9Sstevel@tonic-gate * 2657c478bd9Sstevel@tonic-gate * For compatibility with 32-bit programs which happen to do stat() on 2667c478bd9Sstevel@tonic-gate * a (mknod) bigger than 2GB we suppress the large file EOVERFLOW and 2677c478bd9Sstevel@tonic-gate * instead we return the value MAXOFF32_T (LONG_MAX). 2687c478bd9Sstevel@tonic-gate * 2697c478bd9Sstevel@tonic-gate * 32-bit applications that care about the size of devices should be 2707c478bd9Sstevel@tonic-gate * built 64-bit or use a large file interface (lfcompile(5) or lf64(5)). 2717c478bd9Sstevel@tonic-gate */ 2727c478bd9Sstevel@tonic-gate if ((vattr.va_size > MAXOFF32_T) && 2737c478bd9Sstevel@tonic-gate ((vp->v_type == VBLK) || (vp->v_type == VCHR))) { 2747c478bd9Sstevel@tonic-gate /* OVERFLOW | UNKNOWN_SIZE */ 2757c478bd9Sstevel@tonic-gate vattr.va_size = MAXOFF32_T; 2767c478bd9Sstevel@tonic-gate } 2777c478bd9Sstevel@tonic-gate #endif /* _ILP32 */ 2787c478bd9Sstevel@tonic-gate if (vattr.va_size > MAXOFF_T || vattr.va_nblocks > LONG_MAX || 2797c478bd9Sstevel@tonic-gate vattr.va_nodeid > ULONG_MAX) 2807c478bd9Sstevel@tonic-gate return (EOVERFLOW); 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate bzero(&sb, sizeof (sb)); 2837c478bd9Sstevel@tonic-gate sb.st_dev = vattr.va_fsid; 2847c478bd9Sstevel@tonic-gate sb.st_ino = (ino_t)vattr.va_nodeid; 2857c478bd9Sstevel@tonic-gate sb.st_mode = VTTOIF(vattr.va_type) | vattr.va_mode; 2867c478bd9Sstevel@tonic-gate sb.st_nlink = vattr.va_nlink; 2877c478bd9Sstevel@tonic-gate sb.st_uid = vattr.va_uid; 2887c478bd9Sstevel@tonic-gate sb.st_gid = vattr.va_gid; 2897c478bd9Sstevel@tonic-gate sb.st_rdev = vattr.va_rdev; 2907c478bd9Sstevel@tonic-gate sb.st_size = (off_t)vattr.va_size; 2917c478bd9Sstevel@tonic-gate sb.st_atim = vattr.va_atime; 2927c478bd9Sstevel@tonic-gate sb.st_mtim = vattr.va_mtime; 2937c478bd9Sstevel@tonic-gate sb.st_ctim = vattr.va_ctime; 2947c478bd9Sstevel@tonic-gate sb.st_blksize = vattr.va_blksize; 2957c478bd9Sstevel@tonic-gate sb.st_blocks = (blkcnt_t)vattr.va_nblocks; 2967c478bd9Sstevel@tonic-gate if (vp->v_vfsp != NULL) { 2977c478bd9Sstevel@tonic-gate vswp = &vfssw[vp->v_vfsp->vfs_fstype]; 2987c478bd9Sstevel@tonic-gate if (vswp->vsw_name && *vswp->vsw_name) 2997c478bd9Sstevel@tonic-gate (void) strcpy(sb.st_fstype, vswp->vsw_name); 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate if (copyout(&sb, ubp, sizeof (sb))) 3027c478bd9Sstevel@tonic-gate return (EFAULT); 3037c478bd9Sstevel@tonic-gate return (0); 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate static int 3077c478bd9Sstevel@tonic-gate cstatat(int fd, char *name, int nmflag, struct stat *sb, int follow, int flags) 3087c478bd9Sstevel@tonic-gate { 3097c478bd9Sstevel@tonic-gate vnode_t *vp; 3107c478bd9Sstevel@tonic-gate int error; 3117c478bd9Sstevel@tonic-gate cred_t *cred; 3127c478bd9Sstevel@tonic-gate int link_follow; 313*dd29fa4aSprabahar int estale_retry = 0; 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate link_follow = (follow == AT_SYMLINK_NOFOLLOW) ? NO_FOLLOW : FOLLOW; 3167c478bd9Sstevel@tonic-gate lookup: 3177c478bd9Sstevel@tonic-gate if (error = cstatat_getvp(fd, name, nmflag, link_follow, &vp, &cred)) 3187c478bd9Sstevel@tonic-gate return (set_errno(error)); 3197c478bd9Sstevel@tonic-gate error = cstat(vp, sb, flags, cred); 3207c478bd9Sstevel@tonic-gate crfree(cred); 3217c478bd9Sstevel@tonic-gate VN_RELE(vp); 3227c478bd9Sstevel@tonic-gate out: 3237c478bd9Sstevel@tonic-gate if (error != 0) { 3247c478bd9Sstevel@tonic-gate if (error == ESTALE && 325*dd29fa4aSprabahar fs_need_estale_retry(estale_retry++) && 3267c478bd9Sstevel@tonic-gate (nmflag == 1 || (nmflag == 2 && name != NULL))) 3277c478bd9Sstevel@tonic-gate goto lookup; 3287c478bd9Sstevel@tonic-gate return (set_errno(error)); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate return (0); 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL) 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate /* 3367c478bd9Sstevel@tonic-gate * 64-bit kernel, 32-bit applications, 32-bit file offsets 3377c478bd9Sstevel@tonic-gate */ 3387c478bd9Sstevel@tonic-gate static int cstatat32(int, char *, int, struct stat32 *, int, int); 3397c478bd9Sstevel@tonic-gate static int cstat32(vnode_t *, struct stat32 *, int, cred_t *); 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate int 3427c478bd9Sstevel@tonic-gate stat32(char *fname, struct stat32 *sb) 3437c478bd9Sstevel@tonic-gate { 3447c478bd9Sstevel@tonic-gate return (cstatat32(AT_FDCWD, fname, 1, sb, 0, ATTR_REAL)); 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate int 3487c478bd9Sstevel@tonic-gate lstat32(char *fname, struct stat32 *sb) 3497c478bd9Sstevel@tonic-gate { 3507c478bd9Sstevel@tonic-gate return (cstatat32(AT_FDCWD, fname, 1, sb, AT_SYMLINK_NOFOLLOW, 0)); 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate int 3547c478bd9Sstevel@tonic-gate fstat32(int fd, struct stat32 *sb) 3557c478bd9Sstevel@tonic-gate { 3567c478bd9Sstevel@tonic-gate FSTAT_BODY(fd, sb, cstat32) 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate int 3607c478bd9Sstevel@tonic-gate fstatat32(int fd, char *name, struct stat32 *sb, int flag) 3617c478bd9Sstevel@tonic-gate { 3627c478bd9Sstevel@tonic-gate return (cstatat32(fd, name, 2, sb, flag, 0)); 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate #if defined(__i386_COMPAT) 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate /* 3687c478bd9Sstevel@tonic-gate * Syscalls for i386 applications that issue {,l,f}xstat() directly 3697c478bd9Sstevel@tonic-gate */ 3707c478bd9Sstevel@tonic-gate int 3717c478bd9Sstevel@tonic-gate xstat32(int version, char *fname, struct stat32 *sb) 3727c478bd9Sstevel@tonic-gate { 3737c478bd9Sstevel@tonic-gate XSTAT_BODY(version, fname, sb, stat32) 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate int 3777c478bd9Sstevel@tonic-gate lxstat32(int version, char *fname, struct stat32 *sb) 3787c478bd9Sstevel@tonic-gate { 3797c478bd9Sstevel@tonic-gate XSTAT_BODY(version, fname, sb, lstat32) 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate int 3837c478bd9Sstevel@tonic-gate fxstat32(int version, int fd, struct stat32 *sb) 3847c478bd9Sstevel@tonic-gate { 3857c478bd9Sstevel@tonic-gate XSTAT_BODY(version, fd, sb, fstat32) 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate #endif /* __i386_COMPAT */ 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate static int 3917c478bd9Sstevel@tonic-gate cstat32(vnode_t *vp, struct stat32 *ubp, int flag, struct cred *cr) 3927c478bd9Sstevel@tonic-gate { 3937c478bd9Sstevel@tonic-gate struct vfssw *vswp; 3947c478bd9Sstevel@tonic-gate struct stat32 sb; 3957c478bd9Sstevel@tonic-gate vattr_t vattr; 3967c478bd9Sstevel@tonic-gate int error; 3977c478bd9Sstevel@tonic-gate dev32_t st_dev, st_rdev; 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate vattr.va_mask = AT_STAT | AT_NBLOCKS | AT_BLKSIZE | AT_SIZE; 4007c478bd9Sstevel@tonic-gate if (error = VOP_GETATTR(vp, &vattr, flag, cr)) 4017c478bd9Sstevel@tonic-gate return (error); 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate /* devices are a special case, see comments in cstat */ 4047c478bd9Sstevel@tonic-gate if ((vattr.va_size > MAXOFF32_T) && 4057c478bd9Sstevel@tonic-gate ((vp->v_type == VBLK) || (vp->v_type == VCHR))) { 4067c478bd9Sstevel@tonic-gate /* OVERFLOW | UNKNOWN_SIZE */ 4077c478bd9Sstevel@tonic-gate vattr.va_size = MAXOFF32_T; 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate /* check for large values */ 4117c478bd9Sstevel@tonic-gate if (!cmpldev(&st_dev, vattr.va_fsid) || 4127c478bd9Sstevel@tonic-gate !cmpldev(&st_rdev, vattr.va_rdev) || 4137c478bd9Sstevel@tonic-gate vattr.va_size > MAXOFF32_T || 4147c478bd9Sstevel@tonic-gate vattr.va_nblocks > INT32_MAX || 4157c478bd9Sstevel@tonic-gate vattr.va_nodeid > UINT32_MAX || 4167c478bd9Sstevel@tonic-gate TIMESPEC_OVERFLOW(&(vattr.va_atime)) || 4177c478bd9Sstevel@tonic-gate TIMESPEC_OVERFLOW(&(vattr.va_mtime)) || 4187c478bd9Sstevel@tonic-gate TIMESPEC_OVERFLOW(&(vattr.va_ctime))) 4197c478bd9Sstevel@tonic-gate return (EOVERFLOW); 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate bzero(&sb, sizeof (sb)); 4227c478bd9Sstevel@tonic-gate sb.st_dev = st_dev; 4237c478bd9Sstevel@tonic-gate sb.st_ino = (ino32_t)vattr.va_nodeid; 4247c478bd9Sstevel@tonic-gate sb.st_mode = VTTOIF(vattr.va_type) | vattr.va_mode; 4257c478bd9Sstevel@tonic-gate sb.st_nlink = vattr.va_nlink; 4267c478bd9Sstevel@tonic-gate sb.st_uid = vattr.va_uid; 4277c478bd9Sstevel@tonic-gate sb.st_gid = vattr.va_gid; 4287c478bd9Sstevel@tonic-gate sb.st_rdev = st_rdev; 4297c478bd9Sstevel@tonic-gate sb.st_size = (off32_t)vattr.va_size; 4307c478bd9Sstevel@tonic-gate TIMESPEC_TO_TIMESPEC32(&(sb.st_atim), &(vattr.va_atime)); 4317c478bd9Sstevel@tonic-gate TIMESPEC_TO_TIMESPEC32(&(sb.st_mtim), &(vattr.va_mtime)); 4327c478bd9Sstevel@tonic-gate TIMESPEC_TO_TIMESPEC32(&(sb.st_ctim), &(vattr.va_ctime)); 4337c478bd9Sstevel@tonic-gate sb.st_blksize = vattr.va_blksize; 4347c478bd9Sstevel@tonic-gate sb.st_blocks = (blkcnt32_t)vattr.va_nblocks; 4357c478bd9Sstevel@tonic-gate if (vp->v_vfsp != NULL) { 4367c478bd9Sstevel@tonic-gate vswp = &vfssw[vp->v_vfsp->vfs_fstype]; 4377c478bd9Sstevel@tonic-gate if (vswp->vsw_name && *vswp->vsw_name) 4387c478bd9Sstevel@tonic-gate (void) strcpy(sb.st_fstype, vswp->vsw_name); 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate if (copyout(&sb, ubp, sizeof (sb))) 4417c478bd9Sstevel@tonic-gate return (EFAULT); 4427c478bd9Sstevel@tonic-gate return (0); 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate static int 4467c478bd9Sstevel@tonic-gate cstatat32(int fd, char *name, int nmflag, struct stat32 *sb, 4477c478bd9Sstevel@tonic-gate int follow, int flags) 4487c478bd9Sstevel@tonic-gate { 4497c478bd9Sstevel@tonic-gate vnode_t *vp; 4507c478bd9Sstevel@tonic-gate int error; 4517c478bd9Sstevel@tonic-gate cred_t *cred; 4527c478bd9Sstevel@tonic-gate int link_follow; 453*dd29fa4aSprabahar int estale_retry = 0; 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate link_follow = (follow == AT_SYMLINK_NOFOLLOW) ? NO_FOLLOW : FOLLOW; 4567c478bd9Sstevel@tonic-gate lookup: 4577c478bd9Sstevel@tonic-gate if (error = cstatat_getvp(fd, name, nmflag, link_follow, &vp, &cred)) 4587c478bd9Sstevel@tonic-gate return (set_errno(error)); 4597c478bd9Sstevel@tonic-gate error = cstat32(vp, sb, flags, cred); 4607c478bd9Sstevel@tonic-gate crfree(cred); 4617c478bd9Sstevel@tonic-gate VN_RELE(vp); 4627c478bd9Sstevel@tonic-gate out: 4637c478bd9Sstevel@tonic-gate if (error != 0) { 4647c478bd9Sstevel@tonic-gate if (error == ESTALE && 465*dd29fa4aSprabahar fs_need_estale_retry(estale_retry++) && 4667c478bd9Sstevel@tonic-gate (nmflag == 1 || (nmflag == 2 && name != NULL))) 4677c478bd9Sstevel@tonic-gate goto lookup; 4687c478bd9Sstevel@tonic-gate return (set_errno(error)); 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate return (0); 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate #if defined(_ILP32) 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate /* 4787c478bd9Sstevel@tonic-gate * 32-bit kernel, 32-bit applications, 64-bit file offsets. 4797c478bd9Sstevel@tonic-gate * 4807c478bd9Sstevel@tonic-gate * These routines are implemented differently on 64-bit kernels. 4817c478bd9Sstevel@tonic-gate */ 4827c478bd9Sstevel@tonic-gate static int cstatat64(int, char *, int, struct stat64 *, int, int); 4837c478bd9Sstevel@tonic-gate static int cstat64(vnode_t *, struct stat64 *, int, cred_t *); 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate int 4867c478bd9Sstevel@tonic-gate stat64(char *fname, struct stat64 *sb) 4877c478bd9Sstevel@tonic-gate { 4887c478bd9Sstevel@tonic-gate return (cstatat64(AT_FDCWD, fname, 1, sb, 0, ATTR_REAL)); 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate int 4927c478bd9Sstevel@tonic-gate lstat64(char *fname, struct stat64 *sb) 4937c478bd9Sstevel@tonic-gate { 4947c478bd9Sstevel@tonic-gate return (cstatat64(AT_FDCWD, fname, 1, sb, AT_SYMLINK_NOFOLLOW, 0)); 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate int 4987c478bd9Sstevel@tonic-gate fstat64(int fd, struct stat64 *sb) 4997c478bd9Sstevel@tonic-gate { 5007c478bd9Sstevel@tonic-gate FSTAT_BODY(fd, sb, cstat64) 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate int 5047c478bd9Sstevel@tonic-gate fstatat64(int fd, char *name, struct stat64 *sb, int flags) 5057c478bd9Sstevel@tonic-gate { 5067c478bd9Sstevel@tonic-gate return (cstatat64(fd, name, 2, sb, flags, 0)); 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate static int 5107c478bd9Sstevel@tonic-gate cstat64(vnode_t *vp, struct stat64 *ubp, int flag, cred_t *cr) 5117c478bd9Sstevel@tonic-gate { 5127c478bd9Sstevel@tonic-gate struct vfssw *vswp; 5137c478bd9Sstevel@tonic-gate struct stat64 lsb; 5147c478bd9Sstevel@tonic-gate vattr_t vattr; 5157c478bd9Sstevel@tonic-gate int error; 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate vattr.va_mask = AT_STAT | AT_NBLOCKS | AT_BLKSIZE | AT_SIZE; 5187c478bd9Sstevel@tonic-gate if (error = VOP_GETATTR(vp, &vattr, flag, cr)) 5197c478bd9Sstevel@tonic-gate return (error); 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate bzero(&lsb, sizeof (lsb)); 5227c478bd9Sstevel@tonic-gate lsb.st_dev = vattr.va_fsid; 5237c478bd9Sstevel@tonic-gate lsb.st_ino = vattr.va_nodeid; 5247c478bd9Sstevel@tonic-gate lsb.st_mode = VTTOIF(vattr.va_type) | vattr.va_mode; 5257c478bd9Sstevel@tonic-gate lsb.st_nlink = vattr.va_nlink; 5267c478bd9Sstevel@tonic-gate lsb.st_uid = vattr.va_uid; 5277c478bd9Sstevel@tonic-gate lsb.st_gid = vattr.va_gid; 5287c478bd9Sstevel@tonic-gate lsb.st_rdev = vattr.va_rdev; 5297c478bd9Sstevel@tonic-gate lsb.st_size = vattr.va_size; 5307c478bd9Sstevel@tonic-gate lsb.st_atim = vattr.va_atime; 5317c478bd9Sstevel@tonic-gate lsb.st_mtim = vattr.va_mtime; 5327c478bd9Sstevel@tonic-gate lsb.st_ctim = vattr.va_ctime; 5337c478bd9Sstevel@tonic-gate lsb.st_blksize = vattr.va_blksize; 5347c478bd9Sstevel@tonic-gate lsb.st_blocks = vattr.va_nblocks; 5357c478bd9Sstevel@tonic-gate if (vp->v_vfsp != NULL) { 5367c478bd9Sstevel@tonic-gate vswp = &vfssw[vp->v_vfsp->vfs_fstype]; 5377c478bd9Sstevel@tonic-gate if (vswp->vsw_name && *vswp->vsw_name) 5387c478bd9Sstevel@tonic-gate (void) strcpy(lsb.st_fstype, vswp->vsw_name); 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate if (copyout(&lsb, ubp, sizeof (lsb))) 5417c478bd9Sstevel@tonic-gate return (EFAULT); 5427c478bd9Sstevel@tonic-gate return (0); 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate static int 5467c478bd9Sstevel@tonic-gate cstatat64(int fd, char *name, int nmflag, struct stat64 *sb, 5477c478bd9Sstevel@tonic-gate int follow, int flags) 5487c478bd9Sstevel@tonic-gate { 5497c478bd9Sstevel@tonic-gate vnode_t *vp; 5507c478bd9Sstevel@tonic-gate int error; 5517c478bd9Sstevel@tonic-gate cred_t *cred; 5527c478bd9Sstevel@tonic-gate int link_follow; 553*dd29fa4aSprabahar int estale_retry = 0; 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate link_follow = (follow == AT_SYMLINK_NOFOLLOW) ? NO_FOLLOW : FOLLOW; 5567c478bd9Sstevel@tonic-gate lookup: 5577c478bd9Sstevel@tonic-gate if (error = cstatat_getvp(fd, name, nmflag, link_follow, &vp, &cred)) 5587c478bd9Sstevel@tonic-gate return (set_errno(error)); 5597c478bd9Sstevel@tonic-gate error = cstat64(vp, sb, flags, cred); 5607c478bd9Sstevel@tonic-gate crfree(cred); 5617c478bd9Sstevel@tonic-gate VN_RELE(vp); 5627c478bd9Sstevel@tonic-gate out: 5637c478bd9Sstevel@tonic-gate if (error != 0) { 5647c478bd9Sstevel@tonic-gate if (error == ESTALE && 565*dd29fa4aSprabahar fs_need_estale_retry(estale_retry++) && 5667c478bd9Sstevel@tonic-gate (nmflag == 1 || (nmflag == 2 && name != NULL))) 5677c478bd9Sstevel@tonic-gate goto lookup; 5687c478bd9Sstevel@tonic-gate return (set_errno(error)); 5697c478bd9Sstevel@tonic-gate } 5707c478bd9Sstevel@tonic-gate return (0); 5717c478bd9Sstevel@tonic-gate } 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate #endif /* _ILP32 */ 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL) 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate /* 5787c478bd9Sstevel@tonic-gate * 64-bit kernel, 32-bit applications, 64-bit file offsets. 5797c478bd9Sstevel@tonic-gate * 5807c478bd9Sstevel@tonic-gate * We'd really like to call the "native" stat calls for these ones, 5817c478bd9Sstevel@tonic-gate * but the problem is that the 64-bit ABI defines the 'stat64' structure 5827c478bd9Sstevel@tonic-gate * differently from the way the 32-bit ABI defines it. 5837c478bd9Sstevel@tonic-gate */ 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate static int cstatat64_32(int, char *, int, struct stat64_32 *, int, int); 5867c478bd9Sstevel@tonic-gate static int cstat64_32(vnode_t *, struct stat64_32 *, int, cred_t *); 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate int 5897c478bd9Sstevel@tonic-gate stat64_32(char *fname, struct stat64_32 *sb) 5907c478bd9Sstevel@tonic-gate { 5917c478bd9Sstevel@tonic-gate return (cstatat64_32(AT_FDCWD, fname, 1, sb, 0, ATTR_REAL)); 5927c478bd9Sstevel@tonic-gate } 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate int 5957c478bd9Sstevel@tonic-gate lstat64_32(char *fname, struct stat64_32 *sb) 5967c478bd9Sstevel@tonic-gate { 5977c478bd9Sstevel@tonic-gate return (cstatat64_32(AT_FDCWD, fname, 1, sb, AT_SYMLINK_NOFOLLOW, 0)); 5987c478bd9Sstevel@tonic-gate } 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate int 6017c478bd9Sstevel@tonic-gate fstat64_32(int fd, struct stat64_32 *sb) 6027c478bd9Sstevel@tonic-gate { 6037c478bd9Sstevel@tonic-gate FSTAT_BODY(fd, sb, cstat64_32) 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate int 6077c478bd9Sstevel@tonic-gate fstatat64_32(int fd, char *name, struct stat64_32 *sb, int flag) 6087c478bd9Sstevel@tonic-gate { 6097c478bd9Sstevel@tonic-gate return (cstatat64_32(fd, name, 2, sb, flag, 0)); 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate static int 6137c478bd9Sstevel@tonic-gate cstat64_32(vnode_t *vp, struct stat64_32 *ubp, int flag, cred_t *cr) 6147c478bd9Sstevel@tonic-gate { 6157c478bd9Sstevel@tonic-gate struct vfssw *vswp; 6167c478bd9Sstevel@tonic-gate struct stat64_32 lsb; 6177c478bd9Sstevel@tonic-gate vattr_t vattr; 6187c478bd9Sstevel@tonic-gate int error; 6197c478bd9Sstevel@tonic-gate dev32_t st_dev, st_rdev; 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate vattr.va_mask = AT_STAT | AT_NBLOCKS | AT_BLKSIZE | AT_SIZE; 6227c478bd9Sstevel@tonic-gate if (error = VOP_GETATTR(vp, &vattr, flag, cr)) 6237c478bd9Sstevel@tonic-gate return (error); 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate if (!cmpldev(&st_dev, vattr.va_fsid) || 6267c478bd9Sstevel@tonic-gate !cmpldev(&st_rdev, vattr.va_rdev) || 6277c478bd9Sstevel@tonic-gate TIMESPEC_OVERFLOW(&(vattr.va_atime)) || 6287c478bd9Sstevel@tonic-gate TIMESPEC_OVERFLOW(&(vattr.va_mtime)) || 6297c478bd9Sstevel@tonic-gate TIMESPEC_OVERFLOW(&(vattr.va_ctime))) 6307c478bd9Sstevel@tonic-gate return (EOVERFLOW); 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate bzero(&lsb, sizeof (lsb)); 6337c478bd9Sstevel@tonic-gate lsb.st_dev = st_dev; 6347c478bd9Sstevel@tonic-gate lsb.st_ino = vattr.va_nodeid; 6357c478bd9Sstevel@tonic-gate lsb.st_mode = VTTOIF(vattr.va_type) | vattr.va_mode; 6367c478bd9Sstevel@tonic-gate lsb.st_nlink = vattr.va_nlink; 6377c478bd9Sstevel@tonic-gate lsb.st_uid = vattr.va_uid; 6387c478bd9Sstevel@tonic-gate lsb.st_gid = vattr.va_gid; 6397c478bd9Sstevel@tonic-gate lsb.st_rdev = st_rdev; 6407c478bd9Sstevel@tonic-gate lsb.st_size = vattr.va_size; 6417c478bd9Sstevel@tonic-gate TIMESPEC_TO_TIMESPEC32(&(lsb.st_atim), &(vattr.va_atime)); 6427c478bd9Sstevel@tonic-gate TIMESPEC_TO_TIMESPEC32(&(lsb.st_mtim), &(vattr.va_mtime)); 6437c478bd9Sstevel@tonic-gate TIMESPEC_TO_TIMESPEC32(&(lsb.st_ctim), &(vattr.va_ctime)); 6447c478bd9Sstevel@tonic-gate lsb.st_blksize = vattr.va_blksize; 6457c478bd9Sstevel@tonic-gate lsb.st_blocks = vattr.va_nblocks; 6467c478bd9Sstevel@tonic-gate if (vp->v_vfsp != NULL) { 6477c478bd9Sstevel@tonic-gate vswp = &vfssw[vp->v_vfsp->vfs_fstype]; 6487c478bd9Sstevel@tonic-gate if (vswp->vsw_name && *vswp->vsw_name) 6497c478bd9Sstevel@tonic-gate (void) strcpy(lsb.st_fstype, vswp->vsw_name); 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate if (copyout(&lsb, ubp, sizeof (lsb))) 6527c478bd9Sstevel@tonic-gate return (EFAULT); 6537c478bd9Sstevel@tonic-gate return (0); 6547c478bd9Sstevel@tonic-gate } 6557c478bd9Sstevel@tonic-gate 6567c478bd9Sstevel@tonic-gate static int 6577c478bd9Sstevel@tonic-gate cstatat64_32(int fd, char *name, int nmflag, struct stat64_32 *sb, 6587c478bd9Sstevel@tonic-gate int follow, int flags) 6597c478bd9Sstevel@tonic-gate { 6607c478bd9Sstevel@tonic-gate vnode_t *vp; 6617c478bd9Sstevel@tonic-gate int error; 6627c478bd9Sstevel@tonic-gate cred_t *cred; 6637c478bd9Sstevel@tonic-gate int link_follow; 664*dd29fa4aSprabahar int estale_retry = 0; 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate link_follow = (follow == AT_SYMLINK_NOFOLLOW) ? NO_FOLLOW : FOLLOW; 6677c478bd9Sstevel@tonic-gate lookup: 6687c478bd9Sstevel@tonic-gate if (error = cstatat_getvp(fd, name, nmflag, link_follow, &vp, &cred)) 6697c478bd9Sstevel@tonic-gate return (set_errno(error)); 6707c478bd9Sstevel@tonic-gate error = cstat64_32(vp, sb, flags, cred); 6717c478bd9Sstevel@tonic-gate crfree(cred); 6727c478bd9Sstevel@tonic-gate VN_RELE(vp); 6737c478bd9Sstevel@tonic-gate out: 6747c478bd9Sstevel@tonic-gate if (error != 0) { 6757c478bd9Sstevel@tonic-gate if (error == ESTALE && 676*dd29fa4aSprabahar fs_need_estale_retry(estale_retry++) && 6777c478bd9Sstevel@tonic-gate (nmflag == 1 || (nmflag == 2 && name != NULL))) 6787c478bd9Sstevel@tonic-gate goto lookup; 6797c478bd9Sstevel@tonic-gate return (set_errno(error)); 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate return (0); 6827c478bd9Sstevel@tonic-gate } 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 685