Skip to content
Snippets Groups Projects
Commit b8d43667 authored by Hilde Jordal's avatar Hilde Jordal
Browse files

myfs v2?

parent 1c99b65f
No related branches found
No related tags found
No related merge requests found
......@@ -4,44 +4,42 @@
I denne oppgaven får dere utlevert kode som simulerer et enkelt filsystem. Kjør ´``main.py`` for å generere filsystemet med noen eksempelfiler.
Filsystemet er som helhet lagret i en fil ``myfilesystem.fs`` og har headers, blokker osv. Les kommentarer og dokumentasjon i koden for å forstå koden bedre. Det er også mulig å åpne filsystemet som rå data ved å bruke kommando ``xxd myfilesystem.fs`` i terminal. Da vil du se en oversikt over filsystemet i hexadesimalt format.
Filsystemet er som helhet lagret i en fil ``myfilesystem.fs`` og er delt inn i blokker. Den første blokken har headerinformasjon om filsystemet, og resten er blokker brukt til filinnhold. Les kommentarer og dokumentasjon i koden for å forstå koden bedre. Det er også mulig å åpne filsystemet som rå data ved å bruke kommando ``xxd myfilesystem.fs`` i terminal. Da vil du se en oversikt over filsystemet i hexadesimalt format.
## Oppgave 1: save()
## Oppgave 1: Bedre bruk av frie blokker
- File size in header, block is 256 so size entry is 1 byte
- 15 bytes for filename, 1 byte for file size
- (hint at split instead of direct explanation, would be good idea to update the GLOBAL_FILENAME_SIZE variable and use it)
-
- Read through the code and understand how save keeps track of free blocks, and understand why this is not ideal.
Now change it such that it always finds the first available free block to write to. This should work in union with remove() (or we can say it should work after a file has been removed anywhere). Make sure that an error is still raised when you cannot save any more files.
Forsøk å forstå hvordan ``save()`` bestemmer hvor en ny fil skal lagres. Tenk over hvorfor dette ikke er ideelt med tanke på at filer kan slettes. Endre koden slik at den alltid finner den første tilgjengelige blokken å skrive til. Dette bør fungere i samspill med ``remove()``, som sletter filer. Pass på at du fortsatt får samme feilmelding dersom du ikke har plass til å lagre flere filer.
## Oppgave 2: load()
- Update load() so that it uses the file size from the header to read the correct number of bytes from the block.
## Oppgave 2: Bedre lasting av filer
## Oppgave 3: remove()
- Make the remove() function more efficient now that we are storing the file size in the file header.
Slik load() er implementert, hva skjer med filer som har gyldige ``\0`` bytes på slutten av innholdet? Vi ønsker å endre load() slik at den leser så mange bytes som filen faktisk inneholder, og ikke hele blokken. Da løser vi det problemet.
## Oppgave 4: link()
- There are unused lines of the file system header, lines that do not correspond to a block. We can use this remaining space to create links to existing files. Implement the link() function such that it creates a file entry (using the same global file name size) which is linked to an existing file. This linked file should have the same content as the original file, but should not take up any additional space in the file system.
- hint: the file size is not needed for the link since the existing file should have it. You can make use of this space to implement link().
Dette vil kreve at vi lagrer filstørrelsen i filens header. Tenk over hvor mye av en file entry du har behov for å bruke til dette formålet, og oppdater ``FILENAME_SIZE`` i henhold til dette. Etter det kan du endre ``save()`` slik at den lagrer filstørrelsen i headeren, og endre ``load()`` slik at den leser riktig antall bytes fra blokken.
## Oppgave 4: remove() continued
- Update remove() to consider linked files. Removing a link should not remove the original file nor its content. But removing the original file should remove all links to it.
## Oppgave 3: Bedre remove()
Siden `load()` nå leser bare eksakt det innholdet som er lagret i en fil og ikke hele blokken, kan vi endre ``remove()`` slik at den gjør mindre arbeid for å frigjøre plass. Din oppgave er å gjøre den endringen.
# Ideas:
## Oppgave 4: hard_link()
Vi har gitt filsystemet en hel blokk til headerinformasjon. Der lagres filnavnene og størrelsene som vi har brukt så langt. Men vi har ikke nok blokker til å fylle den fullstendig med file entries. Med den resterende plassen skal vi tillate å lage hard links til eksisterende filer.
### Del A
Implementer ``hard_link(f, existing_file, linked_file)``. Funksjonen skal lage en ny file entry som peker til en eksisterende fil. Med andre ord, funksjonen skal lage en hard link.
- load() should load only file size
- Remove() should free the space taken by the file. New files should use the new free space if available instead of following the incremented block number.
- Load() should allow files to have \0 characters in them.
- Implement ls() to see all the files in the directory
- allow file sizes of multiple blocks?
- problem is perhaps recording that the extra blocks are taken since they probably wont be associated with a filename
- require change in most of the code?, so large task
(Hint: Filstørrelsen er ikke nødvendig for en hard link siden den eksisterende filen allerede har den. Du kan bruke denne plassen til noe annet for å implementere hard_link.)
## Todo:
- Add explanation of how the file system works in intro text?
- add error for save() which fails if we have exceeded file system size, ifthere is no space to save
- add doc for ls and link
\ No newline at end of file
### Del B
Oppdater `load()` slik at den kan lese innholdet fra en hard link.
### Del C
Oppdater `remove()` slik:
- Hvis `remove()` blir kallet for en fil, skal filens originale file entry erstattes av den øverste hard linken som peker til filen. Hvis det ikke finnes noen slike hard linker, skal filen slettes.
- Hvis `remove()` blir kallet for en hard link, skal hard linken slettes.
- Husk å bruke `NoFile` som exception når filnavnet ikke finnes hverken som fil eller link.
## change log
- changed find_fileno so it uses FILENAME_SIZE from the start, so not needed to change in student task
- added error for save() if no space is available which is used in save() to begin with.
- added error to remove() if file not found
- Made it so errors are not caught in the file system, such that the student can see the error messages and they can be checked in unit tests.
\ No newline at end of file
......@@ -11,16 +11,25 @@ COUNTER_BYTES = 0x1
FILE_ENTRY_SIZE = 0x10
# size of a file block (content of a file)
FILE_BLOCK_SIZE = 0x100
# max number of files (first block is reserved for metainfo, rest are files)
MAX_FILES = (TOTAL_SIZE - FILE_BLOCK_SIZE) // FILE_BLOCK_SIZE
GLOBAL_FILENAME_SIZE = FILE_ENTRY_SIZE #TODO
FILENAME_SIZE = FILE_ENTRY_SIZE #TODO
# use "xxd myfilesystem.fs" to look at the raw contents
# internal exception to signal no file
###### EXCEPTIONS ######
class NoFile(Exception):
pass
def __init__(self, message="No such file found"):
self.message = message
super().__init__(self.message)
class NoFreeSpace(Exception):
def __init__(self, message="No free space available"):
self.message = message
super().__init__(self.message)
###### FILE SYSTEM OPERATIONS ######
def format(f):
"""
Formats the file system by writing the initial metadata.
......@@ -53,6 +62,9 @@ def save(f, filename, content):
num_existing = _get_num_files(f)
new_fileno = num_existing + 1
_set_num_files(f, new_fileno)
if new_fileno >= MAX_FILES:
raise NoFreeSpace(f"No free space available, max files: {MAX_FILES}")
# write filename in ftable next free entry, truncate if needed
f.seek(HEADER_START + FILE_ENTRY_SIZE * new_fileno)
......@@ -68,14 +80,13 @@ 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 = f.read(FILENAME_SIZE)
name = name.decode("ascii").strip('\0')
if name == filename:
return pos
else:
print(f"File {filename} not found", file=sys.stderr)
raise NoFile
raise NoFile(f"File {filename} not found")
def load(f, filename):
"""
......@@ -91,7 +102,7 @@ def load(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):
......@@ -104,11 +115,7 @@ def copy(f, infile, outfile):
infile (str): The name of the file to copy from.
outfile (str): The name of the new file to copy to.
"""
try:
content = load(f, infile)
except NoFile:
return
content = load(f, infile)
save(f, outfile, content)
......@@ -120,7 +127,9 @@ def remove(f, filename):
f (file object): The file object representing the file system.
filename (str): The name of the file to remove.
"""
fileno = find_fileno(f, filename)
f.seek(HEADER_START + FILE_BLOCK_SIZE * (fileno+1))
f.write(b'\0' * FILE_BLOCK_SIZE)
......@@ -128,45 +137,14 @@ def remove(f, filename):
f.write(b'\0' * FILE_ENTRY_SIZE)
def link(f, existing_file, linked_file):
"""_summary_
def hard_link(f, existing_file, link_name):
"""
Create a hard link to an existing file.
Args:
f (_type_): _description_
existing_file (_type_): _description_
linked_file (_type_): _description_
f (file object): The file object representing the file system.
existing_file (str): The name of the existing file.
link_name (str): The name of the new hard link.
"""
# YOUR CODE HERE
#TODO: implement this function
...
##########################
##########################
# 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