PageRenderTime 68ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/filesystems/procfs/procfs.cc

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