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 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 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 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 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 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 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 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