1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3# Copyright (c) 2024 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import optparse 17import os 18import sys 19import stat 20import json 21import operator 22 23 24def parse_args(args): 25 from scripts.util import build_utils # noqa: E402 26 27 args = build_utils.expand_file_args(args) 28 29 parser = optparse.OptionParser() 30 build_utils.add_depfile_option(parser) 31 parser.add_option('--output', help='the final install file name') 32 parser.add_option('--source-file', help='source passwd files') 33 parser.add_option('--append-file', action="append", type="string", dest="files", help='appended files') 34 parser.add_option('--append-line', action="append", type="string", dest="lines", help='appended lines') 35 parser.add_option('--input-ranges', help="uid/gid value range") 36 37 options, _ = parser.parse_args(args) 38 return options 39 40 41def load_group_file_as_dict(source_f): 42 source_dict = {} 43 for line in source_f: 44 arr = line.strip().split(":") 45 if arr: 46 key = arr[0] 47 passwd_gid_value = [arr[1], arr[2]] 48 value = [':'.join(passwd_gid_value), arr[3]] 49 source_dict[key] = value 50 return source_dict 51 52 53def insert_append_user_value(key, arr, source_dict): 54 if source_dict[key][1] and arr[3]: 55 if arr[3] not in source_dict[key][1]: 56 user_value = [source_dict[key][1], arr[3]] 57 source_dict[key][1] = ','.join(user_value) 58 elif source_dict[key][1] == " " and arr[3]: 59 source_dict[key][1] = arr[3] 60 61 62def get_append_value(src, source_dict): 63 for line in src: 64 if line != "\n": 65 arr = line.strip().split(":") 66 key = arr[0] 67 passwd_gid_value = [arr[1], arr[2]] 68 if len(arr) > 3: 69 value = [':'.join(passwd_gid_value), arr[3]] 70 else: 71 value = [':'.join(passwd_gid_value), " "] 72 if key in source_dict.keys(): 73 insert_append_user_value(key, arr, source_dict) 74 else: 75 source_dict[key] = value 76 77 78def append_group_by_lines(options, source_dict): 79 for line in options.lines: 80 arr = line.strip().split(":") 81 key = arr[0] 82 passwd_gid_value = [arr[1], arr[2]] 83 if len(arr) > 3: 84 value = [':'.join(passwd_gid_value), arr[3]] 85 else: 86 value = [':'.join(passwd_gid_value), " "] 87 if key in source_dict.keys(): 88 insert_append_user_value(key, arr, source_dict) 89 else: 90 source_dict[key] = value 91 92 93def append_group_by_files(options, source_dict): 94 for append_f in options.files: 95 with open(append_f, 'r') as src: 96 get_append_value(src, source_dict) 97 98 99def append_group_files(target_f, options): 100 with open(options.source_file, 'r') as source_f: 101 source_dict = load_group_file_as_dict(source_f) 102 if options.files: 103 append_group_by_files(options, source_dict) 104 if options.lines: 105 append_group_by_lines(options, source_dict) 106 for item in source_dict: 107 target_f.write(f"{item}:{':'.join(source_dict[item])}\n") 108 109 110def handle_passwd_info(passwd_info, limits): 111 is_passed = True 112 name = passwd_info[0].strip() 113 gid = int(passwd_info[3], 10) 114 uid = int(passwd_info[2], 10) 115 if gid >= int(limits[0]) and gid <= int(limits[1]): 116 pass 117 else: 118 is_passed = False 119 log_str = "error: name={} gid={} is not in range {}".format(name, gid, limits) 120 print(log_str) 121 122 if uid >= int(limits[0]) and uid <= int(limits[1]): 123 pass 124 else: 125 is_passed = False 126 log_str = "error: name={} uid={} is not in range {}".format(name, gid, limits) 127 print(log_str) 128 return is_passed 129 130 131def check_passwd_file(file_name, limits): 132 is_passed = True 133 with open(file_name, encoding='utf-8') as fp: 134 line = fp.readline() 135 while line : 136 if line.startswith("#") or len(line) < 3: 137 line = fp.readline() 138 continue 139 passwd_info = line.strip("\n").split(":") 140 if len(passwd_info) < 4: 141 line = fp.readline() 142 continue 143 if not handle_passwd_info(passwd_info, limits): 144 is_passed = False 145 line = fp.readline() 146 return is_passed 147 148 149def load_file(file_name, limit): 150 151 if not os.path.exists(file_name): 152 print("error: %s is not exit", file_name) 153 return False 154 is_passed = True 155 limits = limit.split("-") 156 try: 157 is_passed = check_passwd_file(file_name, limits) 158 except: 159 raise Exception("Exception in reading passwd, file name:", file_name) 160 return is_passed 161 162 163def append_passwd_files(target_f, options): 164 # Read source file 165 file_list = options.source_file.split(":") 166 range_list = options.input_ranges.split(":") 167 168 for i, file in enumerate(file_list): 169 if i >= len(range_list): 170 print("error: %s is error", file) 171 return 172 if not load_file(file, range_list[i]): 173 # check gid/uid Exception log: raise Exception("Exception, check passwd file error, ", file) 174 print("error: heck passwd file error, file path: ", file) 175 pass 176 try: 177 with open(file, 'r') as source_f: 178 source_contents = source_f.read() 179 target_f.write(source_contents) 180 except: 181 raise Exception("Exception in appending passwd, file name:", file) 182 183 184def main(args): 185 sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, 186 os.pardir, os.pardir, os.pardir, os.pardir, "build")) 187 from scripts.util import build_utils # noqa: E402 188 189 options = parse_args(args) 190 if options.files: 191 depfile_deps = ([options.source_file] + options.files) 192 else: 193 depfile_deps = ([options.source_file]) 194 195 with os.fdopen(os.open(options.output, os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR), 'w') as target_f: 196 if operator.contains(options.source_file, "group"): 197 append_group_files(target_f, options) 198 else: 199 append_passwd_files(target_f, options) 200 201 build_utils.write_depfile(options.depfile, 202 options.output, depfile_deps, add_pydeps=False) 203 204 205if __name__ == '__main__': 206 sys.exit(main(sys.argv[1:])) 207