示例#1
0
def main():
    parser = argparse.ArgumentParser(description='Inspect '
                                     'a given MFT file record.')
    parser.add_argument('-a',
                        action="store",
                        metavar="cache_size",
                        type=int,
                        dest="cache_size",
                        default=1024,
                        help="Size of cache.")
    parser.add_argument('-p',
                        action="store",
                        metavar="prefix",
                        nargs=1,
                        dest="prefix",
                        default="\\.",
                        help="Prefix paths with `prefix` rather than \\.\\")
    parser.add_argument('-v',
                        action="store_true",
                        dest="verbose",
                        help="Print debugging information")
    parser.add_argument('mft', action="store", help="Path to MFT")
    parser.add_argument('record_or_path',
                        action="store",
                        help="MFT record or file path to inspect")

    results = parser.parse_args()

    if results.verbose:
        logging.basicConfig(level=logging.DEBUG)

    with Mmap(results.mft) as buf:
        record_cache = Cache(results.cache_size)
        path_cache = Cache(results.cache_size)

        enum = MFTEnumerator(buf,
                             record_cache=record_cache,
                             path_cache=path_cache)

        should_use_inode = False
        try:
            record_num = int(results.record_or_path)
            should_use_inode = True
        except ValueError:
            should_use_inode = False

        if should_use_inode:
            record = enum.get_record(record_num)
            path = results.prefix + enum.get_path(record)
            print_indx_info(record, path)
        else:
            path = results.record_or_path
            record = enum.get_record_by_path(path)
            print_indx_info(record, results.prefix + path)
def main():
    parser = argparse.ArgumentParser(description='Inspect '
                                     'a given MFT file record.')
    parser.add_argument('-a', action="store", metavar="cache_size", type=int,
                        dest="cache_size", default=1024,
                        help="Size of cache.")
    parser.add_argument('-p', action="store", metavar="prefix",
                        nargs=1, dest="prefix", default="\\.",
                        help="Prefix paths with `prefix` rather than \\.\\")
    parser.add_argument('-v', action="store_true", dest="verbose",
                        help="Print debugging information")
    parser.add_argument('mft', action="store",
                        help="Path to MFT")
    parser.add_argument('record_or_path', action="store",
                        help="MFT record or file path to inspect")

    results = parser.parse_args()

    if results.verbose:
        logging.basicConfig(level=logging.DEBUG)

    with Mmap(results.mft) as buf:
        record_cache = Cache(results.cache_size)
        path_cache = Cache(results.cache_size)

        enum = MFTEnumerator(buf,
                             record_cache=record_cache,
                             path_cache=path_cache)

        should_use_inode = False
        try:
            record_num = int(results.record_or_path)
            should_use_inode = True
        except ValueError:
            should_use_inode = False

        if should_use_inode:
            record = enum.get_record(record_num)
            path = results.prefix + enum.get_path(record)
            print_indx_info(record, path)
        else:
            path = results.record_or_path
            record = enum.get_record_by_path(path)
            print_indx_info(record, results.prefix + path)
