<s> from __future__ import with_statement <EOL> import os <EOL> import sys <EOL> import stat <EOL> import errno <EOL> import inspect <EOL> import calendar <EOL> from fuse import FUSE , FuseOSError , Operations , fuse_get_context <EOL> from Progress import ProgressBarProgress <EOL> from BinaryParser import Mmap <EOL> from MFT import MFTTree <EOL> from MFT import Cache <EOL> from MFT import MFTEnumerator <EOL> from get_file_info import format_record <EOL> PERMISSION_ALL_READ = int ( "<STR_LIT>" , <NUM_LIT:8> ) <EOL> def unixtimestamp ( ts ) : <EOL> """<STR_LIT>""" <EOL> return calendar . timegm ( ts . utctimetuple ( ) ) <EOL> def log ( func ) : <EOL> """<STR_LIT>""" <EOL> def inner ( * args , ** kwargs ) : <EOL> func_name = inspect . stack ( ) [ <NUM_LIT:3> ] [ <NUM_LIT:3> ] <EOL> if func_name == "<STR_LIT>" : <EOL> func_name = inspect . stack ( ) [ <NUM_LIT:2> ] [ <NUM_LIT:3> ] <EOL> ( uid , gid , pid ) = fuse_get_context ( ) <EOL> pre = "<STR_LIT>" % ( <EOL> func_name , uid , gid , pid , <EOL> "<STR_LIT:U+002CU+0020>" . join ( map ( str , list ( args ) [ <NUM_LIT:1> : ] ) ) , str ( ** kwargs ) ) <EOL> try : <EOL> ret = func ( * args , ** kwargs ) <EOL> post = "<STR_LIT>" % ( str ( ret ) ) <EOL> sys . stderr . write ( "<STR_LIT>" % ( pre , post ) ) <EOL> return ret <EOL> except Exception as e : <EOL> post = "<STR_LIT>" % ( str ( e ) ) <EOL> sys . stderr . write ( "<STR_LIT>" % ( pre , post ) ) <EOL> raise e <EOL> return inner <EOL> class FH ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , fh , record ) : <EOL> super ( FH , self ) . __init__ ( ) <EOL> self . _fh = fh <EOL> self . _record = record <EOL> def get_data ( self ) : <EOL> """<STR_LIT>""" <EOL> raise RuntimeError ( "<STR_LIT>" ) <EOL> def get_size ( self ) : <EOL> """<STR_LIT>""" <EOL> raise RuntimeError ( "<STR_LIT>" ) <EOL> def get_fh ( self ) : <EOL> return self . _fh <EOL> class RegularFH ( FH ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , fh , record ) : <EOL> super ( RegularFH , self ) . __init__ ( fh , record ) <EOL> def get_data ( self ) : <EOL> data_attribute = self . _record . data_attribute ( ) <EOL> if data_attribute is not None and data_attribute . non_resident ( ) == <NUM_LIT:0> : <EOL> return data_attribute . value ( ) <EOL> return "<STR_LIT>" <EOL> def get_size ( self ) : <EOL> data_attribute = self . _record . data_attribute ( ) <EOL> if data_attribute is not None : <EOL> if data_attribute . non_resident ( ) == <NUM_LIT:0> : <EOL> return len ( self . get_data ( ) ) <EOL> else : <EOL> return data_attribute . data_size ( ) <EOL> else : <EOL> return self . _record . standard_information . logical_size ( ) <EOL> def get_meta_for_file ( record , path ) : <EOL> """<STR_LIT>""" <EOL> return format_record ( record , path ) <EOL> class MetaFH ( FH ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , fh , record , path , record_buf ) : <EOL> super ( MetaFH , self ) . __init__ ( fh , record ) <EOL> self . _path = path <EOL> self . _record_buf = record_buf <EOL> def get_data ( self ) : <EOL> return get_meta_for_file ( self . _record , self . _path ) <EOL> def get_size ( self ) : <EOL> return len ( self . get_data ( ) ) <EOL> def is_special_file ( path ) : <EOL> """<STR_LIT>""" <EOL> return "<STR_LIT>" in path . rpartition ( "<STR_LIT:/>" ) [ <NUM_LIT:2> ] <EOL> def explode_special_file ( path ) : <EOL> """<STR_LIT>""" <EOL> ( base , _ , special ) = path . rpartition ( "<STR_LIT>" ) <EOL> return base , special <EOL> class MFTFuseOperations ( Operations ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , root , mfttree , buf ) : <EOL> self . _root = root <EOL> self . _tree = mfttree <EOL> self . _buf = buf <EOL> self . _opened_files = { } <EOL> record_cache = Cache ( <NUM_LIT> ) <EOL> path_cache = Cache ( <NUM_LIT> ) <EOL> self . _enumerator = MFTEnumerator ( buf , <EOL> record_cache = record_cache , <EOL> path_cache = path_cache ) <EOL> def _get_node ( self , path ) : <EOL> """<STR_LIT>""" <EOL> if path . startswith ( "<STR_LIT:/>" ) : <EOL> path = path [ <NUM_LIT:1> : ] <EOL> current_node = self . _tree . get_root ( ) <EOL> for component in path . split ( "<STR_LIT:/>" ) : <EOL> if component == "<STR_LIT>" : <EOL> continue <EOL> try : <EOL> current_node = current_node . get_child_node ( component ) <EOL> except KeyError : <EOL> raise FuseOSError ( errno . ENOENT ) <EOL> return current_node <EOL> def _get_record ( self , path ) : <EOL> """<STR_LIT>""" <EOL> return self . _enumerator . get_record ( self . _get_node ( path ) . get_record_number ( ) ) <EOL> @ log <EOL> def getattr ( self , path , fh = None ) : <EOL> ( uid , gid , pid ) = fuse_get_context ( ) <EOL> working_path = path <EOL> if is_special_file ( path ) : <EOL> ( working_path , special ) = explode_special_file ( working_path ) <EOL> record = self . _get_record ( working_path ) <EOL> if record . is_directory ( ) : <EOL> mode = ( stat . S_IFDIR | PERMISSION_ALL_READ ) <EOL> nlink = <NUM_LIT:2> <EOL> else : <EOL> mode = ( stat . S_IFREG | PERMISSION_ALL_READ ) <EOL> nlink = <NUM_LIT:1> <EOL> if is_special_file ( path ) : <EOL> size = <NUM_LIT:0> <EOL> ( working_path , special ) = explode_special_file ( path ) <EOL> if special == "<STR_LIT>" : <EOL> node = self . _get_node ( working_path ) <EOL> record_buf = self . _enumerator . get_record_buf ( node . get_record_number ( ) ) <EOL> size = len ( get_meta_for_file ( record , working_path ) ) <EOL> else : <EOL> data_attribute = record . data_attribute ( ) <EOL> if data_attribute is not None : <EOL> if data_attribute . non_resident ( ) == <NUM_LIT:0> : <EOL> size = len ( data_attribute . value ( ) ) <EOL> else : <EOL> size = data_attribute . data_size ( ) <EOL> else : <EOL> size = record . filename_information ( ) . logical_size ( ) <EOL> return { <EOL> "<STR_LIT>" : unixtimestamp ( record . standard_information ( ) . accessed_time ( ) ) , <EOL> "<STR_LIT>" : unixtimestamp ( record . standard_information ( ) . changed_time ( ) ) , <EOL> "<STR_LIT>" : unixtimestamp ( record . standard_information ( ) . modified_time ( ) ) , <EOL> "<STR_LIT>" : size , <EOL> "<STR_LIT>" : uid , <EOL> "<STR_LIT>" : gid , <EOL> "<STR_LIT>" : mode , <EOL> "<STR_LIT>" : nlink , <EOL> } <EOL> @ log <EOL> def readdir ( self , path , fh ) : <EOL> dirents = [ '<STR_LIT:.>' , '<STR_LIT:..>' ] <EOL> record = self . _get_node ( path ) <EOL> dirents . extend ( map ( lambda r : r . get_filename ( ) , record . get_children_nodes ( ) ) ) <EOL> for r in dirents : <EOL> yield r <EOL> @ log <EOL> def readlink ( self , path ) : <EOL> return path <EOL> @ log <EOL> def statfs ( self , path ) : <EOL> return dict ( ( key , <NUM_LIT:0> ) for key in ( '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' ) ) <EOL> @ log <EOL> def chmod ( self , path , mode ) : <EOL> return errno . EROFS <EOL> @ log <EOL> def chown ( self , path , uid , gid ) : <EOL> return errno . EROFS <EOL> @ log <EOL> def mknod ( self , path , mode , dev ) : <EOL> return errno . EROFS <EOL> @ log <EOL> def rmdir ( self , path ) : <EOL> return errno . EROFS <EOL> @ log <EOL> def mkdir ( self , path , mode ) : <EOL> return errno . EROFS <EOL> @ log <EOL> def unlink ( self , path ) : <EOL> return errno . EROFS <EOL> @ log <EOL> def symlink ( self , target , name ) : <EOL> return errno . EROFS <EOL> @ log <EOL> def rename ( self , old , new ) : <EOL> return errno . EROFS <EOL> @ log <EOL> def link ( self , target , name ) : <EOL> return errno . EROFS <EOL> @ log <EOL> def utimens ( self , path , times = None ) : <EOL> return errno . EROFS <EOL> def _get_available_fh ( self ) : <EOL> """<STR_LIT>""" <EOL> for i in xrange ( <NUM_LIT> ) : <EOL> if i not in self . _opened_files : <EOL> return i <EOL> @ log <EOL> def open ( self , path , flags ) : <EOL> if flags & os . O_WRONLY > <NUM_LIT:0> : <EOL> return errno . EROFS <EOL> if flags & os . O_RDWR > <NUM_LIT:0> : <EOL> return errno . EROFS <EOL> fh = self . _get_available_fh ( ) <EOL> if is_special_file ( path ) : <EOL> ( path , special ) = explode_special_file ( path ) <EOL> if special == "<STR_LIT>" : <EOL> record = self . _get_record ( path ) <EOL> node = self . _get_node ( path ) <EOL> record_buf = self . _enumerator . get_record_buf ( node . get_record_number ( ) ) <EOL> self . _opened_files [ fh ] = MetaFH ( fh , record , path , record_buf ) <EOL> else : <EOL> raise FuseOSError ( errno . ENOENT ) <EOL> else : <EOL> self . _opened_files [ fh ] = RegularFH ( fh , self . _get_record ( path ) ) <EOL> return fh <EOL> @ log <EOL> def read ( self , path , length , offset , fh ) : <EOL> txt = self . _opened_files [ fh ] . get_data ( ) . encode ( "<STR_LIT:utf-8>" ) <EOL> return txt [ offset : offset + length ] <EOL> @ log <EOL> def flush ( self , path , fh ) : <EOL> return "<STR_LIT>" <EOL> @ log <EOL> def release ( self , path , fh ) : <EOL> del self . _opened_files [ fh ] <EOL> @ log <EOL> def create ( self , path , mode , fi = None ) : <EOL> return errno . EROFS <EOL> @ log <EOL> def write ( self , path , buf , offset , fh ) : <EOL> return errno . EROFS <EOL> @ log <EOL> def truncate ( self , path , length , fh = None ) : <EOL> return errno . EROFS <EOL> @ log <EOL> def fsync ( self , path , fdatasync , fh ) : <EOL> return errno . EPERM <EOL> def main ( mft_filename , mountpoint ) : <EOL> with Mmap ( mft_filename ) as buf : <EOL> tree = MFTTree ( buf ) <EOL> tree . build ( progress_class = ProgressBarProgress ) <EOL> handler = MFTFuseOperations ( mountpoint , tree , buf ) <EOL> FUSE ( handler , mountpoint , foreground = True ) <EOL> if __name__ == '<STR_LIT:__main__>' : <EOL> main ( sys . argv [ <NUM_LIT:1> ] , sys . argv [ <NUM_LIT:2> ] ) </s>
