#!/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)