def __init__(self, *args, **kw): Fuse.__init__(self, *args, **kw) self.root = '/' self.state = StateUtils();
class InferatoFS(Fuse):#TODO: refactor this #Fuse has no information about the usage of these files. forbidden = ["autorun.inf", ".Trash", ".Trash-1000", "BDMV", ".xdg-volume-info", ".directory", ".krcdirs", ".kateconfig"] #True - disable VF + sequence deleting functionality for this flag hide_vfs = False def __init__(self, *args, **kw): Fuse.__init__(self, *args, **kw) self.root = '/' self.state = StateUtils(); #uncomment this to see what operation are supported #print Fuse._attrs def getattr(self, path): if os.path.split(path)[1] in self.forbidden: #ignore this stuff #TODO: find the right way of usage pass else: #capture the case, when user follows the symbolic link. if Parser(path).isMetaLink(): st = MyStat() st.st_mode = stat.S_IFDIR | 0777 st.st_nlink = 5 return st elif not self.hide_vfs: if Parser(path).isLenghFile(): st = MyStat() st.st_mode = stat.S_IFREG st.st_nlink = 1 st.st_size = len(str(len(PathUtils(path).getName()))) return st elif str(path).endswith(FSTemplates.file_type): st = MyStat() st.st_mode = stat.S_IFREG st.st_nlink = 1 st.st_size = 0 return st elif str(path).endswith(FSTemplates.email_message): st = MyStat() st.st_mode = stat.S_IFREG st.st_nlink = 1 st.st_size = 0 return st else: return os.lstat("." + path) return os.lstat("." + path) def readlink(self, path): return os.readlink("." + path) def writeInferatoFSEmail(self, emailMessage): emailMessage.storagePath = emailMessage.storagePath + TransformerTemplate.forwardSlash #Create Message ID File if emailMessage.emailHeader._messageID != None: fileHandler = open(emailMessage.storagePath + TransformerTemplate._messageID, TransformerTemplate.fileWrite) fileHandler.write(emailMessage.emailHeader._messageID) fileHandler.close() #Create From File fileHandler = open(emailMessage.storagePath + TransformerTemplate._from, TransformerTemplate.fileWrite) if(emailMessage.emailHeader._from.fullName != emailMessage.emailHeader._from.emailAddress): fileHandler.write(emailMessage.emailHeader._from.fullName + TransformerTemplate.newLine) fileHandler.write(emailMessage.emailHeader._from.emailAddress) fileHandler.close() #Create Sender File if (emailMessage.emailHeader._sender != None and emailMessage.emailHeader._sender.fullName != TransformerTemplate.emptyString and emailMessage.emailHeader._sender.emailAddress != TransformerTemplate.emptyString): fileHandler = open(emailMessage.storagePath + TransformerTemplate._sender, TransformerTemplate.fileWrite) if(emailMessage.emailHeader._sender.fullName != emailMessage.emailHeader._sender.emailAddress): fileHandler.write(emailMessage.emailHeader._sender.fullName + TransformerTemplate.newLine) fileHandler.write(emailMessage.emailHeader._sender.emailAddress) fileHandler.close() #Create Subject File if emailMessage.emailHeader._subject != None: fileHandler = open(emailMessage.storagePath + TransformerTemplate._subject, TransformerTemplate.fileWrite) fileHandler.write(emailMessage.emailHeader._subject) fileHandler.close() #Create Date File if emailMessage.emailHeader._dateTime != None: fileHandler = open(emailMessage.storagePath + TransformerTemplate._date, TransformerTemplate.fileWrite) fileHandler.write(emailMessage.emailHeader._dateTime) fileHandler.close() #Create Header File if emailMessage.actualFileName != None: headerFileName = TransformerTemplate.header + emailMessage.actualFileName #print "Header Path: " + emailMessage.storagePath + headerFileName fileHandler = open(emailMessage.storagePath + headerFileName, TransformerTemplate.fileWrite) fileHandler.write(emailMessage.entireHeader) fileHandler.close() #Create Body File if emailMessage.emailBody != None: fileHandler = open(emailMessage.storagePath + TransformerTemplate.body + emailMessage.emailBody._extension, TransformerTemplate.fileWrite) fileHandler.write(emailMessage.emailBody._body) fileHandler.close() #Create To Folder and Store Contacts if len(emailMessage.emailHeader._to) != 0: if not os.path.exists(emailMessage.storagePath + TransformerTemplate._to): os.mkdir(emailMessage.storagePath + TransformerTemplate._to) toPath = emailMessage.storagePath + TransformerTemplate._to + TransformerTemplate.forwardSlash for toContact in emailMessage.emailHeader._to: fileHandler = open(toPath + toContact.fullName, TransformerTemplate.fileWrite) if(toContact.fullName != toContact.emailAddress): fileHandler.write(toContact.fullName + TransformerTemplate.newLine) fileHandler.write(toContact.emailAddress) fileHandler.close() #Create Cc Folder and Store Contacts if len(emailMessage.emailHeader._cc) != 0: if not os.path.exists(emailMessage.storagePath + TransformerTemplate._cc): os.mkdir(emailMessage.storagePath + TransformerTemplate._cc) ccPath = emailMessage.storagePath + TransformerTemplate._cc + TransformerTemplate.forwardSlash for ccContact in emailMessage.emailHeader._cc: fileHandler = open(ccPath + ccContact.fullName, TransformerTemplate.fileWrite) if(ccContact.fullName != ccContact.emailAddress): fileHandler.write(ccContact.fullName + TransformerTemplate.newLine) fileHandler.write(ccContact.emailAddress) fileHandler.close() #Create Bcc Folder and Store Contacts if len(emailMessage.emailHeader._bcc) != 0: if not os.path.exists(emailMessage.storagePath + TransformerTemplate._bcc): os.mkdir(emailMessage.storagePath + TransformerTemplate._bcc) bccPath = emailMessage.storagePath + TransformerTemplate._bcc + TransformerTemplate.forwardSlash for bccContact in emailMessage.emailHeader._bcc: fileHandler = open(bccPath + bccContact.fullName, TransformerTemplate.fileWrite) if(bccContact.fullName != bccContact.emailAddress): fileHandler.write(bccContact.fullName + TransformerTemplate.newLine) fileHandler.write(bccContact.emailAddress) fileHandler.close() #Create Attachments Folder and Store Attachments if len(emailMessage.emailBody._attachments) != 0: if not os.path.exists(emailMessage.storagePath + TransformerTemplate.attachments): os.mkdir(emailMessage.storagePath + TransformerTemplate.attachments) if True: #self.duplicate != TransformerTemplate.attachmentsOnly: attachmentsPath = emailMessage.storagePath + TransformerTemplate.attachments + TransformerTemplate.forwardSlash for attachment in emailMessage.emailBody._attachments: fileHandler = open(attachmentsPath + attachment.attachmentName, TransformerTemplate.fileWrite) fileHandler.write(attachment.attachedFile) fileHandler.close() del fileHandler return def readdir(self, path, offset): global transform, transformer, duplicatePaths emailMessage = EmailMessage() yield fuse.Direntry(".") yield fuse.Direntry("..") if Parser(path).isMetaFolder(): if not self.hide_vfs: # wanted to change the passed argument from 'file_len' to 'file_type #print "(1) " + path yield fuse.Direntry(FSTemplates.file_len) yield fuse.Direntry(FSTemplates.file_type) folder = path[str(path).rfind(os.sep):] if str(folder).find("From:") != -1 and str(folder).find("To:") != -1: yield fuse.Direntry(FSTemplates.email_message) if os.path.exists("." + path): for e in os.listdir("." + path): if transform: #Check file type for email files fileType = determineFileType(self, "." + path + TransformerTemplate.forwardSlash + e) #Process email file if found if emailMessage and emailMessage.actualFileName and e.__eq__(emailMessage.actualFileName + FSTemplates._suffix): pass elif str(fileType).endswith(TransformerTemplate.email_message): if str.find(e, TransformerTemplate.header) == -1: transformer.workingPath = self.root + path + TransformerTemplate.forwardSlash + e transformer.outputPath = emailMessage.pathToParent = "." + path + TransformerTemplate.forwardSlash #Read Input Email File emailMessage.readEmailMessage(transformer) #Prepare Output Folder Name and Duplicity Count emailMessage.prepareFolderName() messageList = emailMessage.hashEmailMessage(transformer) emailNumber = emailMessage.occurenceNumber if emailNumber != 0: emailMessage.folderName += "[%(emailNumber)s]" % locals() #Storage Path ~ Parent Folder for InferatoFS Email emailMessage.storagePath = transformer.outputPath + emailMessage.folderName #Determine Nature of Duplication if emailMessage.occurenceNumber != 1: emailMessage.determineDuplicate(messageList, transformer) #print emailMessage.duplicate + " - " + duplicate if (os.path.exists(transformer.outputPath) and not os.path.exists(emailMessage.storagePath) and str(transformer.outputPath).find(emailMessage.folderName) == -1 ):#and emailMessage.duplicate != TransformerTemplate.absolute): #yield fuse.Direntry(emailMessage.folderName) if emailMessage.duplicate != TransformerTemplate.absolute: #print "Duplicate not found!" os.mkdir(emailMessage.storagePath) self.writeInferatoFSEmail(emailMessage) else: #os.mkdir(emailMessage.storagePath) self.symlink(os.path.realpath(emailMessage.duplicatePath), transformer.outputPath[1:] + emailMessage.folderName) if emailMessage.duplicate != None and emailMessage.duplicate == TransformerTemplate.absolute: #os.link(emailMessage.duplicatePath, emailMessage.storagePath) #os.mkdir(emailMessage.storagePath[:-1] + FSTemplates._suffix) #You can't create a link on Mount's #. For renaming store the duplicate's path in global #and call rename after the # folder has been read and corresponding link on actual has been #created #print "Key: " + emailMessage.folderName[:-3] if emailMessage.folderName[:-3] not in duplicatePaths: duplicatePaths[emailMessage.folderName[:-3]] = emailMessage.duplicatePath else: #For writing Header Files yield fuse.Direntry(e) elif not os.path.islink(e): yield fuse.Direntry(e) #print "Movement allowed for " + e #if (str(e[-5:-4]).isdigit() and e[-6:-5] == TransformerTemplate.openingSquareBracket #and e[-4:-3] == TransformerTemplate.closingSquareBracket and e[-5:-4] != "1"): if re.search("\[[2-9]\]\[\#\]\Z", e) != None: hashedName = e[str.find(e, os.sep)+1:-6] #print "Hash Key: " + hashedName #print "Duplicate Path: " + duplicatePaths[hashedName] if hashedName in duplicatePaths: #print "Duplicate Path: " + duplicatePaths[hashedName] self.rename(e[:-3], duplicatePaths[hashedName][:-1] + FSTemplates._suffix + os.sep + e[:-3]) else: #print "(2) " + e yield fuse.Direntry(e) else: #print "\n(3) " + e yield fuse.Direntry(e) if re.search("\[[2-9]\]\[\#\]\Z", e) != None: ePath = self.root + path + TransformerTemplate.forwardSlash + e[:-3] #print "Full Path: " + ePath fileType = determineFileType(self, ePath) #print "File Type is " + str(fileType) if fileType != None and str.find(str.lower(fileType), "link") != -1: pointedPath = fileType[str.find(fileType, os.sep):-1] #print "Pointed Path is " + str(pointedPath[len(self.root):-1]) self.rename(e[:-3], "." + pointedPath[len(self.root):-1] + FSTemplates._suffix + os.sep + e[:-3]) #delete def unlink(self, path): if Parser(path).isMeta(): if Parser(path).isTagFolder(): untagInMeta(self, self.getabs(path)) return elif Parser(path).isLenghFile(): #do nothing since it is a virtual file return if self.state.cur_state[0] == 3: #allow deleting VF for action 3 return print "Can not unlink " + str(path) + ". It is a system file." return else: mode = os.lstat("." + path)[0] #self.hide_vfs=True also means that first usr call was rmdir #(folders could also contain meta-data links) if not self.hide_vfs: # if regular file, then delete meta-data before if (mode & stat.S_IFREG) and (mode < stat.S_IFLNK): metalink = os.path.realpath(self.root + path + FSTemplates._suffix) os.unlink("." + path + FSTemplates._suffix) shutil.rmtree(metalink) else: if Parser(path).isMeta() and (mode & stat.S_IFLNK) and (mode >= stat.S_IFLNK): metalink = os.path.realpath(self.root + path) shutil.rmtree(metalink) os.unlink("." + path) def rmdir(self, path): if Parser(path).isMeta(): tulpe = PathUtils(self.getabs(path)).isAloneLink() print tulpe if tulpe[0]: untagInMeta(self, tulpe[1]) return print " rmdir, this operation is restricted for path: " + path else: #disable temporary all virtual files self.hide_vfs = True metalink = os.path.realpath(self.root + path + FSTemplates._suffix) if os.path.exists("." + path + FSTemplates._suffix): os.unlink("." + path + FSTemplates._suffix) if os.path.exists(metalink): shutil.rmtree(metalink) os.rmdir("." + path) #enable vfiles self.hide_vfs = False def symlink(self, path, path1): #print "symlink - path: " + path #print "symlink - path1: " + path1 #print "Path Exists: " + str(os.path.exists(path)) #print "Path1 Exists: " + str(os.path.exists("." + path1)) if Parser(path).isMeta(): print "symlink: this operation is restricted for path: " + path else: os.symlink(path, "." + path1) def rename(self, path, path1): print "Path: " + path print "Path1: " + path1 #path to tag path_abs = self.getabs(path) #if not os.path.exists(path_abs): #pass #path of link in tags folder path1_abs = self.getabs(path1) # equals to "[suffix]/tags" suf = FSTemplates._suffix + os.sep + FSTemplates.folder_tags # get ../tags abs_path path1_abs_minus = os.path.split(path1_abs)[0] # eliminate FSTemplates._suffix and get origin if exists path1_abs_minus_orig = str(path1_abs_minus).split(FSTemplates._suffix)[0] #destination root s = os.path.split(path1_abs)[0] print "=====" #target and tag are equals if str(path_abs).__eq__(path1_abs_minus_orig): print "Can not tag itself!" return #expected sample input for path: [regular file/dir] and ...[FSTemplates._suffix]/[file/dir] where last one is metalink of directory if str(path1_abs_minus).endswith(FSTemplates._suffix) and not Parser(path_abs).isMeta() and os.path.isdir(path1_abs_minus_orig): print "tagging: multiple targets" self.state.initAction(1) self.state.next() tag(self, path_abs, path1_abs_minus_orig) self.state.finishAction() #expected sample input for path: ...[FSTemplates._suffix]/tags and [regular directory] elif os.path.isdir(path_abs): print "tagging: multiple tags" self.state.initAction(2) self.state.next() #already tagged with this name case if os.path.exists(str(path1_abs_minus + os.sep + os.path.split(path_abs)[1])): print str(path1_abs_minus + os.sep + os.path.split(path_abs)[1]) print "Can not tag " + path1_abs_minus_orig + " with " + path_abs + ". You already tagged it with this name. Please, untag it first and then repeat." if Parser(s).isTagFolder(): #candidate for tag can not be a special file/folder self.state.next() self.state if not Parser(path).isMeta(): obj_path = str(path1_abs).split(suf)[0] self.state.next() tag(self, obj_path, path_abs) self.state.finishAction() else: print "Restricted operation for tagging" else: print " forbidden operation for tagging: " + s + " is not a special folder as expected" #Still a Question: Should we actually allow the folder movement without considering various scenarios? print "Path-Suffix: ." + path + FSTemplates._suffix, "- ." + path1 + FSTemplates._suffix print "Just-Path: ." + path, "." + path1 os.rename("." + path + FSTemplates._suffix, "." + path1 + FSTemplates._suffix) os.rename("." + path, "." + path1) #fix the broken link if os.path.isdir(s): fixTaggedLink(self, s, path, path1) elif Parser(path).isMeta() or Parser(path1).isMeta(): print "rename: this operation is restricted for path " + path else: print "Here!" os.rename("." + path + FSTemplates._suffix, "." + path1 + FSTemplates._suffix) os.rename("." + path, "." + path1) if os.path.isdir(s): fixDeletedLink(self, s, path, path1) def link(self, path, path1): #print "link - path: " + path #print "link - path1: " + path1 os.link("." + path, "." + path1) def chmod(self, path, mode): if Parser(path).isMeta(): print "chmod: this operation is restricted for path " + path else: os.chmod("." + path, mode) def chown(self, path, user, group): os.chown("." + path, user, group) def truncate(self, path, len): f = open("." + path, "a") f.truncate(len) f.close() def mknod(self, path, mode, dev): #print "mknod - path: " + path os.mknod("." + path, mode, dev) def mkdir(self, path, mode): if Parser(path).isMeta(): print "mkdir: this operation is restricted for path " + path else: os.mkdir("." + path, mode) def utime(self, path, times): os.utime("." + path, times) def access(self, path, mode): #print "access - path: " + path if Parser(path).isMeta(): pass elif not os.access("." + path, mode): #TODO: do custom access controls return -EACCES pass if not Parser(path).isMeta(): checkMeta(self, path) #print "Done with checkMeta!" def statfs(self): """ Should return an object with statvfs attributes (f_bsize, f_frsize...). Eg., the return value of os.statvfs() is such a thing (since py 2.2). If you are not reusing an existing statvfs object, start with fuse.StatVFS(), and define the attributes. To provide usable information (ie., you want sensible df(1) output, you are suggested to specify the following attributes: - f_bsize - preferred size of file blocks, in bytes - f_frsize - fundamental size of file blcoks, in bytes [if you have no idea, use the same as blocksize] - f_blocks - total number of blocks in the filesystem - f_bfree - number of free blocks - f_files - total number of file inodes - f_ffree - number of free file inodes """ return os.statvfs(".") def fsinit(self): os.chdir(self.root) #TODO: make possible to resolve also relative path with data and mount folders if os.path.exists(FSTemplates._meta_storage): print " meta-storage found in '" + self.root + "'" else: print "creating meta-storage '" + self.root + "' ..." os.mkdir(FSTemplates._meta_storage) print "...done" #for local u #for local usage only def getabs(self, path): p = self.root + os.sep + path return os.path.normpath(p) class InferatoFile(object): """ Virtual File Manipulation TODO: Re-factor Class Name TODO: Relocate Class """ direct_io = 1 keep_cache = 0 def __init__(self, path, flags, *mode): self.path = path if Parser(path).isLenghFile(): #if cmp(path[str.rfind(path, '/')+1:len(path)], FSTemplates.file_len): self.file = tempfile.NamedTemporaryFile(mode='r+t') #File Name Length is being written to 'length' file here. self.file.writelines([str(len(PathUtils(path).getName()))]) self.fd = self.file.fileno() elif str(path).endswith(FSTemplates.file_type): self.file = tempfile.NamedTemporaryFile(mode='r+t') actualPath = determineActualDataPath(self, path) fileType = determineFileType(self, actualPath) self.file.write(str(fileType)) if fileType != None and str.find(str.lower(fileType), "link") != -1: pointedPath = fileType[str.find(fileType, os.sep):-1] #print "Link Target: " + pointedPath fileType = determineFileType(self, pointedPath) self.file.write("\nLink Target Type: ") self.file.write(str(fileType)) if(os.path.isdir(actualPath) and os.path.isdir(actualPath + os.sep + FSTemplates._to) and os.path.isfile(actualPath + os.sep + FSTemplates._from)): self.file.write("\n") self.file.write(FSTemplates.inferatoFS_email) self.fd = self.file.fileno() elif str(path).endswith(FSTemplates.email_message): self.file = tempfile.NamedTemporaryFile(mode='r+t') tail = -1 * (len(FSTemplates.email_message) + len(FSTemplates._suffix) + 1) contentPath = determineActualDataPath(self, path[:tail]) self.file.write(composeEmail(contentPath)) self.fd = self.file.fileno() else: self.file = os.fdopen(os.open("." + path, flags, *mode), flag2mode(flags)) #self.file = os.fdopen(os.open("." + path, flags, *mode), flag2mode(flags)) self.fd = self.file.fileno() def read(self, length, offset): self.file.seek(offset) return self.file.read(length) def write(self, buf, offset): self.file.write(buf) return len(buf) def release(self, flags): self.file.close() def _fflush(self): if 'w' in self.file.mode or 'a' in self.file.mode: self.file.flush() def fsync(self, isfsyncfile): self._fflush() if isfsyncfile and hasattr(os, 'fdatasync'): os.fdatasync(self.fd) else: os.fsync(self.fd) def flush(self): self._fflush() # cf. xmp_flush() in fusexmp_fh.c os.close(os.dup(self.fd)) def fgetattr(self): return os.fstat(self.fd) def ftruncate(self, len): self.file.truncate(len) def lock(self, cmd, owner, **kw): op = { fcntl.F_UNLCK : fcntl.LOCK_UN, fcntl.F_RDLCK : fcntl.LOCK_SH, fcntl.F_WRLCK : fcntl.LOCK_EX }[kw['l_type']] if cmd == fcntl.F_GETLK: return -EOPNOTSUPP elif cmd == fcntl.F_SETLK: if op != fcntl.LOCK_UN: op |= fcntl.LOCK_NB elif cmd == fcntl.F_SETLKW: pass else: return -EINVAL fcntl.lockf(self.fd, op, kw['l_start'], kw['l_len']) def main(self, *a, **kw): self.file_class = self.InferatoFile return Fuse.main(self, *a, **kw)