021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 1) #!/usr/bin/gawk -f
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 2) # SPDX-License-Identifier: GPL-2.0
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 3)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 4) # Script to check sysctl documentation against source files
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 5) #
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 6) # Copyright (c) 2020 Stephen Kitt
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 7)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 8) # Example invocation:
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 9) # scripts/check-sysctl-docs -vtable="kernel" \
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 10) # Documentation/admin-guide/sysctl/kernel.rst \
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 11) # $(git grep -l register_sysctl_)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 12) #
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 13) # Specify -vdebug=1 to see debugging information
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 14)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 15) BEGIN {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 16) if (!table) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 17) print "Please specify the table to look for using the table variable" > "/dev/stderr"
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 18) exit 1
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 19) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 20) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 21)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 22) # The following globals are used:
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 23) # children: maps ctl_table names and procnames to child ctl_table names
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 24) # documented: maps documented entries (each key is an entry)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 25) # entries: maps ctl_table names and procnames to counts (so
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 26) # enumerating the subkeys for a given ctl_table lists its
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 27) # procnames)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 28) # files: maps procnames to source file names
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 29) # paths: maps ctl_path names to paths
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 30) # curpath: the name of the current ctl_path struct
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 31) # curtable: the name of the current ctl_table struct
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 32) # curentry: the name of the current proc entry (procname when parsing
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 33) # a ctl_table, constructed path when parsing a ctl_path)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 34)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 35)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 36) # Remove punctuation from the given value
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 37) function trimpunct(value) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 38) while (value ~ /^["&]/) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 39) value = substr(value, 2)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 40) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 41) while (value ~ /[]["&,}]$/) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 42) value = substr(value, 1, length(value) - 1)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 43) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 44) return value
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 45) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 46)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 47) # Print the information for the given entry
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 48) function printentry(entry) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 49) seen[entry]++
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 50) printf "* %s from %s", entry, file[entry]
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 51) if (documented[entry]) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 52) printf " (documented)"
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 53) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 54) print ""
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 55) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 56)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 57)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 58) # Stage 1: build the list of documented entries
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 59) FNR == NR && /^=+$/ {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 60) if (prevline ~ /Documentation for/) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 61) # This is the main title
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 62) next
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 63) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 64)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 65) # The previous line is a section title, parse it
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 66) $0 = prevline
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 67) if (debug) print "Parsing " $0
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 68) inbrackets = 0
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 69) for (i = 1; i <= NF; i++) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 70) if (length($i) == 0) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 71) continue
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 72) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 73) if (!inbrackets && substr($i, 1, 1) == "(") {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 74) inbrackets = 1
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 75) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 76) if (!inbrackets) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 77) token = trimpunct($i)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 78) if (length(token) > 0 && token != "and") {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 79) if (debug) print trimpunct($i)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 80) documented[trimpunct($i)]++
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 81) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 82) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 83) if (inbrackets && substr($i, length($i), 1) == ")") {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 84) inbrackets = 0
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 85) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 86) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 87) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 88)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 89) FNR == NR {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 90) prevline = $0
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 91) next
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 92) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 93)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 94)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 95) # Stage 2: process each file and find all sysctl tables
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 96) BEGINFILE {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 97) delete children
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 98) delete entries
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 99) delete paths
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 100) curpath = ""
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 101) curtable = ""
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 102) curentry = ""
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 103) if (debug) print "Processing file " FILENAME
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 104) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 105)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 106) /^static struct ctl_path/ {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 107) match($0, /static struct ctl_path ([^][]+)/, tables)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 108) curpath = tables[1]
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 109) if (debug) print "Processing path " curpath
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 110) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 111)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 112) /^static struct ctl_table/ {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 113) match($0, /static struct ctl_table ([^][]+)/, tables)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 114) curtable = tables[1]
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 115) if (debug) print "Processing table " curtable
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 116) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 117)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 118) /^};$/ {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 119) curpath = ""
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 120) curtable = ""
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 121) curentry = ""
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 122) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 123)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 124) curpath && /\.procname[\t ]*=[\t ]*".+"/ {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 125) match($0, /.procname[\t ]*=[\t ]*"([^"]+)"/, names)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 126) if (curentry) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 127) curentry = curentry "/" names[1]
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 128) } else {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 129) curentry = names[1]
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 130) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 131) if (debug) print "Setting path " curpath " to " curentry
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 132) paths[curpath] = curentry
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 133) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 134)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 135) curtable && /\.procname[\t ]*=[\t ]*".+"/ {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 136) match($0, /.procname[\t ]*=[\t ]*"([^"]+)"/, names)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 137) curentry = names[1]
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 138) if (debug) print "Adding entry " curentry " to table " curtable
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 139) entries[curtable][curentry]++
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 140) file[curentry] = FILENAME
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 141) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 142)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 143) /\.child[\t ]*=/ {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 144) child = trimpunct($NF)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 145) if (debug) print "Linking child " child " to table " curtable " entry " curentry
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 146) children[curtable][curentry] = child
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 147) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 148)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 149) /register_sysctl_table\(.*\)/ {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 150) match($0, /register_sysctl_table\(([^)]+)\)/, tables)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 151) if (debug) print "Registering table " tables[1]
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 152) if (children[tables[1]][table]) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 153) for (entry in entries[children[tables[1]][table]]) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 154) printentry(entry)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 155) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 156) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 157) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 158)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 159) /register_sysctl_paths\(.*\)/ {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 160) match($0, /register_sysctl_paths\(([^)]+), ([^)]+)\)/, tables)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 161) if (debug) print "Attaching table " tables[2] " to path " tables[1]
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 162) if (paths[tables[1]] == table) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 163) for (entry in entries[tables[2]]) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 164) printentry(entry)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 165) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 166) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 167) split(paths[tables[1]], components, "/")
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 168) if (length(components) > 1 && components[1] == table) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 169) # Count the first subdirectory as seen
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 170) seen[components[2]]++
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 171) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 172) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 173)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 174)
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 175) END {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 176) for (entry in documented) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 177) if (!seen[entry]) {
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 178) print "No implementation for " entry
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 179) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 180) }
021622df556b7 (Stephen Kitt 2020-02-19 16:34:42 +0100 181) }