189b491bcSJoel Granados#!/usr/bin/env -S gawk -f 2021622dfSStephen Kitt# SPDX-License-Identifier: GPL-2.0 3021622dfSStephen Kitt 4021622dfSStephen Kitt# Script to check sysctl documentation against source files 5021622dfSStephen Kitt# 6021622dfSStephen Kitt# Copyright (c) 2020 Stephen Kitt 7021622dfSStephen Kitt 8021622dfSStephen Kitt# Example invocation: 9021622dfSStephen Kitt# scripts/check-sysctl-docs -vtable="kernel" \ 10021622dfSStephen Kitt# Documentation/admin-guide/sysctl/kernel.rst \ 110f6588b3SThomas Weißschuh# $(git grep -l register_sysctl) 12021622dfSStephen Kitt# 13021622dfSStephen Kitt# Specify -vdebug=1 to see debugging information 14021622dfSStephen Kitt 15021622dfSStephen KittBEGIN { 16021622dfSStephen Kitt if (!table) { 17021622dfSStephen Kitt print "Please specify the table to look for using the table variable" > "/dev/stderr" 18021622dfSStephen Kitt exit 1 19021622dfSStephen Kitt } 20be0aef10SJoel Granados 21be0aef10SJoel Granados # Documentation title skiplist 22be0aef10SJoel Granados skiplist[0] = "^Documentation for" 23be0aef10SJoel Granados skiplist[1] = "Network core options$" 24be0aef10SJoel Granados skiplist[2] = "POSIX message queues filesystem$" 25be0aef10SJoel Granados skiplist[3] = "Configuration options" 26be0aef10SJoel Granados skiplist[4] = ". /proc/sys/fs" 27be0aef10SJoel Granados skiplist[5] = "^Introduction$" 28be0aef10SJoel Granados skiplist[6] = "^seccomp$" 29be0aef10SJoel Granados skiplist[7] = "^pty$" 30be0aef10SJoel Granados skiplist[8] = "^firmware_config$" 31be0aef10SJoel Granados skiplist[9] = "^random$" 32021622dfSStephen Kitt} 33021622dfSStephen Kitt 34021622dfSStephen Kitt# The following globals are used: 35021622dfSStephen Kitt# documented: maps documented entries (each key is an entry) 36021622dfSStephen Kitt# entries: maps ctl_table names and procnames to counts (so 37021622dfSStephen Kitt# enumerating the subkeys for a given ctl_table lists its 38021622dfSStephen Kitt# procnames) 39021622dfSStephen Kitt# curtable: the name of the current ctl_table struct 40021622dfSStephen Kitt# curentry: the name of the current proc entry (procname when parsing 41021622dfSStephen Kitt# a ctl_table, constructed path when parsing a ctl_path) 42021622dfSStephen Kitt 43021622dfSStephen Kitt 44021622dfSStephen Kitt# Remove punctuation from the given value 45021622dfSStephen Kittfunction trimpunct(value) { 46021622dfSStephen Kitt while (value ~ /^["&]/) { 47021622dfSStephen Kitt value = substr(value, 2) 48021622dfSStephen Kitt } 49021622dfSStephen Kitt while (value ~ /[]["&,}]$/) { 50021622dfSStephen Kitt value = substr(value, 1, length(value) - 1) 51021622dfSStephen Kitt } 52021622dfSStephen Kitt return value 53021622dfSStephen Kitt} 54021622dfSStephen Kitt 55021622dfSStephen Kitt# Print the information for the given entry 56021622dfSStephen Kittfunction printentry(entry) { 57021622dfSStephen Kitt seen[entry]++ 58021622dfSStephen Kitt printf "* %s from %s", entry, file[entry] 59021622dfSStephen Kitt if (documented[entry]) { 60021622dfSStephen Kitt printf " (documented)" 61021622dfSStephen Kitt } 62021622dfSStephen Kitt print "" 63021622dfSStephen Kitt} 64021622dfSStephen Kitt 65021622dfSStephen Kitt 66021622dfSStephen Kitt# Stage 1: build the list of documented entries 67021622dfSStephen KittFNR == NR && /^=+$/ { 68be0aef10SJoel Granados for (i in skiplist) { 69be0aef10SJoel Granados if (prevline ~ skiplist[i]) { 70021622dfSStephen Kitt next 71021622dfSStephen Kitt } 72be0aef10SJoel Granados } 73021622dfSStephen Kitt 74021622dfSStephen Kitt # The previous line is a section title, parse it 75021622dfSStephen Kitt $0 = prevline 76021622dfSStephen Kitt if (debug) print "Parsing " $0 77021622dfSStephen Kitt inbrackets = 0 78021622dfSStephen Kitt for (i = 1; i <= NF; i++) { 79021622dfSStephen Kitt if (length($i) == 0) { 80021622dfSStephen Kitt continue 81021622dfSStephen Kitt } 82021622dfSStephen Kitt if (!inbrackets && substr($i, 1, 1) == "(") { 83021622dfSStephen Kitt inbrackets = 1 84021622dfSStephen Kitt } 85021622dfSStephen Kitt if (!inbrackets) { 86021622dfSStephen Kitt token = trimpunct($i) 87021622dfSStephen Kitt if (length(token) > 0 && token != "and") { 88021622dfSStephen Kitt if (debug) print trimpunct($i) 89021622dfSStephen Kitt documented[trimpunct($i)]++ 90021622dfSStephen Kitt } 91021622dfSStephen Kitt } 92021622dfSStephen Kitt if (inbrackets && substr($i, length($i), 1) == ")") { 93021622dfSStephen Kitt inbrackets = 0 94021622dfSStephen Kitt } 95021622dfSStephen Kitt } 96021622dfSStephen Kitt} 97021622dfSStephen Kitt 98021622dfSStephen KittFNR == NR { 99021622dfSStephen Kitt prevline = $0 100021622dfSStephen Kitt next 101021622dfSStephen Kitt} 102021622dfSStephen Kitt 103021622dfSStephen Kitt 104021622dfSStephen Kitt# Stage 2: process each file and find all sysctl tables 105021622dfSStephen KittBEGINFILE { 106021622dfSStephen Kitt delete entries 107021622dfSStephen Kitt curtable = "" 108021622dfSStephen Kitt curentry = "" 1094f1136a5SThomas Weißschuh delete vars 110021622dfSStephen Kitt if (debug) print "Processing file " FILENAME 111021622dfSStephen Kitt} 112021622dfSStephen Kitt 1130f6588b3SThomas Weißschuh/^static( const)? struct ctl_table/ { 1140f6588b3SThomas Weißschuh match($0, /static( const)? struct ctl_table ([^][]+)/, tables) 1150f6588b3SThomas Weißschuh curtable = tables[2] 116021622dfSStephen Kitt if (debug) print "Processing table " curtable 117021622dfSStephen Kitt} 118021622dfSStephen Kitt 119021622dfSStephen Kitt/^};$/ { 120021622dfSStephen Kitt curtable = "" 121021622dfSStephen Kitt curentry = "" 1224f1136a5SThomas Weißschuh delete vars 123021622dfSStephen Kitt} 124021622dfSStephen Kitt 125021622dfSStephen Kittcurtable && /\.procname[\t ]*=[\t ]*".+"/ { 126021622dfSStephen Kitt match($0, /.procname[\t ]*=[\t ]*"([^"]+)"/, names) 127021622dfSStephen Kitt curentry = names[1] 128021622dfSStephen Kitt if (debug) print "Adding entry " curentry " to table " curtable 129021622dfSStephen Kitt entries[curtable][curentry]++ 130021622dfSStephen Kitt file[curentry] = FILENAME 131021622dfSStephen Kitt} 132021622dfSStephen Kitt 133e97a96baSJoel Granadoscurtable && /UCOUNT_ENTRY.*/ { 134e97a96baSJoel Granados match($0, /UCOUNT_ENTRY\("([^"]+)"\)/, names) 135e97a96baSJoel Granados curentry = names[1] 136e97a96baSJoel Granados if (debug) print "Adding entry " curentry " to table " curtable 137e97a96baSJoel Granados entries[curtable][curentry]++ 138e97a96baSJoel Granados file[curentry] = FILENAME 139e97a96baSJoel Granados} 140e97a96baSJoel Granados 1410f6588b3SThomas Weißschuh/register_sysctl.*/ { 1420f6588b3SThomas Weißschuh match($0, /register_sysctl(|_init|_sz)\("([^"]+)" *, *([^,)]+)/, tables) 1430f6588b3SThomas Weißschuh if (debug) print "Registering table " tables[3] " at " tables[2] 1440f6588b3SThomas Weißschuh if (tables[2] == table) { 1450f6588b3SThomas Weißschuh for (entry in entries[tables[3]]) { 1460f6588b3SThomas Weißschuh printentry(entry) 1470f6588b3SThomas Weißschuh } 1480f6588b3SThomas Weißschuh } 149021622dfSStephen Kitt} 150021622dfSStephen Kitt 1514f1136a5SThomas Weißschuh/kmemdup.*/ { 1524f1136a5SThomas Weißschuh match($0, /([^ \t]+) *= *kmemdup\(([^,]+) *,/, names) 1534f1136a5SThomas Weißschuh if (debug) print "Found variable " names[1] " for table " names[2] 1544f1136a5SThomas Weißschuh if (names[2] in entries) { 1554f1136a5SThomas Weißschuh vars[names[1]] = names[2] 1564f1136a5SThomas Weißschuh } 1574f1136a5SThomas Weißschuh} 1584f1136a5SThomas Weißschuh 1594f1136a5SThomas Weißschuh/__register_sysctl_table.*/ { 1604f1136a5SThomas Weißschuh match($0, /__register_sysctl_table\([^,]+, *"([^"]+)" *, *([^,]+)/, tables) 1614f1136a5SThomas Weißschuh if (debug) print "Registering variable table " tables[2] " at " tables[1] 1624f1136a5SThomas Weißschuh if (tables[1] == table && tables[2] in vars) { 1634f1136a5SThomas Weißschuh for (entry in entries[vars[tables[2]]]) { 1644f1136a5SThomas Weißschuh printentry(entry) 1654f1136a5SThomas Weißschuh } 1664f1136a5SThomas Weißschuh } 1674f1136a5SThomas Weißschuh} 1684f1136a5SThomas Weißschuh 169021622dfSStephen KittEND { 170021622dfSStephen Kitt for (entry in documented) { 171*999aab7fSJoel Granados if (!seen[entry]) 172021622dfSStephen Kitt print "No implementation for " entry 173021622dfSStephen Kitt } 174021622dfSStephen Kitt} 175