1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
7 * Reserved.  This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License').  You may not use this file
10 * except in compliance with the License.  Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25/*
26cc -I/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders -DPRIVATE -D__APPLE_PRIVATE -arch x86_64 -arch i386 -O -lutil -o fs_usage fs_usage.c
27*/
28
29#include <stdlib.h>
30#include <stdio.h>
31#include <signal.h>
32#include <strings.h>
33#include <nlist.h>
34#include <fcntl.h>
35#include <aio.h>
36#include <string.h>
37#include <dirent.h>
38#include <libc.h>
39#include <termios.h>
40#include <errno.h>
41#include <err.h>
42#include <libutil.h>
43
44#include <sys/types.h>
45#include <sys/param.h>
46#include <sys/time.h>
47#include <sys/ioctl.h>
48#include <sys/socket.h>
49#include <sys/mman.h>
50#include <sys/sysctl.h>
51#include <sys/disk.h>
52#include <sys/file.h>
53
54#ifndef KERNEL_PRIVATE
55#define KERNEL_PRIVATE
56#include <sys/kdebug.h>
57#undef KERNEL_PRIVATE
58#else
59#include <sys/kdebug.h>
60#endif /*KERNEL_PRIVATE*/
61
62#import <mach/clock_types.h>
63#import <mach/mach_time.h>
64
65
66
67#define F_OPENFROM      56              /* SPI: open a file relative to fd (must be a dir) */
68#define F_UNLINKFROM    57              /* SPI: open a file relative to fd (must be a dir) */
69#define F_CHECK_OPENEVT 58              /* SPI: if a process is marked OPENEVT, or in O_EVTONLY on opens of this vnode */
70
71
72#ifndef	RAW_VERSION1
73typedef struct {
74        int             version_no;
75        int             thread_count;
76        uint64_t        TOD_secs;
77	uint32_t        TOD_usecs;
78} RAW_header;
79
80#define RAW_VERSION0    0x55aa0000
81#define RAW_VERSION1    0x55aa0101
82#endif
83
84
85#define MAXINDEX 2048
86
87typedef struct LibraryRange {
88	uint64_t b_address;
89	uint64_t e_address;
90} LibraryRange;
91
92LibraryRange framework32;
93LibraryRange framework64;
94
95
96#define	TEXT_R		0
97#define DATA_R		1
98#define OBJC_R		2
99#define IMPORT_R	3
100#define UNICODE_R	4
101#define IMAGE_R		5
102#define LINKEDIT_R	6
103
104
105char *frameworkType[] = {
106	"<TEXT>    ",
107	"<DATA>    ",
108	"<OBJC>    ",
109	"<IMPORT>  ",
110	"<UNICODE> ",
111	"<IMAGE>   ",
112	"<LINKEDIT>",
113};
114
115
116typedef struct LibraryInfo {
117	uint64_t b_address;
118	uint64_t e_address;
119	int	 r_type;
120	char     *name;
121} LibraryInfo;
122
123LibraryInfo frameworkInfo[MAXINDEX];
124int numFrameworks = 0;
125
126
127/*
128 * MAXCOLS controls when extra data kicks in.
129 * MAX_WIDE_MODE_COLS controls -w mode to get even wider data in path.
130 * If NUMPARMS changes to match the kernel, it will automatically
131 * get reflected in the -w mode output.
132 */
133#define NUMPARMS 23
134#define PATHLENGTH (NUMPARMS*sizeof(uintptr_t))
135
136#define MAXCOLS 132
137#define MAX_WIDE_MODE_COLS (PATHLENGTH + 80)
138#define MAXWIDTH MAX_WIDE_MODE_COLS + 64
139
140#define MAX_PATHNAMES		3
141#define MAX_SCALL_PATHNAMES	2
142
143typedef struct th_info *th_info_t;
144
145struct  lookup {
146	uintptr_t pathname[NUMPARMS + 1];	/* add room for null terminator */
147};
148
149struct th_info {
150	th_info_t  next;
151        uintptr_t  thread;
152        uintptr_t  child_thread;
153
154        int  in_filemgr;
155	int  in_hfs_update;
156        int  pid;
157        int  type;
158        int  arg1;
159        int  arg2;
160        int  arg3;
161        int  arg4;
162        int  arg5;
163        int  arg6;
164        int  arg7;
165        int  arg8;
166        int  waited;
167        double stime;
168	uint64_t  vnodeid;
169        char      *nameptr;
170        uintptr_t *pathptr;
171	int  pn_scall_index;
172	int  pn_work_index;
173	struct lookup lookups[MAX_PATHNAMES];
174};
175
176
177typedef struct threadmap * threadmap_t;
178
179struct threadmap {
180	threadmap_t	tm_next;
181
182	uintptr_t	tm_thread;
183	unsigned int	tm_setsize;	/* this is a bit count */
184	unsigned long  *tm_setptr;	/* file descripter bitmap */
185	char		tm_command[MAXCOMLEN + 1];
186};
187
188
189typedef struct vnode_info * vnode_info_t;
190
191struct vnode_info {
192	vnode_info_t	vn_next;
193	uint64_t	vn_id;
194	uintptr_t	vn_pathname[NUMPARMS + 1];
195};
196
197typedef struct meta_info * meta_info_t;
198
199struct meta_info {
200        meta_info_t     m_next;
201        uint64_t        m_blkno;
202        char            *m_nameptr;
203};
204
205#define HASH_SIZE       1024
206#define HASH_MASK       (HASH_SIZE - 1)
207
208th_info_t	th_info_hash[HASH_SIZE];
209th_info_t	th_info_freelist;
210
211threadmap_t	threadmap_hash[HASH_SIZE];
212threadmap_t	threadmap_freelist;
213
214
215#define VN_HASH_SHIFT   3
216#define VN_HASH_SIZE	16384
217#define VN_HASH_MASK	(VN_HASH_SIZE - 1)
218
219vnode_info_t	vn_info_hash[VN_HASH_SIZE];
220meta_info_t     m_info_hash[VN_HASH_SIZE];
221
222
223int  filemgr_in_progress = 0;
224int  need_new_map = 1;
225int  bias_secs = 0;
226long last_time;
227int  wideflag = 0;
228int  columns = 0;
229
230int  one_good_pid = 0;    /* Used to fail gracefully when bad pids given */
231int  select_pid_mode = 0;  /* Flag set indicates that output is restricted
232			      to selected pids or commands */
233
234char	*arguments = 0;
235int     argmax = 0;
236
237
238#define	USLEEP_MIN	1
239#define USLEEP_BEHIND	2
240#define	USLEEP_MAX	32
241int	usleep_ms = USLEEP_MIN;
242
243/*
244 * Network only or filesystem only output filter
245 * Default of zero means report all activity - no filtering
246 */
247#define FILESYS_FILTER    0x01
248#define NETWORK_FILTER    0x02
249#define EXEC_FILTER	  0x08
250#define PATHNAME_FILTER	  0x10
251#define DISKIO_FILTER	0x20
252#define DEFAULT_DO_NOT_FILTER  0x00
253
254int filter_mode = DEFAULT_DO_NOT_FILTER;
255
256boolean_t show_cachehits = FALSE;
257
258#define NFS_DEV -1
259#define CS_DEV	-2
260
261struct diskrec {
262        struct diskrec *next;
263        char *diskname;
264        int   dev;
265};
266
267struct diskio {
268        struct diskio *next;
269        struct diskio *prev;
270        int  type;
271        int  bp;
272        int  dev;
273        int  blkno;
274        int  iosize;
275        int  io_errno;
276        int  is_meta;
277	uint64_t   vnodeid;
278        uintptr_t  issuing_thread;
279        uintptr_t  completion_thread;
280        char issuing_command[MAXCOMLEN];
281        double issued_time;
282        double completed_time;
283		uint32_t bc_info;
284};
285
286struct diskrec *disk_list = NULL;
287struct diskio *free_diskios = NULL;
288struct diskio *busy_diskios = NULL;
289
290
291struct diskio *insert_diskio();
292struct diskio *find_diskio(int);
293struct diskio *complete_diskio();
294void    	free_diskio();
295void		print_diskio();
296
297int		check_filter_mode(struct th_info *, int, int, int, char *);
298void            format_print(struct th_info *, char *, uintptr_t, int, uintptr_t, uintptr_t, uintptr_t, uintptr_t, int, double, double, int, char *, struct diskio *);
299void		enter_event_now(uintptr_t, int, kd_buf *, char *, double);
300void		enter_event(uintptr_t, int, kd_buf *, char *, double);
301void            exit_event(char *, uintptr_t, int, uintptr_t, uintptr_t, uintptr_t, uintptr_t, int, double);
302void		extend_syscall(uintptr_t, int, kd_buf *);
303
304char           *generate_cs_disk_name(int, char *s);
305char           *find_disk_name(int);
306void		cache_disk_names();
307void		recache_disk_names();
308
309void		lookup_name(uint64_t user_addr, char **type, char **name);
310int 		ReadSharedCacheMap(const char *, LibraryRange *, char *);
311void 		SortFrameworkAddresses();
312
313void		fs_usage_fd_set(uintptr_t, unsigned int);
314int		fs_usage_fd_isset(uintptr_t, unsigned int);
315void		fs_usage_fd_clear(uintptr_t, unsigned int);
316
317void		init_arguments_buffer();
318int	        get_real_command_name(int, char *, int);
319
320void		delete_all_events();
321void	 	delete_event(th_info_t);
322th_info_t 	add_event(uintptr_t, int);
323th_info_t	find_event(uintptr_t, int);
324void		mark_thread_waited(uintptr_t);
325
326void		read_command_map();
327void		delete_all_map_entries();
328void            create_map_entry(uintptr_t, int, char *);
329void		delete_map_entry(uintptr_t);
330threadmap_t 	find_map_entry(uintptr_t);
331
332char		*add_vnode_name(uint64_t, char *);
333char		*find_vnode_name(uint64_t);
334char            *find_meta_name(uint64_t);
335void            add_meta_name(uint64_t, char *);
336
337void		getdivisor();
338void		argtopid();
339void		set_remove();
340void		set_pidcheck();
341void		set_pidexclude();
342int		quit();
343
344
345#define CLASS_MASK	0xff000000
346#define CSC_MASK	0xffff0000
347#define BSC_INDEX(type)	((type >> 2) & 0x3fff)
348
349
350#define TRACE_DATA_NEWTHREAD   0x07000004
351#define TRACE_DATA_EXEC        0x07000008
352#define TRACE_STRING_NEWTHREAD 0x07010004
353#define TRACE_STRING_EXEC      0x07010008
354
355#define MACH_vmfault    0x01300008
356#define MACH_pageout    0x01300004
357#define MACH_sched      0x01400000
358#define MACH_stkhandoff 0x01400008
359#define MACH_idle	0x01400024
360#define VFS_LOOKUP      0x03010090
361#define VFS_ALIAS_VP    0x03010094
362
363#define BSC_thread_terminate    0x040c05a4
364
365#define HFS_update	     0x3018000
366#define HFS_modify_block_end 0x3018004
367
368#define Throttled	0x3010184
369#define SPEC_ioctl	0x3060000
370#define SPEC_unmap_info	0x3060004
371#define proc_exit	0x4010004
372
373#define BC_IO_HIT				0x03070010
374#define BC_IO_HIT_STALLED		0x03070020
375#define BC_IO_MISS				0x03070040
376#define BC_IO_MISS_CUT_THROUGH	0x03070080
377#define BC_PLAYBACK_IO			0x03070100
378#define BC_STR(s)	( \
379	(s == BC_IO_HIT) ? "HIT" : \
380	(s == BC_IO_HIT_STALLED) ? "STALL" : \
381	(s == BC_IO_MISS) ? "MISS" : \
382	(s == BC_IO_MISS_CUT_THROUGH) ? "CUT" : \
383	(s == BC_PLAYBACK_IO) ? "PLBK" : \
384	(s == 0x0) ? "NONE" : "UNKN" )
385
386#ifndef DKIO_NOCACHE
387#define DKIO_NOCACHE	0x80
388#endif
389
390#define P_DISKIO_READ	  (DKIO_READ << 2)
391#define P_DISKIO_ASYNC	  (DKIO_ASYNC << 2)
392#define P_DISKIO_META	  (DKIO_META << 2)
393#define P_DISKIO_PAGING   (DKIO_PAGING << 2)
394#define P_DISKIO_THROTTLE (DKIO_THROTTLE << 2)
395#define P_DISKIO_PASSIVE  (DKIO_PASSIVE << 2)
396#define P_DISKIO_NOCACHE  (DKIO_NOCACHE << 2)
397#define P_DISKIO_TIER_MASK  (DKIO_TIER_MASK << 2)
398#define P_DISKIO_TIER_SHIFT (DKIO_TIER_SHIFT + 2)
399
400#define P_DISKIO	(FSDBG_CODE(DBG_DKRW, 0))
401#define P_DISKIO_DONE	(P_DISKIO | (DKIO_DONE << 2))
402#define P_DISKIO_TYPE	(P_DISKIO | P_DISKIO_READ | P_DISKIO_META | P_DISKIO_PAGING)
403#define P_DISKIO_MASK	(CSC_MASK | 0x4)
404
405#define P_WrData	(P_DISKIO)
406#define P_RdData	(P_DISKIO | P_DISKIO_READ)
407#define P_WrMeta	(P_DISKIO | P_DISKIO_META)
408#define P_RdMeta	(P_DISKIO | P_DISKIO_META | P_DISKIO_READ)
409#define P_PgOut		(P_DISKIO | P_DISKIO_PAGING)
410#define P_PgIn		(P_DISKIO | P_DISKIO_PAGING | P_DISKIO_READ)
411
412#define P_CS_Class		0x0a000000	// DBG_CORESTORAGE
413#define P_CS_Type_Mask		0xfffffff0
414#define P_CS_IO_Done		0x00000004
415
416#define P_CS_ReadChunk		0x0a000200	// chopped up request
417#define P_CS_WriteChunk		0x0a000210
418#define P_CS_MetaRead		0x0a000300	// meta data
419#define P_CS_MetaWrite		0x0a000310
420#define P_CS_TransformRead	0x0a000500	// background transform
421#define P_CS_TransformWrite	0x0a000510
422#define P_CS_MigrationRead	0x0a000600	// composite disk block migration
423#define P_CS_MigrationWrite	0x0a000610
424#define P_CS_SYNC_DISK		0x0a010000
425
426#define MSC_map_fd   0x010c00ac
427
428#define BSC_BASE     0x040C0000
429#define MSC_BASE     0x010C0000
430
431// Network related codes
432#define	BSC_recvmsg		0x040C006C
433#define	BSC_sendmsg		0x040C0070
434#define	BSC_recvfrom		0x040C0074
435#define BSC_accept		0x040C0078
436#define BSC_select		0x040C0174
437#define BSC_socket		0x040C0184
438#define BSC_connect		0x040C0188
439#define BSC_bind		0x040C01A0
440#define BSC_listen		0x040C01A8
441#define	BSC_sendto		0x040C0214
442#define BSC_socketpair		0x040C021C
443#define BSC_recvmsg_nocancel	0x040c0644
444#define BSC_sendmsg_nocancel	0x040c0648
445#define BSC_recvfrom_nocancel	0x040c064c
446#define BSC_accept_nocancel	0x040c0650
447#define BSC_connect_nocancel	0x040c0664
448#define BSC_sendto_nocancel	0x040c0674
449
450#define BSC_exit		0x040C0004
451#define BSC_read		0x040C000C
452#define BSC_write		0x040C0010
453#define BSC_open		0x040C0014
454#define BSC_close		0x040C0018
455#define BSC_link		0x040C0024
456#define BSC_unlink		0x040C0028
457#define BSC_chdir		0x040c0030
458#define BSC_fchdir		0x040c0034
459#define BSC_mknod		0x040C0038
460#define BSC_chmod		0x040C003C
461#define BSC_chown		0x040C0040
462#define BSC_getfsstat		0x040C0048
463#define BSC_access		0x040C0084
464#define BSC_chflags		0x040C0088
465#define BSC_fchflags		0x040C008C
466#define BSC_sync		0x040C0090
467#define BSC_dup			0x040C00A4
468#define BSC_ioctl		0x040C00D8
469#define BSC_revoke		0x040C00E0
470#define BSC_symlink		0x040C00E4
471#define BSC_readlink		0x040C00E8
472#define BSC_execve		0x040C00EC
473#define BSC_umask		0x040C00F0
474#define BSC_chroot		0x040C00F4
475#define BSC_msync		0x040C0104
476#define BSC_dup2		0x040C0168
477#define BSC_fcntl		0x040C0170
478#define BSC_fsync		0x040C017C
479#define BSC_readv		0x040C01E0
480#define BSC_writev		0x040C01E4
481#define BSC_fchown		0x040C01EC
482#define BSC_fchmod		0x040C01F0
483#define BSC_rename		0x040C0200
484#define BSC_flock		0x040C020C
485#define BSC_mkfifo		0x040C0210
486#define BSC_mkdir		0x040C0220
487#define BSC_rmdir		0x040C0224
488#define BSC_utimes		0x040C0228
489#define BSC_futimes		0x040C022C
490#define BSC_pread		0x040C0264
491#define BSC_pwrite		0x040C0268
492#define BSC_statfs		0x040C0274
493#define BSC_fstatfs		0x040C0278
494#define BSC_unmount	        0x040C027C
495#define BSC_mount	        0x040C029C
496#define BSC_fdatasync		0x040C02EC
497#define BSC_stat		0x040C02F0
498#define BSC_fstat		0x040C02F4
499#define BSC_lstat		0x040C02F8
500#define BSC_pathconf		0x040C02FC
501#define BSC_fpathconf		0x040C0300
502#define BSC_getdirentries	0x040C0310
503#define BSC_mmap		0x040c0314
504#define BSC_lseek		0x040c031c
505#define BSC_truncate		0x040C0320
506#define BSC_ftruncate   	0x040C0324
507#define BSC_undelete		0x040C0334
508#define BSC_open_dprotected_np 	0x040C0360
509#define BSC_getattrlist 	0x040C0370
510#define BSC_setattrlist 	0x040C0374
511#define BSC_getdirentriesattr	0x040C0378
512#define BSC_exchangedata	0x040C037C
513#define BSC_checkuseraccess	0x040C0380
514#define BSC_searchfs    	0x040C0384
515#define BSC_delete      	0x040C0388
516#define BSC_copyfile   		0x040C038C
517#define BSC_fgetattrlist	0x040C0390
518#define BSC_fsetattrlist	0x040C0394
519#define BSC_getxattr		0x040C03A8
520#define BSC_fgetxattr		0x040C03AC
521#define BSC_setxattr		0x040C03B0
522#define BSC_fsetxattr		0x040C03B4
523#define BSC_removexattr		0x040C03B8
524#define BSC_fremovexattr	0x040C03BC
525#define BSC_listxattr		0x040C03C0
526#define BSC_flistxattr		0x040C03C4
527#define BSC_fsctl       	0x040C03C8
528#define BSC_posix_spawn       	0x040C03D0
529#define BSC_ffsctl       	0x040C03D4
530#define BSC_open_extended	0x040C0454
531#define BSC_umask_extended	0x040C0458
532#define BSC_stat_extended	0x040C045C
533#define BSC_lstat_extended	0x040C0460
534#define BSC_fstat_extended	0x040C0464
535#define BSC_chmod_extended	0x040C0468
536#define BSC_fchmod_extended	0x040C046C
537#define BSC_access_extended	0x040C0470
538#define BSC_mkfifo_extended	0x040C048C
539#define BSC_mkdir_extended	0x040C0490
540#define BSC_aio_fsync		0x040C04E4
541#define	BSC_aio_return		0x040C04E8
542#define BSC_aio_suspend		0x040C04EC
543#define BSC_aio_cancel		0x040C04F0
544#define BSC_aio_error		0x040C04F4
545#define BSC_aio_read		0x040C04F8
546#define BSC_aio_write		0x040C04FC
547#define BSC_lio_listio		0x040C0500
548#define BSC_sendfile		0x040C0544
549#define BSC_stat64		0x040C0548
550#define BSC_fstat64		0x040C054C
551#define BSC_lstat64		0x040C0550
552#define BSC_stat64_extended	0x040C0554
553#define BSC_lstat64_extended	0x040C0558
554#define BSC_fstat64_extended	0x040C055C
555#define BSC_getdirentries64	0x040C0560
556#define BSC_statfs64		0x040C0564
557#define BSC_fstatfs64		0x040C0568
558#define BSC_getfsstat64		0x040C056C
559#define BSC_pthread_chdir	0x040C0570
560#define BSC_pthread_fchdir	0x040C0574
561#define BSC_lchown		0x040C05B0
562
563#define BSC_read_nocancel	0x040c0630
564#define BSC_write_nocancel	0x040c0634
565#define BSC_open_nocancel	0x040c0638
566#define BSC_close_nocancel      0x040c063c
567#define BSC_msync_nocancel	0x040c0654
568#define BSC_fcntl_nocancel	0x040c0658
569#define BSC_select_nocancel	0x040c065c
570#define BSC_fsync_nocancel	0x040c0660
571#define BSC_readv_nocancel	0x040c066c
572#define BSC_writev_nocancel	0x040c0670
573#define BSC_pread_nocancel	0x040c0678
574#define BSC_pwrite_nocancel	0x040c067c
575#define BSC_aio_suspend_nocancel	0x40c0694
576#define BSC_guarded_open_np	0x040c06e4
577#define BSC_guarded_close_np	0x040c06e8
578
579#define BSC_fsgetpath		0x040c06ac
580
581#define BSC_msync_extended	0x040e0104
582#define BSC_pread_extended	0x040e0264
583#define BSC_pwrite_extended	0x040e0268
584#define BSC_mmap_extended	0x040e0314
585#define BSC_mmap_extended2	0x040f0314
586
587// Carbon File Manager support
588#define FILEMGR_PBGETCATALOGINFO		0x1e000020
589#define FILEMGR_PBGETCATALOGINFOBULK		0x1e000024
590#define FILEMGR_PBCREATEFILEUNICODE		0x1e000028
591#define FILEMGR_PBCREATEDIRECTORYUNICODE	0x1e00002c
592#define FILEMGR_PBCREATEFORK			0x1e000030
593#define FILEMGR_PBDELETEFORK			0x1e000034
594#define FILEMGR_PBITERATEFORK			0x1e000038
595#define FILEMGR_PBOPENFORK			0x1e00003c
596#define FILEMGR_PBREADFORK			0x1e000040
597#define FILEMGR_PBWRITEFORK			0x1e000044
598#define FILEMGR_PBALLOCATEFORK			0x1e000048
599#define FILEMGR_PBDELETEOBJECT			0x1e00004c
600#define FILEMGR_PBEXCHANGEOBJECT		0x1e000050
601#define FILEMGR_PBGETFORKCBINFO			0x1e000054
602#define FILEMGR_PBGETVOLUMEINFO			0x1e000058
603#define FILEMGR_PBMAKEFSREF			0x1e00005c
604#define FILEMGR_PBMAKEFSREFUNICODE		0x1e000060
605#define FILEMGR_PBMOVEOBJECT			0x1e000064
606#define FILEMGR_PBOPENITERATOR			0x1e000068
607#define FILEMGR_PBRENAMEUNICODE			0x1e00006c
608#define FILEMGR_PBSETCATALOGINFO		0x1e000070
609#define FILEMGR_PBSETVOLUMEINFO			0x1e000074
610#define FILEMGR_FSREFMAKEPATH			0x1e000078
611#define FILEMGR_FSPATHMAKEREF			0x1e00007c
612
613#define FILEMGR_PBGETCATINFO			0x1e010000
614#define FILEMGR_PBGETCATINFOLITE		0x1e010004
615#define FILEMGR_PBHGETFINFO			0x1e010008
616#define FILEMGR_PBXGETVOLINFO			0x1e01000c
617#define FILEMGR_PBHCREATE			0x1e010010
618#define FILEMGR_PBHOPENDF			0x1e010014
619#define FILEMGR_PBHOPENRF			0x1e010018
620#define FILEMGR_PBHGETDIRACCESS			0x1e01001c
621#define FILEMGR_PBHSETDIRACCESS			0x1e010020
622#define FILEMGR_PBHMAPID			0x1e010024
623#define FILEMGR_PBHMAPNAME			0x1e010028
624#define FILEMGR_PBCLOSE				0x1e01002c
625#define FILEMGR_PBFLUSHFILE			0x1e010030
626#define FILEMGR_PBGETEOF			0x1e010034
627#define FILEMGR_PBSETEOF			0x1e010038
628#define FILEMGR_PBGETFPOS			0x1e01003c
629#define FILEMGR_PBREAD				0x1e010040
630#define FILEMGR_PBWRITE				0x1e010044
631#define FILEMGR_PBGETFCBINFO			0x1e010048
632#define FILEMGR_PBSETFINFO			0x1e01004c
633#define FILEMGR_PBALLOCATE			0x1e010050
634#define FILEMGR_PBALLOCCONTIG			0x1e010054
635#define FILEMGR_PBSETFPOS			0x1e010058
636#define FILEMGR_PBSETCATINFO			0x1e01005c
637#define FILEMGR_PBGETVOLPARMS			0x1e010060
638#define FILEMGR_PBSETVINFO			0x1e010064
639#define FILEMGR_PBMAKEFSSPEC			0x1e010068
640#define FILEMGR_PBHGETVINFO			0x1e01006c
641#define FILEMGR_PBCREATEFILEIDREF		0x1e010070
642#define FILEMGR_PBDELETEFILEIDREF		0x1e010074
643#define FILEMGR_PBRESOLVEFILEIDREF		0x1e010078
644#define FILEMGR_PBFLUSHVOL			0x1e01007c
645#define FILEMGR_PBHRENAME			0x1e010080
646#define FILEMGR_PBCATMOVE			0x1e010084
647#define FILEMGR_PBEXCHANGEFILES			0x1e010088
648#define FILEMGR_PBHDELETE			0x1e01008c
649#define FILEMGR_PBDIRCREATE			0x1e010090
650#define FILEMGR_PBCATSEARCH			0x1e010094
651#define FILEMGR_PBHSETFLOCK			0x1e010098
652#define FILEMGR_PBHRSTFLOCK			0x1e01009c
653#define FILEMGR_PBLOCKRANGE			0x1e0100a0
654#define FILEMGR_PBUNLOCKRANGE			0x1e0100a4
655
656
657#define FILEMGR_CLASS   0x1e
658#define FILEMGR_BASE	0x1e000000
659
660#define	FMT_DEFAULT	0
661#define FMT_FD		1
662#define FMT_FD_IO	2
663#define FMT_FD_2	3
664#define FMT_SOCKET	4
665#define	FMT_PGIN	5
666#define	FMT_PGOUT	6
667#define	FMT_CACHEHIT	7
668#define FMT_DISKIO	8
669#define FMT_LSEEK	9
670#define FMT_PREAD	10
671#define FMT_FTRUNC	11
672#define FMT_TRUNC	12
673#define FMT_SELECT	13
674#define FMT_OPEN	14
675#define	FMT_AIO_FSYNC	15
676#define	FMT_AIO_RETURN	16
677#define	FMT_AIO_SUSPEND	17
678#define	FMT_AIO_CANCEL	18
679#define	FMT_AIO		19
680#define	FMT_LIO_LISTIO	20
681#define FMT_MSYNC	21
682#define	FMT_FCNTL	22
683#define FMT_ACCESS	23
684#define FMT_CHMOD	24
685#define FMT_FCHMOD	25
686#define	FMT_CHMOD_EXT	26
687#define	FMT_FCHMOD_EXT	27
688#define FMT_CHFLAGS	28
689#define FMT_FCHFLAGS	29
690#define	FMT_IOCTL	30
691#define FMT_MMAP	31
692#define FMT_UMASK	32
693#define FMT_SENDFILE	33
694#define FMT_IOCTL_SYNC	34
695#define FMT_MOUNT	35
696#define FMT_UNMOUNT	36
697#define FMT_DISKIO_CS	37
698#define FMT_SYNC_DISK_CS	38
699#define FMT_IOCTL_UNMAP	39
700#define FMT_UNMAP_INFO	40
701#define FMT_HFS_update	41
702#define FMT_FLOCK	42
703
704#define MAX_BSD_SYSCALL	512
705
706struct bsd_syscall {
707        char	*sc_name;
708        int	sc_format;
709} bsd_syscalls[MAX_BSD_SYSCALL];
710
711
712int bsd_syscall_types[] = {
713        BSC_recvmsg,
714        BSC_recvmsg_nocancel,
715	BSC_sendmsg,
716	BSC_sendmsg_nocancel,
717	BSC_recvfrom,
718	BSC_recvfrom_nocancel,
719	BSC_accept,
720	BSC_accept_nocancel,
721	BSC_select,
722	BSC_select_nocancel,
723	BSC_socket,
724	BSC_connect,
725	BSC_connect_nocancel,
726	BSC_bind,
727	BSC_listen,
728	BSC_sendto,
729	BSC_sendto_nocancel,
730	BSC_socketpair,
731	BSC_read,
732	BSC_read_nocancel,
733	BSC_write,
734	BSC_write_nocancel,
735	BSC_open,
736	BSC_open_nocancel,
737	BSC_close,
738	BSC_close_nocancel,
739	BSC_link,
740	BSC_unlink,
741	BSC_chdir,
742	BSC_fchdir,
743	BSC_mknod,
744	BSC_chmod,
745	BSC_chown,
746	BSC_access,
747	BSC_chflags,
748	BSC_fchflags,
749	BSC_sync,
750	BSC_dup,
751	BSC_revoke,
752	BSC_symlink,
753	BSC_readlink,
754	BSC_exit,
755	BSC_execve,
756	BSC_posix_spawn,
757	BSC_umask,
758	BSC_chroot,
759	BSC_dup2,
760	BSC_fsync,
761	BSC_fsync_nocancel,
762	BSC_readv,
763	BSC_readv_nocancel,
764	BSC_writev,
765	BSC_writev_nocancel,
766	BSC_fchown,
767	BSC_fchmod,
768	BSC_rename,
769	BSC_mkfifo,
770	BSC_mkdir,
771	BSC_rmdir,
772	BSC_utimes,
773	BSC_futimes,
774	BSC_pread,
775	BSC_pread_nocancel,
776	BSC_pwrite,
777	BSC_pwrite_nocancel,
778	BSC_statfs,
779	BSC_fstatfs,
780	BSC_fdatasync,
781	BSC_stat,
782	BSC_fstat,
783	BSC_lstat,
784	BSC_mount,
785	BSC_unmount,
786	BSC_pathconf,
787	BSC_fpathconf,
788	BSC_getdirentries,
789	BSC_mmap,
790	BSC_lseek,
791	BSC_truncate,
792	BSC_ftruncate,
793	BSC_flock,
794	BSC_undelete,
795	BSC_open_dprotected_np,
796	BSC_getattrlist,
797	BSC_setattrlist,
798	BSC_fgetattrlist,
799	BSC_fsetattrlist,
800	BSC_getdirentriesattr,
801	BSC_exchangedata,
802	BSC_checkuseraccess,
803	BSC_searchfs,
804	BSC_delete,
805	BSC_copyfile,
806	BSC_getxattr,
807	BSC_fgetxattr,
808	BSC_setxattr,
809	BSC_fsetxattr,
810	BSC_removexattr,
811	BSC_fremovexattr,
812	BSC_listxattr,
813	BSC_flistxattr,
814	BSC_fsctl,
815	BSC_ffsctl,
816	BSC_open_extended,
817	BSC_umask_extended,
818	BSC_stat_extended,
819	BSC_lstat_extended,
820	BSC_fstat_extended,
821	BSC_chmod_extended,
822	BSC_fchmod_extended,
823	BSC_access_extended,
824	BSC_mkfifo_extended,
825	BSC_mkdir_extended,
826	BSC_aio_fsync,
827	BSC_aio_return,
828	BSC_aio_suspend,
829	BSC_aio_suspend_nocancel,
830	BSC_aio_cancel,
831	BSC_aio_error,
832	BSC_aio_read,
833	BSC_aio_write,
834	BSC_lio_listio,
835	BSC_lchown,
836	BSC_sendfile,
837	BSC_msync,
838	BSC_msync_nocancel,
839	BSC_fcntl,
840	BSC_fcntl_nocancel,
841	BSC_ioctl,
842	BSC_stat64,
843	BSC_fstat64,
844	BSC_lstat64,
845	BSC_stat64_extended,
846	BSC_lstat64_extended,
847	BSC_fstat64_extended,
848	BSC_getdirentries64,
849	BSC_statfs64,
850	BSC_fstatfs64,
851	BSC_pthread_chdir,
852	BSC_pthread_fchdir,
853	BSC_getfsstat,
854	BSC_getfsstat64,
855	BSC_guarded_open_np,
856	BSC_guarded_close_np,
857	BSC_fsgetpath,
858	0
859};
860
861
862#define MAX_FILEMGR	512
863
864struct filemgr_call {
865        char	*fm_name;
866} filemgr_calls[MAX_FILEMGR];
867
868
869int filemgr_call_types[] = {
870        FILEMGR_PBGETCATALOGINFO,
871	FILEMGR_PBGETCATALOGINFOBULK,
872	FILEMGR_PBCREATEFILEUNICODE,
873	FILEMGR_PBCREATEDIRECTORYUNICODE,
874	FILEMGR_PBCREATEFORK,
875	FILEMGR_PBDELETEFORK,
876	FILEMGR_PBITERATEFORK,
877	FILEMGR_PBOPENFORK,
878	FILEMGR_PBREADFORK,
879	FILEMGR_PBWRITEFORK,
880	FILEMGR_PBALLOCATEFORK,
881	FILEMGR_PBDELETEOBJECT,
882	FILEMGR_PBEXCHANGEOBJECT,
883	FILEMGR_PBGETFORKCBINFO,
884	FILEMGR_PBGETVOLUMEINFO,
885	FILEMGR_PBMAKEFSREF,
886	FILEMGR_PBMAKEFSREFUNICODE,
887	FILEMGR_PBMOVEOBJECT,
888	FILEMGR_PBOPENITERATOR,
889	FILEMGR_PBRENAMEUNICODE,
890	FILEMGR_PBSETCATALOGINFO,
891	FILEMGR_PBSETVOLUMEINFO,
892	FILEMGR_FSREFMAKEPATH,
893	FILEMGR_FSPATHMAKEREF,
894
895	FILEMGR_PBGETCATINFO,
896	FILEMGR_PBGETCATINFOLITE,
897	FILEMGR_PBHGETFINFO,
898	FILEMGR_PBXGETVOLINFO,
899	FILEMGR_PBHCREATE,
900	FILEMGR_PBHOPENDF,
901	FILEMGR_PBHOPENRF,
902	FILEMGR_PBHGETDIRACCESS,
903	FILEMGR_PBHSETDIRACCESS,
904	FILEMGR_PBHMAPID,
905	FILEMGR_PBHMAPNAME,
906	FILEMGR_PBCLOSE,
907	FILEMGR_PBFLUSHFILE,
908	FILEMGR_PBGETEOF,
909	FILEMGR_PBSETEOF,
910	FILEMGR_PBGETFPOS,
911	FILEMGR_PBREAD,
912	FILEMGR_PBWRITE,
913	FILEMGR_PBGETFCBINFO,
914	FILEMGR_PBSETFINFO,
915	FILEMGR_PBALLOCATE,
916	FILEMGR_PBALLOCCONTIG,
917	FILEMGR_PBSETFPOS,
918	FILEMGR_PBSETCATINFO,
919	FILEMGR_PBGETVOLPARMS,
920	FILEMGR_PBSETVINFO,
921	FILEMGR_PBMAKEFSSPEC,
922	FILEMGR_PBHGETVINFO,
923	FILEMGR_PBCREATEFILEIDREF,
924	FILEMGR_PBDELETEFILEIDREF,
925	FILEMGR_PBRESOLVEFILEIDREF,
926	FILEMGR_PBFLUSHVOL,
927	FILEMGR_PBHRENAME,
928	FILEMGR_PBCATMOVE,
929	FILEMGR_PBEXCHANGEFILES,
930	FILEMGR_PBHDELETE,
931	FILEMGR_PBDIRCREATE,
932	FILEMGR_PBCATSEARCH,
933	FILEMGR_PBHSETFLOCK,
934	FILEMGR_PBHRSTFLOCK,
935	FILEMGR_PBLOCKRANGE,
936	FILEMGR_PBUNLOCKRANGE,
937	0
938};
939
940
941
942#define MAX_PIDS 256
943int    pids[MAX_PIDS];
944
945int    num_of_pids = 0;
946int    exclude_pids = 0;
947int    exclude_default_pids = 1;
948
949
950struct kinfo_proc *kp_buffer = 0;
951int kp_nentries = 0;
952
953#define EVENT_BASE 60000
954
955int num_events = EVENT_BASE;
956
957
958#define DBG_FUNC_ALL	(DBG_FUNC_START | DBG_FUNC_END)
959#define DBG_FUNC_MASK	0xfffffffc
960
961double divisor = 0.0;       /* Trace divisor converts to microseconds */
962
963int mib[6];
964size_t needed;
965char  *my_buffer;
966
967kbufinfo_t bufinfo = {0, 0, 0, 0, 0};
968
969
970/* defines for tracking file descriptor state */
971#define FS_USAGE_FD_SETSIZE 256		/* Initial number of file descriptors per
972					   thread that we will track */
973
974#define FS_USAGE_NFDBITS      (sizeof (unsigned long) * 8)
975#define FS_USAGE_NFDBYTES(n)  (((n) / FS_USAGE_NFDBITS) * sizeof (unsigned long))
976
977int trace_enabled = 0;
978int set_remove_flag = 1;
979
980int BC_flag = 0;
981
982char *RAW_file = (char *)0;
983int   RAW_flag = 0;
984int   RAW_fd = 0;
985
986uint64_t sample_TOD_secs;
987uint32_t sample_TOD_usecs;
988
989double	bias_now = 0.0;
990double start_time = 0.0;
991double end_time = 999999999999.9;
992
993
994void set_numbufs();
995void set_filter();
996void set_init();
997void set_enable();
998void sample_sc();
999int quit();
1000
1001/*
1002 *  signal handlers
1003 */
1004
1005void leave()			/* exit under normal conditions -- INT handler */
1006{
1007        int i;
1008	void set_enable();
1009	void set_pidcheck();
1010	void set_pidexclude();
1011	void set_remove();
1012
1013	fflush(0);
1014
1015	set_enable(0);
1016
1017	if (exclude_pids == 0) {
1018	        for (i = 0; i < num_of_pids; i++)
1019		        set_pidcheck(pids[i], 0);
1020	}
1021	else {
1022	        for (i = 0; i < num_of_pids; i++)
1023		        set_pidexclude(pids[i], 0);
1024	}
1025	set_remove();
1026
1027	exit(0);
1028}
1029
1030
1031int
1032quit(s)
1033char *s;
1034{
1035        if (trace_enabled)
1036	       set_enable(0);
1037
1038	/*
1039	 * This flag is turned off when calling
1040	 * quit() due to a set_remove() failure.
1041	 */
1042	if (set_remove_flag)
1043	        set_remove();
1044
1045        fprintf(stderr, "fs_usage: ");
1046	if (s)
1047		fprintf(stderr, "%s", s);
1048
1049	exit(1);
1050}
1051
1052
1053void get_screenwidth()
1054{
1055        struct winsize size;
1056
1057	columns = MAXCOLS;
1058
1059	if (isatty(1)) {
1060	        if (ioctl(1, TIOCGWINSZ, &size) != -1) {
1061		        columns = size.ws_col;
1062
1063			if (columns > MAXWIDTH)
1064			        columns = MAXWIDTH;
1065		}
1066	}
1067}
1068
1069
1070void sigwinch()
1071{
1072        if (!wideflag)
1073	        get_screenwidth();
1074}
1075
1076
1077void getdivisor()
1078{
1079	struct mach_timebase_info mti;
1080
1081	mach_timebase_info(&mti);
1082
1083	divisor = ((double)mti.denom / (double)mti.numer) * 1000;
1084}
1085
1086
1087int
1088exit_usage(char *myname) {
1089
1090	fprintf(stderr, "Usage: %s [-e] [-w] [-f mode] [-b] [-t seconds] [-R rawfile [-S start_time] [-E end_time]] [pid | cmd [pid | cmd] ...]\n", myname);
1091	fprintf(stderr, "  -e    exclude the specified list of pids from the sample\n");
1092	fprintf(stderr, "        and exclude fs_usage by default\n");
1093	fprintf(stderr, "  -w    force wider, detailed, output\n");
1094	fprintf(stderr, "  -f    output is based on the mode provided\n");
1095	fprintf(stderr, "          mode = \"network\"  Show network-related events\n");
1096	fprintf(stderr, "          mode = \"filesys\"  Show filesystem-related events\n");
1097	fprintf(stderr, "          mode = \"pathname\" Show only pathname-related events\n");
1098	fprintf(stderr, "          mode = \"exec\"     Show only exec and spawn events\n");
1099	fprintf(stderr, "          mode = \"diskio\"   Show only disk I/O events\n");
1100	fprintf(stderr, "          mode = \"cachehit\" In addition, show cache hits\n");
1101	fprintf(stderr, "  -b    annotate disk I/O events with BootCache info (if available)\n");
1102	fprintf(stderr, "  -t    specifies timeout in seconds (for use in automated tools)\n");
1103	fprintf(stderr, "  -R    specifies a raw trace file to process\n");
1104	fprintf(stderr, "  -S    if -R is specified, selects a start point in microseconds\n");
1105	fprintf(stderr, "  -E    if -R is specified, selects an end point in microseconds\n");
1106	fprintf(stderr, "  pid   selects process(s) to sample\n");
1107	fprintf(stderr, "  cmd   selects process(s) matching command string to sample\n");
1108	fprintf(stderr, "\n%s will handle a maximum list of %d pids.\n\n", myname, MAX_PIDS);
1109	fprintf(stderr, "By default (no options) the following processes are excluded from the output:\n");
1110	fprintf(stderr, "fs_usage, Terminal, telnetd, sshd, rlogind, tcsh, csh, sh\n\n");
1111
1112	exit(1);
1113}
1114
1115
1116int filemgr_index(type) {
1117
1118        if (type & 0x10000)
1119	        return (((type >> 2) & 0x3fff) + 256);
1120
1121        return (((type >> 2) & 0x3fff));
1122}
1123
1124
1125void init_tables(void)
1126{	int i;
1127        int type;
1128        int code;
1129
1130
1131	for (i = 0; i < MAX_BSD_SYSCALL; i++) {
1132	        bsd_syscalls[i].sc_name = NULL;
1133	        bsd_syscalls[i].sc_format = FMT_DEFAULT;
1134	}
1135
1136	for (i = 0; i < MAX_FILEMGR; i++) {
1137	        filemgr_calls[i].fm_name = NULL;
1138	}
1139
1140	for (i = 0; (type = bsd_syscall_types[i]); i++) {
1141
1142	        code = BSC_INDEX(type);
1143
1144		if (code >= MAX_BSD_SYSCALL) {
1145		        printf("BSD syscall init (%x):  type exceeds table size\n", type);
1146		        continue;
1147		}
1148		switch (type) {
1149
1150		    case BSC_sendfile:
1151		      bsd_syscalls[code].sc_name = "sendfile";
1152		      bsd_syscalls[code].sc_format = FMT_FD;		/* this should be changed to FMT_SENDFILE */
1153		      break;						/* once we add an extended info trace event */
1154
1155		    case BSC_recvmsg:
1156		    case BSC_recvmsg_nocancel:
1157		      bsd_syscalls[code].sc_name = "recvmsg";
1158		      bsd_syscalls[code].sc_format = FMT_FD_IO;
1159		      break;
1160
1161		    case BSC_sendmsg:
1162		    case BSC_sendmsg_nocancel:
1163		      bsd_syscalls[code].sc_name = "sendmsg";
1164		      bsd_syscalls[code].sc_format = FMT_FD_IO;
1165		      break;
1166
1167		    case BSC_recvfrom:
1168		    case BSC_recvfrom_nocancel:
1169		      bsd_syscalls[code].sc_name = "recvfrom";
1170		      bsd_syscalls[code].sc_format = FMT_FD_IO;
1171		      break;
1172
1173		    case BSC_sendto:
1174		    case BSC_sendto_nocancel:
1175		      bsd_syscalls[code].sc_name = "sendto";
1176		      bsd_syscalls[code].sc_format = FMT_FD_IO;
1177		      break;
1178
1179		    case BSC_select:
1180		    case BSC_select_nocancel:
1181		      bsd_syscalls[code].sc_name = "select";
1182		      bsd_syscalls[code].sc_format = FMT_SELECT;
1183		      break;
1184
1185		    case BSC_accept:
1186		    case BSC_accept_nocancel:
1187		      bsd_syscalls[code].sc_name = "accept";
1188		      bsd_syscalls[code].sc_format = FMT_FD_2;
1189		      break;
1190
1191		    case BSC_socket:
1192		      bsd_syscalls[code].sc_name = "socket";
1193		      bsd_syscalls[code].sc_format = FMT_SOCKET;
1194		      break;
1195
1196		    case BSC_connect:
1197		    case BSC_connect_nocancel:
1198		      bsd_syscalls[code].sc_name = "connect";
1199		      bsd_syscalls[code].sc_format = FMT_FD;
1200		      break;
1201
1202		    case BSC_bind:
1203		      bsd_syscalls[code].sc_name = "bind";
1204		      bsd_syscalls[code].sc_format = FMT_FD;
1205		      break;
1206
1207		    case BSC_listen:
1208		      bsd_syscalls[code].sc_name = "listen";
1209		      bsd_syscalls[code].sc_format = FMT_FD;
1210		      break;
1211
1212		    case BSC_mmap:
1213		      bsd_syscalls[code].sc_name = "mmap";
1214		      bsd_syscalls[code].sc_format = FMT_MMAP;
1215		      break;
1216
1217		    case BSC_socketpair:
1218		      bsd_syscalls[code].sc_name = "socketpair";
1219		      break;
1220
1221		    case BSC_getxattr:
1222		      bsd_syscalls[code].sc_name = "getxattr";
1223		      break;
1224
1225		    case BSC_setxattr:
1226		      bsd_syscalls[code].sc_name = "setxattr";
1227		      break;
1228
1229		    case BSC_removexattr:
1230		      bsd_syscalls[code].sc_name = "removexattr";
1231		      break;
1232
1233		    case BSC_listxattr:
1234		      bsd_syscalls[code].sc_name = "listxattr";
1235		      break;
1236
1237		    case BSC_stat:
1238		      bsd_syscalls[code].sc_name = "stat";
1239		      break;
1240
1241		    case BSC_stat64:
1242		      bsd_syscalls[code].sc_name = "stat64";
1243		      break;
1244
1245		    case BSC_stat_extended:
1246		      bsd_syscalls[code].sc_name = "stat_extended";
1247		      break;
1248
1249		    case BSC_stat64_extended:
1250		      bsd_syscalls[code].sc_name = "stat_extended64";
1251		      break;
1252
1253		    case BSC_mount:
1254		      bsd_syscalls[code].sc_name = "mount";
1255		      bsd_syscalls[code].sc_format = FMT_MOUNT;
1256		      break;
1257
1258		    case BSC_unmount:
1259		      bsd_syscalls[code].sc_name = "unmount";
1260		      bsd_syscalls[code].sc_format = FMT_UNMOUNT;
1261		      break;
1262
1263		    case BSC_exit:
1264		      bsd_syscalls[code].sc_name = "exit";
1265		      break;
1266
1267		    case BSC_execve:
1268		      bsd_syscalls[code].sc_name = "execve";
1269		      break;
1270
1271		    case BSC_posix_spawn:
1272		      bsd_syscalls[code].sc_name = "posix_spawn";
1273		      break;
1274
1275		    case BSC_open:
1276		    case BSC_open_nocancel:
1277		      bsd_syscalls[code].sc_name = "open";
1278		      bsd_syscalls[code].sc_format = FMT_OPEN;
1279		      break;
1280
1281		    case BSC_open_extended:
1282		      bsd_syscalls[code].sc_name = "open_extended";
1283		      bsd_syscalls[code].sc_format = FMT_OPEN;
1284		      break;
1285
1286		    case BSC_guarded_open_np:
1287		      bsd_syscalls[code].sc_name = "guarded_open_np";
1288		      bsd_syscalls[code].sc_format = FMT_OPEN;
1289		      break;
1290
1291		    case BSC_open_dprotected_np:
1292		      bsd_syscalls[code].sc_name = "open_dprotected";
1293		      bsd_syscalls[code].sc_format = FMT_OPEN;
1294		      break;
1295
1296		    case BSC_dup:
1297		      bsd_syscalls[code].sc_name = "dup";
1298		      bsd_syscalls[code].sc_format = FMT_FD_2;
1299		      break;
1300
1301		    case BSC_dup2:
1302		      bsd_syscalls[code].sc_name = "dup2";
1303		      bsd_syscalls[code].sc_format = FMT_FD_2;
1304		      break;
1305
1306		    case BSC_close:
1307		    case BSC_close_nocancel:
1308		      bsd_syscalls[code].sc_name = "close";
1309		      bsd_syscalls[code].sc_format = FMT_FD;
1310		      break;
1311
1312		    case BSC_guarded_close_np:
1313		      bsd_syscalls[code].sc_name = "guarded_close_np";
1314		      bsd_syscalls[code].sc_format = FMT_FD;
1315		      break;
1316
1317		    case BSC_read:
1318		    case BSC_read_nocancel:
1319		      bsd_syscalls[code].sc_name = "read";
1320		      bsd_syscalls[code].sc_format = FMT_FD_IO;
1321		      break;
1322
1323		    case BSC_write:
1324		    case BSC_write_nocancel:
1325		      bsd_syscalls[code].sc_name = "write";
1326		      bsd_syscalls[code].sc_format = FMT_FD_IO;
1327		      break;
1328
1329		    case BSC_fgetxattr:
1330		      bsd_syscalls[code].sc_name = "fgetxattr";
1331		      bsd_syscalls[code].sc_format = FMT_FD;
1332		      break;
1333
1334		    case BSC_fsetxattr:
1335		      bsd_syscalls[code].sc_name = "fsetxattr";
1336		      bsd_syscalls[code].sc_format = FMT_FD;
1337		      break;
1338
1339		    case BSC_fremovexattr:
1340		      bsd_syscalls[code].sc_name = "fremovexattr";
1341		      bsd_syscalls[code].sc_format = FMT_FD;
1342		      break;
1343
1344		    case BSC_flistxattr:
1345		      bsd_syscalls[code].sc_name = "flistxattr";
1346		      bsd_syscalls[code].sc_format = FMT_FD;
1347		      break;
1348
1349		    case BSC_fstat:
1350		      bsd_syscalls[code].sc_name = "fstat";
1351		      bsd_syscalls[code].sc_format = FMT_FD;
1352		      break;
1353
1354		    case BSC_fstat64:
1355		      bsd_syscalls[code].sc_name = "fstat64";
1356		      bsd_syscalls[code].sc_format = FMT_FD;
1357		      break;
1358
1359		    case BSC_fstat_extended:
1360		      bsd_syscalls[code].sc_name = "fstat_extended";
1361		      bsd_syscalls[code].sc_format = FMT_FD;
1362		      break;
1363
1364		    case BSC_fstat64_extended:
1365		      bsd_syscalls[code].sc_name = "fstat64_extended";
1366		      bsd_syscalls[code].sc_format = FMT_FD;
1367		      break;
1368
1369		    case BSC_lstat:
1370		      bsd_syscalls[code].sc_name = "lstat";
1371		      break;
1372
1373		    case BSC_lstat64:
1374		      bsd_syscalls[code].sc_name = "lstat64";
1375		      break;
1376
1377		    case BSC_lstat_extended:
1378		      bsd_syscalls[code].sc_name = "lstat_extended";
1379		      break;
1380
1381		    case BSC_lstat64_extended:
1382		      bsd_syscalls[code].sc_name = "lstat_extended64";
1383		      break;
1384
1385		    case BSC_link:
1386		      bsd_syscalls[code].sc_name = "link";
1387		      break;
1388
1389		    case BSC_unlink:
1390		      bsd_syscalls[code].sc_name = "unlink";
1391		      break;
1392
1393		    case BSC_mknod:
1394		      bsd_syscalls[code].sc_name = "mknod";
1395		      break;
1396
1397		    case BSC_umask:
1398		      bsd_syscalls[code].sc_name = "umask";
1399		      bsd_syscalls[code].sc_format = FMT_UMASK;
1400		      break;
1401
1402		    case BSC_umask_extended:
1403		      bsd_syscalls[code].sc_name = "umask_extended";
1404		      bsd_syscalls[code].sc_format = FMT_UMASK;
1405		      break;
1406
1407		    case BSC_chmod:
1408		      bsd_syscalls[code].sc_name = "chmod";
1409		      bsd_syscalls[code].sc_format = FMT_CHMOD;
1410		      break;
1411
1412		    case BSC_chmod_extended:
1413		      bsd_syscalls[code].sc_name = "chmod_extended";
1414		      bsd_syscalls[code].sc_format = FMT_CHMOD_EXT;
1415		      break;
1416
1417		    case BSC_fchmod:
1418		      bsd_syscalls[code].sc_name = "fchmod";
1419		      bsd_syscalls[code].sc_format = FMT_FCHMOD;
1420		      break;
1421
1422		    case BSC_fchmod_extended:
1423		      bsd_syscalls[code].sc_name = "fchmod_extended";
1424		      bsd_syscalls[code].sc_format = FMT_FCHMOD_EXT;
1425		      break;
1426
1427		    case BSC_chown:
1428		      bsd_syscalls[code].sc_name = "chown";
1429		      break;
1430
1431		    case BSC_lchown:
1432		      bsd_syscalls[code].sc_name = "lchown";
1433		      break;
1434
1435		    case BSC_fchown:
1436		      bsd_syscalls[code].sc_name = "fchown";
1437		      bsd_syscalls[code].sc_format = FMT_FD;
1438		      break;
1439
1440		    case BSC_access:
1441		      bsd_syscalls[code].sc_name = "access";
1442		      bsd_syscalls[code].sc_format = FMT_ACCESS;
1443		      break;
1444
1445		    case BSC_access_extended:
1446		      bsd_syscalls[code].sc_name = "access_extended";
1447		      break;
1448
1449		    case BSC_chdir:
1450		      bsd_syscalls[code].sc_name = "chdir";
1451		      break;
1452
1453		    case BSC_pthread_chdir:
1454		      bsd_syscalls[code].sc_name = "pthread_chdir";
1455		      break;
1456
1457		    case BSC_chroot:
1458		      bsd_syscalls[code].sc_name = "chroot";
1459		      break;
1460
1461		    case BSC_utimes:
1462		      bsd_syscalls[code].sc_name = "utimes";
1463		      break;
1464
1465		    case BSC_delete:
1466		      bsd_syscalls[code].sc_name = "delete-Carbon";
1467		      break;
1468
1469		    case BSC_undelete:
1470		      bsd_syscalls[code].sc_name = "undelete";
1471		      break;
1472
1473		    case BSC_revoke:
1474		      bsd_syscalls[code].sc_name = "revoke";
1475		      break;
1476
1477		    case BSC_fsctl:
1478		      bsd_syscalls[code].sc_name = "fsctl";
1479		      break;
1480
1481		    case BSC_ffsctl:
1482		      bsd_syscalls[code].sc_name = "ffsctl";
1483		      bsd_syscalls[code].sc_format = FMT_FD;
1484		      break;
1485
1486		    case BSC_chflags:
1487		      bsd_syscalls[code].sc_name = "chflags";
1488		      bsd_syscalls[code].sc_format = FMT_CHFLAGS;
1489		      break;
1490
1491		    case BSC_fchflags:
1492		      bsd_syscalls[code].sc_name = "fchflags";
1493		      bsd_syscalls[code].sc_format = FMT_FCHFLAGS;
1494		      break;
1495
1496		    case BSC_fchdir:
1497		      bsd_syscalls[code].sc_name = "fchdir";
1498		      bsd_syscalls[code].sc_format = FMT_FD;
1499		      break;
1500
1501		    case BSC_pthread_fchdir:
1502		      bsd_syscalls[code].sc_name = "pthread_fchdir";
1503		      bsd_syscalls[code].sc_format = FMT_FD;
1504		      break;
1505
1506		    case BSC_futimes:
1507		      bsd_syscalls[code].sc_name = "futimes";
1508		      bsd_syscalls[code].sc_format = FMT_FD;
1509		      break;
1510
1511		    case BSC_sync:
1512		      bsd_syscalls[code].sc_name = "sync";
1513		      break;
1514
1515		    case BSC_symlink:
1516		      bsd_syscalls[code].sc_name = "symlink";
1517		      break;
1518
1519		    case BSC_readlink:
1520		      bsd_syscalls[code].sc_name = "readlink";
1521		      break;
1522
1523		    case BSC_fsync:
1524		    case BSC_fsync_nocancel:
1525		      bsd_syscalls[code].sc_name = "fsync";
1526		      bsd_syscalls[code].sc_format = FMT_FD;
1527		      break;
1528
1529		    case BSC_fdatasync:
1530		      bsd_syscalls[code].sc_name = "fdatasync";
1531		      bsd_syscalls[code].sc_format = FMT_FD;
1532		      break;
1533
1534		    case BSC_readv:
1535		    case BSC_readv_nocancel:
1536		      bsd_syscalls[code].sc_name = "readv";
1537		      bsd_syscalls[code].sc_format = FMT_FD_IO;
1538		      break;
1539
1540		    case BSC_writev:
1541		    case BSC_writev_nocancel:
1542		      bsd_syscalls[code].sc_name = "writev";
1543		      bsd_syscalls[code].sc_format = FMT_FD_IO;
1544		      break;
1545
1546		    case BSC_pread:
1547		    case BSC_pread_nocancel:
1548		      bsd_syscalls[code].sc_name = "pread";
1549		      bsd_syscalls[code].sc_format = FMT_PREAD;
1550		      break;
1551
1552		    case BSC_pwrite:
1553		    case BSC_pwrite_nocancel:
1554		      bsd_syscalls[code].sc_name = "pwrite";
1555		      bsd_syscalls[code].sc_format = FMT_PREAD;
1556		      break;
1557
1558		    case BSC_mkdir:
1559		      bsd_syscalls[code].sc_name = "mkdir";
1560		      break;
1561
1562		    case BSC_mkdir_extended:
1563		      bsd_syscalls[code].sc_name = "mkdir_extended";
1564		      break;
1565
1566		    case BSC_mkfifo:
1567		      bsd_syscalls[code].sc_name = "mkfifo";
1568		      break;
1569
1570		    case BSC_mkfifo_extended:
1571		      bsd_syscalls[code].sc_name = "mkfifo_extended";
1572		      break;
1573
1574		    case BSC_rmdir:
1575		      bsd_syscalls[code].sc_name = "rmdir";
1576		      break;
1577
1578		    case BSC_statfs:
1579		      bsd_syscalls[code].sc_name = "statfs";
1580		      break;
1581
1582		    case BSC_statfs64:
1583		      bsd_syscalls[code].sc_name = "statfs64";
1584		      break;
1585
1586		    case BSC_getfsstat:
1587		      bsd_syscalls[code].sc_name = "getfsstat";
1588		      break;
1589
1590		    case BSC_getfsstat64:
1591		      bsd_syscalls[code].sc_name = "getfsstat64";
1592		      break;
1593
1594		    case BSC_fstatfs:
1595		      bsd_syscalls[code].sc_name = "fstatfs";
1596		      bsd_syscalls[code].sc_format = FMT_FD;
1597		      break;
1598
1599		    case BSC_fstatfs64:
1600		      bsd_syscalls[code].sc_name = "fstatfs64";
1601		      bsd_syscalls[code].sc_format = FMT_FD;
1602		      break;
1603
1604		    case BSC_pathconf:
1605		      bsd_syscalls[code].sc_name = "pathconf";
1606		      break;
1607
1608		    case BSC_fpathconf:
1609		      bsd_syscalls[code].sc_name = "fpathconf";
1610		      bsd_syscalls[code].sc_format = FMT_FD;
1611		      break;
1612
1613		    case BSC_getdirentries:
1614		      bsd_syscalls[code].sc_name = "getdirentries";
1615		      bsd_syscalls[code].sc_format = FMT_FD_IO;
1616		      break;
1617
1618		    case BSC_getdirentries64:
1619		      bsd_syscalls[code].sc_name = "getdirentries64";
1620		      bsd_syscalls[code].sc_format = FMT_FD_IO;
1621		      break;
1622
1623		    case BSC_lseek:
1624		      bsd_syscalls[code].sc_name = "lseek";
1625		      bsd_syscalls[code].sc_format = FMT_LSEEK;
1626		      break;
1627
1628		    case BSC_truncate:
1629		      bsd_syscalls[code].sc_name = "truncate";
1630		      bsd_syscalls[code].sc_format = FMT_TRUNC;
1631		      break;
1632
1633		    case BSC_ftruncate:
1634		      bsd_syscalls[code].sc_name = "ftruncate";
1635		      bsd_syscalls[code].sc_format = FMT_FTRUNC;
1636		      break;
1637
1638		    case BSC_flock:
1639		      bsd_syscalls[code].sc_name = "flock";
1640		      bsd_syscalls[code].sc_format = FMT_FLOCK;
1641		      break;
1642
1643		    case BSC_getattrlist:
1644		      bsd_syscalls[code].sc_name = "getattrlist";
1645		      break;
1646
1647		    case BSC_setattrlist:
1648		      bsd_syscalls[code].sc_name = "setattrlist";
1649		      break;
1650
1651		    case BSC_fgetattrlist:
1652		      bsd_syscalls[code].sc_name = "fgetattrlist";
1653		      bsd_syscalls[code].sc_format = FMT_FD;
1654		      break;
1655
1656		    case BSC_fsetattrlist:
1657		      bsd_syscalls[code].sc_name = "fsetattrlist";
1658		      bsd_syscalls[code].sc_format = FMT_FD;
1659		      break;
1660
1661		    case BSC_getdirentriesattr:
1662		      bsd_syscalls[code].sc_name = "getdirentriesattr";
1663		      bsd_syscalls[code].sc_format = FMT_FD;
1664		      break;
1665
1666		    case BSC_exchangedata:
1667		      bsd_syscalls[code].sc_name = "exchangedata";
1668		      break;
1669
1670		    case BSC_rename:
1671		      bsd_syscalls[code].sc_name = "rename";
1672		      break;
1673
1674		    case BSC_copyfile:
1675		      bsd_syscalls[code].sc_name = "copyfile";
1676		      break;
1677
1678		    case BSC_checkuseraccess:
1679		      bsd_syscalls[code].sc_name = "checkuseraccess";
1680		      break;
1681
1682		    case BSC_searchfs:
1683		      bsd_syscalls[code].sc_name = "searchfs";
1684		      break;
1685
1686		    case BSC_aio_fsync:
1687		      bsd_syscalls[code].sc_name = "aio_fsync";
1688		      bsd_syscalls[code].sc_format = FMT_AIO_FSYNC;
1689		      break;
1690
1691		    case BSC_aio_return:
1692		      bsd_syscalls[code].sc_name = "aio_return";
1693		      bsd_syscalls[code].sc_format = FMT_AIO_RETURN;
1694		      break;
1695
1696		    case BSC_aio_suspend:
1697		    case BSC_aio_suspend_nocancel:
1698		      bsd_syscalls[code].sc_name = "aio_suspend";
1699		      bsd_syscalls[code].sc_format = FMT_AIO_SUSPEND;
1700		      break;
1701
1702		    case BSC_aio_cancel:
1703		      bsd_syscalls[code].sc_name = "aio_cancel";
1704		      bsd_syscalls[code].sc_format = FMT_AIO_CANCEL;
1705		      break;
1706
1707		    case BSC_aio_error:
1708		      bsd_syscalls[code].sc_name = "aio_error";
1709		      bsd_syscalls[code].sc_format = FMT_AIO;
1710		      break;
1711
1712		    case BSC_aio_read:
1713		      bsd_syscalls[code].sc_name = "aio_read";
1714		      bsd_syscalls[code].sc_format = FMT_AIO;
1715		      break;
1716
1717		    case BSC_aio_write:
1718		      bsd_syscalls[code].sc_name = "aio_write";
1719		      bsd_syscalls[code].sc_format = FMT_AIO;
1720		      break;
1721
1722		    case BSC_lio_listio:
1723		      bsd_syscalls[code].sc_name = "lio_listio";
1724		      bsd_syscalls[code].sc_format = FMT_LIO_LISTIO;
1725		      break;
1726
1727		    case BSC_msync:
1728		    case BSC_msync_nocancel:
1729		      bsd_syscalls[code].sc_name = "msync";
1730		      bsd_syscalls[code].sc_format = FMT_MSYNC;
1731		      break;
1732
1733		    case BSC_fcntl:
1734		    case BSC_fcntl_nocancel:
1735		      bsd_syscalls[code].sc_name = "fcntl";
1736		      bsd_syscalls[code].sc_format = FMT_FCNTL;
1737		      break;
1738
1739		    case BSC_ioctl:
1740		      bsd_syscalls[code].sc_name = "ioctl";
1741		      bsd_syscalls[code].sc_format = FMT_IOCTL;
1742		      break;
1743
1744		    case BSC_fsgetpath:
1745		      bsd_syscalls[code].sc_name = "fsgetpath";
1746		      break;
1747		}
1748	}
1749
1750	for (i = 0; (type = filemgr_call_types[i]); i++) {
1751	        char * p;
1752
1753	        code = filemgr_index(type);
1754
1755		if (code >= MAX_FILEMGR) {
1756		        printf("FILEMGR call init (%x):  type exceeds table size\n", type);
1757		        continue;
1758		}
1759		switch (type) {
1760
1761		    case FILEMGR_PBGETCATALOGINFO:
1762		      p = "GetCatalogInfo";
1763		      break;
1764
1765		    case FILEMGR_PBGETCATALOGINFOBULK:
1766		      p = "GetCatalogInfoBulk";
1767		      break;
1768
1769		    case FILEMGR_PBCREATEFILEUNICODE:
1770		      p = "CreateFileUnicode";
1771		      break;
1772
1773		    case FILEMGR_PBCREATEDIRECTORYUNICODE:
1774		      p = "CreateDirectoryUnicode";
1775		      break;
1776
1777		    case FILEMGR_PBCREATEFORK:
1778		      p = "PBCreateFork";
1779		      break;
1780
1781		    case FILEMGR_PBDELETEFORK:
1782		      p = "PBDeleteFork";
1783		      break;
1784
1785		    case FILEMGR_PBITERATEFORK:
1786		      p = "PBIterateFork";
1787		      break;
1788
1789		    case FILEMGR_PBOPENFORK:
1790		      p = "PBOpenFork";
1791		      break;
1792
1793		    case FILEMGR_PBREADFORK:
1794		      p = "PBReadFork";
1795		      break;
1796
1797		    case FILEMGR_PBWRITEFORK:
1798		      p = "PBWriteFork";
1799		      break;
1800
1801		    case FILEMGR_PBALLOCATEFORK:
1802		      p = "PBAllocateFork";
1803		      break;
1804
1805		    case FILEMGR_PBDELETEOBJECT:
1806		      p = "PBDeleteObject";
1807		      break;
1808
1809		    case FILEMGR_PBEXCHANGEOBJECT:
1810		      p = "PBExchangeObject";
1811		      break;
1812
1813		    case FILEMGR_PBGETFORKCBINFO:
1814		      p = "PBGetForkCBInfo";
1815		      break;
1816
1817		    case FILEMGR_PBGETVOLUMEINFO:
1818		      p = "PBGetVolumeInfo";
1819		      break;
1820
1821		    case FILEMGR_PBMAKEFSREF:
1822		      p = "PBMakeFSRef";
1823		      break;
1824
1825		    case FILEMGR_PBMAKEFSREFUNICODE:
1826		      p = "PBMakeFSRefUnicode";
1827		      break;
1828
1829		    case FILEMGR_PBMOVEOBJECT:
1830		      p = "PBMoveObject";
1831		      break;
1832
1833		    case FILEMGR_PBOPENITERATOR:
1834		      p = "PBOpenIterator";
1835		      break;
1836
1837		    case FILEMGR_PBRENAMEUNICODE:
1838		      p = "PBRenameUnicode";
1839		      break;
1840
1841		    case FILEMGR_PBSETCATALOGINFO:
1842		      p = "SetCatalogInfo";
1843		      break;
1844
1845		    case FILEMGR_PBSETVOLUMEINFO:
1846		      p = "SetVolumeInfo";
1847		      break;
1848
1849		    case FILEMGR_FSREFMAKEPATH:
1850		      p = "FSRefMakePath";
1851		      break;
1852
1853		    case FILEMGR_FSPATHMAKEREF:
1854		      p = "FSPathMakeRef";
1855		      break;
1856
1857		    case FILEMGR_PBGETCATINFO:
1858		      p = "GetCatInfo";
1859		      break;
1860
1861		    case FILEMGR_PBGETCATINFOLITE:
1862		      p = "GetCatInfoLite";
1863		      break;
1864
1865		    case FILEMGR_PBHGETFINFO:
1866		      p = "PBHGetFInfo";
1867		      break;
1868
1869		    case FILEMGR_PBXGETVOLINFO:
1870		      p = "PBXGetVolInfo";
1871		      break;
1872
1873		    case FILEMGR_PBHCREATE:
1874		      p = "PBHCreate";
1875		      break;
1876
1877		    case FILEMGR_PBHOPENDF:
1878		      p = "PBHOpenDF";
1879		      break;
1880
1881		    case FILEMGR_PBHOPENRF:
1882		      p = "PBHOpenRF";
1883		      break;
1884
1885		    case FILEMGR_PBHGETDIRACCESS:
1886		      p = "PBHGetDirAccess";
1887		      break;
1888
1889		    case FILEMGR_PBHSETDIRACCESS:
1890		      p = "PBHSetDirAccess";
1891		      break;
1892
1893		    case FILEMGR_PBHMAPID:
1894		      p = "PBHMapID";
1895		      break;
1896
1897		    case FILEMGR_PBHMAPNAME:
1898		      p = "PBHMapName";
1899		      break;
1900
1901		    case FILEMGR_PBCLOSE:
1902		      p = "PBClose";
1903		      break;
1904
1905		    case FILEMGR_PBFLUSHFILE:
1906		      p = "PBFlushFile";
1907		      break;
1908
1909		    case FILEMGR_PBGETEOF:
1910		      p = "PBGetEOF";
1911		      break;
1912
1913		    case FILEMGR_PBSETEOF:
1914		      p = "PBSetEOF";
1915		      break;
1916
1917		    case FILEMGR_PBGETFPOS:
1918		      p = "PBGetFPos";
1919		      break;
1920
1921		    case FILEMGR_PBREAD:
1922		      p = "PBRead";
1923		      break;
1924
1925		    case FILEMGR_PBWRITE:
1926		      p = "PBWrite";
1927		      break;
1928
1929		    case FILEMGR_PBGETFCBINFO:
1930		      p = "PBGetFCBInfo";
1931		      break;
1932
1933		    case FILEMGR_PBSETFINFO:
1934		      p = "PBSetFInfo";
1935		      break;
1936
1937		    case FILEMGR_PBALLOCATE:
1938		      p = "PBAllocate";
1939		      break;
1940
1941		    case FILEMGR_PBALLOCCONTIG:
1942		      p = "PBAllocContig";
1943		      break;
1944
1945		    case FILEMGR_PBSETFPOS:
1946		      p = "PBSetFPos";
1947		      break;
1948
1949		    case FILEMGR_PBSETCATINFO:
1950		      p = "PBSetCatInfo";
1951		      break;
1952
1953		    case FILEMGR_PBGETVOLPARMS:
1954		      p = "PBGetVolParms";
1955		      break;
1956
1957		    case FILEMGR_PBSETVINFO:
1958		      p = "PBSetVInfo";
1959		      break;
1960
1961		    case FILEMGR_PBMAKEFSSPEC:
1962		      p = "PBMakeFSSpec";
1963		      break;
1964
1965		    case FILEMGR_PBHGETVINFO:
1966		      p = "PBHGetVInfo";
1967		      break;
1968
1969		    case FILEMGR_PBCREATEFILEIDREF:
1970		      p = "PBCreateFileIDRef";
1971		      break;
1972
1973		    case FILEMGR_PBDELETEFILEIDREF:
1974		      p = "PBDeleteFileIDRef";
1975		      break;
1976
1977		    case FILEMGR_PBRESOLVEFILEIDREF:
1978		      p = "PBResolveFileIDRef";
1979		      break;
1980
1981		    case FILEMGR_PBFLUSHVOL:
1982		      p = "PBFlushVol";
1983		      break;
1984
1985		    case FILEMGR_PBHRENAME:
1986		      p = "PBHRename";
1987		      break;
1988
1989		    case FILEMGR_PBCATMOVE:
1990		      p = "PBCatMove";
1991		      break;
1992
1993		    case FILEMGR_PBEXCHANGEFILES:
1994		      p = "PBExchangeFiles";
1995		      break;
1996
1997		    case FILEMGR_PBHDELETE:
1998		      p = "PBHDelete";
1999		      break;
2000
2001		    case FILEMGR_PBDIRCREATE:
2002		      p = "PBDirCreate";
2003		      break;
2004
2005		    case FILEMGR_PBCATSEARCH:
2006		      p = "PBCatSearch";
2007		      break;
2008
2009		    case FILEMGR_PBHSETFLOCK:
2010		      p = "PBHSetFlock";
2011		      break;
2012
2013		    case FILEMGR_PBHRSTFLOCK:
2014		      p = "PBHRstFLock";
2015		      break;
2016
2017		    case FILEMGR_PBLOCKRANGE:
2018		      p = "PBLockRange";
2019		      break;
2020
2021		    case FILEMGR_PBUNLOCKRANGE:
2022		      p = "PBUnlockRange";
2023		      break;
2024
2025		    default:
2026		      p = NULL;
2027		      break;
2028		}
2029		filemgr_calls[code].fm_name = p;
2030	}
2031}
2032
2033
2034
2035int
2036main(argc, argv)
2037	int	argc;
2038	char	*argv[];
2039{
2040	char	*myname = "fs_usage";
2041	int     i;
2042	char    ch;
2043
2044	time_t stop_at_time = 0;
2045
2046	if (0 != reexec_to_match_kernel()) {
2047		fprintf(stderr, "Could not re-execute: %d\n", errno);
2048		exit(1);
2049	}
2050	get_screenwidth();
2051
2052	/*
2053	 * get our name
2054	 */
2055	if (argc > 0) {
2056		if ((myname = rindex(argv[0], '/')) == 0)
2057			myname = argv[0];
2058		else
2059			myname++;
2060	}
2061
2062	while ((ch = getopt(argc, argv, "bewf:R:S:E:t:")) != EOF) {
2063
2064               switch(ch) {
2065
2066                case 'e':
2067		    exclude_pids = 1;
2068		    exclude_default_pids = 0;
2069		    break;
2070
2071                case 'w':
2072		    wideflag = 1;
2073		    if ((uint)columns < MAX_WIDE_MODE_COLS)
2074			    columns = MAX_WIDE_MODE_COLS;
2075		    break;
2076
2077	       case 'f':
2078		   if (!strcmp(optarg, "network"))
2079			   filter_mode |= NETWORK_FILTER;
2080		   else if (!strcmp(optarg, "filesys"))
2081			   filter_mode |= FILESYS_FILTER;
2082		   else if (!strcmp(optarg, "cachehit"))
2083			   show_cachehits = TRUE;
2084		   else if (!strcmp(optarg, "exec"))
2085			   filter_mode |= EXEC_FILTER;
2086		   else if (!strcmp(optarg, "pathname"))
2087			   filter_mode |= PATHNAME_FILTER;
2088		   else if (!strcmp(optarg, "diskio"))
2089			   filter_mode |= DISKIO_FILTER;
2090		   break;
2091
2092		case 'b':
2093			BC_flag = 1;
2094			break;
2095
2096		case 't':
2097			stop_at_time = time(NULL) + strtoul(optarg, NULL, 10);
2098			break;
2099
2100	       case 'R':
2101		   RAW_flag = 1;
2102		   RAW_file = optarg;
2103		   break;
2104
2105	       case 'S':
2106		   start_time = atof(optarg);
2107		   break;
2108
2109	       case 'E':
2110		   end_time = atof(optarg);
2111		   break;
2112
2113	       default:
2114		 exit_usage(myname);
2115	       }
2116	}
2117	if (!RAW_flag) {
2118		if ( geteuid() != 0 ) {
2119			fprintf(stderr, "'fs_usage' must be run as root...\n");
2120			exit(1);
2121		}
2122	}
2123        argc -= optind;
2124        argv += optind;
2125
2126	/*
2127	 * when excluding, fs_usage should be the first in line for pids[]
2128	 *
2129	 * the !exclude_pids && argc == 0 catches the exclude_default_pids
2130	 * case below where exclude_pids is later set and the fs_usage PID
2131	 * needs to make it into pids[]
2132	 */
2133	if (exclude_pids || (!exclude_pids && argc == 0)) {
2134		if (num_of_pids < (MAX_PIDS - 1))
2135			pids[num_of_pids++] = getpid();
2136	}
2137
2138	/*
2139	 * If we process any list of pids/cmds, then turn off the defaults
2140	 */
2141	if (argc > 0)
2142		exclude_default_pids = 0;
2143
2144	while (argc > 0 && num_of_pids < (MAX_PIDS - 1)) {
2145		select_pid_mode++;
2146		argtopid(argv[0]);
2147		argc--;
2148		argv++;
2149	}
2150	/*
2151	 * Exclude a set of default pids
2152	 */
2153	if (exclude_default_pids) {
2154		argtopid("Terminal");
2155		argtopid("telnetd");
2156		argtopid("telnet");
2157		argtopid("sshd");
2158		argtopid("rlogind");
2159		argtopid("tcsh");
2160		argtopid("csh");
2161		argtopid("sh");
2162		exclude_pids = 1;
2163	}
2164#if 0
2165	for (i = 0; i < num_of_pids; i++) {
2166		if (exclude_pids)
2167			fprintf(stderr, "exclude pid %d\n", pids[i]);
2168		else
2169			fprintf(stderr, "pid %d\n", pids[i]);
2170	}
2171#endif
2172	if (!RAW_flag) {
2173		struct sigaction osa;
2174		int	num_cpus;
2175		size_t	len;
2176
2177		/* set up signal handlers */
2178		signal(SIGINT, leave);
2179		signal(SIGQUIT, leave);
2180
2181		sigaction(SIGHUP, (struct sigaction *)NULL, &osa);
2182
2183		if (osa.sa_handler == SIG_DFL)
2184			signal(SIGHUP, leave);
2185		signal(SIGTERM, leave);
2186		/*
2187		 * grab the number of cpus
2188		 */
2189		mib[0] = CTL_HW;
2190		mib[1] = HW_NCPU;
2191		mib[2] = 0;
2192		len = sizeof(num_cpus);
2193
2194		sysctl(mib, 2, &num_cpus, &len, NULL, 0);
2195		num_events = EVENT_BASE * num_cpus;
2196	}
2197	signal(SIGWINCH, sigwinch);
2198
2199	if ((my_buffer = malloc(num_events * sizeof(kd_buf))) == (char *)0)
2200		quit("can't allocate memory for tracing info\n");
2201
2202	if (ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_i386.map", &framework32, "/var/db/dyld/dyld_shared_cache_i386")) {
2203		ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_x86_64.map", &framework64, "/var/db/dyld/dyld_shared_cache_x86_64");
2204	} else {
2205		ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc.map", &framework32, "/var/db/dyld/dyld_shared_cache_ppc");
2206		ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc64.map", &framework64, "/var/db/dyld/dyld_shared_cache_ppc64");
2207	}
2208	SortFrameworkAddresses();
2209
2210        cache_disk_names();
2211
2212	if (!RAW_flag) {
2213
2214		set_remove();
2215		set_numbufs(num_events);
2216		set_init();
2217
2218		if (exclude_pids == 0) {
2219			for (i = 0; i < num_of_pids; i++)
2220				set_pidcheck(pids[i], 1);
2221		} else {
2222			for (i = 0; i < num_of_pids; i++)
2223				set_pidexclude(pids[i], 1);
2224		}
2225		if (select_pid_mode && !one_good_pid) {
2226			/*
2227			 *  An attempt to restrict output to a given
2228			 *  pid or command has failed. Exit gracefully
2229			 */
2230			set_remove();
2231			exit_usage(myname);
2232		}
2233
2234		set_filter();
2235
2236		set_enable(1);
2237
2238		init_arguments_buffer();
2239	}
2240	getdivisor();
2241
2242	init_tables();
2243
2244	/*
2245	 * main loop
2246	 */
2247	while (stop_at_time == 0 || last_time < stop_at_time) {
2248		if (!RAW_flag)
2249			usleep(1000 * usleep_ms);
2250
2251		sample_sc();
2252
2253		last_time = time((long *)0);
2254	}
2255}
2256
2257
2258void
2259find_proc_names()
2260{
2261        size_t			bufSize = 0;
2262	struct kinfo_proc	*kp;
2263
2264	mib[0] = CTL_KERN;
2265	mib[1] = KERN_PROC;
2266	mib[2] = KERN_PROC_ALL;
2267	mib[3] = 0;
2268
2269	if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0)
2270		quit("trace facility failure, KERN_PROC_ALL\n");
2271
2272	if ((kp = (struct kinfo_proc *)malloc(bufSize)) == (struct kinfo_proc *)0)
2273		quit("can't allocate memory for proc buffer\n");
2274
2275	if (sysctl(mib, 4, kp, &bufSize, NULL, 0) < 0)
2276		quit("trace facility failure, KERN_PROC_ALL\n");
2277
2278        kp_nentries = bufSize/ sizeof(struct kinfo_proc);
2279	kp_buffer = kp;
2280}
2281
2282
2283void
2284set_enable(int val)
2285{
2286	mib[0] = CTL_KERN;
2287	mib[1] = KERN_KDEBUG;
2288	mib[2] = KERN_KDENABLE;		/* protocol */
2289	mib[3] = val;
2290	mib[4] = 0;
2291	mib[5] = 0;		        /* no flags */
2292
2293	if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
2294		quit("trace facility failure, KERN_KDENABLE\n");
2295
2296	if (val)
2297		trace_enabled = 1;
2298	else
2299		trace_enabled = 0;
2300}
2301
2302void
2303set_numbufs(int nbufs)
2304{
2305	mib[0] = CTL_KERN;
2306	mib[1] = KERN_KDEBUG;
2307	mib[2] = KERN_KDSETBUF;
2308	mib[3] = nbufs;
2309	mib[4] = 0;
2310	mib[5] = 0;		        /* no flags */
2311
2312	if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
2313		quit("trace facility failure, KERN_KDSETBUF\n");
2314
2315	mib[0] = CTL_KERN;
2316	mib[1] = KERN_KDEBUG;
2317	mib[2] = KERN_KDSETUP;
2318	mib[3] = 0;
2319	mib[4] = 0;
2320	mib[5] = 0;		        /* no flags */
2321
2322	if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
2323		quit("trace facility failure, KERN_KDSETUP\n");
2324}
2325
2326#define ENCODE_CSC_LOW(class, subclass) \
2327	( (uint16_t) ( ((class) & 0xff) << 8 ) | ((subclass) & 0xff) )
2328
2329void
2330set_filter(void)
2331{
2332	uint8_t type_filter_bitmap[KDBG_TYPEFILTER_BITMAP_SIZE];
2333	bzero(type_filter_bitmap, sizeof(type_filter_bitmap));
2334
2335	setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_TRACE,DBG_TRACE_DATA));
2336	setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_TRACE,DBG_TRACE_STRING));
2337
2338	setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_MACH,DBG_MACH_EXCP_SC)); //0x010c
2339	setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_MACH,DBG_MACH_VM)); //0x0130
2340	setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_MACH,DBG_MACH_SCHED)); //0x0140
2341
2342	setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_FSRW)); //0x0301
2343	setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_DKRW)); //0x0302
2344	setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_IOCTL)); //0x0306
2345	setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_BOOTCACHE)); //0x0307
2346
2347	setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_BSD,DBG_BSD_EXCP_SC)); //0x040c
2348	setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_BSD,DBG_BSD_PROC)); //0x0401
2349	setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_BSD,DBG_BSD_SC_EXTENDED_INFO)); //0x040e
2350	setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_BSD,DBG_BSD_SC_EXTENDED_INFO2)); //0x040f
2351
2352	setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_CORESTORAGE,DBG_CS_IO)); //0x0a00
2353	setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_CORESTORAGE, 1)); //0x0a01 for P_SCCS_SYNC_DIS
2354
2355	setbit(type_filter_bitmap, ENCODE_CSC_LOW(FILEMGR_CLASS, 0)); //Carbon File Manager
2356	setbit(type_filter_bitmap, ENCODE_CSC_LOW(FILEMGR_CLASS, 1)); //Carbon File Manager
2357
2358	errno = 0;
2359	int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDSET_TYPEFILTER };
2360	size_t needed = KDBG_TYPEFILTER_BITMAP_SIZE;
2361	if(sysctl(mib, 3, type_filter_bitmap, &needed, NULL, 0)) {
2362		quit("trace facility failure, KERN_KDSET_TYPEFILTER\n");
2363	}
2364}
2365
2366void
2367set_pidcheck(int pid, int on_off)
2368{
2369        kd_regtype kr;
2370
2371	kr.type = KDBG_TYPENONE;
2372	kr.value1 = pid;
2373	kr.value2 = on_off;
2374	needed = sizeof(kd_regtype);
2375	mib[0] = CTL_KERN;
2376	mib[1] = KERN_KDEBUG;
2377	mib[2] = KERN_KDPIDTR;
2378	mib[3] = 0;
2379	mib[4] = 0;
2380	mib[5] = 0;
2381
2382	if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) {
2383	        if (on_off == 1)
2384		        fprintf(stderr, "pid %d does not exist\n", pid);
2385	} else
2386		one_good_pid++;
2387}
2388
2389/*
2390 * on_off == 0 turns off pid exclusion
2391 * on_off == 1 turns on pid exclusion
2392 */
2393void
2394set_pidexclude(int pid, int on_off)
2395{
2396        kd_regtype kr;
2397
2398	one_good_pid++;
2399
2400	kr.type = KDBG_TYPENONE;
2401	kr.value1 = pid;
2402	kr.value2 = on_off;
2403	needed = sizeof(kd_regtype);
2404	mib[0] = CTL_KERN;
2405	mib[1] = KERN_KDEBUG;
2406	mib[2] = KERN_KDPIDEX;
2407	mib[3] = 0;
2408	mib[4] = 0;
2409	mib[5] = 0;
2410
2411	if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) {
2412	        if (on_off == 1)
2413		          fprintf(stderr, "pid %d does not exist\n", pid);
2414	}
2415}
2416
2417void
2418get_bufinfo(kbufinfo_t *val)
2419{
2420        needed = sizeof (*val);
2421	mib[0] = CTL_KERN;
2422	mib[1] = KERN_KDEBUG;
2423	mib[2] = KERN_KDGETBUF;
2424	mib[3] = 0;
2425	mib[4] = 0;
2426	mib[5] = 0;		/* no flags */
2427
2428	if (sysctl(mib, 3, val, &needed, 0, 0) < 0)
2429		quit("trace facility failure, KERN_KDGETBUF\n");
2430
2431}
2432
2433void
2434set_remove()
2435{
2436        errno = 0;
2437
2438	mib[0] = CTL_KERN;
2439	mib[1] = KERN_KDEBUG;
2440	mib[2] = KERN_KDREMOVE;		/* protocol */
2441	mib[3] = 0;
2442	mib[4] = 0;
2443	mib[5] = 0;		/* no flags */
2444
2445	if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) {
2446		set_remove_flag = 0;
2447
2448		if (errno == EBUSY)
2449			quit("the trace facility is currently in use...\n          fs_usage, sc_usage, and latency use this feature.\n\n");
2450		else
2451			quit("trace facility failure, KERN_KDREMOVE\n");
2452	}
2453}
2454
2455void
2456set_init()
2457{       kd_regtype kr;
2458
2459	kr.type = KDBG_RANGETYPE;
2460	kr.value1 = 0;
2461	kr.value2 = -1;
2462	needed = sizeof(kd_regtype);
2463
2464	mib[0] = CTL_KERN;
2465	mib[1] = KERN_KDEBUG;
2466	mib[2] = KERN_KDSETREG;
2467	mib[3] = 0;
2468	mib[4] = 0;
2469	mib[5] = 0;		/* no flags */
2470
2471	if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0)
2472		quit("trace facility failure, KERN_KDSETREG\n");
2473
2474	mib[0] = CTL_KERN;
2475	mib[1] = KERN_KDEBUG;
2476	mib[2] = KERN_KDSETUP;
2477	mib[3] = 0;
2478	mib[4] = 0;
2479	mib[5] = 0;		/* no flags */
2480
2481	if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
2482		quit("trace facility failure, KERN_KDSETUP\n");
2483}
2484
2485
2486void
2487sample_sc()
2488{
2489	kd_buf *kd;
2490	int i, count;
2491	size_t needed;
2492	uint32_t my_buffer_size = 0;
2493
2494	if (!RAW_flag)
2495		get_bufinfo(&bufinfo);
2496	else
2497		my_buffer_size = num_events * sizeof(kd_buf);
2498
2499	if (need_new_map) {
2500	        read_command_map();
2501	        need_new_map = 0;
2502	}
2503	if (!RAW_flag) {
2504		needed = bufinfo.nkdbufs * sizeof(kd_buf);
2505
2506		mib[0] = CTL_KERN;
2507		mib[1] = KERN_KDEBUG;
2508		mib[2] = KERN_KDREADTR;
2509		mib[3] = 0;
2510		mib[4] = 0;
2511		mib[5] = 0;		/* no flags */
2512
2513		if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0)
2514			quit("trace facility failure, KERN_KDREADTR\n");
2515		count = needed;
2516
2517		if (count > (num_events / 8)) {
2518			if (usleep_ms > USLEEP_BEHIND)
2519				usleep_ms = USLEEP_BEHIND;
2520			else if (usleep_ms > USLEEP_MIN)
2521				usleep_ms /= 2;
2522
2523		} else	if (count < (num_events / 16)) {
2524			if (usleep_ms < USLEEP_MAX)
2525		                usleep_ms *= 2;
2526		}
2527
2528		if (bufinfo.flags & KDBG_WRAPPED) {
2529			fprintf(stderr, "fs_usage: buffer overrun, events generated too quickly: %d\n", count);
2530
2531			delete_all_events();
2532
2533			need_new_map = 1;
2534
2535			set_enable(0);
2536			set_enable(1);
2537		}
2538	} else {
2539		int bytes_read;
2540
2541                if ((bytes_read = read(RAW_fd, my_buffer, my_buffer_size)) < sizeof(kd_buf))
2542			exit(0);
2543		count = bytes_read / sizeof(kd_buf);
2544	}
2545	kd = (kd_buf *)my_buffer;
2546#if 0
2547	fprintf(stderr, "READTR returned %d items\n", count);
2548#endif
2549	for (i = 0; i < count; i++) {
2550		uint32_t debugid;
2551		uintptr_t thread;
2552		int type;
2553		int index;
2554		uintptr_t *sargptr;
2555		uint64_t now;
2556		long long l_usecs;
2557		int secs;
2558		long curr_time;
2559		th_info_t	ti;
2560                struct diskio  *dio;
2561
2562
2563		thread  = kd[i].arg5;
2564		debugid = kd[i].debugid;
2565		type    = kd[i].debugid & DBG_FUNC_MASK;
2566
2567		now = kdbg_get_timestamp(&kd[i]);
2568
2569		if (i == 0 && !RAW_flag) {
2570
2571			curr_time = time((long *)0);
2572			/*
2573			 * Compute bias seconds after each trace buffer read.
2574			 * This helps resync timestamps with the system clock
2575			 * in the event of a system sleep.
2576			 */
2577			if (bias_secs == 0 || curr_time < last_time || curr_time > (last_time + 2)) {
2578				l_usecs = (long long)(now / divisor);
2579				secs = l_usecs / 1000000;
2580				bias_secs = curr_time - secs;
2581			}
2582		}
2583		if (RAW_flag && bias_now == 0.0)
2584			bias_now = now;
2585
2586		if ((type & P_DISKIO_MASK) == P_DISKIO) {
2587			insert_diskio(type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, thread, (double)now);
2588			continue;
2589		}
2590		if ((type & P_DISKIO_MASK) == P_DISKIO_DONE) {
2591			if ((dio = complete_diskio(kd[i].arg1, kd[i].arg4, kd[i].arg3, thread, (double)now))) {
2592				dio->vnodeid = kd[i].arg2;
2593				print_diskio(dio);
2594				free_diskio(dio);
2595			}
2596			continue;
2597		}
2598
2599		if ((type & CLASS_MASK) == P_CS_Class) {
2600
2601		    // the usual DBG_FUNC_START/END does not work for i/o since it will
2602		    // return on a different thread, this code uses the P_CS_IO_Done (0x4) bit
2603		    // instead. the trace command doesn't know how handle either method
2604		    // (unmatched start/end or 0x4) but works a little better this way.
2605
2606		    int cs_type = type & P_CS_Type_Mask;   // strip out the done bit
2607		    bool start = (type & P_CS_IO_Done) != P_CS_IO_Done;
2608
2609		    switch (cs_type) {
2610
2611		    case P_CS_ReadChunk:
2612		    case P_CS_WriteChunk:
2613		    case P_CS_MetaRead:
2614		    case P_CS_MetaWrite:
2615			if (start) {
2616			    insert_diskio(cs_type, kd[i].arg2, kd[i].arg1, kd[i].arg3, kd[i].arg4, thread, (double)now);
2617			} else {
2618			    if ((dio = complete_diskio(kd[i].arg2, kd[i].arg4, kd[i].arg3, thread, (double)now))) {
2619				    print_diskio(dio);
2620				    free_diskio(dio);
2621			    }
2622			}
2623			continue;
2624
2625		    case P_CS_TransformRead:
2626		    case P_CS_TransformWrite:
2627		    case P_CS_MigrationRead:
2628		    case P_CS_MigrationWrite:
2629			if (start) {
2630			    insert_diskio(cs_type, kd[i].arg2, CS_DEV, kd[i].arg3, kd[i].arg4, thread, (double)now);
2631			} else {
2632			    if ((dio = complete_diskio(kd[i].arg2, kd[i].arg4, kd[i].arg3, thread, (double)now))) {
2633				    print_diskio(dio);
2634				    free_diskio(dio);
2635			    }
2636			}
2637			continue;
2638
2639		    case P_CS_SYNC_DISK:
2640			if (start) {
2641			    enter_event(thread, cs_type, &kd[i], NULL, (double)now);
2642			} else {
2643			    exit_event("  SyncCacheCS", thread, cs_type, kd[i].arg1, 0, 0, 0, FMT_SYNC_DISK_CS, (double)now);
2644			}
2645			continue;
2646		    }
2647
2648		    continue;	// ignore other cs timestamps
2649		}
2650
2651		switch (type) {
2652
2653		case TRACE_DATA_NEWTHREAD:
2654		    if (kd[i].arg1) {
2655			    if ((ti = add_event(thread, TRACE_DATA_NEWTHREAD)) == NULL)
2656				    continue;
2657			    ti->child_thread = kd[i].arg1;
2658			    ti->pid = kd[i].arg2;
2659		    }
2660		    continue;
2661
2662		case TRACE_STRING_NEWTHREAD:
2663		    if ((ti = find_event(thread, TRACE_DATA_NEWTHREAD)) == (struct th_info *)0)
2664		            continue;
2665
2666		    create_map_entry(ti->child_thread, ti->pid, (char *)&kd[i].arg1);
2667
2668		    delete_event(ti);
2669		    continue;
2670
2671		case TRACE_DATA_EXEC:
2672		    if ((ti = add_event(thread, TRACE_DATA_EXEC)) == NULL)
2673		            continue;
2674
2675		    ti->pid = kd[i].arg1;
2676		    continue;
2677
2678		case TRACE_STRING_EXEC:
2679		    if ((ti = find_event(thread, BSC_execve))) {
2680			    if (ti->lookups[0].pathname[0])
2681				    exit_event("execve", thread, BSC_execve, 0, 0, 0, 0, FMT_DEFAULT, (double)now);
2682
2683		    } else if ((ti = find_event(thread, BSC_posix_spawn))) {
2684			    if (ti->lookups[0].pathname[0])
2685				    exit_event("posix_spawn", thread, BSC_posix_spawn, 0, 0, 0, 0, FMT_DEFAULT, (double)now);
2686		    }
2687		    if ((ti = find_event(thread, TRACE_DATA_EXEC)) == (struct th_info *)0)
2688			    continue;
2689
2690		    create_map_entry(thread, ti->pid, (char *)&kd[i].arg1);
2691
2692		    delete_event(ti);
2693		    continue;
2694
2695		case BSC_thread_terminate:
2696		    delete_map_entry(thread);
2697		    continue;
2698
2699		case BSC_exit:
2700		    continue;
2701
2702		case proc_exit:
2703		    kd[i].arg1 = kd[i].arg2 >> 8;
2704		    type = BSC_exit;
2705		    break;
2706
2707		case BSC_mmap:
2708		    if (kd[i].arg4 & MAP_ANON)
2709			    continue;
2710		    break;
2711
2712		case MACH_idle:
2713		case MACH_sched:
2714		case MACH_stkhandoff:
2715                    mark_thread_waited(thread);
2716		    continue;
2717
2718		case BC_IO_HIT:
2719		case BC_IO_HIT_STALLED:
2720		case BC_IO_MISS:
2721		case BC_IO_MISS_CUT_THROUGH:
2722		case BC_PLAYBACK_IO:
2723			if ((dio = find_diskio(kd[i].arg1)) != NULL)
2724				dio->bc_info = type;
2725			continue;
2726
2727		case HFS_modify_block_end:
2728		     if ((ti = find_event(thread, 0))) {
2729		             if (ti->nameptr)
2730			             add_meta_name(kd[i].arg2, ti->nameptr);
2731		     }
2732		     continue;
2733
2734		case VFS_ALIAS_VP:
2735		     add_vnode_name(kd[i].arg2, find_vnode_name(kd[i].arg1));
2736		     continue;
2737
2738		case VFS_LOOKUP:
2739		    if ((ti = find_event(thread, 0)) == (struct th_info *)0)
2740		            continue;
2741
2742		    if (debugid & DBG_FUNC_START) {
2743
2744			    if (ti->in_hfs_update) {
2745				    ti->pn_work_index = (MAX_PATHNAMES - 1);
2746			    } else {
2747				    if (ti->pn_scall_index < MAX_SCALL_PATHNAMES)
2748					    ti->pn_work_index = ti->pn_scall_index;
2749				    else
2750					    continue;
2751			    }
2752			    sargptr = &ti->lookups[ti->pn_work_index].pathname[0];
2753
2754			    ti->vnodeid = kd[i].arg1;
2755
2756			    *sargptr++ = kd[i].arg2;
2757			    *sargptr++ = kd[i].arg3;
2758			    *sargptr++ = kd[i].arg4;
2759			    /*
2760			     * NULL terminate the 'string'
2761			     */
2762			    *sargptr = 0;
2763
2764			    ti->pathptr = sargptr;
2765		    } else {
2766		            sargptr = ti->pathptr;
2767
2768			    /*
2769			     * We don't want to overrun our pathname buffer if the
2770			     * kernel sends us more VFS_LOOKUP entries than we can
2771			     * handle and we only handle 2 pathname lookups for
2772			     * a given system call
2773			     */
2774			    if (sargptr == 0)
2775				    continue;
2776
2777			    if ((uintptr_t)sargptr < (uintptr_t)&ti->lookups[ti->pn_work_index].pathname[NUMPARMS]) {
2778
2779				    *sargptr++ = kd[i].arg1;
2780				    *sargptr++ = kd[i].arg2;
2781				    *sargptr++ = kd[i].arg3;
2782				    *sargptr++ = kd[i].arg4;
2783				    /*
2784				     * NULL terminate the 'string'
2785				     */
2786				    *sargptr = 0;
2787			    }
2788		    }
2789		    if (debugid & DBG_FUNC_END) {
2790
2791			    ti->nameptr = add_vnode_name(ti->vnodeid, &ti->lookups[ti->pn_work_index].pathname[0]);
2792
2793			    if (ti->pn_work_index == ti->pn_scall_index) {
2794
2795				    ti->pn_scall_index++;
2796
2797				    if (ti->pn_scall_index < MAX_SCALL_PATHNAMES)
2798					    ti->pathptr = &ti->lookups[ti->pn_scall_index].pathname[0];
2799				    else
2800					    ti->pathptr = 0;
2801			    }
2802		    } else
2803			    ti->pathptr = sargptr;
2804
2805		    continue;
2806		}
2807
2808		if (debugid & DBG_FUNC_START) {
2809		        char * p;
2810
2811			if ((type & CLASS_MASK) == FILEMGR_BASE) {
2812
2813				index = filemgr_index(type);
2814
2815				if (index >= MAX_FILEMGR)
2816				        continue;
2817
2818				if ((p = filemgr_calls[index].fm_name) == NULL)
2819				        continue;
2820			} else
2821			        p = NULL;
2822
2823			enter_event(thread, type, &kd[i], p, (double)now);
2824			continue;
2825		}
2826
2827		switch (type) {
2828
2829		case Throttled:
2830		     exit_event("  THROTTLED", thread, type, 0, 0, 0, 0, FMT_DEFAULT, (double)now);
2831		     continue;
2832
2833		case HFS_update:
2834		     exit_event("  HFS_update", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_HFS_update, (double)now);
2835		     continue;
2836
2837		case SPEC_unmap_info:
2838		     if (check_filter_mode(NULL, SPEC_unmap_info, 0, 0, "SPEC_unmap_info"))
2839			     format_print(NULL, "  TrimExtent", thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, 0, FMT_UNMAP_INFO, now, now, 0, "", NULL);
2840		     continue;
2841
2842		case SPEC_ioctl:
2843		     if (kd[i].arg2 == DKIOCSYNCHRONIZECACHE)
2844			     exit_event("IOCTL", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_IOCTL_SYNC, (double)now);
2845		     else if (kd[i].arg2 == DKIOCUNMAP)
2846			     exit_event("IOCTL", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_IOCTL_UNMAP, (double)now);
2847		     else {
2848			     if ((ti = find_event(thread, type)))
2849				     delete_event(ti);
2850		     }
2851		     continue;
2852
2853		case MACH_pageout:
2854		     if (kd[i].arg2)
2855			     exit_event("PAGE_OUT_ANON", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now);
2856		     else
2857			     exit_event("PAGE_OUT_FILE", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now);
2858		     continue;
2859
2860		case MACH_vmfault:
2861		     if (kd[i].arg4 == DBG_PAGEIN_FAULT)
2862			     exit_event("PAGE_IN", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now);
2863		     else if (kd[i].arg4 == DBG_PAGEINV_FAULT)
2864			     exit_event("PAGE_IN_FILE", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now);
2865		     else if (kd[i].arg4 == DBG_PAGEIND_FAULT)
2866			     exit_event("PAGE_IN_ANON", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now);
2867		     else if (kd[i].arg4 == DBG_CACHE_HIT_FAULT)
2868			     exit_event("CACHE_HIT", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_CACHEHIT, (double)now);
2869		     else {
2870			     if ((ti = find_event(thread, type)))
2871				     delete_event(ti);
2872		     }
2873		     continue;
2874
2875		case MSC_map_fd:
2876		     exit_event("map_fd", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_FD, (double)now);
2877		     continue;
2878
2879		case BSC_mmap_extended:
2880		case BSC_mmap_extended2:
2881		case BSC_msync_extended:
2882		case BSC_pread_extended:
2883		case BSC_pwrite_extended:
2884		     extend_syscall(thread, type, &kd[i]);
2885		     continue;
2886		}
2887
2888		if ((type & CSC_MASK) == BSC_BASE) {
2889
2890		        if ((index = BSC_INDEX(type)) >= MAX_BSD_SYSCALL)
2891			        continue;
2892
2893			if (bsd_syscalls[index].sc_name) {
2894				exit_event(bsd_syscalls[index].sc_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4,
2895					   bsd_syscalls[index].sc_format, (double)now);
2896
2897				if (type == BSC_exit)
2898					delete_map_entry(thread);
2899			}
2900		} else if ((type & CLASS_MASK) == FILEMGR_BASE) {
2901
2902			if ((index = filemgr_index(type)) >= MAX_FILEMGR)
2903			        continue;
2904
2905			if (filemgr_calls[index].fm_name) {
2906				exit_event(filemgr_calls[index].fm_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4,
2907					   FMT_DEFAULT, (double)now);
2908			}
2909		}
2910	}
2911	fflush(0);
2912}
2913
2914
2915void
2916enter_event_now(uintptr_t thread, int type, kd_buf *kd, char *name, double now)
2917{
2918	th_info_t	ti;
2919	threadmap_t	tme;
2920	int secs;
2921	int usecs;
2922	long long l_usecs;
2923	long curr_time;
2924	int clen = 0;
2925	int tsclen = 0;
2926	int nmclen = 0;
2927	int argsclen = 0;
2928	char buf[MAXWIDTH];
2929
2930	if ((ti = add_event(thread, type)) == NULL)
2931		return;
2932
2933	ti->stime  = now;
2934	ti->arg1   = kd->arg1;
2935	ti->arg2   = kd->arg2;
2936	ti->arg3   = kd->arg3;
2937	ti->arg4   = kd->arg4;
2938
2939	switch (type) {
2940
2941	case HFS_update:
2942		ti->in_hfs_update = 1;
2943		break;
2944	}
2945
2946	if ((type & CLASS_MASK) == FILEMGR_BASE &&
2947	    (!RAW_flag || (now >= start_time && now <= end_time))) {
2948
2949		filemgr_in_progress++;
2950		ti->in_filemgr = 1;
2951
2952		if (RAW_flag) {
2953			l_usecs = (long long)((now - bias_now) / divisor);
2954			l_usecs += (sample_TOD_secs * 1000000) + sample_TOD_usecs;
2955		} else
2956			l_usecs = (long long)(now / divisor);
2957		secs = l_usecs / 1000000;
2958		curr_time = bias_secs + secs;
2959
2960		sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11]));
2961		tsclen = strlen(buf);
2962
2963		if (columns > MAXCOLS || wideflag) {
2964			usecs = l_usecs - (long long)((long long)secs * 1000000);
2965			sprintf(&buf[tsclen], ".%06ld", (long)usecs);
2966			tsclen = strlen(buf);
2967		}
2968
2969		/*
2970		 * Print timestamp column
2971		 */
2972		printf("%s", buf);
2973
2974		tme = find_map_entry(thread);
2975		if (tme) {
2976			sprintf(buf, "  %-25.25s ", name);
2977			nmclen = strlen(buf);
2978			printf("%s", buf);
2979
2980			sprintf(buf, "(%d, 0x%lx, 0x%lx, 0x%lx)", (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
2981			argsclen = strlen(buf);
2982
2983			/*
2984			 * Calculate white space out to command
2985			 */
2986			if (columns > MAXCOLS || wideflag) {
2987				clen = columns - (tsclen + nmclen + argsclen + 20 + 11);
2988			} else
2989				clen = columns - (tsclen + nmclen + argsclen + 12);
2990
2991			if (clen > 0) {
2992				printf("%s", buf);   /* print the kdargs */
2993				memset(buf, ' ', clen);
2994				buf[clen] = '\0';
2995				printf("%s", buf);
2996			}
2997			else if ((argsclen + clen) > 0) {
2998				/*
2999				 * no room so wipe out the kdargs
3000				 */
3001				memset(buf, ' ', (argsclen + clen));
3002				buf[argsclen + clen] = '\0';
3003				printf("%s", buf);
3004			}
3005			if (columns > MAXCOLS || wideflag)
3006				printf("%s.%d\n", tme->tm_command, (int)thread);
3007			else
3008				printf("%-12.12s\n", tme->tm_command);
3009		} else
3010			printf("  %-24.24s (%5d, %#lx, 0x%lx, 0x%lx)\n",         name, (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
3011	}
3012}
3013
3014
3015void
3016enter_event(uintptr_t thread, int type, kd_buf *kd, char *name, double now)
3017{
3018	int index;
3019
3020	switch (type) {
3021
3022	case P_CS_SYNC_DISK:
3023	case MACH_pageout:
3024	case MACH_vmfault:
3025	case MSC_map_fd:
3026	case SPEC_ioctl:
3027	case Throttled:
3028	case HFS_update:
3029		enter_event_now(thread, type, kd, name, now);
3030		return;
3031
3032	}
3033	if ((type & CSC_MASK) == BSC_BASE) {
3034
3035		if ((index = BSC_INDEX(type)) >= MAX_BSD_SYSCALL)
3036			return;
3037
3038		if (bsd_syscalls[index].sc_name)
3039			enter_event_now(thread, type, kd, name, now);
3040		return;
3041	}
3042	if ((type & CLASS_MASK) == FILEMGR_BASE) {
3043
3044		if ((index = filemgr_index(type)) >= MAX_FILEMGR)
3045			return;
3046
3047		if (filemgr_calls[index].fm_name)
3048			enter_event_now(thread, type, kd, name, now);
3049		return;
3050	}
3051}
3052
3053/*
3054 * Handle system call extended trace data.
3055 * pread and pwrite:
3056 *     Wipe out the kd args that were collected upon syscall_entry
3057 *     because it is the extended info that we really want, and it
3058 *     is all we really need.
3059*/
3060
3061void
3062extend_syscall(uintptr_t thread, int type, kd_buf *kd)
3063{
3064	th_info_t	ti;
3065
3066	switch (type) {
3067	case BSC_mmap_extended:
3068	    if ((ti = find_event(thread, BSC_mmap)) == (struct th_info *)0)
3069		    return;
3070	    ti->arg8   = ti->arg3;  /* save protection */
3071	    ti->arg1   = kd->arg1;  /* the fd */
3072	    ti->arg3   = kd->arg2;  /* bottom half address */
3073	    ti->arg5   = kd->arg3;  /* bottom half size */
3074	    break;
3075	case BSC_mmap_extended2:
3076	    if ((ti = find_event(thread, BSC_mmap)) == (struct th_info *)0)
3077		    return;
3078	    ti->arg2   = kd->arg1;  /* top half address */
3079	    ti->arg4   = kd->arg2;  /* top half size */
3080	    ti->arg6   = kd->arg3;  /* top half file offset */
3081	    ti->arg7   = kd->arg4;  /* bottom half file offset */
3082	    break;
3083	case BSC_msync_extended:
3084	    if ((ti = find_event(thread, BSC_msync)) == (struct th_info *)0) {
3085		    if ((ti = find_event(thread, BSC_msync_nocancel)) == (struct th_info *)0)
3086			    return;
3087	    }
3088	    ti->arg4   = kd->arg1;  /* top half address */
3089	    ti->arg5   = kd->arg2;  /* top half size */
3090	    break;
3091	case BSC_pread_extended:
3092	    if ((ti = find_event(thread, BSC_pread)) == (struct th_info *)0) {
3093		    if ((ti = find_event(thread, BSC_pread_nocancel)) == (struct th_info *)0)
3094			    return;
3095	    }
3096	    ti->arg1   = kd->arg1;  /* the fd */
3097	    ti->arg2   = kd->arg2;  /* nbytes */
3098	    ti->arg3   = kd->arg3;  /* top half offset */
3099	    ti->arg4   = kd->arg4;  /* bottom half offset */
3100	    break;
3101	case BSC_pwrite_extended:
3102	    if ((ti = find_event(thread, BSC_pwrite)) == (struct th_info *)0) {
3103		    if ((ti = find_event(thread, BSC_pwrite_nocancel)) == (struct th_info *)0)
3104			    return;
3105	    }
3106	    ti->arg1   = kd->arg1;  /* the fd */
3107	    ti->arg2   = kd->arg2;  /* nbytes */
3108	    ti->arg3   = kd->arg3;  /* top half offset */
3109	    ti->arg4   = kd->arg4;  /* bottom half offset */
3110	    break;
3111	default:
3112	    return;
3113       }
3114}
3115
3116
3117void
3118exit_event(char *sc_name, uintptr_t thread, int type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4,
3119	   int format, double now)
3120{
3121        th_info_t	ti;
3122
3123	if ((ti = find_event(thread, type)) == (struct th_info *)0)
3124	        return;
3125
3126	ti->nameptr = 0;
3127
3128	if (check_filter_mode(ti, type, arg1, arg2, sc_name))
3129	        format_print(ti, sc_name, thread, type, arg1, arg2, arg3, arg4, format, now, ti->stime, ti->waited, (char *)&ti->lookups[0].pathname[0], NULL);
3130
3131	switch (type) {
3132
3133	case HFS_update:
3134		ti->in_hfs_update = 0;
3135		break;
3136	}
3137	if ((type & CLASS_MASK) == FILEMGR_BASE) {
3138	        ti->in_filemgr = 0;
3139
3140		if (filemgr_in_progress > 0)
3141		        filemgr_in_progress--;
3142	}
3143	delete_event(ti);
3144}
3145
3146
3147void
3148get_mode_nibble(char * buf, int smode, int special, char x_on, char x_off)
3149{
3150        if (smode & 04)
3151	        buf[0] = 'r';
3152        if (smode & 02)
3153	        buf[1] = 'w';
3154	if (smode & 01) {
3155	        if (special)
3156		        buf[2] = x_on;
3157		else
3158		        buf[2] = 'x';
3159	} else {
3160	        if (special)
3161		        buf[2] = x_off;
3162	}
3163}
3164
3165
3166void
3167get_mode_string(int mode, char *buf)
3168{
3169        memset(buf, '-', 9);
3170	buf[9] = '\0';
3171
3172	get_mode_nibble(&buf[6], mode, (mode & 01000), 't', 'T');
3173	get_mode_nibble(&buf[3], (mode>>3), (mode & 02000), 's', 'S');
3174	get_mode_nibble(&buf[0], (mode>>6), (mode & 04000), 's', 'S');
3175}
3176
3177
3178int clip_64bit(char *s, uint64_t value)
3179{
3180        int clen = 0;
3181
3182	if ( (value & 0xff00000000000000LL) )
3183	        clen = printf("%s0x%16.16qx", s, value);
3184	else if ( (value & 0x00ff000000000000LL) )
3185	        clen = printf("%s0x%14.14qx  ", s, value);
3186	else if ( (value & 0x0000ff0000000000LL) )
3187	        clen = printf("%s0x%12.12qx    ", s, value);
3188	else if ( (value & 0x000000ff00000000LL) )
3189	        clen = printf("%s0x%10.10qx      ", s, value);
3190	else
3191	        clen = printf("%s0x%8.8qx        ", s, value);
3192
3193	return (clen);
3194}
3195
3196
3197void
3198format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4,
3199	     int format, double now, double stime, int waited, char *pathname, struct diskio *dio)
3200{
3201        int secs;
3202	int usecs;
3203	int nopadding = 0;
3204	long long l_usecs;
3205	long curr_time;
3206	char *command_name;
3207	int in_filemgr = 0;
3208	int len = 0;
3209	int clen = 0;
3210	int tlen = 0;
3211	int class;
3212	uint64_t user_addr;
3213	uint64_t user_size;
3214	char *framework_name;
3215	char *framework_type;
3216	char *p1;
3217	char *p2;
3218	char buf[MAXWIDTH];
3219	char cs_diskname[32];
3220
3221	static char timestamp[32];
3222	static int  last_timestamp = -1;
3223	static int  timestamp_len = 0;
3224
3225	command_name = "";
3226
3227	if (RAW_flag) {
3228		l_usecs = (long long)((now - bias_now) / divisor);
3229
3230		if ((double)l_usecs < start_time || (double)l_usecs > end_time)
3231			return;
3232
3233		l_usecs += (sample_TOD_secs * 1000000) + sample_TOD_usecs;
3234	}
3235	else
3236		l_usecs = (long long)(now / divisor);
3237	secs = l_usecs / 1000000;
3238	curr_time = bias_secs + secs;
3239
3240	class = type >> 24;
3241
3242	if (dio)
3243	        command_name = dio->issuing_command;
3244	else {
3245		threadmap_t	tme;
3246
3247		if ((tme = find_map_entry(thread)))
3248		        command_name = tme->tm_command;
3249	}
3250	if (last_timestamp != curr_time) {
3251	        timestamp_len = sprintf(timestamp, "%-8.8s", &(ctime(&curr_time)[11]));
3252		last_timestamp = curr_time;
3253	}
3254	if (columns > MAXCOLS || wideflag) {
3255	        int usec;
3256
3257		tlen = timestamp_len;
3258		nopadding = 0;
3259		usec = (l_usecs - (long long)((long long)secs * 1000000));
3260
3261		sprintf(&timestamp[tlen], ".%06ld", (long)usec);
3262		tlen += 7;
3263
3264		timestamp[tlen] = '\0';
3265
3266		if (filemgr_in_progress) {
3267		        if (class != FILEMGR_CLASS) {
3268			        if (find_event(thread, -1))
3269				        in_filemgr = 1;
3270			}
3271		}
3272	} else
3273	        nopadding = 1;
3274
3275	if ((class == FILEMGR_CLASS) && (columns > MAXCOLS || wideflag))
3276	        clen = printf("%s  %-20.20s", timestamp, sc_name);
3277	else if (in_filemgr)
3278	        clen = printf("%s    %-15.15s", timestamp, sc_name);
3279	else
3280	        clen = printf("%s  %-17.17s", timestamp, sc_name);
3281
3282
3283	framework_name = NULL;
3284
3285	if (columns > MAXCOLS || wideflag) {
3286
3287	        off_t offset_reassembled = 0LL;
3288
3289		switch (format) {
3290
3291		      case FMT_DEFAULT:
3292			/*
3293			 * pathname based system calls or
3294			 * calls with no fd or pathname (i.e.  sync)
3295			 */
3296			if (arg1)
3297			        clen += printf("      [%3d]       ", arg1);
3298			else
3299			        clen += printf("                  ");
3300			break;
3301
3302		      case FMT_FD:
3303			/*
3304			 * fd based system call... no I/O
3305			 */
3306			if (arg1)
3307			        clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3308			else
3309			        clen += printf(" F=%-3d", ti->arg1);
3310			break;
3311
3312		      case FMT_FD_2:
3313			/*
3314			 * accept, dup, dup2
3315			 */
3316			if (arg1)
3317			        clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3318			else
3319			        clen += printf(" F=%-3d  F=%-3d", ti->arg1, arg2);
3320			break;
3321
3322		      case FMT_FD_IO:
3323			/*
3324			 * system calls with fd's that return an I/O completion count
3325			 */
3326			if (arg1)
3327			        clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3328			else
3329			        clen += printf(" F=%-3d  B=0x%-6x", ti->arg1, arg2);
3330			break;
3331
3332		      case FMT_PGIN:
3333			/*
3334			 * pagein
3335			 */
3336			user_addr = ((uint64_t)arg2 << 32) | (uint32_t)arg3;
3337
3338		        lookup_name(user_addr, &framework_type, &framework_name);
3339			clen += clip_64bit(" A=", user_addr);
3340			break;
3341
3342		      case FMT_CACHEHIT:
3343			/*
3344			 * cache hit
3345			 */
3346			user_addr = ((uint64_t)arg2 << 32) | (uint32_t)arg3;
3347
3348		        lookup_name(user_addr, &framework_type, &framework_name);
3349			clen += clip_64bit(" A=", user_addr);
3350			break;
3351
3352		      case FMT_PGOUT:
3353			/*
3354			 * pageout
3355			 */
3356		        clen += printf("      B=0x%-8x", arg2);
3357			break;
3358
3359		      case FMT_HFS_update:
3360		      {
3361			char sbuf[7];
3362			int  sflag = (int)arg2;
3363
3364			memset(sbuf, '_', 6);
3365			sbuf[6] = '\0';
3366
3367
3368			if (sflag & 0x10)
3369				sbuf[0] = 'F';
3370			if (sflag & 0x08)
3371				sbuf[1] = 'M';
3372			if (sflag & 0x20)
3373				sbuf[2] = 'D';
3374			if (sflag & 0x04)
3375				sbuf[3] = 'c';
3376			if (sflag & 0x01)
3377				sbuf[4] = 'a';
3378			if (sflag & 0x02)
3379				sbuf[5] = 'm';
3380
3381			clen += printf("            (%s) ", sbuf);
3382
3383			pathname = find_vnode_name(arg1);
3384			nopadding = 1;
3385
3386			break;
3387		      }
3388
3389		      case FMT_DISKIO:
3390		        /*
3391			 * physical disk I/O
3392			 */
3393		        if (dio->io_errno)
3394			        clen += printf(" D=0x%8.8x  [%3d]", dio->blkno, dio->io_errno);
3395			else {
3396 				if (BC_flag)
3397 					clen += printf(" D=0x%8.8x  B=0x%-6x BC:%s /dev/%s ", dio->blkno, dio->iosize, BC_STR(dio->bc_info), find_disk_name(dio->dev));
3398 				else
3399 					clen += printf(" D=0x%8.8x  B=0x%-6x /dev/%s ", dio->blkno, dio->iosize, find_disk_name(dio->dev));
3400
3401				if (dio->is_meta)
3402				        pathname = find_meta_name(dio->blkno);
3403				else
3404				        pathname = find_vnode_name(dio->vnodeid);
3405				nopadding = 1;
3406			}
3407			break;
3408
3409		      case FMT_DISKIO_CS:
3410		        /*
3411			 * physical disk I/O
3412			 */
3413		        if (dio->io_errno)
3414			        clen += printf(" D=0x%8.8x  [%3d]", dio->blkno, dio->io_errno);
3415			else
3416			        clen += printf(" D=0x%8.8x  B=0x%-6x /dev/%s", dio->blkno, dio->iosize, generate_cs_disk_name(dio->dev, &cs_diskname[0]));
3417			break;
3418
3419		      case FMT_SYNC_DISK_CS:
3420		        /*
3421			 * physical disk sync cache
3422			 */
3423			clen += printf("                          /dev/%s", generate_cs_disk_name(arg1, &cs_diskname[0]));
3424
3425			break;
3426
3427		      case FMT_MSYNC:
3428		      {
3429			/*
3430			 * msync
3431			 */
3432			int  mlen = 0;
3433
3434			buf[0] = '\0';
3435
3436			if (ti->arg3 & MS_ASYNC)
3437			        mlen += sprintf(&buf[mlen], "MS_ASYNC | ");
3438			else
3439			        mlen += sprintf(&buf[mlen], "MS_SYNC | ");
3440
3441			if (ti->arg3 & MS_INVALIDATE)
3442			        mlen += sprintf(&buf[mlen], "MS_INVALIDATE | ");
3443			if (ti->arg3 & MS_KILLPAGES)
3444			        mlen += sprintf(&buf[mlen], "MS_KILLPAGES | ");
3445			if (ti->arg3 & MS_DEACTIVATE)
3446			        mlen += sprintf(&buf[mlen], "MS_DEACTIVATE | ");
3447
3448			if (ti->arg3 & ~(MS_ASYNC | MS_SYNC | MS_INVALIDATE | MS_KILLPAGES | MS_DEACTIVATE))
3449			        mlen += sprintf(&buf[mlen], "UNKNOWN | ");
3450
3451			if (mlen)
3452			        buf[mlen - 3] = '\0';
3453
3454			if (arg1)
3455			        clen += printf("      [%3d]", arg1);
3456
3457			user_addr = (((off_t)(unsigned int)(ti->arg4)) << 32) | (unsigned int)(ti->arg1);
3458			clen += clip_64bit(" A=", user_addr);
3459
3460			user_size = (((off_t)(unsigned int)(ti->arg5)) << 32) | (unsigned int)(ti->arg2);
3461
3462		        clen += printf("  B=0x%-16qx  <%s>", user_size, buf);
3463
3464			break;
3465		      }
3466
3467		      case FMT_FLOCK:
3468		      {
3469			/*
3470			 * flock
3471			 */
3472			int  mlen = 0;
3473
3474			buf[0] = '\0';
3475
3476			if (ti->arg2 & LOCK_SH)
3477			        mlen += sprintf(&buf[mlen], "LOCK_SH | ");
3478			if (ti->arg2 & LOCK_EX)
3479			        mlen += sprintf(&buf[mlen], "LOCK_EX | ");
3480			if (ti->arg2 & LOCK_NB)
3481			        mlen += sprintf(&buf[mlen], "LOCK_NB | ");
3482			if (ti->arg2 & LOCK_UN)
3483			        mlen += sprintf(&buf[mlen], "LOCK_UN | ");
3484
3485			if (ti->arg2 & ~(LOCK_SH | LOCK_EX | LOCK_NB | LOCK_UN))
3486			        mlen += sprintf(&buf[mlen], "UNKNOWN | ");
3487
3488			if (mlen)
3489			        buf[mlen - 3] = '\0';
3490
3491			if (arg1)
3492			        clen += printf(" F=%-3d[%3d]  <%s>", ti->arg1, arg1, buf);
3493			else
3494			        clen += printf(" F=%-3d  <%s>", ti->arg1, buf);
3495
3496			break;
3497		      }
3498
3499		      case FMT_FCNTL:
3500		      {
3501			/*
3502			 * fcntl
3503			 */
3504			char *p = NULL;
3505			int  fd = -1;
3506
3507			if (arg1)
3508			        clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3509			else
3510			        clen += printf(" F=%-3d", ti->arg1);
3511
3512			switch(ti->arg2) {
3513
3514			case F_DUPFD:
3515			  p = "DUPFD";
3516			  break;
3517
3518			case F_GETFD:
3519			  p = "GETFD";
3520			  break;
3521
3522			case F_SETFD:
3523			  p = "SETFD";
3524			  break;
3525
3526			case F_GETFL:
3527			  p = "GETFL";
3528			  break;
3529
3530			case F_SETFL:
3531			  p = "SETFL";
3532			  break;
3533
3534			case F_GETOWN:
3535			  p = "GETOWN";
3536			  break;
3537
3538			case F_SETOWN:
3539			  p = "SETOWN";
3540			  break;
3541
3542			case F_GETLK:
3543			  p = "GETLK";
3544			  break;
3545
3546			case F_SETLK:
3547			  p = "SETLK";
3548			  break;
3549
3550			case F_SETLKW:
3551			  p = "SETLKW";
3552			  break;
3553
3554			case F_PREALLOCATE:
3555			  p = "PREALLOCATE";
3556			  break;
3557
3558			case F_SETSIZE:
3559			  p = "SETSIZE";
3560			  break;
3561
3562			case F_RDADVISE:
3563			  p = "RDADVISE";
3564			  break;
3565
3566			case F_GETPATH:
3567			  p = "GETPATH";
3568			  break;
3569
3570			case F_FULLFSYNC:
3571			  p = "FULLFSYNC";
3572			  break;
3573
3574			case F_PATHPKG_CHECK:
3575			  p = "PATHPKG_CHECK";
3576			  break;
3577
3578			case F_OPENFROM:
3579			  p = "OPENFROM";
3580
3581			  if (arg1 == 0)
3582				  fd = arg2;
3583			  break;
3584
3585			case F_UNLINKFROM:
3586			  p = "UNLINKFROM";
3587			  break;
3588
3589			case F_CHECK_OPENEVT:
3590			  p = "CHECK_OPENEVT";
3591			  break;
3592
3593			case F_NOCACHE:
3594			  if (ti->arg3)
3595			          p = "CACHING OFF";
3596			  else
3597			          p = "CACHING ON";
3598			  break;
3599
3600			case F_GLOBAL_NOCACHE:
3601			  if (ti->arg3)
3602			          p = "CACHING OFF (GLOBAL)";
3603			  else
3604			          p = "CACHING ON (GLOBAL)";
3605			  break;
3606
3607			}
3608			if (p) {
3609				if (fd == -1)
3610					clen += printf(" <%s>", p);
3611				else
3612					clen += printf(" <%s> F=%d", p, fd);
3613			} else
3614			        clen += printf(" <CMD=%d>", ti->arg2);
3615
3616			break;
3617		      }
3618
3619		      case FMT_IOCTL:
3620		      {
3621			/*
3622			 * ioctl
3623			 */
3624			if (arg1)
3625			        clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3626			else
3627			        clen += printf(" F=%-3d", ti->arg1);
3628
3629		        clen += printf(" <CMD=0x%x>", ti->arg2);
3630
3631			break;
3632		      }
3633
3634		      case FMT_IOCTL_SYNC:
3635		      {
3636			/*
3637			 * ioctl
3638			 */
3639			clen += printf(" <DKIOCSYNCHRONIZECACHE>  /dev/%s", find_disk_name(arg1));
3640
3641			break;
3642		      }
3643
3644		      case FMT_IOCTL_UNMAP:
3645		      {
3646			/*
3647			 * ioctl
3648			 */
3649			clen += printf(" <DKIOCUNMAP>             /dev/%s", find_disk_name(arg1));
3650
3651			break;
3652		      }
3653
3654		      case FMT_UNMAP_INFO:
3655		      {
3656			clen += printf(" D=0x%8.8x  B=0x%-6x /dev/%s", arg2, arg3, find_disk_name(arg1));
3657
3658			break;
3659		      }
3660
3661		      case FMT_SELECT:
3662			/*
3663			 * select
3664			 */
3665			if (arg1)
3666			        clen += printf("      [%3d]", arg1);
3667			else
3668			        clen += printf("        S=%-3d", arg2);
3669
3670			break;
3671
3672		      case FMT_LSEEK:
3673		      case FMT_PREAD:
3674			/*
3675			 * pread, pwrite, lseek
3676			 */
3677			clen += printf(" F=%-3d", ti->arg1);
3678
3679			if (arg1)
3680			        clen += printf("[%3d]  ", arg1);
3681			else {
3682			        if (format == FMT_PREAD)
3683				        clen += printf("  B=0x%-8x ", arg2);
3684				else
3685				        clen += printf("  ");
3686			}
3687			if (format == FMT_PREAD)
3688			        offset_reassembled = (((off_t)(unsigned int)(ti->arg3)) << 32) | (unsigned int)(ti->arg4);
3689			else
3690#ifdef __ppc__
3691			        offset_reassembled = (((off_t)(unsigned int)(arg2)) << 32) | (unsigned int)(arg3);
3692#else
3693			        offset_reassembled = (((off_t)(unsigned int)(arg3)) << 32) | (unsigned int)(arg2);
3694#endif
3695			clen += clip_64bit("O=", offset_reassembled);
3696
3697			if (format == FMT_LSEEK) {
3698			        char *mode;
3699
3700				if (ti->arg4 == SEEK_SET)
3701				        mode = "SEEK_SET";
3702				else if (ti->arg4 == SEEK_CUR)
3703				        mode = "SEEK_CUR";
3704				else if (ti->arg4 == SEEK_END)
3705				        mode = "SEEK_END";
3706				else
3707				        mode = "UNKNOWN";
3708
3709				clen += printf(" <%s>", mode);
3710			}
3711			break;
3712
3713		      case FMT_MMAP:
3714			/*
3715			 * mmap
3716			 */
3717			clen += printf(" F=%-3d  ", ti->arg1);
3718
3719			if (arg1)
3720			        clen += printf("[%3d]  ", arg1);
3721			else {
3722
3723			        user_addr = (((off_t)(unsigned int)(ti->arg2)) << 32) | (unsigned int)(ti->arg3);
3724
3725				clen += clip_64bit("A=", user_addr);
3726
3727			        offset_reassembled = (((off_t)(unsigned int)(ti->arg6)) << 32) | (unsigned int)(ti->arg7);
3728
3729				clen += clip_64bit("O=", offset_reassembled);
3730
3731			        user_size = (((off_t)(unsigned int)(ti->arg4)) << 32) | (unsigned int)(ti->arg5);
3732
3733				clen += printf("B=0x%-16qx", user_size);
3734
3735				clen += printf(" <");
3736
3737				if (ti->arg8 & PROT_READ)
3738				        clen += printf("READ");
3739
3740				if (ti->arg8 & PROT_WRITE)
3741				        clen += printf("|WRITE");
3742
3743				if (ti->arg8 & PROT_EXEC)
3744				        clen += printf("|EXEC");
3745
3746				clen += printf(">");
3747			}
3748			break;
3749
3750		      case FMT_TRUNC:
3751		      case FMT_FTRUNC:
3752			/*
3753			 * ftruncate, truncate
3754			 */
3755			if (format == FMT_FTRUNC)
3756			        clen += printf(" F=%-3d", ti->arg1);
3757			else
3758			        clen += printf("      ");
3759
3760			if (arg1)
3761			        clen += printf("[%3d]", arg1);
3762
3763#ifdef __ppc__
3764			offset_reassembled = (((off_t)(unsigned int)(ti->arg2)) << 32) | (unsigned int)(ti->arg3);
3765#else
3766			offset_reassembled = (((off_t)(unsigned int)(ti->arg3)) << 32) | (unsigned int)(ti->arg2);
3767#endif
3768			clen += clip_64bit("  O=", offset_reassembled);
3769
3770			nopadding = 1;
3771			break;
3772
3773		      case FMT_FCHFLAGS:
3774		      case FMT_CHFLAGS:
3775		      {
3776			/*
3777			 * fchflags, chflags
3778			 */
3779			int mlen = 0;
3780
3781			if (format == FMT_FCHFLAGS) {
3782			        if (arg1)
3783				        clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3784				else
3785				        clen += printf(" F=%-3d", ti->arg1);
3786			} else {
3787			        if (arg1)
3788				        clen += printf(" [%3d] ", arg1);
3789			}
3790			buf[mlen++] = ' ';
3791			buf[mlen++] = '<';
3792
3793			if (ti->arg2 & UF_NODUMP)
3794			        mlen += sprintf(&buf[mlen], "UF_NODUMP | ");
3795			if (ti->arg2 & UF_IMMUTABLE)
3796			        mlen += sprintf(&buf[mlen], "UF_IMMUTABLE | ");
3797			if (ti->arg2 & UF_APPEND)
3798			        mlen += sprintf(&buf[mlen], "UF_APPEND | ");
3799			if (ti->arg2 & UF_OPAQUE)
3800			        mlen += sprintf(&buf[mlen], "UF_OPAQUE | ");
3801			if (ti->arg2 & SF_ARCHIVED)
3802			        mlen += sprintf(&buf[mlen], "SF_ARCHIVED | ");
3803			if (ti->arg2 & SF_IMMUTABLE)
3804			        mlen += sprintf(&buf[mlen], "SF_IMMUTABLE | ");
3805			if (ti->arg2 & SF_APPEND)
3806			        mlen += sprintf(&buf[mlen], "SF_APPEND | ");
3807
3808			if (ti->arg2 == 0)
3809			        mlen += sprintf(&buf[mlen], "CLEAR_ALL_FLAGS | ");
3810			else if (ti->arg2 & ~(UF_NODUMP | UF_IMMUTABLE | UF_APPEND | SF_ARCHIVED | SF_IMMUTABLE | SF_APPEND))
3811			        mlen += sprintf(&buf[mlen], "UNKNOWN | ");
3812
3813			if (mlen >= 3)
3814			        mlen -= 3;
3815
3816			buf[mlen++] = '>';
3817			buf[mlen] = '\0';
3818
3819			if (mlen < 19) {
3820			        memset(&buf[mlen], ' ', 19 - mlen);
3821				mlen = 19;
3822			}
3823			clen += printf("%s", buf);
3824
3825			nopadding = 1;
3826			break;
3827		      }
3828
3829		      case FMT_UMASK:
3830		      case FMT_FCHMOD:
3831		      case FMT_FCHMOD_EXT:
3832		      case FMT_CHMOD:
3833		      case FMT_CHMOD_EXT:
3834		      {
3835			/*
3836			 * fchmod, fchmod_extended, chmod, chmod_extended
3837			 */
3838			int  mode;
3839
3840			if (format == FMT_FCHMOD || format == FMT_FCHMOD_EXT) {
3841			        if (arg1)
3842				        clen += printf(" F=%-3d[%3d] ", ti->arg1, arg1);
3843				else
3844				        clen += printf(" F=%-3d ", ti->arg1);
3845			} else {
3846			        if (arg1)
3847				        clen += printf(" [%3d] ", arg1);
3848				else
3849				        clen += printf(" ");
3850			}
3851			if (format == FMT_UMASK)
3852				mode = ti->arg1;
3853			else if (format == FMT_FCHMOD || format == FMT_CHMOD)
3854			        mode = ti->arg2;
3855			else
3856			        mode = ti->arg4;
3857
3858			get_mode_string(mode, &buf[0]);
3859
3860			if (arg1 == 0)
3861			        clen += printf("<%s>      ", buf);
3862			else
3863			        clen += printf("<%s>", buf);
3864			break;
3865		      }
3866
3867		      case FMT_ACCESS:
3868		      {
3869			/*
3870			 * access
3871			 */
3872			char mode[5];
3873
3874			memset(mode, '_', 4);
3875			mode[4] = '\0';
3876
3877			if (ti->arg2 & R_OK)
3878			        mode[0] = 'R';
3879			if (ti->arg2 & W_OK)
3880			        mode[1] = 'W';
3881			if (ti->arg2 & X_OK)
3882			        mode[2] = 'X';
3883			if (ti->arg2 == F_OK)
3884			        mode[3] = 'F';
3885
3886		        if (arg1)
3887			        clen += printf("      [%3d] (%s)   ", arg1, mode);
3888			else
3889			        clen += printf("            (%s)   ", mode);
3890
3891			nopadding = 1;
3892			break;
3893		      }
3894
3895		      case FMT_MOUNT:
3896		      {
3897			      if (arg1)
3898				      clen += printf("      [%3d] <FLGS=0x%x> ", arg1, ti->arg3);
3899			      else
3900				      clen += printf("     <FLGS=0x%x> ", ti->arg3);
3901
3902			      nopadding = 1;
3903			      break;
3904		      }
3905
3906		      case FMT_UNMOUNT:
3907		      {
3908			      char *mountflag;
3909
3910			      if (ti->arg2 & MNT_FORCE)
3911				      mountflag = "<FORCE>";
3912			      else
3913				      mountflag = "";
3914
3915			      if (arg1)
3916				      clen += printf("      [%3d] %s  ", arg1, mountflag);
3917			      else
3918				      clen += printf("     %s         ", mountflag);
3919
3920			      nopadding = 1;
3921			      break;
3922		      }
3923
3924		      case FMT_OPEN:
3925		      {
3926			/*
3927			 * open
3928			 */
3929		        char mode[7];
3930
3931			memset(mode, '_', 6);
3932			mode[6] = '\0';
3933
3934			if (ti->arg2 & O_RDWR) {
3935			        mode[0] = 'R';
3936			        mode[1] = 'W';
3937			} else if (ti->arg2 & O_WRONLY)
3938			        mode[1] = 'W';
3939			else
3940			        mode[0] = 'R';
3941
3942			if (ti->arg2 & O_CREAT)
3943			        mode[2] = 'C';
3944
3945			if (ti->arg2 & O_APPEND)
3946			        mode[3] = 'A';
3947
3948			if (ti->arg2 & O_TRUNC)
3949			        mode[4] = 'T';
3950
3951			if (ti->arg2 & O_EXCL)
3952			        mode[5] = 'E';
3953
3954		        if (arg1)
3955			        clen += printf("      [%3d] (%s) ", arg1, mode);
3956			else
3957			        clen += printf(" F=%-3d      (%s) ", arg2, mode);
3958
3959			nopadding = 1;
3960			break;
3961		      }
3962
3963		      case FMT_SOCKET:
3964		      {
3965			/*
3966			 * socket
3967			 *
3968			 */
3969			char *domain;
3970			char *type;
3971
3972			switch (ti->arg1) {
3973
3974			case AF_UNIX:
3975			  domain = "AF_UNIX";
3976			  break;
3977
3978			case AF_INET:
3979			  domain = "AF_INET";
3980			  break;
3981
3982			case AF_ISO:
3983			  domain = "AF_ISO";
3984			  break;
3985
3986			case AF_NS:
3987			  domain = "AF_NS";
3988			  break;
3989
3990			case AF_IMPLINK:
3991			  domain = "AF_IMPLINK";
3992			  break;
3993
3994			default:
3995			  domain = "UNKNOWN";
3996			  break;
3997			}
3998
3999			switch (ti->arg2) {
4000
4001			case SOCK_STREAM:
4002			  type = "SOCK_STREAM";
4003			  break;
4004
4005			case SOCK_DGRAM:
4006			  type = "SOCK_DGRAM";
4007			  break;
4008
4009			case SOCK_RAW:
4010			  type = "SOCK_RAW";
4011			  break;
4012
4013			case SOCK_SEQPACKET:
4014			  type = "SOCK_SEQPACKET";
4015			  break;
4016
4017			case SOCK_RDM:
4018			  type = "SOCK_RDM";
4019			  break;
4020
4021			default:
4022			  type = "UNKNOWN";
4023			  break;
4024			}
4025
4026			if (arg1)
4027			        clen += printf("      [%3d] <%s, %s, 0x%x>", arg1, domain, type, ti->arg3);
4028			else
4029			        clen += printf(" F=%-3d      <%s, %s, 0x%x>", arg2, domain, type, ti->arg3);
4030			break;
4031		      }
4032
4033		      case FMT_AIO_FSYNC:
4034		      {
4035			/*
4036			 * aio_fsync		[errno]   AIOCBP   OP
4037			 */
4038			char *op;
4039
4040			if (ti->arg1 == O_SYNC || ti->arg1 == 0)
4041			        op = "AIO_FSYNC";
4042#if O_DSYNC
4043			else if (ti->arg1 == O_DSYNC)
4044			        op = "AIO_DSYNC";
4045#endif
4046			else
4047			        op = "UNKNOWN";
4048
4049			if (arg1)
4050			        clen += printf("      [%3d] P=0x%8.8x  <%s>", arg1, ti->arg2, op);
4051			else
4052			        clen += printf("            P=0x%8.8x  <%s>", ti->arg2, op);
4053			break;
4054		      }
4055
4056		      case FMT_AIO_RETURN:
4057			/*
4058			 * aio_return		[errno]   AIOCBP   IOSIZE
4059			 */
4060			if (arg1)
4061			        clen += printf("      [%3d] P=0x%8.8x", arg1, ti->arg1);
4062			else
4063			        clen += printf("            P=0x%8.8x  B=0x%-8x", ti->arg1, arg2);
4064			break;
4065
4066		      case FMT_AIO_SUSPEND:
4067			/*
4068			 * aio_suspend		[errno]   NENTS
4069			 */
4070			if (arg1)
4071			        clen += printf("      [%3d] N=%d", arg1, ti->arg2);
4072			else
4073			        clen += printf("            N=%d", ti->arg2);
4074			break;
4075
4076		      case FMT_AIO_CANCEL:
4077			/*
4078			 * aio_cancel	  	[errno]   FD or AIOCBP (if non-null)
4079			 */
4080			if (ti->arg2) {
4081			        if (arg1)
4082				        clen += printf("      [%3d] P=0x%8.8x", arg1, ti->arg2);
4083				else
4084				        clen += printf("            P=0x%8.8x", ti->arg2);
4085			} else {
4086			        if (arg1)
4087				        clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
4088				else
4089				        clen += printf(" F=%-3d", ti->arg1);
4090			}
4091			break;
4092
4093		      case FMT_AIO:
4094			/*
4095			 * aio_error, aio_read, aio_write	[errno]  AIOCBP
4096			 */
4097			if (arg1)
4098			        clen += printf("      [%3d] P=0x%8.8x", arg1, ti->arg1);
4099			else
4100			        clen += printf("            P=0x%8.8x", ti->arg1);
4101			break;
4102
4103		      case FMT_LIO_LISTIO:
4104		      {
4105			/*
4106			 * lio_listio		[errno]   NENTS  MODE
4107			 */
4108			char *op;
4109
4110			if (ti->arg1 == LIO_NOWAIT)
4111			        op = "LIO_NOWAIT";
4112			else if (ti->arg1 == LIO_WAIT)
4113			        op = "LIO_WAIT";
4114			else
4115			        op = "UNKNOWN";
4116
4117			if (arg1)
4118			        clen += printf("      [%3d] N=%d  <%s>", arg1, ti->arg3, op);
4119			else
4120			        clen += printf("            N=%d  <%s>", ti->arg3, op);
4121			break;
4122		      }
4123
4124		}
4125	}
4126
4127	/*
4128	 * Calculate space available to print pathname
4129	 */
4130	if (columns > MAXCOLS || wideflag)
4131	        clen =  columns - (clen + 14 + 20 + 11);
4132	else
4133	        clen =  columns - (clen + 14 + 12);
4134
4135	if (class != FILEMGR_CLASS && !nopadding)
4136	        clen -= 3;
4137
4138	if (framework_name)
4139	        len = sprintf(&buf[0], " %s %s ", framework_type, framework_name);
4140	else if (*pathname != '\0') {
4141	        len = sprintf(&buf[0], " %s ", pathname);
4142
4143		if (format == FMT_MOUNT && ti->lookups[1].pathname[0]) {
4144			int	len2;
4145
4146			memset(&buf[len], ' ', 2);
4147
4148			len2 = sprintf(&buf[len+2], " %s ", (char *)&ti->lookups[1].pathname[0]);
4149			len = len + 2 + len2;
4150		}
4151	} else
4152	        len = 0;
4153
4154	if (clen > len) {
4155	        /*
4156		 * Add null padding if column length
4157		 * is wider than the pathname length.
4158		 */
4159	        memset(&buf[len], ' ', clen - len);
4160		buf[clen] = '\0';
4161
4162		pathname = buf;
4163
4164	} else if (clen == len) {
4165	        pathname = buf;
4166
4167	} else if ((clen > 0) && (clen < len)) {
4168	        /*
4169		 * This prints the tail end of the pathname
4170		 */
4171	        buf[len-clen] = ' ';
4172
4173		pathname = &buf[len - clen];
4174
4175	} else {
4176	        pathname = "";
4177	}
4178
4179	/*
4180	 * fudge some additional system call overhead
4181	 * that currently isn't tracked... this also
4182	 * insures that we see a minimum of 1 us for
4183	 * an elapsed time
4184	 */
4185	usecs = (unsigned long)(((now - stime) + (divisor-1)) / divisor);
4186	secs = usecs / 1000000;
4187	usecs -= secs * 1000000;
4188
4189	if (class != FILEMGR_CLASS && !nopadding)
4190	        p1 = "   ";
4191	else
4192	        p1 = "";
4193
4194	if (waited)
4195	        p2 = " W";
4196	else
4197	        p2 = "  ";
4198
4199	if (columns > MAXCOLS || wideflag)
4200	        printf("%s%s %3ld.%06ld%s %s.%d\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name, (int)thread);
4201	else
4202	        printf("%s%s %3ld.%06ld%s %-12.12s\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name);
4203}
4204
4205
4206void
4207add_meta_name(uint64_t blockno, char *pathname) {
4208	meta_info_t	mi;
4209	int		hashid;
4210
4211	hashid = blockno & VN_HASH_MASK;
4212
4213	for (mi = m_info_hash[hashid]; mi; mi = mi->m_next) {
4214		if (mi->m_blkno == blockno)
4215			break;
4216	}
4217	if (mi == NULL) {
4218		mi = (meta_info_t)malloc(sizeof(struct meta_info));
4219
4220		mi->m_next = m_info_hash[hashid];
4221		m_info_hash[hashid] = mi;
4222		mi->m_blkno = blockno;
4223	}
4224	mi->m_nameptr = pathname;
4225}
4226
4227char *
4228find_meta_name(uint64_t blockno) {
4229	meta_info_t	mi;
4230	int		hashid;
4231
4232	hashid = blockno & VN_HASH_MASK;
4233
4234	for (mi = m_info_hash[hashid]; mi; mi = mi->m_next) {
4235		if (mi->m_blkno == blockno)
4236			return (mi->m_nameptr);
4237	}
4238	return ("");
4239}
4240
4241
4242char *
4243add_vnode_name(uint64_t vn_id, char *pathname) {
4244	vnode_info_t	vn;
4245	int		hashid;
4246
4247	hashid = (vn_id >> VN_HASH_SHIFT) & VN_HASH_MASK;
4248
4249	for (vn = vn_info_hash[hashid]; vn; vn = vn->vn_next) {
4250		if (vn->vn_id == vn_id)
4251			break;
4252	}
4253	if (vn == NULL) {
4254		vn = (vnode_info_t)malloc(sizeof(struct vnode_info));
4255
4256		vn->vn_next = vn_info_hash[hashid];
4257		vn_info_hash[hashid] = vn;
4258		vn->vn_id = vn_id;
4259	}
4260	strcpy(vn->vn_pathname, pathname);
4261
4262	return (&vn->vn_pathname);
4263}
4264
4265
4266char *
4267find_vnode_name(uint64_t vn_id) {
4268	vnode_info_t	vn;
4269	int		hashid;
4270
4271	hashid = (vn_id >> VN_HASH_SHIFT) & VN_HASH_MASK;
4272
4273	for (vn = vn_info_hash[hashid]; vn; vn = vn->vn_next) {
4274		if (vn->vn_id == vn_id)
4275			return (vn->vn_pathname);
4276	}
4277	return ("");
4278}
4279
4280
4281void
4282delete_event(th_info_t ti_to_delete) {
4283	th_info_t	ti;
4284	th_info_t	ti_prev;
4285	int		hashid;
4286
4287	hashid = ti_to_delete->thread & HASH_MASK;
4288
4289	if ((ti = th_info_hash[hashid])) {
4290		if (ti == ti_to_delete)
4291			th_info_hash[hashid] = ti->next;
4292                else {
4293                        ti_prev = ti;
4294
4295			for (ti = ti->next; ti; ti = ti->next) {
4296                                if (ti == ti_to_delete) {
4297					ti_prev->next = ti->next;
4298                                        break;
4299                                }
4300                                ti_prev = ti;
4301			}
4302                }
4303                if (ti) {
4304                        ti->next = th_info_freelist;
4305                        th_info_freelist = ti;
4306                }
4307        }
4308}
4309
4310th_info_t
4311add_event(uintptr_t thread, int type) {
4312	th_info_t	ti;
4313	int		i;
4314	int		hashid;
4315
4316	if ((ti = th_info_freelist))
4317		th_info_freelist = ti->next;
4318	else
4319		ti = (th_info_t)malloc(sizeof(struct th_info));
4320
4321	hashid = thread & HASH_MASK;
4322
4323	ti->next = th_info_hash[hashid];
4324	th_info_hash[hashid] = ti;
4325
4326	ti->thread = thread;
4327	ti->type = type;
4328
4329	ti->waited = 0;
4330	ti->in_filemgr = 0;
4331	ti->in_hfs_update = 0;
4332
4333	ti->pathptr = &ti->lookups[0].pathname[0];
4334	ti->pn_scall_index = 0;
4335	ti->pn_work_index = 0;
4336
4337	for (i = 0; i < MAX_PATHNAMES; i++)
4338		ti->lookups[i].pathname[0] = 0;
4339
4340	return (ti);
4341}
4342
4343th_info_t
4344find_event(uintptr_t thread, int type) {
4345        th_info_t	ti;
4346	int		hashid;
4347
4348	hashid = thread & HASH_MASK;
4349
4350	for (ti = th_info_hash[hashid]; ti; ti = ti->next) {
4351		if (ti->thread == thread) {
4352		        if (type == ti->type)
4353			        return (ti);
4354			if (ti->in_filemgr) {
4355			        if (type == -1)
4356				        return (ti);
4357				continue;
4358			}
4359			if (type == 0)
4360			        return (ti);
4361		}
4362	}
4363	return ((th_info_t) 0);
4364}
4365
4366void
4367delete_all_events() {
4368        th_info_t	ti = 0;
4369        th_info_t	ti_next = 0;
4370        int             i;
4371
4372        for (i = 0; i < HASH_SIZE; i++) {
4373
4374                for (ti = th_info_hash[i]; ti; ti = ti_next) {
4375                        ti_next = ti->next;
4376                        ti->next = th_info_freelist;
4377                        th_info_freelist = ti;
4378                }
4379                th_info_hash[i] = 0;
4380        }
4381}
4382
4383
4384void
4385mark_thread_waited(uintptr_t thread) {
4386        th_info_t	ti;
4387	int		hashid;
4388
4389	hashid = thread & HASH_MASK;
4390
4391	for (ti = th_info_hash[hashid]; ti; ti = ti->next) {
4392		if (ti->thread == thread)
4393			ti->waited = 1;
4394	}
4395}
4396
4397
4398void read_command_map()
4399{
4400	size_t	size;
4401	int	i;
4402	int total_threads = 0;
4403	kd_threadmap *mapptr = 0;
4404
4405	delete_all_map_entries();
4406
4407	if (!RAW_flag) {
4408
4409		total_threads = bufinfo.nkdthreads;
4410		size = bufinfo.nkdthreads * sizeof(kd_threadmap);
4411
4412		if (size) {
4413			if ((mapptr = (kd_threadmap *) malloc(size))) {
4414				int mib[6];
4415
4416				bzero (mapptr, size);
4417				/*
4418				 * Now read the threadmap
4419				 */
4420				mib[0] = CTL_KERN;
4421				mib[1] = KERN_KDEBUG;
4422				mib[2] = KERN_KDTHRMAP;
4423				mib[3] = 0;
4424				mib[4] = 0;
4425				mib[5] = 0;		/* no flags */
4426
4427				if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0) {
4428					/*
4429					 * This is not fatal -- just means I cant map command strings
4430					 */
4431					free(mapptr);
4432					return;
4433				}
4434			}
4435		}
4436	} else {
4437		RAW_header	header;
4438		off_t	offset;
4439
4440		RAW_fd = open(RAW_file, O_RDONLY);
4441
4442		if (RAW_fd < 0) {
4443			perror("Can't open RAW file");
4444			exit(1);
4445		}
4446		if (read(RAW_fd, &header, sizeof(RAW_header)) != sizeof(RAW_header)) {
4447			perror("read failed");
4448			exit(2);
4449		}
4450		if (header.version_no != RAW_VERSION1) {
4451			header.version_no = RAW_VERSION0;
4452			header.TOD_secs = time((long *)0);
4453			header.TOD_usecs = 0;
4454
4455			lseek(RAW_fd, (off_t)0, SEEK_SET);
4456
4457			if (read(RAW_fd, &header.thread_count, sizeof(int)) != sizeof(int)) {
4458				perror("read failed");
4459				exit(2);
4460			}
4461		}
4462		sample_TOD_secs = header.TOD_secs;
4463		sample_TOD_usecs = header.TOD_usecs;
4464
4465		total_threads = header.thread_count;
4466		size = total_threads * sizeof(kd_threadmap);
4467
4468		if (size) {
4469			if ((mapptr = (kd_threadmap *) malloc(size))) {
4470				bzero (mapptr, size);
4471
4472				if (read(RAW_fd, mapptr, size) != size) {
4473					free(mapptr);
4474					return;
4475				}
4476			}
4477		}
4478		if (header.version_no != RAW_VERSION0) {
4479			offset = lseek(RAW_fd, (off_t)0, SEEK_CUR);
4480			offset = (offset + (4095)) & ~4095;
4481
4482			lseek(RAW_fd, offset, SEEK_SET);
4483		}
4484	}
4485	for (i = 0; i < total_threads; i++)
4486		create_map_entry(mapptr[i].thread, mapptr[i].valid, &mapptr[i].command[0]);
4487
4488        free(mapptr);
4489}
4490
4491
4492void delete_all_map_entries()
4493{
4494	threadmap_t     tme = 0;
4495        threadmap_t     tme_next = 0;
4496	int             i;
4497
4498	for (i = 0; i < HASH_SIZE; i++) {
4499
4500		for (tme = threadmap_hash[i]; tme; tme = tme_next) {
4501                        if (tme->tm_setptr)
4502				free(tme->tm_setptr);
4503			tme_next = tme->tm_next;
4504                        tme->tm_next = threadmap_freelist;
4505			threadmap_freelist = tme;
4506                }
4507                threadmap_hash[i] = 0;
4508	}
4509}
4510
4511
4512void create_map_entry(uintptr_t thread, int pid, char *command)
4513{
4514        threadmap_t     tme;
4515        int             hashid;
4516
4517        if ((tme = threadmap_freelist))
4518                threadmap_freelist = tme->tm_next;
4519        else
4520                tme = (threadmap_t)malloc(sizeof(struct threadmap));
4521
4522        tme->tm_thread  = thread;
4523	tme->tm_setsize = 0;
4524	tme->tm_setptr  = 0;
4525
4526        (void)strncpy (tme->tm_command, command, MAXCOMLEN);
4527        tme->tm_command[MAXCOMLEN] = '\0';
4528
4529        hashid = thread & HASH_MASK;
4530
4531        tme->tm_next = threadmap_hash[hashid];
4532        threadmap_hash[hashid] = tme;
4533
4534	if (pid != 0 && pid != 1) {
4535		if (!strncmp(command, "LaunchCFMA", 10))
4536			(void)get_real_command_name(pid, tme->tm_command, MAXCOMLEN);
4537	}
4538}
4539
4540
4541threadmap_t
4542find_map_entry(uintptr_t thread)
4543{
4544        threadmap_t     tme;
4545        int     hashid;
4546
4547	hashid = thread & HASH_MASK;
4548
4549        for (tme = threadmap_hash[hashid]; tme; tme = tme->tm_next) {
4550		if (tme->tm_thread == thread)
4551			return (tme);
4552	}
4553        return (0);
4554}
4555
4556
4557void
4558delete_map_entry(uintptr_t thread)
4559{
4560        threadmap_t     tme = 0;
4561        threadmap_t     tme_prev;
4562        int             hashid;
4563
4564        hashid = thread & HASH_MASK;
4565
4566        if ((tme = threadmap_hash[hashid])) {
4567                if (tme->tm_thread == thread)
4568			threadmap_hash[hashid] = tme->tm_next;
4569                else {
4570                        tme_prev = tme;
4571
4572			for (tme = tme->tm_next; tme; tme = tme->tm_next) {
4573                                if (tme->tm_thread == thread) {
4574                                        tme_prev->tm_next = tme->tm_next;
4575                                        break;
4576				}
4577                                tme_prev = tme;
4578			}
4579		}
4580                if (tme) {
4581			if (tme->tm_setptr)
4582				free(tme->tm_setptr);
4583
4584                        tme->tm_next = threadmap_freelist;
4585			threadmap_freelist = tme;
4586		}
4587	}
4588}
4589
4590
4591void
4592fs_usage_fd_set(uintptr_t thread, unsigned int fd)
4593{
4594	threadmap_t	tme;
4595
4596	if ((tme = find_map_entry(thread)) == 0)
4597		return;
4598	/*
4599	 * If the map is not allocated, then now is the time
4600	 */
4601	if (tme->tm_setptr == (unsigned long *)0) {
4602		if ((tme->tm_setptr = (unsigned long *)malloc(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE))) == 0)
4603			return;
4604
4605		tme->tm_setsize = FS_USAGE_FD_SETSIZE;
4606		bzero(tme->tm_setptr, (FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE)));
4607	}
4608	/*
4609	 * If the map is not big enough, then reallocate it
4610	 */
4611	while (tme->tm_setsize <= fd) {
4612		int	n;
4613
4614		n = tme->tm_setsize * 2;
4615		tme->tm_setptr = (unsigned long *)realloc(tme->tm_setptr, (FS_USAGE_NFDBYTES(n)));
4616
4617		bzero(&tme->tm_setptr[(tme->tm_setsize/FS_USAGE_NFDBITS)], (FS_USAGE_NFDBYTES(tme->tm_setsize)));
4618		tme->tm_setsize = n;
4619	}
4620	/*
4621	 * set the bit
4622	 */
4623	tme->tm_setptr[fd/FS_USAGE_NFDBITS] |= (1 << ((fd) % FS_USAGE_NFDBITS));
4624}
4625
4626
4627/*
4628 * Return values:
4629 *  0 : File Descriptor bit is not set
4630 *  1 : File Descriptor bit is set
4631 */
4632int
4633fs_usage_fd_isset(uintptr_t thread, unsigned int fd)
4634{
4635	threadmap_t	tme;
4636	int		ret = 0;
4637
4638	if ((tme = find_map_entry(thread))) {
4639		if (tme->tm_setptr && fd < tme->tm_setsize)
4640			ret = tme->tm_setptr[fd/FS_USAGE_NFDBITS] & (1 << (fd % FS_USAGE_NFDBITS));
4641	}
4642	return (ret);
4643}
4644
4645
4646void
4647fs_usage_fd_clear(uintptr_t thread, unsigned int fd)
4648{
4649	threadmap_t	tme;
4650
4651	if ((tme = find_map_entry(thread))) {
4652		if (tme->tm_setptr && fd < tme->tm_setsize)
4653			tme->tm_setptr[fd/FS_USAGE_NFDBITS] &= ~(1 << (fd % FS_USAGE_NFDBITS));
4654	}
4655}
4656
4657
4658
4659void
4660argtopid(char *str)
4661{
4662        char *cp;
4663        int ret;
4664	int i;
4665
4666        ret = (int)strtol(str, &cp, 10);
4667
4668        if (cp == str || *cp) {
4669		/*
4670		 * Assume this is a command string and find matching pids
4671		 */
4672	        if (!kp_buffer)
4673		        find_proc_names();
4674
4675	        for (i = 0; i < kp_nentries && num_of_pids < (MAX_PIDS - 1); i++) {
4676			if (kp_buffer[i].kp_proc.p_stat == 0)
4677				continue;
4678			else {
4679				if (!strncmp(str, kp_buffer[i].kp_proc.p_comm,
4680					     sizeof(kp_buffer[i].kp_proc.p_comm) -1))
4681					pids[num_of_pids++] = kp_buffer[i].kp_proc.p_pid;
4682			}
4683		}
4684	}
4685	else if (num_of_pids < (MAX_PIDS - 1))
4686	        pids[num_of_pids++] = ret;
4687}
4688
4689
4690
4691void
4692lookup_name(uint64_t user_addr, char **type, char **name)
4693{
4694        int i;
4695	int start, last;
4696
4697	*name = NULL;
4698	*type = NULL;
4699
4700	if (numFrameworks) {
4701
4702		if ((user_addr >= framework32.b_address && user_addr < framework32.e_address) ||
4703		    (user_addr >= framework64.b_address && user_addr < framework64.e_address)) {
4704
4705			start = 0;
4706			last  = numFrameworks;
4707
4708			for (i = numFrameworks / 2; start < last; i = start + ((last - start) / 2)) {
4709				if (user_addr > frameworkInfo[i].e_address)
4710					start = i+1;
4711				else
4712					last = i;
4713			}
4714			if (start < numFrameworks &&
4715			    user_addr >= frameworkInfo[start].b_address && user_addr < frameworkInfo[start].e_address) {
4716				*type = frameworkType[frameworkInfo[start].r_type];
4717				*name = frameworkInfo[start].name;
4718			}
4719		}
4720	}
4721}
4722
4723
4724/*
4725 * Comparison routines for sorting
4726 */
4727static int compareFrameworkAddress(const void  *aa, const void *bb)
4728{
4729	LibraryInfo *a = (LibraryInfo *)aa;
4730	LibraryInfo *b = (LibraryInfo *)bb;
4731
4732	if (a->b_address < b->b_address) return -1;
4733	if (a->b_address == b->b_address) return 0;
4734	return 1;
4735}
4736
4737
4738int scanline(char *inputstring, char **argv, int maxtokens)
4739{
4740	int n = 0;
4741	char **ap = argv, *p, *val;
4742
4743	for (p = inputstring; n < maxtokens && p != NULL; ) {
4744
4745		while ((val = strsep(&p, " \t")) != NULL && *val == '\0');
4746
4747		*ap++ = val;
4748		n++;
4749	}
4750	*ap = 0;
4751
4752	return n;
4753}
4754
4755
4756int ReadSharedCacheMap(const char *path, LibraryRange *lr, char *linkedit_name)
4757{
4758	uint64_t	b_address, e_address;
4759	char	buf[1024];
4760	char	*fnp;
4761	FILE	*fd;
4762	char	frameworkName[256];
4763	char	*tokens[64];
4764	int	ntokens;
4765	int	type;
4766	int	linkedit_found = 0;
4767	char	*substring, *ptr;
4768
4769	bzero(buf, sizeof(buf));
4770	bzero(tokens, sizeof(tokens));
4771
4772	lr->b_address = 0;
4773	lr->e_address = 0;
4774
4775	if ((fd = fopen(path, "r")) == 0)
4776		return 0;
4777
4778	while (fgets(buf, 1023, fd)) {
4779		if (strncmp(buf, "mapping", 7))
4780			break;
4781	}
4782	buf[strlen(buf)-1] = 0;
4783
4784	frameworkName[0] = 0;
4785
4786	for (;;) {
4787		/*
4788		 * Extract lib name from path name
4789		 */
4790		if ((substring = strrchr(buf, '.')))
4791		{
4792			/*
4793			 * There is a ".": name is whatever is between the "/" around the "."
4794			 */
4795			while ( *substring != '/')		    /* find "/" before "." */
4796				substring--;
4797			substring++;
4798
4799			strncpy(frameworkName, substring, 256);           /* copy path from "/" */
4800			frameworkName[255] = 0;
4801			substring = frameworkName;
4802
4803			while ( *substring != '/' && *substring)    /* find "/" after "." and stop string there */
4804				substring++;
4805			*substring = 0;
4806		}
4807		else
4808		{
4809			/*
4810			 * No ".": take segment after last "/"
4811			 */
4812			ptr = buf;
4813			substring = ptr;
4814
4815			while (*ptr)  {
4816				if (*ptr == '/')
4817					substring = ptr + 1;
4818				ptr++;
4819			}
4820			strncpy(frameworkName, substring, 256);
4821			frameworkName[255] = 0;
4822		}
4823		fnp = (char *)malloc(strlen(frameworkName) + 1);
4824		strcpy(fnp, frameworkName);
4825
4826		while (fgets(buf, 1023, fd) && numFrameworks < (MAXINDEX - 2)) {
4827			/*
4828			 * Get rid of EOL
4829			 */
4830			buf[strlen(buf)-1] = 0;
4831
4832			ntokens = scanline(buf, tokens, 64);
4833
4834			if (ntokens < 4)
4835				continue;
4836
4837			if (strncmp(tokens[0], "__TEXT", 6) == 0)
4838				type = TEXT_R;
4839			else if (strncmp(tokens[0], "__DATA", 6) == 0)
4840				type = DATA_R;
4841			else if (strncmp(tokens[0], "__OBJC", 6) == 0)
4842				type = OBJC_R;
4843			else if (strncmp(tokens[0], "__IMPORT", 8) == 0)
4844				type = IMPORT_R;
4845			else if (strncmp(tokens[0], "__UNICODE", 9) == 0)
4846				type = UNICODE_R;
4847			else if (strncmp(tokens[0], "__IMAGE", 7) == 0)
4848				type = IMAGE_R;
4849			else if (strncmp(tokens[0], "__LINKEDIT", 10) == 0)
4850				type = LINKEDIT_R;
4851			else
4852				type = -1;
4853
4854			if (type == LINKEDIT_R && linkedit_found)
4855				break;
4856
4857			if (type != -1) {
4858				b_address = strtoull(tokens[1], 0, 16);
4859				e_address = strtoull(tokens[3], 0, 16);
4860
4861				frameworkInfo[numFrameworks].b_address	= b_address;
4862				frameworkInfo[numFrameworks].e_address	= e_address;
4863				frameworkInfo[numFrameworks].r_type	= type;
4864
4865				if (type == LINKEDIT_R) {
4866					frameworkInfo[numFrameworks].name = linkedit_name;
4867					linkedit_found = 1;
4868				} else
4869					frameworkInfo[numFrameworks].name = fnp;
4870#if 0
4871				printf("%s(%d): %qx-%qx\n", frameworkInfo[numFrameworks].name, type, b_address, e_address);
4872#endif
4873				if (lr->b_address == 0 || b_address < lr->b_address)
4874					lr->b_address = b_address;
4875
4876				if (lr->e_address == 0 || e_address > lr->e_address)
4877					lr->e_address = e_address;
4878
4879				numFrameworks++;
4880			}
4881			if (type == LINKEDIT_R)
4882				break;
4883		}
4884		if (fgets(buf, 1023, fd) == 0)
4885			break;
4886
4887		buf[strlen(buf)-1] = 0;
4888	}
4889	fclose(fd);
4890
4891#if 0
4892	printf("%s range, %qx-%qx\n", path, lr->b_address, lr->e_address);
4893#endif
4894	return 1;
4895}
4896
4897
4898void
4899SortFrameworkAddresses()
4900{
4901
4902	frameworkInfo[numFrameworks].b_address = frameworkInfo[numFrameworks - 1].b_address + 0x800000;
4903	frameworkInfo[numFrameworks].e_address = frameworkInfo[numFrameworks].b_address;
4904	frameworkInfo[numFrameworks].name = (char *)0;
4905
4906	qsort(frameworkInfo, numFrameworks, sizeof(LibraryInfo), compareFrameworkAddress);
4907}
4908
4909
4910struct diskio *insert_diskio(int type, int bp, int dev, int blkno, int io_size, uintptr_t thread, double curtime)
4911{
4912	struct diskio	*dio;
4913	threadmap_t	tme;
4914
4915	if ((dio = free_diskios))
4916		free_diskios = dio->next;
4917	else {
4918		if ((dio = (struct diskio *)malloc(sizeof(struct diskio))) == NULL)
4919			return (NULL);
4920	}
4921	dio->prev = NULL;
4922
4923	dio->type = type;
4924	dio->bp = bp;
4925	dio->dev = dev;
4926	dio->blkno = blkno;
4927	dio->iosize = io_size;
4928	dio->issued_time = curtime;
4929	dio->issuing_thread = thread;
4930
4931	dio->bc_info = 0x0;
4932
4933	if ((tme = find_map_entry(thread))) {
4934		strncpy(dio->issuing_command, tme->tm_command, MAXCOMLEN);
4935		dio->issuing_command[MAXCOMLEN-1] = '\0';
4936	} else
4937		strcpy(dio->issuing_command, "");
4938
4939	dio->next = busy_diskios;
4940	if (dio->next)
4941		dio->next->prev = dio;
4942	busy_diskios = dio;
4943
4944	return (dio);
4945}
4946
4947struct diskio *find_diskio(int bp) {
4948	struct diskio *dio;
4949
4950	for (dio = busy_diskios; dio; dio = dio->next) {
4951		if (dio->bp == bp)
4952			return (dio);
4953	}
4954
4955	return NULL;
4956}
4957
4958
4959struct diskio *complete_diskio(int bp, int io_errno, int resid, uintptr_t thread, double curtime)
4960{
4961	struct diskio *dio;
4962
4963	if ((dio = find_diskio(bp)) == NULL) return NULL;
4964
4965	if (dio == busy_diskios) {
4966		if ((busy_diskios = dio->next))
4967			dio->next->prev = NULL;
4968	} else {
4969		if (dio->next)
4970			dio->next->prev = dio->prev;
4971		dio->prev->next = dio->next;
4972	}
4973
4974	dio->iosize -= resid;
4975	dio->io_errno = io_errno;
4976	dio->completed_time = curtime;
4977	dio->completion_thread = thread;
4978
4979	return dio;
4980}
4981
4982
4983void free_diskio(struct diskio *dio)
4984{
4985	dio->next = free_diskios;
4986	free_diskios = dio;
4987}
4988
4989
4990void print_diskio(struct diskio *dio)
4991{
4992	char  *p = NULL;
4993	int   len = 0;
4994	int   type;
4995	int   format = FMT_DISKIO;
4996	char  buf[64];
4997
4998	type = dio->type;
4999	dio->is_meta = 0;
5000
5001	if ((type & P_CS_Class) == P_CS_Class) {
5002
5003		switch (type) {
5004
5005		case P_CS_ReadChunk:
5006			p = "    RdChunkCS";
5007			len = 13;
5008			format = FMT_DISKIO_CS;
5009			break;
5010		case P_CS_WriteChunk:
5011			p = "    WrChunkCS";
5012			len = 13;
5013			format = FMT_DISKIO_CS;
5014			break;
5015		case P_CS_MetaRead:
5016			p = "  RdMetaCS";
5017			len = 10;
5018			format = FMT_DISKIO_CS;
5019			break;
5020		case P_CS_MetaWrite:
5021			p = "  WrMetaCS";
5022			len = 10;
5023			format = FMT_DISKIO_CS;
5024			break;
5025		case P_CS_TransformRead:
5026			p = "  RdBgTfCS";
5027			len = 10;
5028			break;
5029		case P_CS_TransformWrite:
5030			p = "  WrBgTfCS";
5031			len = 10;
5032			break;
5033		case P_CS_MigrationRead:
5034			p = "  RdBgMigrCS";
5035			len = 12;
5036			break;
5037		case P_CS_MigrationWrite:
5038			p = "  WrBgMigrCS";
5039			len = 12;
5040			break;
5041		}
5042		strncpy(buf, p, len);
5043	} else {
5044
5045		switch (type & P_DISKIO_TYPE) {
5046
5047		case P_RdMeta:
5048		        dio->is_meta = 1;
5049			p = "  RdMeta";
5050			len = 8;
5051			break;
5052		case P_WrMeta:
5053		        dio->is_meta = 1;
5054			p = "  WrMeta";
5055			len = 8;
5056			break;
5057		case P_RdData:
5058			p = "  RdData";
5059			len = 8;
5060			break;
5061		case P_WrData:
5062			p = "  WrData";
5063			len = 8;
5064			break;
5065		case P_PgIn:
5066			p = "  PgIn";
5067			len = 6;
5068			break;
5069		case P_PgOut:
5070			p = "  PgOut";
5071			len = 7;
5072			break;
5073		default:
5074			p = "  ";
5075			len = 2;
5076			break;
5077		}
5078		strncpy(buf, p, len);
5079
5080		buf[len++] = '[';
5081
5082		if (type & P_DISKIO_ASYNC)
5083			buf[len++] = 'A';
5084		else
5085			buf[len++] = 'S';
5086
5087		if (type & P_DISKIO_NOCACHE)
5088			buf[len++] = 'N';
5089
5090		int tier = (type & P_DISKIO_TIER_MASK) >> P_DISKIO_TIER_SHIFT;
5091		if (tier > 0) {
5092			buf[len++] = 'T';
5093			if (tier > 0 && tier < 10)
5094				buf[len++] = '0' + tier;
5095		}
5096
5097		if (type & P_DISKIO_PASSIVE)
5098			buf[len++] = 'P';
5099
5100
5101		buf[len++] = ']';
5102	}
5103	buf[len] = 0;
5104
5105	if (check_filter_mode(NULL, type, 0, 0, buf))
5106		format_print(NULL, buf, dio->issuing_thread, type, 0, 0, 0, 0, format, dio->completed_time, dio->issued_time, 1, "", dio);
5107}
5108
5109
5110void cache_disk_names()
5111{
5112	struct stat    st;
5113	DIR            *dirp = NULL;
5114	struct dirent  *dir;
5115	struct diskrec *dnp;
5116
5117
5118	if ((dirp = opendir("/dev")) == NULL)
5119		return;
5120
5121	while ((dir = readdir(dirp)) != NULL) {
5122		char nbuf[MAXPATHLEN];
5123
5124		if (dir->d_namlen < 5 || strncmp("disk", dir->d_name, 4))
5125			continue;
5126
5127		snprintf(nbuf, MAXPATHLEN, "%s/%s", "/dev", dir->d_name);
5128
5129		if (stat(nbuf, &st) < 0)
5130			continue;
5131
5132		if ((dnp = (struct diskrec *)malloc(sizeof(struct diskrec))) == NULL)
5133			continue;
5134
5135		if ((dnp->diskname = (char *)malloc(dir->d_namlen + 1)) == NULL) {
5136			free(dnp);
5137			continue;
5138		}
5139		strncpy(dnp->diskname, dir->d_name, dir->d_namlen);
5140		dnp->diskname[dir->d_namlen] = 0;
5141		dnp->dev = st.st_rdev;
5142
5143		dnp->next = disk_list;
5144		disk_list = dnp;
5145	}
5146	(void) closedir(dirp);
5147}
5148
5149
5150void recache_disk_names()
5151{
5152	struct diskrec *dnp, *next_dnp;
5153
5154	for (dnp = disk_list; dnp; dnp = next_dnp) {
5155		next_dnp = dnp->next;
5156
5157		free(dnp->diskname);
5158		free(dnp);
5159	}
5160	disk_list = NULL;
5161
5162	cache_disk_names();
5163}
5164
5165
5166char *find_disk_name(int dev)
5167{
5168	struct diskrec *dnp;
5169	int	i;
5170
5171	if (dev == NFS_DEV)
5172		return ("NFS");
5173
5174	if (dev == CS_DEV)
5175		return ("CS");
5176
5177	for (i = 0; i < 2; i++) {
5178		for (dnp = disk_list; dnp; dnp = dnp->next) {
5179			if (dnp->dev == dev)
5180				return (dnp->diskname);
5181		}
5182		recache_disk_names();
5183	}
5184	return ("NOTFOUND");
5185}
5186
5187
5188char *generate_cs_disk_name(int dev, char *s)
5189{
5190	if (dev == -1)
5191		return ("UNKNOWN");
5192
5193	sprintf(s, "disk%ds%d", (dev >> 16) & 0xffff, dev & 0xffff);
5194
5195	return (s);
5196}
5197
5198
5199
5200/*
5201 * ret = 1 means print the entry
5202 * ret = 0 means don't print the entry
5203 */
5204
5205/*
5206 * meaning of filter flags:
5207 * cachehit	turn on display of CACHE_HIT events (which are filtered out by default)
5208 *
5209 * exec		show exec/posix_spawn
5210 * pathname	show events with a pathname and close()
5211 * diskio	show disk I/Os
5212 * filesys	show filesystem events
5213 * network	show network events
5214 *
5215 * filters may be combined; default is all filters on (except cachehit)
5216 */
5217int
5218check_filter_mode(struct th_info *ti, int type, int error, int retval, char *sc_name)
5219{
5220	int ret = 0;
5221	int network_fd_isset = 0;
5222	unsigned int fd;
5223
5224	/* cachehit is special -- it's not on by default */
5225	if (sc_name[0] == 'C' && !strcmp(sc_name, "CACHE_HIT")) {
5226		if (show_cachehits) return 1;
5227		else return 0;
5228	}
5229
5230	if (filter_mode == DEFAULT_DO_NOT_FILTER)
5231		return(1);
5232
5233	if (filter_mode & DISKIO_FILTER) {
5234		if ((type & P_DISKIO_MASK) == P_DISKIO)
5235			return 1;
5236	}
5237
5238	if (filter_mode & EXEC_FILTER) {
5239		if (type == BSC_execve || type == BSC_posix_spawn)
5240			return(1);
5241	}
5242
5243	if (filter_mode & PATHNAME_FILTER) {
5244            if (ti && ti->lookups[0].pathname[0])
5245	            return(1);
5246	    if (type == BSC_close || type == BSC_close_nocancel ||
5247		    type == BSC_guarded_close_np)
5248	            return(1);
5249	}
5250
5251	if (ti == (struct th_info *)0) {
5252		if (filter_mode & FILESYS_FILTER)
5253			return(1);
5254		return(0);
5255	}
5256
5257	switch (type) {
5258
5259	case BSC_close:
5260	case BSC_close_nocancel:
5261	case BSC_guarded_close_np:
5262	    fd = ti->arg1;
5263	    network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
5264
5265	    if (error == 0)
5266		    fs_usage_fd_clear(ti->thread,fd);
5267
5268	    if (network_fd_isset) {
5269		    if (filter_mode & NETWORK_FILTER)
5270			    ret = 1;
5271	    } else
5272		    if (filter_mode & FILESYS_FILTER)
5273			    ret = 1;
5274	    break;
5275
5276	case BSC_read:
5277	case BSC_write:
5278	case BSC_read_nocancel:
5279	case BSC_write_nocancel:
5280	    /*
5281	     * we don't care about error in these cases
5282	     */
5283	    fd = ti->arg1;
5284	    network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
5285
5286	    if (network_fd_isset) {
5287		    if (filter_mode & NETWORK_FILTER)
5288			    ret = 1;
5289	    } else
5290		    if (filter_mode & FILESYS_FILTER)
5291			    ret = 1;
5292	    break;
5293
5294	case BSC_accept:
5295	case BSC_accept_nocancel:
5296	case BSC_socket:
5297	    fd = retval;
5298
5299	    if (error == 0)
5300		    fs_usage_fd_set(ti->thread, fd);
5301	    if (filter_mode & NETWORK_FILTER)
5302		    ret = 1;
5303	    break;
5304
5305	case BSC_recvfrom:
5306	case BSC_sendto:
5307	case BSC_recvmsg:
5308	case BSC_sendmsg:
5309	case BSC_connect:
5310	case BSC_bind:
5311	case BSC_listen:
5312	case BSC_sendto_nocancel:
5313	case BSC_recvfrom_nocancel:
5314	case BSC_recvmsg_nocancel:
5315	case BSC_sendmsg_nocancel:
5316	case BSC_connect_nocancel:
5317	    fd = ti->arg1;
5318
5319	    if (error == 0)
5320		    fs_usage_fd_set(ti->thread, fd);
5321	    if (filter_mode & NETWORK_FILTER)
5322		    ret = 1;
5323	    break;
5324
5325	case BSC_select:
5326	case BSC_select_nocancel:
5327	case BSC_socketpair:
5328	    /*
5329	     * Cannot determine info about file descriptors
5330	     */
5331	    if (filter_mode & NETWORK_FILTER)
5332		    ret = 1;
5333	    break;
5334
5335	case BSC_dup:
5336	case BSC_dup2:
5337	    /*
5338	     * We track these cases for fd state only
5339	     */
5340	    fd = ti->arg1;
5341	    network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
5342
5343	    if (error == 0 && network_fd_isset) {
5344		    /*
5345		     * then we are duping a socket descriptor
5346		     */
5347		    fd = retval;  /* the new fd */
5348		    fs_usage_fd_set(ti->thread, fd);
5349	    }
5350	    break;
5351
5352	default:
5353	    if (filter_mode & FILESYS_FILTER)
5354		    ret = 1;
5355	    break;
5356	}
5357
5358	return(ret);
5359}
5360
5361/*
5362 * Allocate a buffer that is large enough to hold the maximum arguments
5363 * to execve().  This is used when getting the arguments to programs
5364 * when we see LaunchCFMApps.  If this fails, it is not fatal, we will
5365 * simply not resolve the command name.
5366 */
5367
5368void
5369init_arguments_buffer()
5370{
5371	int     mib[2];
5372	size_t  size;
5373
5374	mib[0] = CTL_KERN;
5375	mib[1] = KERN_ARGMAX;
5376	size = sizeof(argmax);
5377
5378	if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1)
5379		return;
5380#if 1
5381	/* Hack to avoid kernel bug. */
5382	if (argmax > 8192) {
5383		argmax = 8192;
5384	}
5385#endif
5386	arguments = (char *)malloc(argmax);
5387}
5388
5389
5390int
5391get_real_command_name(int pid, char *cbuf, int csize)
5392{
5393	/*
5394	 * Get command and arguments.
5395	 */
5396	char	*cp;
5397	int	mib[4];
5398	char    *command_beg, *command, *command_end;
5399
5400	if (cbuf == NULL)
5401		return(0);
5402
5403	if (arguments)
5404		bzero(arguments, argmax);
5405	else
5406		return(0);
5407
5408	/*
5409	 * A sysctl() is made to find out the full path that the command
5410	 * was called with.
5411	 */
5412	mib[0] = CTL_KERN;
5413	mib[1] = KERN_PROCARGS2;
5414	mib[2] = pid;
5415	mib[3] = 0;
5416
5417	if (sysctl(mib, 3, arguments, (size_t *)&argmax, NULL, 0) < 0)
5418		return(0);
5419
5420	/*
5421	 * Skip the saved exec_path
5422	 */
5423	for (cp = arguments; cp < &arguments[argmax]; cp++) {
5424		if (*cp == '\0') {
5425			/*
5426			 * End of exec_path reached
5427			 */
5428			break;
5429		}
5430	}
5431	if (cp == &arguments[argmax])
5432		return(0);
5433
5434	/*
5435	 * Skip trailing '\0' characters
5436	 */
5437	for (; cp < &arguments[argmax]; cp++) {
5438		if (*cp != '\0') {
5439			/*
5440			 * Beginning of first argument reached
5441			 */
5442			break;
5443		}
5444	}
5445	if (cp == &arguments[argmax])
5446		return(0);
5447
5448	command_beg = cp;
5449	/*
5450	 * Make sure that the command is '\0'-terminated.  This protects
5451	 * against malicious programs; under normal operation this never
5452	 * ends up being a problem..
5453	 */
5454	for (; cp < &arguments[argmax]; cp++) {
5455		if (*cp == '\0') {
5456			/*
5457			 * End of first argument reached
5458			 */
5459			break;
5460		}
5461	}
5462	if (cp == &arguments[argmax])
5463		return(0);
5464
5465	command_end = command = cp;
5466
5467	/*
5468	 * Get the basename of command
5469	 */
5470	for (command--; command >= command_beg; command--) {
5471		if (*command == '/') {
5472			command++;
5473			break;
5474		}
5475	}
5476	(void) strncpy(cbuf, (char *)command, csize);
5477	cbuf[csize-1] = '\0';
5478
5479	return(1);
5480}
5481