Galaxie Shell 0.2.6 documentation


Navigation:   | Index   | Search   | Top   | Up   |
Table of Content: |

© Copyright 2020-2024, Galaxie Shell Team.

Top » Module code » glxshell.lib.symbolic_mode

Source code for glxshell.lib.symbolic_mode

import re
from glxshell.lib.stat import S_IRWXU
from glxshell.lib.stat import S_IXUSR
from glxshell.lib.stat import S_IRWXG
from glxshell.lib.stat import S_IXGRP
from glxshell.lib.stat import S_IRWXO
from glxshell.lib.stat import S_IROTH
from glxshell.lib.stat import S_IWOTH
from glxshell.lib.stat import S_IXOTH
from glxshell.lib.stat import S_ISUID
from glxshell.lib.stat import S_ISGID

# The full regular expression is something like:
# [ugoa]*([+=-][rwxXsugo]+)+(,[ugoa]*([+=-][rwxXsugo]+)+)*
users_re = re.compile(r"[ugoa]+")
operation_re = re.compile(r"[+=-]")
permissions_re = re.compile(r"[rwxXsugo]+")


# These are known permissions but not (yet?) supported because
# they are platform specific.
#  t is GNU for specifying the swap device
#  l is IRIX for mandatory locking during access
# Standard POSIX names for the different fields
# Why isn't this available via an existing python module?

# General process:
#  1) construct a mask based on the symbolic information
#       this may need existing mode information (eg, for +ugo)
#  2) apply the mask as appropriate for the given operation
def _apply_symbolic_mode(mode, users, operation, permissions, umask, isdir):
    """(mode, users, operation, permission, umask, isdir) -> new mode
    Given the 'atom' of a symbolic mode (only one operation) and an
    existing umask and the flag to tell if this is a directory or file,
    apply the symbolic information (users, operation, permissions) to
    the existing mode and return the results.
    """
    # If no users are specified, treat it the same as 'a' except that
    # the umask should be used.  If users are specified, ignore the
    # umask (same as setting the umask value to 0).
    if users == "":
        users = "a"
    else:
        umask = 0
    # This multiplier is used to turn on the bits in the appropriate
    # field.  It is 01 for other, 010 for group, 0100 for user
    # 0101 for uo, 0111 for ugo, etc.
    mult = 0
    # This is used for the '=' operator, which should only affect
    # the user ranges specified.  It contains 1 for those bits which
    # are allowed to be changed.
    user_bits = S_ISGID | S_ISUID
    # construct the multiplier and set of bits to use
    if "u" in users or "a" in users:
        mult = mult + S_IXUSR
        user_bits = user_bits | S_IRWXU
    if "g" in users or "a" in users:
        mult = mult + S_IXGRP
        user_bits = user_bits | S_IRWXG
    if "o" in users or "a" in users:
        mult = mult + S_IXOTH
        user_bits = user_bits | S_IRWXO
    assert mult != 0
    # Construct the permissions mask
    mask = 0
    if "r" in permissions:
        mask = mask | (S_IROTH * mult)
    if "w" in permissions:
        mask = mask | (S_IWOTH * mult)
    if "x" in permissions or ("X" in permissions and isdir):
        mask = mask | (S_IXOTH * mult)
    elif "X" in permissions:
        # check if one of the excute bits is set
        if mode & (S_IXOTH | S_IXGRP | S_IXUSR):
            mask = mask | (S_IXOTH * mult)
    # copy from existing bits
    if "u" in permissions:
        mask = mask | ((mode & S_IRWXU) >> 6) * mult
    if "g" in permissions:
        mask = mask | ((mode & S_IRWXG) >> 3) * mult
    if "o" in permissions:
        mask = mask | ((mode & S_IRWXO) >> 0) * mult
    # set-uid/gui bit
    if "s" in permissions:
        if "u" in users:
            mask = mask | S_ISUID
        if "g" in users:
            mask = mask | S_ISGID
        if "o" in users:
            raise ValueError("Cannot use 'o' user flag with 's' permissions")
        if "a" in users:
            raise ValueError("Cannot use 'a' user flag with 's' permissions")
    # Apply the operation
    if operation == "+":
        mode = (mode & umask) | (mode | mask) & ~umask
    elif operation == "-":
        mode = (mode & umask) | (mode & ~mask) & ~umask
    elif operation == "=":
        # only affect the specified users
        umask = umask | ~user_bits
        mode = (mode & umask) | (mask) & ~umask
    else:
        raise AssertionError("unknown operation " + operation)
    return mode


# Break the full symbolic name into "atomic" terms; that is,
# break down into groups containing only:
#  a set of users
#  a single operation
#  a set of permissions
# This require saving the value of the users if there are successive
# operation/permission pairs
[docs] def symbolic_mode(symbolic, mode=None, isdir=0, umask=0): """ Convert a symbolic mode string into a mode. Examples: symbolic_mode("u+w", mode=0444) == 0644 symbolic_mode("=x", mode=0444, umask=0700) == 0411 symbolic_mode("og-rxw", mode=0777) == 0700 symbolic_mode("o-rxw,g-rxw", mode=0777) == 0700 symbolic_mode("a=rx,u+w") == 0755 symbolic_mode("og+X", mode=0644, isdir=0) == 0644 symbolic_mode("og+X", mode=0644, isdir=1) == 0655 For more detailed information, consult your local man page for chmod. :param symbolic: the symbilic mode representation :type symbolic: str :param mode: needed because some operation add, copy or remove bits from the old mode. If no mode is given, the default is 0755. :type mode: oct :param isdir: the X permission acts differently on files than on directories. A true value indicates this should be treated like a directory. The default is 0, which indicates a file. :type isdir: int :param umask: used when no users are given in the mode string. The default value is 0. :type umask: oct :return: mode :rtype: oct """ # offset position in the input pos = 0 # Default mode, according to the GNU documentation if mode is None: mode = 0o755 # scan for atoms while pos < len(symbolic): # Find users m = users_re.match(symbolic, pos) if m is None: users = "" else: users = m.group(0) pos = pos + len(users) while 1: # Find the operation m = operation_re.match(symbolic, pos) if m is None: raise TypeError("Missing operation in mode") operation = m.group(0) pos = pos + len(operation) # Find the permissions m = permissions_re.match(symbolic, pos) if m is None: permissions = "" else: permissions = m.group(0) pos = pos + len(permissions) # Have an atom, so apply it to the existing mode, and # update the mode. mode = _apply_symbolic_mode(mode, users, operation, permissions, umask, isdir) # Am I done with everything (really need a double break here) if not pos < len(symbolic): break # Am I at the start of a new atom? if symbolic[pos] == ",": pos = pos + 1 break return mode

Top » Module code » glxshell.lib.symbolic_mode

© Copyright 2020-2024, Galaxie Shell Team.
This page is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License (CC BY-NC-SA 4.0).
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
See History and License for more information.

Last updated on None.
Created using Sphinx 8.0.2.