240 lines
6.1 KiB
C
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;
|
|
}
|