#!/usr/bin/python3 # Regenerate and update syscall-names.list. # Copyright (C) 2020-2024 Free Software Foundation, Inc. # This file is part of the GNU C Library. # # The GNU C Library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # The GNU C Library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with the GNU C Library; if not, see # . import argparse import io import os import sys import glibcextract import glibcsyscalls def atomic_replace(path, contents): """Atomically replace PATH with CONTENTS, via a temporary file. The name of the temporary file is predictable, so locking is required to avoid corruption. """ path_tmp = path + 'T' with open(path_tmp, 'w') as tmp: tmp.write(contents) ok = False try: os.rename(path_tmp, path) ok = True finally: # On error, try to delete the temporary file. if not ok: try: os.unlink(path_tmp) except: pass def main(): """The main entry point.""" parser = argparse.ArgumentParser( description='System call list consistency checks') parser.add_argument('--cc', metavar='CC', required=True, help='C compiler (including options) to use') parser.add_argument('--lock', metavar='PATH', required=True, help='file to lock during the updates') parser.add_argument('arch_syscall', metavar='ARCH-SYSCALL-H', help='The file to update') parser.add_argument('names_list', metavar='SYSCALL-NAMES-LIST', help='The syscall name list to update ') args = parser.parse_args() kernel_constants = glibcsyscalls.kernel_constants(args.cc) with open(args.lock, 'r+') as lockfile: os.lockf(lockfile.fileno(), os.F_LOCK, 0) # Replace with data derived from kernel headers. # No merging is necessary here. Arch-specific changes should go # into . out = io.StringIO() out.write('/* AUTOGENERATED by update-syscall-lists.py. */\n') for name, value in sorted(kernel_constants.items()): out.write('#define __NR_{} {}\n'.format(name, value)) atomic_replace(args.arch_syscall, out.getvalue()) # Merge the architecture-specific system call names into the # global names list, syscall-names.list. This file contains names # from other architectures (and comments), so it is necessary to # merge the existing files with the names obtained from the # kernel. with open(args.names_list, 'r') as list_file: names_list = glibcsyscalls.SyscallNamesList(list_file) merged = names_list.merge(kernel_constants.keys()) out = io.StringIO() for line in merged: out.write(line) atomic_replace(args.names_list, out.getvalue()) if __name__ == '__main__': main()