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_RENAME(9) [or similar] entry $
6# $Copyright: 2014-2018 Devin Teske. All rights reserved. $
7# $FreeBSD$
8#
9############################################################ DESCRIPTION
10#
11# Print filesystem paths being renamed by VOP_RENAME(9) [or similar]
12# NB: All paths are shown even if error prevents their rename.
13#
14############################################################ PROBE
15
16: ${PROBE:=vfs:vop:$PROFILE:entry}
17
18############################################################ ACTIONS
19
20exec 9<<EOF
21$PROBE /* probe ID $ID */
22{${TRACE:+
23	printf("<$ID>");}
24	this->fvp = args[1] ? args[1]->a_fdvp : NULL;
25	this->fncp = this->fvp != NULL ?
26		this->fvp->v_cache_dst.tqh_first : 0;
27	this->ffi_name = args[1] ? (
28		args[1]->a_fcnp != NULL ?
29			stringof(args[1]->a_fcnp->cn_nameptr) : ""
30	) : "";
31	this->fmount = this->fvp != NULL ?
32		this->fvp->v_mount : NULL; /* ptr to vfs we are in */
33	this->ffi_fs = this->fmount != NULL ?
34		stringof(this->fmount->mnt_stat.f_fstypename) : "";
35	this->ffi_mount = this->fmount != NULL ?
36		stringof(this->fmount->mnt_stat.f_mntonname) : "";
37	this->fd_name = args[0]->v_cache_dd != NULL ?
38		stringof(args[0]->v_cache_dd->nc_name) : "";
39
40	this->tvp = args[1] ? args[1]->a_tdvp : NULL;
41	this->tncp = this->tvp != NULL ?
42		this->tvp->v_cache_dst.tqh_first : 0;
43	this->tfi_name = args[1] ? (
44		args[1]->a_tcnp != NULL ?
45			stringof(args[1]->a_tcnp->cn_nameptr) : ""
46	) : "";
47	this->tmount = this->tvp != NULL ?
48		this->tvp->v_mount : NULL; /* ptr to vfs we are in */
49	this->tfi_fs = this->tmount != NULL ?
50		stringof(this->tmount->mnt_stat.f_fstypename) : "";
51	this->tfi_mount = this->tmount != NULL ?
52		stringof(this->tmount->mnt_stat.f_mntonname) : "";
53	this->td_name = this->tvp != NULL ? (
54		this->tvp->v_cache_dd != NULL ?
55			stringof(this->tvp->v_cache_dd->nc_name) : ""
56	) : "";
57
58	$( awk -v MAX_DEPTH=$MAX_DEPTH '
59		{ sub(/^\\\t/, "\t") }
60		{ buf = buf "\t" $0 "\n" }
61		END {
62			sub(/\n$/, "", buf)
63			$0 = buf
64			sub(/^[[:space:]]*/, "")
65			for (DEPTH = 1; DEPTH <= MAX_DEPTH + 1; DEPTH++) {
66				gsub(/DEPTH/, DEPTH)
67				print
68				$0 = buf
69			}
70		}
71	' <<-EOFDEPTH
72	this->fnameDEPTH = this->tnameDEPTH = "";
73	EOFDEPTH
74	)
75}
76
77$PROBE /this->fvp == 0 || this->ffi_fs == 0 ||
78	this->ffi_fs == "devfs" || this->ffi_fs == "" ||
79	this->ffi_name == ""/ /* probe ID $(( $ID + 1 )) */
80{${TRACE:+
81	printf("<$(( $ID + 1 ))>");}
82	this->fncp = 0;
83}
84
85$PROBE /this->tvp == 0 || this->tfi_fs == 0 ||
86	this->tfi_fs == "devfs" || this->tfi_fs == "" ||
87	this->tfi_name == ""/ /* probe ID $(( $ID + 2 )) */
88{${TRACE:+
89	printf("<$(( $ID + 2 ))>");}
90	this->tncp = 0;
91}
92
93/*********************************************************/
94
95$PROBE /this->fncp/ /* probe ID $(( $ID + 3 )) (depth 1) */
96{${TRACE:+
97	printf("<$(( $ID + 3 ))>");}
98	this->fdvp = this->fncp->nc_dvp != NULL ?
99		this->fncp->nc_dvp->v_cache_dst.tqh_first : 0;
100	this->fname1 = this->fdvp != 0 ? (
101		this->fdvp->nc_name != 0 ? stringof(this->fdvp->nc_name) : ""
102	) : "";
103}
104
105$PROBE /this->tncp/ /* probe ID $(( $ID + 4 )) (depth 1) */
106{${TRACE:+
107	printf("<$(( $ID + 4 ))>");}
108	this->tdvp = this->tncp->nc_dvp != NULL ?
109		this->tncp->nc_dvp->v_cache_dst.tqh_first : 0;
110	this->tname1 = this->tdvp != 0 ? (
111		this->tdvp->nc_name != 0 ? stringof(this->tdvp->nc_name) : ""
112	) : "";
113}
114
115$PROBE /this->fname1 == 0 || this->ffi_fs == 0 ||
116	this->ffi_fs == "devfs" || this->ffi_fs == "" ||
117	this->fname1 == "/" || this->fname1 == ""/ /* probe ID $((
118		$ID + 5
119	)) */
120{${TRACE:+
121	printf("<$(( $ID + 5 ))>");}
122	this->fdvp = 0;
123}
124
125$PROBE /this->tname1 == 0 || this->tfi_fs == 0 ||
126	this->tfi_fs == "devfs" || this->tfi_fs == "" ||
127	this->tname1 == "/" || this->tname1 == ""/ /* probe ID $((
128		$ID + 6
129	)) */
130{${TRACE:+
131	printf("<$(( $ID + 6 ))>");}
132	this->tdvp = 0;
133}
134
135/*********************************************************/
136
137/*
138 * BEGIN Pathname-depth iterators
139 */
140
141$( awk -v ID=$(( $ID + 7 )) -v MAX_DEPTH=$MAX_DEPTH '
142	{ buf = buf $0 "\n" }
143	END {
144		sub(/\n$/, "", buf)
145		for (DEPTH = 2; DEPTH <= MAX_DEPTH; DEPTH++) {
146			$0 = buf
147			gsub(/DEPTH/, DEPTH)
148			gsub(/IDNUM1/, ID)
149			gsub(/IDNUM2/, ID + 1)
150			print
151			ID = ID + 2
152		}
153	}
154' <<EOFDEPTH
155$PROBE /this->fdvp/ /* probe ID IDNUM1 (depth DEPTH) */
156{${TRACE:+
157	printf("<IDNUM1>");}
158	this->fdvp = this->fdvp->nc_dvp != NULL ?
159		this->fdvp->nc_dvp->v_cache_dst.tqh_first : 0;
160	this->fnameDEPTH = this->fdvp != 0 ? (
161		this->fdvp->nc_name != 0 ? stringof(this->fdvp->nc_name) : ""
162	) : "";
163}
164$PROBE /this->tdvp/ /* probe ID IDNUM2 (depth DEPTH) */
165{${TRACE:+
166	printf("<IDNUM2>");}
167	this->tdvp = this->tdvp->nc_dvp != NULL ?
168		this->tdvp->nc_dvp->v_cache_dst.tqh_first : 0;
169	this->tnameDEPTH = this->tdvp != 0 ? (
170		this->tdvp->nc_name != 0 ? stringof(this->tdvp->nc_name) : ""
171	) : "";
172}
173
174EOFDEPTH
175)
176
177$PROBE /this->fdvp/ /* probe ID $(( $ID + $MAX_DEPTH * 2 + 5 )) */
178{${TRACE:+
179	printf("<$(( $ID + $MAX_DEPTH * 2 + 5 ))>");}
180	this->fdvp = this->fdvp->nc_dvp != NULL ?
181		this->fdvp->nc_dvp->v_cache_dst.tqh_first : 0;
182	this->fname$(( $MAX_DEPTH + 1 )) = this->fdvp != 0 ? (
183		this->fdvp->nc_dvp != NULL ? "..." : ""
184	) : "";
185}
186$PROBE /this->tdvp/ /* probe ID $(( $ID + $MAX_DEPTH * 2 + 6 )) */
187{${TRACE:+
188	printf("<$(( $ID + $MAX_DEPTH * 2 + 6 ))>");}
189	this->tdvp = this->tdvp->nc_dvp != NULL ?
190		this->tdvp->nc_dvp->v_cache_dst.tqh_first : 0;
191	this->tname$(( $MAX_DEPTH + 1 )) = this->tdvp != 0 ? (
192		this->tdvp->nc_dvp != NULL ? "..." : ""
193	) : "";
194}
195
196/*
197 * END Pathname-depth iterators
198 */
199
200/*********************************************************/
201
202$PROBE /this->ffi_mount != 0 && this->tfi_mount != 0/ /* probe ID $((
203	$ID + $MAX_DEPTH * 2 + 7
204)) */
205{${TRACE:+
206	printf("<$(( $ID + $MAX_DEPTH * 2 + 7 ))>");
207}
208	/*
209	 * Join 'from' full path
210	 * NB: Up-to but not including the parent directory (joined below)
211	 */
212	this->fpath = this->ffi_mount;
213	this->fpath = strjoin(this->fpath, this->ffi_mount != 0 ? (
214		this->ffi_mount == "/" ? "" : "/"
215	) : "/");
216	$( awk -v MAX_DEPTH=$MAX_DEPTH '
217		{ sub(/^\\\t/, "\t") }
218		{ buf = buf "\t" $0 "\n" }
219		END {
220			sub(/\n$/, "", buf)
221			$0 = buf
222			sub(/^[[:space:]]*/, "")
223			for (N = MAX_DEPTH + 1; N > 0; N--) {
224				gsub(/N/, N)
225				print
226				$0 = buf
227			}
228		}
229	' <<-EOFDEPTH
230	this->fpath = strjoin(this->fpath,
231	\	strjoin(this->fnameN, this->fnameN != "" ? "/" : ""));
232	EOFDEPTH
233	)
234
235	/* Join the 'from' parent directory name */
236	this->fpath = strjoin(this->fpath, strjoin(this->fname =
237		(this->fd_name != 0 ? this->fd_name : ""),
238		this->fname != "" ? "/" : ""));
239
240	/* Join the 'from' entry name */
241	this->fpath = strjoin(this->fpath,
242		this->fname = (this->ffi_name != 0 ? this->ffi_name : ""));
243
244	/*
245	 * Join 'to' full path
246	 * NB: Up-to but not including the parent directory (joined below)
247	 */
248	this->tpath = this->tfi_mount;
249	this->tpath = strjoin(this->tpath, this->tfi_mount != 0 ? (
250		this->tfi_mount == "/" ? "" : "/"
251	) : "/");
252	$( awk -v MAX_DEPTH=$MAX_DEPTH '
253		{ sub(/^\\\t/, "\t") }
254		{ buf = buf "\t" $0 "\n" }
255		END {
256			sub(/\n$/, "", buf)
257			$0 = buf
258			sub(/^[[:space:]]*/, "")
259			for (N = MAX_DEPTH + 1; N > 0; N--) {
260				gsub(/N/, N)
261				print
262				$0 = buf
263			}
264		}
265	' <<-EOFDEPTH
266	this->tpath = strjoin(this->tpath,
267	\	strjoin(this->tnameN, this->tnameN != "" ? "/" : ""));
268	EOFDEPTH
269	)
270
271	/* Join the 'to' parent directory name */
272	this->tpath = strjoin(this->tpath, strjoin(this->tname =
273		(this->td_name != 0 ? this->td_name : ""),
274		this->tname != "" ? "/" : ""));
275
276	/* Join the 'to' entry name */
277	this->tpath = strjoin(this->tpath,
278		this->tname = (this->tfi_name != 0 ? this->tfi_name : ""));
279}
280EOF
281ACTIONS=$( cat <&9 )
282ID=$(( $ID + $MAX_DEPTH * 2 + 8 ))
283
284############################################################ EVENT ACTION
285
286EVENT_TEST="this->ffi_mount != 0 && this->tfi_mount != 0"
287
288############################################################ EVENT DETAILS
289
290if [ ! "$CUSTOM_DETAILS" ]; then
291exec 9<<EOF
292	/*
293	 * Print 'from' and 'to' full paths
294	 */
295	printf("%s -> %s", this->fpath, this->tpath);
296EOF
297EVENT_DETAILS=$( cat <&9 )
298fi
299
300################################################################################
301# END
302################################################################################
303