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/isa_defs.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/fcntl.h>
35 #include <sys/sysmacros.h>
36 #include "libproc.h"
37
38 #ifdef _LP64
39 /*
40 * in case of 64-bit *stat() and *stat64 library call and 32-bit subject
41 * process convert 64-bit struct stat/stat64 into 32-bit struct stat64
42 */
43 static void
stat64_32_to_n(struct stat64_32 * src,struct stat * dest)44 stat64_32_to_n(struct stat64_32 *src, struct stat *dest)
45 {
46 (void) memset(dest, 0, sizeof (*dest));
47 dest->st_dev = DEVEXPL(src->st_dev);
48 dest->st_ino = (ino_t)src->st_ino;
49 dest->st_mode = (mode_t)src->st_mode;
50 dest->st_nlink = (nlink_t)src->st_nlink;
51 dest->st_uid = (uid_t)src->st_uid;
52 dest->st_gid = (gid_t)src->st_gid;
53 dest->st_rdev = DEVEXPL(src->st_rdev);
54 dest->st_size = (off_t)src->st_size;
55 TIMESPEC32_TO_TIMESPEC(&dest->st_atim, &src->st_atim);
56 TIMESPEC32_TO_TIMESPEC(&dest->st_mtim, &src->st_mtim);
57 TIMESPEC32_TO_TIMESPEC(&dest->st_ctim, &src->st_ctim);
58 dest->st_blksize = (blksize_t)src->st_blksize;
59 dest->st_blocks = (blkcnt_t)src->st_blocks;
60 (void) memcpy(dest->st_fstype, src->st_fstype,
61 sizeof (dest->st_fstype));
62 }
63 #endif /* _LP64 */
64
65 /*
66 * stat() system call -- executed by subject process
67 */
68 int
pr_stat(struct ps_prochandle * Pr,const char * path,struct stat * buf)69 pr_stat(struct ps_prochandle *Pr, const char *path, struct stat *buf)
70 {
71 sysret_t rval; /* return value from stat() */
72 argdes_t argd[4]; /* arg descriptors for fstatat() */
73 argdes_t *adp = &argd[0]; /* first argument */
74 int syscall; /* SYS_fstatat or SYS_fstatat64 */
75 int error;
76 #ifdef _LP64
77 struct stat64_32 statb64_32;
78 #endif /* _LP64 */
79
80 if (Pr == NULL) /* no subject process */
81 return (stat(path, buf));
82
83 if (Pstatus(Pr)->pr_dmodel != PR_MODEL_NATIVE) {
84 /* 64-bit process controls 32-bit subject process */
85 syscall = SYS_fstatat64;
86 } else {
87 syscall = SYS_fstatat;
88 }
89
90 adp->arg_value = AT_FDCWD;
91 adp->arg_object = NULL;
92 adp->arg_type = AT_BYVAL;
93 adp->arg_inout = AI_INPUT;
94 adp->arg_size = 0;
95 adp++; /* move to path argument */
96
97 adp->arg_value = 0;
98 adp->arg_object = (void *)path;
99 adp->arg_type = AT_BYREF;
100 adp->arg_inout = AI_INPUT;
101 adp->arg_size = strlen(path) + 1;
102 adp++; /* move to buffer argument */
103
104 adp->arg_value = 0;
105 adp->arg_type = AT_BYREF;
106 adp->arg_inout = AI_OUTPUT;
107 #ifdef _LP64
108 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
109 adp->arg_object = &statb64_32;
110 adp->arg_size = sizeof (statb64_32);
111 } else {
112 adp->arg_object = buf;
113 adp->arg_size = sizeof (*buf);
114 }
115 #else /* _LP64 */
116 adp->arg_object = buf;
117 adp->arg_size = sizeof (*buf);
118 #endif /* _LP64 */
119 adp++; /* move to flags argument */
120
121 adp->arg_value = 0;
122 adp->arg_object = NULL;
123 adp->arg_type = AT_BYVAL;
124 adp->arg_inout = AI_INPUT;
125 adp->arg_size = 0;
126
127 error = Psyscall(Pr, &rval, syscall, 4, &argd[0]);
128
129 if (error) {
130 errno = (error > 0)? error : ENOSYS;
131 return (-1);
132 }
133 #ifdef _LP64
134 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
135 stat64_32_to_n(&statb64_32, buf);
136 #endif /* _LP64 */
137 return (0);
138 }
139
140 /*
141 * lstat() system call -- executed by subject process
142 */
143 int
pr_lstat(struct ps_prochandle * Pr,const char * path,struct stat * buf)144 pr_lstat(struct ps_prochandle *Pr, const char *path, struct stat *buf)
145 {
146 sysret_t rval; /* return value from stat() */
147 argdes_t argd[4]; /* arg descriptors for fstatat() */
148 argdes_t *adp = &argd[0]; /* first argument */
149 int syscall; /* SYS_fstatat or SYS_fstatat64 */
150 int error;
151 #ifdef _LP64
152 struct stat64_32 statb64_32;
153 #endif /* _LP64 */
154
155 if (Pr == NULL) /* no subject process */
156 return (lstat(path, buf));
157
158 if (Pstatus(Pr)->pr_dmodel != PR_MODEL_NATIVE) {
159 /* 64-bit process controls 32-bit subject process */
160 syscall = SYS_fstatat64;
161 } else {
162 syscall = SYS_fstatat;
163 }
164
165 adp->arg_value = AT_FDCWD;
166 adp->arg_object = NULL;
167 adp->arg_type = AT_BYVAL;
168 adp->arg_inout = AI_INPUT;
169 adp->arg_size = 0;
170 adp++; /* move to path argument */
171
172 adp->arg_value = 0;
173 adp->arg_object = (void *)path;
174 adp->arg_type = AT_BYREF;
175 adp->arg_inout = AI_INPUT;
176 adp->arg_size = strlen(path) + 1;
177 adp++; /* move to buffer argument */
178
179 adp->arg_value = 0;
180 adp->arg_type = AT_BYREF;
181 adp->arg_inout = AI_OUTPUT;
182 #ifdef _LP64
183 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
184 adp->arg_object = &statb64_32;
185 adp->arg_size = sizeof (statb64_32);
186 } else {
187 adp->arg_object = buf;
188 adp->arg_size = sizeof (*buf);
189 }
190 #else /* _LP64 */
191 adp->arg_object = buf;
192 adp->arg_size = sizeof (*buf);
193 #endif /* _LP64 */
194 adp++; /* move to flags argument */
195
196 adp->arg_value = AT_SYMLINK_NOFOLLOW;
197 adp->arg_object = NULL;
198 adp->arg_type = AT_BYVAL;
199 adp->arg_inout = AI_INPUT;
200 adp->arg_size = 0;
201
202 error = Psyscall(Pr, &rval, syscall, 4, &argd[0]);
203
204 if (error) {
205 errno = (error > 0)? error : ENOSYS;
206 return (-1);
207 }
208 #ifdef _LP64
209 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
210 stat64_32_to_n(&statb64_32, buf);
211 #endif /* _LP64 */
212 return (0);
213 }
214
215 /*
216 * fstat() system call -- executed by subject process
217 */
218 int
pr_fstat(struct ps_prochandle * Pr,int fd,struct stat * buf)219 pr_fstat(struct ps_prochandle *Pr, int fd, struct stat *buf)
220 {
221 sysret_t rval; /* return value from stat() */
222 argdes_t argd[4]; /* arg descriptors for fstatat() */
223 argdes_t *adp = &argd[0]; /* first argument */
224 int syscall; /* SYS_fstatat or SYS_fstatat64 */
225 int error;
226 #ifdef _LP64
227 struct stat64_32 statb64_32;
228 #endif /* _LP64 */
229
230 if (Pr == NULL) /* no subject process */
231 return (fstat(fd, buf));
232
233 if (Pstatus(Pr)->pr_dmodel != PR_MODEL_NATIVE) {
234 /* 64-bit process controls 32-bit subject process */
235 syscall = SYS_fstatat64;
236 } else {
237 syscall = SYS_fstatat;
238 }
239
240 adp->arg_value = fd;
241 adp->arg_object = NULL;
242 adp->arg_type = AT_BYVAL;
243 adp->arg_inout = AI_INPUT;
244 adp->arg_size = 0;
245 adp++; /* move to path argument */
246
247 adp->arg_value = 0;
248 adp->arg_object = NULL;
249 adp->arg_type = AT_BYVAL;
250 adp->arg_inout = AI_INPUT;
251 adp->arg_size = 0;
252 adp++; /* move to buffer argument */
253
254 adp->arg_value = 0;
255 adp->arg_type = AT_BYREF;
256 adp->arg_inout = AI_OUTPUT;
257 #ifdef _LP64
258 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
259 adp->arg_object = &statb64_32;
260 adp->arg_size = sizeof (statb64_32);
261 } else {
262 adp->arg_object = buf;
263 adp->arg_size = sizeof (*buf);
264 }
265 #else /* _LP64 */
266 adp->arg_object = buf;
267 adp->arg_size = sizeof (*buf);
268 #endif /* _LP64 */
269 adp++; /* move to flags argument */
270
271 adp->arg_value = 0;
272 adp->arg_object = NULL;
273 adp->arg_type = AT_BYVAL;
274 adp->arg_inout = AI_INPUT;
275 adp->arg_size = 0;
276
277 error = Psyscall(Pr, &rval, syscall, 4, &argd[0]);
278
279 if (error) {
280 errno = (error > 0)? error : ENOSYS;
281 return (-1);
282 }
283 #ifdef _LP64
284 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
285 stat64_32_to_n(&statb64_32, buf);
286 #endif /* _LP64 */
287 return (0);
288 }
289
290 /*
291 * stat64() system call -- executed by subject process
292 */
293 int
pr_stat64(struct ps_prochandle * Pr,const char * path,struct stat64 * buf)294 pr_stat64(struct ps_prochandle *Pr, const char *path, struct stat64 *buf)
295 {
296 sysret_t rval; /* return value from stat() */
297 argdes_t argd[4]; /* arg descriptors for fstatat() */
298 argdes_t *adp = &argd[0]; /* first argument */
299 int syscall; /* SYS_fstatat or SYS_fstatat64 */
300 int error;
301 #ifdef _LP64
302 struct stat64_32 statb64_32;
303 #endif /* _LP64 */
304
305 if (Pr == NULL) /* no subject process */
306 return (stat64(path, buf));
307
308 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
309 /*
310 * 32-bit native and
311 * 64-bit process controls 32-bit subject process
312 */
313 syscall = SYS_fstatat64;
314 } else {
315 /* 64-bit native */
316 syscall = SYS_fstatat;
317 }
318
319 adp->arg_value = AT_FDCWD;
320 adp->arg_object = NULL;
321 adp->arg_type = AT_BYVAL;
322 adp->arg_inout = AI_INPUT;
323 adp->arg_size = 0;
324 adp++; /* move to path argument */
325
326 adp->arg_value = 0;
327 adp->arg_object = (void *)path;
328 adp->arg_type = AT_BYREF;
329 adp->arg_inout = AI_INPUT;
330 adp->arg_size = strlen(path) + 1;
331 adp++; /* move to buffer argument */
332
333 adp->arg_value = 0;
334 adp->arg_type = AT_BYREF;
335 adp->arg_inout = AI_OUTPUT;
336 #ifdef _LP64
337 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
338 adp->arg_object = &statb64_32;
339 adp->arg_size = sizeof (statb64_32);
340 } else {
341 adp->arg_object = buf;
342 adp->arg_size = sizeof (*buf);
343 }
344 #else /* _LP64 */
345 adp->arg_object = buf;
346 adp->arg_size = sizeof (*buf);
347 #endif /* _LP64 */
348 adp++; /* move to flags argument */
349
350 adp->arg_value = 0;
351 adp->arg_object = NULL;
352 adp->arg_type = AT_BYVAL;
353 adp->arg_inout = AI_INPUT;
354 adp->arg_size = 0;
355
356 error = Psyscall(Pr, &rval, syscall, 4, &argd[0]);
357
358 if (error) {
359 errno = (error > 0)? error : ENOSYS;
360 return (-1);
361 }
362 #ifdef _LP64
363 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
364 stat64_32_to_n(&statb64_32, (struct stat *)buf);
365 #endif /* _LP64 */
366 return (0);
367 }
368
369 /*
370 * lstat64() system call -- executed by subject process
371 */
372 int
pr_lstat64(struct ps_prochandle * Pr,const char * path,struct stat64 * buf)373 pr_lstat64(struct ps_prochandle *Pr, const char *path, struct stat64 *buf)
374 {
375 sysret_t rval; /* return value from stat() */
376 argdes_t argd[4]; /* arg descriptors for fstatat() */
377 argdes_t *adp = &argd[0]; /* first argument */
378 int syscall; /* SYS_fstatat or SYS_fstatat64 */
379 int error;
380 #ifdef _LP64
381 struct stat64_32 statb64_32;
382 #endif /* _LP64 */
383
384 if (Pr == NULL) /* no subject process */
385 return (lstat64(path, buf));
386
387 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
388 /*
389 * 32-bit native and
390 * 64-bit process controls 32-bit subject process
391 */
392 syscall = SYS_fstatat64;
393 } else {
394 /* 64-bit native */
395 syscall = SYS_fstatat;
396 }
397
398 adp->arg_value = AT_FDCWD;
399 adp->arg_object = NULL;
400 adp->arg_type = AT_BYVAL;
401 adp->arg_inout = AI_INPUT;
402 adp->arg_size = 0;
403 adp++; /* move to path argument */
404
405 adp->arg_value = 0;
406 adp->arg_object = (void *)path;
407 adp->arg_type = AT_BYREF;
408 adp->arg_inout = AI_INPUT;
409 adp->arg_size = strlen(path) + 1;
410 adp++; /* move to buffer argument */
411
412 adp->arg_value = 0;
413 adp->arg_type = AT_BYREF;
414 adp->arg_inout = AI_OUTPUT;
415 #ifdef _LP64
416 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
417 adp->arg_object = &statb64_32;
418 adp->arg_size = sizeof (statb64_32);
419 } else {
420 adp->arg_object = buf;
421 adp->arg_size = sizeof (*buf);
422 }
423 #else /* _LP64 */
424 adp->arg_object = buf;
425 adp->arg_size = sizeof (*buf);
426 #endif /* _LP64 */
427 adp++; /* move to flags argument */
428
429 adp->arg_value = AT_SYMLINK_NOFOLLOW;
430 adp->arg_object = NULL;
431 adp->arg_type = AT_BYVAL;
432 adp->arg_inout = AI_INPUT;
433 adp->arg_size = 0;
434
435 error = Psyscall(Pr, &rval, syscall, 4, &argd[0]);
436
437 if (error) {
438 errno = (error > 0)? error : ENOSYS;
439 return (-1);
440 }
441 #ifdef _LP64
442 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
443 stat64_32_to_n(&statb64_32, (struct stat *)buf);
444 #endif /* _LP64 */
445 return (0);
446 }
447
448 /*
449 * fstat64() system call -- executed by subject process
450 */
451 int
pr_fstat64(struct ps_prochandle * Pr,int fd,struct stat64 * buf)452 pr_fstat64(struct ps_prochandle *Pr, int fd, struct stat64 *buf)
453 {
454 sysret_t rval; /* return value from stat() */
455 argdes_t argd[4]; /* arg descriptors for fstatat() */
456 argdes_t *adp = &argd[0]; /* first argument */
457 int syscall; /* SYS_fstatat or SYS_fstatat64 */
458 int error;
459 #ifdef _LP64
460 struct stat64_32 statb64_32;
461 #endif /* _LP64 */
462
463 if (Pr == NULL) /* no subject process */
464 return (fstat64(fd, buf));
465
466 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
467 /*
468 * 32-bit native and
469 * 64-bit process controls 32-bit subject process
470 */
471 syscall = SYS_fstatat64;
472 } else {
473 /* 64-bit native */
474 syscall = SYS_fstatat;
475 }
476
477 adp->arg_value = fd;
478 adp->arg_object = NULL;
479 adp->arg_type = AT_BYVAL;
480 adp->arg_inout = AI_INPUT;
481 adp->arg_size = 0;
482 adp++; /* move to path argument */
483
484 adp->arg_value = 0;
485 adp->arg_object = NULL;
486 adp->arg_type = AT_BYVAL;
487 adp->arg_inout = AI_INPUT;
488 adp->arg_size = 0;
489 adp++; /* move to buffer argument */
490
491 adp->arg_value = 0;
492 adp->arg_type = AT_BYREF;
493 adp->arg_inout = AI_OUTPUT;
494 #ifdef _LP64
495 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32) {
496 adp->arg_object = &statb64_32;
497 adp->arg_size = sizeof (statb64_32);
498 } else {
499 adp->arg_object = buf;
500 adp->arg_size = sizeof (*buf);
501 }
502 #else /* _LP64 */
503 adp->arg_object = buf;
504 adp->arg_size = sizeof (*buf);
505 #endif /* _LP64 */
506 adp++; /* move to flags argument */
507
508 adp->arg_value = 0;
509 adp->arg_object = NULL;
510 adp->arg_type = AT_BYVAL;
511 adp->arg_inout = AI_INPUT;
512 adp->arg_size = 0;
513
514 error = Psyscall(Pr, &rval, syscall, 4, &argd[0]);
515
516 if (error) {
517 errno = (error > 0)? error : ENOSYS;
518 return (-1);
519 }
520 #ifdef _LP64
521 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_ILP32)
522 stat64_32_to_n(&statb64_32, (struct stat *)buf);
523 #endif /* _LP64 */
524 return (0);
525 }
526