/filesystems/procfs/procfs.cc
C++ | 4975 lines | 4101 code | 796 blank | 78 comment | 606 complexity | 8905523075cf982ed57d446bcdf473d7 MD5 | raw file
1/* 2 * procfs as a MacFUSE file system for Mac OS X 3 * 4 * Copyright Amit Singh. All Rights Reserved. 5 * http://osxbook.com 6 * 7 * http://code.google.com/p/macfuse/ 8 * 9 * Source License: GNU GENERAL PUBLIC LICENSE (GPL) 10 */ 11 12#define MACFUSE_PROCFS_VERSION "2.0" 13#define FUSE_USE_VERSION 26 14 15#include <dirent.h> 16#include <errno.h> 17#include <fcntl.h> 18#include <getopt.h> 19#include <pthread.h> 20#include <stdio.h> 21#include <string.h> 22#include <sys/sysctl.h> 23 24#include <grp.h> 25#include <pwd.h> 26 27#include <mach/mach.h> 28#include <mach/mach_vm.h> 29#include <mach/vm_region.h> 30#include <mach/vm_statistics.h> 31 32#include <Carbon/Carbon.h> 33#include <CoreFoundation/CoreFoundation.h> 34#include <IOKit/IOKitLib.h> 35 36#include <cassert> 37#include <vector> 38#include <pcrecpp.h> 39 40#include <fuse.h> 41 42#include "procfs_displays.h" 43#include "procfs_proc_info.h" 44#include "procfs_windows.h" 45#include "sequencegrab/procfs_sequencegrab.h" 46 47#if MACFUSE_PROCFS_ENABLE_TPM 48#include "procfs_tpm.h" 49#endif /* MACFUSE_PROCFS_ENABLE_TPM */ 50 51static int procfs_ui = 0; 52#define PROCFS_DEFAULT_FILE_SIZE 65536 53 54static int total_file_patterns = 0; 55static int total_directory_patterns = 0; 56static int total_link_patterns = 0; 57 58static processor_port_array_t processor_list; 59static mach_port_t p_default_set = 0; 60static mach_port_t p_default_set_control = 0; 61static host_priv_t host_priv; 62static natural_t processor_count = 0; 63static io_connect_t lightsensor_port = 0; 64static io_connect_t motionsensor_port = 0; 65static unsigned int sms_gIndex = 0; 66static IOItemCount sms_gStructureInputSize = 0; 67static IOByteCount sms_gStructureOutputSize = 0; 68 69/* camera */ 70static pthread_mutex_t camera_lock; 71static int camera_busy = 0; 72static CFMutableDataRef camera_tiff = (CFMutableDataRef)0; 73 74/* display */ 75static pthread_mutex_t display_lock; 76static int display_busy = 0; 77static CFMutableDataRef display_png = (CFMutableDataRef)0; 78 79static pcrecpp::RE *valid_process_pattern = new pcrecpp::RE("/(\\d+)"); 80 81typedef struct { 82 char x; 83 char y; 84 char z; 85 short v; 86#define FILLER_SIZE 60 87 char scratch[FILLER_SIZE]; 88} MotionSensorData_t; 89 90static kern_return_t 91sms_getOrientation_hardware_apple(MotionSensorData_t *odata) 92{ 93 kern_return_t kr; 94 IOItemCount isize = sms_gStructureInputSize; 95 IOByteCount osize = sms_gStructureOutputSize; 96 MotionSensorData_t idata; 97 98 kr = IOConnectMethodStructureIStructureO(motionsensor_port, 99 sms_gIndex, 100 isize, 101 &osize, 102 &idata, 103 odata); 104 return kr; 105} 106 107static int init_task_list(task_array_t *task_list, 108 mach_msg_type_number_t *task_count) 109{ 110 return processor_set_tasks(p_default_set_control, task_list, task_count); 111} 112 113static void fini_task_list(task_array_t task_list, 114 mach_msg_type_number_t task_count) 115{ 116 unsigned int i; 117 for (i = 0; i < task_count; i++) { 118 mach_port_deallocate(mach_task_self(), task_list[i]); 119 } 120 vm_deallocate(mach_task_self(), (vm_address_t)task_list, 121 task_count * sizeof(task_t)); 122} 123 124static int init_thread_list(task_t the_task, 125 thread_array_t *thread_list, 126 mach_msg_type_number_t *thread_count) 127{ 128 return task_threads(the_task, thread_list, thread_count); 129} 130 131static void fini_thread_list(thread_array_t thread_list, 132 mach_msg_type_number_t thread_count) 133{ 134 unsigned int i; 135 for (i = 0; i < thread_count; i++) { 136 mach_port_deallocate(mach_task_self(), thread_list[i]); 137 } 138 vm_deallocate(mach_task_self(), (vm_address_t)thread_list, 139 thread_count * sizeof(thread_act_t)); 140} 141 142static int init_port_list(task_t the_task, 143 mach_port_name_array_t *name_list, 144 mach_msg_type_number_t *name_count, 145 mach_port_type_array_t *type_list, 146 mach_msg_type_number_t *type_count) 147{ 148 return mach_port_names(the_task, 149 name_list, name_count, type_list, type_count); 150} 151 152static void fini_port_list(mach_port_name_array_t name_list, 153 mach_msg_type_number_t name_count, 154 mach_port_type_array_t type_list, 155 mach_msg_type_number_t type_count) 156{ 157 vm_deallocate(mach_task_self(), (vm_address_t)name_list, 158 name_count * sizeof(mach_port_name_t)); 159 vm_deallocate(mach_task_self(), (vm_address_t)type_list, 160 type_count * sizeof(mach_port_type_t)); 161} 162 163 164#define DECL_PORT_LIST() \ 165 mach_port_name_array_t name_list; \ 166 mach_msg_type_number_t name_count; \ 167 mach_port_type_array_t type_list; \ 168 mach_msg_type_number_t type_count; 169#define INIT_PORT_LIST(the_task) \ 170 if (init_port_list(the_task, &name_list, &name_count, &type_list, &type_count) != 0) { \ 171 return -EIO; \ 172 } 173#define FINI_PORT_LIST() \ 174 fini_port_list(name_list, name_count, type_list, type_count) 175 176#define DECL_TASK_LIST() \ 177 task_array_t task_list; \ 178 mach_msg_type_number_t task_count; 179#define INIT_TASK_LIST() \ 180 if (init_task_list(&task_list, &task_count) != 0) { return -EIO; } 181#define FINI_TASK_LIST() \ 182 fini_task_list(task_list, task_count) 183 184#define DECL_THREAD_LIST() \ 185 thread_array_t thread_list; \ 186 mach_msg_type_number_t thread_count; 187#define INIT_THREAD_LIST(the_task) \ 188 if (init_thread_list(the_task, &thread_list, &thread_count) != 0) { \ 189 return -EIO; \ 190 } 191#define FINI_THREAD_LIST() \ 192 fini_thread_list(thread_list, thread_count) 193 194struct procfs_dispatcher_entry; 195typedef struct procfs_dispatcher_entry * procfs_dispatcher_entry_t; 196 197typedef int (*procfs_open_handler_t)(procfs_dispatcher_entry_t e, 198 const char *argv[], 199 const char *path, 200 struct fuse_file_info *fi); 201 202typedef int (*procfs_release_handler_t)(procfs_dispatcher_entry_t e, 203 const char *argv[], 204 const char *path, 205 struct fuse_file_info *fi); 206typedef int (*procfs_opendir_handler_t)(procfs_dispatcher_entry_t e, 207 const char *argv[], 208 const char *path, 209 struct fuse_file_info *fi); 210 211typedef int (*procfs_releasedir_handler_t)(procfs_dispatcher_entry_t e, 212 const char *argv[], 213 const char *path, 214 struct fuse_file_info *fi); 215 216typedef int (*procfs_getattr_handler_t)(procfs_dispatcher_entry_t e, 217 const char *argv[], 218 struct stat *stbuf); 219 220typedef int (*procfs_read_handler_t)(procfs_dispatcher_entry_t e, 221 const char *argv[], 222 char *buf, 223 size_t size, 224 off_t offset, 225 struct fuse_file_info *fi); 226 227typedef int (*procfs_readdir_handler_t)(procfs_dispatcher_entry_t e, 228 const char *argv[], 229 void *buf, 230 fuse_fill_dir_t filler, 231 off_t offset, 232 struct fuse_file_info *fi); 233 234typedef int (*procfs_readlink_handler_t)(procfs_dispatcher_entry_t e, 235 const char *argv[], 236 char *buf, 237 size_t size); 238 239typedef struct procfs_dispatcher_entry { 240 int flag; 241 char *pattern; 242 pcrecpp::RE *compiled_pattern; 243 int argc; 244 procfs_open_handler_t open; 245 procfs_release_handler_t release; 246 procfs_opendir_handler_t opendir; 247 procfs_releasedir_handler_t releasedir; 248 procfs_getattr_handler_t getattr; 249 procfs_read_handler_t read; 250 procfs_readdir_handler_t readdir; 251 procfs_readlink_handler_t readlink; 252 const char *content_files[32]; 253 const char *content_directories[32]; 254}; 255 256/* flags */ 257#define PROCFS_FLAG_ISDOTFILE 0x00000001 258 259#define PROCFS_MAX_ARGS 3 260 261#define OPEN_HANDLER(handler) \ 262int \ 263procfs_open_##handler(procfs_dispatcher_entry_t e, \ 264 const char *argv[], \ 265 const char *path, \ 266 struct fuse_file_info *fi) \ 267 268#define RELEASE_HANDLER(handler) \ 269int \ 270procfs_release_##handler(procfs_dispatcher_entry_t e, \ 271 const char *argv[], \ 272 const char *path, \ 273 struct fuse_file_info *fi) \ 274 275#define OPENDIR_HANDLER(handler) \ 276int \ 277procfs_opendir_##handler(procfs_dispatcher_entry_t e, \ 278 const char *argv[], \ 279 const char *path, \ 280 struct fuse_file_info *fi) \ 281 282#define RELEASEDIR_HANDLER(handler) \ 283int \ 284procfs_releasedir_##handler(procfs_dispatcher_entry_t e, \ 285 const char *argv[], \ 286 const char *path, \ 287 struct fuse_file_info *fi) \ 288 289#define GETATTR_HANDLER(handler) \ 290int \ 291procfs_getattr_##handler(procfs_dispatcher_entry_t e, \ 292 const char *argv[], \ 293 struct stat *stbuf) \ 294 295#define READ_HANDLER(handler) \ 296int \ 297procfs_read_##handler(procfs_dispatcher_entry_t e, \ 298 const char *argv[], \ 299 char *buf, \ 300 size_t size, \ 301 off_t offset, \ 302 struct fuse_file_info *fi) \ 303 304#define READDIR_HANDLER(handler) \ 305int \ 306procfs_readdir_##handler(procfs_dispatcher_entry_t e, \ 307 const char *argv[], \ 308 void *buf, \ 309 fuse_fill_dir_t filler, \ 310 off_t offset, \ 311 struct fuse_file_info *fi) \ 312 313#define READLINK_HANDLER(handler) \ 314int \ 315procfs_readlink_##handler(procfs_dispatcher_entry_t e, \ 316 const char *argv[], \ 317 char *buf, \ 318 size_t size) \ 319 320#define PROTO_OPEN_HANDLER(handler) OPEN_HANDLER(handler) 321#define PROTO_RELEASE_HANDLER(handler) RELEASE_HANDLER(handler) 322#define PROTO_OPENDIR_HANDLER(handler) OPENDIR_HANDLER(handler) 323#define PROTO_RELEASEDIR_HANDLER(handler) RELEASEDIR_HANDLER(handler) 324#define PROTO_READ_HANDLER(handler) READ_HANDLER(handler) 325#define PROTO_READDIR_HANDLER(handler) READDIR_HANDLER(handler) 326#define PROTO_READLINK_HANDLER(handler) READLINK_HANDLER(handler) 327#define PROTO_GETATTR_HANDLER(handler) GETATTR_HANDLER(handler) 328 329#define DECL_FILE(pattern, argc, openp, releasep, getattrp, readp) \ 330 { \ 331 0, \ 332 pattern, \ 333 new pcrecpp::RE(pattern), \ 334 argc, \ 335 procfs_open_##openp, \ 336 procfs_release_##releasep, \ 337 procfs_opendir_enotdir, \ 338 procfs_releasedir_enotdir, \ 339 procfs_getattr_##getattrp, \ 340 procfs_read_##readp, \ 341 procfs_readdir_enotdir, \ 342 procfs_readlink_einval, \ 343 { NULL }, \ 344 { NULL } \ 345 }, 346 347#define DECL_FILE_WITHFLAGS(flag, pattern, argc, openp, releasep, getattrp, readp) \ 348 { \ 349 flag, \ 350 pattern, \ 351 new pcrecpp::RE(pattern), \ 352 argc, \ 353 procfs_open_##openp, \ 354 procfs_release_##releasep, \ 355 procfs_opendir_enotdir, \ 356 procfs_releasedir_enotdir, \ 357 procfs_getattr_##getattrp, \ 358 procfs_read_##readp, \ 359 procfs_readdir_enotdir, \ 360 procfs_readlink_einval, \ 361 { NULL }, \ 362 { NULL } \ 363 }, 364 365#define DECL_DIRECTORY(pattern, argc, opendirp, releasedirp, getattrp, readdirp, contents, ...) \ 366 { \ 367 0, \ 368 pattern, \ 369 new pcrecpp::RE(pattern), \ 370 argc, \ 371 procfs_open_eisdir, \ 372 procfs_release_eisdir, \ 373 procfs_opendir_##opendirp, \ 374 procfs_releasedir_##releasedirp, \ 375 procfs_getattr_##getattrp, \ 376 procfs_read_eisdir, \ 377 procfs_readdir_##readdirp, \ 378 procfs_readlink_einval, \ 379 contents, \ 380 __VA_ARGS__ \ 381 }, 382 383#define DECL_DIRECTORY_COMPACT(pattern, contents, ...) \ 384 { \ 385 0, \ 386 pattern, \ 387 new pcrecpp::RE(pattern), \ 388 0, \ 389 procfs_open_eisdir, \ 390 procfs_release_eisdir, \ 391 procfs_opendir_default_directory, \ 392 procfs_releasedir_default_directory, \ 393 procfs_getattr_default_directory, \ 394 procfs_read_eisdir, \ 395 procfs_readdir_default, \ 396 procfs_readlink_einval, \ 397 contents, \ 398 ##__VA_ARGS__ \ 399 }, 400 401#define DECL_LINK(pattern, argc, openp, releasep, getattrp, readlinkp) \ 402 { \ 403 0, \ 404 pattern, \ 405 new pcrecpp::RE(pattern), \ 406 argc, \ 407 procfs_open_##openp, \ 408 procfs_release_##releasep, \ 409 procfs_opendir_enotdir, \ 410 procfs_releasedir_enotdir, \ 411 procfs_getattr_##getattrp, \ 412 procfs_read_einval, \ 413 procfs_readdir_enotdir, \ 414 procfs_readlink_##readlinkp, \ 415 { NULL }, \ 416 { NULL } \ 417 }, 418 419#define DECL_LINK_COMPACT(pattern, argc, readlinkp) \ 420 { \ 421 0, \ 422 pattern, \ 423 new pcrecpp::RE(pattern), \ 424 argc, \ 425 procfs_open_default_file, \ 426 procfs_release_default_file, \ 427 procfs_opendir_enotdir, \ 428 procfs_releasedir_enotdir, \ 429 procfs_getattr_default_link, \ 430 procfs_read_einval, \ 431 procfs_readdir_enotdir, \ 432 procfs_readlink_##readlinkp, \ 433 { NULL }, \ 434 { NULL } \ 435 }, 436 437PROTO_OPEN_HANDLER(default_file); 438PROTO_OPEN_HANDLER(eisdir); 439PROTO_OPEN_HANDLER(proc__windows__identify); 440PROTO_OPEN_HANDLER(proc__windows__screenshots__window); 441PROTO_OPEN_HANDLER(system__hardware__camera__screenshot); 442PROTO_OPEN_HANDLER(system__hardware__displays__display__screenshot); 443 444PROTO_RELEASE_HANDLER(default_file); 445PROTO_RELEASE_HANDLER(eisdir); 446PROTO_RELEASE_HANDLER(proc__windows__identify); 447PROTO_RELEASE_HANDLER(proc__windows__screenshots__window); 448PROTO_RELEASE_HANDLER(system__hardware__camera__screenshot); 449PROTO_RELEASE_HANDLER(system__hardware__displays__display__screenshot); 450 451PROTO_OPENDIR_HANDLER(default_directory); 452PROTO_OPENDIR_HANDLER(enotdir); 453 454PROTO_RELEASEDIR_HANDLER(default_directory); 455PROTO_RELEASEDIR_HANDLER(enotdir); 456 457PROTO_GETATTR_HANDLER(default_file); 458PROTO_GETATTR_HANDLER(default_file_finder_info); 459PROTO_GETATTR_HANDLER(default_directory); 460PROTO_GETATTR_HANDLER(default_link); 461PROTO_GETATTR_HANDLER(byname__name); 462PROTO_GETATTR_HANDLER(system__hardware__camera__screenshot); 463PROTO_GETATTR_HANDLER(system__hardware__displays__display); 464PROTO_GETATTR_HANDLER(system__hardware__displays__display__screenshot); 465#if MACFUSE_PROCFS_ENABLE_TPM 466PROTO_GETATTR_HANDLER(system__hardware__tpm__keyslots__slot); 467PROTO_GETATTR_HANDLER(system__hardware__tpm__pcrs__pcr); 468#endif /* MACFUSE_PROCFS_ENABLE_TPM */ 469PROTO_GETATTR_HANDLER(proc__task__ports__port); 470PROTO_GETATTR_HANDLER(proc__task__threads__thread); 471PROTO_GETATTR_HANDLER(proc__windows__screenshots__window); 472 473PROTO_READ_HANDLER(einval); 474PROTO_READ_HANDLER(eisdir); 475PROTO_READ_HANDLER(zero); 476PROTO_READ_HANDLER(default_file_finder_info); 477PROTO_READ_HANDLER(proc__carbon); 478#if __i386__ 479PROTO_READ_HANDLER(proc__fds); 480#endif /* __i386__ */ 481PROTO_READ_HANDLER(proc__generic); 482PROTO_READ_HANDLER(proc__task__absolutetime_info); 483PROTO_READ_HANDLER(proc__task__basic_info); 484PROTO_READ_HANDLER(proc__task__events_info); 485PROTO_READ_HANDLER(proc__task__thread_times_info); 486PROTO_READ_HANDLER(proc__task__mach_name); 487PROTO_READ_HANDLER(proc__task__ports__port); 488PROTO_READ_HANDLER(proc__task__role); 489PROTO_READ_HANDLER(proc__task__threads__thread__basic_info); 490PROTO_READ_HANDLER(proc__task__threads__thread__states__debug); 491PROTO_READ_HANDLER(proc__task__threads__thread__states__exception); 492PROTO_READ_HANDLER(proc__task__threads__thread__states__float); 493PROTO_READ_HANDLER(proc__task__threads__thread__states__thread); 494PROTO_READ_HANDLER(proc__task__tokens); 495PROTO_READ_HANDLER(proc__task__vmmap); 496PROTO_READ_HANDLER(proc__task__vmmap_r); 497PROTO_READ_HANDLER(proc__windows__generic); 498PROTO_READ_HANDLER(proc__windows__screenshots__window); 499PROTO_READ_HANDLER(proc__xcred); 500PROTO_READ_HANDLER(system__firmware__variables); 501PROTO_READ_HANDLER(system__hardware__camera__screenshot); 502PROTO_READ_HANDLER(system__hardware__cpus__cpu__data); 503PROTO_READ_HANDLER(system__hardware__displays__display__info); 504PROTO_READ_HANDLER(system__hardware__displays__display__screenshot); 505#if MACFUSE_PROCFS_ENABLE_TPM 506PROTO_READ_HANDLER(system__hardware__tpm__hwmodel); 507PROTO_READ_HANDLER(system__hardware__tpm__hwvendor); 508PROTO_READ_HANDLER(system__hardware__tpm__hwversion); 509PROTO_READ_HANDLER(system__hardware__tpm__keyslots__slot); 510PROTO_READ_HANDLER(system__hardware__tpm__pcrs__pcr); 511#endif /* MACFUSE_PROCFS_ENABLE_TPM */ 512PROTO_READ_HANDLER(system__hardware__xsensor); 513 514PROTO_READDIR_HANDLER(default); 515PROTO_READDIR_HANDLER(enotdir); 516PROTO_READDIR_HANDLER(byname); 517PROTO_READDIR_HANDLER(proc__task__ports); 518PROTO_READDIR_HANDLER(proc__task__threads); 519PROTO_READDIR_HANDLER(proc__windows__screenshots); 520PROTO_READDIR_HANDLER(root); 521PROTO_READDIR_HANDLER(system__hardware__cpus); 522PROTO_READDIR_HANDLER(system__hardware__cpus__cpu); 523PROTO_READDIR_HANDLER(system__hardware__displays); 524PROTO_READDIR_HANDLER(system__hardware__displays__display); 525#if MACFUSE_PROCFS_ENABLE_TPM 526PROTO_READDIR_HANDLER(system__hardware__tpm__keyslots); 527PROTO_READDIR_HANDLER(system__hardware__tpm__pcrs); 528#endif /* MACFUSE_PROCFS_ENABLE_TPM */ 529 530PROTO_READLINK_HANDLER(einval); 531PROTO_READLINK_HANDLER(byname__name); 532 533static struct procfs_dispatcher_entry 534procfs_link_table[] = { 535 536 DECL_LINK( 537 "/byname/(.+)", 538 1, 539 default_file, 540 default_file, 541 byname__name, 542 byname__name 543 ) 544}; 545 546static struct procfs_dispatcher_entry 547procfs_file_table[] = { 548 549 DECL_FILE_WITHFLAGS( 550 PROCFS_FLAG_ISDOTFILE, 551 "/system/.*\\._.*|/\\d+/.*\\._.*", 552 0, 553 default_file, 554 default_file, 555 default_file_finder_info, 556 default_file_finder_info 557 ) 558 559 DECL_FILE( 560 "/system/firmware/variables", 561 0, 562 default_file, 563 default_file, 564 default_file, 565 system__firmware__variables 566 ) 567 568 DECL_FILE( 569 "/system/hardware/(lightsensor|motionsensor|mouse)/data", 570 1, 571 default_file, 572 default_file, 573 default_file, 574 system__hardware__xsensor 575 ) 576 577 DECL_FILE( 578 "/system/hardware/camera/screenshot.tiff", 579 0, 580 system__hardware__camera__screenshot, 581 system__hardware__camera__screenshot, 582 system__hardware__camera__screenshot, 583 system__hardware__camera__screenshot 584 ) 585 586 DECL_FILE( 587 "/system/hardware/cpus/(\\d+)/data", 588 1, 589 default_file, 590 default_file, 591 default_file, 592 system__hardware__cpus__cpu__data 593 ) 594 595 DECL_FILE( 596 "/system/hardware/displays/(\\d+)/info", 597 1, 598 default_file, 599 default_file, 600 default_file, 601 system__hardware__displays__display__info 602 ) 603 604 DECL_FILE( 605 "/system/hardware/displays/(\\d+)/screenshot.png", 606 1, 607 system__hardware__displays__display__screenshot, 608 system__hardware__displays__display__screenshot, 609 system__hardware__displays__display__screenshot, 610 system__hardware__displays__display__screenshot 611 ) 612 613#if MACFUSE_PROCFS_ENABLE_TPM 614 DECL_FILE( 615 "/system/hardware/tpm/hwmodel", 616 0, 617 default_file, 618 default_file, 619 default_file, 620 system__hardware__tpm__hwmodel 621 ) 622 623 DECL_FILE( 624 "/system/hardware/tpm/hwvendor", 625 0, 626 default_file, 627 default_file, 628 default_file, 629 system__hardware__tpm__hwvendor 630 ) 631 632 DECL_FILE( 633 "/system/hardware/tpm/hwversion", 634 0, 635 default_file, 636 default_file, 637 default_file, 638 system__hardware__tpm__hwversion 639 ) 640 641 DECL_FILE( 642 "/system/hardware/tpm/keyslots/key(\\d+)", 643 1, 644 default_file, 645 default_file, 646 system__hardware__tpm__keyslots__slot, 647 system__hardware__tpm__keyslots__slot 648 ) 649 650 DECL_FILE( 651 "/system/hardware/tpm/pcrs/pcr(\\d+)", 652 1, 653 default_file, 654 default_file, 655 system__hardware__tpm__pcrs__pcr, 656 system__hardware__tpm__pcrs__pcr 657 ) 658#endif /* MACFUSE_PROCFS_ENABLE_TPM */ 659 660 DECL_FILE( 661 "/(\\d+)/carbon/(name|psn)", 662 2, 663 default_file, 664 default_file, 665 default_file, 666 proc__carbon 667 ) 668 669#if __i386__ 670 DECL_FILE( 671 "/(\\d+)/fds", 672 1, 673 default_file, 674 default_file, 675 default_file, 676 proc__fds 677 ) 678#endif /* __i386__ */ 679 680 DECL_FILE( 681 "/(\\d+)/(cmdline|jobc|paddr|pgid|ppid|tdev|tpgid|wchan)", 682 2, 683 default_file, 684 default_file, 685 default_file, 686 proc__generic 687 ) 688 689 DECL_FILE( 690 "/(\\d+)/task/absolutetime_info/(threads_system|threads_user|total_system|total_user)", 691 2, 692 default_file, 693 default_file, 694 default_file, 695 proc__task__absolutetime_info 696 ) 697 698 DECL_FILE( 699 "/(\\d+)/task/basic_info/(policy|resident_size|suspend_count|system_time|user_time|virtual_size)", 700 2, 701 default_file, 702 default_file, 703 default_file, 704 proc__task__basic_info 705 ) 706 707 DECL_FILE( 708 "/(\\d+)/task/events_info/(cow_faults|csw|faults|messages_received|messages_sent|pageins|syscalls_mach|syscalls_unix)", 709 2, 710 default_file, 711 default_file, 712 default_file, 713 proc__task__events_info 714 ) 715 716 DECL_FILE( 717 "/(\\d+)/task/thread_times_info/(system_time|user_time)", 718 2, 719 default_file, 720 default_file, 721 default_file, 722 proc__task__thread_times_info 723 ) 724 725 DECL_FILE( 726 "/(\\d+)/task/mach_name", 727 1, 728 default_file, 729 default_file, 730 default_file, 731 proc__task__mach_name 732 ) 733 734 DECL_FILE( 735 "/(\\d+)/task/ports/([a-f\\d]+)/(msgcount|qlimit|seqno|sorights|task_rights)", 736 3, 737 default_file, 738 default_file, 739 default_file, 740 proc__task__ports__port 741 ) 742 743 DECL_FILE( 744 "/(\\d+)/task/role", 745 1, 746 default_file, 747 default_file, 748 default_file, 749 proc__task__role 750 ) 751 752 DECL_FILE( 753 "/(\\d+)/task/threads/([a-f\\d]+)/basic_info/(cpu_usage|flags|policy|run_state|sleep_time|suspend_count|system_time|user_time)", 754 3, 755 default_file, 756 default_file, 757 default_file, 758 proc__task__threads__thread__basic_info 759 ) 760 761 DECL_FILE( 762 "/(\\d+)/task/threads/([a-f\\d]+)/states/debug/(dr[0-7])", 763 3, 764 default_file, 765 default_file, 766 default_file, 767 proc__task__threads__thread__states__debug 768 ) 769 770 DECL_FILE( 771 "/(\\d+)/task/threads/([a-f\\d]+)/states/exception/(err|faultvaddr|trapno)", 772 3, 773 default_file, 774 default_file, 775 default_file, 776 proc__task__threads__thread__states__exception 777 ) 778 779 DECL_FILE( 780 "/(\\d+)/task/threads/([a-f\\d]+)/states/float/(fpu_fcw|fpu_fsw|fpu_ftw|fpu_fop|fpu_ip|fpu_cs|fpu_dp|fpu_ds|fpu_mxcsr|fpu_mxcsrmask)", 781 3, 782 default_file, 783 default_file, 784 default_file, 785 proc__task__threads__thread__states__float 786 ) 787 788 DECL_FILE( 789 "/(\\d+)/task/threads/([a-f\\d]+)/states/thread/(e[a-d]x|edi|esi|ebp|esp|ss|eflags|eip|[cdefg]s)", 790 3, 791 default_file, 792 default_file, 793 default_file, 794 proc__task__threads__thread__states__thread 795 ) 796 797 DECL_FILE( 798 "/(\\d+)/task/tokens/(audit|security)", 799 2, 800 default_file, 801 default_file, 802 default_file, 803 proc__task__tokens 804 ) 805 806 DECL_FILE( 807 "/(\\d+)/task/vmmap", 808 1, 809 default_file, 810 default_file, 811 default_file, 812 proc__task__vmmap 813 ) 814 815 DECL_FILE( 816 "/(\\d+)/task/vmmap_r", 817 1, 818 default_file, 819 default_file, 820 default_file, 821 proc__task__vmmap_r 822 ) 823 824 DECL_FILE( 825 "/(\\d+)/windows/(all|onscreen)", 826 2, 827 default_file, 828 default_file, 829 default_file, 830 proc__windows__generic 831 ) 832 833 DECL_FILE( 834 "/(\\d+)/windows/identify", 835 1, 836 proc__windows__identify, 837 proc__windows__identify, 838 default_file, 839 zero 840 ) 841 842 DECL_FILE( 843 "/(\\d+)/windows/screenshots/([a-f\\d]+).png", 844 2, 845 proc__windows__screenshots__window, 846 proc__windows__screenshots__window, 847 proc__windows__screenshots__window, 848 proc__windows__screenshots__window 849 ) 850 851 DECL_FILE( 852 "/(\\d+)/(ucred|pcred)/(groups|rgid|ruid|svgid|svuid|uid)", 853 3, 854 default_file, 855 default_file, 856 default_file, 857 proc__xcred 858 ) 859}; 860 861static struct procfs_dispatcher_entry 862procfs_directory_table[] = { 863 DECL_DIRECTORY( 864 "/", 865 0, 866 default_directory, 867 default_directory, 868 default_directory, 869 root, 870 { NULL }, 871 { "byname", "system", NULL } 872 ) 873 874 DECL_DIRECTORY( 875 "/byname", 876 0, 877 default_directory, 878 default_directory, 879 default_directory, 880 byname, 881 { NULL }, 882 { NULL } 883 ) 884 885 DECL_DIRECTORY_COMPACT( 886 "/system", 887 { NULL }, 888 { "firmware", "hardware", NULL }, 889 ) 890 891 DECL_DIRECTORY_COMPACT( 892 "/system/firmware", 893 { "variables", NULL }, 894 { NULL } 895 ) 896 897 DECL_DIRECTORY_COMPACT( 898 "/system/hardware", 899 { NULL }, 900#if MACFUSE_PROCFS_ENABLE_TPM 901 { 902 "camera", "cpus", "displays", "lightsensor", "motionsensor", 903 "mouse", "tpm", NULL 904 } 905#else 906 { 907 "camera", "cpus", "displays", "lightsensor", "motionsensor", 908 "mouse", NULL 909 } 910#endif /* MACFUSE_PROCFS_ENABLE_TPM */ 911 ) 912 913 DECL_DIRECTORY_COMPACT( 914 "/system/hardware/camera", 915 { "screenshot.tiff", NULL }, 916 { NULL }, 917 ) 918 919 DECL_DIRECTORY( 920 "/system/hardware/cpus", 921 0, 922 default_directory, 923 default_directory, 924 default_directory, 925 system__hardware__cpus, 926 { NULL }, 927 { NULL }, 928 ) 929 930 DECL_DIRECTORY( 931 "/system/hardware/cpus/(\\d+)", 932 1, 933 default_directory, 934 default_directory, 935 default_directory, 936 system__hardware__cpus__cpu, 937 { "data", NULL }, 938 { NULL }, 939 ) 940 941 DECL_DIRECTORY( 942 "/system/hardware/displays", 943 0, 944 default_directory, 945 default_directory, 946 default_directory, 947 system__hardware__displays, 948 { NULL }, 949 { NULL }, 950 ) 951 952 DECL_DIRECTORY( 953 "/system/hardware/displays/(\\d+)", 954 1, 955 default_directory, 956 default_directory, 957 system__hardware__displays__display, 958 system__hardware__displays__display, 959 { "info", "screenshot.png", NULL }, 960 { NULL }, 961 ) 962 963 DECL_DIRECTORY_COMPACT( 964 "/system/hardware/lightsensor", 965 { "data", NULL }, 966 { NULL }, 967 ) 968 969 DECL_DIRECTORY_COMPACT( 970 "/system/hardware/motionsensor", 971 { "data", NULL }, 972 { NULL }, 973 ) 974 975 DECL_DIRECTORY_COMPACT( 976 "/system/hardware/mouse", 977 { "data", NULL }, 978 { NULL }, 979 ) 980 981#if MACFUSE_PROCFS_ENABLE_TPM 982 DECL_DIRECTORY_COMPACT( 983 "/system/hardware/tpm", 984 { "hwmodel", "hwvendor", "hwversion", NULL }, 985 { "keyslots", "pcrs" } 986 ) 987 988 DECL_DIRECTORY( 989 "/system/hardware/tpm/keyslots", 990 0, 991 default_directory, 992 default_directory, 993 default_directory, 994 system__hardware__tpm__keyslots, 995 { NULL }, 996 { NULL }, 997 ) 998 999 DECL_DIRECTORY( 1000 "/system/hardware/tpm/pcrs", 1001 0, 1002 default_directory, 1003 default_directory, 1004 default_directory, 1005 system__hardware__tpm__pcrs, 1006 { NULL }, 1007 { NULL }, 1008 ) 1009#endif /* MACFUSE_PROCFS_ENABLE_TPM */ 1010 1011 DECL_DIRECTORY_COMPACT( 1012 "/\\d+", 1013 { 1014 "cmdline", 1015#if __i386__ 1016 "fds", 1017#endif /* __i386__ */ 1018 "jobc", "paddr", "pgid", "ppid", "tdev", "tpgid", 1019 "wchan", "windows", NULL 1020 }, 1021 { "carbon", "pcred", "task", "ucred", NULL } 1022 ) 1023 1024 DECL_DIRECTORY_COMPACT( 1025 "/\\d+/carbon", 1026 { "name", "psn", NULL }, 1027 { NULL } 1028 ) 1029 1030 DECL_DIRECTORY_COMPACT( 1031 "/\\d+/pcred", 1032 { "rgid", "ruid", "svgid", "svgid", NULL }, 1033 { NULL } 1034 ) 1035 1036 DECL_DIRECTORY_COMPACT( 1037 "/\\d+/task", 1038 { "mach_name", "role", "vmmap", "vmmap_r", NULL }, 1039 { 1040 "absolutetime_info", "basic_info", "events_info", "ports", 1041 "thread_times_info", "threads", "tokens", NULL 1042 } 1043 ) 1044 1045 DECL_DIRECTORY_COMPACT( 1046 "/\\d+/task/absolutetime_info", 1047 { 1048 "threads_system", "threads_user", "total_system", 1049 "total_user", NULL 1050 }, 1051 { NULL } 1052 ) 1053 1054 DECL_DIRECTORY_COMPACT( 1055 "/\\d+/task/basic_info", 1056 { 1057 "policy", "resident_size", "suspend_count", "system_time", 1058 "user_time", "virtual_size", NULL 1059 }, 1060 { NULL } 1061 ) 1062 1063 DECL_DIRECTORY_COMPACT( 1064 "/\\d+/task/events_info", 1065 { 1066 "cow_faults", "csw", "faults", "messages_received", 1067 "messages_sent", "pageins", "syscalls_mach", "syscalls_unix", NULL 1068 }, 1069 { NULL } 1070 ) 1071 1072 DECL_DIRECTORY( 1073 "/(\\d+)/task/ports", 1074 1, 1075 default_directory, 1076 default_directory, 1077 default_directory, 1078 proc__task__ports, 1079 { NULL }, 1080 { NULL } 1081 ) 1082 1083 DECL_DIRECTORY( 1084 "/(\\d+)/task/ports/([a-f\\d]+)", 1085 2, 1086 default_directory, 1087 default_directory, 1088 proc__task__ports__port, 1089 default, 1090 { "msgcount", "qlimit", "seqno", "sorights", "task_rights", NULL }, 1091 { NULL } 1092 ) 1093 1094 DECL_DIRECTORY_COMPACT( 1095 "/\\d+/task/thread_times_info", 1096 { "system_time", "user_time", NULL }, 1097 { NULL } 1098 ) 1099 1100 DECL_DIRECTORY( 1101 "/(\\d+)/task/threads", 1102 1, 1103 default_directory, 1104 default_directory, 1105 default_directory, 1106 proc__task__threads, 1107 { NULL }, 1108 { NULL } 1109 ) 1110 1111 DECL_DIRECTORY( 1112 "/(\\d+)/task/threads/([a-f\\d])+", 1113 2, 1114 default_directory, 1115 default_directory, 1116 proc__task__threads__thread, 1117 default, 1118 { NULL }, 1119 { "basic_info", "states", NULL } 1120 ) 1121 1122 DECL_DIRECTORY_COMPACT( 1123 "/\\d+/task/threads/[a-f\\d]+/basic_info", 1124 { 1125 "cpu_usage", "flags", "policy", "run_state", "sleep_time", 1126 "suspend_count", "system_time", "user_time", NULL 1127 }, 1128 { NULL } 1129 ) 1130 1131 DECL_DIRECTORY_COMPACT( 1132 "/\\d+/task/threads/[a-f\\d]+/states", 1133 { "debug", "exception", "float", "thread", NULL }, 1134 { NULL } 1135 ) 1136 1137 DECL_DIRECTORY_COMPACT( 1138 "/\\d+/task/threads/[a-f\\d]+/states/debug", 1139 { "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", NULL }, 1140 { NULL } 1141 ) 1142 1143 DECL_DIRECTORY_COMPACT( 1144 "/\\d+/task/threads/[a-f\\d]+/states/exception", 1145 { "err", "faultvaddr", "trapno", NULL }, 1146 { NULL } 1147 ) 1148 1149 DECL_DIRECTORY_COMPACT( 1150 "/\\d+/task/threads/[a-f\\d]+/states/float", 1151 { 1152 "fpu_cs", "fpu_dp", "fpu_ds", "fpu_fcw", "fpu_fop", "fpu_fsw", 1153 "fpu_ftw", "fpu_ip", "fpu_mxcsr", "fpu_mxcsrmask", NULL 1154 }, 1155 { NULL } 1156 ) 1157 1158 DECL_DIRECTORY_COMPACT( 1159 "/\\d+/task/threads/[a-f\\d]+/states/thread", 1160 { 1161 "eax", "ebx", "ecx", "edx", "edi", "esi", "ebp", "esp", "ss", 1162 "eflags", "eip", "cs", "ds", "es", "fs", "gs", NULL 1163 }, 1164 { NULL } 1165 ) 1166 1167 DECL_DIRECTORY_COMPACT( 1168 "/\\d+/task/tokens", 1169 { "audit", "security", NULL }, 1170 { NULL } 1171 ) 1172 1173 DECL_DIRECTORY_COMPACT( 1174 "/\\d+/ucred", 1175 { "groups", "uid", NULL }, 1176 { NULL } 1177 ) 1178 1179 DECL_DIRECTORY_COMPACT( 1180 "/\\d+/windows", 1181 { "all", "onscreen", "identify", NULL }, 1182 { "screenshots", NULL } 1183 ) 1184 1185 DECL_DIRECTORY( 1186 "/(\\d+)/windows/screenshots", 1187 1, 1188 default_directory, 1189 default_directory, 1190 default_directory, 1191 proc__windows__screenshots, 1192 { NULL }, 1193 { NULL }, 1194 ) 1195 1196}; 1197 1198// BEGIN: OPEN/OPENDIR 1199 1200// 1201// int 1202// procfs_open/opendir_<handler>(procfs_dispatcher_entry_t e, 1203// const char *argv[], 1204// const char *path, 1205// struct fuse_file_info *fi) 1206 1207OPEN_HANDLER(default_file) 1208{ 1209 return 0; 1210} 1211 1212OPEN_HANDLER(eisdir) 1213{ 1214 return -EISDIR; 1215} 1216 1217OPEN_HANDLER(proc__windows__identify) 1218{ 1219 if (fi->fh != 0) { /* XXX: need locking */ 1220 return 0; 1221 } else { 1222 fi->fh = 1; 1223 } 1224 char *whandler = NULL; 1225 if ((whandler = getenv("MACFUSE_PROCFS_WHANDLER")) == NULL) { 1226 goto bail; 1227 } 1228 int npid = vfork(); 1229 if (npid == 0) { 1230 execl(whandler, whandler, argv[0], NULL); 1231 return 0; 1232 } 1233 1234bail: 1235 return 0; 1236} 1237 1238OPEN_HANDLER(proc__windows__screenshots__window) 1239{ 1240 if (fi->fh != 0) { /* XXX: need locking */ 1241 return 0; 1242 } 1243 1244 pid_t pid = strtol(argv[0], NULL, 10); 1245 CGWindowID target = strtol(argv[1], NULL, 16); 1246 ProcessSerialNumber psn; 1247 1248 OSStatus status = GetProcessForPID(pid, &psn); 1249 if (status != noErr) { 1250 return -ENOENT; 1251 } 1252 1253 CGSConnectionID conn; 1254 CGError err = CGSGetConnectionIDForPSN(0, &psn, &conn); 1255 if (err != kCGErrorSuccess) { 1256 return -ENOENT; 1257 } 1258 1259#define MAX_WINDOWS 256 1260 CGSWindowID windowIDs[MAX_WINDOWS]; 1261 int windowCount = 0; 1262 int i = 0; 1263 1264 err = CGSGetWindowList(_CGSDefaultConnection(), conn, MAX_WINDOWS, 1265 windowIDs, &windowCount); 1266 1267 for (i = 0; i < windowCount; i++) { 1268 if (windowIDs[i] == target) { 1269 goto doread; 1270 } 1271 } 1272 1273 return -ENOENT; 1274 1275doread: 1276 1277 CFMutableDataRef window_png = (CFMutableDataRef)0; 1278 int ret = PROCFS_GetPNGForWindowAtIndex(target, &window_png); 1279 1280 if (ret == -1) { 1281 return -EIO; 1282 } 1283 1284 struct ProcfsWindowData *pwd = 1285 (struct ProcfsWindowData *)malloc(sizeof(struct ProcfsWindowData)); 1286 if (!pwd) { 1287 CFRelease(window_png); 1288 return -ENOMEM; 1289 } 1290 1291 pwd->window_png = window_png; 1292 pwd->max_len = PROCFS_GetPNGSizeForWindowAtIndex(target); 1293 pwd->len = (size_t)CFDataGetLength(window_png); 1294 1295 fi->fh = (uint64_t)pwd; 1296 1297 return 0; 1298} 1299 1300OPEN_HANDLER(system__hardware__camera__screenshot) 1301{ 1302 pthread_mutex_lock(&camera_lock); 1303 if (camera_busy) { 1304 pthread_mutex_unlock(&camera_lock); 1305 return -EBUSY; 1306 } else { 1307 camera_busy = 1; 1308 pthread_mutex_unlock(&camera_lock); 1309 } 1310 1311 int ret = PROCFS_GetTIFFFromCamera(&camera_tiff); 1312 1313 return ret; 1314} 1315 1316OPEN_HANDLER(system__hardware__displays__display__screenshot) 1317{ 1318 pthread_mutex_lock(&display_lock); 1319 if (display_busy) { 1320 pthread_mutex_unlock(&display_lock); 1321 return -EBUSY; 1322 } else { 1323 display_busy = 1; 1324 pthread_mutex_unlock(&display_lock); 1325 } 1326 1327 unsigned long index = strtol(argv[0], NULL, 10); 1328 CGDisplayCount display_count = PROCFS_GetDisplayCount(); 1329 1330 if (index >= display_count) { 1331 return -ENOENT; 1332 } 1333 1334 if (display_png) { 1335 CFRelease(display_png); 1336 display_png = (CFMutableDataRef)0; 1337 } 1338 1339 int ret = PROCFS_GetPNGForDisplayAtIndex(index, &display_png); 1340 if (ret) { 1341 if (display_png) { 1342 CFRelease(display_png); 1343 display_png = (CFMutableDataRef)0; 1344 } 1345 return -EIO; 1346 } 1347 1348 return 0; 1349} 1350 1351OPENDIR_HANDLER(default_directory) 1352{ 1353 return 0; 1354} 1355 1356OPENDIR_HANDLER(enotdir) 1357{ 1358 return -ENOTDIR; 1359} 1360 1361// END: OPEN/OPENDIR 1362 1363 1364// BEGIN: RELEASE/RELEASEDIR 1365 1366// 1367// int 1368// procfs_release/releasedir_<handler>(procfs_dispatcher_entry_t e, 1369// const char *argv[], 1370// const char *path, 1371// struct fuse_file_info *fi) 1372 1373RELEASE_HANDLER(default_file) 1374{ 1375 return 0; 1376} 1377 1378RELEASE_HANDLER(eisdir) 1379{ 1380 return -EISDIR; 1381} 1382 1383RELEASE_HANDLER(proc__windows__identify) 1384{ 1385 fi->fh = 0; 1386 1387 return 0; 1388} 1389 1390RELEASE_HANDLER(proc__windows__screenshots__window) 1391{ 1392 if (fi->fh) { 1393 struct ProcfsWindowData *pwd = (struct ProcfsWindowData *)(fi->fh); 1394 CFRelease((CFMutableDataRef)(pwd->window_png)); 1395 free((void *)pwd); 1396 fi->fh = 0; 1397 } 1398 1399 return 0; 1400} 1401 1402RELEASE_HANDLER(system__hardware__camera__screenshot) 1403{ 1404 pthread_mutex_lock(&camera_lock); 1405 camera_busy = 0; 1406 pthread_mutex_unlock(&camera_lock); 1407 1408 return 0; 1409} 1410 1411RELEASE_HANDLER(system__hardware__displays__display__screenshot) 1412{ 1413 pthread_mutex_lock(&display_lock); 1414 display_busy = 0; 1415 if (display_png) { 1416 CFRelease(display_png); 1417 display_png = (CFMutableDataRef)0; 1418 } 1419 pthread_mutex_unlock(&display_lock); 1420 1421 return 0; 1422} 1423 1424RELEASEDIR_HANDLER(default_directory) 1425{ 1426 return 0; 1427} 1428 1429RELEASEDIR_HANDLER(enotdir) 1430{ 1431 return -ENOTDIR; 1432} 1433 1434// END: RELEASE/RELEASEDIR 1435 1436 1437// BEGIN: GETATTR 1438 1439// 1440// int 1441// procfs_getattr_<handler>(procfs_dispatcher_entry_t e, 1442// const char *argv[], 1443// struct stat *stbuf) 1444 1445 1446GETATTR_HANDLER(default_file) 1447{ 1448 time_t current_time = time(NULL); 1449 stbuf->st_mode = S_IFREG | 0444; 1450 stbuf->st_nlink = 1; 1451 stbuf->st_size = 0; 1452 if (procfs_ui) { 1453 stbuf->st_size = PROCFS_DEFAULT_FILE_SIZE; 1454 } 1455 stbuf->st_atime = stbuf->st_ctime = stbuf->st_mtime = current_time; 1456 1457 return 0; 1458} 1459 1460GETATTR_HANDLER(default_file_finder_info) 1461{ 1462 if (!procfs_ui) { 1463 return -ENOENT; 1464 } 1465 1466 time_t current_time = time(NULL); 1467 stbuf->st_mode = S_IFREG | 0444; 1468 stbuf->st_nlink = 1; 1469 stbuf->st_size = 82; 1470 stbuf->st_atime = stbuf->st_ctime = stbuf->st_mtime = current_time; 1471 1472 return 0; 1473} 1474 1475GETATTR_HANDLER(default_directory) 1476{ 1477 time_t current_time = time(NULL); 1478 1479 stbuf->st_mode = S_IFDIR | 0555; 1480 stbuf->st_nlink = 1; 1481 stbuf->st_size = 0; 1482 stbuf->st_atime = stbuf->st_ctime = stbuf->st_mtime = current_time; 1483 1484 return 0; 1485} 1486 1487GETATTR_HANDLER(default_link) 1488{ 1489 stbuf->st_mode = S_IFLNK | 0755; 1490 stbuf->st_nlink = 1; 1491 stbuf->st_size = 0; 1492 1493 return 0; 1494} 1495 1496GETATTR_HANDLER(byname__name) 1497{ 1498 const char *target_Pname = argv[0]; 1499 struct stat the_stat; 1500 char the_name[MAXNAMLEN + 1]; 1501 Boolean strstatus = false; 1502 1503 ProcessSerialNumber psn; 1504 OSErr osErr = noErr; 1505 OSStatus status; 1506 CFStringRef Pname; 1507 pid_t Pid; 1508 1509 psn.highLongOfPSN = kNoProcess; 1510 psn.lowLongOfPSN = kNoProcess; 1511 1512 while ((osErr = GetNextProcess(&psn)) != procNotFound) { 1513 status = GetProcessPID(&psn, &Pid); 1514 if (status != noErr) { 1515 continue; 1516 } 1517 Pname = (CFStringRef)0; 1518 status = CopyProcessName(&psn, &Pname); 1519 if (status != noErr) { 1520 if (Pname) { 1521 CFRelease(Pname); 1522 Pname = (CFStringRef)0; 1523 } 1524 continue; 1525 } 1526 1527 strstatus = CFStringGetCString(Pname, the_name, MAXNAMLEN, 1528 kCFStringEncodingASCII); 1529 if (strstatus != true) { 1530 Pid = 0; 1531 } else if (strcmp(target_Pname, the_name) != 0) { 1532 Pid = 0; 1533 } 1534 1535 CFRelease(Pname); 1536 Pname = (CFStringRef)0; 1537 1538 if (Pid) { 1539 break; 1540 } 1541 } 1542 1543 if (!Pid) { 1544 return -ENOENT; 1545 } 1546 1547 time_t current_time = time(NULL); 1548 stbuf->st_mode = S_IFLNK | 0755; 1549 stbuf->st_nlink = 1; 1550 stbuf->st_atime = stbuf->st_ctime = stbuf->st_mtime = current_time; 1551 int len = snprintf(the_name, MAXNAMLEN, "../%u", Pid); 1552 the_stat.st_size = len; 1553 1554 return 0; 1555} 1556 1557GETATTR_HANDLER(system__hardware__displays__display) 1558{ 1559 unsigned long index = strtol(argv[0], NULL, 10); 1560 CGDisplayCount display_count = PROCFS_GetDisplayCount(); 1561 1562 if (index >= display_count) { 1563 return -ENOENT; 1564 } 1565 1566 time_t current_time = time(NULL); 1567 1568 stbuf->st_mode = S_IFDIR | 0555; 1569 stbuf->st_nlink = 1; 1570 stbuf->st_size = 0; 1571 stbuf->st_atime = stbuf->st_ctime = stbuf->st_mtime = current_time; 1572 1573 return 0; 1574} 1575 1576GETATTR_HANDLER(system__hardware__camera__screenshot) 1577{ 1578 time_t current_time = time(NULL); 1579 1580 stbuf->st_mode = S_IFREG | 0444; 1581 stbuf->st_nlink = 1; 1582 stbuf->st_atime = stbuf->st_ctime = stbuf->st_mtime = current_time; 1583 stbuf->st_size = PROCFS_GetTIFFSizeFromCamera(); 1584 1585 return 0; 1586} 1587 1588GETATTR_HANDLER(system__hardware__displays__display__screenshot) 1589{ 1590 unsigned long index = strtol(argv[0], NULL, 10); 1591 1592 time_t current_time = time(NULL); 1593 1594 stbuf->st_mode = S_IFREG | 0444; 1595 stbuf->st_nlink = 1; 1596 stbuf->st_atime = stbuf->st_ctime = stbuf->st_mtime = current_time; 1597 stbuf->st_size = PROCFS_GetPNGSizeForDisplayAtIndex(index); 1598 1599 return 0; 1600} 1601 1602#if MACFUSE_PROCFS_ENABLE_TPM 1603GETATTR_HANDLER(system__hardware__tpm__keyslots__slot) 1604{ 1605 uint32_t keys[256]; 1606 unsigned long slotno = strtol(argv[0], NULL, 10); 1607 1608 uint16_t slots_used = 0; 1609 uint32_t slots_free = 0; 1610 uint32_t slots_total = 0; 1611 1612 if (TPM_GetCapability_Slots(&slots_free)) { 1613 return -ENOENT; 1614 } 1615 1616 if (TPM_GetCapability_Key_Handle(&slots_used, keys)) { 1617 return -ENOENT; 1618 } 1619 1620 slots_total = slots_used + slots_free; 1621 1622 if (slotno >= slots_total) { 1623 return -ENOENT; 1624 } 1625 1626 time_t current_time = time(NULL); 1627 stbuf->st_nlink = 1; 1628 stbuf->st_size = 9; 1629 stbuf->st_atime = stbuf->st_ctime = stbuf->st_mtime = current_time; 1630 1631 if (slotno >= slots_used) { 1632 stbuf->st_mode = S_IFREG | 0000; 1633 } else { 1634 stbuf->st_mode = S_IFREG | 0444; 1635 } 1636 1637 return 0; 1638} 1639 1640GETATTR_HANDLER(system__hardware__tpm__pcrs__pcr) 1641{ 1642 time_t current_time = time(NULL); 1643 stbuf->st_mode = S_IFREG | 0444; 1644 stbuf->st_nlink = 1; 1645 stbuf->st_size = 60; 1646 stbuf->st_atime = stbuf->st_ctime = stbuf->st_mtime = current_time; 1647 1648 return 0; 1649} 1650#endif /* MACFUSE_PROCFS_ENABLE_TPM */ 1651 1652GETATTR_HANDLER(proc__task__ports__port) 1653{ 1654 kern_return_t kr; 1655 task_t the_task = MACH_PORT_NULL; 1656 pid_t pid = strtol(argv[0], NULL, 10); 1657 1658 kr = task_for_pid(mach_task_self(), pid, &the_task); 1659 if (kr != KERN_SUCCESS) { 1660 return -ENOENT; 1661 } 1662 1663 DECL_PORT_LIST(); 1664 INIT_PORT_LIST(the_task); 1665 1666 int found = 0; 1667 unsigned int i; 1668 unsigned int the_port_name = strtoul(argv[1], NULL, 16); 1669 1670 for (i = 0; i < name_count; i++) { 1671 if (the_port_name == name_list[i]) { 1672 found = 1; 1673 break; 1674 } 1675 } 1676 1677 FINI_PORT_LIST(); 1678 1679 if (the_task != MACH_PORT_NULL) { 1680 mach_port_deallocate(mach_task_self(), the_task); 1681 } 1682 1683 if (!found) { 1684 return -ENOENT; 1685 } 1686 1687 time_t current_time = time(NULL); 1688 1689 stbuf->st_mode = S_IFDIR | 0555; 1690 stbuf->st_nlink = 1; 1691 stbuf->st_size = 0; 1692 stbuf->st_atime = stbuf->st_ctime = stbuf->st_mtime = current_time; 1693 1694 return 0; 1695} 1696 1697GETATTR_HANDLER(proc__task__threads__thread) 1698{ 1699 kern_return_t kr; 1700 task_t the_task = MACH_PORT_NULL; 1701 pid_t pid = strtol(argv[0], NULL, 10); 1702 1703 kr = task_for_pid(mach_task_self(), pid, &the_task); 1704 if (kr != KERN_SUCCESS) { 1705 return -ENOENT; 1706 } 1707 1708 DECL_THREAD_LIST(); 1709 INIT_THREAD_LIST(the_task); 1710 FINI_THREAD_LIST(); 1711 1712 if (the_task != MACH_PORT_NULL) { 1713 mach_port_deallocate(mach_task_self(), the_task); 1714 } 1715 1716 unsigned int the_thread_name = strtoul(argv[1], NULL, 16); 1717 if (the_thread_name >= thread_count) { 1718 return -ENOENT; 1719 } 1720 1721 time_t current_time = time(NULL); 1722 1723 stbuf->st_mode = S_IFDIR | 0555; 1724 stbuf->st_nlink = 1; 1725 stbuf->st_size = 0; 1726 stbuf->st_atime = stbuf->st_ctime = stbuf->st_mtime = current_time; 1727 1728 return 0; 1729} 1730 1731GETATTR_HANDLER(proc__windows__screenshots__window) 1732{ 1733 pid_t pid = strtol(argv[0], NULL, 10); 1734 CGWindowID target = strtol(argv[1], NULL, 16); 1735 ProcessSerialNumber psn; 1736 1737 OSStatus status = GetProcessForPID(pid, &psn); 1738 if (status != noErr) { 1739 return 0; /* technically not an error in this case */ 1740 } 1741 1742 CGSConnectionID conn; 1743 CGError err = CGSGetConnectionIDForPSN(0, &psn, &conn); 1744 if (err != kCGErrorSuccess) { 1745 return 0; /* just be nice */ 1746 } 1747 1748#define MAX_WINDOWS 256 1749 CGSWindowID windowIDs[MAX_WINDOWS]; 1750 int windowCount = 0; 1751 int i = 0; 1752 1753 err = CGSGetWindowList(_CGSDefaultConnection(), conn, MAX_WINDOWS, 1754 windowIDs, &windowCount); 1755 1756 for (i = 0; i < windowCount; i++) { 1757 if (windowIDs[i] == target) { 1758 time_t current_time = time(NULL); 1759 1760 stbuf->st_mode = S_IFREG | 0444; 1761 stbuf->st_nlink = 1; 1762 stbuf->st_atime = stbuf->st_ctime = stbuf->st_mtime = current_time; 1763 stbuf->st_size = PROCFS_GetPNGSizeForWindowAtIndex(windowIDs[i]); 1764 return 0; 1765 } 1766 } 1767 1768 return -ENOENT; 1769} 1770 1771// END: GETATTR 1772 1773 1774#include <stdio.h> 1775#include <stdlib.h> 1776#include <string.h> 1777#include <libgen.h> 1778#include <sys/sysctl.h> 1779 1780int 1781procinfo(pid_t pid, struct kinfo_proc *kp) 1782{ 1783 int mib[4]; 1784 size_t bufsize = 0, orig_bufsize = 0; 1785 struct kinfo_proc *kprocbuf; 1786 int retry_count = 0; 1787 int local_error; 1788 1789 mib[0] = CTL_KERN; 1790 mib[1] = KERN_PROC; 1791 mib[2] = KERN_PROC_PID; 1792 mib[3] = pid; 1793 1794 kprocbuf = kp; 1795 orig_bufsize = bufsize = sizeof(struct kinfo_proc); 1796 for (retry_count = 0; ; retry_count++) { 1797 local_error = 0; 1798 bufsize = orig_bufsize; 1799 if ((local_error = sysctl(mib, 4, kp, &bufsize, NULL, 0)) < 0) { 1800 if (retry_count < 1000) { 1801 sleep(1); 1802 continue; 1803 } 1804 return local_error; 1805 } else if (local_error == 0) { 1806 break; 1807 } 1808 sleep(1); 1809 } 1810 1811 return local_error; 1812} 1813 1814int 1815getproccmdline(pid_t pid, char *cmdlinebuf, int len) 1816{ 1817 int i, mib[4], rlen, tlen, thislen; 1818 int argmax, target_argc; 1819 char *target_argv, *target_argv_end; 1820 char *cp; 1821 size_t size; 1822 1823 if (pid == 0) { 1824 return snprintf(cmdlinebuf, len, "kernel\n"); 1825 } 1826 1827 mib[0] = CTL_KERN; 1828 mib[1] = KERN_ARGMAX; 1829 1830 size = sizeof(argmax); 1831 if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) { 1832 return -1; 1833 } 1834 1835 target_argv = (char *)malloc(argmax); 1836 if (target_argv == NULL) { 1837 return -1; 1838 } 1839 1840 target_argv_end = target_argv + argmax; 1841 1842 mib[0] = CTL_KERN; 1843 mib[1] = KERN_PROCARGS2; 1844 mib[2] = pid; 1845 1846 size = (size_t)argmax; 1847 if (sysctl(mib, 3, target_argv, &size, NULL, 0) == -1) { 1848 free(target_argv); 1849 return -1; 1850 } 1851 1852 memcpy(&target_argc, target_argv, sizeof(target_argc)); 1853 cp = target_argv + sizeof(target_argc); 1854 cp += strlen(cp) + 1; // saved exec path 1855 rlen = len; 1856 tlen = 0; 1857 for (i = 1; i < target_argc + 1; i++) { 1858 while (cp < target_argv_end && *cp == '\0') 1859 cp++; 1860 if (cp == target_argv_end) { 1861 /* 1862 * We've reached the end of target_argv without finding target_argc 1863 * arguments. This can happen when a process changes its argv. 1864 * Reported by Francis Devereux. 1865 */ 1866 break; 1867 } 1868 thislen = snprintf(cmdlinebuf + tlen, rlen, "%s ", cp); 1869 tlen += thislen; 1870 rlen -= thislen; 1871 if (rlen <= 0) { 1872 break; 1873 } 1874 cp += strlen(cp) + 1; 1875 } 1876 if (rlen > 0) { 1877 thislen = snprintf(cmdlinebuf + tlen, rlen, "\n"); 1878 tlen += thislen; 1879 rlen -= thislen; 1880 } 1881 return tlen; 1882} 1883 1884// BEGIN: READ 1885 1886// int 1887// procfs_read_<handler>(procfs_dispatcher_entry_t e, 1888// const char *argv[], 1889// void *buf, 1890// size_t size, 1891// off_t offset, 1892// struct fuse_file_info *fi) 1893 1894 1895READ_HANDLER(einval) 1896{ 1897 return -EINVAL; 1898} 1899 1900READ_HANDLER(eisdir) 1901{ 1902 return -EISDIR; 1903} 1904 1905READ_HANDLER(zero) 1906{ 1907 return 0; 1908} 1909 1910READ_HANDLER(default_file_finder_info) 1911{ 1912 if (!procfs_ui) { 1913 return -ENOENT; 1914 } 1915 1916 char tmpbuf[] = { 1917 0x0, 0x5, 0x16, 0x7, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 1918 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 1919 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x32, 0x0, 0x0, 0x0, 0x20, 0x0, 1920 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x52, 0x0, 0x0, 0x0, 0x0, 0x54, 0x45, 1921 0x58, 0x54, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 1922 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 1923 0x0, 0x0, 0x0, 0x0, 1924 }; 1925 int len = 82; 1926 1927 if (offset < len) { 1928 if (offset + size > len) 1929 size = len - offset; 1930 memcpy(buf, tmpbuf + offset, size); 1931 } else 1932 size = 0; 1933 1934 return size; 1935} 1936 1937READ_HANDLER(system__firmware__variables) 1938{ 1939 io_registry_entry_t options; 1940 CFMutableDictionaryRef optionsDict; 1941 kern_return_t kr = KERN_FAILURE; 1942 1943 options = IORegistryEntryFromPath(kIOMasterPortDefault, 1944 kIODeviceTreePlane ":/options"); 1945 if (options) { 1946 kr = IORegistryEntryCreateCFProperties(options, &optionsDict, 0, 0); 1947 if (kr == KERN_SUCCESS) { 1948 CFDataRef xml = CFPropertyListCreateXMLData(kCFAllocatorDefault, 1949 (CFPropertyListRef)optionsDict); 1950 1951 int len = CFDataGetLength(xml); 1952 if (len < 0) { 1953 kr = KERN_FAILURE; 1954 goto done; 1955 } 1956 1957 const UInt8 *tmpbuf = CFDataGetBytePtr(xml); 1958 1959 if (offset < len) { 1960 if (offset + size > len) 1961 size = len - offset; 1962 memcpy(buf, tmpbuf + offset, size); 1963 } else 1964 size = 0; 1965done: 1966 CFRelease(xml); 1967 CFRelease(optionsDict); 1968 } 1969 IOObjectRelease(options); 1970 } 1971 1972 if (kr != KERN_SUCCESS) { 1973 return -EIO; 1974 } 1975 1976 return size; 1977} 1978 1979READ_HANDLER(system__hardware__cpus__cpu__data) 1980{ 1981 int len; 1982 kern_return_t kr; 1983 char tmpbuf[4096]; 1984 const char *whichfile = argv[0]; 1985 unsigned int whichcpu = atoi(whichfile); 1986 1987 if (whichcpu >= processor_count) { 1988 return -ENOENT; 1989 } 1990 1991 processor_basic_info_data_t basic_info; 1992 processor_cpu_load_info_data_t cpu_load_info; 1993 natural_t info_count; 1994 host_name_port_t myhost = mach_host_self(); 1995 1996 info_count = PROCESSOR_BASIC_INFO_COUNT; 1997 kr = processor_info(processor_list[whichcpu], PROCESSOR_BASIC_INFO, 1998 &myhost, (processor_info_t)&basic_info, &info_count); 1999 if (kr != KERN_SUCCESS) { 2000 return -EIO; 2001 } 2002 info_count = PROCESSOR_CPU_LOAD_INFO_COUNT; 2003 kr = processor_info(processor_list[whichcpu], PROCESSOR_CPU_LOAD_INFO, 2004 &myhost, (processor_info_t)&cpu_load_info, &info_count); 2005 if (kr != KERN_SUCCESS) { 2006 return -EIO; 2007 } 2008 2009 len = 0; 2010 unsigned long ticks; 2011 2012 len += snprintf(tmpbuf + len, 4096 - len, "slot %d%s%s", 2013 basic_info.slot_num, 2014 (basic_info.is_master) ? " (master)," : ",", 2015 (basic_info.running) ? " running\n" : " not running\n"); 2016 len += snprintf(tmpbuf + len, 4096 - len, "type %d, subtype %d\n", 2017 basic_info.cpu_type, basic_info.cpu_subtype); 2018 2019 ticks = cpu_load_info.cpu_ticks[CPU_STATE_USER] + 2020 cpu_load_info.cpu_ticks[CPU_STATE_SYSTEM] + 2021 cpu_load_info.cpu_ticks[CPU_STATE_IDLE] + 2022 cpu_load_info.cpu_ticks[CPU_STATE_NICE]; 2023 len += snprintf(tmpbuf + len, 4096 - len, 2024 "%ld ticks (user %u system %u idle %u nice %u)\n", 2025 ticks, 2026 cpu_load_info.cpu_ticks[CPU_STATE_USER], 2027 cpu_load_info.cpu_ticks[CPU_STATE_SYSTEM], 2028 cpu_load_info.cpu_ticks[CPU_STATE_IDLE], 2029 cpu_load_info.cpu_ticks[CPU_STATE_NICE]); 2030 len += snprintf(tmpbuf + len, 4096 - len, "cpu uptime %ldh %ldm %lds\n", 2031 (ticks / 100) / 3600, ((ticks / 100) % 3600) / 60, 2032 (ticks / 100) % 60); 2033 2034 if (len < 0) { 2035 return -EIO; 2036 } 2037 2038 if (offset < len) { 2039 if (offset + size > len) 2040 size = len - offset; 2041 memcpy(buf, tmpbuf + offset, size); 2042 } else 2043 size = 0; 2044 2045 return size; 2046} 2047 2048READ_HANDLER(system__hardware__displays__display__info) 2049{ 2050 char tmpbuf[4096]; 2051 unsigned long index = strtol(argv[0], NULL, 10); 2052 CGDisplayCount display_count = PROCFS_GetDisplayCount(); 2053 2054 if (index >= display_count) { 2055 return -ENOENT; 2056 } 2057 2058 size_t len = 4096; 2059 int ret = PROCFS_GetInfoForDisplayAtIndex(index, tmpbuf, &len); 2060 if (ret) { 2061 return -EIO; 2062 } 2063 2064 if (len < 0) { 2065 return -EIO; 2066 } 2067 2068 if (offset < len) { 2069 if (offset + size > len) 2070 size = len - offset; 2071 memcpy(buf, tmpbuf + offset, size); 2072 } else 2073 size = 0; 2074 2075 return size; 2076} 2077 2078READ_HANDLER(system__hardware__camera__screenshot) 2079{ 2080 size_t max_len = PROCFS_GetTIFFSizeFromCamera(); 2081 size_t len = (size_t)CFDataGetLength(camera_tiff); 2082 2083 if (len > max_len) { 2084 return -EIO; 2085 } 2086 2087 CFDataSetLength(camera_tiff, max_len); 2088 2089 const UInt8 *tmpbuf = CFDataGetBytePtr(camera_tiff); 2090 2091 if (len < 0) { 2092 return -EIO; 2093 } 2094 2095 if (offset < len) { 2096 if (offset + size > len) 2097 size = len - offset; 2098 memcpy(buf, tmpbuf + offset, size); 2099 } else 2100 size = 0; 2101 2102 return size; 2103} 2104 2105READ_HANDLER(system__hardware__displays__display__screenshot) 2106{ 2107 unsigned long index = strtol(argv[0], NULL, 10); 2108 CGDisplayCount display_count = PROCFS_GetDisplayCount(); 2109 2110 if (index >= display_count) { 2111 return -ENOENT; 2112 2113 } 2114 pthread_mutex_lock(&display_lock); 2115 if (!display_png) { 2116 pthread_mutex_unlock(&display_lock); 2117 return -EIO; 2118 } 2119 CFRetain(display_png); 2120 pthread_mutex_unlock(&display_lock); 2121 2122 size_t max_len = PROCFS_GetPNGSizeForDisplayAtIndex(index); 2123 size_t len = (size_t)CFDataGetLength(display_png); 2124 2125 if (len > max_len) { 2126 pthread_mutex_lock(&display_lock); 2127 CFRelease(display_png); 2128 pthread_mutex_unlock(&display_lock); 2129 return -EIO; 2130 } 2131 2132 CFDataSetLength(display_png, max_len); 2133 len = max_len; 2134 const UInt8 *tmpbuf = CFDataGetBytePtr(display_png); 2135 2136 if (len < 0) { 2137 pthread_mutex_lock(&display_lock); 2138 CFRelease(display_png); 2139 pthread_mutex_unlock(&display_lock); 2140 return -EIO; 2141 } 2142 2143 if (offset < len) { 2144 if (offset + size > len) 2145 size = len - offset; 2146 memcpy(buf, tmpbuf + offset, size); 2147 } else 2148 size = 0; 2149 2150 pthread_mutex_lock(&display_lock); 2151 CFRelease(display_png); 2152 pthread_mutex_unlock(&display_lock); 2153 2154 return size; 2155} 2156 2157typedef struct { 2158 const char *classname; 2159 unsigned int index; 2160 IOItemCount structureInputSize; 2161 IOByteCount structureOutputSize; 2162} sms_configuration_t; 2163 2164sms_configuration_t 2165SMS_CONFIGURATIONS[] = { 2166 { "SMCMotionSensor", 5, 40, 40 }, // 0 2167 { "PMUMotionSensor", 21, 60, 60 }, // 1 2168 { "IOI2CMotionSensor", 21, 60, 60 }, // 2 2169 { NULL, -1, 0, 0 }, 2170}; 2171 2172enum { sms_maxConfigurationID = 2 }; 2173 2174static int sms_configurationID = -1; 2175 2176READ_HANDLER(system__hardware__xsensor) 2177{ 2178 int len = -1; 2179 kern_return_t kr; 2180 char tmpbuf[4096]; 2181 const char *whichfile = argv[0]; 2182 2183 if (strcmp(whichfile, "lightsensor") == 0) { 2184 unsigned int gIndex = 0; 2185 IOItemCount scalarInputCount = 0; 2186 IOItemCount scalarOutputCount = 2; 2187 SInt32 left = 0, right = 0; 2188 if (lightsensor_port == 0) { 2189 len = snprintf(tmpbuf, 4096, "not available\n"); 2190 goto gotdata; 2191 } 2192 kr = IOConnectMethodScalarIScalarO(lightsensor_port, gIndex, 2193 scalarInputCount, scalarOutputCount, 2194 &left, &right); 2195 if (kr == KERN_SUCCESS) { 2196 len = snprintf(tmpbuf, 4096, "%ld %ld\n", left, right); 2197 } else if (kr == kIOReturnBusy) { 2198 len = snprintf(tmpbuf, 4096, "busy\n"); 2199 } else { 2200 len = snprintf(tmpbuf, 4096, "error %d\n", kr); 2201 } 2202 goto gotdata; 2203 } 2204 2205 if (strcmp(whichfile, "motionsensor") == 0) { 2206 MotionSensorData_t sms_data; 2207 if (motionsensor_port == 0) { 2208 len = snprintf(tmpbuf, 4096, "not available\n"); 2209 goto gotdata; 2210 } 2211 kr = sms_getOrientation_hardware_apple(&sms_data); 2212 if (kr != KERN_SUCCESS) { 2213 len = snprintf(tmpbuf, 4096, "error %d\n", kr); 2214 } else { 2215 len = snprintf(tmpbuf, 4096, "%hhd %hhd %hhd\n", 2216 sms_data.x, sms_data.y, sms_data.z); 2217 } 2218 goto gotdata; 2219 } 2220 2221 if (strcmp(whichfile, "mouse") == 0) { 2222 HIPoint mouselocation = { 0.0, 0.0 }; 2223 (void)HIGetMousePosition(kHICoordSpaceScreenPixel, 2224 NULL, &mouselocation); 2225 len = snprintf(tmpbuf, 4096, "%.0f %.0f\n", 2226 mouselocation.x, mouselocation.y); 2227 goto gotdata; 2228 } 2229 2230gotdata: 2231 2232 if (len < 0) { 2233 return -EIO; 2234 } 2235 2236 if (offset < len) { 2237 if (offset + size > len) 2238 size = len - offset; 2239 memcpy(buf, tmpbuf + offset, size); 2240 } else 2241 size = 0; 2242 2243 return size; 2244} 2245 2246/* 2247 * To make the tpm stuff work, you need to: 2248 * 2249 * 1. Get the Mac OS X TPM device driver from 2250 * http://osxbook.com/book/bonus/chapter10/tpm/ 2251 * 2252 * 2. Get IBM's libtpm user-space library. 2253 * 2254 * 3. Define MACFUSE_PROCFS_ENABLE_TPM to 1, compile procfs.cc, and link with 2255 * libtpm. 2256 */ 2257 2258#if MACFUSE_PROCFS_ENABLE_TPM 2259READ_HANDLER(system__hardware__tpm__hwmodel) 2260{ 2261 int len; 2262 char tmpbuf[4096]; 2263 2264 len = snprintf(tmpbuf, 4096, "%s\n", "SLB 9635 TT 1.2"); 2265 2266 if (len <= 0) { 2267 return -EIO; 2268 } 2269 2270 if (offset < len) { 2271 if (offset + size > len) 2272 size = len - offset; 2273 memcpy(buf, tmpbuf + offset, size); 2274 } else 2275 size = 0; 2276 2277 return size; 2278} 2279 2280READ_HANDLER(system__hardware__tpm__hwvendor) 2281{ 2282 int len; 2283 char tmpbuf[4096]; 2284 2285 len = snprintf(tmpbuf, 4096, "%s\n", "Infineon"); 2286 2287 if (len <= 0) { 2288 return -EIO; 2289 } 2290 2291 if (offset < len) { 2292 if (offset + size > len) 2293 size = len - offset; 2294 memcpy(buf, tmpbuf + offset, size); 2295 } else 2296 size = 0; 2297 2298 return size; 2299} 2300 2301READ_HANDLER(system__hardware__tpm__hwversion) 2302{ 2303 int major, minor, version, rev, len; 2304 char tmpbuf[4096]; 2305 2306 if (TPM_GetCapability_Version(&major, &minor, &version, &rev)) { 2307 return -EIO; 2308 } 2309 2310 len = snprintf(tmpbuf, 4096, "%d.%d.%d.%d\n", major, minor, version, rev); 2311 2312 if (len <= 0) { 2313 return -EIO; 2314 } 2315 2316 if (offset < len) { 2317 if (offset + size > len) 2318 size = len - offset; 2319 memcpy(buf, tmpbuf + offset, size); 2320 } else 2321 size = 0; 2322 2323 return size; 2324} 2325 2326READ_HANDLER(system__hardware__tpm__keyslots__slot) 2327{ 2328 char tmpbuf[32] = { 0 }; 2329 int len; 2330 uint32_t keys[256]; 2331 unsigned long slotno = strtol(argv[0], NULL, 10); 2332 2333 uint16_t slots_used = 0; 2334 uint32_t slots_free = 0; 2335 uint32_t slots_total = 0; 2336 2337 if (TPM_GetCapability_Slots(&slots_free)) { 2338 return -ENOENT; 2339 } 2340 2341 if (TPM_GetCapability_Key_Handle(&slots_used, keys)) { 2342 return -ENOENT; 2343 } 2344 2345 slots_total = slots_used + slots_free; 2346 2347 if (slotno >= slots_used) { 2348 return -EIO; 2349 } 2350 2351 len = snprintf(tmpbuf, 32, "%08x\n", keys[slotno]); 2352 if (offset < len) { 2353 if (offset + size > len) 2354 size = len - offset; 2355 memcpy(buf, tmpbuf + offset, size); 2356 } else { 2357 size = 0; 2358 } 2359 2360 return size; 2361} 2362 2363READ_HANDLER(system__hardware__tpm__pcrs__pcr) 2364{ 2365 uint32_t pcrs, the_pcr; 2366 unsigned char pcr_data[20]; 2367 char tmpbuf[4096] = { 0 }; 2368 int len, i; 2369 2370 if (TPM_GetCapability_Pcrs(&pcrs)) { 2371 return -EIO; 2372 } 2373 2374 the_pcr = strtol(argv[0], NULL, 10); 2375 if ((the_pcr < 0) || (the_pcr >= pcrs)) { 2376 return -ENOENT; 2377 } 2378 2379 if (TPM_PcrRead(the_pcr, pcr_data)) { 2380 return -EIO; 2381 } 2382 2383 len = 0; 2384 for (i = 0; i < 20; i++) { 2385 len += snprintf(tmpbuf + len, 4096 - len, "%02x ", pcr_data[i]); 2386 } 2387 tmpbuf[len - 1] = '\n'; 2388 2389 if (offset < len) { 2390 if (offset + size > len) 2391 size = len - offset; 2392 memcpy(buf, tmpbuf + offset, size); 2393 } else { 2394 size = 0; 2395 } 2396 2397 return size; 2398} 2399#endif /* MACFUSE_PROCFS_ENABLE_TPM */ 2400 2401READ_HANDLER(proc__carbon) 2402{ 2403 OSStatus status = procNotFound; 2404 ProcessSerialNumber psn; 2405 CFStringRef nameRef; 2406 char tmpbuf[4096]; 2407 int len = -1; 2408 2409 pid_t pid = atoi(argv[0]); 2410 const char *whichfile = argv[1]; 2411 2412 if (pid <= 0) { 2413 return 0; 2414 } 2415 2416 status = GetProcessForPID(pid, &psn); 2417 2418 if (status != noErr) { 2419 return 0; 2420 } 2421 2422 if (strcmp(whichfile, "psn") == 0) { 2423 len = snprintf(tmpbuf, 4096, "%lu:%lu\n", 2424 psn.highLongOfPSN, psn.lowLongOfPSN); 2425 goto gotdata; 2426 } 2427 2428 if (strcmp(whichfile, "name") == 0) { 2429 status = CopyProcessName(&psn, &nameRef); 2430 CFStringGetCString(nameRef, tmpbuf, 4096, kCFStringEncodingASCII); 2431 len = snprintf(tmpbuf, 4096, "%s\n", tmpbuf); 2432 CFRelease(nameRef); 2433 goto gotdata; 2434 } 2435 2436 return -ENOENT; 2437 2438gotdata: 2439 2440 if (len < 0) { 2441 return -EIO; 2442 } 2443 2444 if (offset < len) { 2445 if (offset + size > len) 2446 size = len - offset; 2447 memcpy(buf, tmpbuf + offset, size); 2448 } else 2449 size = 0; 2450 2451 return size; 2452} 2453 2454#if __i386__ 2455READ_HANDLER(proc__fds) 2456{ 2457 pid_t pid = atoi(argv[0]); 2458 char tmpbuf[65536]; 2459 int len = 65536; 2460 2461 int ret = procfs_proc_pidinfo(pid, tmpbuf, &len); 2462 2463 if (ret) { 2464 return -EIO; 2465 } 2466 2467 if (offset < len) { 2468 if (offset + size > len) 2469 size = len - offset; 2470 memcpy(buf, tmpbuf + offset, size); 2471 } else 2472 size = 0; 2473 2474 return size; 2475} 2476#endif /* __i386__ */ 2477 2478#define HANDLE_GENERIC_ITEM(item, fmt, datasrc) \ 2479 if (strcmp(whichfile, item) == 0) { \ 2480 len = snprintf(tmpbuf, 4096, fmt, datasrc); \ 2481 goto gotdata; \ 2482 } 2483 2484READ_HANDLER(proc__generic) 2485{ 2486 pid_t pid = atoi(argv[0]); 2487 const char *whichfile = argv[1]; 2488 struct kinfo_proc kp; 2489 int len; 2490 char tmpbuf[4096]; 2491 2492 len = procinfo(pid, &kp); 2493 if (len != 0) { 2494 return -EIO; 2495 } 2496 2497 len = -1; 2498 2499 if (strcmp(whichfile, "cmdline") == 0) { 2500 len = getproccmdline(pid, tmpbuf, 4096); 2501 goto gotdata; 2502 } 2503 2504 if (strcmp(whichfile, "tdev") == 0) { 2505 char *dr = devname_r(kp.kp_eproc.e_tdev, S_IFCHR, tmpbuf, 4096); 2506 if (!dr) { 2507 len = snprintf(tmpbuf, 4096, "none\n"); 2508 } else { 2509 len = snprintf(tmpbuf, 4096, "%s\n", dr); 2510 } 2511 goto gotdata; 2512 } 2513 2514 HANDLE_GENERIC_ITEM("jobc", "%hd\n", kp.kp_eproc.e_jobc); 2515 HANDLE_GENERIC_ITEM("paddr", "%p\n", kp.kp_eproc.e_paddr); 2516 HANDLE_GENERIC_ITEM("pgid", "%d\n", kp.kp_eproc.e_pgid); 2517 HANDLE_GENERIC_ITEM("ppid", "%d\n", kp.kp_eproc.e_ppid); 2518 HANDLE_GENERIC_ITEM("wchan", "%s\n", 2519 (kp.kp_eproc.e_wmesg[0]) ? kp.kp_eproc.e_wmesg : "-"); 2520 HANDLE_GENERIC_ITEM("tpgid", "%d\n", kp.kp_eproc.e_tpgid); 2521 2522gotdata: 2523 2524 if (len < 0) { 2525 return -EIO; 2526 } 2527 2528 if (offset < len) { 2529 if (offset + size > len) 2530 size = len - offset; 2531 memcpy(buf, tmpbuf + offset, size); 2532 } else 2533 size = 0; 2534 2535 return size; 2536} 2537 2538#define READ_PROC_TASK_PROLOGUE() \ 2539 int len = -1; \ 2540 kern_return_t kr; \ 2541 char tmpbuf[4096]; \ 2542 task_t the_task = MACH_PORT_NULL; \ 2543 pid_t pid = strtol(argv[0], NULL, 10); \ 2544 \ 2545 kr = task_for_pid(mach_task_self(), pid, &the_task); \ 2546 if (kr != KERN_SUCCESS) { \ 2547 return -EIO; \ 2548 } 2549 2550#define READ_PROC_TASK_EPILOGUE() \ 2551 \ 2552 if (the_task != MACH_PORT_NULL) { \ 2553 mach_port_deallocate(mach_task_self(), the_task); \ 2554 } \ 2555 \ 2556 if (len < 0) { \ 2557 return -EIO; \ 2558 } \ 2559 \ 2560 if (offset < len) { \ 2561 if (offset + size > len) \ 2562 size = len - offset; \ 2563 memcpy(buf, tmpbuf + offset, size); \ 2564 } else \ 2565 size = 0; \ 2566 \ 2567 return size; 2568 2569static const char *thread_policies[] = { 2570 "UNKNOWN?", 2571 "STANDARD|EXTENDED", 2572 "TIME_CONSTRAINT", 2573 "PRECEDENCE", 2574}; 2575#define THREAD_POLICIES_MAX (int)(sizeof(thread_policies)/sizeof(char *)) 2576 2577READ_HANDLER(proc__task__absolutetime_info) 2578{ 2579 READ_PROC_TASK_PROLOGUE(); 2580 2581 task_info_data_t tinfo; 2582 mach_msg_type_number_t task_info_count; 2583 task_absolutetime_info_t absolutetime_info; 2584 2585 task_info_count = TASK_INFO_MAX; 2586 kr = task_info(the_task, TASK_ABSOLUTETIME_INFO, (task_info_t)tinfo, 2587 &task_info_count); 2588 if (kr != KERN_SUCCESS) { 2589 return -EIO; 2590 } 2591 2592 const char *whichfile = argv[1]; 2593 absolutetime_info = (task_absolutetime_info_t)tinfo; 2594 2595 if (strcmp(whichfile, "threads_system") == 0) { 2596 len = snprintf(tmpbuf, 4096, "%lld\n", 2597 absolutetime_info->threads_system); 2598 goto gotdata; 2599 } 2600 2601 if (strcmp(whichfile, "threads_user") == 0) { 2602 len = snprintf(tmpbuf, 4096, "%lld\n", 2603 absolutetime_info->threads_user); 2604 goto gotdata; 2605 } 2606 2607 if (strcmp(whichfile, "total_system") == 0) { 2608 len = snprintf(tmpbuf, 4096, "%lld\n", 2609 absolutetime_info->total_system); 2610 goto gotdata; 2611 } 2612 2613 if (strcmp(whichfile, "total_user") == 0) { 2614 len = snprintf(tmpbuf, 4096, "%lld\n", 2615 absolutetime_info->total_user); 2616 goto gotdata; 2617 } 2618 2619gotdata: 2620 2621 READ_PROC_TASK_EPILOGUE(); 2622} 2623 2624READ_HANDLER(proc__task__basic_info) 2625{ 2626 READ_PROC_TASK_PROLOGUE(); 2627 2628 task_info_data_t tinfo; 2629 mach_msg_type_number_t task_info_count; 2630 task_basic_info_t basic_info; 2631 2632 task_info_count = TASK_INFO_MAX; 2633 kr = task_info(the_task, TASK_BASIC_INFO, (task_info_t)tinfo, 2634 &task_info_count); 2635 if (kr != KERN_SUCCESS) { 2636 return -EIO; 2637 } 2638 2639 basic_info = (task_basic_info_t)tinfo; 2640 const char *whichfile = argv[1]; 2641 2642 if (strcmp(whichfile, "policy") == 0) { 2643 if ((basic_info->policy < 0) && 2644 (basic_info->policy > THREAD_POLICIES_MAX)) { 2645 basic_info->policy = 0; 2646 } 2647 len = snprintf(tmpbuf, 4096, "%s\n", 2648 thread_policies[basic_info->policy]); 2649 goto gotdata; 2650 } 2651 2652 if (strcmp(whichfile, "resident_size") == 0) { 2653 len = snprintf(tmpbuf, 4096, "%u KB\n", 2654 basic_info->resident_size >> 10); 2655 goto gotdata; 2656 } 2657 2658 if (strcmp(whichfile, "suspend_count") == 0) { 2659 len = snprintf(tmpbuf, 4096, "%u\n", basic_info->suspend_count); 2660 goto gotdata; 2661 } 2662 2663 if (strcmp(whichfile, "system_time") == 0) { 2664 len = snprintf(tmpbuf, 4096, "%us %uus\n", 2665 basic_info->system_time.seconds, 2666 basic_info->system_time.microseconds); 2667 goto gotdata; 2668 } 2669 2670 if (strcmp(whichfile, "user_time") == 0) { 2671 len = snprintf(tmpbuf, 4096, "%us %uus\n", 2672 basic_info->user_time.seconds, 2673 basic_info->user_time.microseconds); 2674 goto gotdata; 2675 } 2676 2677 if (strcmp(whichfile, "virtual_size") == 0) { 2678 len = snprintf(tmpbuf, 4096, "%u KB\n", basic_info->virtual_size >> 10); 2679 goto gotdata; 2680 } 2681 2682gotdata: 2683 2684 READ_PROC_TASK_EPILOGUE(); 2685} 2686 2687READ_HANDLER(proc__task__events_info) 2688{ 2689 READ_PROC_TASK_PROLOGUE(); 2690 2691 task_info_data_t tinfo; 2692 mach_msg_type_number_t task_info_count; 2693 task_events_info_t events_info; 2694 2695 task_info_count = TASK_INFO_MAX; 2696 kr = task_info(the_task, TASK_EVENTS_INFO, (task_info_t)tinfo, 2697 &task_info_count); 2698 if (kr != KERN_SUCCESS) { 2699 return -EIO; 2700 } 2701 2702 const char *whichfile = argv[1]; 2703 events_info = (task_events_info_t)tinfo; 2704 2705#define HANDLE_TASK_EVENT_ITEM(item, datasrc) \ 2706 if (strcmp(whichfile, item) == 0) { \ 2707 len = snprintf(tmpbuf, 4096, "%u\n", datasrc); \ 2708 goto gotdata; \ 2709 } 2710 2711 HANDLE_TASK_EVENT_ITEM("cow_faults", events_info->cow_faults); 2712 HANDLE_TASK_EVENT_ITEM("csw", events_info->csw); 2713 HANDLE_TASK_EVENT_ITEM("faults", events_info->faults); 2714 HANDLE_TASK_EVENT_ITEM("messages_received", events_info->messages_received); 2715 HANDLE_TASK_EVENT_ITEM("messages_sent", events_info->messages_sent); 2716 HANDLE_TASK_EVENT_ITEM("pageins", events_info->pageins); 2717 HANDLE_TASK_EVENT_ITEM("syscalls_mach", events_info->syscalls_mach); 2718 HANDLE_TASK_EVENT_ITEM("syscalls_unix", events_info->syscalls_unix); 2719 2720 return -EIO; 2721 2722gotdata: 2723 2724 READ_PROC_TASK_EPILOGUE(); 2725} 2726 2727READ_HANDLER(proc__task__thread_times_info) 2728{ 2729 READ_PROC_TASK_PROLOGUE(); 2730 2731 task_info_data_t tinfo; 2732 mach_msg_type_number_t task_info_count; 2733 task_thread_times_info_t thread_times_info; 2734 2735 task_info_count = TASK_INFO_MAX; 2736 kr = task_info(the_task, TASK_THREAD_TIMES_INFO, (task_info_t)tinfo, 2737 &task_info_count); 2738 if (kr != KERN_SUCCESS) { 2739 return -EIO; 2740 } 2741 2742 const char *whichfile = argv[1]; 2743 thread_times_info = (task_thread_times_info_t)tinfo; 2744 2745 if (strcmp(whichfile, "system_time") == 0) { 2746 len = snprintf(tmpbuf, 4096, "%us %uus\n", 2747 thread_times_info->system_time.seconds, 2748 thread_times_info->system_time.microseconds); 2749 goto gotdata; 2750 } 2751 2752 if (strcmp(whichfile, "user_time") == 0) { 2753 len = snprintf(tmpbuf, 4096, "%us %uus\n", 2754 thread_times_info->user_time.seconds, 2755 thread_times_info->user_time.microseconds); 2756 goto gotdata; 2757 } 2758 2759 return -ENOENT; 2760 2761gotdata: 2762 2763 READ_PROC_TASK_EPILOGUE(); 2764} 2765 2766READ_HANDLER(proc__task__mach_name) 2767{ 2768 READ_PROC_TASK_PROLOGUE(); 2769 2770 len = snprintf(tmpbuf, 4096, "%x\n", the_task); 2771 2772 READ_PROC_TASK_EPILOGUE(); 2773} 2774 2775READ_HANDLER(proc__task__ports__port) 2776{ 2777 READ_PROC_TASK_PROLOGUE(); 2778 DECL_PORT_LIST(); 2779 INIT_PORT_LIST(the_task); 2780 unsigned int i; 2781 char the_name[MAXNAMLEN + 1]; 2782 mach_port_t the_port = MACH_PORT_NULL; 2783 mach_port_type_t the_type = 0; 2784 for (i = 0; i < name_count; i++) { 2785 snprintf(the_name, MAXNAMLEN, "%x", name_list[i]); 2786 if (strcmp(the_name, argv[1]) == 0) { 2787 the_port = name_list[i]; 2788 the_type = type_list[i]; 2789 break; 2790 } 2791 } 2792 2793 if (the_port == MACH_PORT_NULL) { 2794 FINI_PORT_LIST(); 2795 return -ENOENT; 2796 } 2797 2798 const char *whichfile = argv[2]; 2799 mach_msg_type_number_t port_info_count; 2800 2801 if (strcmp(whichfile, "task_rights") == 0) { 2802 len = 0; 2803 if (the_type & MACH_PORT_TYPE_SEND) { 2804 len += snprintf(tmpbuf + len, 4096 - len, "%s ", "SEND"); 2805 } 2806 if (the_type & MACH_PORT_TYPE_RECEIVE) { 2807 len += snprintf(tmpbuf + len, 4096 - len, "%s ", "RECEIVE"); 2808 } 2809 if (the_type & MACH_PORT_TYPE_SEND_ONCE) { 2810 len += snprintf(tmpbuf + len, 4096 - len, "%s ", "SEND_ONCE"); 2811 } 2812 if (the_type & MACH_PORT_TYPE_PORT_SET) { 2813 len += snprintf(tmpbuf + len, 4096 - len, "%s ", "PORT_SET"); 2814 } 2815 if (the_type & MACH_PORT_TYPE_DEAD_NAME) { 2816 len += snprintf(tmpbuf + len, 4096 - len, "%s ", "DEAD_NAME"); 2817 } 2818 if (the_type & MACH_PORT_TYPE_DNREQUEST) { 2819 len += snprintf(tmpbuf + len, 4096 - len, "%s ", "DNREQUEST"); 2820 } 2821 len += snprintf(tmpbuf + len, 4096 - len, "\n"); 2822 goto gotdata; 2823 } 2824 2825 mach_port_limits_t port_limits; 2826 mach_port_status_t port_status; 2827 2828 port_info_count = MACH_PORT_LIMITS_INFO_COUNT; 2829 kr = mach_port_get_attributes(the_task, the_port, MACH_PORT_LIMITS_INFO, 2830 (mach_port_info_t)&port_limits, 2831 &port_info_count); 2832 2833 if ((kr != KERN_SUCCESS) && (kr != KERN_INVALID_RIGHT)) { 2834 FINI_PORT_LIST(); 2835 return -EIO; 2836 } 2837 2838 if (strcmp(whichfile, "qlimit") == 0) { 2839 if (kr == KERN_SUCCESS) { 2840 len = snprintf(tmpbuf, 4096, "%d\n", port_limits.mpl_qlimit); 2841 } else { 2842 len = snprintf(tmpbuf, 4096, "-\n"); 2843 } 2844 goto gotdata; 2845 } 2846 2847 port_info_count = MACH_PORT_RECEIVE_STATUS_COUNT; 2848 kr = mach_port_get_attributes(the_task, the_port, MACH_PORT_RECEIVE_STATUS, 2849 (mach_port_info_t)&port_status, 2850 &port_info_count); 2851 if ((kr != KERN_SUCCESS) && (kr != KERN_INVALID_RIGHT)) { 2852 FINI_PORT_LIST(); 2853 return -EIO; 2854 } 2855 2856 if (strcmp(whichfile, "msgcount") == 0) { 2857 if (kr == KERN_SUCCESS) { 2858 len = snprintf(tmpbuf, 4096, "%d\n", port_status.mps_msgcount); 2859 } else { 2860 len = snprintf(tmpbuf, 4096, "-\n"); 2861 } 2862 goto gotdata; 2863 } 2864 2865 if (strcmp(whichfile, "seqno") == 0) { 2866 if (kr == KERN_SUCCESS) { 2867 len = snprintf(tmpbuf, 4096, "%d\n", port_status.mps_seqno); 2868 } else { 2869 len = snprintf(tmpbuf, 4096, "-\n"); 2870 } 2871 goto gotdata; 2872 } 2873 2874 if (strcmp(whichfile, "sorights") == 0) { 2875 if (kr == KERN_SUCCESS) { 2876 len = snprintf(tmpbuf, 4096, "%d\n", port_status.mps_sorights); 2877 } else { 2878 len = snprintf(tmpbuf, 4096, "-\n"); 2879 } 2880 goto gotdata; 2881 } 2882 2883gotdata: 2884 2885 FINI_PORT_LIST(); 2886 2887 READ_PROC_TASK_EPILOGUE(); 2888} 2889 2890static const char *task_roles[] = { 2891 "RENICED", 2892 "UNSPECIFIED", 2893 "FOREGROUND_APPLICATION", 2894 "BACKGROUND_APPLICATION", 2895 "CONTROL_APPLICATION", 2896 "GRAPHICS_SERVER", 2897}; 2898#define TASK_ROLES_MAX (int)(sizeof(task_roles)/sizeof(char *)) 2899 2900READ_HANDLER(proc__task__role) 2901{ 2902 READ_PROC_TASK_PROLOGUE(); 2903 2904 task_category_policy_data_t category_policy; 2905 mach_msg_type_number_t task_info_count; 2906 boolean_t get_default; 2907 2908 len = snprintf(tmpbuf, 4096, "NONE\n"); 2909 2910 task_info_count = TASK_CATEGORY_POLICY_COUNT; 2911 get_default = FALSE; 2912 kr = task_policy_get(the_task, TASK_CATEGORY_POLICY, 2913 (task_policy_t)&category_policy, 2914 &task_info_count, &get_default); 2915 if (kr == KERN_SUCCESS) { 2916 if (get_default == FALSE) { 2917 if ((category_policy.role >= -1) && 2918 (category_policy.role < (TASK_ROLES_MAX - 1))) { 2919 len = snprintf(tmpbuf, 4096, "%s\n", 2920 task_roles[category_policy.role + 1]); 2921 } 2922 } 2923 } 2924 2925 READ_PROC_TASK_EPILOGUE(); 2926} 2927 2928static const char *thread_states[] = { 2929 "NONE", 2930 "RUNNING", 2931 "STOPPED", 2932 "WAITING", 2933 "UNINTERRUPTIBLE", 2934 "HALTED", 2935}; 2936#define THREAD_STATES_MAX (int)(sizeof(thread_states)/sizeof(char *)) 2937 2938READ_HANDLER(proc__task__threads__thread__basic_info) 2939{ 2940 READ_PROC_TASK_PROLOGUE(); 2941 DECL_THREAD_LIST(); 2942 INIT_THREAD_LIST(the_task); 2943 2944 thread_t the_thread = MACH_PORT_NULL; 2945 unsigned int i = strtoul(argv[1], NULL, 16); 2946 2947 if (i < thread_count) { 2948 the_thread = thread_list[i]; 2949 } 2950 2951 if (the_thread == MACH_PORT_NULL) { 2952 FINI_THREAD_LIST(); 2953 return -ENOENT; 2954 } 2955 2956 const char *whichfile = argv[2]; 2957 2958 thread_info_data_t thinfo; 2959 mach_msg_type_number_t thread_info_count; 2960 thread_basic_info_t basic_info_th; 2961 2962 thread_info_count = THREAD_INFO_MAX; 2963 kr = thread_info(the_thread, THREAD_BASIC_INFO, (thread_info_t)thinfo, 2964 &thread_info_count); 2965 2966 if (kr != KERN_SUCCESS) { 2967 FINI_THREAD_LIST(); 2968 return -EIO; 2969 } 2970 2971 basic_info_th = (thread_basic_info_t)thinfo; 2972 2973 if (strcmp(whichfile, "cpu_usage") == 0) { 2974 len = snprintf(tmpbuf, 4096, "%u\n", basic_info_th->cpu_usage); 2975 goto gotdata; 2976 } 2977 2978 if (strcmp(whichfile, "flags") == 0) { 2979 len = 0; 2980 len += snprintf(tmpbuf + len, 4096 - len, "%x", basic_info_th->flags); 2981 len += snprintf(tmpbuf + len, 4096 - len, "%s", 2982 (basic_info_th->flags & TH_FLAGS_IDLE) ? " (IDLE)" : ""); 2983 len += snprintf(tmpbuf + len, 4096 - len, "%s", 2984 (basic_info_th->flags & TH_FLAGS_SWAPPED) ? " (SWAPPED)" : ""); 2985 len += snprintf(tmpbuf + len, 4096 - len, "\n"); 2986 goto gotdata; 2987 } 2988 2989 if (strcmp(whichfile, "policy") == 0) { 2990 2991 len = 0; 2992 boolean_t get_default = FALSE; 2993 thread_extended_policy_data_t extended_policy; 2994 thread_time_constraint_policy_data_t time_constraint_policy; 2995 thread_precedence_policy_data_t precedence_policy; 2996 2997 switch (basic_info_th->policy) { 2998 2999 case THREAD_EXTENDED_POLICY: 3000 thread_info_count = THREAD_EXTENDED_POLICY_COUNT; 3001 kr = thread_policy_get(the_thread, THREAD_EXTENDED_POLICY, 3002 (thread_policy_t)&extended_policy, 3003 &thread_info_count, &get_default); 3004 if (kr != KERN_SUCCESS) { 3005 len += snprintf(tmpbuf + len, 4096 - len, 3006 "STANDARD/EXTENDED\n"); 3007 break; 3008 } 3009 len += snprintf(tmpbuf + len, 4096 - len, "%s\n", 3010 (extended_policy.timeshare == TRUE) ? \ 3011 "STANDARD" : "EXTENDED"); 3012 break; 3013 3014 case THREAD_TIME_CONSTRAINT_POLICY: 3015 len += snprintf(tmpbuf + len, 4096 - len, "TIME_CONSTRAINT"); 3016 thread_info_count = THREAD_TIME_CONSTRAINT_POLICY_COUNT; 3017 kr = thread_policy_get(the_thread, THREAD_TIME_CONSTRAINT_POLICY, 3018 (thread_policy_t)&time_constraint_policy, 3019 &thread_info_count, &get_default); 3020 if (kr != KERN_SUCCESS) { 3021 len += snprintf(tmpbuf + len, 4096 - len, "\n"); 3022 break; 3023 } 3024 len += snprintf(tmpbuf + len, 4096 - len, 3025 " (period=%u computation=%u constraint=%u " 3026 "preemptible=%s)\n", 3027 time_constraint_policy.period, 3028 time_constraint_policy.computation, 3029 time_constraint_policy.constraint, 3030 (time_constraint_policy.preemptible == TRUE) ? \ 3031 "TRUE" : "FALSE"); 3032 break; 3033 3034 case THREAD_PRECEDENCE_POLICY: 3035 len += snprintf(tmpbuf + len, 4096 - len, "PRECEDENCE"); 3036 thread_info_count = THREAD_PRECEDENCE_POLICY; 3037 kr = thread_policy_get(the_thread, THREAD_PRECEDENCE_POLICY, 3038 (thread_policy_t)&precedence_policy, 3039 &thread_info_count, &get_default); 3040 if (kr != KERN_SUCCESS) { 3041 len += snprintf(tmpbuf + len, 4096 - len, "\n"); 3042 break; 3043 } 3044 len += snprintf(tmpbuf + len, 4096 - len, " (importance=%u)\n", 3045 precedence_policy.importance); 3046 break; 3047 3048 default: 3049 len = snprintf(tmpbuf, 4096, "UNKNOWN?\n"); 3050 break; 3051 } 3052 goto gotdata; 3053 } 3054 3055 if (strcmp(whichfile, "run_state") == 0) { 3056 len = 0; 3057 len += snprintf(tmpbuf + len, 4096 - len, "%u", 3058 basic_info_th->run_state); 3059 len += snprintf(tmpbuf + len, 4096 - len, " (%s)\n", 3060 (basic_info_th->run_state >= THREAD_STATE_MAX) ? \ 3061 "?" : thread_states[basic_info_th->run_state]); 3062 goto gotdata; 3063 } 3064 3065 if (strcmp(whichfile, "sleep_time") == 0) { 3066 len = snprintf(tmpbuf, 4096, "%us\n", basic_info_th->sleep_time); 3067 goto gotdata; 3068 } 3069 3070 if (strcmp(whichfile, "suspend_count") == 0) { 3071 len = snprintf(tmpbuf, 4096, "%u\n", basic_info_th->suspend_count); 3072 goto gotdata; 3073 } 3074 3075 if (strcmp(whichfile, "system_time") == 0) { 3076 len = snprintf(tmpbuf, 4096, "%us %uus\n", 3077 basic_info_th->system_time.seconds, 3078 basic_info_th->system_time.microseconds); 3079 goto gotdata; 3080 } 3081 3082 if (strcmp(whichfile, "user_time") == 0) { 3083 len = snprintf(tmpbuf, 4096, "%us %uus\n", 3084 basic_info_th->user_time.seconds, 3085 basic_info_th->user_time.microseconds); 3086 goto gotdata; 3087 } 3088 3089gotdata: 3090 3091 FINI_THREAD_LIST(); 3092 3093 READ_PROC_TASK_EPILOGUE(); 3094} 3095 3096READ_HANDLER(proc__task__threads__thread__states__debug) 3097{ 3098 READ_PROC_TASK_PROLOGUE(); 3099 len = snprintf(tmpbuf, 4096, "not yet implemented\n"); 3100 READ_PROC_TASK_EPILOGUE(); 3101} 3102 3103READ_HANDLER(proc__task__threads__thread__states__exception) 3104{ 3105 READ_PROC_TASK_PROLOGUE(); 3106 len = snprintf(tmpbuf, 4096, "not yet implemented\n"); 3107 READ_PROC_TASK_EPILOGUE(); 3108} 3109 3110READ_HANDLER(proc__task__threads__thread__states__float) 3111{ 3112 READ_PROC_TASK_PROLOGUE(); 3113 DECL_THREAD_LIST(); 3114 INIT_THREAD_LIST(the_task); 3115 3116 thread_t the_thread = MACH_PORT_NULL; 3117 unsigned int i = strtoul(argv[1], NULL, 16); 3118 3119 if (i < thread_count) { 3120 the_thread = thread_list[i]; 3121 } 3122 3123 if (the_thread == MACH_PORT_NULL) { 3124 FINI_THREAD_LIST(); 3125 return -ENOENT; 3126 } 3127 3128#if defined(__i386__) 3129 const char *whichfile = argv[2]; 3130 3131 x86_float_state_t state = { 0 }; 3132 unsigned int count = x86_FLOAT_STATE_COUNT; 3133 kr = thread_get_state(the_thread, x86_FLOAT_STATE, (thread_state_t)&state, 3134 &count); 3135 if (kr != KERN_SUCCESS) { 3136 FINI_THREAD_LIST(); 3137 return -EIO; 3138 } 3139 3140#define HANDLE_x86_FLOAT_STATE_ITEM(item, fmt) \ 3141 if (strcmp(whichfile, #item) == 0) { \ 3142 len = snprintf(tmpbuf, 4096, fmt, state.ufs.fs32.__##item); \ 3143 goto gotdata; \ 3144 } 3145 3146 HANDLE_x86_FLOAT_STATE_ITEM(fpu_cs, "%hx\n"); 3147 HANDLE_x86_FLOAT_STATE_ITEM(fpu_dp, "%x\n"); 3148 HANDLE_x86_FLOAT_STATE_ITEM(fpu_ds, "%hx\n"); 3149 HANDLE_x86_FLOAT_STATE_ITEM(fpu_fop, "%hx\n"); 3150 HANDLE_x86_FLOAT_STATE_ITEM(fpu_ftw, "%hhx\n"); 3151 HANDLE_x86_FLOAT_STATE_ITEM(fpu_ip, "%x\n"); 3152 HANDLE_x86_FLOAT_STATE_ITEM(fpu_mxcsr, "%x\n"); 3153 HANDLE_x86_FLOAT_STATE_ITEM(fpu_mxcsrmask, "%x\n"); 3154 3155#define HANDLE_x86_FLOAT_STATE_ITEM_CONTROL_BIT(bit) \ 3156 if (state.ufs.fs32.__fpu_fcw.__##bit) { \ 3157 len += snprintf(tmpbuf + len, 4096 - len, "%s ", #bit); \ 3158 } 3159 3160 if (strcmp(whichfile, "fpu_fcw") == 0) { /* control */ 3161 len = 0; 3162 HANDLE_x86_FLOAT_STATE_ITEM_CONTROL_BIT(invalid); 3163 HANDLE_x86_FLOAT_STATE_ITEM_CONTROL_BIT(denorm); 3164 HANDLE_x86_FLOAT_STATE_ITEM_CONTROL_BIT(zdiv); 3165 HANDLE_x86_FLOAT_STATE_ITEM_CONTROL_BIT(ovrfl); 3166 HANDLE_x86_FLOAT_STATE_ITEM_CONTROL_BIT(undfl); 3167 HANDLE_x86_FLOAT_STATE_ITEM_CONTROL_BIT(precis); 3168 HANDLE_x86_FLOAT_STATE_ITEM_CONTROL_BIT(pc); 3169 switch (state.ufs.fs32.__fpu_fcw.__pc) { 3170 case 0: 3171 len += snprintf(tmpbuf + len, 4096 - len, "(24B) "); 3172 break; 3173 case 2: 3174 len += snprintf(tmpbuf + len, 4096 - len, "(53B) "); 3175 break; 3176 case 3: 3177 len += snprintf(tmpbuf + len, 4096 - len, "(64B) "); 3178 break; 3179 } 3180 HANDLE_x86_FLOAT_STATE_ITEM_CONTROL_BIT(rc); 3181 switch (state.ufs.fs32.__fpu_fcw.__rc) { 3182 case 0: 3183 len += snprintf(tmpbuf + len, 4096 - len, "(round near) "); 3184 break; 3185 case 1: 3186 len += snprintf(tmpbuf + len, 4096 - len, "(round down) "); 3187 break; 3188 case 2: 3189 len += snprintf(tmpbuf + len, 4096 - len, "(round up) "); 3190 break; 3191 case 3: 3192 len += snprintf(tmpbuf + len, 4096 - len, "(chop) "); 3193 break; 3194 } 3195 len += snprintf(tmpbuf + len, 4096 - len, "\n"); 3196 goto gotdata; 3197 } 3198 3199#define HANDLE_x86_FLOAT_STATE_ITEM_STATUS_BIT(bit) \ 3200 if (state.ufs.fs32.__fpu_fsw.__##bit) { \ 3201 len += snprintf(tmpbuf + len, 4096 - len, "%s ", #bit); \ 3202 } 3203 3204 if (strcmp(whichfile, "fpu_fsw") == 0) { /* status */ 3205 len = 0; 3206 HANDLE_x86_FLOAT_STATE_ITEM_STATUS_BIT(invalid); 3207 HANDLE_x86_FLOAT_STATE_ITEM_STATUS_BIT(denorm); 3208 HANDLE_x86_FLOAT_STATE_ITEM_STATUS_BIT(zdiv); 3209 HANDLE_x86_FLOAT_STATE_ITEM_STATUS_BIT(ovrfl); 3210 HANDLE_x86_FLOAT_STATE_ITEM_STATUS_BIT(undfl); 3211 HANDLE_x86_FLOAT_STATE_ITEM_STATUS_BIT(precis); 3212 HANDLE_x86_FLOAT_STATE_ITEM_STATUS_BIT(stkflt); 3213 HANDLE_x86_FLOAT_STATE_ITEM_STATUS_BIT(errsumm); 3214 HANDLE_x86_FLOAT_STATE_ITEM_STATUS_BIT(c0); 3215 HANDLE_x86_FLOAT_STATE_ITEM_STATUS_BIT(c1); 3216 HANDLE_x86_FLOAT_STATE_ITEM_STATUS_BIT(c2); 3217 HANDLE_x86_FLOAT_STATE_ITEM_STATUS_BIT(c3); 3218 HANDLE_x86_FLOAT_STATE_ITEM_STATUS_BIT(busy); 3219 len += snprintf(tmpbuf + len, 4096 - len, "tos=%hhx\n", 3220 state.ufs.fs32.__fpu_fsw.__tos); 3221 goto gotdata; 3222 } 3223 3224#else 3225 len = -1; 3226 goto gotdata; 3227#endif 3228 3229gotdata: 3230 3231 FINI_THREAD_LIST(); 3232 3233 READ_PROC_TASK_EPILOGUE(); 3234} 3235 3236READ_HANDLER(proc__task__threads__thread__states__thread) 3237{ 3238 READ_PROC_TASK_PROLOGUE(); 3239 DECL_THREAD_LIST(); 3240 INIT_THREAD_LIST(the_task); 3241 3242 thread_t the_thread = MACH_PORT_NULL; 3243 unsigned int i = strtoul(argv[1], NULL, 16); 3244 3245 if (i < thread_count) { 3246 the_thread = thread_list[i]; 3247 } 3248 3249 if (the_thread == MACH_PORT_NULL) { 3250 FINI_THREAD_LIST(); 3251 return -ENOENT; 3252 } 3253 3254#if defined(__i386__) 3255 3256 const char *whichfile = argv[2]; 3257 3258 x86_thread_state_t state = { 0 }; 3259 unsigned int count = x86_THREAD_STATE_COUNT; 3260 kr = thread_get_state(the_thread, x86_THREAD_STATE, (thread_state_t)&state, 3261 &count); 3262 if (kr != KERN_SUCCESS) { 3263 FINI_THREAD_LIST(); 3264 return -EIO; 3265 } 3266 3267#define HANDLE_x86_THREAD_STATE_ITEM(item) \ 3268 if (strcmp(whichfile, #item) == 0) { \ 3269 len = snprintf(tmpbuf, 4096, "%x\n", state.uts.ts32.__##item); \ 3270 goto gotdata; \ 3271 } 3272 3273 HANDLE_x86_THREAD_STATE_ITEM(eax); 3274 HANDLE_x86_THREAD_STATE_ITEM(ebx); 3275 HANDLE_x86_THREAD_STATE_ITEM(ecx); 3276 HANDLE_x86_THREAD_STATE_ITEM(edx); 3277 HANDLE_x86_THREAD_STATE_ITEM(edi); 3278 HANDLE_x86_THREAD_STATE_ITEM(esi); 3279 HANDLE_x86_THREAD_STATE_ITEM(ebp); 3280 HANDLE_x86_THREAD_STATE_ITEM(esp); 3281 HANDLE_x86_THREAD_STATE_ITEM(ss); 3282 HANDLE_x86_THREAD_STATE_ITEM(eflags); 3283 HANDLE_x86_THREAD_STATE_ITEM(eip); 3284 HANDLE_x86_THREAD_STATE_ITEM(cs); 3285 HANDLE_x86_THREAD_STATE_ITEM(ds); 3286 HANDLE_x86_THREAD_STATE_ITEM(es); 3287 HANDLE_x86_THREAD_STATE_ITEM(fs); 3288 HANDLE_x86_THREAD_STATE_ITEM(gs); 3289 3290#else 3291 len = -1; 3292 goto gotdata; 3293#endif 3294 3295gotdata: 3296 3297 FINI_THREAD_LIST(); 3298 3299 READ_PROC_TASK_EPILOGUE(); 3300} 3301 3302READ_HANDLER(proc__task__tokens) 3303{ 3304 READ_PROC_TASK_PROLOGUE(); 3305 3306 unsigned int n; 3307 audit_token_t audit_token; 3308 security_token_t security_token; 3309 mach_msg_type_number_t task_info_count; 3310 const char *whichfile = argv[1]; 3311 3312 if (strcmp(whichfile, "audit") == 0) { 3313 task_info_count = TASK_AUDIT_TOKEN_COUNT; 3314 kr = task_info(the_task, TASK_AUDIT_TOKEN, 3315 (task_info_t)&audit_token, &task_info_count); 3316 len = -1; 3317 if (kr == KERN_SUCCESS) { 3318 len = 0; 3319 for (n = 0; n < sizeof(audit_token)/sizeof(uint32_t); n++) { 3320 len += snprintf(tmpbuf + len, 4096 - len, "%x ", 3321 audit_token.val[n]); 3322 } 3323 len += snprintf(tmpbuf + len, 4096 - len, "\n"); 3324 } 3325 goto gotdata; 3326 } 3327 3328 if (strcmp(whichfile, "security") == 0) { 3329 task_info_count = TASK_SECURITY_TOKEN_COUNT; 3330 kr = task_info(the_task, TASK_SECURITY_TOKEN, 3331 (task_info_t)&security_token, &task_info_count); 3332 len = -1; 3333 if (kr == KERN_SUCCESS) { 3334 len = 0; 3335 for (n = 0; n < sizeof(security_token)/sizeof(uint32_t); n++) { 3336 len += snprintf(tmpbuf + len, 4096 - len, "%x ", 3337 security_token.val[n]); 3338 } 3339 len += snprintf(tmpbuf + len, 4096 - len, "\n"); 3340 } 3341 goto gotdata; 3342 } 3343 3344 return -ENOENT; 3345 3346gotdata: 3347 3348 READ_PROC_TASK_EPILOGUE(); 3349} 3350 3351const char * 3352inheritance_strings[] = { 3353 "SHARE", "COPY", "NONE", "DONATE_COPY", 3354}; 3355 3356const char * 3357behavior_strings[] = { 3358 "DEFAULT", "RANDOM", "SEQUENTIAL", "RESQNTL", "WILLNEED", "DONTNEED", 3359}; 3360 3361READ_HANDLER(proc__task__vmmap) 3362{ 3363 int len = -1; 3364 kern_return_t kr; 3365#define MAX_VMMAP_SIZE 65536 /* XXX */ 3366 char tmpbuf[MAX_VMMAP_SIZE]; 3367 task_t the_task; 3368 pid_t pid = strtol(argv[0], NULL, 10); 3369 3370 kr = task_for_pid(mach_task_self(), pid, &the_task); 3371 if (kr != KERN_SUCCESS) { 3372 return -EIO; 3373 } 3374 3375 vm_size_t vmsize; 3376 vm_address_t address; 3377 vm_region_basic_info_data_t info; 3378 mach_msg_type_number_t info_count; 3379 vm_region_flavor_t flavor; 3380 memory_object_name_t object; 3381 3382 kr = KERN_SUCCESS; 3383 address = 0; 3384 len = 0; 3385 3386 do { 3387 flavor = VM_REGION_BASIC_INFO; 3388 info_count = VM_REGION_BASIC_INFO_COUNT; 3389 kr = vm_region(the_task, &address, &vmsize, flavor, 3390 (vm_region_info_t)&info, &info_count, &object); 3391 if (kr == KERN_SUCCESS) { 3392 if (len >= MAX_VMMAP_SIZE) { 3393 goto gotdata; 3394 } 3395 len += snprintf(tmpbuf + len, MAX_VMMAP_SIZE - len, 3396 "%08x-%08x %8uK %c%c%c/%c%c%c %11s %6s %10s uwir=%hu sub=%u\n", 3397 address, (address + vmsize), (vmsize >> 10), 3398 (info.protection & VM_PROT_READ) ? 'r' : '-', 3399 (info.protection & VM_PROT_WRITE) ? 'w' : '-', 3400 (info.protection & VM_PROT_EXECUTE) ? 'x' : '-', 3401 (info.max_protection & VM_PROT_READ) ? 'r' : '-', 3402 (info.max_protection & VM_PROT_WRITE) ? 'w' : '-', 3403 (info.max_protection & VM_PROT_EXECUTE) ? 'x' : '-', 3404 inheritance_strings[info.inheritance], 3405 (info.shared) ? "shared" : "-", 3406 behavior_strings[info.behavior], 3407 info.user_wired_count, 3408 info.reserved); 3409 address += vmsize; 3410 } else if (kr != KERN_INVALID_ADDRESS) { 3411 3412 if (the_task != MACH_PORT_NULL) { 3413 mach_port_deallocate(mach_task_self(), the_task); 3414 } 3415 3416 return -EIO; 3417 } 3418 } while (kr != KERN_INVALID_ADDRESS); 3419 3420gotdata: 3421 3422 if (the_task != MACH_PORT_NULL) { 3423 mach_port_deallocate(mach_task_self(), the_task); 3424 } 3425 3426 READ_PROC_TASK_EPILOGUE(); 3427} 3428 3429static int 3430M_get_vmmap_entries(task_t task) 3431{ 3432 kern_return_t kr = KERN_SUCCESS; 3433 vm_address_t address = 0; 3434 vm_size_t size = 0; 3435 int n = 1; 3436 3437 while (1) { 3438 mach_msg_type_number_t count; 3439 struct vm_region_submap_info_64 info; 3440 uint32_t nesting_depth; 3441 3442 count = VM_REGION_SUBMAP_INFO_COUNT_64; 3443 kr = vm_region_recurse_64(task, &address, &size, &nesting_depth, 3444 (vm_region_info_64_t)&info, &count); 3445 if (kr == KERN_INVALID_ADDRESS) { 3446 break; 3447 } else if (kr) { 3448 mach_error("vm_region:", kr); 3449 break; /* last region done */ 3450 } 3451 3452 if (info.is_submap) { 3453 nesting_depth++; 3454 } else { 3455 address += size; 3456 n++; 3457 } 3458 } 3459 3460 return n; 3461} 3462 3463#define CAST_DOWN(type, addr) (((type)((uintptr_t)(addr)))) 3464 3465static char * 3466get_user_tag_description(unsigned int user_tag) 3467{ 3468 char *description = "unknown"; 3469 3470 switch (user_tag) { 3471 3472 case VM_MEMORY_MALLOC: 3473 description = "MALLOC"; 3474 break; 3475 case VM_MEMORY_MALLOC_SMALL: 3476 description = "MALLOC_SMALL"; 3477 break; 3478 case VM_MEMORY_MALLOC_LARGE: 3479 description = "MALLOC_LARGE"; 3480 break; 3481 case VM_MEMORY_MALLOC_HUGE: 3482 description = "MALLOC_HUGE"; 3483 break; 3484 case VM_MEMORY_SBRK: 3485 description = "SBRK"; 3486 break; 3487 case VM_MEMORY_REALLOC: 3488 description = "REALLOC"; 3489 break; 3490 case VM_MEMORY_MALLOC_TINY: 3491 description = "MALLOC_TINY"; 3492 break; 3493 case VM_MEMORY_ANALYSIS_TOOL: 3494 description = "ANALYSIS_TOOL"; 3495 break; 3496 case VM_MEMORY_MACH_MSG: 3497 description = "MACH_MSG"; 3498 break; 3499 case VM_MEMORY_IOKIT: 3500 description = "IOKIT"; 3501 break; 3502 case VM_MEMORY_STACK: 3503 description = "STACK"; 3504 break; 3505 case VM_MEMORY_GUARD: 3506 description = "MEMORY_GUARD"; 3507 break; 3508 case VM_MEMORY_SHARED_PMAP: 3509 description = "SHARED_PMAP"; 3510 break; 3511 case VM_MEMORY_DYLIB: 3512 description = "DYLIB"; 3513 break; 3514 case VM_MEMORY_APPKIT: 3515 description = "AppKit"; 3516 break; 3517 case VM_MEMORY_FOUNDATION: 3518 description = "Foundation"; 3519 break; 3520 case VM_MEMORY_COREGRAPHICS: 3521 description = "CoreGraphics"; 3522 break; 3523 case VM_MEMORY_CARBON: 3524 description = "Carbon"; 3525 break; 3526 case VM_MEMORY_JAVA: 3527 description = "Java"; 3528 break; 3529 case VM_MEMORY_ATS: 3530 description = "ATS"; 3531 break; 3532 case VM_MEMORY_DYLD: 3533 description = "DYLD"; 3534 break; 3535 case VM_MEMORY_DYLD_MALLOC: 3536 description = "DYLD_MALLOC"; 3537 break; 3538 case VM_MEMORY_APPLICATION_SPECIFIC_1: 3539 description = "APPLICATION_SPECIFIC_1"; 3540 break; 3541 case VM_MEMORY_APPLICATION_SPECIFIC_16: 3542 description = "APPLICATION_SPECIFIC_16"; 3543 break; 3544 default: 3545 break; 3546 } 3547 3548 return description; 3549} 3550 3551READ_HANDLER(proc__task__vmmap_r) 3552{ 3553 int len = -1; 3554 kern_return_t kr; 3555 uint32_t nesting_depth = 0; 3556 struct vm_region_submap_info_64 vbr; 3557 mach_msg_type_number_t vbrcount = 0; 3558#define MAX_VMMAP_R_SIZE 262144 /* XXX */ 3559 char tmpbuf[MAX_VMMAP_R_SIZE]; 3560 task_t the_task; 3561 int segment_count; 3562 pid_t pid = strtol(argv[0], NULL, 10); 3563 3564 kr = task_for_pid(mach_task_self(), pid, &the_task); 3565 if (kr != KERN_SUCCESS) { 3566 return -EIO; 3567 } 3568 3569 mach_vm_size_t vmsize; 3570 mach_vm_address_t address; 3571 3572 kr = KERN_SUCCESS; 3573 address = 0; 3574 len = 0; 3575 3576 segment_count = M_get_vmmap_entries(the_task); 3577 3578 while (segment_count > 0) { 3579 while (1) { /* next region */ 3580 vbrcount = VM_REGION_SUBMAP_INFO_COUNT_64; 3581 if ((kr = mach_vm_region_recurse(the_task, &address, &vmsize, 3582 &nesting_depth, 3583 (vm_region_recurse_info_t)&vbr, 3584 &vbrcount)) != KERN_SUCCESS) { 3585 break; 3586 } 3587 if (address + vmsize > VM_MAX_ADDRESS) { 3588 kr = KERN_INVALID_ADDRESS; 3589 break; 3590 } 3591 if (vbr.is_submap) { 3592 nesting_depth++; 3593 continue; 3594 } else { 3595 break; 3596 } 3597 } /* while (1) */ 3598 3599 if (kr != KERN_SUCCESS) { 3600 if (kr != KERN_INVALID_ADDRESS) { 3601 if (the_task != MACH_PORT_NULL) { 3602 mach_port_deallocate(mach_task_self(), the_task); 3603 } 3604 return -EIO; 3605 } 3606 break; 3607 } 3608 3609 if (len >= MAX_VMMAP_R_SIZE) { 3610 goto gotdata; 3611 } 3612 3613 /* XXX: 32-bit only */ 3614 3615 len += snprintf(tmpbuf + len, MAX_VMMAP_R_SIZE - len, 3616 "%08x-%08x %8uK %c%c%c/%c%c%c ", 3617 CAST_DOWN(uint32_t,address), 3618 CAST_DOWN(uint32_t,(address + vmsize)), 3619 CAST_DOWN(uint32_t,(vmsize >> 10)), 3620 (vbr.protection & VM_PROT_READ) ? 'r' : '-', 3621 (vbr.protection & VM_PROT_WRITE) ? 'w' : '-', 3622 (vbr.protection & VM_PROT_EXECUTE) ? 'x' : '-', 3623 (vbr.max_protection & VM_PROT_READ) ? 'r' : '-', 3624 (vbr.max_protection & VM_PROT_WRITE) ? 'w' : '-', 3625 (vbr.max_protection & VM_PROT_EXECUTE) ? 'x' : '-'); 3626 3627 if (vbr.is_submap) { 3628 len += snprintf(tmpbuf + len, MAX_VMMAP_R_SIZE - len, 3629 "%20s %s\n", "(submap)", 3630 get_user_tag_description(vbr.user_tag)); 3631 } else { 3632 len += snprintf(tmpbuf + len, MAX_VMMAP_R_SIZE - len, 3633 "%6d %6d %6d %s\n", 3634 vbr.pages_resident, 3635 vbr.pages_swapped_out, 3636 vbr.pages_dirtied, 3637 get_user_tag_description(vbr.user_tag)); 3638 } 3639 3640 address += vmsize; 3641 segment_count--; 3642 3643 } /* while (segment_count > 0) */ 3644 3645gotdata: 3646 3647 if (the_task != MACH_PORT_NULL) { 3648 mach_port_deallocate(mach_task_self(), the_task); 3649 } 3650 3651 READ_PROC_TASK_EPILOGUE(); 3652} 3653 3654READ_HANDLER(proc__windows__generic) 3655{ 3656 pid_t pid = atoi(argv[0]); 3657 const char *whichfile = argv[1]; 3658 ProcessSerialNumber psn; 3659 3660 OSStatus status = GetProcessForPID(pid, &psn); 3661 if (status != noErr) { 3662 return 0; /* technically not an error in this case */ 3663 } 3664 3665 CGSConnectionID conn; 3666 CGError err = CGSGetConnectionIDForPSN(0, &psn, &conn); 3667 if (err != kCGErrorSuccess) { 3668 return 0; /* just be nice */ 3669 } 3670 3671#define MAX_WINDOWS 256 3672 CGSWindowID windowIDs[MAX_WINDOWS]; 3673 int windowCount = 0; 3674 3675 if (strcmp(whichfile, "all") == 0) { 3676 err = CGSGetWindowList(_CGSDefaultConnection(), conn, MAX_WINDOWS, 3677 windowIDs, &windowCount); 3678 } else if (strcmp(whichfile, "onscreen") == 0) { 3679 err = CGSGetOnScreenWindowList(_CGSDefaultConnection(), conn, 3680 MAX_WINDOWS, windowIDs, &windowCount); 3681 } 3682 3683 if (err != kCGErrorSuccess) { 3684 return -EIO; 3685 } 3686 3687 if (windowCount == 0) { 3688 return 0; 3689 } 3690 3691#define MAX_WINDOWDATA 16384 3692 char tmpbuf[MAX_WINDOWDATA]; 3693 int i, len = 0; 3694 3695 for (i = 0; i < windowCount; i++) { 3696 3697 if (len > MAX_WINDOWDATA) { 3698 goto gotdata; 3699 } 3700 3701 CGRect rect; 3702 err = CGSGetScreenRectForWindow(_CGSDefaultConnection(), windowIDs[i], 3703 &rect); 3704 CGWindowLevel level; 3705 CGError err2 = CGSGetWindowLevel(_CGSDefaultConnection(), windowIDs[i], 3706 &level); 3707 len += snprintf(tmpbuf + len, MAX_WINDOWDATA - len, 3708 "%-4d %-6x %.0f x %.0f @ (%.0f, %.0f, %d)\n", 3709 i + 1, windowIDs[i], 3710 (err == kCGErrorSuccess) ? rect.size.width : -1, 3711 (err == kCGErrorSuccess) ? rect.size.height : -1, 3712 (err == kCGErrorSuccess) ? rect.origin.x : -1, 3713 (err == kCGErrorSuccess) ? rect.origin.y : -1, 3714 (err2 == kCGErrorSuccess) ? level : -1); 3715 } 3716 3717gotdata: 3718 3719 if (offset < len) { 3720 if (offset + size > len) 3721 size = len - offset; 3722 memcpy(buf, tmpbuf + offset, size); 3723 } else 3724 size = 0; 3725 3726 return size; 3727} 3728 3729READ_HANDLER(proc__windows__screenshots__window) 3730{ 3731 if (fi->fh == 0) { 3732 return 0; 3733 } 3734 3735 struct ProcfsWindowData *pwd = (struct ProcfsWindowData *)fi->fh; 3736 3737 CFMutableDataRef window_png = pwd->window_png; 3738 size_t max_len = pwd->max_len; 3739 size_t len = pwd->len; 3740 3741 if (len > max_len) { 3742 return -EIO; 3743 } 3744 3745 CFDataSetLength(window_png, max_len); 3746 len = max_len; 3747 3748 const UInt8 *tmpbuf = CFDataGetBytePtr(window_png); 3749 3750 if (len < 0) { 3751 return -EIO; 3752 } 3753 3754 if (offset < len) { 3755 if (offset + size > len) 3756 size = len - offset; 3757 memcpy(buf, tmpbuf + offset, size); 3758 } else 3759 size = 0; 3760 3761 return size; 3762} 3763 3764READ_HANDLER(proc__xcred) 3765{ 3766 pid_t pid = atoi(argv[0]); 3767 const char *whichfile = argv[2]; 3768 struct kinfo_proc kp; 3769 int len; 3770 char tmpbuf[4096]; 3771 struct passwd *p; 3772 struct group *g; 3773 3774 len = procinfo(pid, &kp); 3775 if (len != 0) { 3776 return -EIO; 3777 } 3778 3779 len = -1; 3780 3781 if (strcmp(whichfile, "groups") == 0) { 3782 short n; 3783 len = 0; 3784 for (n = 0; n < kp.kp_eproc.e_ucred.cr_ngroups; n++) { 3785 g = getgrgid(kp.kp_eproc.e_ucred.cr_groups[n]); 3786 len += snprintf(tmpbuf + len, 4096 - len, "%d(%s) ", 3787 kp.kp_eproc.e_ucred.cr_groups[n], 3788 (g) ? g->gr_name : "?"); 3789 } 3790 len += snprintf(tmpbuf + len, 4096 - len, "\n"); 3791 goto gotdata; 3792 } 3793 3794 if (strcmp(whichfile, "rgid") == 0) { 3795 g = getgrgid(kp.kp_eproc.e_pcred.p_rgid); 3796 len = snprintf(tmpbuf, 4096, "%d(%s)\n", kp.kp_eproc.e_pcred.p_rgid, 3797 (g) ? g->gr_name : "?"); 3798 goto gotdata; 3799 } 3800 3801 if (strcmp(whichfile, "svgid") == 0) { 3802 g = getgrgid(kp.kp_eproc.e_pcred.p_svgid); 3803 len = snprintf(tmpbuf, 4096, "%d(%s)\n", kp.kp_eproc.e_pcred.p_svgid, 3804 (g) ? g->gr_name : "?"); 3805 goto gotdata; 3806 } 3807 3808 if (strcmp(whichfile, "ruid") == 0) { 3809 p = getpwuid(kp.kp_eproc.e_pcred.p_ruid); 3810 len = snprintf(tmpbuf, 4096, "%d(%s)\n", kp.kp_eproc.e_pcred.p_ruid, 3811 (p) ? p->pw_name : "?"); 3812 goto gotdata; 3813 } 3814 3815 if (strcmp(whichfile, "svuid") == 0) { 3816 p = getpwuid(kp.kp_eproc.e_pcred.p_svuid); 3817 len = snprintf(tmpbuf, 4096, "%d(%s)\n", kp.kp_eproc.e_pcred.p_svuid, 3818 (p) ? p->pw_name : "?"); 3819 goto gotdata; 3820 } 3821 3822 if (strcmp(whichfile, "uid") == 0) { 3823 p = getpwuid(kp.kp_eproc.e_ucred.cr_uid); 3824 len = snprintf(tmpbuf, 4096, "%d(%s)\n", kp.kp_eproc.e_ucred.cr_uid, 3825 (p) ? p->pw_name : "?"); 3826 goto gotdata; 3827 } 3828 3829gotdata: 3830 3831 if (len < 0) { 3832 return -EIO; 3833 } 3834 3835 if (offset < len) { 3836 if (offset + size > len) 3837 size = len - offset; 3838 memcpy(buf, tmpbuf + offset, size); 3839 } else 3840 size = 0; 3841 3842 return size; 3843} 3844 3845// END: READ 3846 3847 3848// BEGIN: READDIR 3849 3850// int 3851// procfs_readdir_<handler>(procfs_dispatcher_entry_t *e, 3852// const char *argv[], 3853// void *buf, 3854// fuse_fill_dir_t filler, 3855// off_t offset, 3856// struct fuse_file_info *fi) 3857 3858 3859int 3860procfs_populate_directory(const char **content_files, 3861 const char **content_directories, 3862 void *buf, 3863 fuse_fill_dir_t filler, 3864 off_t offset, 3865 struct fuse_file_info *fi) 3866{ 3867 int bufferfull = 0; 3868 struct stat dir_stat; 3869 struct stat file_stat; 3870 const char **name; 3871 3872 memset(&dir_stat, 0, sizeof(dir_stat)); 3873 dir_stat.st_mode = S_IFDIR | 0555; 3874 dir_stat.st_size = 0; 3875 3876 memset(&file_stat, 0, sizeof(file_stat)); 3877 dir_stat.st_mode = S_IFREG | 0444; 3878 dir_stat.st_size = 0; 3879 3880 if (filler(buf, ".", NULL, 0)) { 3881 bufferfull = 1; 3882 goto out; 3883 } 3884 3885 if (filler(buf, "..", NULL, 0)) { 3886 bufferfull = 1; 3887 goto out; 3888 } 3889 3890 if (!content_files && !content_directories) { 3891 goto out; 3892 } 3893 3894 name = content_directories; 3895 if (name) { 3896 for (; *name; name++) { 3897 if (filler(buf, *name, &dir_stat, 0)) { 3898 bufferfull = 1; 3899 goto out; 3900 } 3901 } 3902 } 3903 3904 name = content_files; 3905 if (name) { 3906 for (; *name; name++) { 3907 if (filler(buf, *name, &file_stat, 0)) { 3908 bufferfull = 1; 3909 goto out; 3910 } 3911 } 3912 } 3913 3914 if (procfs_ui) { 3915 name = content_files; 3916 if (name) { 3917 for (; *name; name++) { 3918 char dot_name[MAXPATHLEN + 1]; 3919 snprintf(dot_name, MAXPATHLEN, "._%s", *name); 3920 if (filler(buf, dot_name, &file_stat, 0)) { 3921 bufferfull = 1; 3922 goto out; 3923 } 3924 } 3925 } 3926 } 3927 3928out: 3929 return bufferfull; 3930} 3931 3932 3933READDIR_HANDLER(enotdir) 3934{ 3935 return -ENOTDIR; 3936} 3937 3938READDIR_HANDLER(default) 3939{ 3940 return 0; 3941} 3942 3943READDIR_HANDLER(root) 3944{ 3945 unsigned int i; 3946 kern_return_t kr; 3947 char the_name[MAXNAMLEN + 1]; 3948 struct stat dir_stat; 3949 pid_t pid; 3950 DECL_TASK_LIST(); 3951 3952 INIT_TASK_LIST(); 3953 for (i = 0; i < task_count; i++) { 3954 memset(&dir_stat, 0, sizeof(dir_stat)); 3955 dir_stat.st_mode = S_IFDIR | 0755; 3956 dir_stat.st_size = 0; 3957 kr = pid_for_task(task_list[i], &pid); 3958 if (kr != KERN_SUCCESS) { 3959 continue; 3960 } 3961 snprintf(the_name, MAXNAMLEN, "%d", pid); 3962 if (filler(buf, the_name, &dir_stat, 0)) { 3963 break; 3964 } 3965 } 3966 FINI_TASK_LIST(); 3967 3968 return 0; 3969} 3970 3971READDIR_HANDLER(byname) 3972{ 3973 int len; 3974 char the_name[MAXNAMLEN + 1]; 3975 Boolean strstatus = false; 3976 struct stat the_stat; 3977 3978 ProcessSerialNumber psn; 3979 OSErr osErr = noErr; 3980 OSStatus status; 3981 CFStringRef Pname; 3982 pid_t Pid; 3983 3984 psn.highLongOfPSN = kNoProcess; 3985 psn.lowLongOfPSN = kNoProcess; 3986 memset(&the_stat, 0, sizeof(the_stat)); 3987 3988 while ((osErr = GetNextProcess(&psn)) != procNotFound) { 3989 status = GetProcessPID(&psn, &Pid); 3990 if (status != noErr) { 3991 continue; 3992 } 3993 Pname = (CFStringRef)0; 3994 status = CopyProcessName(&psn, &Pname); 3995 if (status != noErr) { 3996 if (Pname) { 3997 CFRelease(Pname); 3998 Pname = (CFStringRef)0; 3999 } 4000 continue; 4001 } 4002 the_stat.st_mode = S_IFLNK | 0755; 4003 the_stat.st_nlink = 1; 4004 len = snprintf(the_name, MAXNAMLEN, "../%u", Pid); 4005 the_stat.st_size = len; 4006 4007 strstatus = CFStringGetCString(Pname, the_name, MAXNAMLEN, 4008 kCFStringEncodingASCII); 4009 if (strstatus == false) { 4010 CFRelease(Pname); 4011 Pname = (CFStringRef)0; 4012 continue; 4013 } 4014 4015 if (filler(buf, the_name, &the_stat, 0)) { 4016 CFRelease(Pname); 4017 break; 4018 } 4019 CFRelease(Pname); 4020 } 4021 4022 return 0; 4023} 4024 4025READDIR_HANDLER(system__hardware__cpus) 4026{ 4027 int len; 4028 unsigned int i; 4029 char the_name[MAXNAMLEN + 1]; 4030 struct stat the_stat; 4031 4032 memset(&the_stat, 0, sizeof(the_stat)); 4033 4034 for (i = 0; i < processor_count; i++) { 4035 the_stat.st_mode = S_IFDIR | 0555; 4036 the_stat.st_nlink = 1; 4037 len = snprintf(the_name, MAXNAMLEN, "%d", i); 4038 if (filler(buf, the_name, &the_stat, 0)) { 4039 break; 4040 } 4041 } 4042 4043 return 0; 4044} 4045 4046READDIR_HANDLER(system__hardware__cpus__cpu) 4047{ 4048 return 0; 4049} 4050 4051READDIR_HANDLER(system__hardware__displays) 4052{ 4053 int len; 4054 unsigned int i; 4055 char the_name[MAXNAMLEN + 1]; 4056 struct stat the_stat; 4057 CGDisplayCount display_count = PROCFS_GetDisplayCount(); 4058 4059 memset(&the_stat, 0, sizeof(the_stat)); 4060 4061 for (i = 0; i < display_count; i++) { 4062 the_stat.st_mode = S_IFDIR | 0555; 4063 the_stat.st_nlink = 1; 4064 len = snprintf(the_name, MAXNAMLEN, "%d", i); 4065 if (filler(buf, the_name, &the_stat, 0)) { 4066 break; 4067 } 4068 } 4069 4070 return 0; 4071 4072} 4073 4074READDIR_HANDLER(system__hardware__displays__display) 4075{ 4076 unsigned long index = strtol(argv[0], NULL, 10); 4077 CGDisplayCount display_count = PROCFS_GetDisplayCount(); 4078 4079 if (index >= display_count) { 4080 return -ENOENT; 4081 } 4082 4083 return 0; 4084} 4085 4086READDIR_HANDLER(system__hardware__tpm__keyslots) 4087{ 4088#if MACFUSE_PROCFS_ENABLE_TPM 4089 unsigned int i, len; 4090 char the_name[MAXNAMLEN + 1]; 4091 struct stat the_stat; 4092 uint32_t keys[256]; 4093 4094 uint16_t slots_used = 0; 4095 uint32_t slots_free = 0; 4096 uint32_t slots_total = 0; 4097 4098 if (TPM_GetCapability_Slots(&slots_free)) { 4099 return -ENOENT; 4100 } 4101 4102 if (TPM_GetCapability_Key_Handle(&slots_used, keys)) { 4103 return -ENOENT; 4104 } 4105 4106 slots_total = slots_used + slots_free; 4107 4108 memset(&the_stat, 0, sizeof(the_stat)); 4109 4110 for (i = 0; i < slots_total; i++) { 4111 len = snprintf(the_name, MAXNAMLEN, "key%02d", i); 4112 if (i >= slots_used) { 4113 the_stat.st_size = 0; 4114 the_stat.st_mode = S_IFREG | 0000; 4115 } else { 4116 the_stat.st_size = 4096; 4117 the_stat.st_mode = S_IFREG | 0444; 4118 } 4119 if (filler(buf, the_name, &the_stat, 0)) { 4120 break; 4121 } 4122 } 4123#endif 4124 4125 return 0; 4126} 4127 4128READDIR_HANDLER(system__hardware__tpm__pcrs) 4129{ 4130#if MACFUSE_PROCFS_ENABLE_TPM 4131 unsigned int i, len; 4132 uint32_t pcrs; 4133 char the_name[MAXNAMLEN + 1]; 4134 struct stat the_stat; 4135 4136 if (TPM_GetCapability_Pcrs(&pcrs)) { 4137 return -ENOENT; 4138 } 4139 4140 memset(&the_stat, 0, sizeof(the_stat)); 4141 4142 for (i = 0; i < pcrs; i++) { 4143 len = snprintf(the_name, MAXNAMLEN, "pcr%02d", i); 4144 the_stat.st_size = 4096; 4145 the_stat.st_mode = S_IFREG | 0444; 4146 if (filler(buf, the_name, &the_stat, 0)) { 4147 break; 4148 } 4149 } 4150#endif 4151 4152 return 0; 4153} 4154 4155READDIR_HANDLER(proc__task__ports) 4156{ 4157 unsigned int i; 4158 kern_return_t kr; 4159 DECL_PORT_LIST(); 4160 pid_t pid = strtol(argv[0], NULL, 10); 4161 struct stat dir_stat; 4162 char the_name[MAXNAMLEN + 1]; 4163 task_t the_task = MACH_PORT_NULL; 4164 4165 kr = task_for_pid(mach_task_self(), pid, &the_task); 4166 if (kr != KERN_SUCCESS) { 4167 return -ENOENT; 4168 } 4169 4170 memset(&dir_stat, 0, sizeof(dir_stat)); 4171 dir_stat.st_mode = S_IFDIR | 0755; 4172 dir_stat.st_size = 0; 4173 4174 INIT_PORT_LIST(the_task); 4175 for (i = 0; i < name_count; i++) { 4176 snprintf(the_name, MAXNAMLEN, "%x", name_list[i]); 4177 if (filler(buf, the_name, &dir_stat, 0)) { 4178 break; 4179 } 4180 } 4181 FINI_PORT_LIST(); 4182 4183 if (the_task != MACH_PORT_NULL) { 4184 mach_port_deallocate(mach_task_self(), the_task); 4185 } 4186 4187 return 0; 4188} 4189 4190READDIR_HANDLER(proc__task__threads) 4191{ 4192 unsigned int i; 4193 kern_return_t kr; 4194 DECL_THREAD_LIST(); 4195 pid_t pid = strtol(argv[0], NULL, 10); 4196 struct stat dir_stat; 4197 char the_name[MAXNAMLEN + 1]; 4198 task_t the_task = MACH_PORT_NULL; 4199 4200 kr = task_for_pid(mach_task_self(), pid, &the_task); 4201 if (kr != KERN_SUCCESS) { 4202 return -ENOENT; 4203 } 4204 4205 memset(&dir_stat, 0, sizeof(dir_stat)); 4206 dir_stat.st_mode = S_IFDIR | 0755; 4207 dir_stat.st_size = 0; 4208 4209 INIT_THREAD_LIST(the_task); 4210 FINI_THREAD_LIST(); 4211 4212 for (i = 0; i < thread_count; i++) { 4213 snprintf(the_name, MAXNAMLEN, "%x", i); 4214 if (filler(buf, the_name, &dir_stat, 0)) { 4215 break; 4216 } 4217 } 4218 4219 if (the_task != MACH_PORT_NULL) { 4220 mach_port_deallocate(mach_task_self(), the_task); 4221 } 4222 4223 return 0; 4224} 4225 4226READDIR_HANDLER(proc__windows__screenshots) 4227{ 4228 int i; 4229 pid_t pid = strtol(argv[0], NULL, 10); 4230 struct stat dir_stat; 4231 char the_name[MAXNAMLEN + 1]; 4232 4233 ProcessSerialNumber psn; 4234 4235 OSStatus status = GetProcessForPID(pid, &psn); 4236 if (status != noErr) { 4237 return 0; /* technically not an error in this case */ 4238 } 4239 4240 memset(&dir_stat, 0, sizeof(dir_stat)); 4241 dir_stat.st_mode = S_IFDIR | 0755; 4242 dir_stat.st_size = 0; 4243 4244 CGSConnectionID conn; 4245 CGError err = CGSGetConnectionIDForPSN(0, &psn, &conn); 4246 if (err != kCGErrorSuccess) { 4247 return 0; /* just be nice */ 4248 } 4249 4250#define MAX_WINDOWS 256 4251 CGSWindowID windowIDs[MAX_WINDOWS]; 4252 int windowCount = 0; 4253 4254 err = CGSGetOnScreenWindowList(_CGSDefaultConnection(), conn, 4255 MAX_WINDOWS, windowIDs, &windowCount); 4256 4257 if (err != kCGErrorSuccess) { 4258 return -EIO; 4259 } 4260 4261 if (windowCount == 0) { 4262 return 0; 4263 } 4264 4265 for (i = 0; i < windowCount; i++) { 4266 snprintf(the_name, MAXNAMLEN, "%x.png", windowIDs[i]); 4267 dir_stat.st_mode = S_IFREG | 0444; 4268 dir_stat.st_size = PROCFS_GetPNGSizeForWindowAtIndex(windowIDs[i]); 4269 if (filler(buf, the_name, &dir_stat, 0)) { 4270 break; 4271 } 4272 } 4273 4274 return 0; 4275} 4276 4277// END: READDIR 4278 4279 4280// BEGIN: READLINK 4281 4282// int 4283// procfs_readlink_<handler>(procfs_dispatcher_entry_t e, 4284// const char *argv[], 4285// char *buf, 4286// size_t size) 4287 4288READLINK_HANDLER(einval) 4289{ 4290 return -EINVAL; 4291} 4292 4293READLINK_HANDLER(byname__name) 4294{ 4295 const char *target_Pname = argv[0]; 4296 char the_name[MAXNAMLEN + 1]; 4297 Boolean strstatus = false; 4298 4299 ProcessSerialNumber psn; 4300 OSErr osErr = noErr; 4301 OSStatus status; 4302 CFStringRef Pname; 4303 pid_t Pid; 4304 4305 psn.highLongOfPSN = kNoProcess; 4306 psn.lowLongOfPSN = kNoProcess; 4307 4308 while ((osErr = GetNextProcess(&psn)) != procNotFound) { 4309 status = GetProcessPID(&psn, &Pid); 4310 if (status != noErr) { 4311 continue; 4312 } 4313 Pname = (CFStringRef)0; 4314 status = CopyProcessName(&psn, &Pname); 4315 if (status != noErr) { 4316 if (Pname) { 4317 CFRelease(Pname); 4318 Pname = (CFStringRef)0; 4319 } 4320 continue; 4321 } 4322 4323 strstatus = CFStringGetCString(Pname, the_name, MAXNAMLEN, 4324 kCFStringEncodingASCII); 4325 4326 if (strcmp(target_Pname, the_name) != 0) { 4327 Pid = 0; 4328 } 4329 4330 CFRelease(Pname); 4331 Pname = (CFStringRef)0; 4332 4333 if (Pid) { 4334 break; 4335 } 4336 } 4337 4338 if (!Pid) { 4339 return -ENOENT; 4340 } 4341 4342 (void)snprintf(the_name, MAXNAMLEN, "../%u", Pid); 4343 4344 strncpy(buf, the_name, size - 1); 4345 4346 return 0; 4347} 4348 4349// END: READLINK 4350 4351 4352#define DEBUG 1 4353#ifdef DEBUG 4354#define TRACEME() { fprintf(stderr, "%s: path=%s\n", __FUNCTION__, path); } 4355#else 4356#define TRACEME() { } 4357#endif 4358 4359#define EXIT_ON_MACH_ERROR(msg, retval) \ 4360 if (kr != KERN_SUCCESS) { mach_error(msg ":" , kr); exit((retval)); } 4361 4362static void * 4363procfs_init(struct fuse_conn_info *conn) 4364{ 4365 int i; 4366 kern_return_t kr; 4367 4368 kr = processor_set_default(mach_host_self(), &p_default_set); 4369 EXIT_ON_MACH_ERROR("processor_default", 1); 4370 4371 kr = host_processor_set_priv(mach_host_self(), p_default_set, 4372 &p_default_set_control); 4373 EXIT_ON_MACH_ERROR("host_processor_set_priv", 1); 4374 4375 kr = host_get_host_priv_port(mach_host_self(), &host_priv); 4376 EXIT_ON_MACH_ERROR("host_get_host_priv_port", 1); 4377 4378 processor_list = (processor_port_array_t)0; 4379 kr = host_processors(host_priv, &processor_list, &processor_count); 4380 EXIT_ON_MACH_ERROR("host_processors", 1); 4381 4382 io_service_t serviceObject; 4383 4384 serviceObject = IOServiceGetMatchingService(kIOMasterPortDefault, 4385 IOServiceMatching("AppleLMUController")); 4386 if (serviceObject) { 4387 kr = IOServiceOpen(serviceObject, mach_task_self(), 0, 4388 &lightsensor_port); 4389 IOObjectRelease(serviceObject); 4390 if (kr != KERN_SUCCESS) { 4391 lightsensor_port = 0; 4392 } 4393 } 4394 4395 kr = KERN_FAILURE; 4396 CFDictionaryRef classToMatch; 4397 MotionSensorData_t sms_data; 4398 4399 for (i = 0; i <= sms_maxConfigurationID; i++) { 4400 4401 sms_gIndex = SMS_CONFIGURATIONS[i].index; 4402 classToMatch = IOServiceMatching(SMS_CONFIGURATIONS[i].classname); 4403 sms_gStructureInputSize = SMS_CONFIGURATIONS[i].structureInputSize; 4404 sms_gStructureOutputSize = SMS_CONFIGURATIONS[i].structureOutputSize; 4405 sms_configurationID = i; 4406 4407 serviceObject = IOServiceGetMatchingService(kIOMasterPortDefault, 4408 classToMatch); 4409 if (!serviceObject) { 4410 continue; 4411 } 4412 4413 kr = IOServiceOpen(serviceObject, mach_task_self(), 0, 4414 &motionsensor_port); 4415 IOObjectRelease(serviceObject); 4416 if (kr != KERN_SUCCESS) { 4417 continue; 4418 } 4419 4420 kr = sms_getOrientation_hardware_apple(&sms_data); 4421 if (kr != KERN_SUCCESS) { 4422 IOServiceClose(motionsensor_port); 4423 motionsensor_port = 0; 4424 continue; 4425 } else { 4426 break; 4427 } 4428 } 4429 4430 total_file_patterns = 4431 sizeof(procfs_file_table)/sizeof(struct procfs_dispatcher_entry); 4432 total_directory_patterns = 4433 sizeof(procfs_directory_table)/sizeof(struct procfs_dispatcher_entry); 4434 total_link_patterns = 4435 sizeof(procfs_link_table)/sizeof(struct procfs_dispatcher_entry); 4436 4437 pthread_mutex_init(&camera_lock, NULL); 4438 pthread_mutex_init(&display_lock, NULL); 4439 4440 camera_tiff = CFDataCreateMutable(kCFAllocatorDefault, (CFIndex)0); 4441 4442 return NULL; 4443} 4444 4445static void 4446procfs_destroy(void *arg) 4447{ 4448 (void)mach_port_deallocate(mach_task_self(), p_default_set); 4449 (void)mach_port_deallocate(mach_task_self(), p_default_set_control); 4450 4451 pthread_mutex_destroy(&camera_lock); 4452 pthread_mutex_destroy(&display_lock); 4453 4454 CFRelease(camera_tiff); 4455} 4456 4457#define PROCFS_OPEN_RELEASE_COMMON() \ 4458 int i; \ 4459 procfs_dispatcher_entry_t e; \ 4460 string arg1, arg2, arg3; \ 4461 const char *real_argv[PROCFS_MAX_ARGS]; \ 4462 \ 4463 if (valid_process_pattern->PartialMatch(path, &arg1)) { \ 4464 pid_t check_pid = atoi(arg1.c_str()); \ 4465 if (getpgid(check_pid) == -1) { \ 4466 return -ENOENT; \ 4467 } \ 4468 } \ 4469 \ 4470 for (i = 0; i < PROCFS_MAX_ARGS; i++) { \ 4471 real_argv[i] = (char *)0; \ 4472 } \ 4473 \ 4474 for (i = 0; i < total_file_patterns; i++) { \ 4475 e = &procfs_file_table[i]; \ 4476 if ((e->flag & PROCFS_FLAG_ISDOTFILE) & !procfs_ui) { \ 4477 continue; \ 4478 } \ 4479 switch (e->argc) { \ 4480 case 0: \ 4481 if (e->compiled_pattern->FullMatch(path)) { \ 4482 goto out; \ 4483 } \ 4484 break; \ 4485 \ 4486 case 1: \ 4487 if (e->compiled_pattern->FullMatch(path, &arg1)) { \ 4488 real_argv[0] = arg1.c_str(); \ 4489 goto out; \ 4490 } \ 4491 break; \ 4492 \ 4493 case 2: \ 4494 if (e->compiled_pattern->FullMatch(path, &arg1, &arg2)) { \ 4495 real_argv[0] = arg1.c_str(); \ 4496 real_argv[1] = arg2.c_str(); \ 4497 goto out; \ 4498 } \ 4499 break; \ 4500 \ 4501 case 3: \ 4502 if (e->compiled_pattern->FullMatch(path, &arg1, &arg2, &arg3)) { \ 4503 real_argv[0] = arg1.c_str(); \ 4504 real_argv[1] = arg2.c_str(); \ 4505 real_argv[2] = arg3.c_str(); \ 4506 goto out; \ 4507 } \ 4508 break; \ 4509 \ 4510 default: \ 4511 break; \ 4512 } \ 4513 } \ 4514 \ 4515 for (i = 0; i < total_link_patterns; i++) { \ 4516 e = &procfs_link_table[i]; \ 4517 switch (e->argc) { \ 4518 case 0: \ 4519 if (e->compiled_pattern->FullMatch(path)) { \ 4520 goto out; \ 4521 } \ 4522 break; \ 4523 \ 4524 case 1: \ 4525 if (e->compiled_pattern->FullMatch(path, &arg1)) { \ 4526 real_argv[0] = arg1.c_str(); \ 4527 goto out; \ 4528 } \ 4529 break; \ 4530 \ 4531 case 2: \ 4532 if (e->compiled_pattern->FullMatch(path, &arg1, &arg2)) { \ 4533 real_argv[0] = arg1.c_str(); \ 4534 real_argv[1] = arg2.c_str(); \ 4535 goto out; \ 4536 } \ 4537 break; \ 4538 \ 4539 case 3: \ 4540 if (e->compiled_pattern->FullMatch(path, &arg1, &arg2, &arg3)) { \ 4541 real_argv[0] = arg1.c_str(); \ 4542 real_argv[1] = arg2.c_str(); \ 4543 real_argv[2] = arg3.c_str(); \ 4544 goto out; \ 4545 } \ 4546 break; \ 4547 \ 4548 default: \ 4549 break; \ 4550 } \ 4551 } \ 4552 \ 4553 return -ENOENT; \ 4554 \ 4555out: \ 4556 4557static int 4558procfs_open(const char *path, struct fuse_file_info *fi) 4559{ 4560 PROCFS_OPEN_RELEASE_COMMON() 4561 4562 return e->open(e, real_argv, path, fi); 4563} 4564 4565static int 4566procfs_release(const char *path, struct fuse_file_info *fi) 4567{ 4568 PROCFS_OPEN_RELEASE_COMMON() 4569 4570 return e->release(e, real_argv, path, fi); 4571} 4572 4573static int 4574procfs_opendir(const char *path, struct fuse_file_info *fi) 4575{ 4576 return 0; 4577} 4578 4579static int 4580procfs_releasedir(const char *path, struct fuse_file_info *fi) 4581{ 4582 return 0; 4583} 4584 4585static int 4586procfs_getattr(const char *path, struct stat *stbuf) 4587{ 4588 int i; 4589 procfs_dispatcher_entry_t e; 4590 string arg1, arg2, arg3; 4591 const char *real_argv[PROCFS_MAX_ARGS]; 4592 4593 if (valid_process_pattern->PartialMatch(path, &arg1)) { 4594 pid_t check_pid = atoi(arg1.c_str()); 4595 if (getpgid(check_pid) == -1) { 4596 return -ENOENT; 4597 } 4598 } 4599 4600 for (i = 0; i < PROCFS_MAX_ARGS; i++) { 4601 real_argv[i] = (char *)0; 4602 } 4603 4604 for (i = 0; i < total_directory_patterns; i++) { 4605 e = &procfs_directory_table[i]; 4606 switch (e->argc) { 4607 case 0: 4608 if (e->compiled_pattern->FullMatch(path)) { 4609 goto out; 4610 } 4611 break; 4612 4613 case 1: 4614 if (e->compiled_pattern->FullMatch(path, &arg1)) { 4615 real_argv[0] = arg1.c_str(); 4616 goto out; 4617 } 4618 break; 4619 4620 case 2: 4621 if (e->compiled_pattern->FullMatch(path, &arg1, &arg2)) { 4622 real_argv[0] = arg1.c_str(); 4623 real_argv[1] = arg2.c_str(); 4624 goto out; 4625 } 4626 break; 4627 4628 case 3: 4629 if (e->compiled_pattern->FullMatch(path, &arg1, &arg2, &arg3)) { 4630 real_argv[0] = arg1.c_str(); 4631 real_argv[1] = arg2.c_str(); 4632 real_argv[2] = arg3.c_str(); 4633 goto out; 4634 } 4635 break; 4636 4637 default: 4638 break; 4639 } 4640 } 4641 4642 for (i = 0; i < total_file_patterns; i++) { 4643 e = &procfs_file_table[i]; 4644 if ((e->flag & PROCFS_FLAG_ISDOTFILE) & !procfs_ui) { 4645 continue; 4646 } 4647 switch (e->argc) { 4648 case 0: 4649 if (e->compiled_pattern->FullMatch(path)) { 4650 goto out; 4651 } 4652 break; 4653 4654 case 1: 4655 if (e->compiled_pattern->FullMatch(path, &arg1)) { 4656 real_argv[0] = arg1.c_str(); 4657 goto out; 4658 } 4659 break; 4660 4661 case 2: 4662 if (e->compiled_pattern->FullMatch(path, &arg1, &arg2)) { 4663 real_argv[0] = arg1.c_str(); 4664 real_argv[1] = arg2.c_str(); 4665 goto out; 4666 } 4667 break; 4668 4669 case 3: 4670 if (e->compiled_pattern->FullMatch(path, &arg1, &arg2, &arg3)) { 4671 real_argv[0] = arg1.c_str(); 4672 real_argv[1] = arg2.c_str(); 4673 real_argv[2] = arg3.c_str(); 4674 goto out; 4675 } 4676 break; 4677 4678 default: 4679 break; 4680 } 4681 } 4682 4683 for (i = 0; i < total_link_patterns; i++) { 4684 e = &procfs_link_table[i]; 4685 if ((e->flag & PROCFS_FLAG_ISDOTFILE) & !procfs_ui) { 4686 continue; 4687 } 4688 switch (e->argc) { 4689 case 0: 4690 if (e->compiled_pattern->FullMatch(path)) { 4691 goto out; 4692 } 4693 break; 4694 4695 case 1: 4696 if (e->compiled_pattern->FullMatch(path, &arg1)) { 4697 real_argv[0] = arg1.c_str(); 4698 goto out; 4699 } 4700 break; 4701 4702 case 2: 4703 if (e->compiled_pattern->FullMatch(path, &arg1, &arg2)) { 4704 real_argv[0] = arg1.c_str(); 4705 real_argv[1] = arg2.c_str(); 4706 goto out; 4707 } 4708 break; 4709 4710 case 3: 4711 if (e->compiled_pattern->FullMatch(path, &arg1, &arg2, &arg3)) { 4712 real_argv[0] = arg1.c_str(); 4713 real_argv[1] = arg2.c_str(); 4714 real_argv[2] = arg3.c_str(); 4715 goto out; 4716 } 4717 break; 4718 4719 default: 4720 break; 4721 } 4722 } 4723 4724 return -ENOENT; 4725 4726out: 4727 return e->getattr(e, real_argv, stbuf); 4728} 4729 4730 4731static int 4732procfs_readdir(const char *path, 4733 void *buf, 4734 fuse_fill_dir_t filler, 4735 off_t offset, 4736 struct fuse_file_info *fi) 4737{ 4738 int i; 4739 procfs_dispatcher_entry_t e; 4740 string arg1, arg2, arg3; 4741 const char *real_argv[PROCFS_MAX_ARGS]; 4742 4743 if (valid_process_pattern->PartialMatch(path, &arg1)) { 4744 pid_t check_pid = atoi(arg1.c_str()); 4745 if (getpgid(check_pid) == -1) { 4746 return -ENOENT; 4747 } 4748 } 4749 4750 for (i = 0; i < PROCFS_MAX_ARGS; i++) { 4751 real_argv[i] = (char *)0; 4752 } 4753 4754 for (i = 0; i < total_directory_patterns; i++) { 4755 4756 e = &procfs_directory_table[i]; 4757 4758 switch (e->argc) { 4759 case 0: 4760 if (e->compiled_pattern->FullMatch(path)) { 4761 goto out; 4762 } 4763 break; 4764 4765 case 1: 4766 if (e->compiled_pattern->FullMatch(path, &arg1)) { 4767 real_argv[0] = arg1.c_str(); 4768 goto out; 4769 } 4770 break; 4771 4772 case 2: 4773 if (e->compiled_pattern->FullMatch(path, &arg1, &arg2)) { 4774 real_argv[0] = arg1.c_str(); 4775 real_argv[1] = arg2.c_str(); 4776 goto out; 4777 } 4778 break; 4779 4780 case 3: 4781 if (e->compiled_pattern->FullMatch(path, &arg1, &arg2, &arg3)) { 4782 real_argv[0] = arg1.c_str(); 4783 real_argv[1] = arg2.c_str(); 4784 real_argv[2] = arg3.c_str(); 4785 goto out; 4786 } 4787 break; 4788 4789 default: 4790 return -ENOENT; 4791 } 4792 } 4793 4794 return -ENOENT; 4795 4796out: 4797 (void)e->readdir(e, real_argv, buf, filler, offset, fi); 4798 4799 (void)procfs_populate_directory(e->content_files, e->content_directories, 4800 buf, filler, offset, fi); 4801 4802 return 0; 4803} 4804 4805static int 4806procfs_readlink(const char *path, char *buf, size_t size) 4807{ 4808 int i; 4809 procfs_dispatcher_entry_t e; 4810 string arg1, arg2, arg3; 4811 const char *real_argv[PROCFS_MAX_ARGS]; 4812 4813 for (i = 0; i < PROCFS_MAX_ARGS; i++) { 4814 real_argv[i] = (char *)0; 4815 } 4816 4817 for (i = 0; i < total_link_patterns; i++) { 4818 4819 e = &procfs_link_table[i]; 4820 4821 if ((e->flag & PROCFS_FLAG_ISDOTFILE) & !procfs_ui) { 4822 continue; 4823 } 4824 4825 switch (e->argc) { 4826 case 0: 4827 if (e->compiled_pattern->FullMatch(path)) { 4828 goto out; 4829 } 4830 break; 4831 case 1: 4832 if (e->compiled_pattern->FullMatch(path, &arg1)) { 4833 real_argv[0] = arg1.c_str(); 4834 goto out; 4835 } 4836 break; 4837 case 2: 4838 if (e->compiled_pattern->FullMatch(path, &arg1, &arg2)) { 4839 real_argv[0] = arg1.c_str(); 4840 real_argv[1] = arg2.c_str(); 4841 goto out; 4842 } 4843 break; 4844 } 4845 } 4846 4847 return -ENOENT; 4848 4849out: 4850 return e->readlink(e, real_argv, buf, size); 4851} 4852 4853static int 4854procfs_read(const char *path, char *buf, size_t size, off_t offset, 4855 struct fuse_file_info *fi) 4856{ 4857 int i; 4858 procfs_dispatcher_entry_t e; 4859 string arg1, arg2, arg3; 4860 const char *real_argv[PROCFS_MAX_ARGS]; 4861 4862 for (i = 0; i < PROCFS_MAX_ARGS; i++) { 4863 real_argv[i] = (char *)0; 4864 } 4865 4866 for (i = 0; i < total_file_patterns; i++) { 4867 4868 e = &procfs_file_table[i]; 4869 4870 if ((e->flag & PROCFS_FLAG_ISDOTFILE) & !procfs_ui) { 4871 continue; 4872 } 4873 4874 switch (e->argc) { 4875 case 0: 4876 if (e->compiled_pattern->FullMatch(path)) { 4877 goto out; 4878 } 4879 break; 4880 4881 case 1: 4882 if (e->compiled_pattern->FullMatch(path, &arg1)) { 4883 real_argv[0] = arg1.c_str(); 4884 goto out; 4885 } 4886 break; 4887 4888 case 2: 4889 if (e->compiled_pattern->FullMatch(path, &arg1, &arg2)) { 4890 real_argv[0] = arg1.c_str(); 4891 real_argv[1] = arg2.c_str(); 4892 goto out; 4893 } 4894 break; 4895 4896 case 3: 4897 if (e->compiled_pattern->FullMatch(path, &arg1, &arg2, &arg3)) { 4898 real_argv[0] = arg1.c_str(); 4899 real_argv[1] = arg2.c_str(); 4900 real_argv[2] = arg3.c_str(); 4901 goto out; 4902 } 4903 break; 4904 4905 default: 4906 return -EIO; 4907 } 4908 } 4909 4910 return -EIO; 4911 4912out: 4913 return e->read(e, real_argv, buf, size, offset, fi); 4914} 4915 4916static int 4917procfs_statfs(const char *path, struct statvfs *buf) 4918{ 4919 (void)path; 4920 4921 buf->f_namemax = 255; 4922 buf->f_bsize = 1048576; 4923 buf->f_frsize = 1048576; 4924 buf->f_blocks = buf->f_bfree = buf->f_bavail = 4925 1000ULL * 1024 * 1024 * 1024 / buf->f_frsize; 4926 buf->f_files = buf->f_ffree = 1000000000; 4927 return 0; 4928} 4929 4930static struct fuse_operations procfs_oper; 4931 4932static void 4933procfs_oper_populate(struct fuse_operations *oper) 4934{ 4935 oper->init = procfs_init; 4936 oper->destroy = procfs_destroy; 4937 oper->statfs = procfs_statfs; 4938 oper->open = procfs_open; 4939 oper->release = procfs_release; 4940 oper->opendir = procfs_opendir; 4941 oper->releasedir = procfs_releasedir; 4942 oper->getattr = procfs_getattr; 4943 oper->read = procfs_read; 4944 oper->readdir = procfs_readdir; 4945 oper->readlink = procfs_readlink; 4946} 4947 4948static char *def_opts = "-oallow_other,direct_io,nobrowse,nolocalcaches,ro,iosize=1048576,volname=ProcFS"; 4949static char *def_opts_ui = "-oallow_other,local,nolocalcaches,ro,iosize=1048576,volname=ProcFS"; 4950 4951int 4952main(int argc, char *argv[]) 4953{ 4954 int i; 4955 char **new_argv; 4956 char *extra_opts = def_opts; 4957 4958 if (getenv("MACFUSE_PROCFS_UI")) { 4959 procfs_ui = 1; 4960 extra_opts = def_opts_ui; 4961 } 4962 4963 argc++; 4964 new_argv = (char **)malloc(sizeof(char *) * argc); 4965 if (!new_argv) 4966 return -1; 4967 for (i = 0; i < (argc - 1); i++) { 4968 new_argv[i] = argv[i]; 4969 } 4970 argv[i] = extra_opts; 4971 4972 procfs_oper_populate(&procfs_oper); 4973 4974 return fuse_main(argc, argv, &procfs_oper, NULL); 4975}