<s> import socket <EOL> import sys <EOL> import os <EOL> import pwd <EOL> import grp <EOL> import fuse <EOL> import stat <EOL> import errno <EOL> import time <EOL> import threading <EOL> import py9p <EOL> import traceback <EOL> MIN_TFID = <NUM_LIT:64> <EOL> MAX_TFID = <NUM_LIT> <EOL> MIN_FID = <NUM_LIT> <EOL> MAX_FID = <NUM_LIT> <EOL> MAX_RECONNECT_INTERVAL = <NUM_LIT> <EOL> IOUNIT = <NUM_LIT> * <NUM_LIT:16> <EOL> FAIL_TRIES = <NUM_LIT:2> <EOL> FAIL_TIMEOUT = <NUM_LIT:0.5> <EOL> uid_map = { } <EOL> gid_map = { } <EOL> rpccodes = { <EOL> py9p . Eunknownfid : - errno . EBADFD , <EOL> py9p . Edupfid : - errno . EBADFD , <EOL> py9p . Ebaddir : - errno . EBADFD , <EOL> py9p . Enocreate : - errno . EPERM , <EOL> py9p . Enoremove : - errno . EPERM , <EOL> py9p . Enostat : - errno . EPERM , <EOL> py9p . Enowstat : - errno . EPERM , <EOL> py9p . Eperm : - errno . EPERM , <EOL> py9p . Enotfound : - errno . ENOENT , <EOL> py9p . Eisdir : - errno . EISDIR , <EOL> py9p . Ewalknotdir : - errno . ENOTDIR , <EOL> py9p . Ecreatenondir : - errno . ENOTDIR } <EOL> class Error ( py9p . Error ) : <EOL> pass <EOL> class NoFidError ( Exception ) : <EOL> pass <EOL> fuse . fuse_python_api = ( <NUM_LIT:0> , <NUM_LIT:2> ) <EOL> class fStat ( fuse . Stat ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , inode ) : <EOL> self . st_mode = py9p . mode2stat ( inode . mode ) <EOL> self . st_ino = <NUM_LIT:0> <EOL> self . st_dev = <NUM_LIT:0> <EOL> if inode . mode & stat . S_IFDIR : <EOL> self . st_nlink = inode . length <EOL> else : <EOL> self . st_nlink = <NUM_LIT:1> <EOL> self . st_uid = int ( uid_map . get ( inode . uidnum , inode . uidnum ) ) <EOL> self . st_gid = int ( gid_map . get ( inode . gidnum , inode . gidnum ) ) <EOL> self . st_size = inode . length <EOL> self . st_atime = inode . atime <EOL> self . st_mtime = inode . mtime <EOL> self . st_ctime = inode . mtime <EOL> class fakeRoot ( fuse . Stat ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . st_mode = stat . S_IFDIR | <NUM_LIT> <EOL> self . st_ino = <NUM_LIT:0> <EOL> self . st_dev = <NUM_LIT:0> <EOL> self . st_nlink = <NUM_LIT:3> <EOL> self . st_uid = <NUM_LIT:0> <EOL> self . st_gid = <NUM_LIT:0> <EOL> self . st_size = <NUM_LIT:3> <EOL> self . st_atime = self . st_mtime = self . st_ctime = time . time ( ) <EOL> def guard ( c ) : <EOL> """<STR_LIT>""" <EOL> def wrapped ( self , * argv , ** kwarg ) : <EOL> ret = - errno . EIO <EOL> for i in range ( FAIL_TRIES ) : <EOL> try : <EOL> tfid = self . tfidcache . acquire ( ) <EOL> with self . _rlock : <EOL> ret = c ( self , tfid . fid , * argv , ** kwarg ) <EOL> self . tfidcache . release ( tfid ) <EOL> break <EOL> except NoFidError : <EOL> ret = - errno . EMFILE <EOL> break <EOL> except py9p . RpcError as e : <EOL> ret = rpccodes . get ( e . message . lower ( ) , - errno . EIO ) <EOL> break <EOL> except : <EOL> if self . debug : <EOL> traceback . print_exc ( ) <EOL> if self . keep_reconnect : <EOL> self . _reconnect ( ) <EOL> time . sleep ( FAIL_TIMEOUT ) <EOL> else : <EOL> sys . exit ( <NUM_LIT:255> ) <EOL> return ret <EOL> return wrapped <EOL> class FidCache ( dict ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , start = MIN_FID , limit = MAX_FID ) : <EOL> """<STR_LIT>""" <EOL> dict . __init__ ( self ) <EOL> self . start = start <EOL> self . limit = limit <EOL> self . iounit = IOUNIT <EOL> self . fids = list ( range ( self . start , self . limit + <NUM_LIT:1> ) ) <EOL> def acquire ( self ) : <EOL> """<STR_LIT>""" <EOL> if len ( self . fids ) < <NUM_LIT:1> : <EOL> raise NoFidError ( ) <EOL> return Fid ( self . fids . pop ( <NUM_LIT:0> ) , self . iounit ) <EOL> def release ( self , f ) : <EOL> """<STR_LIT>""" <EOL> self . fids . append ( f . fid ) <EOL> class Fid ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , fid , iounit = IOUNIT ) : <EOL> self . fid = fid <EOL> self . iounit = iounit <EOL> class ClientFS ( fuse . Fuse ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , address , credentials , mountpoint , <EOL> debug = False , timeout = <NUM_LIT:10> , keep_reconnect = False ) : <EOL> """<STR_LIT>""" <EOL> self . address = address <EOL> self . credentials = credentials <EOL> self . debug = debug <EOL> self . timeout = timeout <EOL> self . msize = IOUNIT <EOL> self . sock = None <EOL> self . exit = None <EOL> self . dotu = <NUM_LIT:1> <EOL> self . keep_reconnect = keep_reconnect <EOL> self . _lock = threading . Lock ( ) <EOL> self . _rlock = threading . RLock ( ) <EOL> self . _interval = <NUM_LIT:1> <EOL> self . _reconnect_event = threading . Event ( ) <EOL> self . _connected_event = threading . Event ( ) <EOL> self . fidcache = FidCache ( ) <EOL> self . _reconnect ( init = True ) <EOL> self . dircache = { } <EOL> self . tfidcache = FidCache ( start = MIN_TFID , limit = MAX_TFID ) <EOL> fuse . Fuse . __init__ ( self , version = "<STR_LIT>" + fuse . __version__ , <EOL> dash_s_do = '<STR_LIT>' ) <EOL> if debug : <EOL> self . fuse_args . setmod ( '<STR_LIT>' ) <EOL> self . fuse_args . add ( '<STR_LIT>' ) <EOL> self . fuse_args . add ( '<STR_LIT>' ) <EOL> self . fuse_args . add ( '<STR_LIT>' ) <EOL> self . fuse_args . mountpoint = os . path . realpath ( mountpoint ) <EOL> def fsinit ( self ) : <EOL> try : <EOL> from Crypto import Random <EOL> Random . atfork ( ) <EOL> except : <EOL> pass <EOL> def _reconnect ( self , init = False , dotu = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> if self . _lock . acquire ( False ) : <EOL> self . _connected_event . clear ( ) <EOL> t = threading . Thread ( <EOL> target = self . _reconnect_target , <EOL> args = ( init , dotu ) ) <EOL> t . setDaemon ( True ) <EOL> t . start ( ) <EOL> if init : <EOL> t . join ( ) <EOL> else : <EOL> self . _connected_event . wait ( self . timeout + <NUM_LIT:2> ) <EOL> if self . exit : <EOL> print ( str ( self . exit ) ) <EOL> sys . exit ( <NUM_LIT:255> ) <EOL> def _reconnect_interval ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _interval = min ( self . _interval * <NUM_LIT:2> , MAX_RECONNECT_INTERVAL ) <EOL> return self . _interval <EOL> def _reconnect_target ( self , init = False , dotu = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> while True : <EOL> try : <EOL> self . sock . close ( ) <EOL> except : <EOL> pass <EOL> try : <EOL> if self . debug : <EOL> print ( "<STR_LIT>" ) <EOL> if self . address [ <NUM_LIT:0> ] . find ( "<STR_LIT:/>" ) > - <NUM_LIT:1> : <EOL> self . sock = socket . socket ( socket . AF_UNIX ) <EOL> else : <EOL> self . sock = socket . socket ( socket . AF_INET ) <EOL> self . sock . settimeout ( self . timeout ) <EOL> self . sock . connect ( self . address ) <EOL> self . client = py9p . Client ( <EOL> fd = self . sock , <EOL> chatty = self . debug , <EOL> credentials = self . credentials , <EOL> dotu = dotu , msize = self . msize ) <EOL> self . msize = self . client . msize <EOL> self . fidcache . iounit = self . client . msize - py9p . IOHDRSZ <EOL> self . _connected_event . set ( ) <EOL> self . _lock . release ( ) <EOL> return <EOL> except py9p . VersionError : <EOL> if dotu : <EOL> self . dotu = <NUM_LIT:0> <EOL> self . _reconnect_target ( init , <NUM_LIT:0> ) <EOL> else : <EOL> self . exit = Exception ( "<STR_LIT>" ) <EOL> return <EOL> except Exception as e : <EOL> if self . keep_reconnect : <EOL> if init : <EOL> self . _lock . release ( ) <EOL> self . _connected_event . set ( ) <EOL> return <EOL> s = self . _reconnect_interval ( ) <EOL> if self . debug : <EOL> print ( "<STR_LIT>" % ( s ) ) <EOL> self . _reconnect_event . wait ( s ) <EOL> self . _reconnect_event . clear ( ) <EOL> else : <EOL> self . exit = e <EOL> self . _lock . release ( ) <EOL> self . _connected_event . set ( ) <EOL> return <EOL> @ guard <EOL> def open ( self , tfid , path , mode ) : <EOL> f = self . fidcache . acquire ( ) <EOL> try : <EOL> self . client . _walk ( self . client . ROOT , <EOL> f . fid , filter ( None , path . split ( "<STR_LIT:/>" ) ) ) <EOL> fcall = self . client . _open ( f . fid , py9p . open2plan ( mode ) ) <EOL> f . iounit = fcall . iounit <EOL> return f <EOL> except Exception as e : <EOL> self . fidcache . release ( f ) <EOL> raise e <EOL> @ guard <EOL> def _wstat ( self , tfid , path , <EOL> uid = py9p . ERRUNDEF , <EOL> gid = py9p . ERRUNDEF , <EOL> mode = py9p . ERRUNDEF , <EOL> newname = None ) : <EOL> self . client . _walk ( self . client . ROOT , <EOL> tfid , filter ( None , path . split ( "<STR_LIT:/>" ) ) ) <EOL> if self . dotu : <EOL> stats = [ py9p . Dir ( <EOL> dotu = <NUM_LIT:1> , <EOL> type = <NUM_LIT:0> , <EOL> dev = <NUM_LIT:0> , <EOL> qid = py9p . Qid ( <NUM_LIT:0> , <NUM_LIT:0> , py9p . hash8 ( path ) ) , <EOL> mode = mode , <EOL> atime = int ( time . time ( ) ) , <EOL> mtime = int ( time . time ( ) ) , <EOL> length = py9p . ERRUNDEF , <EOL> name = newname or path . split ( "<STR_LIT:/>" ) [ - <NUM_LIT:1> ] , <EOL> uid = "<STR_LIT>" , <EOL> gid = "<STR_LIT>" , <EOL> muid = "<STR_LIT>" , <EOL> extension = "<STR_LIT>" , <EOL> uidnum = uid , <EOL> gidnum = gid , <EOL> muidnum = py9p . ERRUNDEF ) , ] <EOL> else : <EOL> stats = [ py9p . Dir ( <EOL> dotu = <NUM_LIT:0> , <EOL> type = <NUM_LIT:0> , <EOL> dev = <NUM_LIT:0> , <EOL> qid = py9p . Qid ( <NUM_LIT:0> , <NUM_LIT:0> , py9p . hash8 ( path ) ) , <EOL> mode = mode , <EOL> atime = int ( time . time ( ) ) , <EOL> mtime = int ( time . time ( ) ) , <EOL> length = py9p . ERRUNDEF , <EOL> name = newname or path . split ( "<STR_LIT:/>" ) [ - <NUM_LIT:1> ] , <EOL> uid = pwd . getpwuid ( uid ) . pw_name , <EOL> gid = grp . getgrgid ( gid ) . gr_name , <EOL> muid = "<STR_LIT>" ) , ] <EOL> self . client . _wstat ( tfid , stats ) <EOL> self . client . _clunk ( tfid ) <EOL> def chmod ( self , path , mode ) : <EOL> return self . _wstat ( path , mode = py9p . mode2plan ( mode ) ) <EOL> def chown ( self , path , uid , gid ) : <EOL> return self . _wstat ( path , uid , gid ) <EOL> def utime ( self , path , times ) : <EOL> pass <EOL> @ guard <EOL> def unlink ( self , tfid , path ) : <EOL> self . client . _walk ( self . client . ROOT , <EOL> tfid , filter ( None , path . split ( "<STR_LIT:/>" ) ) ) <EOL> self . client . _remove ( tfid ) <EOL> self . dircache = { } <EOL> def rmdir ( self , path ) : <EOL> self . unlink ( path ) <EOL> @ guard <EOL> def symlink ( self , tfid , target , path ) : <EOL> if not self . dotu : <EOL> return - errno . ENOSYS <EOL> self . client . _walk ( self . client . ROOT , tfid , <EOL> filter ( None , path . split ( "<STR_LIT:/>" ) ) [ : - <NUM_LIT:1> ] ) <EOL> self . client . _create ( tfid , filter ( None , path . split ( "<STR_LIT:/>" ) ) [ - <NUM_LIT:1> ] , <EOL> py9p . DMSYMLINK , <NUM_LIT:0> , target ) <EOL> self . client . _clunk ( tfid ) <EOL> @ guard <EOL> def mknod ( self , tfid , path , mode , dev ) : <EOL> if dev != <NUM_LIT:0> : <EOL> return - errno . ENOSYS <EOL> if not mode & stat . S_IFREG : <EOL> mode |= stat . S_IFDIR <EOL> try : <EOL> self . client . _walk ( self . client . ROOT , <EOL> tfid , filter ( None , path . split ( "<STR_LIT:/>" ) ) ) <EOL> self . client . _open ( tfid , py9p . OTRUNC ) <EOL> self . client . _clunk ( tfid ) <EOL> except py9p . RpcError as e : <EOL> if e . message == "<STR_LIT>" : <EOL> self . client . _walk ( self . client . ROOT , <EOL> tfid , filter ( None , path . split ( "<STR_LIT:/>" ) ) [ : - <NUM_LIT:1> ] ) <EOL> self . client . _create ( tfid , <EOL> filter ( None , path . split ( "<STR_LIT:/>" ) ) [ - <NUM_LIT:1> ] , <EOL> py9p . mode2plan ( mode ) , <NUM_LIT:0> ) <EOL> self . client . _clunk ( tfid ) <EOL> else : <EOL> return - errno . EIO <EOL> def mkdir ( self , path , mode ) : <EOL> return self . mknod ( path , mode | stat . S_IFDIR , <NUM_LIT:0> ) <EOL> @ guard <EOL> def truncate ( self , tfid , path , size ) : <EOL> if size != <NUM_LIT:0> : <EOL> return - errno . ENOSYS <EOL> self . client . _walk ( self . client . ROOT , <EOL> tfid , filter ( None , path . split ( "<STR_LIT:/>" ) ) ) <EOL> self . client . _open ( tfid , py9p . OTRUNC ) <EOL> self . client . _clunk ( tfid ) <EOL> @ guard <EOL> def write ( self , tfid , path , buf , offset , f ) : <EOL> if py9p . hash8 ( path ) in self . dircache : <EOL> del self . dircache [ py9p . hash8 ( path ) ] <EOL> size = len ( buf ) <EOL> for i in range ( ( size + f . iounit - <NUM_LIT:1> ) / f . iounit ) : <EOL> start = i * f . iounit <EOL> length = start + f . iounit <EOL> self . client . _write ( f . fid , offset + start , <EOL> buf [ start : length ] ) <EOL> return size <EOL> @ guard <EOL> def read ( self , tfid , path , size , offset , f ) : <EOL> data = bytes ( ) <EOL> i = <NUM_LIT:0> <EOL> while True : <EOL> ret = self . client . _read ( f . fid , offset , <EOL> min ( size - len ( data ) , f . iounit ) ) <EOL> data += ret . data <EOL> offset += len ( ret . data ) <EOL> if size <= len ( data ) or len ( ret . data ) == <NUM_LIT:0> : <EOL> break <EOL> i += <NUM_LIT:1> <EOL> return data [ : size ] <EOL> @ guard <EOL> def rename ( self , tfid , path , dest ) : <EOL> for i in ( path , dest ) : <EOL> if py9p . hash8 ( i ) in self . dircache : <EOL> del self . dircache [ py9p . hash8 ( i ) ] <EOL> if path . split ( "<STR_LIT:/>" ) [ : - <NUM_LIT:1> ] == dest . split ( "<STR_LIT:/>" ) [ : - <NUM_LIT:1> ] : <EOL> return self . _wstat ( path , newname = dest . split ( "<STR_LIT:/>" ) [ - <NUM_LIT:1> ] ) <EOL> source = self . _getattr ( path ) <EOL> destination = self . _getattr ( dest ) <EOL> if - errno . EIO in ( source , destination ) : <EOL> return - errno . EIO <EOL> if destination == - errno . ENOENT : <EOL> self . mknod ( dest , source . st_mode , <NUM_LIT:0> ) <EOL> if source . st_mode & stat . S_IFDIR : <EOL> for i in self . _readdir ( path , <NUM_LIT:0> ) : <EOL> self . rename ( <EOL> "<STR_LIT:/>" . join ( ( path , i . name ) ) , <EOL> "<STR_LIT:/>" . join ( ( dest , i . name ) ) ) <EOL> else : <EOL> sf = self . open ( path , os . O_RDONLY ) <EOL> df = self . open ( dest , os . O_WRONLY | os . O_TRUNC ) <EOL> for i in range ( ( source . st_size + self . msize - <NUM_LIT:1> ) / self . msize ) : <EOL> block = self . read ( path , self . msize , i * self . msize , sf ) <EOL> self . write ( dest , block , i * self . msize , df ) <EOL> self . release ( path , <NUM_LIT:0> , sf ) <EOL> self . release ( dest , <NUM_LIT:0> , df ) <EOL> self . unlink ( path ) <EOL> @ guard <EOL> def release ( self , tfid , path , flags , f ) : <EOL> try : <EOL> self . client . _clunk ( f . fid ) <EOL> self . fidcache . release ( f ) <EOL> except : <EOL> pass <EOL> @ guard <EOL> def readlink ( self , tfid , path ) : <EOL> if py9p . hash8 ( path ) in self . dircache : <EOL> return self . dircache [ py9p . hash8 ( path ) ] . extension <EOL> self . client . _walk ( self . client . ROOT , <EOL> tfid , filter ( None , path . split ( "<STR_LIT:/>" ) ) ) <EOL> self . client . _open ( tfid , py9p . OREAD ) <EOL> ret = self . client . _read ( tfid , <NUM_LIT:0> , self . msize ) <EOL> self . client . _clunk ( tfid ) <EOL> return ret . data <EOL> @ guard <EOL> def _getattr ( self , tfid , path ) : <EOL> if py9p . hash8 ( path ) in self . dircache : <EOL> return fStat ( self . dircache [ py9p . hash8 ( path ) ] ) <EOL> self . client . _walk ( self . client . ROOT , <EOL> tfid , filter ( None , path . split ( "<STR_LIT:/>" ) ) ) <EOL> ret = self . client . _stat ( tfid ) . stat [ <NUM_LIT:0> ] <EOL> s = fStat ( ret ) <EOL> self . client . _clunk ( tfid ) <EOL> self . dircache [ py9p . hash8 ( path ) ] = ret <EOL> return s <EOL> def getattr ( self , path ) : <EOL> self . _interval = <NUM_LIT:1> <EOL> self . _reconnect_event . set ( ) <EOL> s = self . _getattr ( path ) <EOL> if s == - errno . EIO : <EOL> if self . keep_reconnect : <EOL> if path == "<STR_LIT:/>" : <EOL> return fakeRoot ( ) <EOL> else : <EOL> return - errno . ENOENT <EOL> return s <EOL> @ guard <EOL> def _readdir ( self , tfid , path , offset ) : <EOL> dirs = [ ] <EOL> self . client . _walk ( self . client . ROOT , <EOL> tfid , filter ( None , path . split ( "<STR_LIT:/>" ) ) ) <EOL> self . client . _open ( tfid , py9p . OREAD ) <EOL> offset = <NUM_LIT:0> <EOL> while True : <EOL> ret = self . client . _read ( tfid , offset , self . msize ) <EOL> if len ( ret . data ) == <NUM_LIT:0> : <EOL> break <EOL> offset += len ( ret . data ) <EOL> p9 = py9p . Marshal9P ( dotu = self . dotu ) <EOL> p9 . setBuffer ( ret . data ) <EOL> p9 . buf . seek ( <NUM_LIT:0> ) <EOL> fcall = py9p . Fcall ( py9p . Rstat ) <EOL> p9 . decstat ( fcall . stat , <NUM_LIT:0> ) <EOL> dirs . extend ( fcall . stat ) <EOL> self . client . _clunk ( tfid ) <EOL> return dirs <EOL> def readdir ( self , path , offset ) : <EOL> self . _interval = <NUM_LIT:1> <EOL> self . _reconnect_event . set ( ) <EOL> dirs = self . _readdir ( path , offset ) <EOL> if not isinstance ( dirs , list ) : <EOL> dirs = [ ] <EOL> if path == "<STR_LIT:/>" : <EOL> path = "<STR_LIT>" <EOL> for i in dirs : <EOL> self . dircache [ py9p . hash8 ( "<STR_LIT:/>" . join ( ( path , i . name ) ) ) ] = i <EOL> yield fuse . Direntry ( i . name ) </s>
