diff options
author | Kelvin M. Klann <kmk3.code@protonmail.com> | 2022-11-23 16:32:37 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-23 16:32:37 +0000 |
commit | 9ab61c4aba5065a9eb9b640b4e1e64f8e4b55a17 (patch) | |
tree | 01c368d19fb61dd2dfc678a0c8c9b8da411d66fe | |
parent | fix opening links in firefox youtube-viewers-common.profile (#5352) (diff) | |
parent | sort.py: use script name in usage/main docstring (diff) | |
download | firejail-9ab61c4aba5065a9eb9b640b4e1e64f8e4b55a17.tar.gz firejail-9ab61c4aba5065a9eb9b640b4e1e64f8e4b55a17.tar.zst firejail-9ab61c4aba5065a9eb9b640b4e1e64f8e4b55a17.zip |
Merge pull request #5429 from kmk3/sort-py-improvements
build: sort.py improvements
-rwxr-xr-x | contrib/sort.py | 91 |
1 files changed, 56 insertions, 35 deletions
diff --git a/contrib/sort.py b/contrib/sort.py index 6f21370ec..638f14516 100755 --- a/contrib/sort.py +++ b/contrib/sort.py | |||
@@ -2,48 +2,61 @@ | |||
2 | # This file is part of Firejail project | 2 | # This file is part of Firejail project |
3 | # Copyright (C) 2014-2022 Firejail Authors | 3 | # Copyright (C) 2014-2022 Firejail Authors |
4 | # License GPL v2 | 4 | # License GPL v2 |
5 | """ | ||
6 | Sort the items of multi-item options in profiles, the following options are supported: | ||
7 | private-bin, private-etc, private-lib, caps.drop, caps.keep, seccomp.drop, seccomp.drop, protocol | ||
8 | 5 | ||
9 | Usage: | 6 | # Requirements: |
10 | $ ./sort.py /path/to/profile [ /path/to/profile2 /path/to/profile3 ... ] | 7 | # python >= 3.6 |
8 | from os import path | ||
9 | from sys import argv, exit as sys_exit, stderr | ||
10 | |||
11 | __doc__ = f"""\ | ||
12 | Sort the arguments of commands in profiles. | ||
13 | |||
14 | Usage: {path.basename(argv[0])} [/path/to/profile ...] | ||
15 | |||
16 | The following commands are supported: | ||
17 | |||
18 | private-bin, private-etc, private-lib, caps.drop, caps.keep, seccomp.drop, | ||
19 | seccomp.drop, protocol | ||
20 | |||
21 | Note that this is only applicable to commands that support multiple arguments. | ||
22 | |||
11 | Keep in mind that this will overwrite your profile(s). | 23 | Keep in mind that this will overwrite your profile(s). |
12 | 24 | ||
13 | Examples: | 25 | Examples: |
14 | $ ./sort.py MyAwesomeProfile.profile | 26 | $ {argv[0]} MyAwesomeProfile.profile |
15 | $ ./sort.py new_profile.profile second_new_profile.profile | 27 | $ {argv[0]} new_profile.profile second_new_profile.profile |
16 | $ ./sort.py ~/.config/firejail/*.{profile,inc,local} | 28 | $ {argv[0]} ~/.config/firejail/*.{{profile,inc,local}} |
17 | $ sudo ./sort.py /etc/firejail/*.{profile,inc,local} | 29 | $ sudo {argv[0]} /etc/firejail/*.{{profile,inc,local}} |
18 | 30 | ||
19 | Exit-Codes: | 31 | Exit Codes: |
20 | 0: No Error; No Profile Fixed. | 32 | 0: Success: No profiles needed fixing. |
21 | 1: Error, one or more profiles were not processed correctly. | 33 | 1: Error: One or more profiles could not be processed correctly. |
22 | 101: No Error; One or more profile were fixed. | 34 | 2: Error: Missing arguments. |
35 | 101: Info: One or more profiles were fixed. | ||
23 | """ | 36 | """ |
24 | 37 | ||
25 | # Requirements: | ||
26 | # python >= 3.6 | ||
27 | from sys import argv, exit as sys_exit | ||
28 | |||
29 | 38 | ||
30 | def sort_alphabetical(raw_items): | 39 | def sort_alphabetical(original_items): |
31 | items = raw_items.split(",") | 40 | items = original_items.split(",") |
32 | items.sort(key=lambda s: s.casefold()) | 41 | items.sort(key=str.casefold) |
33 | return ",".join(items) | 42 | return ",".join(items) |
34 | 43 | ||
35 | 44 | ||
36 | def sort_protocol(protocols): | 45 | def sort_protocol(original_protocols): |
37 | """sort the given protocols into this scheme: unix,inet,inet6,netlink,packet,bluetooth""" | 46 | """ |
47 | Sort the given protocols into the following order: | ||
48 | |||
49 | unix,inet,inet6,netlink,packet,bluetooth | ||
50 | """ | ||
38 | 51 | ||
39 | # shortcut for common protocol lines | 52 | # shortcut for common protocol lines |
40 | if protocols in ("unix", "unix,inet,inet6"): | 53 | if original_protocols in ("unix", "unix,inet,inet6"): |
41 | return protocols | 54 | return original_protocols |
42 | 55 | ||
43 | fixed_protocols = "" | 56 | fixed_protocols = "" |
44 | for protocol in ("unix", "inet", "inet6", "netlink", "packet", "bluetooth"): | 57 | for protocol in ("unix", "inet", "inet6", "netlink", "packet", "bluetooth"): |
45 | for prefix in ("", "-", "+", "="): | 58 | for prefix in ("", "-", "+", "="): |
46 | if f",{prefix}{protocol}," in f",{protocols},": | 59 | if f",{prefix}{protocol}," in f",{original_protocols},": |
47 | fixed_protocols += f"{prefix}{protocol}," | 60 | fixed_protocols += f"{prefix}{protocol}," |
48 | return fixed_protocols[:-1] | 61 | return fixed_protocols[:-1] |
49 | 62 | ||
@@ -53,7 +66,7 @@ def fix_profile(filename): | |||
53 | lines = profile.read().split("\n") | 66 | lines = profile.read().split("\n") |
54 | was_fixed = False | 67 | was_fixed = False |
55 | fixed_profile = [] | 68 | fixed_profile = [] |
56 | for lineno, line in enumerate(lines): | 69 | for lineno, line in enumerate(lines, 1): |
57 | if line[:12] in ("private-bin ", "private-etc ", "private-lib "): | 70 | if line[:12] in ("private-bin ", "private-etc ", "private-lib "): |
58 | fixed_line = f"{line[:12]}{sort_alphabetical(line[12:])}" | 71 | fixed_line = f"{line[:12]}{sort_alphabetical(line[12:])}" |
59 | elif line[:13] in ("seccomp.drop ", "seccomp.keep "): | 72 | elif line[:13] in ("seccomp.drop ", "seccomp.keep "): |
@@ -69,8 +82,8 @@ def fix_profile(filename): | |||
69 | if fixed_line != line: | 82 | if fixed_line != line: |
70 | was_fixed = True | 83 | was_fixed = True |
71 | print( | 84 | print( |
72 | f"{filename}:{lineno + 1}:-{line}\n" | 85 | f"{filename}:{lineno}:-{line}\n" |
73 | f"{filename}:{lineno + 1}:+{fixed_line}" | 86 | f"{filename}:{lineno}:+{fixed_line}" |
74 | ) | 87 | ) |
75 | fixed_profile.append(fixed_line) | 88 | fixed_profile.append(fixed_line) |
76 | if was_fixed: | 89 | if was_fixed: |
@@ -84,22 +97,30 @@ def fix_profile(filename): | |||
84 | 97 | ||
85 | 98 | ||
86 | def main(args): | 99 | def main(args): |
100 | if len(args) < 1: | ||
101 | print(__doc__, file=stderr) | ||
102 | return 2 | ||
103 | |||
104 | print(f"sort.py: checking {len(args)} profile(s)...") | ||
105 | |||
87 | exit_code = 0 | 106 | exit_code = 0 |
88 | print(f"sort.py: checking {len(args)} {'profiles' if len(args) != 1 else 'profile'}...") | ||
89 | for filename in args: | 107 | for filename in args: |
90 | try: | 108 | try: |
91 | if exit_code not in (1, 101): | 109 | if exit_code not in (1, 101): |
92 | exit_code = fix_profile(filename) | 110 | exit_code = fix_profile(filename) |
93 | else: | 111 | else: |
94 | fix_profile(filename) | 112 | fix_profile(filename) |
95 | except FileNotFoundError: | 113 | except FileNotFoundError as err: |
96 | print(f"[ Error ] Can't find `{filename}'") | 114 | print(f"[ Error ] {err}", file=stderr) |
97 | exit_code = 1 | 115 | exit_code = 1 |
98 | except PermissionError: | 116 | except PermissionError as err: |
99 | print(f"[ Error ] Can't read/write `{filename}'") | 117 | print(f"[ Error ] {err}", file=stderr) |
100 | exit_code = 1 | 118 | exit_code = 1 |
101 | except Exception as err: | 119 | except Exception as err: |
102 | print(f"[ Error ] An error occurred while processing `{filename}': {err}") | 120 | print( |
121 | f"[ Error ] An error occurred while processing '{filename}': {err}", | ||
122 | file=stderr, | ||
123 | ) | ||
103 | exit_code = 1 | 124 | exit_code = 1 |
104 | return exit_code | 125 | return exit_code |
105 | 126 | ||