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 /*
  23  * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
  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 /*
  35  * Get file attribute information through a file name or a file descriptor.
  36  */
  37 
  38 #include <sys/param.h>
  39 #include <sys/isa_defs.h>
  40 #include <sys/types.h>
  41 #include <sys/sysmacros.h>
  42 #include <sys/cred.h>
  43 #include <sys/systm.h>
  44 #include <sys/errno.h>
  45 #include <sys/fcntl.h>
  46 #include <sys/pathname.h>
  47 #include <sys/stat.h>
  48 #include <sys/vfs.h>
  49 #include <sys/vnode.h>
  50 #include <sys/mode.h>
  51 #include <sys/file.h>
  52 #include <sys/proc.h>
  53 #include <sys/uio.h>
  54 #include <sys/debug.h>
  55 #include <sys/cmn_err.h>
  56 #include <c2/audit.h>
  57 #include <fs/fs_subr.h>
  58 
  59 /*
  60  * Get the vp to be stated and the cred to be used for the call
  61  * to VOP_GETATTR
  62  */
  63 
  64 int
  65 cstatat_getvp(int fd, char *name, int follow, vnode_t **vp, cred_t **cred)
  66 {
  67         vnode_t *startvp;
  68         file_t *fp;
  69         int error;
  70         cred_t *cr;
  71         int estale_retry = 0;
  72 
  73         *vp = NULL;
  74 
  75         /*
  76          * Only return EFAULT for fstatat when fd == AT_FDCWD && name == NULL
  77          */
  78 
  79         if (fd == AT_FDCWD) {
  80                 startvp = NULL;
  81                 cr = CRED();
  82                 crhold(cr);
  83         } else {
  84                 char startchar;
  85 
  86                 if (copyin(name, &startchar, sizeof (char)))
  87                         return (EFAULT);
  88                 if (startchar != '/') {
  89                         if ((fp = getf(fd)) == NULL) {
  90                                 return (EBADF);
  91                         }
  92                         startvp = fp->f_vnode;
  93                         cr = fp->f_cred;
  94                         crhold(cr);
  95                         VN_HOLD(startvp);
  96                         releasef(fd);
  97                 } else {
  98                         startvp = NULL;
  99                         cr = CRED();
 100                         crhold(cr);
 101                 }
 102         }
 103         *cred = cr;
 104 
 105         if (AU_AUDITING() && startvp != NULL)
 106                 audit_setfsat_path(1);
 107 
 108 lookup:
 109         if (error = lookupnameat(name, UIO_USERSPACE, follow, NULLVPP,
 110             vp, startvp)) {
 111                 if ((error == ESTALE) &&
 112                     fs_need_estale_retry(estale_retry++))
 113                         goto lookup;
 114                 if (startvp != NULL)
 115                         VN_RELE(startvp);
 116                 crfree(cr);
 117                 return (error);
 118         }
 119         if (startvp != NULL)
 120                 VN_RELE(startvp);
 121 
 122         return (0);
 123 }
 124 
 125 /*
 126  * Native syscall interfaces:
 127  *
 128  * N-bit kernel, N-bit applications, N-bit file offsets
 129  */
 130 
 131 static int cstatat(int, char *, struct stat *, int, int);
 132 static int cstat(vnode_t *vp, struct stat *, int, cred_t *);
 133 
 134 /*
 135  * fstat can and should be fast, do an inline implementation here.
 136  */
 137 #define FSTAT_BODY(fd, sb, statfn)                              \
 138         {                                                       \
 139                 file_t *fp;                                     \
 140                 int error;                                      \
 141                                                                 \
 142                 if (fd == AT_FDCWD)                             \
 143                         return (set_errno(EFAULT));             \
 144                 if ((fp = getf(fd)) == NULL)                    \
 145                         return (set_errno(EBADF));              \
 146                 error = statfn(fp->f_vnode, sb, 0, fp->f_cred);   \
 147                 releasef(fd);                                   \
 148                 if (error)                                      \
 149                         return (set_errno(error));              \
 150                 return (0);                                     \
 151         }
 152 
 153 int
 154 fstat(int fd, struct stat *sb)
 155 {
 156         FSTAT_BODY(fd, sb, cstat)
 157 }
 158 
 159 int
 160 fstatat(int fd, char *name, struct stat *sb, int flags)
 161 {
 162         int followflag;
 163         int csflags;
 164 
 165         if (name == NULL)
 166                 return (fstat(fd, sb));
 167 
 168         followflag = (flags & AT_SYMLINK_NOFOLLOW);
 169         csflags = (flags & _AT_TRIGGER ? ATTR_TRIGGER : 0);
 170         if (followflag == 0)
 171                 csflags |= ATTR_REAL;   /* flag for procfs lookups */
 172 
 173         return (cstatat(fd, name, sb, followflag, csflags));
 174 }
 175 
 176 int
 177 stat(char *name, struct stat *sb)
 178 {
 179         return (fstatat(AT_FDCWD, name, sb, 0));
 180 }
 181 
 182 int
 183 lstat(char *name, struct stat *sb)
 184 {
 185         return (fstatat(AT_FDCWD, name, sb, AT_SYMLINK_NOFOLLOW));
 186 }
 187 
 188 /*
 189  * Common code for stat(), lstat(), and fstat().
 190  * (32-bit kernel, 32-bit applications, 32-bit files)
 191  * (64-bit kernel, 64-bit applications, 64-bit files)
 192  */
 193 static int
 194 cstat(vnode_t *vp, struct stat *ubp, int flag, cred_t *cr)
 195 {
 196         struct vfssw *vswp;
 197         struct stat sb;
 198         vattr_t vattr;
 199         int error;
 200 
 201         vattr.va_mask = AT_STAT | AT_NBLOCKS | AT_BLKSIZE | AT_SIZE;
 202         if ((error = VOP_GETATTR(vp, &vattr, flag, cr, NULL)) != 0)
 203                 return (error);
 204 #ifdef  _ILP32
 205         /*
 206          * (32-bit kernel, 32-bit applications, 32-bit files)
 207          * NOTE: 32-bit kernel maintains a 64-bit unsigend va_size.
 208          *
 209          * st_size of devices (VBLK and VCHR special files) is a special case.
 210          * POSIX does not define size behavior for special files, so the
 211          * following Solaris specific behavior is not a violation. Solaris
 212          * returns the size of the device.
 213          *
 214          * For compatibility with 32-bit programs which happen to do stat() on
 215          * a (mknod) bigger than 2GB we suppress the large file EOVERFLOW and
 216          * instead we return the value MAXOFF32_T (LONG_MAX).
 217          *
 218          * 32-bit applications that care about the size of devices should be
 219          * built 64-bit or use a large file interface (lfcompile(5) or lf64(5)).
 220          */
 221         if ((vattr.va_size > MAXOFF32_T) &&
 222             ((vp->v_type == VBLK) || (vp->v_type == VCHR))) {
 223                 /* OVERFLOW | UNKNOWN_SIZE */
 224                 vattr.va_size = MAXOFF32_T;
 225         }
 226 #endif  /* _ILP32 */
 227         if (vattr.va_size > MAXOFF_T || vattr.va_nblocks > LONG_MAX ||
 228             vattr.va_nodeid > ULONG_MAX)
 229                 return (EOVERFLOW);
 230 
 231         bzero(&sb, sizeof (sb));
 232         sb.st_dev = vattr.va_fsid;
 233         sb.st_ino = (ino_t)vattr.va_nodeid;
 234         sb.st_mode = VTTOIF(vattr.va_type) | vattr.va_mode;
 235         sb.st_nlink = vattr.va_nlink;
 236         sb.st_uid = vattr.va_uid;
 237         sb.st_gid = vattr.va_gid;
 238         sb.st_rdev = vattr.va_rdev;
 239         sb.st_size = (off_t)vattr.va_size;
 240         sb.st_atim = vattr.va_atime;
 241         sb.st_mtim = vattr.va_mtime;
 242         sb.st_ctim = vattr.va_ctime;
 243         sb.st_blksize = vattr.va_blksize;
 244         sb.st_blocks = (blkcnt_t)vattr.va_nblocks;
 245         if (vp->v_vfsp != NULL) {
 246                 vswp = &vfssw[vp->v_vfsp->vfs_fstype];
 247                 if (vswp->vsw_name && *vswp->vsw_name)
 248                         (void) strcpy(sb.st_fstype, vswp->vsw_name);
 249         }
 250         if (copyout(&sb, ubp, sizeof (sb)))
 251                 return (EFAULT);
 252         return (0);
 253 }
 254 
 255 static int
 256 cstatat(int fd, char *name, struct stat *sb, int follow, int flags)
 257 {
 258         vnode_t *vp;
 259         int error;
 260         cred_t *cred;
 261         int link_follow;
 262         int estale_retry = 0;
 263 
 264         link_follow = (follow == AT_SYMLINK_NOFOLLOW) ? NO_FOLLOW : FOLLOW;
 265 lookup:
 266         if (error = cstatat_getvp(fd, name, link_follow, &vp, &cred))
 267                 return (set_errno(error));
 268         error = cstat(vp, sb, flags, cred);
 269         crfree(cred);
 270         VN_RELE(vp);
 271         if (error != 0) {
 272                 if (error == ESTALE &&
 273                     fs_need_estale_retry(estale_retry++))
 274                         goto lookup;
 275                 return (set_errno(error));
 276         }
 277         return (0);
 278 }
 279 
 280 #if defined(_SYSCALL32_IMPL)
 281 
 282 /*
 283  * 64-bit kernel, 32-bit applications, 32-bit file offsets
 284  */
 285 static int cstatat32(int, char *, struct stat32 *, int, int);
 286 static int cstat32(vnode_t *, struct stat32 *, int, cred_t *);
 287 
 288 int
 289 fstat32(int fd, struct stat32 *sb)
 290 {
 291         FSTAT_BODY(fd, sb, cstat32)
 292 }
 293 
 294 int
 295 fstatat32(int fd, char *name, struct stat32 *sb, int flags)
 296 {
 297         int followflag;
 298         int csflags;
 299 
 300         if (name == NULL)
 301                 return (fstat32(fd, sb));
 302 
 303         followflag = (flags & AT_SYMLINK_NOFOLLOW);
 304         csflags = (flags & _AT_TRIGGER ? ATTR_TRIGGER : 0);
 305         if (followflag == 0)
 306                 csflags |= ATTR_REAL;   /* flag for procfs lookups */
 307 
 308         return (cstatat32(fd, name, sb, followflag, csflags));
 309 }
 310 
 311 int
 312 stat32(char *name, struct stat32 *sb)
 313 {
 314         return (fstatat32(AT_FDCWD, name, sb, 0));
 315 }
 316 
 317 int
 318 lstat32(char *name, struct stat32 *sb)
 319 {
 320         return (fstatat32(AT_FDCWD, name, sb, AT_SYMLINK_NOFOLLOW));
 321 }
 322 
 323 static int
 324 cstat32(vnode_t *vp, struct stat32 *ubp, int flag, struct cred *cr)
 325 {
 326         struct vfssw *vswp;
 327         struct stat32 sb;
 328         vattr_t vattr;
 329         int error;
 330         dev32_t st_dev, st_rdev;
 331 
 332         vattr.va_mask = AT_STAT | AT_NBLOCKS | AT_BLKSIZE | AT_SIZE;
 333         if (error = VOP_GETATTR(vp, &vattr, flag, cr, NULL))
 334                 return (error);
 335 
 336         /* devices are a special case, see comments in cstat */
 337         if ((vattr.va_size > MAXOFF32_T) &&
 338             ((vp->v_type == VBLK) || (vp->v_type == VCHR))) {
 339                 /* OVERFLOW | UNKNOWN_SIZE */
 340                 vattr.va_size = MAXOFF32_T;
 341         }
 342 
 343         /* check for large values */
 344         if (!cmpldev(&st_dev, vattr.va_fsid) ||
 345             !cmpldev(&st_rdev, vattr.va_rdev) ||
 346             vattr.va_size > MAXOFF32_T ||
 347             vattr.va_nblocks > INT32_MAX ||
 348             vattr.va_nodeid > UINT32_MAX ||
 349             TIMESPEC_OVERFLOW(&(vattr.va_atime)) ||
 350             TIMESPEC_OVERFLOW(&(vattr.va_mtime)) ||
 351             TIMESPEC_OVERFLOW(&(vattr.va_ctime)))
 352                 return (EOVERFLOW);
 353 
 354         bzero(&sb, sizeof (sb));
 355         sb.st_dev = st_dev;
 356         sb.st_ino = (ino32_t)vattr.va_nodeid;
 357         sb.st_mode = VTTOIF(vattr.va_type) | vattr.va_mode;
 358         sb.st_nlink = vattr.va_nlink;
 359         sb.st_uid = vattr.va_uid;
 360         sb.st_gid = vattr.va_gid;
 361         sb.st_rdev = st_rdev;
 362         sb.st_size = (off32_t)vattr.va_size;
 363         TIMESPEC_TO_TIMESPEC32(&(sb.st_atim), &(vattr.va_atime));
 364         TIMESPEC_TO_TIMESPEC32(&(sb.st_mtim), &(vattr.va_mtime));
 365         TIMESPEC_TO_TIMESPEC32(&(sb.st_ctim), &(vattr.va_ctime));
 366         sb.st_blksize = vattr.va_blksize;
 367         sb.st_blocks = (blkcnt32_t)vattr.va_nblocks;
 368         if (vp->v_vfsp != NULL) {
 369                 vswp = &vfssw[vp->v_vfsp->vfs_fstype];
 370                 if (vswp->vsw_name && *vswp->vsw_name)
 371                         (void) strcpy(sb.st_fstype, vswp->vsw_name);
 372         }
 373         if (copyout(&sb, ubp, sizeof (sb)))
 374                 return (EFAULT);
 375         return (0);
 376 }
 377 
 378 static int
 379 cstatat32(int fd, char *name, struct stat32 *sb, int follow, int flags)
 380 {
 381         vnode_t *vp;
 382         int error;
 383         cred_t *cred;
 384         int link_follow;
 385         int estale_retry = 0;
 386 
 387         link_follow = (follow == AT_SYMLINK_NOFOLLOW) ? NO_FOLLOW : FOLLOW;
 388 lookup:
 389         if (error = cstatat_getvp(fd, name, link_follow, &vp, &cred))
 390                 return (set_errno(error));
 391         error = cstat32(vp, sb, flags, cred);
 392         crfree(cred);
 393         VN_RELE(vp);
 394         if (error != 0) {
 395                 if (error == ESTALE &&
 396                     fs_need_estale_retry(estale_retry++))
 397                         goto lookup;
 398                 return (set_errno(error));
 399         }
 400         return (0);
 401 }
 402 
 403 #endif  /* _SYSCALL32_IMPL */
 404 
 405 #if defined(_ILP32)
 406 
 407 /*
 408  * 32-bit kernel, 32-bit applications, 64-bit file offsets.
 409  *
 410  * These routines are implemented differently on 64-bit kernels.
 411  */
 412 static int cstatat64(int, char *, struct stat64 *, int, int);
 413 static int cstat64(vnode_t *, struct stat64 *, int, cred_t *);
 414 
 415 int
 416 fstat64(int fd, struct stat64 *sb)
 417 {
 418         FSTAT_BODY(fd, sb, cstat64)
 419 }
 420 
 421 int
 422 fstatat64(int fd, char *name, struct stat64 *sb, int flags)
 423 {
 424         int followflag;
 425         int csflags;
 426 
 427         if (name == NULL)
 428                 return (fstat64(fd, sb));
 429 
 430         followflag = (flags & AT_SYMLINK_NOFOLLOW);
 431         csflags = (flags & _AT_TRIGGER ? ATTR_TRIGGER : 0);
 432         if (followflag == 0)
 433                 csflags |= ATTR_REAL;   /* flag for procfs lookups */
 434 
 435         return (cstatat64(fd, name, sb, followflag, csflags));
 436 }
 437 
 438 int
 439 stat64(char *name, struct stat64 *sb)
 440 {
 441         return (fstatat64(AT_FDCWD, name, sb, 0));
 442 }
 443 
 444 int
 445 lstat64(char *name, struct stat64 *sb)
 446 {
 447         return (fstatat64(AT_FDCWD, name, sb, AT_SYMLINK_NOFOLLOW));
 448 }
 449 
 450 static int
 451 cstat64(vnode_t *vp, struct stat64 *ubp, int flag, cred_t *cr)
 452 {
 453         struct vfssw *vswp;
 454         struct stat64 lsb;
 455         vattr_t vattr;
 456         int error;
 457 
 458         vattr.va_mask = AT_STAT | AT_NBLOCKS | AT_BLKSIZE | AT_SIZE;
 459         if (error = VOP_GETATTR(vp, &vattr, flag, cr, NULL))
 460                 return (error);
 461 
 462         bzero(&lsb, sizeof (lsb));
 463         lsb.st_dev = vattr.va_fsid;
 464         lsb.st_ino = vattr.va_nodeid;
 465         lsb.st_mode = VTTOIF(vattr.va_type) | vattr.va_mode;
 466         lsb.st_nlink = vattr.va_nlink;
 467         lsb.st_uid = vattr.va_uid;
 468         lsb.st_gid = vattr.va_gid;
 469         lsb.st_rdev = vattr.va_rdev;
 470         lsb.st_size = vattr.va_size;
 471         lsb.st_atim = vattr.va_atime;
 472         lsb.st_mtim = vattr.va_mtime;
 473         lsb.st_ctim = vattr.va_ctime;
 474         lsb.st_blksize = vattr.va_blksize;
 475         lsb.st_blocks = vattr.va_nblocks;
 476         if (vp->v_vfsp != NULL) {
 477                 vswp = &vfssw[vp->v_vfsp->vfs_fstype];
 478                 if (vswp->vsw_name && *vswp->vsw_name)
 479                         (void) strcpy(lsb.st_fstype, vswp->vsw_name);
 480         }
 481         if (copyout(&lsb, ubp, sizeof (lsb)))
 482                 return (EFAULT);
 483         return (0);
 484 }
 485 
 486 static int
 487 cstatat64(int fd, char *name, struct stat64 *sb, int follow, int flags)
 488 {
 489         vnode_t *vp;
 490         int error;
 491         cred_t *cred;
 492         int link_follow;
 493         int estale_retry = 0;
 494 
 495         link_follow = (follow == AT_SYMLINK_NOFOLLOW) ? NO_FOLLOW : FOLLOW;
 496 lookup:
 497         if (error = cstatat_getvp(fd, name, link_follow, &vp, &cred))
 498                 return (set_errno(error));
 499         error = cstat64(vp, sb, flags, cred);
 500         crfree(cred);
 501         VN_RELE(vp);
 502         if (error != 0) {
 503                 if (error == ESTALE &&
 504                     fs_need_estale_retry(estale_retry++))
 505                         goto lookup;
 506                 return (set_errno(error));
 507         }
 508         return (0);
 509 }
 510 
 511 #endif  /* _ILP32 */
 512 
 513 #if defined(_SYSCALL32_IMPL)
 514 
 515 /*
 516  * 64-bit kernel, 32-bit applications, 64-bit file offsets.
 517  *
 518  * We'd really like to call the "native" stat calls for these ones,
 519  * but the problem is that the 64-bit ABI defines the 'stat64' structure
 520  * differently from the way the 32-bit ABI defines it.
 521  */
 522 
 523 static int cstatat64_32(int, char *, struct stat64_32 *, int, int);
 524 static int cstat64_32(vnode_t *, struct stat64_32 *, int, cred_t *);
 525 
 526 int
 527 fstat64_32(int fd, struct stat64_32 *sb)
 528 {
 529         FSTAT_BODY(fd, sb, cstat64_32)
 530 }
 531 
 532 int
 533 fstatat64_32(int fd, char *name, struct stat64_32 *sb, int flags)
 534 {
 535         int followflag;
 536         int csflags;
 537 
 538         if (name == NULL)
 539                 return (fstat64_32(fd, sb));
 540 
 541         followflag = (flags & AT_SYMLINK_NOFOLLOW);
 542         csflags = (flags & _AT_TRIGGER ? ATTR_TRIGGER : 0);
 543         if (followflag == 0)
 544                 csflags |= ATTR_REAL;   /* flag for procfs lookups */
 545 
 546         return (cstatat64_32(fd, name, sb, followflag, csflags));
 547 }
 548 
 549 int
 550 stat64_32(char *name, struct stat64_32 *sb)
 551 {
 552         return (fstatat64_32(AT_FDCWD, name, sb, 0));
 553 }
 554 
 555 int
 556 lstat64_32(char *name, struct stat64_32 *sb)
 557 {
 558         return (fstatat64_32(AT_FDCWD, name, sb, AT_SYMLINK_NOFOLLOW));
 559 }
 560 
 561 static int
 562 cstat64_32(vnode_t *vp, struct stat64_32 *ubp, int flag, cred_t *cr)
 563 {
 564         struct vfssw *vswp;
 565         struct stat64_32 lsb;
 566         vattr_t vattr;
 567         int error;
 568         dev32_t st_dev, st_rdev;
 569 
 570         vattr.va_mask = AT_STAT | AT_NBLOCKS | AT_BLKSIZE | AT_SIZE;
 571         if (error = VOP_GETATTR(vp, &vattr, flag, cr, NULL))
 572                 return (error);
 573 
 574         if (!cmpldev(&st_dev, vattr.va_fsid) ||
 575             !cmpldev(&st_rdev, vattr.va_rdev) ||
 576             TIMESPEC_OVERFLOW(&(vattr.va_atime)) ||
 577             TIMESPEC_OVERFLOW(&(vattr.va_mtime)) ||
 578             TIMESPEC_OVERFLOW(&(vattr.va_ctime)))
 579                 return (EOVERFLOW);
 580 
 581         bzero(&lsb, sizeof (lsb));
 582         lsb.st_dev = st_dev;
 583         lsb.st_ino = vattr.va_nodeid;
 584         lsb.st_mode = VTTOIF(vattr.va_type) | vattr.va_mode;
 585         lsb.st_nlink = vattr.va_nlink;
 586         lsb.st_uid = vattr.va_uid;
 587         lsb.st_gid = vattr.va_gid;
 588         lsb.st_rdev = st_rdev;
 589         lsb.st_size = vattr.va_size;
 590         TIMESPEC_TO_TIMESPEC32(&(lsb.st_atim), &(vattr.va_atime));
 591         TIMESPEC_TO_TIMESPEC32(&(lsb.st_mtim), &(vattr.va_mtime));
 592         TIMESPEC_TO_TIMESPEC32(&(lsb.st_ctim), &(vattr.va_ctime));
 593         lsb.st_blksize = vattr.va_blksize;
 594         lsb.st_blocks = vattr.va_nblocks;
 595         if (vp->v_vfsp != NULL) {
 596                 vswp = &vfssw[vp->v_vfsp->vfs_fstype];
 597                 if (vswp->vsw_name && *vswp->vsw_name)
 598                         (void) strcpy(lsb.st_fstype, vswp->vsw_name);
 599         }
 600         if (copyout(&lsb, ubp, sizeof (lsb)))
 601                 return (EFAULT);
 602         return (0);
 603 }
 604 
 605 static int
 606 cstatat64_32(int fd, char *name, struct stat64_32 *sb, int follow, int flags)
 607 {
 608         vnode_t  *vp;
 609         int error;
 610         cred_t *cred;
 611         int link_follow;
 612         int estale_retry = 0;
 613 
 614         link_follow = (follow == AT_SYMLINK_NOFOLLOW) ? NO_FOLLOW : FOLLOW;
 615 lookup:
 616         if (error = cstatat_getvp(fd, name, link_follow, &vp, &cred))
 617                 return (set_errno(error));
 618         error = cstat64_32(vp, sb, flags, cred);
 619         crfree(cred);
 620         VN_RELE(vp);
 621         if (error != 0) {
 622                 if (error == ESTALE &&
 623                     fs_need_estale_retry(estale_retry++))
 624                         goto lookup;
 625                 return (set_errno(error));
 626         }
 627         return (0);
 628 }
 629 
 630 #endif /* _SYSCALL32_IMPL */