169570cc8Sopenharmony_ci#!/usr/bin/env python 269570cc8Sopenharmony_ci# -*- coding: utf-8 -*- 369570cc8Sopenharmony_ci# Copyright (c) 2023 Huawei Device Co., Ltd. 469570cc8Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 569570cc8Sopenharmony_ci# you may not use this file except in compliance with the License. 669570cc8Sopenharmony_ci# You may obtain a copy of the License at 769570cc8Sopenharmony_ci# 869570cc8Sopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 969570cc8Sopenharmony_ci# 1069570cc8Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software 1169570cc8Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 1269570cc8Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1369570cc8Sopenharmony_ci# See the License for the specific language governing permissions and 1469570cc8Sopenharmony_ci# limitations under the License. 1569570cc8Sopenharmony_ci 1669570cc8Sopenharmony_ciimport optparse 1769570cc8Sopenharmony_ciimport os 1869570cc8Sopenharmony_ciimport sys 1969570cc8Sopenharmony_ciimport json 2069570cc8Sopenharmony_ciimport stat 2169570cc8Sopenharmony_ci 2269570cc8Sopenharmony_cisys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, 2369570cc8Sopenharmony_ci os.pardir, os.pardir, os.pardir, "build")) 2469570cc8Sopenharmony_cifrom scripts.util import build_utils # noqa: E402 2569570cc8Sopenharmony_ci 2669570cc8Sopenharmony_ci#default json 2769570cc8Sopenharmony_ci 2869570cc8Sopenharmony_ciAPP_SANDBOX_DEFAULT = ''' 2969570cc8Sopenharmony_ci{ 3069570cc8Sopenharmony_ci "common" : [{ 3169570cc8Sopenharmony_ci "top-sandbox-switch": "ON", 3269570cc8Sopenharmony_ci "app-base" : [{ 3369570cc8Sopenharmony_ci "sandbox-root" : "/mnt/sandbox/<currentUserId>/<PackageName>", 3469570cc8Sopenharmony_ci "sandbox-ns-flags" : [], 3569570cc8Sopenharmony_ci "mount-paths" : [], 3669570cc8Sopenharmony_ci "symbol-links": [], 3769570cc8Sopenharmony_ci "flags-point" : [] 3869570cc8Sopenharmony_ci }], 3969570cc8Sopenharmony_ci "app-resources" : [{ 4069570cc8Sopenharmony_ci "sandbox-root" : "/mnt/sandbox/<currentUserId>/<PackageName>", 4169570cc8Sopenharmony_ci "mount-paths" : [], 4269570cc8Sopenharmony_ci "flags-point" : [], 4369570cc8Sopenharmony_ci "symbol-links" : [] 4469570cc8Sopenharmony_ci }] 4569570cc8Sopenharmony_ci }], 4669570cc8Sopenharmony_ci "individual" : [{}], 4769570cc8Sopenharmony_ci "permission" :[{}] 4869570cc8Sopenharmony_ci} 4969570cc8Sopenharmony_ci''' 5069570cc8Sopenharmony_ci#only string in list 5169570cc8Sopenharmony_ci 5269570cc8Sopenharmony_ci 5369570cc8Sopenharmony_cidef _merge_list(origin, new): 5469570cc8Sopenharmony_ci if origin is None or new is None: 5569570cc8Sopenharmony_ci return 5669570cc8Sopenharmony_ci for data1 in new: 5769570cc8Sopenharmony_ci if data1 not in origin: 5869570cc8Sopenharmony_ci origin.append(data1) 5969570cc8Sopenharmony_ci 6069570cc8Sopenharmony_ci 6169570cc8Sopenharmony_cidef _is_same_data(data1, data2, keys): 6269570cc8Sopenharmony_ci for key in keys: 6369570cc8Sopenharmony_ci if data1.get(key) != data2.get(key): 6469570cc8Sopenharmony_ci return False 6569570cc8Sopenharmony_ci return True 6669570cc8Sopenharmony_ci 6769570cc8Sopenharmony_ci#for object in list 6869570cc8Sopenharmony_ci 6969570cc8Sopenharmony_ci 7069570cc8Sopenharmony_cidef _handle_same_array(data1, data2): 7169570cc8Sopenharmony_ci for field in ["sandbox-root", "sandbox-path", "check-action-status", "fs-type", "link-name"]: 7269570cc8Sopenharmony_ci if data1.get(field) is not None: 7369570cc8Sopenharmony_ci data2[field] = data1[field] 7469570cc8Sopenharmony_ci 7569570cc8Sopenharmony_ci for field in ["sandbox-flags"]: # by list merger 7669570cc8Sopenharmony_ci item = data1.get(field) 7769570cc8Sopenharmony_ci if item is not None and len(item) > 0: 7869570cc8Sopenharmony_ci _merge_list(data2[field], item) 7969570cc8Sopenharmony_ci 8069570cc8Sopenharmony_ci 8169570cc8Sopenharmony_cidef _merge_scope_array(origin, new, keys): 8269570cc8Sopenharmony_ci for data1 in new: 8369570cc8Sopenharmony_ci found = False 8469570cc8Sopenharmony_ci for data2 in origin: 8569570cc8Sopenharmony_ci if _is_same_data(data1, data2, keys): 8669570cc8Sopenharmony_ci found = True 8769570cc8Sopenharmony_ci _handle_same_array(data1, data2) 8869570cc8Sopenharmony_ci break 8969570cc8Sopenharmony_ci if not found: 9069570cc8Sopenharmony_ci origin.append(data1) 9169570cc8Sopenharmony_ci 9269570cc8Sopenharmony_ci 9369570cc8Sopenharmony_cidef _handle_same_data(data1, data2, field_infos): 9469570cc8Sopenharmony_ci for field in ["sandbox-root"]: 9569570cc8Sopenharmony_ci if data1.get(field) is not None: 9669570cc8Sopenharmony_ci data2[field] = data1[field] 9769570cc8Sopenharmony_ci 9869570cc8Sopenharmony_ci # for array 9969570cc8Sopenharmony_ci for name, keys in field_infos.items(): 10069570cc8Sopenharmony_ci item = data1.get(name) 10169570cc8Sopenharmony_ci if item is not None and len(item) > 0: 10269570cc8Sopenharmony_ci _merge_scope_array(data2[field], item, keys) 10369570cc8Sopenharmony_ci 10469570cc8Sopenharmony_ci 10569570cc8Sopenharmony_cidef _merge_scope_flags_point(origin, new): 10669570cc8Sopenharmony_ci field_infos = { 10769570cc8Sopenharmony_ci "mount-paths": ["src-path"] 10869570cc8Sopenharmony_ci } 10969570cc8Sopenharmony_ci for data1 in new: 11069570cc8Sopenharmony_ci found = False 11169570cc8Sopenharmony_ci for data2 in origin: 11269570cc8Sopenharmony_ci if _is_same_data(data1, data2, ["flags"]): 11369570cc8Sopenharmony_ci found = True 11469570cc8Sopenharmony_ci _handle_same_data(data1, data2, field_infos) 11569570cc8Sopenharmony_ci break 11669570cc8Sopenharmony_ci 11769570cc8Sopenharmony_ci if not found: 11869570cc8Sopenharmony_ci origin.append(data1) 11969570cc8Sopenharmony_ci 12069570cc8Sopenharmony_ci 12169570cc8Sopenharmony_cidef _merge_scope_app(origin, new): 12269570cc8Sopenharmony_ci field_infos = { 12369570cc8Sopenharmony_ci "mount-paths": ["src-path"], 12469570cc8Sopenharmony_ci "symbol-links": ["target-name"] 12569570cc8Sopenharmony_ci } 12669570cc8Sopenharmony_ci # normal filed 12769570cc8Sopenharmony_ci for k in ["sandbox-root", "sandbox-switch", "gids", "sandbox-ns-flags"]: 12869570cc8Sopenharmony_ci if new[0].get(k) is not None: 12969570cc8Sopenharmony_ci origin[0][k] = new[0].get(k) 13069570cc8Sopenharmony_ci 13169570cc8Sopenharmony_ci # for flags-point 13269570cc8Sopenharmony_ci flags_points = new[0].get("flags-point") 13369570cc8Sopenharmony_ci if flags_points: 13469570cc8Sopenharmony_ci _merge_scope_flags_point(origin[0]["flags-point"], flags_points) 13569570cc8Sopenharmony_ci 13669570cc8Sopenharmony_ci # by list merger 13769570cc8Sopenharmony_ci for field in ["sandbox-ns-flags"]: 13869570cc8Sopenharmony_ci item = origin[0].get(field) 13969570cc8Sopenharmony_ci if item is not None and len(item) > 0: 14069570cc8Sopenharmony_ci _merge_list(new[0][field], item) 14169570cc8Sopenharmony_ci 14269570cc8Sopenharmony_ci # for array 14369570cc8Sopenharmony_ci for name, keys in field_infos.items(): 14469570cc8Sopenharmony_ci item = new[0].get(name) 14569570cc8Sopenharmony_ci if item is not None and len(item) > 0: 14669570cc8Sopenharmony_ci _merge_scope_array(origin[0].get(name), item, keys) 14769570cc8Sopenharmony_ci 14869570cc8Sopenharmony_ci 14969570cc8Sopenharmony_cidef _merge_scope_individual(origin, new): 15069570cc8Sopenharmony_ci for k, v in new.items(): 15169570cc8Sopenharmony_ci if k not in origin: 15269570cc8Sopenharmony_ci origin[k] = v 15369570cc8Sopenharmony_ci else: 15469570cc8Sopenharmony_ci _merge_scope_app(origin[k], v) 15569570cc8Sopenharmony_ci 15669570cc8Sopenharmony_ci 15769570cc8Sopenharmony_cidef _merge_scope_permission(origin, new): 15869570cc8Sopenharmony_ci for k, v in new.items(): 15969570cc8Sopenharmony_ci if k not in origin: 16069570cc8Sopenharmony_ci origin[k] = v 16169570cc8Sopenharmony_ci else: 16269570cc8Sopenharmony_ci _merge_scope_app(origin[k], v) 16369570cc8Sopenharmony_ci 16469570cc8Sopenharmony_ci 16569570cc8Sopenharmony_cidef _merge_scope_common(origin, new): 16669570cc8Sopenharmony_ci # 处理 top-sandbox-switch 16769570cc8Sopenharmony_ci for name in ["top-sandbox-switch"]: 16869570cc8Sopenharmony_ci if new.get(name) : 16969570cc8Sopenharmony_ci origin[name] = new.get(name) 17069570cc8Sopenharmony_ci 17169570cc8Sopenharmony_ci #处理 app-base 17269570cc8Sopenharmony_ci app = new.get("app-base") 17369570cc8Sopenharmony_ci if app is not None and len(app) > 0: 17469570cc8Sopenharmony_ci _merge_scope_app(origin.get("app-base"), app) 17569570cc8Sopenharmony_ci pass 17669570cc8Sopenharmony_ci 17769570cc8Sopenharmony_ci #处理 app-resources 17869570cc8Sopenharmony_ci app = new.get("app-resources") 17969570cc8Sopenharmony_ci if app is not None and len(app) > 0: 18069570cc8Sopenharmony_ci _merge_scope_app(origin.get("app-resources"), app) 18169570cc8Sopenharmony_ci pass 18269570cc8Sopenharmony_ci 18369570cc8Sopenharmony_ci 18469570cc8Sopenharmony_cidef parse_args(args): 18569570cc8Sopenharmony_ci args = build_utils.expand_file_args(args) 18669570cc8Sopenharmony_ci parser = optparse.OptionParser() 18769570cc8Sopenharmony_ci build_utils.add_depfile_option(parser) 18869570cc8Sopenharmony_ci parser.add_option('--output', help='fixed sandbox configure file') 18969570cc8Sopenharmony_ci parser.add_option('--source-file', help='source para file') 19069570cc8Sopenharmony_ci parser.add_option('--patterns', action="append", 19169570cc8Sopenharmony_ci type="string", dest="patterns", help='replace string patterns like libpath:lib64') 19269570cc8Sopenharmony_ci parser.add_option('--extra_sandbox_cfg', action="append", 19369570cc8Sopenharmony_ci type="string", dest="extra_sandbox_cfgs", help='extra sandbox') 19469570cc8Sopenharmony_ci 19569570cc8Sopenharmony_ci options, _ = parser.parse_args(args) 19669570cc8Sopenharmony_ci return options 19769570cc8Sopenharmony_ci 19869570cc8Sopenharmony_ci 19969570cc8Sopenharmony_cidef __substitude_contents(options, source_file): 20069570cc8Sopenharmony_ci with open(source_file, "r") as f: 20169570cc8Sopenharmony_ci contents = f.read() 20269570cc8Sopenharmony_ci if not options.patterns: 20369570cc8Sopenharmony_ci return json.loads(contents) 20469570cc8Sopenharmony_ci for pattern in options.patterns: 20569570cc8Sopenharmony_ci parts = pattern.split(":") 20669570cc8Sopenharmony_ci contents = contents.replace("{%s}" % parts[0], parts[1]) 20769570cc8Sopenharmony_ci return json.loads(contents) 20869570cc8Sopenharmony_ci 20969570cc8Sopenharmony_ci 21069570cc8Sopenharmony_cidef _get_json_list(options): 21169570cc8Sopenharmony_ci data_list = [] 21269570cc8Sopenharmony_ci #decode source file 21369570cc8Sopenharmony_ci contents = __substitude_contents(options, options.source_file) 21469570cc8Sopenharmony_ci if contents : 21569570cc8Sopenharmony_ci data_list.append(contents) 21669570cc8Sopenharmony_ci 21769570cc8Sopenharmony_ci if options.extra_sandbox_cfgs is None: 21869570cc8Sopenharmony_ci return data_list 21969570cc8Sopenharmony_ci 22069570cc8Sopenharmony_ci #decode extra file 22169570cc8Sopenharmony_ci for sandbox_cfg in options.extra_sandbox_cfgs: 22269570cc8Sopenharmony_ci contents = __substitude_contents(options, sandbox_cfg) 22369570cc8Sopenharmony_ci if contents : 22469570cc8Sopenharmony_ci data_list.append(contents) 22569570cc8Sopenharmony_ci return data_list 22669570cc8Sopenharmony_ci 22769570cc8Sopenharmony_ci 22869570cc8Sopenharmony_cidef fix_sandbox_config_file(options): 22969570cc8Sopenharmony_ci data_list = _get_json_list(options) 23069570cc8Sopenharmony_ci #decode template 23169570cc8Sopenharmony_ci origin_json = json.loads(APP_SANDBOX_DEFAULT) 23269570cc8Sopenharmony_ci 23369570cc8Sopenharmony_ci for data in data_list: 23469570cc8Sopenharmony_ci # 处理common 23569570cc8Sopenharmony_ci common = data.get("common") 23669570cc8Sopenharmony_ci if common is not None and len(common) > 0: 23769570cc8Sopenharmony_ci _merge_scope_common(origin_json.get("common")[0], common[0]) 23869570cc8Sopenharmony_ci 23969570cc8Sopenharmony_ci #处理individual 24069570cc8Sopenharmony_ci individuals = data.get("individual") 24169570cc8Sopenharmony_ci if individuals is not None and len(individuals) > 0: 24269570cc8Sopenharmony_ci _merge_scope_individual(origin_json.get("individual")[0], individuals[0]) 24369570cc8Sopenharmony_ci pass 24469570cc8Sopenharmony_ci 24569570cc8Sopenharmony_ci # 处理permission 24669570cc8Sopenharmony_ci permission = data.get("permission") 24769570cc8Sopenharmony_ci if permission is not None and len(permission) > 0: 24869570cc8Sopenharmony_ci _merge_scope_permission(origin_json.get("permission")[0], permission[0]) 24969570cc8Sopenharmony_ci 25069570cc8Sopenharmony_ci # dump json to output 25169570cc8Sopenharmony_ci flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC 25269570cc8Sopenharmony_ci modes = stat.S_IWUSR | stat.S_IRUSR | stat.S_IWGRP | stat.S_IRGRP 25369570cc8Sopenharmony_ci with os.fdopen(os.open(options.output, flags, modes), 'w') as f: 25469570cc8Sopenharmony_ci f.write(json.dumps(origin_json, ensure_ascii=False, indent=2)) 25569570cc8Sopenharmony_ci 25669570cc8Sopenharmony_ci 25769570cc8Sopenharmony_cidef main(args): 25869570cc8Sopenharmony_ci options = parse_args(args) 25969570cc8Sopenharmony_ci depfile_deps = ([options.source_file]) 26069570cc8Sopenharmony_ci fix_sandbox_config_file(options) 26169570cc8Sopenharmony_ci build_utils.write_depfile(options.depfile, options.output, depfile_deps, add_pydeps=False) 26269570cc8Sopenharmony_ci 26369570cc8Sopenharmony_ciif __name__ == '__main__': 26469570cc8Sopenharmony_ci sys.exit(main(sys.argv[1:])) 265