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