xref: /illumos-gate/usr/src/lib/libproc/common/pr_stat.c (revision 942c5e3c2dd127463517e5cc1694ee94ca45e021)
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