1# -*- tab-width: 4 -*- ;; Emacs
2# vi: set filetype=sh tabstop=8 shiftwidth=8 noexpandtab :: Vi/ViM
3############################################################ IDENT(1)
4#
5# $Title: dwatch(8) module for VOP_CREATE(9) [or similar] entry $
6# $Copyright: 2014-2018 Devin Teske. All rights reserved. $
7#
8############################################################ DESCRIPTION
9#
10# Print filesystem paths being operated-on by VOP_CREATE(9) [or similar]
11# NB: All paths are shown even if error prevents operation.
12#
13############################################################ PROBE
14
15: ${PROBE:=vfs:vop:$PROFILE:entry}
16
17############################################################ ACTIONS
18
19exec 9<<EOF
20$PROBE /* probe ID $ID */
21{${TRACE:+
22	printf("<$ID>");}
23	this->vp = (struct vnode *)arg0;
24	this->ncp = this->vp != NULL ?
25		this->vp->v_cache_dst.tqh_first : 0;
26	this->fi_name = args[1] ? (
27		args[1]->a_cnp != NULL ?
28			stringof(args[1]->a_cnp->cn_nameptr) : ""
29	) : "";
30	this->mount = this->vp != NULL ?
31		this->vp->v_mount : NULL; /* ptr to vfs we are in */
32	this->fi_fs = this->mount != NULL ?
33		stringof(this->mount->mnt_stat.f_fstypename) : "";
34	this->fi_mount = this->mount != NULL ?
35		stringof(this->mount->mnt_stat.f_mntonname) : "";
36	this->d_name = args[0]->v_cache_dd != NULL ?
37		stringof(args[0]->v_cache_dd->nc_name) : "";
38
39	$( awk -v MAX_DEPTH=$MAX_DEPTH '
40		{ sub(/^\\\t/, "\t") }
41		{ buf = buf "\t" $0 "\n" }
42		END {
43			sub(/\n$/, "", buf)
44			$0 = buf
45			sub(/^[[:space:]]*/, "")
46			for (DEPTH = 1; DEPTH <= MAX_DEPTH + 1; DEPTH++) {
47				gsub(/DEPTH/, DEPTH)
48				print
49				$0 = buf
50			}
51		}
52	' <<-EOFDEPTH
53	this->nameDEPTH = "";
54	EOFDEPTH
55	)
56}
57
58$PROBE /this->vp == 0 || this->fi_fs == 0 ||
59	this->fi_fs == "devfs" || this->fi_fs == "" ||
60	this->fi_name == ""/ /* probe ID $(( $ID + 1 )) */
61{${TRACE:+
62	printf("<$(( $ID + 1 ))>");}
63	this->ncp = 0;
64}
65
66/*********************************************************/
67
68$PROBE /this->ncp/ /* probe ID $(( $ID + 2 )) (depth 1) */
69{${TRACE:+
70	printf("<$(( $ID + 2 ))>");}
71	this->dvp = this->ncp->nc_dvp != NULL ?
72		this->ncp->nc_dvp->v_cache_dst.tqh_first : 0;
73	this->name1 = this->dvp != 0 ? (
74		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
75	) : "";
76}
77
78$PROBE /this->name1 == 0 || this->fi_fs == 0 ||
79	this->fi_fs == "devfs" || this->fi_fs == "" ||
80	this->name1 == "/" || this->name1 == ""/ /* probe ID $(( $ID + 3 )) */
81{${TRACE:+
82	printf("<$(( $ID + 3 ))>");}
83	this->dvp = 0;
84}
85
86/*********************************************************/
87
88/*
89 * BEGIN Pathname-depth iterators
90 */
91
92$( awk -v ID=$(( $ID + 4 )) -v MAX_DEPTH=$MAX_DEPTH '
93	{ buf = buf $0 "\n" }
94	END {
95		sub(/\n$/, "", buf)
96		for (DEPTH = 2; DEPTH <= MAX_DEPTH; DEPTH++) {
97			$0 = buf
98			gsub(/DEPTH/, DEPTH)
99			gsub(/IDNUM/, ID++)
100			print
101		}
102	}
103' <<EOFDEPTH
104$PROBE /this->dvp/ /* probe ID IDNUM (depth DEPTH) */
105{${TRACE:+
106	printf("<IDNUM>");}
107	this->dvp = this->dvp->nc_dvp != NULL ?
108		this->dvp->nc_dvp->v_cache_dst.tqh_first : 0;
109	this->nameDEPTH = this->dvp != 0 ? (
110		this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
111	) : "";
112}
113
114EOFDEPTH
115)
116
117$PROBE /this->dvp/ /* probe ID $(( $ID + $MAX_DEPTH + 3 )) */
118{${TRACE:+
119	printf("<$(( $ID + $MAX_DEPTH + 3 ))>");}
120	this->dvp = this->dvp->nc_dvp != NULL ?
121		this->dvp->nc_dvp->v_cache_dst.tqh_first : 0;
122	this->name$(( $MAX_DEPTH + 1 )) = this->dvp != 0 ? (
123		this->dvp->nc_dvp != NULL ? "..." : ""
124	) : "";
125}
126
127/*
128 * END Pathname-depth iterators
129 */
130
131/*********************************************************/
132
133$PROBE /this->fi_mount != 0/ /* probe ID $(( $ID + $MAX_DEPTH + 4 )) */
134{${TRACE:+
135	printf("<$(( $ID + $MAX_DEPTH + 4 ))>");
136}
137	/*
138	 * Join full path
139	 * NB: Up-to but not including the parent directory (joined below)
140	 */
141	this->path = this->fi_mount;
142	this->path = strjoin(this->path, this->fi_mount != 0 ? (
143		this->fi_mount == "/" ? "" : "/"
144	) : "/");
145	$( awk -v MAX_DEPTH=$MAX_DEPTH '
146		{ sub(/^\\\t/, "\t") }
147		{ buf = buf "\t" $0 "\n" }
148		END {
149			sub(/\n$/, "", buf)
150			$0 = buf
151			sub(/^[[:space:]]*/, "")
152			for (N = MAX_DEPTH + 1; N > 0; N--) {
153				gsub(/N/, N)
154				print
155				$0 = buf
156			}
157		}
158	' <<-EOFDEPTH
159	this->path = strjoin(this->path,
160	\	strjoin(this->nameN, this->nameN != "" ? "/" : ""));
161	EOFDEPTH
162	)
163
164	/* Join the parent directory name */
165	this->path = strjoin(this->path, strjoin(this->name =
166		(this->d_name != 0 ? this->d_name : ""),
167		this->name != "" ? "/" : ""));
168
169	/* Join the entry name */
170	this->path = strjoin(this->path,
171		this->name = (this->fi_name != 0 ? this->fi_name : ""));
172}
173EOF
174ACTIONS=$( cat <&9 )
175ID=$(( $ID + $MAX_DEPTH + 5 ))
176
177############################################################ EVENT ACTION
178
179EVENT_TEST="this->fi_mount != 0"
180
181############################################################ EVENT DETAILS
182
183if [ ! "$CUSTOM_DETAILS" ]; then
184exec 9<<EOF
185	/*
186	 * Print full path
187	 */
188	printf("%s", this->path);
189EOF
190EVENT_DETAILS=$( cat <&9 )
191fi
192
193################################################################################
194# END
195################################################################################
196