17db96d56Sopenharmony_ciimport fnmatch 27db96d56Sopenharmony_ciimport glob 37db96d56Sopenharmony_ciimport os 47db96d56Sopenharmony_ciimport os.path 57db96d56Sopenharmony_ciimport shutil 67db96d56Sopenharmony_ciimport stat 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_cifrom .iterutil import iter_many 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ci 117db96d56Sopenharmony_ciUSE_CWD = object() 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_ci 147db96d56Sopenharmony_ciC_SOURCE_SUFFIXES = ('.c', '.h') 157db96d56Sopenharmony_ci 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_cidef create_backup(old, backup=None): 187db96d56Sopenharmony_ci if isinstance(old, str): 197db96d56Sopenharmony_ci filename = old 207db96d56Sopenharmony_ci else: 217db96d56Sopenharmony_ci filename = getattr(old, 'name', None) 227db96d56Sopenharmony_ci if not filename: 237db96d56Sopenharmony_ci return None 247db96d56Sopenharmony_ci if not backup or backup is True: 257db96d56Sopenharmony_ci backup = f'{filename}.bak' 267db96d56Sopenharmony_ci try: 277db96d56Sopenharmony_ci shutil.copyfile(filename, backup) 287db96d56Sopenharmony_ci except FileNotFoundError as exc: 297db96d56Sopenharmony_ci if exc.filename != filename: 307db96d56Sopenharmony_ci raise # re-raise 317db96d56Sopenharmony_ci backup = None 327db96d56Sopenharmony_ci return backup 337db96d56Sopenharmony_ci 347db96d56Sopenharmony_ci 357db96d56Sopenharmony_ci################################## 367db96d56Sopenharmony_ci# filenames 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_cidef fix_filename(filename, relroot=USE_CWD, *, 397db96d56Sopenharmony_ci fixroot=True, 407db96d56Sopenharmony_ci _badprefix=f'..{os.path.sep}', 417db96d56Sopenharmony_ci ): 427db96d56Sopenharmony_ci """Return a normalized, absolute-path copy of the given filename.""" 437db96d56Sopenharmony_ci if not relroot or relroot is USE_CWD: 447db96d56Sopenharmony_ci return os.path.abspath(filename) 457db96d56Sopenharmony_ci if fixroot: 467db96d56Sopenharmony_ci relroot = os.path.abspath(relroot) 477db96d56Sopenharmony_ci return _fix_filename(filename, relroot) 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_ci 507db96d56Sopenharmony_cidef _fix_filename(filename, relroot, *, 517db96d56Sopenharmony_ci _badprefix=f'..{os.path.sep}', 527db96d56Sopenharmony_ci ): 537db96d56Sopenharmony_ci orig = filename 547db96d56Sopenharmony_ci 557db96d56Sopenharmony_ci # First we normalize. 567db96d56Sopenharmony_ci filename = os.path.normpath(filename) 577db96d56Sopenharmony_ci if filename.startswith(_badprefix): 587db96d56Sopenharmony_ci raise ValueError(f'bad filename {orig!r} (resolves beyond relative root') 597db96d56Sopenharmony_ci 607db96d56Sopenharmony_ci # Now make sure it is absolute (relative to relroot). 617db96d56Sopenharmony_ci if not os.path.isabs(filename): 627db96d56Sopenharmony_ci filename = os.path.join(relroot, filename) 637db96d56Sopenharmony_ci else: 647db96d56Sopenharmony_ci relpath = os.path.relpath(filename, relroot) 657db96d56Sopenharmony_ci if os.path.join(relroot, relpath) != filename: 667db96d56Sopenharmony_ci raise ValueError(f'expected {relroot!r} as lroot, got {orig!r}') 677db96d56Sopenharmony_ci 687db96d56Sopenharmony_ci return filename 697db96d56Sopenharmony_ci 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_cidef fix_filenames(filenames, relroot=USE_CWD): 727db96d56Sopenharmony_ci if not relroot or relroot is USE_CWD: 737db96d56Sopenharmony_ci filenames = (os.path.abspath(v) for v in filenames) 747db96d56Sopenharmony_ci else: 757db96d56Sopenharmony_ci relroot = os.path.abspath(relroot) 767db96d56Sopenharmony_ci filenames = (_fix_filename(v, relroot) for v in filenames) 777db96d56Sopenharmony_ci return filenames, relroot 787db96d56Sopenharmony_ci 797db96d56Sopenharmony_ci 807db96d56Sopenharmony_cidef format_filename(filename, relroot=USE_CWD, *, 817db96d56Sopenharmony_ci fixroot=True, 827db96d56Sopenharmony_ci normalize=True, 837db96d56Sopenharmony_ci _badprefix=f'..{os.path.sep}', 847db96d56Sopenharmony_ci ): 857db96d56Sopenharmony_ci """Return a consistent relative-path representation of the filename.""" 867db96d56Sopenharmony_ci orig = filename 877db96d56Sopenharmony_ci if normalize: 887db96d56Sopenharmony_ci filename = os.path.normpath(filename) 897db96d56Sopenharmony_ci if relroot is None: 907db96d56Sopenharmony_ci # Otherwise leave it as-is. 917db96d56Sopenharmony_ci return filename 927db96d56Sopenharmony_ci elif relroot is USE_CWD: 937db96d56Sopenharmony_ci # Make it relative to CWD. 947db96d56Sopenharmony_ci filename = os.path.relpath(filename) 957db96d56Sopenharmony_ci else: 967db96d56Sopenharmony_ci # Make it relative to "relroot". 977db96d56Sopenharmony_ci if fixroot: 987db96d56Sopenharmony_ci relroot = os.path.abspath(relroot) 997db96d56Sopenharmony_ci elif not relroot: 1007db96d56Sopenharmony_ci raise ValueError('missing relroot') 1017db96d56Sopenharmony_ci filename = os.path.relpath(filename, relroot) 1027db96d56Sopenharmony_ci if filename.startswith(_badprefix): 1037db96d56Sopenharmony_ci raise ValueError(f'bad filename {orig!r} (resolves beyond relative root') 1047db96d56Sopenharmony_ci return filename 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_ci 1077db96d56Sopenharmony_ci################################## 1087db96d56Sopenharmony_ci# find files 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_cidef match_glob(filename, pattern): 1117db96d56Sopenharmony_ci if fnmatch.fnmatch(filename, pattern): 1127db96d56Sopenharmony_ci return True 1137db96d56Sopenharmony_ci 1147db96d56Sopenharmony_ci # fnmatch doesn't handle ** quite right. It will not match the 1157db96d56Sopenharmony_ci # following: 1167db96d56Sopenharmony_ci # 1177db96d56Sopenharmony_ci # ('x/spam.py', 'x/**/*.py') 1187db96d56Sopenharmony_ci # ('spam.py', '**/*.py') 1197db96d56Sopenharmony_ci # 1207db96d56Sopenharmony_ci # though it *will* match the following: 1217db96d56Sopenharmony_ci # 1227db96d56Sopenharmony_ci # ('x/y/spam.py', 'x/**/*.py') 1237db96d56Sopenharmony_ci # ('x/spam.py', '**/*.py') 1247db96d56Sopenharmony_ci 1257db96d56Sopenharmony_ci if '**/' not in pattern: 1267db96d56Sopenharmony_ci return False 1277db96d56Sopenharmony_ci 1287db96d56Sopenharmony_ci # We only accommodate the single-"**" case. 1297db96d56Sopenharmony_ci return fnmatch.fnmatch(filename, pattern.replace('**/', '', 1)) 1307db96d56Sopenharmony_ci 1317db96d56Sopenharmony_ci 1327db96d56Sopenharmony_cidef process_filenames(filenames, *, 1337db96d56Sopenharmony_ci start=None, 1347db96d56Sopenharmony_ci include=None, 1357db96d56Sopenharmony_ci exclude=None, 1367db96d56Sopenharmony_ci relroot=USE_CWD, 1377db96d56Sopenharmony_ci ): 1387db96d56Sopenharmony_ci if relroot and relroot is not USE_CWD: 1397db96d56Sopenharmony_ci relroot = os.path.abspath(relroot) 1407db96d56Sopenharmony_ci if start: 1417db96d56Sopenharmony_ci start = fix_filename(start, relroot, fixroot=False) 1427db96d56Sopenharmony_ci if include: 1437db96d56Sopenharmony_ci include = set(fix_filename(v, relroot, fixroot=False) 1447db96d56Sopenharmony_ci for v in include) 1457db96d56Sopenharmony_ci if exclude: 1467db96d56Sopenharmony_ci exclude = set(fix_filename(v, relroot, fixroot=False) 1477db96d56Sopenharmony_ci for v in exclude) 1487db96d56Sopenharmony_ci 1497db96d56Sopenharmony_ci onempty = Exception('no filenames provided') 1507db96d56Sopenharmony_ci for filename, solo in iter_many(filenames, onempty): 1517db96d56Sopenharmony_ci filename = fix_filename(filename, relroot, fixroot=False) 1527db96d56Sopenharmony_ci relfile = format_filename(filename, relroot, fixroot=False, normalize=False) 1537db96d56Sopenharmony_ci check, start = _get_check(filename, start, include, exclude) 1547db96d56Sopenharmony_ci yield filename, relfile, check, solo 1557db96d56Sopenharmony_ci 1567db96d56Sopenharmony_ci 1577db96d56Sopenharmony_cidef expand_filenames(filenames): 1587db96d56Sopenharmony_ci for filename in filenames: 1597db96d56Sopenharmony_ci # XXX Do we need to use glob.escape (a la commit 9355868458, GH-20994)? 1607db96d56Sopenharmony_ci if '**/' in filename: 1617db96d56Sopenharmony_ci yield from glob.glob(filename.replace('**/', '')) 1627db96d56Sopenharmony_ci yield from glob.glob(filename) 1637db96d56Sopenharmony_ci 1647db96d56Sopenharmony_ci 1657db96d56Sopenharmony_cidef _get_check(filename, start, include, exclude): 1667db96d56Sopenharmony_ci if start and filename != start: 1677db96d56Sopenharmony_ci return (lambda: '<skipped>'), start 1687db96d56Sopenharmony_ci else: 1697db96d56Sopenharmony_ci def check(): 1707db96d56Sopenharmony_ci if _is_excluded(filename, exclude, include): 1717db96d56Sopenharmony_ci return '<excluded>' 1727db96d56Sopenharmony_ci return None 1737db96d56Sopenharmony_ci return check, None 1747db96d56Sopenharmony_ci 1757db96d56Sopenharmony_ci 1767db96d56Sopenharmony_cidef _is_excluded(filename, exclude, include): 1777db96d56Sopenharmony_ci if include: 1787db96d56Sopenharmony_ci for included in include: 1797db96d56Sopenharmony_ci if match_glob(filename, included): 1807db96d56Sopenharmony_ci return False 1817db96d56Sopenharmony_ci return True 1827db96d56Sopenharmony_ci elif exclude: 1837db96d56Sopenharmony_ci for excluded in exclude: 1847db96d56Sopenharmony_ci if match_glob(filename, excluded): 1857db96d56Sopenharmony_ci return True 1867db96d56Sopenharmony_ci return False 1877db96d56Sopenharmony_ci else: 1887db96d56Sopenharmony_ci return False 1897db96d56Sopenharmony_ci 1907db96d56Sopenharmony_ci 1917db96d56Sopenharmony_cidef _walk_tree(root, *, 1927db96d56Sopenharmony_ci _walk=os.walk, 1937db96d56Sopenharmony_ci ): 1947db96d56Sopenharmony_ci # A wrapper around os.walk that resolves the filenames. 1957db96d56Sopenharmony_ci for parent, _, names in _walk(root): 1967db96d56Sopenharmony_ci for name in names: 1977db96d56Sopenharmony_ci yield os.path.join(parent, name) 1987db96d56Sopenharmony_ci 1997db96d56Sopenharmony_ci 2007db96d56Sopenharmony_cidef walk_tree(root, *, 2017db96d56Sopenharmony_ci suffix=None, 2027db96d56Sopenharmony_ci walk=_walk_tree, 2037db96d56Sopenharmony_ci ): 2047db96d56Sopenharmony_ci """Yield each file in the tree under the given directory name. 2057db96d56Sopenharmony_ci 2067db96d56Sopenharmony_ci If "suffix" is provided then only files with that suffix will 2077db96d56Sopenharmony_ci be included. 2087db96d56Sopenharmony_ci """ 2097db96d56Sopenharmony_ci if suffix and not isinstance(suffix, str): 2107db96d56Sopenharmony_ci raise ValueError('suffix must be a string') 2117db96d56Sopenharmony_ci 2127db96d56Sopenharmony_ci for filename in walk(root): 2137db96d56Sopenharmony_ci if suffix and not filename.endswith(suffix): 2147db96d56Sopenharmony_ci continue 2157db96d56Sopenharmony_ci yield filename 2167db96d56Sopenharmony_ci 2177db96d56Sopenharmony_ci 2187db96d56Sopenharmony_cidef glob_tree(root, *, 2197db96d56Sopenharmony_ci suffix=None, 2207db96d56Sopenharmony_ci _glob=glob.iglob, 2217db96d56Sopenharmony_ci ): 2227db96d56Sopenharmony_ci """Yield each file in the tree under the given directory name. 2237db96d56Sopenharmony_ci 2247db96d56Sopenharmony_ci If "suffix" is provided then only files with that suffix will 2257db96d56Sopenharmony_ci be included. 2267db96d56Sopenharmony_ci """ 2277db96d56Sopenharmony_ci suffix = suffix or '' 2287db96d56Sopenharmony_ci if not isinstance(suffix, str): 2297db96d56Sopenharmony_ci raise ValueError('suffix must be a string') 2307db96d56Sopenharmony_ci 2317db96d56Sopenharmony_ci for filename in _glob(f'{root}/*{suffix}'): 2327db96d56Sopenharmony_ci yield filename 2337db96d56Sopenharmony_ci for filename in _glob(f'{root}/**/*{suffix}'): 2347db96d56Sopenharmony_ci yield filename 2357db96d56Sopenharmony_ci 2367db96d56Sopenharmony_ci 2377db96d56Sopenharmony_cidef iter_files(root, suffix=None, relparent=None, *, 2387db96d56Sopenharmony_ci get_files=os.walk, 2397db96d56Sopenharmony_ci _glob=glob_tree, 2407db96d56Sopenharmony_ci _walk=walk_tree, 2417db96d56Sopenharmony_ci ): 2427db96d56Sopenharmony_ci """Yield each file in the tree under the given directory name. 2437db96d56Sopenharmony_ci 2447db96d56Sopenharmony_ci If "root" is a non-string iterable then do the same for each of 2457db96d56Sopenharmony_ci those trees. 2467db96d56Sopenharmony_ci 2477db96d56Sopenharmony_ci If "suffix" is provided then only files with that suffix will 2487db96d56Sopenharmony_ci be included. 2497db96d56Sopenharmony_ci 2507db96d56Sopenharmony_ci if "relparent" is provided then it is used to resolve each 2517db96d56Sopenharmony_ci filename as a relative path. 2527db96d56Sopenharmony_ci """ 2537db96d56Sopenharmony_ci if not isinstance(root, str): 2547db96d56Sopenharmony_ci roots = root 2557db96d56Sopenharmony_ci for root in roots: 2567db96d56Sopenharmony_ci yield from iter_files(root, suffix, relparent, 2577db96d56Sopenharmony_ci get_files=get_files, 2587db96d56Sopenharmony_ci _glob=_glob, _walk=_walk) 2597db96d56Sopenharmony_ci return 2607db96d56Sopenharmony_ci 2617db96d56Sopenharmony_ci # Use the right "walk" function. 2627db96d56Sopenharmony_ci if get_files in (glob.glob, glob.iglob, glob_tree): 2637db96d56Sopenharmony_ci get_files = _glob 2647db96d56Sopenharmony_ci else: 2657db96d56Sopenharmony_ci _files = _walk_tree if get_files in (os.walk, walk_tree) else get_files 2667db96d56Sopenharmony_ci get_files = (lambda *a, **k: _walk(*a, walk=_files, **k)) 2677db96d56Sopenharmony_ci 2687db96d56Sopenharmony_ci # Handle a single suffix. 2697db96d56Sopenharmony_ci if suffix and not isinstance(suffix, str): 2707db96d56Sopenharmony_ci filenames = get_files(root) 2717db96d56Sopenharmony_ci suffix = tuple(suffix) 2727db96d56Sopenharmony_ci else: 2737db96d56Sopenharmony_ci filenames = get_files(root, suffix=suffix) 2747db96d56Sopenharmony_ci suffix = None 2757db96d56Sopenharmony_ci 2767db96d56Sopenharmony_ci for filename in filenames: 2777db96d56Sopenharmony_ci if suffix and not isinstance(suffix, str): # multiple suffixes 2787db96d56Sopenharmony_ci if not filename.endswith(suffix): 2797db96d56Sopenharmony_ci continue 2807db96d56Sopenharmony_ci if relparent: 2817db96d56Sopenharmony_ci filename = os.path.relpath(filename, relparent) 2827db96d56Sopenharmony_ci yield filename 2837db96d56Sopenharmony_ci 2847db96d56Sopenharmony_ci 2857db96d56Sopenharmony_cidef iter_files_by_suffix(root, suffixes, relparent=None, *, 2867db96d56Sopenharmony_ci walk=walk_tree, 2877db96d56Sopenharmony_ci _iter_files=iter_files, 2887db96d56Sopenharmony_ci ): 2897db96d56Sopenharmony_ci """Yield each file in the tree that has the given suffixes. 2907db96d56Sopenharmony_ci 2917db96d56Sopenharmony_ci Unlike iter_files(), the results are in the original suffix order. 2927db96d56Sopenharmony_ci """ 2937db96d56Sopenharmony_ci if isinstance(suffixes, str): 2947db96d56Sopenharmony_ci suffixes = [suffixes] 2957db96d56Sopenharmony_ci # XXX Ignore repeated suffixes? 2967db96d56Sopenharmony_ci for suffix in suffixes: 2977db96d56Sopenharmony_ci yield from _iter_files(root, suffix, relparent) 2987db96d56Sopenharmony_ci 2997db96d56Sopenharmony_ci 3007db96d56Sopenharmony_ci################################## 3017db96d56Sopenharmony_ci# file info 3027db96d56Sopenharmony_ci 3037db96d56Sopenharmony_ci# XXX posix-only? 3047db96d56Sopenharmony_ci 3057db96d56Sopenharmony_ciS_IRANY = stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH 3067db96d56Sopenharmony_ciS_IWANY = stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH 3077db96d56Sopenharmony_ciS_IXANY = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH 3087db96d56Sopenharmony_ci 3097db96d56Sopenharmony_ci 3107db96d56Sopenharmony_cidef is_readable(file, *, user=None, check=False): 3117db96d56Sopenharmony_ci filename, st, mode = _get_file_info(file) 3127db96d56Sopenharmony_ci if check: 3137db96d56Sopenharmony_ci try: 3147db96d56Sopenharmony_ci okay = _check_file(filename, S_IRANY) 3157db96d56Sopenharmony_ci except NotImplementedError: 3167db96d56Sopenharmony_ci okay = NotImplemented 3177db96d56Sopenharmony_ci if okay is not NotImplemented: 3187db96d56Sopenharmony_ci return okay 3197db96d56Sopenharmony_ci # Fall back to checking the mode. 3207db96d56Sopenharmony_ci return _check_mode(st, mode, S_IRANY, user) 3217db96d56Sopenharmony_ci 3227db96d56Sopenharmony_ci 3237db96d56Sopenharmony_cidef is_writable(file, *, user=None, check=False): 3247db96d56Sopenharmony_ci filename, st, mode = _get_file_info(file) 3257db96d56Sopenharmony_ci if check: 3267db96d56Sopenharmony_ci try: 3277db96d56Sopenharmony_ci okay = _check_file(filename, S_IWANY) 3287db96d56Sopenharmony_ci except NotImplementedError: 3297db96d56Sopenharmony_ci okay = NotImplemented 3307db96d56Sopenharmony_ci if okay is not NotImplemented: 3317db96d56Sopenharmony_ci return okay 3327db96d56Sopenharmony_ci # Fall back to checking the mode. 3337db96d56Sopenharmony_ci return _check_mode(st, mode, S_IWANY, user) 3347db96d56Sopenharmony_ci 3357db96d56Sopenharmony_ci 3367db96d56Sopenharmony_cidef is_executable(file, *, user=None, check=False): 3377db96d56Sopenharmony_ci filename, st, mode = _get_file_info(file) 3387db96d56Sopenharmony_ci if check: 3397db96d56Sopenharmony_ci try: 3407db96d56Sopenharmony_ci okay = _check_file(filename, S_IXANY) 3417db96d56Sopenharmony_ci except NotImplementedError: 3427db96d56Sopenharmony_ci okay = NotImplemented 3437db96d56Sopenharmony_ci if okay is not NotImplemented: 3447db96d56Sopenharmony_ci return okay 3457db96d56Sopenharmony_ci # Fall back to checking the mode. 3467db96d56Sopenharmony_ci return _check_mode(st, mode, S_IXANY, user) 3477db96d56Sopenharmony_ci 3487db96d56Sopenharmony_ci 3497db96d56Sopenharmony_cidef _get_file_info(file): 3507db96d56Sopenharmony_ci filename = st = mode = None 3517db96d56Sopenharmony_ci if isinstance(file, int): 3527db96d56Sopenharmony_ci mode = file 3537db96d56Sopenharmony_ci elif isinstance(file, os.stat_result): 3547db96d56Sopenharmony_ci st = file 3557db96d56Sopenharmony_ci else: 3567db96d56Sopenharmony_ci if isinstance(file, str): 3577db96d56Sopenharmony_ci filename = file 3587db96d56Sopenharmony_ci elif hasattr(file, 'name') and os.path.exists(file.name): 3597db96d56Sopenharmony_ci filename = file.name 3607db96d56Sopenharmony_ci else: 3617db96d56Sopenharmony_ci raise NotImplementedError(file) 3627db96d56Sopenharmony_ci st = os.stat(filename) 3637db96d56Sopenharmony_ci return filename, st, mode or st.st_mode 3647db96d56Sopenharmony_ci 3657db96d56Sopenharmony_ci 3667db96d56Sopenharmony_cidef _check_file(filename, check): 3677db96d56Sopenharmony_ci if not isinstance(filename, str): 3687db96d56Sopenharmony_ci raise Exception(f'filename required to check file, got {filename}') 3697db96d56Sopenharmony_ci if check & S_IRANY: 3707db96d56Sopenharmony_ci flags = os.O_RDONLY 3717db96d56Sopenharmony_ci elif check & S_IWANY: 3727db96d56Sopenharmony_ci flags = os.O_WRONLY 3737db96d56Sopenharmony_ci elif check & S_IXANY: 3747db96d56Sopenharmony_ci # We can worry about S_IXANY later 3757db96d56Sopenharmony_ci return NotImplemented 3767db96d56Sopenharmony_ci else: 3777db96d56Sopenharmony_ci raise NotImplementedError(check) 3787db96d56Sopenharmony_ci 3797db96d56Sopenharmony_ci try: 3807db96d56Sopenharmony_ci fd = os.open(filename, flags) 3817db96d56Sopenharmony_ci except PermissionError: 3827db96d56Sopenharmony_ci return False 3837db96d56Sopenharmony_ci # We do not ignore other exceptions. 3847db96d56Sopenharmony_ci else: 3857db96d56Sopenharmony_ci os.close(fd) 3867db96d56Sopenharmony_ci return True 3877db96d56Sopenharmony_ci 3887db96d56Sopenharmony_ci 3897db96d56Sopenharmony_cidef _get_user_info(user): 3907db96d56Sopenharmony_ci import pwd 3917db96d56Sopenharmony_ci username = uid = gid = groups = None 3927db96d56Sopenharmony_ci if user is None: 3937db96d56Sopenharmony_ci uid = os.geteuid() 3947db96d56Sopenharmony_ci #username = os.getlogin() 3957db96d56Sopenharmony_ci username = pwd.getpwuid(uid)[0] 3967db96d56Sopenharmony_ci gid = os.getgid() 3977db96d56Sopenharmony_ci groups = os.getgroups() 3987db96d56Sopenharmony_ci else: 3997db96d56Sopenharmony_ci if isinstance(user, int): 4007db96d56Sopenharmony_ci uid = user 4017db96d56Sopenharmony_ci entry = pwd.getpwuid(uid) 4027db96d56Sopenharmony_ci username = entry.pw_name 4037db96d56Sopenharmony_ci elif isinstance(user, str): 4047db96d56Sopenharmony_ci username = user 4057db96d56Sopenharmony_ci entry = pwd.getpwnam(username) 4067db96d56Sopenharmony_ci uid = entry.pw_uid 4077db96d56Sopenharmony_ci else: 4087db96d56Sopenharmony_ci raise NotImplementedError(user) 4097db96d56Sopenharmony_ci gid = entry.pw_gid 4107db96d56Sopenharmony_ci os.getgrouplist(username, gid) 4117db96d56Sopenharmony_ci return username, uid, gid, groups 4127db96d56Sopenharmony_ci 4137db96d56Sopenharmony_ci 4147db96d56Sopenharmony_cidef _check_mode(st, mode, check, user): 4157db96d56Sopenharmony_ci orig = check 4167db96d56Sopenharmony_ci _, uid, gid, groups = _get_user_info(user) 4177db96d56Sopenharmony_ci if check & S_IRANY: 4187db96d56Sopenharmony_ci check -= S_IRANY 4197db96d56Sopenharmony_ci matched = False 4207db96d56Sopenharmony_ci if mode & stat.S_IRUSR: 4217db96d56Sopenharmony_ci if st.st_uid == uid: 4227db96d56Sopenharmony_ci matched = True 4237db96d56Sopenharmony_ci if mode & stat.S_IRGRP: 4247db96d56Sopenharmony_ci if st.st_uid == gid or st.st_uid in groups: 4257db96d56Sopenharmony_ci matched = True 4267db96d56Sopenharmony_ci if mode & stat.S_IROTH: 4277db96d56Sopenharmony_ci matched = True 4287db96d56Sopenharmony_ci if not matched: 4297db96d56Sopenharmony_ci return False 4307db96d56Sopenharmony_ci if check & S_IWANY: 4317db96d56Sopenharmony_ci check -= S_IWANY 4327db96d56Sopenharmony_ci matched = False 4337db96d56Sopenharmony_ci if mode & stat.S_IWUSR: 4347db96d56Sopenharmony_ci if st.st_uid == uid: 4357db96d56Sopenharmony_ci matched = True 4367db96d56Sopenharmony_ci if mode & stat.S_IWGRP: 4377db96d56Sopenharmony_ci if st.st_uid == gid or st.st_uid in groups: 4387db96d56Sopenharmony_ci matched = True 4397db96d56Sopenharmony_ci if mode & stat.S_IWOTH: 4407db96d56Sopenharmony_ci matched = True 4417db96d56Sopenharmony_ci if not matched: 4427db96d56Sopenharmony_ci return False 4437db96d56Sopenharmony_ci if check & S_IXANY: 4447db96d56Sopenharmony_ci check -= S_IXANY 4457db96d56Sopenharmony_ci matched = False 4467db96d56Sopenharmony_ci if mode & stat.S_IXUSR: 4477db96d56Sopenharmony_ci if st.st_uid == uid: 4487db96d56Sopenharmony_ci matched = True 4497db96d56Sopenharmony_ci if mode & stat.S_IXGRP: 4507db96d56Sopenharmony_ci if st.st_uid == gid or st.st_uid in groups: 4517db96d56Sopenharmony_ci matched = True 4527db96d56Sopenharmony_ci if mode & stat.S_IXOTH: 4537db96d56Sopenharmony_ci matched = True 4547db96d56Sopenharmony_ci if not matched: 4557db96d56Sopenharmony_ci return False 4567db96d56Sopenharmony_ci if check: 4577db96d56Sopenharmony_ci raise NotImplementedError((orig, check)) 4587db96d56Sopenharmony_ci return True 459