extFS-Seyshell/src/disk.c
2026-04-21 11:56:36 +02:00

240 lines
6.1 KiB
C

/** @file */
#include "disk.h"
#include "struct.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int init_inode_in_disk(disk *d, int inode_index, int filetype,
unsigned short perms, int owned_bloc) {
if (d->inodes[inode_index].filetype != TYPE_NULL)
return -1;
d->owned_blocs[owned_bloc] = 1;
d->inodes[inode_index].filetype = filetype;
d->inodes[inode_index].perms = perms;
for (int i = 0; i < MAX_BLOCS; i++) {
d->inodes[inode_index].blocs[i] = -1;
}
d->inodes[inode_index].blocs[0] = owned_bloc;
return 0;
}
int find_free_bloc(disk *d) {
for (int i = 0; i < MAX_BLOCS; i++) {
if (d->owned_blocs[i] == 0) {
d->owned_blocs[i] = 1;
return i;
}
}
return -1;
}
int find_offset_in_parent_bloc(bloc *parent_bloc) {
int entry_size = MAX_INODE_NAME + sizeof(int);
int max_entries = MAX_BYTES_PER_BLOC / entry_size;
for (int i = 0; i < max_entries; i++) {
int current_offset = i * entry_size;
// Si le premier caractère est '\0', la case est libre
if (parent_bloc->datas[current_offset] == '\0') {
return current_offset;
}
}
return -1;
}
int create_directory(disk *disk, inode *parent, char *dirname) {}
int create_file(disk *disk, inode *parent, char *filename) {
int inode_index = 0;
while (inode_index < MAX_INODE &&
disk->inodes[inode_index].filetype != TYPE_NULL) {
inode_index++;
}
if (inode_index >= MAX_INODE) {
dprintf(STDERR_FILENO, "No free inodes\n");
return -1;
}
int new_bloc_idx = find_free_bloc(disk);
if (new_bloc_idx == -1) {
dprintf(STDERR_FILENO, "Disk Full\n");
return -1;
}
int p_bloc_idx = parent->blocs[0];
int offset = find_offset_in_parent_bloc(&disk->blocs[p_bloc_idx]);
if (offset == -1) {
dprintf(STDERR_FILENO, "Parent directory full\n");
return -1;
}
strncpy(&disk->blocs[p_bloc_idx].datas[offset], filename, MAX_INODE_NAME);
memcpy(&disk->blocs[p_bloc_idx].datas[offset + MAX_INODE_NAME], &inode_index,
sizeof(int));
init_inode_in_disk(disk, inode_index, TYPE_FILE, 0b111111111, new_bloc_idx);
return inode_index;
}
int create_inode(disk *disk, inode *parent, char inode_type, char *name) {
if (strlen(name) > MAX_INODE_NAME) {
dprintf(STDERR_FILENO, "A inode name must be < %d\n", MAX_INODE_NAME);
return -1;
}
if (parent->filetype != TYPE_DIRECTORY) {
dprintf(STDERR_FILENO, "A parent's inode must be a directory!\n");
return -1;
}
switch (inode_type) {
case TYPE_DIRECTORY:
return create_directory(disk, parent, name);
break;
case TYPE_FILE:
return create_file(disk, parent, name);
case TYPE_BINARY:
// TODO plus tard
break;
case TYPE_SYMBOLIC_LINK:
// TODO plus tard
break;
default:
break;
}
return -1;
}
void write_in_file(disk *d, int file_index, char *data /*, char mode*/) {
inode file = d->inodes[file_index];
if (file.filetype != TYPE_FILE) {
dprintf(STDERR_FILENO, "Can only write in files\n");
return;
}
// mode 'w' (on écrase tout ^^)
// les blocs sont possédés par un seul inode donc c'est ok de tout écraser
// TODO: regarder si l'inode est sur plusieurs blocs et écraser tous les blocs
// possédé
int bloc_index_to_overwrite = file.blocs[0];
if (bloc_index_to_overwrite == -1) {
dprintf(STDERR_FILENO, "This inode does not have any bloc\n");
return;
}
strncpy(&d->blocs[bloc_index_to_overwrite].datas[0], data, strlen(data));
}
void do_ls(disk *d, int dir_index) {
inode dir = d->inodes[dir_index];
if (dir.filetype != TYPE_DIRECTORY) {
dprintf(STDERR_FILENO, "ls: Can only list in directories\n");
return;
}
// TODO: chercher sur tous les blocs possédés
int bloc = dir.blocs[0];
for (int i = 0; i < MAX_BYTES_PER_BLOC; i += MAX_INODE_NAME + sizeof(int)) {
if (d->blocs[bloc].datas[i] != '\0') {
int inode_id;
memcpy(&inode_id, &d->blocs[bloc].datas[i + MAX_INODE_NAME], sizeof(int));
dprintf(STDOUT_FILENO, "%-16s %d\n", &d->blocs[bloc].datas[i], inode_id);
}
}
}
char *read_in_file(disk *d, int file_index) {
inode file = d->inodes[file_index];
if (file.filetype != TYPE_FILE) {
dprintf(STDERR_FILENO, "Can only read in files\n");
return NULL;
}
// TODO: chercher sur tous les blocs possédés
int bloc = file.blocs[0];
char *out;
int c_index = 0;
while (d->blocs[bloc].datas[c_index] != '\0' || c_index < MAX_BYTES_PER_BLOC) {
c_index++;
}
out = malloc(c_index * sizeof(char));
if (out == NULL) {
dprintf(STDERR_FILENO, "Error while allocating with malloc\n");
exit(EXIT_FAILURE);
}
strncpy(out, d->blocs[bloc].datas, c_index);
return out;
}
void init_env_var_file(disk *d) {
int inode_idx = create_inode(d, &d->inodes[0], TYPE_FILE, "env");
write_in_file(d, inode_idx, "PWD=/\nUSER=user");
}
/**
* @brief Créer un fichier "disk" de taille MAX_BYTES_PER_BLOC * MAX_BLOCS,
* renvoi ce disque
* @return Le disque créé
*/
disk create_disk() {
FILE *fptr;
fptr = fopen("disk", "wb");
disk d;
for (int i = 0; i < MAX_INODE; i++) {
d.inodes[i].filetype = TYPE_NULL;
d.inodes[i].perms = 0b000000000;
for (int j = 0; j < MAX_BLOCS; j++) {
d.inodes[i].blocs[j] = -1;
}
}
for (int i = 0; i < MAX_BLOCS; i++) {
d.owned_blocs[i] = 0;
}
// création de la racine '/'
d.inodes[0].filetype = TYPE_DIRECTORY;
d.inodes[0].perms = 0b111111111; // tlm fait ce qu'il veut
d.inodes[0].blocs[0] = 0; // utilise le bloc 0
d.owned_blocs[0] = 1; // le bloc 1 est maintenant occupé
init_env_var_file(&d);
int n = fwrite(&d, sizeof(disk), 1, fptr);
if (n == 1) {
dprintf(STDOUT_FILENO, "Disk of size %.2fKb created successfully.\n",
(float)(MAX_BYTES_PER_BLOC * MAX_BLOCS) / 1000);
}
fclose(fptr);
return d;
}
/**
* @brief Si un fichier filename existe, alors on le lit et le stocke en mémoire
* @param char *filename Le nom du fichier à lire
* @return Le disque lu
*/
disk open_disk(char *filename) {
disk d;
FILE *fptr = fopen(filename, "r");
if (fptr == NULL)
exit(EXIT_FAILURE);
fread(&d, sizeof(d), 1, fptr);
fclose(fptr);
return d;
}