From 7d6f628ed4c3c3dca32bef01b2581f2e9bcde189 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sat, 14 Jan 2017 14:41:18 +0530 Subject: Support file perms for install_data and install_subdir With the 'install_mode' kwarg, you can now specify the file and directory permissions and the owner and the group to be used while installing. You can pass either: * A single string specifying just the permissions * A list of strings with: - The first argument a string of permissions - The second argument a string specifying the owner or an int specifying the uid - The third argument a string specifying the group or an int specifying the gid Specifying `false` as any of the arguments skips setting that one. The format of the permissions kwarg is the same as the symbolic notation used by ls -l with the first character that specifies 'd', '-', 'c', etc for the file type omitted since that is always obvious from the context. Includes unit tests for the same. Sadly these only run on Linux right now, but we want them to run on all platforms. We do set the mode in the integration tests for all platforms but we don't check if they were actually set correctly. --- mesonbuild/scripts/meson_install.py | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'mesonbuild/scripts/meson_install.py') diff --git a/mesonbuild/scripts/meson_install.py b/mesonbuild/scripts/meson_install.py index 676a1e5..a74573e 100644 --- a/mesonbuild/scripts/meson_install.py +++ b/mesonbuild/scripts/meson_install.py @@ -16,10 +16,34 @@ import sys, pickle, os, shutil, subprocess, gzip, platform from glob import glob from . import depfixer from . import destdir_join -from ..mesonlib import Popen_safe +from ..mesonlib import is_windows, Popen_safe install_log_file = None +def set_mode(path, mode): + if mode is None: + # Keep mode unchanged + return + if (mode.perms_s or mode.owner or mode.group) is None: + # Nothing to set + return + # No chown() on Windows, and must set one of owner/group + if not is_windows() and (mode.owner or mode.group) is not None: + try: + shutil.chown(path, mode.owner, mode.group) + except PermissionError as e: + msg = '{!r}: Unable to set owner {!r} and group {!r}: {}, ignoring...' + print(msg.format(path, mode.owner, mode.group, e.strerror)) + # Must set permissions *after* setting owner/group otherwise the + # setuid/setgid bits will get wiped by chmod + # NOTE: On Windows you can set read/write perms; the rest are ignored + if mode.perms_s is not None: + try: + os.chmod(path, mode.perms) + except PermissionError as e: + msg = '{!r}: Unable to set permissions {!r}: {}, ignoring...' + print(msg.format(path, mode.perms_s, e.strerror)) + def append_to_log(line): install_log_file.write(line) if not line.endswith('\n'): @@ -96,7 +120,7 @@ def do_install(datafilename): run_install_script(d) def install_subdirs(data): - for (src_dir, inst_dir, dst_dir) in data.install_subdirs: + for (src_dir, inst_dir, dst_dir, mode) in data.install_subdirs: if src_dir.endswith('/') or src_dir.endswith('\\'): src_dir = src_dir[:-1] src_prefix = os.path.join(src_dir, inst_dir) @@ -105,15 +129,19 @@ def install_subdirs(data): if not os.path.exists(dst_dir): os.makedirs(dst_dir) do_copydir(src_prefix, src_dir, dst_dir) + dst_prefix = os.path.join(dst_dir, inst_dir) + set_mode(dst_prefix, mode) def install_data(d): for i in d.data: fullfilename = i[0] outfilename = get_destdir_path(d, i[1]) + mode = i[2] outdir = os.path.split(outfilename)[0] os.makedirs(outdir, exist_ok=True) print('Installing %s to %s.' % (fullfilename, outdir)) do_copyfile(fullfilename, outfilename) + set_mode(outfilename, mode) def install_man(d): for m in d.man: -- cgit v1.1