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*8fd04b83SRoger A. Faulkner  * Common Development and Distribution License (the "License").
6*8fd04b83SRoger A. Faulkner  * 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  */
21*8fd04b83SRoger A. Faulkner 
227c478bd9Sstevel@tonic-gate /*
23*8fd04b83SRoger A. Faulkner  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24*8fd04b83SRoger A. Faulkner  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <unistd.h>
307c478bd9Sstevel@tonic-gate #include <string.h>
317c478bd9Sstevel@tonic-gate #include <errno.h>
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <sys/stat.h>
34*8fd04b83SRoger A. Faulkner #include <sys/fcntl.h>
357c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
367c478bd9Sstevel@tonic-gate #include "libproc.h"
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #ifdef _LP64
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate  * in case of 64-bit *stat() and *stat64 library call and 32-bit subject
417c478bd9Sstevel@tonic-gate  * process convert 64-bit struct stat/stat64 into 32-bit struct stat64
427c478bd9Sstevel@tonic-gate  */
437c478bd9Sstevel@tonic-gate static void
stat64_32_to_n(struct stat64_32 * src,struct stat * dest)447c478bd9Sstevel@tonic-gate stat64_32_to_n(struct stat64_32 *src, struct stat *dest)
457c478bd9Sstevel@tonic-gate {
467c478bd9Sstevel@tonic-gate 	(void) memset(dest, 0, sizeof (*dest));
477c478bd9Sstevel@tonic-gate 	dest->st_dev = DEVEXPL(src->st_dev);
487c478bd9Sstevel@tonic-gate 	dest->st_ino = (ino_t)src->st_ino;
497c478bd9Sstevel@tonic-gate 	dest->st_mode = (mode_t)src->st_mode;
507c478bd9Sstevel@tonic-gate 	dest->st_nlink = (nlink_t)src->st_nlink;
517c478bd9Sstevel@tonic-gate 	dest->st_uid = (uid_t)src->st_uid;
527c478bd9Sstevel@tonic-gate 	dest->st_gid = (gid_t)src->st_gid;
537c478bd9Sstevel@tonic-gate 	dest->st_rdev = DEVEXPL(src->st_rdev);
547c478bd9Sstevel@tonic-gate 	dest->st_size = (off_t)src->st_size;
557c478bd9Sstevel@tonic-gate 	TIMESPEC32_TO_TIMESPEC(&dest->st_atim, &src->st_atim);
567c478bd9Sstevel@tonic-gate 	TIMESPEC32_TO_TIMESPEC(&dest->st_mtim, &src->st_mtim);
577c478bd9Sstevel@tonic-gate 	TIMESPEC32_TO_TIMESPEC(&dest->st_ctim, &src->st_ctim);
587c478bd9Sstevel@tonic-gate 	dest->st_blksize = (blksize_t)src->st_blksize;
597c478bd9Sstevel@tonic-gate 	dest->st_blocks = (blkcnt_t)src->st_blocks;
607c478bd9Sstevel@tonic-gate 	(void) memcpy(dest->st_fstype, src->st_fstype,
617c478bd9Sstevel@tonic-gate 	    sizeof (dest->st_fstype));
627c478bd9Sstevel@tonic-gate }
637c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate  * stat() system call -- executed by subject process
677c478bd9Sstevel@tonic-gate  */
687c478bd9Sstevel@tonic-gate int
pr_stat(struct ps_prochandle * Pr,const char * path,struct stat * buf)697c478bd9Sstevel@tonic-gate pr_stat(struct ps_prochandle *Pr, const char *path, struct stat *buf)
707c478bd9Sstevel@tonic-gate {
717c478bd9Sstevel@tonic-gate 	sysret_t rval;			/* return value from stat() */
72*8fd04b83SRoger A. Faulkner 	argdes_t argd[4];		/* arg descriptors for fstatat() */
737c478bd9Sstevel@tonic-gate 	argdes_t *adp = &argd[0];	/* first argument */
74*8fd04b83SRoger A. Faulkner 	int syscall;			/* SYS_fstatat or SYS_fstatat64 */
757c478bd9Sstevel@tonic-gate 	int error;
767c478bd9Sstevel@tonic-gate #ifdef _LP64
777c478bd9Sstevel@tonic-gate 	struct stat64_32 statb64_32;
787c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	if (Pr == NULL)		/* no subject process */
817c478bd9Sstevel@tonic-gate 		return (stat(path, buf));
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel != PR_MODEL_NATIVE) {
847c478bd9Sstevel@tonic-gate 		/* 64-bit process controls 32-bit subject process */
85*8fd04b83SRoger A. Faulkner 		syscall = SYS_fstatat64;
867c478bd9Sstevel@tonic-gate 	} else {
87*8fd04b83SRoger A. Faulkner 		syscall = SYS_fstatat;
887c478bd9Sstevel@tonic-gate 	}
89*8fd04b83SRoger A. Faulkner 
90*8fd04b83SRoger A. Faulkner 	adp->arg_value = AT_FDCWD;
91*8fd04b83SRoger A. Faulkner 	adp->arg_object = NULL;
92*8fd04b83SRoger A. Faulkner 	adp->arg_type = AT_BYVAL;
93*8fd04b83SRoger A. Faulkner 	adp->arg_inout = AI_INPUT;
94*8fd04b83SRoger A. Faulkner 	adp->arg_size = 0;
95*8fd04b83SRoger A. Faulkner 	adp++;			/* move to path argument */
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate 	adp->arg_value = 0;
987c478bd9Sstevel@tonic-gate 	adp->arg_object = (void *)path;
997c478bd9Sstevel@tonic-gate 	adp->arg_type = AT_BYREF;
1007c478bd9Sstevel@tonic-gate 	adp->arg_inout = AI_INPUT;
1017c478bd9Sstevel@tonic-gate 	adp->arg_size = strlen(path) + 1;
1027c478bd9Sstevel@tonic-gate 	adp++;			/* move to buffer argument */
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	adp->arg_value = 0;
1057c478bd9Sstevel@tonic-gate 	adp->arg_type = AT_BYREF;
1067c478bd9Sstevel@tonic-gate 	adp->arg_inout = AI_OUTPUT;
1077c478bd9Sstevel@tonic-gate #ifdef _LP64
1087c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
1097c478bd9Sstevel@tonic-gate 		adp->arg_object = &statb64_32;
1107c478bd9Sstevel@tonic-gate 		adp->arg_size = sizeof (statb64_32);
1117c478bd9Sstevel@tonic-gate 	} else {
1127c478bd9Sstevel@tonic-gate 		adp->arg_object = buf;
1137c478bd9Sstevel@tonic-gate 		adp->arg_size = sizeof (*buf);
1147c478bd9Sstevel@tonic-gate 	}
1157c478bd9Sstevel@tonic-gate #else	/* _LP64 */
1167c478bd9Sstevel@tonic-gate 	adp->arg_object = buf;
1177c478bd9Sstevel@tonic-gate 	adp->arg_size = sizeof (*buf);
1187c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
119*8fd04b83SRoger A. Faulkner 	adp++;			/* move to flags argument */
1207c478bd9Sstevel@tonic-gate 
121*8fd04b83SRoger A. Faulkner 	adp->arg_value = 0;
122*8fd04b83SRoger A. Faulkner 	adp->arg_object = NULL;
123*8fd04b83SRoger A. Faulkner 	adp->arg_type = AT_BYVAL;
124*8fd04b83SRoger A. Faulkner 	adp->arg_inout = AI_INPUT;
125*8fd04b83SRoger A. Faulkner 	adp->arg_size = 0;
126*8fd04b83SRoger A. Faulkner 
127*8fd04b83SRoger A. Faulkner 	error = Psyscall(Pr, &rval, syscall, 4, &argd[0]);
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	if (error) {
1307c478bd9Sstevel@tonic-gate 		errno = (error > 0)? error : ENOSYS;
1317c478bd9Sstevel@tonic-gate 		return (-1);
1327c478bd9Sstevel@tonic-gate 	}
1337c478bd9Sstevel@tonic-gate #ifdef _LP64
1347c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
1357c478bd9Sstevel@tonic-gate 		stat64_32_to_n(&statb64_32, buf);
1367c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
1377c478bd9Sstevel@tonic-gate 	return (0);
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate /*
1417c478bd9Sstevel@tonic-gate  * lstat() system call -- executed by subject process
1427c478bd9Sstevel@tonic-gate  */
1437c478bd9Sstevel@tonic-gate int
pr_lstat(struct ps_prochandle * Pr,const char * path,struct stat * buf)1447c478bd9Sstevel@tonic-gate pr_lstat(struct ps_prochandle *Pr, const char *path, struct stat *buf)
1457c478bd9Sstevel@tonic-gate {
146*8fd04b83SRoger A. Faulkner 	sysret_t rval;			/* return value from stat() */
147*8fd04b83SRoger A. Faulkner 	argdes_t argd[4];		/* arg descriptors for fstatat() */
1487c478bd9Sstevel@tonic-gate 	argdes_t *adp = &argd[0];	/* first argument */
149*8fd04b83SRoger A. Faulkner 	int syscall;			/* SYS_fstatat or SYS_fstatat64 */
1507c478bd9Sstevel@tonic-gate 	int error;
1517c478bd9Sstevel@tonic-gate #ifdef _LP64
1527c478bd9Sstevel@tonic-gate 	struct stat64_32 statb64_32;
1537c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	if (Pr == NULL)		/* no subject process */
1567c478bd9Sstevel@tonic-gate 		return (lstat(path, buf));
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel != PR_MODEL_NATIVE) {
1597c478bd9Sstevel@tonic-gate 		/* 64-bit process controls 32-bit subject process */
160*8fd04b83SRoger A. Faulkner 		syscall = SYS_fstatat64;
1617c478bd9Sstevel@tonic-gate 	} else {
162*8fd04b83SRoger A. Faulkner 		syscall = SYS_fstatat;
1637c478bd9Sstevel@tonic-gate 	}
164*8fd04b83SRoger A. Faulkner 
165*8fd04b83SRoger A. Faulkner 	adp->arg_value = AT_FDCWD;
166*8fd04b83SRoger A. Faulkner 	adp->arg_object = NULL;
167*8fd04b83SRoger A. Faulkner 	adp->arg_type = AT_BYVAL;
168*8fd04b83SRoger A. Faulkner 	adp->arg_inout = AI_INPUT;
169*8fd04b83SRoger A. Faulkner 	adp->arg_size = 0;
170*8fd04b83SRoger A. Faulkner 	adp++;			/* move to path argument */
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 	adp->arg_value = 0;
1737c478bd9Sstevel@tonic-gate 	adp->arg_object = (void *)path;
1747c478bd9Sstevel@tonic-gate 	adp->arg_type = AT_BYREF;
1757c478bd9Sstevel@tonic-gate 	adp->arg_inout = AI_INPUT;
1767c478bd9Sstevel@tonic-gate 	adp->arg_size = strlen(path) + 1;
1777c478bd9Sstevel@tonic-gate 	adp++;			/* move to buffer argument */
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	adp->arg_value = 0;
1807c478bd9Sstevel@tonic-gate 	adp->arg_type = AT_BYREF;
1817c478bd9Sstevel@tonic-gate 	adp->arg_inout = AI_OUTPUT;
1827c478bd9Sstevel@tonic-gate #ifdef _LP64
1837c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
1847c478bd9Sstevel@tonic-gate 		adp->arg_object = &statb64_32;
1857c478bd9Sstevel@tonic-gate 		adp->arg_size = sizeof (statb64_32);
1867c478bd9Sstevel@tonic-gate 	} else {
1877c478bd9Sstevel@tonic-gate 		adp->arg_object = buf;
1887c478bd9Sstevel@tonic-gate 		adp->arg_size = sizeof (*buf);
1897c478bd9Sstevel@tonic-gate 	}
1907c478bd9Sstevel@tonic-gate #else	/* _LP64 */
1917c478bd9Sstevel@tonic-gate 	adp->arg_object = buf;
1927c478bd9Sstevel@tonic-gate 	adp->arg_size = sizeof (*buf);
1937c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
194*8fd04b83SRoger A. Faulkner 	adp++;			/* move to flags argument */
195*8fd04b83SRoger A. Faulkner 
196*8fd04b83SRoger A. Faulkner 	adp->arg_value = AT_SYMLINK_NOFOLLOW;
197*8fd04b83SRoger A. Faulkner 	adp->arg_object = NULL;
198*8fd04b83SRoger A. Faulkner 	adp->arg_type = AT_BYVAL;
199*8fd04b83SRoger A. Faulkner 	adp->arg_inout = AI_INPUT;
200*8fd04b83SRoger A. Faulkner 	adp->arg_size = 0;
2017c478bd9Sstevel@tonic-gate 
202*8fd04b83SRoger A. Faulkner 	error = Psyscall(Pr, &rval, syscall, 4, &argd[0]);
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	if (error) {
2057c478bd9Sstevel@tonic-gate 		errno = (error > 0)? error : ENOSYS;
2067c478bd9Sstevel@tonic-gate 		return (-1);
2077c478bd9Sstevel@tonic-gate 	}
2087c478bd9Sstevel@tonic-gate #ifdef _LP64
2097c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
2107c478bd9Sstevel@tonic-gate 		stat64_32_to_n(&statb64_32, buf);
2117c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
2127c478bd9Sstevel@tonic-gate 	return (0);
2137c478bd9Sstevel@tonic-gate }
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate /*
2167c478bd9Sstevel@tonic-gate  * fstat() system call -- executed by subject process
2177c478bd9Sstevel@tonic-gate  */
2187c478bd9Sstevel@tonic-gate int
pr_fstat(struct ps_prochandle * Pr,int fd,struct stat * buf)2197c478bd9Sstevel@tonic-gate pr_fstat(struct ps_prochandle *Pr, int fd, struct stat *buf)
2207c478bd9Sstevel@tonic-gate {
221*8fd04b83SRoger A. Faulkner 	sysret_t rval;			/* return value from stat() */
222*8fd04b83SRoger A. Faulkner 	argdes_t argd[4];		/* arg descriptors for fstatat() */
2237c478bd9Sstevel@tonic-gate 	argdes_t *adp = &argd[0];	/* first argument */
224*8fd04b83SRoger A. Faulkner 	int syscall;			/* SYS_fstatat or SYS_fstatat64 */
2257c478bd9Sstevel@tonic-gate 	int error;
2267c478bd9Sstevel@tonic-gate #ifdef _LP64
2277c478bd9Sstevel@tonic-gate 	struct stat64_32 statb64_32;
2287c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	if (Pr == NULL)		/* no subject process */
2317c478bd9Sstevel@tonic-gate 		return (fstat(fd, buf));
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel != PR_MODEL_NATIVE) {
2347c478bd9Sstevel@tonic-gate 		/* 64-bit process controls 32-bit subject process */
235*8fd04b83SRoger A. Faulkner 		syscall = SYS_fstatat64;
2367c478bd9Sstevel@tonic-gate 	} else {
237*8fd04b83SRoger A. Faulkner 		syscall = SYS_fstatat;
2387c478bd9Sstevel@tonic-gate 	}
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	adp->arg_value = fd;
2417c478bd9Sstevel@tonic-gate 	adp->arg_object = NULL;
2427c478bd9Sstevel@tonic-gate 	adp->arg_type = AT_BYVAL;
2437c478bd9Sstevel@tonic-gate 	adp->arg_inout = AI_INPUT;
2447c478bd9Sstevel@tonic-gate 	adp->arg_size = 0;
245*8fd04b83SRoger A. Faulkner 	adp++;			/* move to path argument */
246*8fd04b83SRoger A. Faulkner 
247*8fd04b83SRoger A. Faulkner 	adp->arg_value = 0;
248*8fd04b83SRoger A. Faulkner 	adp->arg_object = NULL;
249*8fd04b83SRoger A. Faulkner 	adp->arg_type = AT_BYVAL;
250*8fd04b83SRoger A. Faulkner 	adp->arg_inout = AI_INPUT;
251*8fd04b83SRoger A. Faulkner 	adp->arg_size = 0;
2527c478bd9Sstevel@tonic-gate 	adp++;			/* move to buffer argument */
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	adp->arg_value = 0;
2557c478bd9Sstevel@tonic-gate 	adp->arg_type = AT_BYREF;
2567c478bd9Sstevel@tonic-gate 	adp->arg_inout = AI_OUTPUT;
2577c478bd9Sstevel@tonic-gate #ifdef _LP64
2587c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
2597c478bd9Sstevel@tonic-gate 		adp->arg_object = &statb64_32;
2607c478bd9Sstevel@tonic-gate 		adp->arg_size = sizeof (statb64_32);
2617c478bd9Sstevel@tonic-gate 	} else {
2627c478bd9Sstevel@tonic-gate 		adp->arg_object = buf;
2637c478bd9Sstevel@tonic-gate 		adp->arg_size = sizeof (*buf);
2647c478bd9Sstevel@tonic-gate 	}
2657c478bd9Sstevel@tonic-gate #else	/* _LP64 */
2667c478bd9Sstevel@tonic-gate 	adp->arg_object = buf;
2677c478bd9Sstevel@tonic-gate 	adp->arg_size = sizeof (*buf);
2687c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
269*8fd04b83SRoger A. Faulkner 	adp++;			/* move to flags argument */
2707c478bd9Sstevel@tonic-gate 
271*8fd04b83SRoger A. Faulkner 	adp->arg_value = 0;
272*8fd04b83SRoger A. Faulkner 	adp->arg_object = NULL;
273*8fd04b83SRoger A. Faulkner 	adp->arg_type = AT_BYVAL;
274*8fd04b83SRoger A. Faulkner 	adp->arg_inout = AI_INPUT;
275*8fd04b83SRoger A. Faulkner 	adp->arg_size = 0;
276*8fd04b83SRoger A. Faulkner 
277*8fd04b83SRoger A. Faulkner 	error = Psyscall(Pr, &rval, syscall, 4, &argd[0]);
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	if (error) {
2807c478bd9Sstevel@tonic-gate 		errno = (error > 0)? error : ENOSYS;
2817c478bd9Sstevel@tonic-gate 		return (-1);
2827c478bd9Sstevel@tonic-gate 	}
2837c478bd9Sstevel@tonic-gate #ifdef _LP64
2847c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
2857c478bd9Sstevel@tonic-gate 		stat64_32_to_n(&statb64_32, buf);
2867c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
2877c478bd9Sstevel@tonic-gate 	return (0);
2887c478bd9Sstevel@tonic-gate }
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate /*
2917c478bd9Sstevel@tonic-gate  * stat64() system call -- executed by subject process
2927c478bd9Sstevel@tonic-gate  */
2937c478bd9Sstevel@tonic-gate int
pr_stat64(struct ps_prochandle * Pr,const char * path,struct stat64 * buf)2947c478bd9Sstevel@tonic-gate pr_stat64(struct ps_prochandle *Pr, const char *path, struct stat64 *buf)
2957c478bd9Sstevel@tonic-gate {
296*8fd04b83SRoger A. Faulkner 	sysret_t rval;			/* return value from stat() */
297*8fd04b83SRoger A. Faulkner 	argdes_t argd[4];		/* arg descriptors for fstatat() */
2987c478bd9Sstevel@tonic-gate 	argdes_t *adp = &argd[0];	/* first argument */
299*8fd04b83SRoger A. Faulkner 	int syscall;			/* SYS_fstatat or SYS_fstatat64 */
3007c478bd9Sstevel@tonic-gate 	int error;
3017c478bd9Sstevel@tonic-gate #ifdef _LP64
3027c478bd9Sstevel@tonic-gate 	struct stat64_32 statb64_32;
3037c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	if (Pr == NULL)		/* no subject process */
3067c478bd9Sstevel@tonic-gate 		return (stat64(path, buf));
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
3097c478bd9Sstevel@tonic-gate 		/*
3107c478bd9Sstevel@tonic-gate 		 * 32-bit native and
3117c478bd9Sstevel@tonic-gate 		 * 64-bit process controls 32-bit subject process
3127c478bd9Sstevel@tonic-gate 		 */
313*8fd04b83SRoger A. Faulkner 		syscall = SYS_fstatat64;
3147c478bd9Sstevel@tonic-gate 	} else {
3157c478bd9Sstevel@tonic-gate 		/* 64-bit native */
316*8fd04b83SRoger A. Faulkner 		syscall = SYS_fstatat;
3177c478bd9Sstevel@tonic-gate 	}
3187c478bd9Sstevel@tonic-gate 
319*8fd04b83SRoger A. Faulkner 	adp->arg_value = AT_FDCWD;
320*8fd04b83SRoger A. Faulkner 	adp->arg_object = NULL;
321*8fd04b83SRoger A. Faulkner 	adp->arg_type = AT_BYVAL;
322*8fd04b83SRoger A. Faulkner 	adp->arg_inout = AI_INPUT;
323*8fd04b83SRoger A. Faulkner 	adp->arg_size = 0;
324*8fd04b83SRoger A. Faulkner 	adp++;			/* move to path argument */
325*8fd04b83SRoger A. Faulkner 
3267c478bd9Sstevel@tonic-gate 	adp->arg_value = 0;
3277c478bd9Sstevel@tonic-gate 	adp->arg_object = (void *)path;
3287c478bd9Sstevel@tonic-gate 	adp->arg_type = AT_BYREF;
3297c478bd9Sstevel@tonic-gate 	adp->arg_inout = AI_INPUT;
3307c478bd9Sstevel@tonic-gate 	adp->arg_size = strlen(path) + 1;
3317c478bd9Sstevel@tonic-gate 	adp++;			/* move to buffer argument */
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	adp->arg_value = 0;
3347c478bd9Sstevel@tonic-gate 	adp->arg_type = AT_BYREF;
3357c478bd9Sstevel@tonic-gate 	adp->arg_inout = AI_OUTPUT;
3367c478bd9Sstevel@tonic-gate #ifdef _LP64
3377c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
3387c478bd9Sstevel@tonic-gate 		adp->arg_object = &statb64_32;
3397c478bd9Sstevel@tonic-gate 		adp->arg_size = sizeof (statb64_32);
3407c478bd9Sstevel@tonic-gate 	} else {
3417c478bd9Sstevel@tonic-gate 		adp->arg_object = buf;
3427c478bd9Sstevel@tonic-gate 		adp->arg_size = sizeof (*buf);
3437c478bd9Sstevel@tonic-gate 	}
3447c478bd9Sstevel@tonic-gate #else	/* _LP64 */
3457c478bd9Sstevel@tonic-gate 	adp->arg_object = buf;
3467c478bd9Sstevel@tonic-gate 	adp->arg_size = sizeof (*buf);
3477c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
348*8fd04b83SRoger A. Faulkner 	adp++;			/* move to flags argument */
3497c478bd9Sstevel@tonic-gate 
350*8fd04b83SRoger A. Faulkner 	adp->arg_value = 0;
351*8fd04b83SRoger A. Faulkner 	adp->arg_object = NULL;
352*8fd04b83SRoger A. Faulkner 	adp->arg_type = AT_BYVAL;
353*8fd04b83SRoger A. Faulkner 	adp->arg_inout = AI_INPUT;
354*8fd04b83SRoger A. Faulkner 	adp->arg_size = 0;
355*8fd04b83SRoger A. Faulkner 
356*8fd04b83SRoger A. Faulkner 	error = Psyscall(Pr, &rval, syscall, 4, &argd[0]);
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	if (error) {
3597c478bd9Sstevel@tonic-gate 		errno = (error > 0)? error : ENOSYS;
3607c478bd9Sstevel@tonic-gate 		return (-1);
3617c478bd9Sstevel@tonic-gate 	}
3627c478bd9Sstevel@tonic-gate #ifdef _LP64
3637c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
3647c478bd9Sstevel@tonic-gate 		stat64_32_to_n(&statb64_32, (struct stat *)buf);
3657c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
3667c478bd9Sstevel@tonic-gate 	return (0);
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate /*
3707c478bd9Sstevel@tonic-gate  * lstat64() system call -- executed by subject process
3717c478bd9Sstevel@tonic-gate  */
3727c478bd9Sstevel@tonic-gate int
pr_lstat64(struct ps_prochandle * Pr,const char * path,struct stat64 * buf)3737c478bd9Sstevel@tonic-gate pr_lstat64(struct ps_prochandle *Pr, const char *path, struct stat64 *buf)
3747c478bd9Sstevel@tonic-gate {
375*8fd04b83SRoger A. Faulkner 	sysret_t rval;			/* return value from stat() */
376*8fd04b83SRoger A. Faulkner 	argdes_t argd[4];		/* arg descriptors for fstatat() */
3777c478bd9Sstevel@tonic-gate 	argdes_t *adp = &argd[0];	/* first argument */
378*8fd04b83SRoger A. Faulkner 	int syscall;			/* SYS_fstatat or SYS_fstatat64 */
3797c478bd9Sstevel@tonic-gate 	int error;
3807c478bd9Sstevel@tonic-gate #ifdef _LP64
3817c478bd9Sstevel@tonic-gate 	struct stat64_32 statb64_32;
3827c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	if (Pr == NULL)		/* no subject process */
3857c478bd9Sstevel@tonic-gate 		return (lstat64(path, buf));
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
3887c478bd9Sstevel@tonic-gate 		/*
3897c478bd9Sstevel@tonic-gate 		 * 32-bit native and
3907c478bd9Sstevel@tonic-gate 		 * 64-bit process controls 32-bit subject process
3917c478bd9Sstevel@tonic-gate 		 */
392*8fd04b83SRoger A. Faulkner 		syscall = SYS_fstatat64;
3937c478bd9Sstevel@tonic-gate 	} else {
3947c478bd9Sstevel@tonic-gate 		/* 64-bit native */
395*8fd04b83SRoger A. Faulkner 		syscall = SYS_fstatat;
3967c478bd9Sstevel@tonic-gate 	}
3977c478bd9Sstevel@tonic-gate 
398*8fd04b83SRoger A. Faulkner 	adp->arg_value = AT_FDCWD;
399*8fd04b83SRoger A. Faulkner 	adp->arg_object = NULL;
400*8fd04b83SRoger A. Faulkner 	adp->arg_type = AT_BYVAL;
401*8fd04b83SRoger A. Faulkner 	adp->arg_inout = AI_INPUT;
402*8fd04b83SRoger A. Faulkner 	adp->arg_size = 0;
403*8fd04b83SRoger A. Faulkner 	adp++;			/* move to path argument */
404*8fd04b83SRoger A. Faulkner 
4057c478bd9Sstevel@tonic-gate 	adp->arg_value = 0;
4067c478bd9Sstevel@tonic-gate 	adp->arg_object = (void *)path;
4077c478bd9Sstevel@tonic-gate 	adp->arg_type = AT_BYREF;
4087c478bd9Sstevel@tonic-gate 	adp->arg_inout = AI_INPUT;
4097c478bd9Sstevel@tonic-gate 	adp->arg_size = strlen(path) + 1;
4107c478bd9Sstevel@tonic-gate 	adp++;			/* move to buffer argument */
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 	adp->arg_value = 0;
4137c478bd9Sstevel@tonic-gate 	adp->arg_type = AT_BYREF;
4147c478bd9Sstevel@tonic-gate 	adp->arg_inout = AI_OUTPUT;
4157c478bd9Sstevel@tonic-gate #ifdef _LP64
4167c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
4177c478bd9Sstevel@tonic-gate 		adp->arg_object = &statb64_32;
4187c478bd9Sstevel@tonic-gate 		adp->arg_size = sizeof (statb64_32);
4197c478bd9Sstevel@tonic-gate 	} else {
4207c478bd9Sstevel@tonic-gate 		adp->arg_object = buf;
4217c478bd9Sstevel@tonic-gate 		adp->arg_size = sizeof (*buf);
4227c478bd9Sstevel@tonic-gate 	}
4237c478bd9Sstevel@tonic-gate #else	/* _LP64 */
4247c478bd9Sstevel@tonic-gate 	adp->arg_object = buf;
4257c478bd9Sstevel@tonic-gate 	adp->arg_size = sizeof (*buf);
4267c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
427*8fd04b83SRoger A. Faulkner 	adp++;			/* move to flags argument */
4287c478bd9Sstevel@tonic-gate 
429*8fd04b83SRoger A. Faulkner 	adp->arg_value = AT_SYMLINK_NOFOLLOW;
430*8fd04b83SRoger A. Faulkner 	adp->arg_object = NULL;
431*8fd04b83SRoger A. Faulkner 	adp->arg_type = AT_BYVAL;
432*8fd04b83SRoger A. Faulkner 	adp->arg_inout = AI_INPUT;
433*8fd04b83SRoger A. Faulkner 	adp->arg_size = 0;
434*8fd04b83SRoger A. Faulkner 
435*8fd04b83SRoger A. Faulkner 	error = Psyscall(Pr, &rval, syscall, 4, &argd[0]);
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 	if (error) {
4387c478bd9Sstevel@tonic-gate 		errno = (error > 0)? error : ENOSYS;
4397c478bd9Sstevel@tonic-gate 		return (-1);
4407c478bd9Sstevel@tonic-gate 	}
4417c478bd9Sstevel@tonic-gate #ifdef _LP64
4427c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
4437c478bd9Sstevel@tonic-gate 		stat64_32_to_n(&statb64_32, (struct stat *)buf);
4447c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
4457c478bd9Sstevel@tonic-gate 	return (0);
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate /*
4497c478bd9Sstevel@tonic-gate  * fstat64() system call -- executed by subject process
4507c478bd9Sstevel@tonic-gate  */
4517c478bd9Sstevel@tonic-gate int
pr_fstat64(struct ps_prochandle * Pr,int fd,struct stat64 * buf)4527c478bd9Sstevel@tonic-gate pr_fstat64(struct ps_prochandle *Pr, int fd, struct stat64 *buf)
4537c478bd9Sstevel@tonic-gate {
454*8fd04b83SRoger A. Faulkner 	sysret_t rval;			/* return value from stat() */
455*8fd04b83SRoger A. Faulkner 	argdes_t argd[4];		/* arg descriptors for fstatat() */
4567c478bd9Sstevel@tonic-gate 	argdes_t *adp = &argd[0];	/* first argument */
457*8fd04b83SRoger A. Faulkner 	int syscall;			/* SYS_fstatat or SYS_fstatat64 */
4587c478bd9Sstevel@tonic-gate 	int error;
4597c478bd9Sstevel@tonic-gate #ifdef _LP64
4607c478bd9Sstevel@tonic-gate 	struct stat64_32 statb64_32;
4617c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	if (Pr == NULL)		/* no subject process */
4647c478bd9Sstevel@tonic-gate 		return (fstat64(fd, buf));
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
4677c478bd9Sstevel@tonic-gate 		/*
4687c478bd9Sstevel@tonic-gate 		 * 32-bit native and
4697c478bd9Sstevel@tonic-gate 		 * 64-bit process controls 32-bit subject process
4707c478bd9Sstevel@tonic-gate 		 */
471*8fd04b83SRoger A. Faulkner 		syscall = SYS_fstatat64;
4727c478bd9Sstevel@tonic-gate 	} else {
4737c478bd9Sstevel@tonic-gate 		/* 64-bit native */
474*8fd04b83SRoger A. Faulkner 		syscall = SYS_fstatat;
4757c478bd9Sstevel@tonic-gate 	}
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	adp->arg_value = fd;
4787c478bd9Sstevel@tonic-gate 	adp->arg_object = NULL;
4797c478bd9Sstevel@tonic-gate 	adp->arg_type = AT_BYVAL;
4807c478bd9Sstevel@tonic-gate 	adp->arg_inout = AI_INPUT;
4817c478bd9Sstevel@tonic-gate 	adp->arg_size = 0;
482*8fd04b83SRoger A. Faulkner 	adp++;			/* move to path argument */
483*8fd04b83SRoger A. Faulkner 
484*8fd04b83SRoger A. Faulkner 	adp->arg_value = 0;
485*8fd04b83SRoger A. Faulkner 	adp->arg_object = NULL;
486*8fd04b83SRoger A. Faulkner 	adp->arg_type = AT_BYVAL;
487*8fd04b83SRoger A. Faulkner 	adp->arg_inout = AI_INPUT;
488*8fd04b83SRoger A. Faulkner 	adp->arg_size = 0;
4897c478bd9Sstevel@tonic-gate 	adp++;			/* move to buffer argument */
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate 	adp->arg_value = 0;
4927c478bd9Sstevel@tonic-gate 	adp->arg_type = AT_BYREF;
4937c478bd9Sstevel@tonic-gate 	adp->arg_inout = AI_OUTPUT;
4947c478bd9Sstevel@tonic-gate #ifdef _LP64
4957c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
4967c478bd9Sstevel@tonic-gate 		adp->arg_object = &statb64_32;
4977c478bd9Sstevel@tonic-gate 		adp->arg_size = sizeof (statb64_32);
4987c478bd9Sstevel@tonic-gate 	} else {
4997c478bd9Sstevel@tonic-gate 		adp->arg_object = buf;
5007c478bd9Sstevel@tonic-gate 		adp->arg_size = sizeof (*buf);
5017c478bd9Sstevel@tonic-gate 	}
5027c478bd9Sstevel@tonic-gate #else	/* _LP64 */
5037c478bd9Sstevel@tonic-gate 	adp->arg_object = buf;
5047c478bd9Sstevel@tonic-gate 	adp->arg_size = sizeof (*buf);
5057c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
506*8fd04b83SRoger A. Faulkner 	adp++;			/* move to flags argument */
507*8fd04b83SRoger A. Faulkner 
508*8fd04b83SRoger A. Faulkner 	adp->arg_value = 0;
509*8fd04b83SRoger A. Faulkner 	adp->arg_object = NULL;
510*8fd04b83SRoger A. Faulkner 	adp->arg_type = AT_BYVAL;
511*8fd04b83SRoger A. Faulkner 	adp->arg_inout = AI_INPUT;
512*8fd04b83SRoger A. Faulkner 	adp->arg_size = 0;
5137c478bd9Sstevel@tonic-gate 
514*8fd04b83SRoger A. Faulkner 	error = Psyscall(Pr, &rval, syscall, 4, &argd[0]);
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 	if (error) {
5177c478bd9Sstevel@tonic-gate 		errno = (error > 0)? error : ENOSYS;
5187c478bd9Sstevel@tonic-gate 		return (-1);
5197c478bd9Sstevel@tonic-gate 	}
5207c478bd9Sstevel@tonic-gate #ifdef _LP64
5217c478bd9Sstevel@tonic-gate 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
5227c478bd9Sstevel@tonic-gate 		stat64_32_to_n(&statb64_32, (struct stat *)buf);
5237c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
5247c478bd9Sstevel@tonic-gate 	return (0);
5257c478bd9Sstevel@tonic-gate }
526