示例#3
0
class MFTFuseOperations(Operations):
    """
    MFTFuseOperations is a FUSE driver for NTFS MFT files.
    """
    def __init__(self, root, mfttree, buf):
        self._root = root
        self._tree = mfttree
        self._buf = buf
        self._opened_files = {}  # dict(int --> FH subclass)

        record_cache = Cache(1024)
        path_cache = Cache(1024)

        self._enumerator = MFTEnumerator(buf,
                             record_cache=record_cache,
                             path_cache=path_cache)

    # Helpers
    # =======
    def _get_node(self, path):
        """
        _get_node returns the MFTTreeNode associated with a path.
        @type path: str
        @rtype: MFT.MFTTreeNode
        @raises: FuseOSError(errno.ENOENT)
        """
        if path.startswith("/"):
            path = path[1:]

        current_node = self._tree.get_root()
        for component in path.split("/"):
            if component == "":
                continue
            try:
                current_node = current_node.get_child_node(component)
            except KeyError:
                raise FuseOSError(errno.ENOENT)

        return current_node

    def _get_record(self, path):
        """
        _get_record returns the MFTRecord associated with a path.
        @type path: str
        @rtype: MFT.MFTRecord
        """
        return self._enumerator.get_record(self._get_node(path).get_record_number())

    # Filesystem methods
    # ==================
    @log
    def getattr(self, path, fh=None):
        (uid, gid, pid) = fuse_get_context()

        working_path = path

        if is_special_file(path):
            (working_path, special) = explode_special_file(working_path)

        record = self._get_record(working_path)
        if record.is_directory():
            mode = (stat.S_IFDIR | PERMISSION_ALL_READ)
            nlink = 2
        else:
            mode = (stat.S_IFREG | PERMISSION_ALL_READ)
            nlink = 1

        # TODO(wb): fix the duplication of this code with the FH classes
        if is_special_file(path):
            size = 0
            (working_path, special) = explode_special_file(path)
            if special == "meta":
                node = self._get_node(working_path)
                record_buf = self._enumerator.get_record_buf(node.get_record_number())
                size = len(get_meta_for_file(record, working_path))
        else:
            data_attribute = record.data_attribute()
            if data_attribute is not None:
                if data_attribute.non_resident() == 0:
                    size = len(data_attribute.value())
                else:
                    size = data_attribute.data_size()
            else:
                size = record.filename_information().logical_size()

        return {
            "st_atime": unixtimestamp(record.standard_information().accessed_time()),
            "st_ctime": unixtimestamp(record.standard_information().changed_time()),
            #"st_crtime": unixtimestamp(record.standard_information().created_time()),
            "st_mtime": unixtimestamp(record.standard_information().modified_time()),
            "st_size": size,
            "st_uid": uid,
            "st_gid": gid,
            "st_mode": mode,
            "st_nlink": nlink,
        }

    @log
    def readdir(self, path, fh):
        dirents = ['.', '..']
        record = self._get_node(path)
        dirents.extend(map(lambda r: r.get_filename(), record.get_children_nodes()))
        for r in dirents:
            yield r

    @log
    def readlink(self, path):
        return path

    @log
    def statfs(self, path):
        return dict((key, 0) for key in ('f_bavail', 'f_bfree',
                                         'f_blocks', 'f_bsize', 'f_favail',
                                         'f_ffree', 'f_files', 'f_flag',
                                         'f_frsize', 'f_namemax'))

    @log
    def chmod(self, path, mode):
        return errno.EROFS

    @log
    def chown(self, path, uid, gid):
        return errno.EROFS

    @log
    def mknod(self, path, mode, dev):
        return errno.EROFS

    @log
    def rmdir(self, path):
        return errno.EROFS

    @log
    def mkdir(self, path, mode):
        return errno.EROFS

    @log
    def unlink(self, path):
        return errno.EROFS

    @log
    def symlink(self, target, name):
        return errno.EROFS

    @log
    def rename(self, old, new):
        return errno.EROFS

    @log
    def link(self, target, name):
        return errno.EROFS

    @log
    def utimens(self, path, times=None):
        return errno.EROFS

    # File methods
    # ============

    def _get_available_fh(self):
        """
        _get_available_fh returns an unused fh
        The caller must be careful to handle race conditions.
        @rtype: int
        """
        for i in xrange(65534):
            if i not in self._opened_files:
                return i

    @log
    def open(self, path, flags):
        if flags & os.O_WRONLY > 0:
            return errno.EROFS
        if flags & os.O_RDWR > 0:
            return errno.EROFS

        # TODO(wb): race here on fh used/unused
        fh = self._get_available_fh()
        if is_special_file(path):
            (path, special) = explode_special_file(path)
            if special == "meta":
                record = self._get_record(path)
                node = self._get_node(path)
                record_buf = self._enumerator.get_record_buf(node.get_record_number())
                self._opened_files[fh] = MetaFH(fh, record, path, record_buf)
            else:
                raise FuseOSError(errno.ENOENT)
        else:
            self._opened_files[fh] = RegularFH(fh, self._get_record(path))

        return fh

    @log
    def read(self, path, length, offset, fh):
        txt = self._opened_files[fh].get_data().encode("utf-8")
        return txt[offset:offset+length]

    @log
    def flush(self, path, fh):
        return ""

    @log
    def release(self, path, fh):
        del self._opened_files[fh]

    @log
    def create(self, path, mode, fi=None):
        return errno.EROFS

    @log
    def write(self, path, buf, offset, fh):
        return errno.EROFS

    @log
    def truncate(self, path, length, fh=None):
        return errno.EROFS

    @log
    def fsync(self, path, fdatasync, fh):
        return errno.EPERM