#!/usr/sbin/dtrace -s
/*
** iosnoop.d - A program to print I/O events as they happen, with useful
**	details such as UID, PID, inode, command, etc. 
**	Written in DTrace (Solaris 10 build 63).
**
** NOTE: This version is deprecated. See "iosnoop",
** 	http://www.brendangregg.com/dtrace.html
**
** 10-Oct-2004, ver 0.90
**
**
** USAGE:	./iosnoop.d
**
**	Different styles of output can be selected by changing
**	the "PFORMAT" variable below.
** 	
** FIELDS:
**		COMM	command name for the process
**		ARGS	full argument listing for the process
**		FILE	filename (basename) for io operation
**		MOUNT	mount point 
**		SIZE	size of operation, bytes
**		BLOCK	disk block for the operation (location)
**		STIME 	timestamp for the disk request, us
**		TIME	timestamp for the disk completion, us
**		D	direction, Read or Write
**		...
**
** SEE ALSO: Solaris Dynamic Tracing Guide, http://docs.sun.com
**
** Standard Disclaimer: This is freeware, use at your own risk.
**
** 12-Mar-2004	Brendan Gregg	Created this, build 51.
** 23-May-2004	   "	  "	Fixed mntpt bug.
** 10-Oct-2004	   "      "	Rewritten to use the io provider, build 63.
**
*/

inline int PFORMAT = 1;
/*			1 - Default output (COMM, PATHNAME)
/*			2 - Arguments output (MOUNT, FILE, ARGS)
**			3 - Timestamp output (TIME, COMM, PATHNAME)
**			4 - Everything, space delimited (for spreadsheets)
*/

#pragma D option quiet

/*
**  Print header
*/
dtrace:::BEGIN /PFORMAT == 1/ { 
	printf("%5s %5s %1s %8s %6s %10s %s\n",
	 "UID","PID","D","BLOCK","SIZE","COMM","PATHNAME");
}
dtrace:::BEGIN /PFORMAT == 2/ { 
	printf("%5s %5s %1s %8s %6s %12s %16s %s\n",
	 "UID","PID","D","BLOCK","SIZE","MOUNT","FILE","ARGS");
}
dtrace:::BEGIN /PFORMAT == 3/ { 
	printf("%-14s %5s %5s %1s %8s %6s %10s %s\n",
	 "TIME","UID","PID","D","BLOCK","SIZE","COMM","PATHNAME");
}
dtrace:::BEGIN /PFORMAT == 4/ { 
	printf("%s %s %s %s %s %s %s %s %s %s %s %s %s\n",
	 "TIME","STIME","UID","PID","PPID","D","BLOCK","SIZE","MOUNT",
	 "FILE","PATH","COMM","ARGS");
}

/*
**  Store entry details
*/
io:::start
{
	this->dev = args[0]->b_edev;
	this->blk = args[0]->b_blkno;
	start_uid[this->dev,this->blk] = curpsinfo->pr_euid;
	start_pid[this->dev,this->blk] = pid;
	start_ppid[this->dev,this->blk] = curpsinfo->pr_ppid;
	start_args[this->dev,this->blk] = (char *)curpsinfo->pr_psargs;
	start_comm[this->dev,this->blk] = execname;
	start_time[this->dev,this->blk] = timestamp;
	start_rw[this->dev,this->blk] = args[0]->b_flags & B_READ ? "R" : "W";
}

/*
**  Process completion
*/
io:::done
{
	/* fetch entry values */
	this->dev = args[0]->b_edev;
	this->blk = args[0]->b_blkno;
	this->suid = start_uid[this->dev,this->blk];
	this->spid = start_pid[this->dev,this->blk];
	this->sppid = start_ppid[this->dev,this->blk];
	sargs = (int)start_args[this->dev,this->blk] == 0 ? 
		"" : start_args[this->dev,this->blk];
	scomm = start_comm[this->dev,this->blk];
	this->stime = start_time[this->dev,this->blk];
	readwrite = start_rw[this->dev,this->blk];

	/* memory cleanup */
	start_uid[this->dev,this->blk] = 0;
	start_pid[this->dev,this->blk] = 0;
	start_ppid[this->dev,this->blk] = 0;
	start_args[this->dev,this->blk] = 0;
	start_time[this->dev,this->blk] = 0;
	start_comm[this->dev,this->blk] = 0;
	start_rw[this->dev,this->blk] = 0;
}

/*
**  Print event details
*/
io:::done /PFORMAT == 1/ {
	printf("%5d %5d %1s %8d %6d %10s %s\n",
	 this->suid,this->spid,readwrite,args[0]->b_blkno,args[0]->b_bcount,
	 scomm,args[2]->fi_pathname);
}
io:::done /PFORMAT == 2/ {
	printf("%5d %5d %1s %8d %6d %12s %16s %s\n",
	 this->suid,this->spid,readwrite,args[0]->b_blkno,args[0]->b_bcount,
	 args[2]->fi_mount,args[2]->fi_name,stringof(sargs));
}
io:::done /PFORMAT == 3/ {
	printf("%-14d %5d %5d %1s %8d %6d %10s %s\n",
	 timestamp/1000,this->suid,this->spid,readwrite,args[0]->b_blkno,
	 args[0]->b_bcount,scomm,args[2]->fi_pathname);
}
io:::done /PFORMAT == 4/ {
	printf("%d %d %d %d %d %s %d %d %s %s %s %s %s\n",
	 timestamp/1000,this->stime/1000,this->suid,this->spid,this->sppid,
	 readwrite,args[0]->b_blkno,args[0]->b_bcount,args[2]->fi_mount,
	 args[2]->fi_name,args[2]->fi_pathname,scomm,stringof(sargs));
}

