Skip to content
Snippets Groups Projects
Commit ce8f6d43 authored by David Grellscheid's avatar David Grellscheid
Browse files

Initial sketch of the task. Needs cleanup

parents
No related branches found
No related tags found
No related merge requests found
myfilesystem.fs
myfs.py 0 → 100644
import sys
if len(sys.argv) < 2:
# Missing filesystem name. Assuming default myfilesystem.fs
backingfile = 'myfilesystem.fs'
else:
backingfile = sys.argv[1]
# one could actually use a usb stick raw at "/dev/something"
# Data loss, and it'll need reformatting afterwards!
# create backingfile if needed
try:
with open(backingfile, 'x'): pass
except FileExistsError: pass
##########################################
##########################################
# file system parameters
TOTAL_SIZE = 0x800 # 2kB
HEADER_START = 0x0
COUNTER_BYTES = 0x1
FILE_ENTRY_SIZE = 0x10
FILE_BLOCK_SIZE = 0x100
# file block 0 is the metainfo block
# line 0 of metainfo contains the number of files
# lines 1.. contain the filenames.
# line N has the filename of the file in Block N
# file blocks 1.. contain just the file contents
# use "xxd myfilesystem.fs" to look at the raw contents
# internal exception to signal no file
class NoFile(Exception):
pass
def format(f):
# 2kB filesystem
f.write(b'\0' * TOTAL_SIZE)
def _get_num_files(f):
f.seek(HEADER_START)
bytes = f.read(COUNTER_BYTES)
num = int.from_bytes(bytes, "little", signed=False)
return num
def _set_num_files(f, n):
f.seek(HEADER_START)
bytes = n.to_bytes(COUNTER_BYTES, "little", signed=False)
f.write(bytes)
def save(f, filename, content):
num_existing = _get_num_files(f)
new_fileno = num_existing + 1
_set_num_files(f, new_fileno)
# write filename in ftable next free entry, truncate if needed
f.seek(HEADER_START + FILE_ENTRY_SIZE * new_fileno)
f.write(filename.encode('ascii')[:FILE_ENTRY_SIZE])
# write content to file block, truncate if needed
f.seek(HEADER_START + FILE_BLOCK_SIZE * new_fileno)
f.write(content.encode('ascii')[:FILE_BLOCK_SIZE])
def find_fileno(f, filename):
N = _get_num_files(f)
for pos in range(0, N):
f.seek(HEADER_START + FILE_ENTRY_SIZE * (pos+1))
name = f.read(FILE_ENTRY_SIZE)
name = name.decode("ascii").strip('\0')
if name == filename:
return pos
else:
print(f"File {filename} not found", file=sys.stderr)
raise NoFile
def load(f, filename):
fileno = find_fileno(f, filename)
f.seek(HEADER_START + FILE_BLOCK_SIZE * (fileno+1))
content = f.read(FILE_BLOCK_SIZE)
content = content.decode("ascii").strip('\0')
# what if \0 is a valid part of the content?
return content
def copy(f, infile, outfile):
try:
content = load(f, infile)
except NoFile:
return
save(f, outfile, content)
def remove(f, filename):
fileno = find_fileno(f, filename)
f.seek(HEADER_START + FILE_BLOCK_SIZE * (fileno+1))
f.write(b'\0' * FILE_BLOCK_SIZE)
f.seek(HEADER_START + FILE_ENTRY_SIZE * (fileno+1))
f.write(b'\0' * FILE_ENTRY_SIZE)
##########################
##########################
alice_sample = """Alice was beginning to get very tired of sitting by her sister on the
bank, and of having nothing to do: once or twice she had peeped into the
book her sister was reading, but it had no pictures or conversations in
it, 'and what is the use of a book,' thought Alice 'without pictures or
conversations?'
"""
if __name__ == "__main__":
print()
print("*" * 60)
print(f"* Use xxd {backingfile} to inspect contents")
print("*" * 60)
print()
with open(backingfile, 'r+b') as f:
format(f)
save(f, "hello.txt", "Hello")
save(f, "alice.txt", alice_sample)
alice_back = load(f, "alice.txt")
print(alice_back)
copy(f, "hello.txt", "clone.txt")
save(f, "bye.txt", "Bye Bye")
copy(f, "hello.txt", "clone2.txt")
remove(f, "bye.txt")
# ls(f)
# save(f, A)
# save(f, B)
# remove(f,A)
# save(f,C)
# C should re-use the free slot
# ls(f)
# error if FS full, filetable full, file too big, filename too big, etc.
# how to use the free file block after remove()?
# keep track of file sizes?
# binary file support?
#
# by file ending?
# make a simple REPL that understands the above commands
# NoFile should be handled in the REPL, REPL itself not crashing
# files bigger than 1 block
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment