1#!/bin/bash 2 3set -e 4 5die() { 6 printf '%s\n' "$*" >&2 7 exit 1 8} 9 10EXCLUDE_PATHS_TOPLEVEL=( 11 "include/linux-private" 12) 13 14# The following files are currently not formatted with clang. 15# Exclude them too. 16EXCLUDE_PATHS_TOPLEVEL+=( 17 "include/netlink/addr.h" 18 "include/netlink/attr.h" 19 "include/netlink/cache-api.h" 20 "include/netlink/cache.h" 21 "include/netlink/cli/addr.h" 22 "include/netlink/cli/cls.h" 23 "include/netlink/cli/link.h" 24 "include/netlink/cli/mdb.h" 25 "include/netlink/cli/neigh.h" 26 "include/netlink/cli/qdisc.h" 27 "include/netlink/cli/route.h" 28 "include/netlink/cli/tc.h" 29 "include/netlink/cli/utils.h" 30 "include/netlink/data.h" 31 "include/netlink/errno.h" 32 "include/netlink/fib_lookup/lookup.h" 33 "include/netlink/fib_lookup/request.h" 34 "include/netlink/genl/ctrl.h" 35 "include/netlink/genl/family.h" 36 "include/netlink/genl/genl.h" 37 "include/netlink/genl/mngt.h" 38 "include/netlink/handlers.h" 39 "include/netlink/hash.h" 40 "include/netlink/hashtable.h" 41 "include/netlink/idiag/idiagnl.h" 42 "include/netlink/idiag/meminfo.h" 43 "include/netlink/idiag/msg.h" 44 "include/netlink/idiag/req.h" 45 "include/netlink/idiag/vegasinfo.h" 46 "include/netlink/list.h" 47 "include/netlink/msg.h" 48 "include/netlink/netfilter/ct.h" 49 "include/netlink/netfilter/exp.h" 50 "include/netlink/netfilter/log.h" 51 "include/netlink/netfilter/log_msg.h" 52 "include/netlink/netfilter/netfilter.h" 53 "include/netlink/netfilter/nfnl.h" 54 "include/netlink/netfilter/queue.h" 55 "include/netlink/netfilter/queue_msg.h" 56 "include/netlink/netlink-compat.h" 57 "include/netlink/netlink-kernel.h" 58 "include/netlink/netlink.h" 59 "include/netlink/object.h" 60 "include/netlink/route/act/skbedit.h" 61 "include/netlink/route/action.h" 62 "include/netlink/route/addr.h" 63 "include/netlink/route/class.h" 64 "include/netlink/route/classifier.h" 65 "include/netlink/route/cls/basic.h" 66 "include/netlink/route/cls/cgroup.h" 67 "include/netlink/route/cls/ematch.h" 68 "include/netlink/route/cls/ematch/cmp.h" 69 "include/netlink/route/cls/ematch/meta.h" 70 "include/netlink/route/cls/ematch/nbyte.h" 71 "include/netlink/route/cls/ematch/text.h" 72 "include/netlink/route/cls/flower.h" 73 "include/netlink/route/cls/fw.h" 74 "include/netlink/route/cls/matchall.h" 75 "include/netlink/route/cls/police.h" 76 "include/netlink/route/cls/u32.h" 77 "include/netlink/route/link.h" 78 "include/netlink/route/link/api.h" 79 "include/netlink/route/link/bonding.h" 80 "include/netlink/route/link/bridge.h" 81 "include/netlink/route/link/can.h" 82 "include/netlink/route/link/geneve.h" 83 "include/netlink/route/link/inet.h" 84 "include/netlink/route/link/inet6.h" 85 "include/netlink/route/link/info-api.h" 86 "include/netlink/route/link/ip6gre.h" 87 "include/netlink/route/link/ip6tnl.h" 88 "include/netlink/route/link/ip6vti.h" 89 "include/netlink/route/link/ipgre.h" 90 "include/netlink/route/link/ipip.h" 91 "include/netlink/route/link/ipvlan.h" 92 "include/netlink/route/link/ipvti.h" 93 "include/netlink/route/link/macsec.h" 94 "include/netlink/route/link/macvlan.h" 95 "include/netlink/route/link/macvtap.h" 96 "include/netlink/route/link/ppp.h" 97 "include/netlink/route/link/sit.h" 98 "include/netlink/route/link/sriov.h" 99 "include/netlink/route/link/team.h" 100 "include/netlink/route/link/vlan.h" 101 "include/netlink/route/link/vxlan.h" 102 "include/netlink/route/link/xfrmi.h" 103 "include/netlink/route/mdb.h" 104 "include/netlink/route/neighbour.h" 105 "include/netlink/route/neightbl.h" 106 "include/netlink/route/netconf.h" 107 "include/netlink/route/nexthop.h" 108 "include/netlink/route/pktloc.h" 109 "include/netlink/route/qdisc.h" 110 "include/netlink/route/qdisc/cbq.h" 111 "include/netlink/route/qdisc/dsmark.h" 112 "include/netlink/route/qdisc/fifo.h" 113 "include/netlink/route/qdisc/fq_codel.h" 114 "include/netlink/route/qdisc/hfsc.h" 115 "include/netlink/route/qdisc/htb.h" 116 "include/netlink/route/qdisc/mqprio.h" 117 "include/netlink/route/qdisc/netem.h" 118 "include/netlink/route/qdisc/plug.h" 119 "include/netlink/route/qdisc/prio.h" 120 "include/netlink/route/qdisc/red.h" 121 "include/netlink/route/qdisc/sfq.h" 122 "include/netlink/route/route.h" 123 "include/netlink/route/rtnl.h" 124 "include/netlink/route/rule.h" 125 "include/netlink/route/tc-api.h" 126 "include/netlink/route/tc.h" 127 "include/netlink/socket.h" 128 "include/netlink/types.h" 129 "include/netlink/utils.h" 130 "include/netlink/xfrm/ae.h" 131 "include/netlink/xfrm/lifetime.h" 132 "include/netlink/xfrm/sa.h" 133 "include/netlink/xfrm/selector.h" 134 "include/netlink/xfrm/sp.h" 135 "include/netlink/xfrm/template.h" 136 "include/nl-priv-dynamic-core/cache-api.h" 137 "include/nl-priv-dynamic-core/object-api.h" 138 "lib/addr.c" 139 "lib/attr.c" 140 "lib/cache.c" 141 "lib/cache_mngr.c" 142 "lib/cache_mngt.c" 143 "lib/cli/cls/basic.c" 144 "lib/cli/cls/cgroup.c" 145 "lib/cli/qdisc/bfifo.c" 146 "lib/cli/qdisc/blackhole.c" 147 "lib/cli/qdisc/fq_codel.c" 148 "lib/cli/qdisc/hfsc.c" 149 "lib/cli/qdisc/htb.c" 150 "lib/cli/qdisc/ingress.c" 151 "lib/cli/qdisc/pfifo.c" 152 "lib/cli/qdisc/plug.c" 153 "lib/data.c" 154 "lib/error.c" 155 "lib/fib_lookup/lookup.c" 156 "lib/fib_lookup/request.c" 157 "lib/genl/ctrl.c" 158 "lib/genl/family.c" 159 "lib/genl/genl.c" 160 "lib/genl/mngt.c" 161 "lib/genl/nl-genl.h" 162 "lib/handlers.c" 163 "lib/hash.c" 164 "lib/hashtable.c" 165 "lib/idiag/idiag.c" 166 "lib/idiag/idiag_meminfo_obj.c" 167 "lib/idiag/idiag_msg_obj.c" 168 "lib/idiag/idiag_req_obj.c" 169 "lib/idiag/idiag_vegasinfo_obj.c" 170 "lib/mpls.c" 171 "lib/mpls.h" 172 "lib/msg.c" 173 "lib/netfilter/ct.c" 174 "lib/netfilter/ct_obj.c" 175 "lib/netfilter/exp.c" 176 "lib/netfilter/exp_obj.c" 177 "lib/netfilter/log.c" 178 "lib/netfilter/log_msg.c" 179 "lib/netfilter/log_msg_obj.c" 180 "lib/netfilter/log_obj.c" 181 "lib/netfilter/netfilter.c" 182 "lib/netfilter/nfnl.c" 183 "lib/netfilter/queue.c" 184 "lib/netfilter/queue_msg.c" 185 "lib/netfilter/queue_msg_obj.c" 186 "lib/netfilter/queue_obj.c" 187 "lib/nl-core.h" 188 "lib/nl.c" 189 "lib/object.c" 190 "lib/route/act.c" 191 "lib/route/act/gact.c" 192 "lib/route/act/mirred.c" 193 "lib/route/act/skbedit.c" 194 "lib/route/act/vlan.c" 195 "lib/route/addr.c" 196 "lib/route/class.c" 197 "lib/route/classid.c" 198 "lib/route/cls.c" 199 "lib/route/cls/basic.c" 200 "lib/route/cls/cgroup.c" 201 "lib/route/cls/ematch.c" 202 "lib/route/cls/ematch/cmp.c" 203 "lib/route/cls/ematch/container.c" 204 "lib/route/cls/ematch/meta.c" 205 "lib/route/cls/ematch/nbyte.c" 206 "lib/route/cls/ematch/text.c" 207 "lib/route/cls/flower.c" 208 "lib/route/cls/fw.c" 209 "lib/route/cls/mall.c" 210 "lib/route/cls/police.c" 211 "lib/route/cls/u32.c" 212 "lib/route/link-sriov.h" 213 "lib/route/link.c" 214 "lib/route/link/api.c" 215 "lib/route/link/bonding.c" 216 "lib/route/link/bridge.c" 217 "lib/route/link/can.c" 218 "lib/route/link/dummy.c" 219 "lib/route/link/geneve.c" 220 "lib/route/link/ifb.c" 221 "lib/route/link/inet.c" 222 "lib/route/link/inet6.c" 223 "lib/route/link/ip6gre.c" 224 "lib/route/link/ip6tnl.c" 225 "lib/route/link/ip6vti.c" 226 "lib/route/link/ipgre.c" 227 "lib/route/link/ipip.c" 228 "lib/route/link/ipvlan.c" 229 "lib/route/link/ipvti.c" 230 "lib/route/link/link-api.h" 231 "lib/route/link/macsec.c" 232 "lib/route/link/macvlan.c" 233 "lib/route/link/ppp.c" 234 "lib/route/link/sit.c" 235 "lib/route/link/sriov.c" 236 "lib/route/link/team.c" 237 "lib/route/link/veth.c" 238 "lib/route/link/vlan.c" 239 "lib/route/link/vrf.c" 240 "lib/route/link/vxlan.c" 241 "lib/route/link/xfrmi.c" 242 "lib/route/mdb.c" 243 "lib/route/neigh.c" 244 "lib/route/netconf.c" 245 "lib/route/nexthop-encap.h" 246 "lib/route/nexthop.c" 247 "lib/route/nexthop_encap.c" 248 "lib/route/nh_encap_mpls.c" 249 "lib/route/pktloc.c" 250 "lib/route/qdisc.c" 251 "lib/route/qdisc/blackhole.c" 252 "lib/route/qdisc/cbq.c" 253 "lib/route/qdisc/dsmark.c" 254 "lib/route/qdisc/fifo.c" 255 "lib/route/qdisc/fq_codel.c" 256 "lib/route/qdisc/hfsc.c" 257 "lib/route/qdisc/htb.c" 258 "lib/route/qdisc/ingress.c" 259 "lib/route/qdisc/mqprio.c" 260 "lib/route/qdisc/netem.c" 261 "lib/route/qdisc/plug.c" 262 "lib/route/qdisc/prio.c" 263 "lib/route/qdisc/red.c" 264 "lib/route/qdisc/sfq.c" 265 "lib/route/qdisc/tbf.c" 266 "lib/route/route.c" 267 "lib/route/route_obj.c" 268 "lib/route/route_utils.c" 269 "lib/route/rtnl.c" 270 "lib/route/rule.c" 271 "lib/route/tc-api.h" 272 "lib/route/tc.c" 273 "lib/socket.c" 274 "lib/utils.c" 275 "lib/version.c" 276 "lib/xfrm/ae.c" 277 "lib/xfrm/lifetime.c" 278 "lib/xfrm/sa.c" 279 "lib/xfrm/selector.c" 280 "lib/xfrm/sp.c" 281 "lib/xfrm/template.c" 282 "python/netlink/utils.h" 283 "src/genl-ctrl-list.c" 284 "src/idiag-socket-details.c" 285 "src/lib/addr.c" 286 "src/lib/cls.c" 287 "src/lib/ct.c" 288 "src/lib/exp.c" 289 "src/lib/link.c" 290 "src/lib/neigh.c" 291 "src/lib/route.c" 292 "src/lib/tc.c" 293 "src/lib/utils.c" 294 "src/nf-ct-add.c" 295 "src/nf-ct-events.c" 296 "src/nf-ct-list.c" 297 "src/nf-exp-add.c" 298 "src/nf-exp-delete.c" 299 "src/nf-exp-list.c" 300 "src/nf-log.c" 301 "src/nf-monitor.c" 302 "src/nf-queue.c" 303 "src/nl-addr-add.c" 304 "src/nl-addr-delete.c" 305 "src/nl-addr-list.c" 306 "src/nl-class-add.c" 307 "src/nl-class-delete.c" 308 "src/nl-class-list.c" 309 "src/nl-classid-lookup.c" 310 "src/nl-cls-add.c" 311 "src/nl-cls-delete.c" 312 "src/nl-cls-list.c" 313 "src/nl-fib-lookup.c" 314 "src/nl-link-enslave.c" 315 "src/nl-link-list.c" 316 "src/nl-link-release.c" 317 "src/nl-link-set.c" 318 "src/nl-link-stats.c" 319 "src/nl-list-caches.c" 320 "src/nl-list-sockets.c" 321 "src/nl-monitor.c" 322 "src/nl-neigh-add.c" 323 "src/nl-neigh-delete.c" 324 "src/nl-neigh-list.c" 325 "src/nl-neightbl-list.c" 326 "src/nl-pktloc-lookup.c" 327 "src/nl-qdisc-add.c" 328 "src/nl-qdisc-delete.c" 329 "src/nl-qdisc-list.c" 330 "src/nl-route-add.c" 331 "src/nl-route-delete.c" 332 "src/nl-route-get.c" 333 "src/nl-route-list.c" 334 "src/nl-rule-list.c" 335 "src/nl-tctree-list.c" 336 "src/nl-util-addr.c" 337 "tests/test-cache-mngr.c" 338 "tests/test-complex-HTB-with-hash-filters.c" 339 "tests/test-create-bridge.c" 340 "tests/test-create-geneve.c" 341 "tests/test-create-ip6tnl.c" 342 "tests/test-create-ipgre.c" 343 "tests/test-create-ipgretap.c" 344 "tests/test-create-ipip.c" 345 "tests/test-create-ipvti.c" 346 "tests/test-create-macsec.c" 347 "tests/test-create-macvlan.c" 348 "tests/test-create-macvtap.c" 349 "tests/test-create-sit.c" 350 "tests/test-create-veth.c" 351 "tests/test-create-xfrmi.c" 352 "tests/test-genl.c" 353 "tests/test-nf-cache-mngr.c" 354 "tests/test-socket-creation.c" 355 "tests/test-u32-filter-with-actions.c" 356) 357 358DIR_ROOT="$(git rev-parse --show-toplevel)" || die "not inside a git repository" 359DIR_PREFIX="$(git rev-parse --show-prefix)" || die "not inside a git repository" 360 361if [ ! -f "$DIR_ROOT/.clang-format" ]; then 362 die "Error: the clang-format file in \"$DIR_ROOT\" does not exist" 363fi 364 365if ! command -v clang-format &> /dev/null; then 366 die "Error: clang-format is not installed. On RHEL/Fedora/CentOS run 'dnf install clang-tools-extra'" 367fi 368 369if test -n "$DIR_PREFIX"; then 370 EXCLUDE_PATHS=() 371 for e in "${EXCLUDE_PATHS_TOPLEVEL[@]}"; do 372 REGEX="^$DIR_PREFIX([^/].*)$" 373 if [[ "$e" =~ $REGEX ]]; then 374 EXCLUDE_PATHS+=("${BASH_REMATCH[1]}") 375 fi 376 done 377else 378 EXCLUDE_PATHS=("${EXCLUDE_PATHS_TOPLEVEL[@]}") 379fi 380 381FILES=() 382HAS_EXPLICIT_FILES=0 383SHOW_FILENAMES=0 384TEST_ONLY=0 385CHECK_UPSTREAM= 386 387usage() { 388 printf "Usage: %s [OPTION]... [FILE]...\n" "$(basename "$0")" 389 printf "Reformat source files using clang-format.\n\n" 390 printf "If no file is given the script runs on the whole codebase.\n" 391 printf "OPTIONS:\n" 392 printf " -h Print this help message.\n" 393 printf " -i Reformat files (the default).\n" 394 printf " -n|--dry-run Only check the files (contrary to \"-i\").\n" 395 printf " -a|--all Check all files (the default).\n" 396 printf " -u|--upstream COMMIT Check only files from \`git diff --name-only COMMIT\` (contrary to \"-a\").\n" 397 printf " This also affects directories given in the [FILE] list, but not files.\n" 398 printf " If this is the last parameter and COMMIT is unspecified/empty, it defaults to \"main\".\n" 399 printf " -F|--fast Same as \`-u HEAD^\`.\n" 400 printf " -l|--show-filenames Only print the filenames that would be checked/formatted\n" 401 printf " -- Separate options from filenames/directories\n" 402 if [ -n "${_LIBNL_CODE_FORMAT_CONTAINER+x}" ] ; then 403 printf "\n" 404 printf "Command runs inside container image \"$_LIBNL_CODE_FORMAT_CONTAINER\".\n" 405 printf "Delete/renew image with \`podman rmi \"$_LIBNL_CODE_FORMAT_CONTAINER\"\`.\n" 406 fi 407} 408 409ls_files_exist() { 410 local OLD_IFS="$IFS" 411 local f 412 413 IFS=$'\n' 414 for f in $(cat) ; do 415 test -f "$f" && printf '%s\n' "$f" 416 done 417 IFS="$OLD_IFS" 418} 419 420ls_files_filter() { 421 local OLD_IFS="$IFS" 422 local f 423 424 IFS=$'\n' 425 for f in $(cat) ; do 426 local found=1 427 local p 428 for p; do 429 [[ "$f" = "$p/"* ]] && found= 430 [[ "$f" = "$p" ]] && found= 431 done 432 test -n "$found" && printf '%s\n' "$f" 433 done 434 IFS="$OLD_IFS" 435} 436 437g_ls_files() { 438 local pattern="$1" 439 shift 440 441 if [ -z "$CHECK_UPSTREAM" ]; then 442 git ls-files -- "$pattern" 443 else 444 git diff --no-renames --name-only "$CHECK_UPSTREAM" -- "$pattern" \ 445 | ls_files_exist 446 fi | ls_files_filter "$@" 447} 448 449HAD_DASHDASH=0 450while (( $# )); do 451 if [ "$HAD_DASHDASH" = 0 ]; then 452 case "$1" in 453 -h) 454 usage 455 exit 0 456 ;; 457 -l|--show-filenames) 458 SHOW_FILENAMES=1 459 shift 460 continue 461 ;; 462 -a|--all) 463 CHECK_UPSTREAM= 464 shift 465 continue 466 ;; 467 -u|--upstream) 468 shift 469 CHECK_UPSTREAM="$1" 470 test -n "$CHECK_UPSTREAM" || CHECK_UPSTREAM=main 471 shift || : 472 continue 473 ;; 474 -F|--fast) 475 CHECK_UPSTREAM='HEAD^' 476 shift 477 continue 478 ;; 479 -n|--dry-run) 480 TEST_ONLY=1 481 shift 482 continue 483 ;; 484 -i) 485 TEST_ONLY=0 486 shift 487 continue 488 ;; 489 --) 490 HAD_DASHDASH=1 491 shift 492 continue 493 ;; 494 esac 495 fi 496 if [ -d "$1" ]; then 497 while IFS='' read -r line; 498 do FILES+=("$line") 499 done < <(CHECK_UPSTREAM="$CHECK_UPSTREAM" g_ls_files "${1}/*.[hc]" "${EXCLUDE_PATHS[@]}") 500 elif [ -f "$1" ]; then 501 FILES+=("$1") 502 else 503 usage >&2 504 echo >&2 505 die "Unknown argument \"$1\" which also is neither a file nor a directory." 506 fi 507 shift 508 HAS_EXPLICIT_FILES=1 509done 510 511if [ $HAS_EXPLICIT_FILES = 0 ]; then 512 while IFS='' read -r line; do 513 FILES+=("$line") 514 done < <(CHECK_UPSTREAM="$CHECK_UPSTREAM" g_ls_files '*.[ch]' "${EXCLUDE_PATHS[@]}") 515fi 516 517if [ $SHOW_FILENAMES = 1 ]; then 518 for f in "${FILES[@]}" ; do 519 printf '%s\n' "$f" 520 done 521 exit 0 522fi 523 524if [ "${#FILES[@]}" = 0 ]; then 525 if [ -z "$CHECK_UPSTREAM" ]; then 526 die "Error: no files to check" 527 fi 528 exit 0 529fi 530 531FLAGS_TEST=( --Werror -n --ferror-limit=1 ) 532 533if [ $TEST_ONLY = 1 ]; then 534 # We assume that all formatting is correct. In that mode, passing 535 # all filenames to clang-format is significantly faster. 536 # 537 # Only in case of an error, we iterate over the files one by one 538 # until we find the first invalid file. 539 for f in "${FILES[@]}"; do 540 [ -f "$f" ] || die "Error: file \"$f\" does not exist (or is not a regular file)" 541 done 542 clang-format "${FLAGS_TEST[@]}" "${FILES[@]}" &>/dev/null && exit 0 543 for f in "${FILES[@]}"; do 544 [ -f "$f" ] || die "Error: file \"$f\" does not exist (or is not a regular file)" 545 if ! clang-format "${FLAGS_TEST[@]}" "$f" &>/dev/null; then 546 FF="$(mktemp)" 547 trap 'rm -f "$FF"' EXIT 548 clang-format "$f" 2>/dev/null > "$FF" 549 git --no-pager diff "$f" "$FF" || : 550 FEDORA_VERSION="$(sed -n 's/^ image: fedora:\([0-9]\+\)$/\1/p' .github/workflows/ci.yml)" 551 die "Error: file \"$f\" has style issues."$'\n'"Fix it by running \`\"$0\"\` using $(clang-format --version) 552Alternatively, run \`./tools/clang-format-container.sh\` to use a podman container named \"libnl-code-format-f$FEDORA_VERSION\"." 553 fi 554 done 555 die "an unknown error happened." 556fi 557 558clang-format -i "${FILES[@]}" 559