Changeset View
Standalone View
cddl/usr.sbin/dwatch/libexec/vop_rmdir
- This file was added.
Property | Old Value | New Value |
---|---|---|
svn:keywords | null | FreeBSD=%H \ No newline at end of property |
# -*- tab-width: 4 -*- ;; Emacs | |||||
# vi: set filetype=sh tabstop=8 shiftwidth=8 noexpandtab :: Vi/ViM | |||||
############################################################ IDENT(1) | |||||
# | |||||
# $Title: dwatch(8) module for VOP_RMDIR(9) entry $ | |||||
# $Copyright: 2014-2017 Devin Teske. All rights reserved. $ | |||||
# $FreeBSD$ | |||||
# | |||||
############################################################ DESCRIPTION | |||||
# | |||||
# Print directory paths being removed by VOP_RMDIR(9) | |||||
# NB: All paths are shown even if error prevents their removal. | |||||
# | |||||
############################################################ PROBE | |||||
# This is optional, if you don't set or it is NULL, dwatch(8) will try to | |||||
# dynamically determine the probe via the module's filename. For example, if | |||||
# the module file is named `foo' then dwatch(8) will try `dtrace -ln foo:entry' | |||||
# to determine an appropriate probe for watching `foo'. | |||||
PROBE=vfs:vop:vop_rmdir | |||||
asomers: The `vop_rmdir`, `vop_mkdir`, `vop_mknod`, `vop_remove`, `vop_lookup`, and `vop_create` scripts… | |||||
Done Inline ActionsWithout support for the entire VFS layer at this time, that is highly likely to change and I am not willing to centralize the logic until there is support for remaining items like VOP_SETATTR(9), VOP_LOCK(9), VOP_OPEN(9), VOP_RDWR(9), and other related functions which do not operate in the same manner. dteske: Without support for the entire VFS layer at this time, that is highly likely to change and I am… | |||||
############################################################ ACTIONS | |||||
# Optional actions to be performed before hitting the final print action | |||||
exec 9<<EOF | |||||
$PROBE:entry /* probe ID 2 */ | |||||
{ | |||||
this->vp = (struct vnode *)arg0; | |||||
this->ncp = this->vp != NULL ? | |||||
this->vp->v_cache_dst.tqh_first : 0; | |||||
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) : ""; | |||||
} | |||||
$PROBE:entry /this->vp == 0 || this->fi_fs == 0 || | |||||
this->fi_fs == "devfs" || this->fi_fs == "" || | |||||
this->fi_name == ""/ /* probe ID 3 */ | |||||
{ | |||||
this->ncp = 0; | |||||
} | |||||
/*********************************************************/ | |||||
$PROBE:entry /this->ncp/ /* probe ID 4 (depth 1) */ | |||||
{ | |||||
this->dvp = this->ncp->nc_dvp != NULL ? ( | |||||
this->ncp->nc_dvp != NULL ? | |||||
this->ncp->nc_dvp->v_cache_dst.tqh_first : 0 | |||||
) : 0; | |||||
this->name1 = this->dvp != 0 ? ( | |||||
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : "" | |||||
) : ""; | |||||
} | |||||
$PROBE:entry /this->name1 == 0 || this->fi_fs == 0 || | |||||
this->fi_fs == "devfs" || this->fi_fs == "" || | |||||
this->name1 == "/" || this->name1 == ""/ /* probe ID 5 */ | |||||
{ | |||||
this->dvp = 0; | |||||
} | |||||
/*********************************************************/ | |||||
/* | |||||
* BEGIN Pathname-depth iterators | |||||
*/ | |||||
$( awk -v ID=6 -v MAX_DEPTH=$MAX_DEPTH ' | |||||
buf = buf $0 "\n" { } | |||||
END { | |||||
for (DEPTH = 2; DEPTH <= MAX_DEPTH; DEPTH++) { | |||||
$0 = buf | |||||
gsub(/DEPTH/, DEPTH) | |||||
gsub(/IDNUM/, ID++) | |||||
sub(/\n$/, "") | |||||
} | |||||
} | |||||
' <<EOFDEPTH | |||||
$PROBE:entry /this->dvp/ /* probe ID IDNUM (depth DEPTH) */ | |||||
{ | |||||
this->dvp = this->dvp->nc_dvp != NULL ? ( | |||||
this->dvp->nc_dvp != NULL ? | |||||
this->dvp->nc_dvp->v_cache_dst.tqh_first : 0 | |||||
) : 0; | |||||
this->nameDEPTH = this->dvp != 0 ? ( | |||||
this->dvp->nc_name != 0 ? stringof(this->dvp->nc_name) : "" | |||||
) : ""; | |||||
} | |||||
EOFDEPTH | |||||
) | |||||
/* | |||||
* END Pathname-depth iterators | |||||
*/ | |||||
EOF | |||||
ACTIONS=$( cat <&9 ) | |||||
ID=$(( $MAX_DEPTH + 5 )) | |||||
############################################################ PRINT ACTION | |||||
# The default value is simply `entry'. This is paired with $PROBE (which can be | |||||
# auto-probed when unset or NULL) and can be customized to include clauses for | |||||
# the final print action which must be true before the print action will run. | |||||
PRINT="entry /this->fi_mount != 0/" | |||||
############################################################ EVENT TAG | |||||
# The EVENT_TAG is run inside the print action after the timestamp has been | |||||
# printed. By default, `UID.GID CMD[PID]: ' of the process is printed. | |||||
#exec 9<<EOF | |||||
#EOF | |||||
#EVENT_TAG=$( cat <&9 ) | |||||
############################################################ DETAILS | |||||
# The DETAILS are run after the EVENT_TAG and by default, the program name and | |||||
# arguments of the process hitting the PRINT action are shown. This can be | |||||
# customized to call-specific information because the `-v' flag of dwatch(8) | |||||
# can provide detailed process information for the PRINT action on lines below | |||||
# the DETAILS. | |||||
# | |||||
# NB: Should produce a single-line and not print a trailing newline. | |||||
exec 9<<EOF | |||||
/* | |||||
* Print full path | |||||
* NB: Up-to but not including the parent directory (printed below) | |||||
*/ | |||||
printf("%s%s", this->fi_mount, this->fi_mount != 0 ? ( | |||||
this->fi_mount == "/" ? "" : "/" | |||||
) : "/"); | |||||
$( awk -v MAX_DEPTH=$MAX_DEPTH ' | |||||
buf = buf $0 "\n" { } | |||||
END { | |||||
for (N = MAX_DEPTH; N > 0; N--) { | |||||
$0 = (N < MAX_DEPTH ? "\t" : "") buf | |||||
gsub(/N/, N) | |||||
sub(/\n$/, "") | |||||
} | |||||
} | |||||
' <<-EOFDEPTH | |||||
printf("%s%s", this->name = this->nameN, this->name != "" ? "/" : ""); | |||||
EOFDEPTH | |||||
) | |||||
/* Print the parent directory name */ | |||||
this->name = this->d_name != 0 ? this->d_name : ""; | |||||
printf("%s%s", this->name, this->name != "" ? "/" : ""); | |||||
/* Print the entry name */ | |||||
this->name = this->fi_name != 0 ? this->fi_name : ""; | |||||
printf("%s", this->name); | |||||
EOF | |||||
DETAILS=$( cat <&9 ) | |||||
################################################################################ | |||||
# END | |||||
################################################################################ | |||||
Done Inline ActionsWhat is this module supposed to do? When I invoke it with "dwatch vop_rmdir", the output is the same regardless of whether I have the modules installed. asomers: What is this module supposed to do? When I invoke it with "dwatch vop_rmdir", the output is… | |||||
Done Inline ActionsIt displays the filesystem path of the file being removed. Without the module (which you can disable with `-M') it displays the command name and arguments. See below. % dwatch -qc1 vop_remove dteske: It displays the filesystem path of the file being removed. Without the module (which you can… |
The vop_rmdir, vop_mkdir, vop_mknod, vop_remove, vop_lookup, and vop_create scripts are all identical but for the PROBE= line and some comments. Could they all be built from a common source file? Or better yet, could they all be installed as a single file with multiple hard links?