freebsd-dev/cddl/usr.sbin/dwatch/libexec/vop_symlink
Devin Teske a061d97027 dwatch(1): Allow `-E code' to override profile EVENT_DETAILS
This allows quick changes to the formatted output of a profile.

Sponsored by:	Smule, Inc.
2018-05-12 06:01:41 +00:00

198 lines
5.0 KiB
Bash

# -*- tab-width: 4 -*- ;; Emacs
# vi: set filetype=sh tabstop=8 shiftwidth=8 noexpandtab :: Vi/ViM
############################################################ IDENT(1)
#
# $Title: dwatch(8) module for VOP_SYMLINK(9) [or similar] entry $
# $Copyright: 2014-2018 Devin Teske. All rights reserved. $
# $FreeBSD$
#
############################################################ DESCRIPTION
#
# Print symlink paths being created by VOP_SYMLINK(9) [or similar]
# NB: All paths are shown even if error prevents their creation.
#
############################################################ PROBE
: ${PROBE:=vfs:vop:$PROFILE:entry}
############################################################ ACTIONS
exec 9<<EOF
$PROBE /* probe ID $ID */
{${TRACE:+
printf("<$ID>");}
this->vp = (struct vnode *)arg0;
this->ncp = this->vp != NULL ?
this->vp->v_cache_dst.tqh_first : 0;
this->target = args[1] ? args[1]->a_target : "";
this->fi_name = args[1] ? (
args[1]->a_cnp != NULL ?
stringof(args[1]->a_cnp->cn_nameptr) : ""
) : "";
this->mount = this->vp != NULL ?
this->vp->v_mount : NULL; /* ptr to vfs we are in */
this->fi_fs = this->mount != NULL ?
stringof(this->mount->mnt_stat.f_fstypename) : "";
this->fi_mount = this->mount != NULL ?
stringof(this->mount->mnt_stat.f_mntonname) : "";
this->d_name = args[0]->v_cache_dd != NULL ?
stringof(args[0]->v_cache_dd->nc_name) : "";
$( awk -v MAX_DEPTH=$MAX_DEPTH '
{ sub(/^\\\t/, "\t") }
{ buf = buf "\t" $0 "\n" }
END {
sub(/\n$/, "", buf)
$0 = buf
sub(/^[[:space:]]*/, "")
for (DEPTH = 1; DEPTH <= MAX_DEPTH + 1; DEPTH++) {
gsub(/DEPTH/, DEPTH)
print
$0 = buf
}
}
' <<-EOFDEPTH
this->nameDEPTH = "";
EOFDEPTH
)
}
$PROBE /this->vp == 0 || this->fi_fs == 0 ||
this->fi_fs == "devfs" || this->fi_fs == "" ||
this->fi_name == ""/ /* probe ID $(( $ID + 1 )) */
{${TRACE:+
printf("<$(( $ID + 1 ))>");}
this->ncp = 0;
}
/*********************************************************/
$PROBE /this->ncp/ /* probe ID $(( $ID + 2 )) (depth 1) */
{${TRACE:+
printf("<$(( $ID + 2 ))>");}
this->dvp = this->ncp->nc_dvp != NULL ?
this->ncp->nc_dvp->v_cache_dst.tqh_first : 0;
this->name1 = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
$PROBE /this->name1 == 0 || this->fi_fs == 0 ||
this->fi_fs == "devfs" || this->fi_fs == "" ||
this->name1 == "/" || this->name1 == ""/ /* probe ID $(( $ID + 3 )) */
{${TRACE:+
printf("<$(( $ID + 3 ))>");}
this->dvp = 0;
}
/*********************************************************/
/*
* BEGIN Pathname-depth iterators
*/
$( awk -v ID=$(( $ID + 4 )) -v MAX_DEPTH=$MAX_DEPTH '
{ buf = buf $0 "\n" }
END {
sub(/\n$/, "", buf)
for (DEPTH = 2; DEPTH <= MAX_DEPTH; DEPTH++) {
$0 = buf
gsub(/DEPTH/, DEPTH)
gsub(/IDNUM/, ID++)
print
}
}
' <<EOFDEPTH
$PROBE /this->dvp/ /* probe ID IDNUM (depth DEPTH) */
{${TRACE:+
printf("<IDNUM>");}
this->dvp = this->dvp->nc_dvp != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0;
this->nameDEPTH = this->dvp != 0 ? (
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : ""
) : "";
}
EOFDEPTH
)
$PROBE /this->dvp/ /* probe ID $(( $ID + $MAX_DEPTH + 3 )) */
{${TRACE:+
printf("<$(( $ID + $MAX_DEPTH + 3 ))>");}
this->dvp = this->dvp->nc_dvp != NULL ?
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0;
this->name$(( $MAX_DEPTH + 1 )) = this->dvp != 0 ? (
this->dvp->nc_dvp != NULL ? "..." : ""
) : "";
}
/*
* END Pathname-depth iterators
*/
/*********************************************************/
$PROBE /this->fi_mount != 0/ /* probe ID $(( $ID + $MAX_DEPTH + 4 )) */
{${TRACE:+
printf("<$(( $ID + $MAX_DEPTH + 4 ))>");
}
/*
* Join full path
* NB: Up-to but not including the parent directory (joined below)
*/
this->path = this->fi_mount;
this->path = strjoin(this->path, this->fi_mount != 0 ? (
this->fi_mount == "/" ? "" : "/"
) : "/");
$( awk -v MAX_DEPTH=$MAX_DEPTH '
{ sub(/^\\\t/, "\t") }
{ buf = buf "\t" $0 "\n" }
END {
sub(/\n$/, "", buf)
$0 = buf
sub(/^[[:space:]]*/, "")
for (N = MAX_DEPTH + 1; N > 0; N--) {
gsub(/N/, N)
print
$0 = buf
}
}
' <<-EOFDEPTH
this->path = strjoin(this->path,
\ strjoin(this->nameN, this->nameN != "" ? "/" : ""));
EOFDEPTH
)
/* Join the parent directory name */
this->path = strjoin(this->path, strjoin(this->name =
(this->d_name != 0 ? this->d_name : ""),
this->name != "" ? "/" : ""));
/* Join the entry name */
this->path = strjoin(this->path,
this->name = (this->fi_name != 0 ? this->fi_name : ""));
}
EOF
ACTIONS=$( cat <&9 )
ID=$(( $ID + $MAX_DEPTH + 5 ))
############################################################ EVENT ACTION
EVENT_TEST="this->fi_mount != 0"
############################################################ EVENT DETAILS
if [ ! "$CUSTOM_DETAILS" ]; then
exec 9<<EOF
/*
* Print full path and target
*/
printf("%s -> %s", this->path, this->target);
EOF
EVENT_DETAILS=$( cat <&9 )
fi
################################################################################
# END
################################################################################