Devoir 2 - Système de Fichiers
Informations générales
Date limite: 09 avril, 23:59
Points: 2 points de la note finale
Lien: Devoir 2 - FileSystem
Télécharger en retard: 1 points / jour (maximum 4 jours)
Connaissances évaluées
- Utiliser le langage Rust
- Comprendre le mode de fonctionnement du système de fichiers
- Simuler un système de fichiers
Règles
- Le devoir doit contenir un fichier nommé Readme.md avec des explications concernant la manière choisie pour résoudre le devoir (-0.1p)
- Le devoir doit être implémenté en Rust et seulement en utilisant des fonctions de la bibliothèque standard Rust. Toute autre implémentation conduira à l'annulation du devoir.(0 points)
Copiage
Le devoir est individuel. Toute tentative de copier entraînera 0p pour les devoirs. On utilisera un système automatisé pour détecter le copiage. Si on a des doutes, on va vous adresser des questions supplémentaires concernant le devoir.
Questions
Si vous avez des questions concernant le devoir, posez-les en publiant un issue sur le github https://github.com/UPB-FILS-SdE2/questions avec le format [filesystem] "le titre de votre question" . Vous aurez besoin d'un compte github pour publier des questions.
NE PUBLIEZ PAS DE CODE SOURCE. Cela est considéré comme copiage et vous aller recevoir 0p pour le devoir.
Si vous voulez recevoir un e-mail lorsque des problèmes sont signalés ou lorsqu'il y a de nouveaux messages, accédez au site github repository et cliquez sur Watch.
Système de Fichiers
Le but de ce devoir est d'implémenter un système de fichiers simplifié similaire à celui utilisé sous Linux. Vous devrez la mettre en œuvre:
- une structure arborescente qui stocke les fichiers et les dossiers du système de fichiers;
- une table de descripteurs de fichiers;
- les fonctions permettant d'accéder au système de fichiers simulé.
Afin de résoudre les devoirs, vous devez stocker et gérer les descripteurs de fichiers internes du système de fichiers personnalisé afin de pouvoir suivre les fichiers ouverts. Vous pouvez gérer cette partie comme vous le souhaitez.
Après cela, vous devez implémenter les opérations de base du système de fichiers qui seront détaillées ci-dessous et mettre à jour la table des descripteurs de fichiers en conséquence.
Vous devez vous assurer qu'après chaque opération le fichier correspondant sera fermé!
Énumération INode
Le système de fichiers a une structure arborescente qui est représentée par l'énumération ci-dessous. Un inode est une donnée structure qui garde une trace de tous les fichiers et répertoires. Chaque fichier et répertoire de notre système de fichiers se voit attribuer un INode
.
À partir du nœud racine, chaque fois que nous souhaitons créer un nouveau fichier ou dossier dans notre système, nous devons en réalité faire créez un nouvel élément INode
avec les informations nécessaires.
Il y a 2 champs dans notre énumération :
Folder
- une structure qui représente un dossier dans notre système de fichiers; le contenu est unHashMap
qui contient le nom du dossier ou fichier comme clé et les fichiers et répertoires enfants du dossier représenté parINode
s;permissions
- les autorisations indiquent la lecture/écriture autorisations du dossier
File
- une structure qui représente un fichier dans notre système de fichiers;data
est un vecteur d'octets qui contient les données à l'intérieur du déposer;permissions
- les autorisations indiquent les autorisations de lecture/écriture du fichier
Exemple de système de fichiers INode:
Folder {
contents: {
"folder1": Folder {
contents: {},
permissions: ReadWrite,
},
"file1": File {
data: [],
permissions: ReadWrite,
},
},
permissions: ReadWrite,
}
Il est conseillé de définir des fonctions dédiées à l'ajout et à la suppression d'INodes
car cela rendra ces opérations plus modulaires.
Opérations requises
mount
Cette fonction monte le système de fichiers (crée le nœud racine) qui va être utilisé par les opérations définies dans le Trait du système de fichiers. Il renvoie un un pointeur intelligent (Box
) vers une structure qui implémente le trait FileSystem
.
pub fn mount(_size: usize) -> Box<dyn FileSystem>
Bonus - limiter la taille du système de fichiers en utilisant le paramètre _size
FileSystem
trait
create
Cette fonction créera un fichier s'il n'existe pas et l'ouvrira en mode lecture seule. Il renvoie soit le descripteur de fichier correspondant au fichier spécifié, soit une erreur. Les erreurs suivantes doivent être gérées par cette fonction :
InvalidType
si le chemin pointe vers un dossierPermissionDenied
si le répertoire dans lequel nous créons le fichier ne dispose pas des autorisations d'écriture
fn create(
&mut self,
path: &str,
permission_mode: PermissionsMode,
) -> Result<usize, FileSystemError>;
open
Cette fonction tente d'ouvrir un fichier avec les autorisations demandées. Soit il renvoie le descripteur de fichier correspondant pour le fichier spécifié ou une erreur. Les erreurs suivantes doivent être gérées par cette fonction :
FileNotFound
si le fichier spécifié par le chemin donné en paramètre n'existe pasInvalidType
si le chemin pointe vers un dossierPermissionDenied
si les autorisations avec lesquelles le fichier a été créé sont compatibles avec les autorisations avec lesquelles nous souhaitons ouvrir le fichier
fn open(&mut self, path: &str, permissions: PermissionsMode) -> Result<usize, FileSystemError>;
close
Cette fonction ferme un fichier ouvert, ce qui signifie qu'elle doit supprimer toutes les informations existantes dont il dispose pour le descripteur de fichier correspondant (fd). Il doit renvoyer l'erreur InvalidFileDescriptor si le descripteur de fichier spécifié ne correspond à aucun fichier ouvert.
fn close(&mut self, fd: usize) -> Result<(), FileSystemError>;
read
Cette fonction lit le contenu du fichier indiqué par le descripteur de fichier, qui est passé en paramètre (fd), et remplit le tampon avec eux. Il renvoie soit le nombre d'octets lus, soit une erreur. Les erreurs suivantes doivent être gérées par cette fonction :
InvalidFileDescriptor
si le descripteur de fichier n'est pas valide
fn read(&mut self, fd: usize, buffer: &mut [u8]) -> Result<usize, FileSystemError>;
write
Cette fonction écrit une tranche contenant tout le contenu d'un fichier indiqué par le descripteur de fichier, qui est passé en paramètre (fd). Il renvoie soit le nombre d'octets écrits, soit une erreur. Les erreurs suivantes doivent être gérées par cette fonction :
InvalidFileDescriptor
si le descripteur de fichier n'est pas valideDiskFull
s'il n'y a plus d'espace sur le disque (bonus uniquement)
fn write(&mut self, fd: usize, contents: &[u8]) -> Result<usize, FileSystemError>;
dup2
Cette fonction crée une copie du descripteur de fichier spécifié en utilisant le fd spécifié. Il se comporte de manière similaire à dup()
sauf qu'il essaiera d'utiliser le fd spécifié au lieu d'en allouer un nouveau. Si new_fd est ouvert, cette fonction le fermera.
Les erreurs suivantes doivent être gérées par cette fonction :
InvalidFileDescriptor
est old_fd n'existe pas
fn dup2(&mut self, old_fd: usize, new_fd: usize) -> Result<(), FileSystemError>;
Vous pouvez en savoir plus sur dup et dup2 ici.
seek
Cette fonction déplace le curseur de fichier dans le fichier. Il n'y a pas d'erreur OutOfBounds, la position du fichier sera trucée soit à 0, soit à la taille du fichier. Les erreurs suivantes doivent être gérées par cette fonction :
InvalidFileDescriptor
si le descripteur de fichier n'est pas valide
fn seek(&mut self, fd: usize, position: OffsetFrom) -> Result<usize, FileSystemError>;
Vous pouvez en savoir plus sur seek ici.
file descriptor info
Cette fonction renvoie une référence à la structure FileDescriptorInfo correspondant au paramètre fd. Si le fd n'est pas valide, cette fonction doit renvoyer None.
fn file_descriptor_info(&mut self, fd: usize) -> Option<&dyn FileDescriptorInfo>;
chmod
Cette fonction modifie les autorisations sur un certain fichier/répertoire spécifié par le chemin. Les erreurs suivantes doivent être gérées par cette fonction :
FileNotFound
si le fichier au chemin spécifié n'existe pas
fn chmod(
&mut self,
path: &str,
permissions_mode: PermissionsMode,
) -> Result<(), FileSystemError>;
stat
Cette fonction renvoie la structure FileInfo correspondant au paramètre path. Les erreurs suivantes doivent être gérées par cette fonction :
FileNotFound
si le fichier au chemin spécifié n'existe pas
fn stat(&mut self, path: &str) -> Result<FileInfo, FileSystemError>;
mkdir
Cette fonction crée un nouveau répertoire au chemin spécifié. Les erreurs suivantes doivent être gérées par cette fonction :
FileExists
si le répertoire existe déjà ou s'il existe un fichier à la placePermissionDenied
si le répertoire parent ne dispose pas d'autorisations en écriture
fn mkdir(&mut self, path: &str) -> Result<(), FileSystemError>;
rmdir
Cette fonction supprime le répertoire spécifié par le chemin uniquement si le répertoire est vide. Les erreurs suivantes doivent être gérées par cette fonction :
DirectoryNotEmpty
si le répertoire n'est pas videInvalidFiletype
si le chemin pointe vers un fichierPermissionDenied
si le répertoire parent ne dispose pas d'autorisations en écriture
fn rmdir(&mut self, path: &str) -> Result<(), FileSystemError>;
rm
Cette fonction supprime le fichier spécifié par le chemin. Le répertoire qui contient le fichier doit disposer des autorisations d'écriture. Les erreurs suivantes doivent être gérées par cette fonction :
InvalidFiletype
si le chemin pointe vers un répertoirePermissionDenied
si le répertoire parent ne dispose pas d'autorisations en écriture
fn rm(&mut self, path: &str) -> Result<(), FileSystemError>;
list dir
Cette fonction répertorie tous les fichiers du répertoire spécifié par le paramètre path. Les erreurs suivantes doivent être gérées par cette fonction :
PermissionDenied
si le répertoire ne dispose pas d'autorisations de lecture ou de lecture en écritureFileNotFound
si le chemin est inaccessibleInvalidType
si le chemin spécifié pointe vers un fichier
fn list_dir(&mut self, path: &str) -> Result<Vec<String>, FileSystemError>;
rename
Cette fonction renomme un fichier de son ancien chemin vers un nouveau chemin spécifié par les paramètres. Le new_path ne devrait pas déjà exister. Les autorisations nécessaires à son fonctionnement sont : Lire dans le répertoire parent, Ecrire dans le répertoire de destination. Les erreurs suivantes doivent être gérées par cette fonction :
FileNotFound
si l'ancien chemin n'est pas valideFileExists
si new_path existe déjàPermissionDenied
si les permissions sont compatibles avec celles attendues
fn rename(&mut self, old_path: &str, new_path: &str) -> Result<(), FileSystemError>;
Structures de données
Dans le dépôt de votre travail, lancez cargo doc -open
pour ouvrir la documentation.
Exécuter le devoir
Ecrivez un code qui utilise la bibliothèque que vous avez créée pour votre devoir (sde2_fs
) dans sde2_fs/src/tests.rs
dans la fonction run
. Pour l'exécuter, écrivez cargo test run -- --nocapture
.