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 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 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 83*8fd04b83SRoger A. Faulkner if (Pstatus(Pr)->pr_dmodel != PR_MODEL_NATIVE) { 84*8fd04b83SRoger A. Faulkner /* 64-bit process controls 32-bit subject process */ 85*8fd04b83SRoger A. Faulkner syscall = SYS_fstatat64; 86*8fd04b83SRoger A. Faulkner } else { 87*8fd04b83SRoger A. Faulkner syscall = SYS_fstatat; 88*8fd04b83SRoger A. Faulkner } 89*8fd04b83SRoger A. Faulkner 90*8fd04b83SRoger A. Faulkner adp->arg_value = AT_FDCWD; 917c478bd9Sstevel@tonic-gate adp->arg_object = NULL; 927c478bd9Sstevel@tonic-gate adp->arg_type = AT_BYVAL; 937c478bd9Sstevel@tonic-gate adp->arg_inout = AI_INPUT; 947c478bd9Sstevel@tonic-gate 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 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 158*8fd04b83SRoger A. Faulkner if (Pstatus(Pr)->pr_dmodel != PR_MODEL_NATIVE) { 159*8fd04b83SRoger A. Faulkner /* 64-bit process controls 32-bit subject process */ 160*8fd04b83SRoger A. Faulkner syscall = SYS_fstatat64; 161*8fd04b83SRoger A. Faulkner } else { 162*8fd04b83SRoger A. Faulkner syscall = SYS_fstatat; 163*8fd04b83SRoger A. Faulkner } 164*8fd04b83SRoger A. Faulkner 165*8fd04b83SRoger A. Faulkner adp->arg_value = AT_FDCWD; 1667c478bd9Sstevel@tonic-gate adp->arg_object = NULL; 1677c478bd9Sstevel@tonic-gate adp->arg_type = AT_BYVAL; 1687c478bd9Sstevel@tonic-gate adp->arg_inout = AI_INPUT; 1697c478bd9Sstevel@tonic-gate 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 */ 1957c478bd9Sstevel@tonic-gate 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; 201*8fd04b83SRoger A. Faulkner 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 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 233*8fd04b83SRoger A. Faulkner if (Pstatus(Pr)->pr_dmodel != PR_MODEL_NATIVE) { 234*8fd04b83SRoger A. Faulkner /* 64-bit process controls 32-bit subject process */ 235*8fd04b83SRoger A. Faulkner syscall = SYS_fstatat64; 236*8fd04b83SRoger A. Faulkner } else { 237*8fd04b83SRoger A. Faulkner syscall = SYS_fstatat; 238*8fd04b83SRoger A. Faulkner } 239*8fd04b83SRoger A. Faulkner 240*8fd04b83SRoger A. Faulkner 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 */ 2467c478bd9Sstevel@tonic-gate 247*8fd04b83SRoger A. Faulkner adp->arg_value = 0; 2487c478bd9Sstevel@tonic-gate adp->arg_object = NULL; 2497c478bd9Sstevel@tonic-gate adp->arg_type = AT_BYVAL; 2507c478bd9Sstevel@tonic-gate adp->arg_inout = AI_INPUT; 2517c478bd9Sstevel@tonic-gate 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 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 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 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 */ 5077c478bd9Sstevel@tonic-gate 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; 513*8fd04b83SRoger A. Faulkner 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