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 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/errno.h> 28 #include <sys/syscall.h> 29 #include <sys/fcntl.h> 30 #include <sys/stat.h> 31 #include <sys/param.h> 32 #include "compat.h" 33 #include "s5sysmacros.h" 34 35 #define ST_FSTYPSZ 16 /* array size for file system type name */ 36 37 struct ts { 38 long tv_sec; /* seconds */ 39 long tv_nsec; /* nanoseconds */ 40 }; 41 42 struct n_stat { 43 unsigned long st_dev; 44 long st_pad1[3]; /* reserved for network id */ 45 unsigned long st_ino; 46 unsigned long st_mode; 47 unsigned long st_nlink; 48 long st_uid; 49 long st_gid; 50 unsigned long st_rdev; 51 long st_pad2[2]; 52 long st_size; 53 long st_pad3; /* future off_t expansion */ 54 struct ts st_atim; 55 struct ts st_mtim; 56 struct ts st_ctim; 57 long st_blksize; 58 long st_blocks; 59 char st_fstype[ST_FSTYPSZ]; 60 long st_pad4[8]; /* expansion area */ 61 62 }; 63 64 static void cpstatbuf(struct stat *, struct n_stat *); 65 66 int 67 fstat(int fd, struct stat *buf) 68 { 69 return (bc_fstat(fd, buf)); 70 } 71 72 int 73 bc_fstat(int fd, struct stat *buf) 74 { 75 int ret; 76 struct n_stat nb; 77 extern int errno; 78 79 if (buf == 0) { 80 errno = EFAULT; 81 return (-1); 82 } 83 84 if ((ret = _syscall(SYS_fstatat, fd, NULL, &nb, 0)) == -1) 85 return (ret); 86 87 cpstatbuf(buf, &nb); 88 if (fd_get(fd) != -1) { 89 buf->st_size = getmodsize(buf->st_size, 90 sizeof (struct utmpx), sizeof(struct compat_utmp)); 91 } 92 93 return (ret); 94 } 95 96 int 97 stat_com(int lstat, char *path, struct stat *buf) 98 { 99 int fd, ret; 100 struct n_stat nb; 101 int follow = lstat? AT_SYMLINK_NOFOLLOW : 0; 102 103 if (strcmp(path, "/etc/mtab") == 0) { 104 /* 105 * stat the real mnttab, or the "parsed" mtab 106 * created by open? 107 * 108 * for now, stat the real mnttab. 109 */ 110 111 /* 112 * fd = open_mnt("/etc/mnttab", "mtab", O_RDONLY); 113 * ret = fstat(fd, buf); 114 * close(fd); 115 * return(ret); 116 */ 117 ret = stat_com(lstat, "/etc/mnttab", buf); 118 return(ret); 119 } 120 if (strcmp(path, "/etc/fstab") == 0) { 121 fd = open_mnt("/etc/vfstab", "fstab", O_RDONLY); 122 if (fd < 0) 123 ret = -1; 124 else { 125 ret = fstat(fd, buf); 126 close(fd); 127 } 128 return(ret); 129 } 130 if (strcmp(path, "/etc/utmp") == 0 || 131 strcmp(path, "/var/adm/utmp") == 0) { 132 if ((ret = _syscall(SYS_fstatat, AT_FDCWD, 133 "/var/adm/utmpx", &nb, follow)) != -1) { 134 cpstatbuf(buf, &nb); 135 buf->st_size = getmodsize(buf->st_size, 136 sizeof(struct utmpx), sizeof(struct compat_utmp)); 137 } 138 return(ret); 139 } 140 if (strcmp(path, "/var/adm/wtmp") == 0) { 141 if ((ret = _syscall(SYS_fstatat, AT_FDCWD, 142 "/var/adm/wtmpx", &nb, follow)) != -1) { 143 cpstatbuf(buf, &nb); 144 buf->st_size = getmodsize(buf->st_size, 145 sizeof(struct utmpx), sizeof(struct compat_utmp)); 146 } 147 return(ret); 148 } 149 if (_strstr(path, "/lib/locale/") != 0) { 150 fd = open(path, O_RDONLY); 151 if (fd < 0) 152 ret = -1; 153 else { 154 ret = fstat(fd, buf); 155 close(fd); 156 } 157 return(ret); 158 } 159 160 if ((ret = _syscall(SYS_fstatat, AT_FDCWD, path, &nb, follow)) != -1) 161 cpstatbuf(buf, &nb); 162 return(ret); 163 } 164 165 166 /* 167 * Common code to copy xstat buf to BSD style buf 168 */ 169 static void 170 cpstatbuf(struct stat *bsdbuf, struct n_stat *nbuf) 171 { 172 bsdbuf->st_dev = (dev_t) cmpdev(nbuf->st_dev); 173 bsdbuf->st_ino = nbuf->st_ino; 174 bsdbuf->st_mode = (unsigned short) nbuf->st_mode; 175 bsdbuf->st_nlink = (short) nbuf->st_nlink; 176 177 if ((unsigned long)nbuf->st_uid > 0xffff) 178 bsdbuf->st_uid = 60001; /* UID_NOBODY */ 179 else 180 bsdbuf->st_uid = (uid_t) nbuf->st_uid; 181 182 if ((unsigned long)nbuf->st_gid > 0xffff) 183 bsdbuf->st_gid = 60001; /* GID_NOBODY */ 184 else 185 bsdbuf->st_gid = (gid_t) nbuf->st_gid; 186 187 bsdbuf->st_rdev = (dev_t) cmpdev(nbuf->st_rdev); 188 bsdbuf->st_size = nbuf->st_size; 189 bsdbuf->st_atime = nbuf->st_atim.tv_sec; 190 bsdbuf->st_mtime = nbuf->st_mtim.tv_sec; 191 bsdbuf->st_ctime = nbuf->st_ctim.tv_sec; 192 bsdbuf->st_blksize = nbuf->st_blksize; 193 bsdbuf->st_blocks = nbuf->st_blocks; 194 } 195