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