PageRenderTime 50ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/minix/usr.bin/trace/service/vfs.c

http://www.minix3.org/
C | 2452 lines | 1902 code | 409 blank | 141 comment | 330 complexity | 592e7f8e585ec551d870d4d35dab7ab5 MD5 | raw file
Possible License(s): MIT, WTFPL, AGPL-1.0, BSD-3-Clause, GPL-3.0, LGPL-2.0, JSON, 0BSD

Large files files are truncated, but you can click here to view the full file

  1. #include "inc.h"
  2. #include <fcntl.h>
  3. #include <unistd.h>
  4. #include <dirent.h>
  5. #include <sys/mount.h>
  6. #include <sys/resource.h>
  7. #include <sys/socket.h>
  8. #include <sys/un.h>
  9. #include <netinet/in.h>
  10. #if 0 /* not yet, header is missing */
  11. #include <netbt/bluetooth.h>
  12. #endif
  13. #include <arpa/inet.h>
  14. /*
  15. * This function should always be used when printing a file descriptor. It
  16. * currently offers no benefit, but will in the future allow for features such
  17. * as color highlighting and tracking of specific open files (TODO).
  18. */
  19. void
  20. put_fd(struct trace_proc * proc, const char * name, int fd)
  21. {
  22. put_value(proc, name, "%d", fd);
  23. }
  24. static int
  25. vfs_read_out(struct trace_proc * proc, const message * m_out)
  26. {
  27. put_fd(proc, "fd", m_out->m_lc_vfs_readwrite.fd);
  28. return CT_NOTDONE;
  29. }
  30. static void
  31. vfs_read_in(struct trace_proc * proc, const message * m_out,
  32. const message * m_in, int failed)
  33. {
  34. put_buf(proc, "buf", failed, m_out->m_lc_vfs_readwrite.buf,
  35. m_in->m_type);
  36. put_value(proc, "len", "%zu", m_out->m_lc_vfs_readwrite.len);
  37. put_equals(proc);
  38. put_result(proc);
  39. }
  40. static int
  41. vfs_write_out(struct trace_proc * proc, const message * m_out)
  42. {
  43. put_fd(proc, "fd", m_out->m_lc_vfs_readwrite.fd);
  44. put_buf(proc, "buf", 0, m_out->m_lc_vfs_readwrite.buf,
  45. m_out->m_lc_vfs_readwrite.len);
  46. put_value(proc, "len", "%zu", m_out->m_lc_vfs_readwrite.len);
  47. return CT_DONE;
  48. }
  49. static void
  50. put_lseek_whence(struct trace_proc * proc, const char * name, int whence)
  51. {
  52. const char *text = NULL;
  53. if (!valuesonly) {
  54. switch (whence) {
  55. TEXT(SEEK_SET);
  56. TEXT(SEEK_CUR);
  57. TEXT(SEEK_END);
  58. }
  59. }
  60. if (text != NULL)
  61. put_field(proc, name, text);
  62. else
  63. put_value(proc, name, "%d", whence);
  64. }
  65. static int
  66. vfs_lseek_out(struct trace_proc * proc, const message * m_out)
  67. {
  68. put_fd(proc, "fd", m_out->m_lc_vfs_lseek.fd);
  69. put_value(proc, "offset", "%"PRId64, m_out->m_lc_vfs_lseek.offset);
  70. put_lseek_whence(proc, "whence", m_out->m_lc_vfs_lseek.whence);
  71. return CT_DONE;
  72. }
  73. static void
  74. vfs_lseek_in(struct trace_proc * proc, const message * __unused m_out,
  75. const message * m_in, int failed)
  76. {
  77. if (!failed)
  78. put_value(proc, NULL, "%"PRId64, m_in->m_vfs_lc_lseek.offset);
  79. else
  80. put_result(proc);
  81. }
  82. static const struct flags open_flags[] = {
  83. FLAG_MASK(O_ACCMODE, O_RDONLY),
  84. FLAG_MASK(O_ACCMODE, O_WRONLY),
  85. FLAG_MASK(O_ACCMODE, O_RDWR),
  86. #define ACCMODE_ENTRIES 3 /* the first N entries are for O_ACCMODE */
  87. FLAG(O_NONBLOCK),
  88. FLAG(O_APPEND),
  89. FLAG(O_SHLOCK),
  90. FLAG(O_EXLOCK),
  91. FLAG(O_ASYNC),
  92. FLAG(O_SYNC),
  93. FLAG(O_NOFOLLOW),
  94. FLAG(O_CREAT),
  95. FLAG(O_TRUNC),
  96. FLAG(O_EXCL),
  97. FLAG(O_NOCTTY),
  98. FLAG(O_DSYNC),
  99. FLAG(O_RSYNC),
  100. FLAG(O_ALT_IO),
  101. FLAG(O_DIRECT),
  102. FLAG(O_DIRECTORY),
  103. FLAG(O_CLOEXEC),
  104. FLAG(O_SEARCH),
  105. FLAG(O_NOSIGPIPE),
  106. };
  107. static void
  108. put_open_flags(struct trace_proc * proc, const char * name, int value,
  109. int full)
  110. {
  111. const struct flags *fp;
  112. unsigned int num;
  113. fp = open_flags;
  114. num = COUNT(open_flags);
  115. /*
  116. * If we're not printing a full open()-style set of flags, but instead
  117. * just a loose set of flags, then skip the access mode altogether,
  118. * otherwise we'd be printing O_RDONLY when no access mode is given.
  119. */
  120. if (!full) {
  121. fp += ACCMODE_ENTRIES;
  122. num -= ACCMODE_ENTRIES;
  123. }
  124. put_flags(proc, name, fp, num, "0x%x", value);
  125. }
  126. static const struct flags mode_flags[] = {
  127. FLAG_MASK(S_IFMT, S_IFIFO),
  128. FLAG_MASK(S_IFMT, S_IFCHR),
  129. FLAG_MASK(S_IFMT, S_IFDIR),
  130. FLAG_MASK(S_IFMT, S_IFBLK),
  131. FLAG_MASK(S_IFMT, S_IFREG),
  132. FLAG_MASK(S_IFMT, S_IFLNK),
  133. FLAG_MASK(S_IFMT, S_IFSOCK),
  134. FLAG_MASK(S_IFMT, S_IFWHT),
  135. FLAG(S_ARCH1),
  136. FLAG(S_ARCH2),
  137. FLAG(S_ISUID),
  138. FLAG(S_ISGID),
  139. FLAG(S_ISTXT),
  140. };
  141. /* Do not use %04o instead of 0%03o; it is octal even if greater than 0777. */
  142. #define put_mode(p, n, v) \
  143. put_flags(p, n, mode_flags, COUNT(mode_flags), "0%03o", v)
  144. static void
  145. put_path(struct trace_proc * proc, const message * m_out)
  146. {
  147. size_t len;
  148. if ((len = m_out->m_lc_vfs_path.len) <= M_PATH_STRING_MAX)
  149. put_buf(proc, "path", PF_LOCADDR | PF_PATH,
  150. (vir_bytes)m_out->m_lc_vfs_path.buf, len);
  151. else
  152. put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_path.name, len);
  153. }
  154. static int
  155. vfs_open_out(struct trace_proc * proc, const message * m_out)
  156. {
  157. put_path(proc, m_out);
  158. put_open_flags(proc, "flags", m_out->m_lc_vfs_path.flags,
  159. TRUE /*full*/);
  160. return CT_DONE;
  161. }
  162. /* This function is shared between creat and open. */
  163. static void
  164. vfs_open_in(struct trace_proc * proc, const message * __unused m_out,
  165. const message * m_in, int failed)
  166. {
  167. if (!failed)
  168. put_fd(proc, NULL, m_in->m_type);
  169. else
  170. put_result(proc);
  171. }
  172. static int
  173. vfs_creat_out(struct trace_proc * proc, const message * m_out)
  174. {
  175. put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_creat.name,
  176. m_out->m_lc_vfs_creat.len);
  177. put_open_flags(proc, "flags", m_out->m_lc_vfs_creat.flags,
  178. TRUE /*full*/);
  179. put_mode(proc, "mode", m_out->m_lc_vfs_creat.mode);
  180. return CT_DONE;
  181. }
  182. static int
  183. vfs_close_out(struct trace_proc * proc, const message * m_out)
  184. {
  185. put_fd(proc, "fd", m_out->m_lc_vfs_close.fd);
  186. return CT_DONE;
  187. }
  188. /* This function is used for link, rename, and symlink. */
  189. static int
  190. vfs_link_out(struct trace_proc * proc, const message * m_out)
  191. {
  192. put_buf(proc, "path1", PF_PATH, m_out->m_lc_vfs_link.name1,
  193. m_out->m_lc_vfs_link.len1);
  194. put_buf(proc, "path2", PF_PATH, m_out->m_lc_vfs_link.name2,
  195. m_out->m_lc_vfs_link.len2);
  196. return CT_DONE;
  197. }
  198. static int
  199. vfs_path_out(struct trace_proc * proc, const message * m_out)
  200. {
  201. put_path(proc, m_out);
  202. return CT_DONE;
  203. }
  204. static int
  205. vfs_path_mode_out(struct trace_proc * proc, const message * m_out)
  206. {
  207. put_path(proc, m_out);
  208. put_mode(proc, "mode", m_out->m_lc_vfs_path.mode);
  209. return CT_DONE;
  210. }
  211. void
  212. put_dev(struct trace_proc * proc, const char * name, dev_t dev)
  213. {
  214. devmajor_t major;
  215. devminor_t minor;
  216. major = major(dev);
  217. minor = minor(dev);
  218. /* The value 0 ("no device") should print as "0". */
  219. if (dev != 0 && makedev(major, minor) == dev && !valuesonly)
  220. put_value(proc, name, "<%d,%d>", major, minor);
  221. else
  222. put_value(proc, name, "%"PRIu64, dev);
  223. }
  224. static int
  225. vfs_mknod_out(struct trace_proc * proc, const message * m_out)
  226. {
  227. put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_mknod.name,
  228. m_out->m_lc_vfs_mknod.len);
  229. put_mode(proc, "mode", m_out->m_lc_vfs_mknod.mode);
  230. put_dev(proc, "dev", m_out->m_lc_vfs_mknod.device);
  231. return CT_DONE;
  232. }
  233. static int
  234. vfs_chown_out(struct trace_proc * proc, const message * m_out)
  235. {
  236. put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_chown.name,
  237. m_out->m_lc_vfs_chown.len);
  238. /* -1 means "keep the current value" so print as signed */
  239. put_value(proc, "owner", "%d", m_out->m_lc_vfs_chown.owner);
  240. put_value(proc, "group", "%d", m_out->m_lc_vfs_chown.group);
  241. return CT_DONE;
  242. }
  243. /* TODO: expand this to the full ST_ set. */
  244. static const struct flags mount_flags[] = {
  245. FLAG(MNT_RDONLY),
  246. };
  247. static int
  248. vfs_mount_out(struct trace_proc * proc, const message * m_out)
  249. {
  250. put_buf(proc, "special", PF_PATH, m_out->m_lc_vfs_mount.dev,
  251. m_out->m_lc_vfs_mount.devlen);
  252. put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_mount.path,
  253. m_out->m_lc_vfs_mount.pathlen);
  254. put_flags(proc, "flags", mount_flags, COUNT(mount_flags), "0x%x",
  255. m_out->m_lc_vfs_mount.flags);
  256. put_buf(proc, "type", PF_STRING, m_out->m_lc_vfs_mount.type,
  257. m_out->m_lc_vfs_mount.typelen);
  258. put_buf(proc, "label", PF_STRING, m_out->m_lc_vfs_mount.label,
  259. m_out->m_lc_vfs_mount.labellen);
  260. return CT_DONE;
  261. }
  262. static int
  263. vfs_umount_out(struct trace_proc * proc, const message * m_out)
  264. {
  265. put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_umount.name,
  266. m_out->m_lc_vfs_umount.namelen);
  267. return CT_DONE;
  268. }
  269. static void
  270. vfs_umount_in(struct trace_proc * proc, const message * m_out,
  271. const message * __unused m_in, int failed)
  272. {
  273. put_result(proc);
  274. if (!failed) {
  275. put_open(proc, NULL, 0, "(", ", ");
  276. put_buf(proc, "label", PF_STRING, m_out->m_lc_vfs_umount.label,
  277. m_out->m_lc_vfs_umount.labellen);
  278. put_close(proc, ")");
  279. }
  280. }
  281. static const struct flags access_flags[] = {
  282. FLAG_ZERO(F_OK),
  283. FLAG(R_OK),
  284. FLAG(W_OK),
  285. FLAG(X_OK),
  286. };
  287. static int
  288. vfs_access_out(struct trace_proc * proc, const message * m_out)
  289. {
  290. put_path(proc, m_out);
  291. put_flags(proc, "mode", access_flags, COUNT(access_flags), "0x%x",
  292. m_out->m_lc_vfs_path.mode);
  293. return CT_DONE;
  294. }
  295. static int
  296. vfs_readlink_out(struct trace_proc * proc, const message * m_out)
  297. {
  298. put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_readlink.name,
  299. m_out->m_lc_vfs_readlink.namelen);
  300. return CT_NOTDONE;
  301. }
  302. static void
  303. vfs_readlink_in(struct trace_proc * proc, const message * m_out,
  304. const message * m_in, int failed)
  305. {
  306. /* The call does not return a string, so do not use PF_STRING here. */
  307. put_buf(proc, "buf", failed, m_out->m_lc_vfs_readlink.buf,
  308. m_in->m_type);
  309. put_value(proc, "bufsize", "%zd", m_out->m_lc_vfs_readlink.bufsize);
  310. put_equals(proc);
  311. put_result(proc);
  312. }
  313. static void
  314. put_struct_stat(struct trace_proc * proc, const char * name, int flags,
  315. vir_bytes addr)
  316. {
  317. struct stat buf;
  318. int is_special;
  319. if (!put_open_struct(proc, name, flags, addr, &buf, sizeof(buf)))
  320. return;
  321. /*
  322. * The combination of struct stat's frequent usage and large number of
  323. * fields makes this structure a pain to print. For now, the idea is
  324. * that for verbosity level 0, we print the mode, and the target device
  325. * for block/char special files or the file size for all other files.
  326. * For higher verbosity levels, largely maintain the structure's own
  327. * order of fields. Violate this general structure printing rule for
  328. * some fields though, because the actual field order in struct stat is
  329. * downright ridiculous. Like elsewhere, for verbosity level 1 print
  330. * all fields with meaningful values, and for verbosity level 2 just
  331. * print everything, including fields that are known to be not yet
  332. * supported and fields that contain known values.
  333. */
  334. is_special = (S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode));
  335. if (verbose > 0) {
  336. put_dev(proc, "st_dev", buf.st_dev);
  337. put_value(proc, "st_ino", "%"PRId64, buf.st_ino);
  338. }
  339. put_mode(proc, "st_mode", buf.st_mode);
  340. if (verbose > 0) {
  341. put_value(proc, "st_nlink", "%u", buf.st_nlink);
  342. put_value(proc, "st_uid", "%u", buf.st_uid);
  343. put_value(proc, "st_gid", "%u", buf.st_gid);
  344. }
  345. if (is_special || verbose > 1)
  346. put_dev(proc, "st_rdev", buf.st_rdev);
  347. if (verbose > 0) {
  348. /*
  349. * TODO: print the nanosecond part, but possibly only if we are
  350. * not actually interpreting the time as a date (another TODO),
  351. * and/or possibly only with verbose > 1 (largely unsupported).
  352. */
  353. put_time(proc, "st_atime", buf.st_atime);
  354. put_time(proc, "st_mtime", buf.st_mtime);
  355. put_time(proc, "st_ctime", buf.st_ctime);
  356. }
  357. if (verbose > 1) /* not yet supported on MINIX3 */
  358. put_time(proc, "st_birthtime", buf.st_birthtime);
  359. if (!is_special || verbose > 1)
  360. put_value(proc, "st_size", "%"PRId64, buf.st_size);
  361. if (verbose > 0) {
  362. put_value(proc, "st_blocks", "%"PRId64, buf.st_blocks);
  363. put_value(proc, "st_blksize", "%"PRId32, buf.st_blksize);
  364. }
  365. if (verbose > 1) {
  366. put_value(proc, "st_flags", "%"PRIu32, buf.st_flags);
  367. put_value(proc, "st_gen", "%"PRIu32, buf.st_gen);
  368. }
  369. put_close_struct(proc, verbose > 1);
  370. }
  371. static int
  372. vfs_stat_out(struct trace_proc * proc, const message * m_out)
  373. {
  374. put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_stat.name,
  375. m_out->m_lc_vfs_stat.len);
  376. return CT_NOTDONE;
  377. }
  378. static void
  379. vfs_stat_in(struct trace_proc * proc, const message * m_out,
  380. const message * __unused m_in, int failed)
  381. {
  382. put_struct_stat(proc, "buf", failed, m_out->m_lc_vfs_stat.buf);
  383. put_equals(proc);
  384. put_result(proc);
  385. }
  386. static int
  387. vfs_fstat_out(struct trace_proc * proc, const message * m_out)
  388. {
  389. put_fd(proc, "fd", m_out->m_lc_vfs_fstat.fd);
  390. return CT_NOTDONE;
  391. }
  392. static void
  393. vfs_fstat_in(struct trace_proc * proc, const message * m_out,
  394. const message * __unused m_in, int failed)
  395. {
  396. put_struct_stat(proc, "buf", failed, m_out->m_lc_vfs_fstat.buf);
  397. put_equals(proc);
  398. put_result(proc);
  399. }
  400. static int
  401. vfs_ioctl_out(struct trace_proc * proc, const message * m_out)
  402. {
  403. put_fd(proc, "fd", m_out->m_lc_vfs_ioctl.fd);
  404. put_ioctl_req(proc, "req", m_out->m_lc_vfs_ioctl.req,
  405. FALSE /*is_svrctl*/);
  406. return put_ioctl_arg_out(proc, "arg", m_out->m_lc_vfs_ioctl.req,
  407. (vir_bytes)m_out->m_lc_vfs_ioctl.arg, FALSE /*is_svrctl*/);
  408. }
  409. static void
  410. vfs_ioctl_in(struct trace_proc * proc, const message * m_out,
  411. const message * __unused m_in, int failed)
  412. {
  413. put_ioctl_arg_in(proc, "arg", failed, m_out->m_lc_vfs_ioctl.req,
  414. (vir_bytes)m_out->m_lc_vfs_ioctl.arg, FALSE /*is_svrctl*/);
  415. }
  416. static void
  417. put_fcntl_cmd(struct trace_proc * proc, const char * name, int cmd)
  418. {
  419. const char *text = NULL;
  420. if (!valuesonly) {
  421. switch (cmd) {
  422. TEXT(F_DUPFD);
  423. TEXT(F_GETFD);
  424. TEXT(F_SETFD);
  425. TEXT(F_GETFL);
  426. TEXT(F_SETFL);
  427. TEXT(F_GETOWN);
  428. TEXT(F_SETOWN);
  429. TEXT(F_GETLK);
  430. TEXT(F_SETLK);
  431. TEXT(F_SETLKW);
  432. TEXT(F_CLOSEM);
  433. TEXT(F_MAXFD);
  434. TEXT(F_DUPFD_CLOEXEC);
  435. TEXT(F_GETNOSIGPIPE);
  436. TEXT(F_SETNOSIGPIPE);
  437. TEXT(F_FREESP);
  438. TEXT(F_FLUSH_FS_CACHE);
  439. }
  440. }
  441. if (text != NULL)
  442. put_field(proc, name, text);
  443. else
  444. put_value(proc, name, "%d", cmd);
  445. }
  446. static const struct flags fd_flags[] = {
  447. FLAG(FD_CLOEXEC),
  448. };
  449. #define put_fd_flags(p, n, v) \
  450. put_flags(p, n, fd_flags, COUNT(fd_flags), "0x%x", v)
  451. static void
  452. put_flock_type(struct trace_proc * proc, const char * name, int type)
  453. {
  454. const char *text = NULL;
  455. if (!valuesonly) {
  456. switch (type) {
  457. TEXT(F_RDLCK);
  458. TEXT(F_UNLCK);
  459. TEXT(F_WRLCK);
  460. }
  461. }
  462. if (text != NULL)
  463. put_field(proc, name, text);
  464. else
  465. put_value(proc, name, "%d", type);
  466. }
  467. /*
  468. * With PF_FULL, also print l_pid, unless l_type is F_UNLCK in which case
  469. * only that type is printed. With PF_ALT, print only l_whence/l_start/l_len.
  470. */
  471. static void
  472. put_struct_flock(struct trace_proc * proc, const char * name, int flags,
  473. vir_bytes addr)
  474. {
  475. struct flock flock;
  476. int limited;
  477. if (!put_open_struct(proc, name, flags, addr, &flock, sizeof(flock)))
  478. return;
  479. limited = ((flags & PF_FULL) && flock.l_type == F_UNLCK);
  480. if (!(flags & PF_ALT))
  481. put_flock_type(proc, "l_type", flock.l_type);
  482. if (!limited) {
  483. put_lseek_whence(proc, "l_whence", flock.l_whence);
  484. put_value(proc, "l_start", "%"PRId64, flock.l_start);
  485. put_value(proc, "l_len", "%"PRId64, flock.l_len);
  486. if (flags & PF_FULL)
  487. put_value(proc, "l_pid", "%d", flock.l_pid);
  488. }
  489. put_close_struct(proc, TRUE /*all*/);
  490. }
  491. static int
  492. vfs_fcntl_out(struct trace_proc * proc, const message * m_out)
  493. {
  494. put_fd(proc, "fd", m_out->m_lc_vfs_fcntl.fd);
  495. put_fcntl_cmd(proc, "cmd", m_out->m_lc_vfs_fcntl.cmd);
  496. switch (m_out->m_lc_vfs_fcntl.cmd) {
  497. case F_DUPFD:
  498. case F_DUPFD_CLOEXEC:
  499. put_fd(proc, "fd2", m_out->m_lc_vfs_fcntl.arg_int);
  500. break;
  501. case F_SETFD:
  502. put_fd_flags(proc, "flags", m_out->m_lc_vfs_fcntl.arg_int);
  503. break;
  504. case F_SETFL:
  505. /*
  506. * One of those difficult cases: the access mode is ignored, so
  507. * we don't want to print O_RDONLY if it is not given. On the
  508. * other hand, fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_..) is
  509. * a fairly common construction, in which case we don't want to
  510. * print eg O_..|0x2 if the access mode is O_RDWR. Thus, we
  511. * compromise: show the access mode if any of its bits are set.
  512. */
  513. put_open_flags(proc, "flags", m_out->m_lc_vfs_fcntl.arg_int,
  514. m_out->m_lc_vfs_fcntl.arg_int & O_ACCMODE /*full*/);
  515. break;
  516. case F_SETLK:
  517. case F_SETLKW:
  518. put_struct_flock(proc, "lkp", 0,
  519. m_out->m_lc_vfs_fcntl.arg_ptr);
  520. break;
  521. case F_FREESP:
  522. put_struct_flock(proc, "lkp", PF_ALT,
  523. m_out->m_lc_vfs_fcntl.arg_ptr);
  524. break;
  525. case F_SETNOSIGPIPE:
  526. put_value(proc, "arg", "%d", m_out->m_lc_vfs_fcntl.arg_int);
  527. break;
  528. }
  529. return (m_out->m_lc_vfs_fcntl.cmd != F_GETLK) ? CT_DONE : CT_NOTDONE;
  530. }
  531. static void
  532. vfs_fcntl_in(struct trace_proc * proc, const message * m_out,
  533. const message * m_in, int failed)
  534. {
  535. switch (m_out->m_lc_vfs_fcntl.cmd) {
  536. case F_GETFD:
  537. if (failed)
  538. break;
  539. put_fd_flags(proc, NULL, m_in->m_type);
  540. return;
  541. case F_GETFL:
  542. if (failed)
  543. break;
  544. put_open_flags(proc, NULL, m_in->m_type, TRUE /*full*/);
  545. return;
  546. case F_GETLK:
  547. put_struct_flock(proc, "lkp", failed | PF_FULL,
  548. m_out->m_lc_vfs_fcntl.arg_ptr);
  549. put_equals(proc);
  550. break;
  551. }
  552. put_result(proc);
  553. }
  554. static int
  555. vfs_pipe2_out(struct trace_proc * __unused proc,
  556. const message * __unused m_out)
  557. {
  558. return CT_NOTDONE;
  559. }
  560. static void
  561. vfs_pipe2_in(struct trace_proc * proc, const message * m_out,
  562. const message * m_in, int failed)
  563. {
  564. if (!failed) {
  565. put_open(proc, "fd", PF_NONAME, "[", ", ");
  566. put_fd(proc, "rfd", m_in->m_vfs_lc_fdpair.fd0);
  567. put_fd(proc, "wfd", m_in->m_vfs_lc_fdpair.fd1);
  568. put_close(proc, "]");
  569. } else
  570. put_field(proc, "fd", "&..");
  571. put_open_flags(proc, "flags", m_out->m_lc_vfs_pipe2.flags,
  572. FALSE /*full*/);
  573. put_equals(proc);
  574. put_result(proc);
  575. }
  576. static int
  577. vfs_umask_out(struct trace_proc * proc, const message * m_out)
  578. {
  579. put_mode(proc, NULL, m_out->m_lc_vfs_umask.mask);
  580. return CT_DONE;
  581. }
  582. static void
  583. vfs_umask_in(struct trace_proc * proc, const message * __unused m_out,
  584. const message * m_in, int failed)
  585. {
  586. if (!failed)
  587. put_mode(proc, NULL, m_in->m_type);
  588. else
  589. put_result(proc);
  590. }
  591. static void
  592. put_dirent_type(struct trace_proc * proc, const char * name, unsigned int type)
  593. {
  594. const char *text = NULL;
  595. if (!valuesonly) {
  596. switch (type) {
  597. TEXT(DT_UNKNOWN);
  598. TEXT(DT_FIFO);
  599. TEXT(DT_CHR);
  600. TEXT(DT_DIR);
  601. TEXT(DT_BLK);
  602. TEXT(DT_REG);
  603. TEXT(DT_LNK);
  604. TEXT(DT_SOCK);
  605. TEXT(DT_WHT);
  606. }
  607. }
  608. if (text != NULL)
  609. put_field(proc, name, text);
  610. else
  611. put_value(proc, name, "%u", type);
  612. }
  613. static void
  614. put_struct_dirent(struct trace_proc * proc, const char *name, int flags,
  615. vir_bytes addr)
  616. {
  617. struct dirent dirent;
  618. if (!put_open_struct(proc, name, flags, addr, &dirent, sizeof(dirent)))
  619. return;
  620. if (verbose > 0)
  621. put_value(proc, "d_fileno", "%"PRIu64, dirent.d_fileno);
  622. if (verbose > 1) {
  623. put_value(proc, "d_reclen", "%u", dirent.d_reclen);
  624. put_value(proc, "d_namlen", "%u", dirent.d_namlen);
  625. }
  626. if (verbose >= 1 + (dirent.d_type == DT_UNKNOWN))
  627. put_dirent_type(proc, "d_type", dirent.d_type);
  628. put_buf(proc, "d_name", PF_LOCADDR, (vir_bytes)dirent.d_name,
  629. MIN(dirent.d_namlen, sizeof(dirent.d_name)));
  630. put_close_struct(proc, verbose > 1);
  631. }
  632. static void
  633. put_dirent_array(struct trace_proc * proc, const char * name, int flags,
  634. vir_bytes addr, ssize_t size)
  635. {
  636. struct dirent dirent;
  637. unsigned count, max;
  638. ssize_t off, chunk;
  639. if ((flags & PF_FAILED) || valuesonly > 1 || size < 0) {
  640. put_ptr(proc, name, addr);
  641. return;
  642. }
  643. if (size == 0) {
  644. put_field(proc, name, "[]");
  645. return;
  646. }
  647. if (verbose == 0)
  648. max = 0; /* TODO: should we set this to 1 instead? */
  649. else if (verbose == 1)
  650. max = 3; /* low; just to give an indication where we are */
  651. else
  652. max = INT_MAX;
  653. /*
  654. * TODO: as is, this is highly inefficient, as we are typically copying
  655. * in the same pieces of memory in repeatedly..
  656. */
  657. count = 0;
  658. for (off = 0; off < size; off += chunk) {
  659. chunk = size - off;
  660. if ((size_t)chunk > sizeof(dirent))
  661. chunk = (ssize_t)sizeof(dirent);
  662. if ((size_t)chunk < _DIRENT_MINSIZE(&dirent))
  663. break;
  664. if (mem_get_data(proc->pid, addr + off, &dirent, chunk) < 0) {
  665. if (off == 0) {
  666. put_ptr(proc, name, addr);
  667. return;
  668. }
  669. break;
  670. }
  671. if (off == 0)
  672. put_open(proc, name, PF_NONAME, "[", ", ");
  673. if (count < max)
  674. put_struct_dirent(proc, NULL, PF_LOCADDR,
  675. (vir_bytes)&dirent);
  676. if (chunk > dirent.d_reclen)
  677. chunk = dirent.d_reclen;
  678. count++;
  679. }
  680. if (off < size)
  681. put_tail(proc, 0, 0);
  682. else if (count > max)
  683. put_tail(proc, count, max);
  684. put_close(proc, "]");
  685. }
  686. static int
  687. vfs_getdents_out(struct trace_proc * proc, const message * m_out)
  688. {
  689. put_fd(proc, "fd", m_out->m_lc_vfs_readwrite.fd);
  690. return CT_NOTDONE;
  691. }
  692. static void
  693. vfs_getdents_in(struct trace_proc * proc, const message * m_out,
  694. const message * m_in, int failed)
  695. {
  696. put_dirent_array(proc, "buf", failed, m_out->m_lc_vfs_readwrite.buf,
  697. m_in->m_type);
  698. put_value(proc, "len", "%zu", m_out->m_lc_vfs_readwrite.len);
  699. put_equals(proc);
  700. put_result(proc);
  701. }
  702. static void
  703. put_fd_set(struct trace_proc * proc, const char * name, vir_bytes addr,
  704. int nfds)
  705. {
  706. fd_set set;
  707. size_t off;
  708. unsigned int i, j, words, count, max;
  709. if (addr == 0 || nfds < 0) {
  710. put_ptr(proc, name, addr);
  711. return;
  712. }
  713. /*
  714. * Each process may define its own FD_SETSIZE, so our fd_set may be of
  715. * a different size than theirs. Thus, we copy at a granularity known
  716. * to be valid in any case: a single word of bits. We make the
  717. * assumption that fd_set consists purely of bits, so that we can use
  718. * the second (and so on) bit word as an fd_set by itself.
  719. */
  720. words = (nfds + NFDBITS - 1) / NFDBITS;
  721. count = 0;
  722. if (verbose == 0)
  723. max = 16;
  724. else if (verbose == 1)
  725. max = FD_SETSIZE;
  726. else
  727. max = INT_MAX;
  728. /* TODO: copy in more at once, but stick to fd_mask boundaries. */
  729. for (off = 0, i = 0; i < words; i++, off += sizeof(fd_mask)) {
  730. if (mem_get_data(proc->pid, addr + off, &set,
  731. sizeof(fd_mask)) != 0) {
  732. if (count == 0) {
  733. put_ptr(proc, name, addr);
  734. return;
  735. }
  736. break;
  737. }
  738. for (j = 0; j < NFDBITS; j++) {
  739. if (FD_ISSET(j, &set)) {
  740. if (count == 0)
  741. put_open(proc, name, PF_NONAME, "[",
  742. " ");
  743. if (count < max)
  744. put_fd(proc, NULL, i * NFDBITS + j);
  745. count++;
  746. }
  747. }
  748. }
  749. /*
  750. * The empty set should print as "[]". If copying any part failed, it
  751. * should print as "[x, ..(?)]" where x is the set printed so far, if
  752. * any. If copying never failed, and we did not print all fds in the
  753. * set, print the remaining count n as "[x, ..(+n)]" at the end.
  754. */
  755. if (count == 0)
  756. put_open(proc, name, PF_NONAME, "[", " ");
  757. if (i < words)
  758. put_tail(proc, 0, 0);
  759. else if (count > max)
  760. put_tail(proc, count, max);
  761. put_close(proc, "]");
  762. }
  763. static int
  764. vfs_select_out(struct trace_proc * proc, const message * m_out)
  765. {
  766. int nfds;
  767. nfds = m_out->m_lc_vfs_select.nfds;
  768. put_fd(proc, "nfds", nfds); /* not really a file descriptor.. */
  769. put_fd_set(proc, "readfds",
  770. (vir_bytes)m_out->m_lc_vfs_select.readfds, nfds);
  771. put_fd_set(proc, "writefds",
  772. (vir_bytes)m_out->m_lc_vfs_select.writefds, nfds);
  773. put_fd_set(proc, "errorfds",
  774. (vir_bytes)m_out->m_lc_vfs_select.errorfds, nfds);
  775. put_struct_timeval(proc, "timeout", 0, m_out->m_lc_vfs_select.timeout);
  776. return CT_DONE;
  777. }
  778. static void
  779. vfs_select_in(struct trace_proc * proc, const message * m_out,
  780. const message * __unused m_in, int failed)
  781. {
  782. vir_bytes readfds, writefds, errorfds;
  783. int nfds;
  784. put_result(proc);
  785. if (failed)
  786. return;
  787. nfds = m_out->m_lc_vfs_select.nfds;
  788. readfds = (vir_bytes)m_out->m_lc_vfs_select.readfds;
  789. writefds = (vir_bytes)m_out->m_lc_vfs_select.writefds;
  790. errorfds = (vir_bytes)m_out->m_lc_vfs_select.errorfds;
  791. if (readfds == 0 && writefds == 0 && errorfds == 0)
  792. return;
  793. /* Omit names, because it looks weird. */
  794. put_open(proc, NULL, PF_NONAME, "(", ", ");
  795. if (readfds != 0)
  796. put_fd_set(proc, "readfds", readfds, nfds);
  797. if (writefds != 0)
  798. put_fd_set(proc, "writefds", writefds, nfds);
  799. if (errorfds != 0)
  800. put_fd_set(proc, "errorfds", errorfds, nfds);
  801. put_close(proc, ")");
  802. }
  803. static int
  804. vfs_fchdir_out(struct trace_proc * proc, const message * m_out)
  805. {
  806. put_fd(proc, "fd", m_out->m_lc_vfs_fchdir.fd);
  807. return CT_DONE;
  808. }
  809. static int
  810. vfs_fsync_out(struct trace_proc * proc, const message * m_out)
  811. {
  812. put_fd(proc, "fd", m_out->m_lc_vfs_fsync.fd);
  813. return CT_DONE;
  814. }
  815. static int
  816. vfs_truncate_out(struct trace_proc * proc, const message * m_out)
  817. {
  818. put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_truncate.name,
  819. m_out->m_lc_vfs_truncate.len);
  820. put_value(proc, "length", "%"PRId64, m_out->m_lc_vfs_truncate.offset);
  821. return CT_DONE;
  822. }
  823. static int
  824. vfs_ftruncate_out(struct trace_proc * proc, const message * m_out)
  825. {
  826. put_fd(proc, "fd", m_out->m_lc_vfs_truncate.fd);
  827. put_value(proc, "length", "%"PRId64, m_out->m_lc_vfs_truncate.offset);
  828. return CT_DONE;
  829. }
  830. static int
  831. vfs_fchmod_out(struct trace_proc * proc, const message * m_out)
  832. {
  833. put_fd(proc, "fd", m_out->m_lc_vfs_fchmod.fd);
  834. put_mode(proc, "mode", m_out->m_lc_vfs_fchmod.mode);
  835. return CT_DONE;
  836. }
  837. static int
  838. vfs_fchown_out(struct trace_proc * proc, const message * m_out)
  839. {
  840. put_fd(proc, "fd", m_out->m_lc_vfs_chown.fd);
  841. /* -1 means "keep the current value" so print as signed */
  842. put_value(proc, "owner", "%d", m_out->m_lc_vfs_chown.owner);
  843. put_value(proc, "group", "%d", m_out->m_lc_vfs_chown.group);
  844. return CT_DONE;
  845. }
  846. static const char *
  847. vfs_utimens_name(const message * m_out)
  848. {
  849. int has_path, has_flags;
  850. has_path = (m_out->m_vfs_utimens.name != NULL);
  851. has_flags = (m_out->m_vfs_utimens.flags != 0);
  852. if (has_path && m_out->m_vfs_utimens.flags == AT_SYMLINK_NOFOLLOW)
  853. return "lutimens";
  854. if (has_path && !has_flags)
  855. return "utimens";
  856. else if (!has_path && !has_flags)
  857. return "futimens";
  858. else
  859. return "utimensat";
  860. }
  861. static const struct flags at_flags[] = {
  862. FLAG(AT_EACCESS),
  863. FLAG(AT_SYMLINK_NOFOLLOW),
  864. FLAG(AT_SYMLINK_FOLLOW),
  865. FLAG(AT_REMOVEDIR),
  866. };
  867. static void
  868. put_utimens_timespec(struct trace_proc * proc, const char * name,
  869. time_t sec, long nsec)
  870. {
  871. /* No field names. */
  872. put_open(proc, name, PF_NONAME, "{", ", ");
  873. put_time(proc, "tv_sec", sec);
  874. if (!valuesonly && nsec == UTIME_NOW)
  875. put_field(proc, "tv_nsec", "UTIME_NOW");
  876. else if (!valuesonly && nsec == UTIME_OMIT)
  877. put_field(proc, "tv_nsec", "UTIME_OMIT");
  878. else
  879. put_value(proc, "tv_nsec", "%ld", nsec);
  880. put_close(proc, "}");
  881. }
  882. static int
  883. vfs_utimens_out(struct trace_proc * proc, const message * m_out)
  884. {
  885. int has_path, has_flags;
  886. /* Here we do not care about the utimens/lutimens distinction. */
  887. has_path = (m_out->m_vfs_utimens.name != NULL);
  888. has_flags = !!(m_out->m_vfs_utimens.flags & ~AT_SYMLINK_NOFOLLOW);
  889. if (has_path && has_flags)
  890. put_field(proc, "fd", "AT_CWD"); /* utimensat */
  891. else if (!has_path)
  892. put_fd(proc, "fd", m_out->m_vfs_utimens.fd); /* futimes */
  893. if (has_path || has_flags) /* lutimes, utimes, utimensat */
  894. put_buf(proc, "path", PF_PATH,
  895. (vir_bytes)m_out->m_vfs_utimens.name,
  896. m_out->m_vfs_utimens.len);
  897. put_open(proc, "times", 0, "[", ", ");
  898. put_utimens_timespec(proc, "atime", m_out->m_vfs_utimens.atime,
  899. m_out->m_vfs_utimens.ansec);
  900. put_utimens_timespec(proc, "mtime", m_out->m_vfs_utimens.mtime,
  901. m_out->m_vfs_utimens.mnsec);
  902. put_close(proc, "]");
  903. if (has_flags)
  904. put_flags(proc, "flag", at_flags, COUNT(at_flags), "0x%x",
  905. m_out->m_vfs_utimens.flags);
  906. return CT_DONE;
  907. }
  908. static const struct flags statvfs_flags[] = {
  909. FLAG(ST_WAIT),
  910. FLAG(ST_NOWAIT),
  911. };
  912. static const struct flags st_flags[] = {
  913. FLAG(ST_RDONLY),
  914. FLAG(ST_SYNCHRONOUS),
  915. FLAG(ST_NOEXEC),
  916. FLAG(ST_NOSUID),
  917. FLAG(ST_NODEV),
  918. FLAG(ST_UNION),
  919. FLAG(ST_ASYNC),
  920. FLAG(ST_NOCOREDUMP),
  921. FLAG(ST_RELATIME),
  922. FLAG(ST_IGNORE),
  923. FLAG(ST_NOATIME),
  924. FLAG(ST_SYMPERM),
  925. FLAG(ST_NODEVMTIME),
  926. FLAG(ST_SOFTDEP),
  927. FLAG(ST_LOG),
  928. FLAG(ST_EXTATTR),
  929. FLAG(ST_EXRDONLY),
  930. FLAG(ST_EXPORTED),
  931. FLAG(ST_DEFEXPORTED),
  932. FLAG(ST_EXPORTANON),
  933. FLAG(ST_EXKERB),
  934. FLAG(ST_EXNORESPORT),
  935. FLAG(ST_EXPUBLIC),
  936. FLAG(ST_LOCAL),
  937. FLAG(ST_QUOTA),
  938. FLAG(ST_ROOTFS),
  939. FLAG(ST_NOTRUNC),
  940. };
  941. static void
  942. put_struct_statvfs(struct trace_proc * proc, const char * name, int flags,
  943. vir_bytes addr)
  944. {
  945. struct statvfs buf;
  946. if (!put_open_struct(proc, name, flags, addr, &buf, sizeof(buf)))
  947. return;
  948. put_flags(proc, "f_flag", st_flags, COUNT(st_flags), "0x%x",
  949. buf.f_flag);
  950. put_value(proc, "f_bsize", "%lu", buf.f_bsize);
  951. if (verbose > 0 || buf.f_bsize != buf.f_frsize)
  952. put_value(proc, "f_frsize", "%lu", buf.f_frsize);
  953. if (verbose > 1)
  954. put_value(proc, "f_iosize", "%lu", buf.f_iosize);
  955. put_value(proc, "f_blocks", "%"PRIu64, buf.f_blocks);
  956. put_value(proc, "f_bfree", "%"PRIu64, buf.f_bfree);
  957. if (verbose > 1) {
  958. put_value(proc, "f_bavail", "%"PRIu64, buf.f_bavail);
  959. put_value(proc, "f_bresvd", "%"PRIu64, buf.f_bresvd);
  960. }
  961. if (verbose > 0) {
  962. put_value(proc, "f_files", "%"PRIu64, buf.f_files);
  963. put_value(proc, "f_ffree", "%"PRIu64, buf.f_ffree);
  964. }
  965. if (verbose > 1) {
  966. put_value(proc, "f_favail", "%"PRIu64, buf.f_favail);
  967. put_value(proc, "f_fresvd", "%"PRIu64, buf.f_fresvd);
  968. }
  969. if (verbose > 1) {
  970. put_value(proc, "f_syncreads", "%"PRIu64, buf.f_syncreads);
  971. put_value(proc, "f_syncwrites", "%"PRIu64, buf.f_syncwrites);
  972. put_value(proc, "f_asyncreads", "%"PRIu64, buf.f_asyncreads);
  973. put_value(proc, "f_asyncwrites", "%"PRIu64, buf.f_asyncwrites);
  974. put_value(proc, "f_fsidx", "<%"PRId32",%"PRId32">",
  975. buf.f_fsidx.__fsid_val[0], buf.f_fsidx.__fsid_val[1]);
  976. }
  977. put_dev(proc, "f_fsid", buf.f_fsid); /* MINIX3 interpretation! */
  978. if (verbose > 0)
  979. put_value(proc, "f_namemax", "%lu", buf.f_namemax);
  980. if (verbose > 1)
  981. put_value(proc, "f_owner", "%u", buf.f_owner);
  982. put_buf(proc, "f_fstypename", PF_STRING | PF_LOCADDR,
  983. (vir_bytes)&buf.f_fstypename, sizeof(buf.f_fstypename));
  984. if (verbose > 0)
  985. put_buf(proc, "f_mntfromname", PF_STRING | PF_LOCADDR,
  986. (vir_bytes)&buf.f_mntfromname, sizeof(buf.f_mntfromname));
  987. put_buf(proc, "f_mntonname", PF_STRING | PF_LOCADDR,
  988. (vir_bytes)&buf.f_mntonname, sizeof(buf.f_mntonname));
  989. put_close_struct(proc, verbose > 1);
  990. }
  991. static void
  992. put_statvfs_array(struct trace_proc * proc, const char * name, int flags,
  993. vir_bytes addr, int count)
  994. {
  995. struct statvfs buf;
  996. int i, max;
  997. if ((flags & PF_FAILED) || valuesonly > 1 || count < 0) {
  998. put_ptr(proc, name, addr);
  999. return;
  1000. }
  1001. if (count == 0) {
  1002. put_field(proc, name, "[]");
  1003. return;
  1004. }
  1005. if (verbose == 0)
  1006. max = 0;
  1007. else if (verbose == 1)
  1008. max = 1; /* TODO: is this reasonable? */
  1009. else
  1010. max = INT_MAX;
  1011. if (max > count)
  1012. max = count;
  1013. for (i = 0; i < max; i++) {
  1014. if (mem_get_data(proc->pid, addr + i * sizeof(buf), &buf,
  1015. sizeof(buf)) < 0) {
  1016. if (i == 0) {
  1017. put_ptr(proc, name, addr);
  1018. return;
  1019. }
  1020. break;
  1021. }
  1022. if (i == 0)
  1023. put_open(proc, name, PF_NONAME, "[", ", ");
  1024. put_struct_statvfs(proc, NULL, PF_LOCADDR, (vir_bytes)&buf);
  1025. }
  1026. if (i == 0)
  1027. put_open(proc, name, PF_NONAME, "[", ", ");
  1028. if (i < max)
  1029. put_tail(proc, 0, 0);
  1030. else if (count > i)
  1031. put_tail(proc, count, i);
  1032. put_close(proc, "]");
  1033. }
  1034. static int
  1035. vfs_getvfsstat_out(struct trace_proc * proc, const message * m_out)
  1036. {
  1037. if (m_out->m_lc_vfs_getvfsstat.buf == 0) {
  1038. put_ptr(proc, "buf", m_out->m_lc_vfs_getvfsstat.buf);
  1039. put_value(proc, "bufsize", "%zu",
  1040. m_out->m_lc_vfs_getvfsstat.len);
  1041. put_flags(proc, "flags", statvfs_flags, COUNT(statvfs_flags),
  1042. "%d", m_out->m_lc_vfs_getvfsstat.flags);
  1043. return CT_DONE;
  1044. } else
  1045. return CT_NOTDONE;
  1046. }
  1047. static void
  1048. vfs_getvfsstat_in(struct trace_proc * proc, const message * m_out,
  1049. const message * m_in, int failed)
  1050. {
  1051. if (m_out->m_lc_vfs_getvfsstat.buf != 0) {
  1052. put_statvfs_array(proc, "buf", failed,
  1053. m_out->m_lc_vfs_getvfsstat.buf, m_in->m_type);
  1054. put_value(proc, "bufsize", "%zu",
  1055. m_out->m_lc_vfs_getvfsstat.len);
  1056. put_flags(proc, "flags", statvfs_flags, COUNT(statvfs_flags),
  1057. "%d", m_out->m_lc_vfs_getvfsstat.flags);
  1058. put_equals(proc);
  1059. }
  1060. put_result(proc);
  1061. }
  1062. static int
  1063. vfs_statvfs1_out(struct trace_proc * proc, const message * m_out)
  1064. {
  1065. put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_statvfs1.name,
  1066. m_out->m_lc_vfs_statvfs1.len);
  1067. return CT_NOTDONE;
  1068. }
  1069. static void
  1070. vfs_statvfs1_in(struct trace_proc * proc, const message * m_out,
  1071. const message * __unused m_in, int failed)
  1072. {
  1073. put_struct_statvfs(proc, "buf", failed, m_out->m_lc_vfs_statvfs1.buf);
  1074. put_flags(proc, "flags", statvfs_flags, COUNT(statvfs_flags), "%d",
  1075. m_out->m_lc_vfs_statvfs1.flags);
  1076. put_equals(proc);
  1077. put_result(proc);
  1078. }
  1079. /* This function is shared between statvfs1 and fstatvfs1. */
  1080. static int
  1081. vfs_fstatvfs1_out(struct trace_proc * proc, const message * m_out)
  1082. {
  1083. put_fd(proc, "fd", m_out->m_lc_vfs_statvfs1.fd);
  1084. return CT_NOTDONE;
  1085. }
  1086. static int
  1087. vfs_svrctl_out(struct trace_proc * proc, const message * m_out)
  1088. {
  1089. put_ioctl_req(proc, "request", m_out->m_lc_svrctl.request,
  1090. TRUE /*is_svrctl*/);
  1091. return put_ioctl_arg_out(proc, "arg", m_out->m_lc_svrctl.request,
  1092. m_out->m_lc_svrctl.arg, TRUE /*is_svrctl*/);
  1093. }
  1094. static void
  1095. vfs_svrctl_in(struct trace_proc * proc, const message * m_out,
  1096. const message * __unused m_in, int failed)
  1097. {
  1098. put_ioctl_arg_in(proc, "arg", failed, m_out->m_lc_svrctl.request,
  1099. m_out->m_lc_svrctl.arg, TRUE /*is_svrctl*/);
  1100. }
  1101. static int
  1102. vfs_gcov_flush_out(struct trace_proc * proc, const message * m_out)
  1103. {
  1104. put_ptr(proc, "buff", m_out->m_lc_vfs_gcov.buff_p);
  1105. put_value(proc, "buff_sz", "%zu", m_out->m_lc_vfs_gcov.buff_sz);
  1106. put_value(proc, "server_pid", "%d", m_out->m_lc_vfs_gcov.pid);
  1107. return CT_DONE;
  1108. }
  1109. void
  1110. put_socket_family(struct trace_proc * proc, const char * name, int family)
  1111. {
  1112. const char *text = NULL;
  1113. if (!valuesonly) {
  1114. /*
  1115. * For socket(2) and socketpair(2) this should really be using
  1116. * the prefix "PF_" since those functions take a protocol
  1117. * family rather than an address family. This rule is applied
  1118. * fairly consistently within the system. Here I caved because
  1119. * I don't want to duplicate this entire function just for the
  1120. * one letter. There are exceptions however; some names only
  1121. * exist as "PF_".
  1122. */
  1123. switch (family) {
  1124. TEXT(AF_UNSPEC);
  1125. TEXT(AF_LOCAL);
  1126. TEXT(AF_INET);
  1127. TEXT(AF_IMPLINK);
  1128. TEXT(AF_PUP);
  1129. TEXT(AF_CHAOS);
  1130. TEXT(AF_NS);
  1131. TEXT(AF_ISO);
  1132. TEXT(AF_ECMA);
  1133. TEXT(AF_DATAKIT);
  1134. TEXT(AF_CCITT);
  1135. TEXT(AF_SNA);
  1136. TEXT(AF_DECnet);
  1137. TEXT(AF_DLI);
  1138. TEXT(AF_LAT);
  1139. TEXT(AF_HYLINK);
  1140. TEXT(AF_APPLETALK);
  1141. TEXT(AF_OROUTE);
  1142. TEXT(AF_LINK);
  1143. TEXT(PF_XTP);
  1144. TEXT(AF_COIP);
  1145. TEXT(AF_CNT);
  1146. TEXT(PF_RTIP);
  1147. TEXT(AF_IPX);
  1148. TEXT(AF_INET6);
  1149. TEXT(PF_PIP);
  1150. TEXT(AF_ISDN);
  1151. TEXT(AF_NATM);
  1152. TEXT(AF_ARP);
  1153. TEXT(PF_KEY);
  1154. TEXT(AF_BLUETOOTH);
  1155. TEXT(AF_IEEE80211);
  1156. TEXT(AF_MPLS);
  1157. TEXT(AF_ROUTE);
  1158. }
  1159. }
  1160. if (text != NULL)
  1161. put_field(proc, name, text);
  1162. else
  1163. put_value(proc, name, "%d", family);
  1164. }
  1165. static const struct flags socket_types[] = {
  1166. FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_STREAM),
  1167. FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_DGRAM),
  1168. FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_RAW),
  1169. FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_RDM),
  1170. FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_SEQPACKET),
  1171. FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_CONN_DGRAM),
  1172. FLAG(SOCK_CLOEXEC),
  1173. FLAG(SOCK_NONBLOCK),
  1174. FLAG(SOCK_NOSIGPIPE),
  1175. };
  1176. void
  1177. put_socket_type(struct trace_proc * proc, const char * name, int type)
  1178. {
  1179. put_flags(proc, name, socket_types, COUNT(socket_types), "%d", type);
  1180. }
  1181. static void
  1182. put_socket_protocol(struct trace_proc * proc, const char * name, int family,
  1183. int type, int protocol)
  1184. {
  1185. const char *text = NULL;
  1186. if (!valuesonly && (type == SOCK_RAW || protocol != 0)) {
  1187. switch (family) {
  1188. case PF_INET:
  1189. case PF_INET6:
  1190. /* TODO: is this all that is used in socket(2)? */
  1191. switch (protocol) {
  1192. TEXT(IPPROTO_IP);
  1193. TEXT(IPPROTO_ICMP);
  1194. TEXT(IPPROTO_IGMP);
  1195. TEXT(IPPROTO_TCP);
  1196. TEXT(IPPROTO_UDP);
  1197. TEXT(IPPROTO_ICMPV6);
  1198. TEXT(IPPROTO_RAW);
  1199. }
  1200. break;
  1201. #if 0 /* not yet */
  1202. case PF_BLUETOOTH:
  1203. switch (protocol) {
  1204. TEXT(BTPROTO_HCI);
  1205. TEXT(BTPROTO_L2CAP);
  1206. TEXT(BTPROTO_RFCOMM);
  1207. TEXT(BTPROTO_SCO);
  1208. }
  1209. break;
  1210. #endif
  1211. }
  1212. }
  1213. if (text != NULL)
  1214. put_field(proc, name, text);
  1215. else
  1216. put_value(proc, name, "%d", protocol);
  1217. }
  1218. static int
  1219. vfs_socket_out(struct trace_proc * proc, const message * m_out)
  1220. {
  1221. put_socket_family(proc, "domain", m_out->m_lc_vfs_socket.domain);
  1222. put_socket_type(proc, "type", m_out->m_lc_vfs_socket.type);
  1223. put_socket_protocol(proc, "protocol", m_out->m_lc_vfs_socket.domain,
  1224. m_out->m_lc_vfs_socket.type & ~SOCK_FLAGS_MASK,
  1225. m_out->m_lc_vfs_socket.protocol);
  1226. return CT_DONE;
  1227. }
  1228. static int
  1229. vfs_socketpair_out(struct trace_proc * proc, const message * m_out)
  1230. {
  1231. put_socket_family(proc, "domain", m_out->m_lc_vfs_socket.domain);
  1232. put_socket_type(proc, "type", m_out->m_lc_vfs_socket.type);
  1233. put_socket_protocol(proc, "protocol", m_out->m_lc_vfs_socket.domain,
  1234. m_out->m_lc_vfs_socket.type & ~SOCK_FLAGS_MASK,
  1235. m_out->m_lc_vfs_socket.protocol);
  1236. return CT_NOTDONE;
  1237. }
  1238. static void
  1239. vfs_socketpair_in(struct trace_proc * proc, const message * m_out,
  1240. const message * m_in, int failed)
  1241. {
  1242. if (!failed) {
  1243. put_open(proc, "fd", PF_NONAME, "[", ", ");
  1244. put_fd(proc, "fd0", m_in->m_vfs_lc_fdpair.fd0);
  1245. put_fd(proc, "fd1", m_in->m_vfs_lc_fdpair.fd1);
  1246. put_close(proc, "]");
  1247. } else
  1248. put_field(proc, "fd", "&..");
  1249. put_equals(proc);
  1250. put_result(proc);
  1251. }
  1252. void
  1253. put_in_addr(struct trace_proc * proc, const char * name, struct in_addr in)
  1254. {
  1255. if (!valuesonly) {
  1256. /* Is this an acceptable encapsulation? */
  1257. put_value(proc, name, "[%s]", inet_ntoa(in));
  1258. } else
  1259. put_value(proc, name, "0x%08x", ntohl(in.s_addr));
  1260. }
  1261. static void
  1262. put_in6_addr(struct trace_proc * proc, const char * name, struct in6_addr * in)
  1263. {
  1264. char buf[INET6_ADDRSTRLEN];
  1265. const char *ptr;
  1266. unsigned int i, n;
  1267. if (!valuesonly &&
  1268. (ptr = inet_ntop(AF_INET6, in, buf, sizeof(buf))) != NULL) {
  1269. put_value(proc, name, "[%s]", ptr);
  1270. } else {
  1271. for (i = n = 0; i < 16; i++)
  1272. n += snprintf(buf + n, sizeof(buf) - n, "%02x",
  1273. ((unsigned char *)in)[i]);
  1274. put_value(proc, name, "0x%s", buf);
  1275. }
  1276. }
  1277. static void
  1278. put_struct_sockaddr(struct trace_proc * proc, const char * name, int flags,
  1279. vir_bytes addr, socklen_t addr_len)
  1280. {
  1281. char buf[UCHAR_MAX + 1];
  1282. uint8_t len;
  1283. sa_family_t family;
  1284. struct sockaddr sa;
  1285. struct sockaddr_in sin;
  1286. struct sockaddr_in6 sin6;
  1287. int all, off, left;
  1288. /*
  1289. * For UNIX domain sockets, make sure there's always room to add a
  1290. * trailing NULL byte, because UDS paths are not necessarily null
  1291. * terminated.
  1292. */
  1293. if (addr_len < offsetof(struct sockaddr, sa_data) ||
  1294. addr_len >= sizeof(buf)) {
  1295. put_ptr(proc, name, addr);
  1296. return;
  1297. }
  1298. if (!put_open_struct(proc, name, flags, addr, buf, addr_len))
  1299. return;
  1300. memcpy(&sa, buf, sizeof(sa));
  1301. len = sa.sa_len;
  1302. family = sa.sa_family;
  1303. all = (verbose > 1);
  1304. switch (family) {
  1305. case AF_LOCAL:
  1306. if (verbose > 1)
  1307. put_value(proc, "sun_len", "%u", len);
  1308. if (verbose > 0)
  1309. put_socket_family(proc, "sun_family", family);
  1310. off = (int)offsetof(struct sockaddr_un, sun_path);
  1311. left = addr_len - off;
  1312. if (left > 0) {
  1313. buf[addr_len] = 0; /* force null termination */
  1314. put_buf(proc, "sun_path", PF_LOCADDR | PF_PATH,
  1315. (vir_bytes)&buf[off],
  1316. left + 1 /* include null byte */);
  1317. }
  1318. break;
  1319. case AF_INET:
  1320. if (verbose > 1)
  1321. put_value(proc, "sin_len", "%u", len);
  1322. if (verbose > 0)
  1323. put_socket_family(proc, "sin_family", family);
  1324. if (addr_len == sizeof(sin)) {
  1325. memcpy(&sin, buf, sizeof(sin));
  1326. put_value(proc, "sin_port", "%u", ntohs(sin.sin_port));
  1327. put_in_addr(proc, "sin_addr", sin.sin_addr);
  1328. } else
  1329. all = FALSE;
  1330. break;
  1331. case AF_INET6:
  1332. if (verbose > 1)
  1333. put_value(proc, "sin6_len", "%u", len);
  1334. if (verbose > 0)
  1335. put_socket_family(proc, "sin6_family", family);
  1336. if (addr_len == sizeof(sin6)) {
  1337. memcpy(&sin6, buf, sizeof(sin6));
  1338. put_value(proc, "sin6_port", "%u",
  1339. ntohs(sin6.sin6_port));
  1340. if (verbose > 1)
  1341. put_value(proc, "sin6_flowinfo", "%"PRIu32,
  1342. sin6.sin6_flowinfo);
  1343. put_in6_addr(proc, "sin6_addr", &sin6.sin6_addr);
  1344. if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
  1345. IN6_IS_ADDR_SITELOCAL(&sin6.sin6_addr) ||
  1346. verbose > 0)
  1347. put_value(proc, "sin6_scope_id", "%"PRIu32,
  1348. sin6.sin6_scope_id);
  1349. } else
  1350. all = FALSE;
  1351. break;
  1352. /* TODO: support for other address families */
  1353. default:
  1354. if (verbose > 1)
  1355. put_value(proc, "sa_len", "%u", len);
  1356. put_socket_family(proc, "sa_family", family);
  1357. all = (verbose > 1 && family == AF_UNSPEC);
  1358. }
  1359. put_close_struct(proc, all);
  1360. }
  1361. /* This function is shared between bind and connect. */
  1362. static int
  1363. vfs_bind_out(struct trace_proc * proc, const message * m_out)
  1364. {
  1365. put_fd(proc, "fd", m_out->m_lc_vfs_sockaddr.fd);
  1366. put_struct_sockaddr(proc, "addr", 0, m_out->m_lc_vfs_sockaddr.addr,
  1367. m_out->m_lc_vfs_sockaddr.addr_len);
  1368. put_value(proc, "addr_len", "%u", m_out->m_lc_vfs_sockaddr.addr_len);
  1369. return CT_DONE;
  1370. }
  1371. static int
  1372. vfs_listen_out(struct trace_proc * proc, const message * m_out)
  1373. {
  1374. put_fd(proc, "fd", m_out->m_lc_vfs_listen.fd);
  1375. put_value(proc, "backlog", "%d", m_out->m_lc_vfs_listen.backlog);
  1376. return CT_DONE;
  1377. }
  1378. static int
  1379. vfs_accept_out(struct trace_proc * proc, const message * m_out)
  1380. {
  1381. put_fd(proc, "fd", m_out->m_lc_vfs_sockaddr.fd);
  1382. return CT_NOTDONE;
  1383. }
  1384. static void
  1385. vfs_accept_in(struct trace_proc * proc, const message * m_out,
  1386. const message * m_in, int failed)
  1387. {
  1388. put_struct_sockaddr(proc, "addr", failed,
  1389. m_out->m_lc_vfs_sockaddr.addr, m_in->m_vfs_lc_socklen.len);
  1390. /*
  1391. * We print the resulting address length rather than the given buffer
  1392. * size here, as we do in recvfrom, getsockname, getpeername, and (less
  1393. * explicitly) recvmsg. We could also print both, by adding the
  1394. * resulting length after the call result.
  1395. */
  1396. if (m_out->m_lc_vfs_sockaddr.addr == 0)
  1397. put_field(proc, "addr_len", "NULL");
  1398. else if (!failed)
  1399. put_value(proc, "addr_len", "{%u}",
  1400. m_in->m_vfs_lc_socklen.len);
  1401. else
  1402. put_field(proc, "addr_len", "&..");
  1403. put_equals(proc);
  1404. put_result(proc);
  1405. }
  1406. static const struct flags msg_flags[] = {
  1407. FLAG(MSG_OOB),
  1408. FLAG(MSG_PEEK),
  1409. FLAG(MSG_DONTROUTE),
  1410. FLAG(MSG_EOR),
  1411. FLAG(MSG_TRUNC),
  1412. FLAG(MSG_CTRUNC),
  1413. FLAG(MSG_WAITALL),
  1414. FLAG(MSG_DONTWAIT),
  1415. FLAG(MSG_BCAST),
  1416. FLAG(MSG_MCAST),
  1417. #ifdef MSG_NOSIGNAL
  1418. FLAG(MSG_NOSIGNAL),
  1419. #endif
  1420. FLAG(MSG_CMSG_CLOEXEC),
  1421. FLAG(MSG_NBIO),
  1422. FLAG(MSG_WAITFORONE),
  1423. };
  1424. static int
  1425. vfs_sendto_out(struct trace_proc * proc, const message * m_out)
  1426. {
  1427. put_fd(proc, "fd", m_out->m_lc_vfs_sendrecv.fd);
  1428. put_buf(proc, "buf", 0, m_out->m_lc_vfs_sendrecv.buf,
  1429. m_out->m_lc_vfs_readwrite.len);
  1430. put_value(proc, "len", "%zu", m_out->m_lc_vfs_sendrecv.len);
  1431. put_flags(proc, "flags", msg_flags, COUNT(msg_flags), "0x%x",
  1432. m_out->m_lc_vfs_sendrecv.flags);
  1433. put_struct_sockaddr(proc, "addr", 0, m_out->m_lc_vfs_sendrecv.addr,
  1434. m_out->m_lc_vfs_sendrecv.addr_len);
  1435. put_value(proc, "addr_len", "%u", m_out->m_lc_vfs_sendrecv.addr_len);
  1436. return CT_DONE;
  1437. }
  1438. static void
  1439. put_struct_iovec(struct trace_proc * proc, const char * name, int flags,
  1440. vir_bytes addr, int len, ssize_t bmax)
  1441. {
  1442. struct iovec iov;
  1443. size_t bytes;
  1444. int i, imax;
  1445. /*
  1446. * For simplicity and clarity reasons, we currently print the I/O
  1447. * vector as an array of data elements rather than an array of
  1448. * structures. We also copy in each element separately, because as of
  1449. * writing there is no system support for more than one element anyway.
  1450. * All of this may be changed later.
  1451. */
  1452. if ((flags & PF_FAILED) || valuesonly > 1 || addr == 0 || len < 0) {
  1453. put_ptr(proc, name, addr);
  1454. return;
  1455. }
  1456. if (len == 0 || bmax == 0) {
  1457. put_field(proc, name, "[]");
  1458. return;
  1459. }
  1460. /* As per logic below, 'imax' must be set to a nonzero value here. */
  1461. if (verbose == 0)
  1462. imax = 4;
  1463. else if (verbose == 1)
  1464. imax = 16;
  1465. else
  1466. imax = INT_MAX;
  1467. for (i = 0; i < len && bmax > 0; i++) {
  1468. if (mem_get_data(proc->pid, addr, &iov, sizeof(iov)) < 0) {
  1469. if (i == 0) {
  1470. put_ptr(proc, name, addr);
  1471. return;
  1472. }
  1473. len = imax = 0; /* make put_tail() print an error */
  1474. break;
  1475. }
  1476. if (i == 0)
  1477. put_open(proc, name, 0, "[", ", ");
  1478. bytes = MIN(iov.iov_len, (size_t)bmax);
  1479. if (len < imax)
  1480. put_buf(proc, NULL, 0, (vir_bytes)iov.iov_base, bytes);
  1481. addr += sizeof(struct iovec);
  1482. bmax -= bytes;
  1483. }
  1484. if (imax == 0 || imax < len)
  1485. put_tail(proc, len, imax);
  1486. put_close(proc, "]");
  1487. }
  1488. void
  1489. put_struct_uucred(struct trace_proc * proc, const char * name, int flags,
  1490. vir_bytes addr)
  1491. {
  1492. struct uucred cred;
  1493. if (!put_open_struct(proc, name, flags, addr, &cred, sizeof(cred)))
  1494. return;
  1495. put_value(proc, "cr_uid", "%u", cred.cr_uid);
  1496. if (verbose > 0) {
  1497. put_value(proc, "cr_gid", "%u", cred.cr_gid);
  1498. if (verbose > 1)
  1499. put_value(proc, "cr_ngroups", "%d", cred.cr_ngroups);
  1500. put_groups(proc, "cr_groups", PF_LOCADDR,
  1501. (vir_bytes)&cred.cr_groups, cred.cr_ngroups);
  1502. }
  1503. put_close_struct(proc, verbose > 0);
  1504. }
  1505. static void
  1506. put_socket_level(struct trace_proc * proc, const char * name, int level)
  1507. {
  1508. /*
  1509. * Unfortunately, the level is a domain-specific protocol number. That
  1510. * means that without knowing how the socket was created, we cannot
  1511. * tell what it means. The only thing we can print is SOL_SOCKET,
  1512. * which is the same across all domains.
  1513. */
  1514. if (!valuesonly && level == SOL_SOCKET)
  1515. put_field(proc, name, "SOL_SOCKET");
  1516. else
  1517. put_value(proc, name, "%d", level);
  1518. }
  1519. void
  1520. put_cmsg_type(struct trace_proc * proc, const char * name, int type)
  1521. {
  1522. const char *text = NULL;
  1523. if (!valuesonly) {
  1524. switch (type) {
  1525. TEXT(SCM_RIGHTS);
  1526. TEXT(SCM_CREDS);
  1527. TEXT(SCM_TIMESTAMP);
  1528. }
  1529. }
  1530. if (text != NULL)
  1531. put_field(proc, name, text);
  1532. else
  1533. put_value(proc, name, "%d", type);
  1534. }
  1535. static void
  1536. put_cmsg_rights(struct trace_proc * proc, const char * name, char * buf,
  1537. size_t size, char * cptr, size_t chunk, vir_bytes addr, size_t len)
  1538. {
  1539. unsigned int i, nfds;
  1540. int *ptr;
  1541. put_open(proc, name, PF_NONAME, "[", ", ");
  1542. /*
  1543. * Since file descriptors are important, we print them all, regardless
  1544. * of the current verbosity level. Start with the file descriptors
  1545. * that are already copied into the local buffer.
  1546. */
  1547. ptr = (int *)cptr;
  1548. chunk = MIN(chunk, len);
  1549. nfds = chunk / sizeof(int);
  1550. for (i = 0; i < nfds; i++)
  1551. put_fd(proc, NULL, ptr[i]);
  1552. /* Then do the remaining file descriptors, in chunks. */
  1553. size -= size % sizeof(int);
  1554. for (len -= chunk; len >= sizeof(int); len -= chunk) {
  1555. chunk = MIN(len, size);
  1556. if (mem_get_data(proc->pid, addr, buf, chunk) < 0) {
  1557. put_field(proc, NULL, "..");
  1558. break;
  1559. }
  1560. ptr = (int *)buf;
  1561. nfds = chunk / sizeof(int);
  1562. for (i = 0; i < nfds; i++)
  1563. put_fd(proc, NULL, ptr[i]);
  1564. addr += chunk;
  1565. }
  1566. put_close(proc, "]");
  1567. }
  1568. static void
  1569. put_cmsg(struct trace_proc * proc, const char * name, vir_bytes addr,
  1570. size_t len)
  1571. {
  1572. struct cmsghdr cmsg;
  1573. char buf[CMSG_SPACE(sizeof(struct uucred))];
  1574. size_t off, chunk, datalen;
  1575. if (valuesonly > 1 || addr == 0 || len < CMSG_LEN(0)) {
  1576. put_ptr(proc, name, addr);
  1577. return;
  1578. }
  1579. for (off = 0; off < len; off += CMSG_SPACE(datalen)) {
  1580. chunk = MIN(len - off, sizeof(buf));
  1581. if (chunk < CMSG_LEN(0))
  1582. break;
  1583. if (mem_get_data(proc->pid, addr + off, buf, chunk) < 0) {
  1584. if (off == 0) {
  1585. put_ptr(proc, name, addr);
  1586. return;
  1587. }
  1588. break;
  1589. }
  1590. if (off == 0)
  1591. put_open(proc, name, 0, "[", ", ");
  1592. memcpy(&cmsg, buf, sizeof(cmsg));
  1593. put_open(proc, NULL, 0, "{", ", ");
  1594. if (verbose > 0)
  1595. put_value(proc, "cmsg_len", "%u", cmsg.cmsg_len);
  1596. put_socket_level(proc, "cmsg_level", cmsg.cmsg_level);
  1597. if (cmsg.cmsg_level == SOL_SOCKET)
  1598. put_cmsg_type(proc, "cmsg_type", cmsg.cmsg_type);
  1599. else
  1600. put_value(proc, "cmsg_type", "%d", cmsg.cmsg_type);
  1601. if (cmsg.cmsg_len < CMSG_LEN(0) || off + cmsg.cmsg_len > len) {
  1602. put_tail(proc, 0, 0);
  1603. put_close(proc, "}");
  1604. break;
  1605. }
  1606. datalen = cmsg.cmsg_len - CMSG_LEN(0);
  1607. if (cmsg.cmsg_level == SOL_SOCKET &&
  1608. cmsg.cmsg_type == SCM_RIGHTS) {
  1609. put_cmsg_rights(proc, "cmsg_data", buf, sizeof(buf),
  1610. &buf[CMSG_LEN(0)], chunk - CMSG_LEN(0),
  1611. addr + off + chunk, datalen);
  1612. } else if (cmsg.cmsg_level == SOL_SOCKET &&
  1613. cmsg.cmsg_type == SCM_CREDS &&
  1614. datalen >= sizeof(struct uucred) &&
  1615. chunk >= CMSG_LEN(datalen)) {
  1616. put_struct_uucred(proc, "cmsg_data", PF_LOCADDR,
  1617. (vir_bytes)&buf[CMSG_LEN(0)]);
  1618. } else if (datalen > 0)
  1619. put_field(proc, "cmsg_data", "..");
  1620. if (verbose == 0)
  1621. put_field(proc, NULL, "..");
  1622. put_close(proc, "}");
  1623. }
  1624. if (off < len)
  1625. put_field(proc, NULL, "..");
  1626. put_close(proc, "]");
  1627. }
  1628. static void
  1629. put_struct_msghdr(struct trace_proc * proc, const char * name, int flags,
  1630. vir_bytes addr, ssize_t max)
  1631. {
  1632. struct msghdr msg;
  1633. int all;
  1634. if (!put_open_struct(proc, name, flags, addr, &msg, sizeof(msg)))
  1635. return;
  1636. all = TRUE;
  1637. if (msg.msg_name != NULL || verbose > 1) {
  1638. put_struct_sockaddr(proc, "msg_name", 0,
  1639. (vir_bytes)msg.msg_name, msg.msg_namelen);
  1640. if (verbose > 0)
  1641. put_value(proc, "msg_namelen", "%u", msg.msg_namelen);
  1642. else
  1643. all = FALSE;
  1644. } else
  1645. all = FALSE;
  1646. put_struct_iovec(proc, "msg_iov", 0, (vir_bytes)msg.msg_iov,
  1647. msg.msg_iovlen, max);
  1648. if (verbose > 0)
  1649. put_value(proc, "msg_iovlen", "%d", msg.msg_iovlen);
  1650. else
  1651. all = FALSE;
  1652. if (msg.msg_control != NULL || verbose > 1) {
  1653. put_cmsg(proc, "msg_control", (vir_bytes)msg.msg_control,
  1654. msg.msg_controllen);
  1655. if (verbose > 0)
  1656. put_value(proc, "msg_controllen", "%u",
  1657. msg.msg_controllen);
  1658. else
  1659. all = FALSE;
  1660. } else
  1661. all = FALSE;
  1662. /* When receiving, print the flags field as well. */
  1663. if (flags & PF_ALT)
  1664. put_flags(proc, "msg_flags", msg_flags, COUNT(msg_flags),
  1665. "0x%x", msg.msg_flags);
  1666. put_close_struct(proc, all);
  1667. }
  1668. static int
  1669. vfs_sendmsg_out(struct trace_proc * proc, const message * m_out)
  1670. {
  1671. put_fd(proc, "fd", m_out->m_lc_vfs_sockmsg.fd);
  1672. put_struct_msghdr(proc, "msg", 0, m_out->m_lc_vfs_sockmsg.msgbuf,
  1673. SSIZE_MAX);
  1674. put_flags(proc, "flags", msg_flags, COUNT(msg_flags), "0x%x",
  1675. m_out->m_lc_vfs_sockmsg.flags);
  1676. return CT_DONE;
  1677. }
  1678. static int
  1679. vfs_recvfrom_out(struct trace_proc * proc, const message * m_out)
  1680. {
  1681. put_fd(proc, "fd", m_out->m_lc_vfs_sendrecv.fd);
  1682. return CT_NOTDONE;
  1683. }
  1684. static void
  1685. vfs_recvfrom_in(struct trace_proc * proc, const message * m_out,
  1686. const message * m_in, int failed)
  1687. {
  1688. put_buf(proc, "buf", failed, m_out->m_lc_vfs_sendrecv.buf,
  1689. m_in->m_type);
  1690. put_value(proc, "len", "%zu", m_out->m_lc_vfs_sendrecv.len);
  1691. put_flags(proc, "flags", msg_flags, COUNT(msg_flags), "0x%x",
  1692. m_out->m_lc_vfs_sendrecv.flags);
  1693. put_struct_sockaddr(proc, "addr", failed,
  1694. m_out->m_lc_vfs_sendrecv.addr, m_in->m_vfs_lc_socklen.len);
  1695. if (m_out->m_lc_vfs_sendrecv.addr == 0)
  1696. put_field(proc, "addr_len", "NULL");
  1697. else if (!failed)
  1698. put_value(proc, "addr_len", "{%u}",
  1699. m_in->m_vfs_lc_socklen.len);
  1700. else
  1701. put_field(proc, "addr_len", "&..");
  1702. put_equals(proc);
  1703. put_result(proc);
  1704. }
  1705. static int

Large files files are truncated, but you can click here to view the full file