class MntEnt(object): __slots__ = [ 'mnt_fsname', 'mnt_dir', 'mnt_type', 'mnt_opts', 'mnt_freq', 'mnt_passno', ] @classmethod def from_string(cls, line): data = line.split(' ') mnt_fsname, mnt_dir, mnt_type, mnt_opts = [ cls._decode_octal(_) for _ in data[0:4] ] mnt_freq, mnt_passno = [ int(_, 10) for _ in data[4:6] ] return cls(mnt_fsname, mnt_dir, mnt_type, mnt_opts, mnt_freq, mnt_passno) def __init__(self, mnt_fsname, mnt_dir, mnt_type, mnt_opts, mnt_freq=0, mnt_passno=0): self.mnt_fsname = mnt_fsname self.mnt_dir = mnt_dir self.mnt_type = mnt_type self.mnt_opts = mnt_opts self.mnt_freq = mnt_freq self.mnt_passno = mnt_passno RE_DECODE_OCTAL = re.compile(r'\\([0-7]{3})') @classmethod def _decode_octal(cls, string): r""" >>> MntEnt._decode_octal(r'a\040b\011c\012d\134e') 'a b\tc\nd\\e' """ return cls.RE_DECODE_OCTAL.sub( lambda match: chr(int(match.group(1), 8)), string ) RE_ENCODE_OCTAL = re.compile(r'[\t\n \\]') @classmethod def _encode_octal(cls, string): r""" >>> MntEnt._encode_octal('a b\tc\nd\\e') 'a\\040b\\011c\\012d\\134e' """ return cls.RE_ENCODE_OCTAL.sub( lambda match: r'\%03o' % (ord(match.group()),), string ) def __str__(self): return ' '.join(( self._encode_octal(self.mnt_fsname), self._encode_octal(self.mnt_dir), self._encode_octal(self.mnt_type), self._encode_octal(self.mnt_opts), '%d' % (self.mnt_freq,), '%d' % (self.mnt_passno,), )) def __repr__(self): return '%s(%r, %r, %r, %r, mnt_freq=%d, mnt_passno=%d)' % ( self.__class__.__name__, self.mnt_fsname, self.mnt_dir, self.mnt_type, self.mnt_opts, self.mnt_freq, self.mnt_passno, ) class Mounts(list): def __init__(self, filename='/proc/mounts'): list.__init__(self) for line in open(filename, 'rb'): self.append(MntEnt.from_string(line)) def mounted_directories(self): for mnt in self: yield mnt.mnt_dir def mount_source(self, mount_point): # unused for mnt in reversed(self): if mnt.mnt_dir == mount_point: return mnt.mnt_fsname raise KeyError(mount_point)