/** @file */ #include "disk.h" #include "struct.h" #include #include #include #include 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; }