#!/usr/bin/env python3 # requires fusepy package import os import sys import errno import stat import time import subprocess from datetime import datetime from fuse import FUSE, FuseOSError, Operations class GlitterFS(Operations): def __init__(self): self.files = {} self.data = {} self.fd = 0 # file descriptor now = time.time() self.files['/'] = { 'st_mode': stat.S_IFDIR | 0o755, # dir and permissions in octal 'st_ctime': now, # creation time 'st_mtime': now, # modification time 'st_atime': now, # access time 'st_nlink': 2, # number of hard links, for dirs: . and .. 'st_size': 0 # size in bytes } def getattr(self, path, fh=None): if path not in self.files: raise FuseOSError(errno.ENOENT) return self.files[path] # generator - based def readdir(self, path, fh): yield '.' yield '..' if path == '/': path = '' # For easier concatenation for name in self.files: if name != '/' and name.startswith(path + '/') \ and '/' not in name[len(path) + 1:]: # only base files of directory yield name[len(path) + 1:] def mkdir(self, path, mode): now = time.time() self.files[path] = { 'st_mode': stat.S_IFDIR | mode, 'st_ctime': now, 'st_mtime': now, 'st_atime': now, 'st_nlink': 2, 'st_size': 0 } # Update parent's link count parent = os.path.dirname(path) self.files[parent]['st_nlink'] += 1 return 0 def open(self, path, flags): self.fd += 1 return self.fd def create(self, path, mode, fi=None): now = time.time() self.files[path] = { 'st_mode': stat.S_IFREG | mode, 'st_ctime': now, 'st_mtime': now, 'st_atime': now, 'st_nlink': 1, 'st_size': 37000, # will not call 'read' on size = 0 } self.fd += 1 # Load file Contents filename = os.path.basename(path) filename = filename.replace(" ", "%20") imgname = subprocess.run( "curl -L " + f"'https://www.gigaglitters.com/procesing.php?text={filename}' " + r"| sed -nE 's/.*.*/\1/p'", shell=True, capture_output=True).stdout.decode('utf-8').strip() out = subprocess.run( f"curl --output - 'https://www.gigaglitters.com/created/{imgname}'", shell=True, capture_output=True).stdout self.data[path] = out return self.fd def read(self, path, size, offset, fh): print(offset, size, fh) return self.data[path][offset:offset+size] def write(self, path, data, offset, fh): return len(data) def truncate(self, path, length, fh=None): pass def unlink(self, path): if path in self.files: del self.files[path] if path in self.data: del self.data[path] def rmdir(self, path): # Check if directory is empty for name in self.files: if name != path and name.startswith(path + '/'): raise FuseOSError(errno.ENOTEMPTY) # Remove directory and update parent parent = os.path.dirname(path) self.files[parent]['st_nlink'] -= 1 del self.files[path] def chmod(self, path, mode): if path in self.files: self.files[path]['st_mode'] = (self.files[path]['st_mode'] & ~0o777) | mode self.files[path]['st_mtime'] = time.time() def utimens(self, path, times=None): if path in self.files: now = time.time() atime, mtime = times if times else (now, now) self.files[path]['st_atime'] = atime self.files[path]['st_mtime'] = mtime def main(mountpoint): FUSE(GlitterFS(), mountpoint, nothreads=True, foreground=True) if __name__ == '__main__': if len(sys.argv) != 2: print(f"Usage: {sys.argv[0]} ") sys.exit(1) mountpoint = sys.argv[1] print(f"Mounting synthetic filesystem at {mountpoint}") main(mountpoint)