Home | History | Annotate | Download | only in common
      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, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright (c) 1997-2001 by Sun Microsystems, Inc.
     24  * All rights reserved.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include <sys/isa_defs.h>
     30 
     31 #include <stdlib.h>
     32 #include <unistd.h>
     33 #include <string.h>
     34 #include <errno.h>
     35 #include <sys/types.h>
     36 #include <sys/stat.h>
     37 #include <sys/sysmacros.h>
     38 #include "libproc.h"
     39 
     40 #ifdef _LP64
     41 /*
     42  * in case of 64-bit *stat() and *stat64 library call and 32-bit subject
     43  * process convert 64-bit struct stat/stat64 into 32-bit struct stat64
     44  */
     45 static void
     46 stat64_32_to_n(struct stat64_32 *src, struct stat *dest)
     47 {
     48 	(void) memset(dest, 0, sizeof (*dest));
     49 	dest->st_dev = DEVEXPL(src->st_dev);
     50 	dest->st_ino = (ino_t)src->st_ino;
     51 	dest->st_mode = (mode_t)src->st_mode;
     52 	dest->st_nlink = (nlink_t)src->st_nlink;
     53 	dest->st_uid = (uid_t)src->st_uid;
     54 	dest->st_gid = (gid_t)src->st_gid;
     55 	dest->st_rdev = DEVEXPL(src->st_rdev);
     56 	dest->st_size = (off_t)src->st_size;
     57 	TIMESPEC32_TO_TIMESPEC(&dest->st_atim, &src->st_atim);
     58 	TIMESPEC32_TO_TIMESPEC(&dest->st_mtim, &src->st_mtim);
     59 	TIMESPEC32_TO_TIMESPEC(&dest->st_ctim, &src->st_ctim);
     60 	dest->st_blksize = (blksize_t)src->st_blksize;
     61 	dest->st_blocks = (blkcnt_t)src->st_blocks;
     62 	(void) memcpy(dest->st_fstype, src->st_fstype,
     63 	    sizeof (dest->st_fstype));
     64 }
     65 #endif	/* _LP64 */
     66 
     67 /*
     68  * stat() system call -- executed by subject process
     69  */
     70 int
     71 pr_stat(struct ps_prochandle *Pr, const char *path, struct stat *buf)
     72 {
     73 	sysret_t rval;			/* return value from stat() */
     74 	argdes_t argd[3];		/* arg descriptors for stat() */
     75 	argdes_t *adp = &argd[0];	/* first argument */
     76 	int syscall;			/* stat, xstat or stat64 */
     77 	int nargs = 2;			/* number of actual arguments */
     78 	int error;
     79 #ifdef _LP64
     80 	struct stat64_32 statb64_32;
     81 #endif	/* _LP64 */
     82 
     83 	if (Pr == NULL)		/* no subject process */
     84 		return (stat(path, buf));
     85 
     86 	/*
     87 	 * This is filthy, but /proc reveals everything about the
     88 	 * system call interfaces, despite what the architects of the
     89 	 * header files may desire.  We have to know here whether we
     90 	 * are calling stat() or xstat() in the subject.
     91 	 */
     92 #if defined(_STAT_VER)
     93 	syscall = SYS_xstat;
     94 	nargs = 3;
     95 	adp->arg_value = _STAT_VER;
     96 	adp->arg_object = NULL;
     97 	adp->arg_type = AT_BYVAL;
     98 	adp->arg_inout = AI_INPUT;
     99 	adp->arg_size = 0;
    100 	adp++;			/* move to pathname argument */
    101 #else
    102 	if (Pstatus(Pr)->pr_dmodel != PR_MODEL_NATIVE) {
    103 		/* 64-bit process controls 32-bit subject process */
    104 		syscall = SYS_stat64;
    105 	} else {
    106 		syscall = SYS_stat;
    107 	}
    108 #endif
    109 
    110 	adp->arg_value = 0;
    111 	adp->arg_object = (void *)path;
    112 	adp->arg_type = AT_BYREF;
    113 	adp->arg_inout = AI_INPUT;
    114 	adp->arg_size = strlen(path) + 1;
    115 	adp++;			/* move to buffer argument */
    116 
    117 	adp->arg_value = 0;
    118 	adp->arg_type = AT_BYREF;
    119 	adp->arg_inout = AI_OUTPUT;
    120 #ifdef _LP64
    121 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
    122 		adp->arg_object = &statb64_32;
    123 		adp->arg_size = sizeof (statb64_32);
    124 	} else {
    125 		adp->arg_object = buf;
    126 		adp->arg_size = sizeof (*buf);
    127 	}
    128 #else	/* _LP64 */
    129 	adp->arg_object = buf;
    130 	adp->arg_size = sizeof (*buf);
    131 #endif	/* _LP64 */
    132 
    133 	error = Psyscall(Pr, &rval, syscall, nargs, &argd[0]);
    134 
    135 	if (error) {
    136 		errno = (error > 0)? error : ENOSYS;
    137 		return (-1);
    138 	}
    139 #ifdef _LP64
    140 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
    141 		stat64_32_to_n(&statb64_32, buf);
    142 #endif	/* _LP64 */
    143 	return (0);
    144 }
    145 
    146 /*
    147  * lstat() system call -- executed by subject process
    148  */
    149 int
    150 pr_lstat(struct ps_prochandle *Pr, const char *path, struct stat *buf)
    151 {
    152 	sysret_t rval;			/* return value from lstat() */
    153 	argdes_t argd[3];		/* arg descriptors for lstat() */
    154 	argdes_t *adp = &argd[0];	/* first argument */
    155 	int syscall;			/* lstat, lxstat or lstat64 */
    156 	int nargs = 2;			/* number of actual arguments */
    157 	int error;
    158 #ifdef _LP64
    159 	struct stat64_32 statb64_32;
    160 #endif	/* _LP64 */
    161 
    162 	if (Pr == NULL)		/* no subject process */
    163 		return (lstat(path, buf));
    164 
    165 	/*
    166 	 * This is filthy, but /proc reveals everything about the
    167 	 * system call interfaces, despite what the architects of the
    168 	 * header files may desire.  We have to know here whether we
    169 	 * are calling lstat() or lxstat() in the subject.
    170 	 */
    171 #if defined(_STAT_VER)
    172 	syscall = SYS_lxstat;
    173 	nargs = 3;
    174 	adp->arg_value = _STAT_VER;
    175 	adp->arg_object = NULL;
    176 	adp->arg_type = AT_BYVAL;
    177 	adp->arg_inout = AI_INPUT;
    178 	adp->arg_size = 0;
    179 	adp++;			/* move to pathname argument */
    180 #else
    181 	if (Pstatus(Pr)->pr_dmodel != PR_MODEL_NATIVE) {
    182 		/* 64-bit process controls 32-bit subject process */
    183 		syscall = SYS_lstat64;
    184 	} else {
    185 		syscall = SYS_lstat;
    186 	}
    187 #endif
    188 
    189 	adp->arg_value = 0;
    190 	adp->arg_object = (void *)path;
    191 	adp->arg_type = AT_BYREF;
    192 	adp->arg_inout = AI_INPUT;
    193 	adp->arg_size = strlen(path) + 1;
    194 	adp++;			/* move to buffer argument */
    195 
    196 	adp->arg_value = 0;
    197 	adp->arg_type = AT_BYREF;
    198 	adp->arg_inout = AI_OUTPUT;
    199 #ifdef _LP64
    200 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
    201 		adp->arg_object = &statb64_32;
    202 		adp->arg_size = sizeof (statb64_32);
    203 	} else {
    204 		adp->arg_object = buf;
    205 		adp->arg_size = sizeof (*buf);
    206 	}
    207 #else	/* _LP64 */
    208 	adp->arg_object = buf;
    209 	adp->arg_size = sizeof (*buf);
    210 #endif	/* _LP64 */
    211 
    212 	error = Psyscall(Pr, &rval, syscall, nargs, &argd[0]);
    213 
    214 	if (error) {
    215 		errno = (error > 0)? error : ENOSYS;
    216 		return (-1);
    217 	}
    218 #ifdef _LP64
    219 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
    220 		stat64_32_to_n(&statb64_32, buf);
    221 #endif	/* _LP64 */
    222 	return (0);
    223 }
    224 
    225 /*
    226  * fstat() system call -- executed by subject process
    227  */
    228 int
    229 pr_fstat(struct ps_prochandle *Pr, int fd, struct stat *buf)
    230 {
    231 	sysret_t rval;			/* return value from fstat() */
    232 	argdes_t argd[3];		/* arg descriptors for fstat() */
    233 	argdes_t *adp = &argd[0];	/* first argument */
    234 	int syscall;			/* fstat, fxstat or fstat64 */
    235 	int nargs = 2;			/* number of actual arguments */
    236 	int error;
    237 #ifdef _LP64
    238 	struct stat64_32 statb64_32;
    239 #endif	/* _LP64 */
    240 
    241 	if (Pr == NULL)		/* no subject process */
    242 		return (fstat(fd, buf));
    243 
    244 	/*
    245 	 * This is filthy, but /proc reveals everything about the
    246 	 * system call interfaces, despite what the architects of the
    247 	 * header files may desire.  We have to know here whether we
    248 	 * are calling fstat() or fxstat() in the subject.
    249 	 */
    250 #if defined(_STAT_VER)
    251 	syscall = SYS_fxstat;
    252 	nargs = 3;
    253 	adp->arg_value = _STAT_VER;
    254 	adp->arg_object = NULL;
    255 	adp->arg_type = AT_BYVAL;
    256 	adp->arg_inout = AI_INPUT;
    257 	adp->arg_size = 0;
    258 	adp++;			/* move to fd argument */
    259 #else
    260 	if (Pstatus(Pr)->pr_dmodel != PR_MODEL_NATIVE) {
    261 		/* 64-bit process controls 32-bit subject process */
    262 		syscall = SYS_fstat64;
    263 	} else {
    264 		syscall = SYS_fstat;
    265 	}
    266 #endif
    267 
    268 	adp->arg_value = fd;
    269 	adp->arg_object = NULL;
    270 	adp->arg_type = AT_BYVAL;
    271 	adp->arg_inout = AI_INPUT;
    272 	adp->arg_size = 0;
    273 	adp++;			/* move to buffer argument */
    274 
    275 	adp->arg_value = 0;
    276 	adp->arg_type = AT_BYREF;
    277 	adp->arg_inout = AI_OUTPUT;
    278 #ifdef _LP64
    279 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
    280 		adp->arg_object = &statb64_32;
    281 		adp->arg_size = sizeof (statb64_32);
    282 	} else {
    283 		adp->arg_object = buf;
    284 		adp->arg_size = sizeof (*buf);
    285 	}
    286 #else	/* _LP64 */
    287 	adp->arg_object = buf;
    288 	adp->arg_size = sizeof (*buf);
    289 #endif	/* _LP64 */
    290 
    291 	error = Psyscall(Pr, &rval, syscall, nargs, &argd[0]);
    292 
    293 	if (error) {
    294 		errno = (error > 0)? error : ENOSYS;
    295 		return (-1);
    296 	}
    297 #ifdef _LP64
    298 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
    299 		stat64_32_to_n(&statb64_32, buf);
    300 #endif	/* _LP64 */
    301 	return (0);
    302 }
    303 
    304 /*
    305  * stat64() system call -- executed by subject process
    306  */
    307 int
    308 pr_stat64(struct ps_prochandle *Pr, const char *path, struct stat64 *buf)
    309 {
    310 	sysret_t rval;			/* return value from stat64() */
    311 	argdes_t argd[2];		/* arg descriptors for stat64() */
    312 	argdes_t *adp = &argd[0];	/* first argument */
    313 	int syscall;			/* stat or stat64 */
    314 	int nargs = 2;			/* number of actual arguments */
    315 	int error;
    316 #ifdef _LP64
    317 	struct stat64_32 statb64_32;
    318 #endif	/* _LP64 */
    319 
    320 	if (Pr == NULL)		/* no subject process */
    321 		return (stat64(path, buf));
    322 
    323 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
    324 		/*
    325 		 * 32-bit native and
    326 		 * 64-bit process controls 32-bit subject process
    327 		 */
    328 		syscall = SYS_stat64;
    329 	} else {
    330 		/* 64-bit native */
    331 		syscall = SYS_stat;
    332 	}
    333 
    334 	adp->arg_value = 0;
    335 	adp->arg_object = (void *)path;
    336 	adp->arg_type = AT_BYREF;
    337 	adp->arg_inout = AI_INPUT;
    338 	adp->arg_size = strlen(path) + 1;
    339 	adp++;			/* move to buffer argument */
    340 
    341 	adp->arg_value = 0;
    342 	adp->arg_type = AT_BYREF;
    343 	adp->arg_inout = AI_OUTPUT;
    344 #ifdef _LP64
    345 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
    346 		adp->arg_object = &statb64_32;
    347 		adp->arg_size = sizeof (statb64_32);
    348 	} else {
    349 		adp->arg_object = buf;
    350 		adp->arg_size = sizeof (*buf);
    351 	}
    352 #else	/* _LP64 */
    353 	adp->arg_object = buf;
    354 	adp->arg_size = sizeof (*buf);
    355 #endif	/* _LP64 */
    356 
    357 	error = Psyscall(Pr, &rval, syscall, nargs, &argd[0]);
    358 
    359 	if (error) {
    360 		errno = (error > 0)? error : ENOSYS;
    361 		return (-1);
    362 	}
    363 #ifdef _LP64
    364 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
    365 		stat64_32_to_n(&statb64_32, (struct stat *)buf);
    366 #endif	/* _LP64 */
    367 	return (0);
    368 }
    369 
    370 /*
    371  * lstat64() system call -- executed by subject process
    372  */
    373 int
    374 pr_lstat64(struct ps_prochandle *Pr, const char *path, struct stat64 *buf)
    375 {
    376 	sysret_t rval;			/* return value from lstat64() */
    377 	argdes_t argd[2];		/* arg descriptors for lstat64() */
    378 	argdes_t *adp = &argd[0];	/* first argument */
    379 	int syscall;			/* lstat or lstat64 */
    380 	int nargs = 2;			/* number of actual arguments */
    381 	int error;
    382 #ifdef _LP64
    383 	struct stat64_32 statb64_32;
    384 #endif	/* _LP64 */
    385 
    386 	if (Pr == NULL)		/* no subject process */
    387 		return (lstat64(path, buf));
    388 
    389 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
    390 		/*
    391 		 * 32-bit native and
    392 		 * 64-bit process controls 32-bit subject process
    393 		 */
    394 		syscall = SYS_lstat64;
    395 	} else {
    396 		/* 64-bit native */
    397 		syscall = SYS_lstat;
    398 	}
    399 
    400 	adp->arg_value = 0;
    401 	adp->arg_object = (void *)path;
    402 	adp->arg_type = AT_BYREF;
    403 	adp->arg_inout = AI_INPUT;
    404 	adp->arg_size = strlen(path) + 1;
    405 	adp++;			/* move to buffer argument */
    406 
    407 	adp->arg_value = 0;
    408 	adp->arg_type = AT_BYREF;
    409 	adp->arg_inout = AI_OUTPUT;
    410 #ifdef _LP64
    411 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
    412 		adp->arg_object = &statb64_32;
    413 		adp->arg_size = sizeof (statb64_32);
    414 	} else {
    415 		adp->arg_object = buf;
    416 		adp->arg_size = sizeof (*buf);
    417 	}
    418 #else	/* _LP64 */
    419 	adp->arg_object = buf;
    420 	adp->arg_size = sizeof (*buf);
    421 #endif	/* _LP64 */
    422 
    423 	error = Psyscall(Pr, &rval, syscall, nargs, &argd[0]);
    424 
    425 	if (error) {
    426 		errno = (error > 0)? error : ENOSYS;
    427 		return (-1);
    428 	}
    429 #ifdef _LP64
    430 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
    431 		stat64_32_to_n(&statb64_32, (struct stat *)buf);
    432 #endif	/* _LP64 */
    433 	return (0);
    434 }
    435 
    436 /*
    437  * fstat64() system call -- executed by subject process
    438  */
    439 int
    440 pr_fstat64(struct ps_prochandle *Pr, int fd, struct stat64 *buf)
    441 {
    442 	sysret_t rval;			/* return value from fstat64() */
    443 	argdes_t argd[2];		/* arg descriptors for fstat64() */
    444 	argdes_t *adp = &argd[0];	/* first argument */
    445 	int syscall;			/* fstat or fstat64 */
    446 	int nargs = 2;			/* number of actual arguments */
    447 	int error;
    448 #ifdef _LP64
    449 	struct stat64_32 statb64_32;
    450 #endif	/* _LP64 */
    451 
    452 	if (Pr == NULL)		/* no subject process */
    453 		return (fstat64(fd, buf));
    454 
    455 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
    456 		/*
    457 		 * 32-bit native and
    458 		 * 64-bit process controls 32-bit subject process
    459 		 */
    460 		syscall = SYS_fstat64;
    461 	} else {
    462 		/* 64-bit native */
    463 		syscall = SYS_fstat;
    464 	}
    465 
    466 	adp->arg_value = fd;
    467 	adp->arg_object = NULL;
    468 	adp->arg_type = AT_BYVAL;
    469 	adp->arg_inout = AI_INPUT;
    470 	adp->arg_size = 0;
    471 	adp++;			/* move to buffer argument */
    472 
    473 	adp->arg_value = 0;
    474 	adp->arg_type = AT_BYREF;
    475 	adp->arg_inout = AI_OUTPUT;
    476 #ifdef _LP64
    477 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
    478 		adp->arg_object = &statb64_32;
    479 		adp->arg_size = sizeof (statb64_32);
    480 	} else {
    481 		adp->arg_object = buf;
    482 		adp->arg_size = sizeof (*buf);
    483 	}
    484 #else	/* _LP64 */
    485 	adp->arg_object = buf;
    486 	adp->arg_size = sizeof (*buf);
    487 #endif	/* _LP64 */
    488 
    489 	error = Psyscall(Pr, &rval, syscall, nargs, &argd[0]);
    490 
    491 	if (error) {
    492 		errno = (error > 0)? error : ENOSYS;
    493 		return (-1);
    494 	}
    495 #ifdef _LP64
    496 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
    497 		stat64_32_to_n(&statb64_32, (struct stat *)buf);
    498 #endif	/* _LP64 */
    499 	return (0);
    500 }
    501