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