diff --git a/src/const.h b/src/const.h index 1fcac87..832f163 100644 --- a/src/const.h +++ b/src/const.h @@ -2,7 +2,7 @@ #define BUFSIZE 1024 #define MAX_BLOCS 30 #define MAX_BYTES_PER_BLOC 512 -#define MAX_INODE 20 +#define MAX_INODE 30 #define MAX_INODE_NAME 28 // 27 caractères + '\0' + numero de l'inode ref #define TYPE_NULL 0 diff --git a/src/disk.c b/src/disk.c index 3e47040..f8613e1 100644 --- a/src/disk.c +++ b/src/disk.c @@ -50,7 +50,7 @@ int find_offset_in_parent_bloc(bloc *parent_bloc) { } int is_dir_empty(disk *d, int bloc_index) { - for (int i = 0; i < MAX_BYTES_PER_BLOC; i+= MAX_INODE_NAME + sizeof(int)) { + for (int i = 0; i < MAX_BYTES_PER_BLOC; i += MAX_INODE_NAME + sizeof(int)) { char name[MAX_INODE_NAME]; strncpy(name, &d->blocs[bloc_index].datas[i], MAX_INODE_NAME); if (strcmp(name, "..") != 0 && strcmp(name, ".") != 0 && name[0] != 0) { @@ -103,7 +103,7 @@ int allocate_node(disk *disk, inode *parent, char *name, char type) { } int remove_inode(disk *disk, inode *parent, inode *inode_to_remove, - int inode_to_remove_idx) { + int inode_to_remove_idx) { if (parent == inode_to_remove) { dprintf(STDERR_FILENO, "rm: can't delete root\n"); @@ -140,127 +140,137 @@ int remove_inode(disk *disk, inode *parent, inode *inode_to_remove, } int do_rmdir(disk *disk, char *filepath) { - char *parent_path = NULL; - char *dirname = NULL; + char *parent_path = NULL; + char *dirname = NULL; - if (get_dirname_and_parent_path_by_absolute_path(filepath, &parent_path, &dirname) == -1) { - dprintf(STDERR_FILENO, "rmdir: path error\n"); - return -1; - } + if (get_dirname_and_parent_path_by_absolute_path(filepath, &parent_path, + &dirname) == -1) { + dprintf(STDERR_FILENO, "rmdir: path error\n"); + return -1; + } - int parent_index = 0; - char *token = strtok(parent_path, "/"); + int parent_index = 0; + char *token = strtok(parent_path, "/"); - while (token != NULL) { - parent_index = find_dir_inode_by_name(token, parent_index, disk); + while (token != NULL) { + parent_index = find_dir_inode_by_name(token, parent_index, disk); - if (parent_index == -1) { - dprintf(STDERR_FILENO, "rmdir: path '%s' does not exist\n", token); - free(parent_path); free(dirname); - return -1; - } - - if (disk->inodes[parent_index].filetype != TYPE_DIRECTORY) { - dprintf(STDERR_FILENO, "rmdir: '%s' is not a directory\n", token); - free(parent_path); free(dirname); - return -1; - } - - token = strtok(NULL, "/"); - } - - int file_index = find_dir_inode_by_name(dirname, parent_index, disk); - - if (file_index == -1) { - dprintf(STDERR_FILENO, "rmdir: can't delete '%s': no such directory\n", dirname); - free(parent_path); free(dirname); - return -1; - } - - if (disk->inodes[file_index].filetype != TYPE_DIRECTORY) { - dprintf(STDERR_FILENO, "rmdir: can't delete '%s': not a directory\n", dirname); - free(parent_path); free(dirname); - return -1; - } - - if (!(is_dir_empty(disk, disk->inodes[file_index].blocs[0]) == 1)) { - dprintf(STDERR_FILENO, "rmdir: directory not empty\n"); + if (parent_index == -1) { + dprintf(STDERR_FILENO, "rmdir: path '%s' does not exist\n", token); + free(parent_path); + free(dirname); return -1; } - int res = remove_inode(disk, &disk->inodes[parent_index], &disk->inodes[file_index], file_index); - - if (res == 1) { - } else { - dprintf(STDERR_FILENO, "rmdir: can't delete because of a fatal error\n"); + if (disk->inodes[parent_index].filetype != TYPE_DIRECTORY) { + dprintf(STDERR_FILENO, "rmdir: '%s' is not a directory\n", token); + free(parent_path); + free(dirname); + return -1; } + token = strtok(NULL, "/"); + } + + int file_index = find_dir_inode_by_name(dirname, parent_index, disk); + + if (file_index == -1) { + dprintf(STDERR_FILENO, "rmdir: can't delete '%s': no such directory\n", + dirname); free(parent_path); free(dirname); + return -1; + } - persist_on_disk(disk); + if (disk->inodes[file_index].filetype != TYPE_DIRECTORY) { + dprintf(STDERR_FILENO, "rmdir: can't delete '%s': not a directory\n", + dirname); + free(parent_path); + free(dirname); + return -1; + } - return (res == 1) ? 0 : -1; + if (!(is_dir_empty(disk, disk->inodes[file_index].blocs[0]) == 1)) { + dprintf(STDERR_FILENO, "rmdir: directory not empty\n"); + return -1; + } + + int res = remove_inode(disk, &disk->inodes[parent_index], + &disk->inodes[file_index], file_index); + + if (res == 1) { + } else { + dprintf(STDERR_FILENO, "rmdir: can't delete because of a fatal error\n"); + } + + free(parent_path); + free(dirname); + + return (res == 1) ? 0 : -1; } int do_rm(disk *disk, char *filepath) { - char *parent_path = NULL; - char *dirname = NULL; + char *parent_path = NULL; + char *dirname = NULL; - if (get_dirname_and_parent_path_by_absolute_path(filepath, &parent_path, &dirname) == -1) { - dprintf(STDERR_FILENO, "rm: erreur de chemin\n"); - return -1; + if (get_dirname_and_parent_path_by_absolute_path(filepath, &parent_path, + &dirname) == -1) { + dprintf(STDERR_FILENO, "rm: erreur de chemin\n"); + return -1; + } + + int parent_index = 0; + char *token = strtok(parent_path, "/"); + + while (token != NULL) { + parent_index = find_dir_inode_by_name(token, parent_index, disk); + + if (parent_index == -1) { + dprintf(STDERR_FILENO, "rm: path '%s' does not exist\n", token); + free(parent_path); + free(dirname); + return -1; } - int parent_index = 0; - char *token = strtok(parent_path, "/"); - - while (token != NULL) { - parent_index = find_dir_inode_by_name(token, parent_index, disk); - - if (parent_index == -1) { - dprintf(STDERR_FILENO, "rm: path '%s' does not exist\n", token); - free(parent_path); free(dirname); - return -1; - } - - if (disk->inodes[parent_index].filetype != TYPE_DIRECTORY) { - dprintf(STDERR_FILENO, "rm: '%s' is not a directory\n", token); - free(parent_path); free(dirname); - return -1; - } - - token = strtok(NULL, "/"); + if (disk->inodes[parent_index].filetype != TYPE_DIRECTORY) { + dprintf(STDERR_FILENO, "rm: '%s' is not a directory\n", token); + free(parent_path); + free(dirname); + return -1; } - int file_index = find_dir_inode_by_name(dirname, parent_index, disk); + token = strtok(NULL, "/"); + } - if (file_index == -1) { - dprintf(STDERR_FILENO, "rm: can't delete '%s': no such file\n", dirname); - free(parent_path); free(dirname); - return -1; - } - - if (disk->inodes[file_index].filetype != TYPE_FILE && - disk->inodes[file_index].filetype != TYPE_SYMBOLIC_LINK) { - dprintf(STDERR_FILENO, "rm: can't delete '%s': not a file\n", dirname); - free(parent_path); free(dirname); - return -1; - } - - int res = remove_inode(disk, &disk->inodes[parent_index], &disk->inodes[file_index], file_index); - - if (res == 1) { - } else { - dprintf(STDERR_FILENO, "rm: can't delete because of a fatal error\n"); - } + int file_index = find_dir_inode_by_name(dirname, parent_index, disk); + if (file_index == -1) { + dprintf(STDERR_FILENO, "rm: can't delete '%s': no such file\n", dirname); free(parent_path); free(dirname); + return -1; + } - persist_on_disk(disk); + if (disk->inodes[file_index].filetype != TYPE_FILE && + disk->inodes[file_index].filetype != TYPE_SYMBOLIC_LINK) { + dprintf(STDERR_FILENO, "rm: can't delete '%s': not a file\n", dirname); + free(parent_path); + free(dirname); + return -1; + } - return (res == 1) ? 0 : -1; + int res = remove_inode(disk, &disk->inodes[parent_index], + &disk->inodes[file_index], file_index); + + if (res == 1) { + } else { + dprintf(STDERR_FILENO, "rm: can't delete because of a fatal error\n"); + } + + free(parent_path); + free(dirname); + + return (res == 1) ? 0 : -1; } int create_file(disk *disk, inode *parent, char *filename) { @@ -399,12 +409,13 @@ int get_number_of_inode_left(disk *d) { int do_df(disk *d) { int free_blocs = get_number_of_free_blocs(d); - printf(" Free blocs : %i\n", free_blocs); - printf(" Inode left : %i\n", get_number_of_inode_left(d)); - // N'est pas la taille réelle à proprement parlé mais plutot l'espace - // possiblement occupable par le reste d'inode sur le disque - printf(" Space left : %.2fKb\n", - (float)(free_blocs * MAX_BYTES_PER_BLOC) / 1000); + int inodes_left = get_number_of_inode_left(d); + float space_left = (float)(free_blocs * MAX_BYTES_PER_BLOC) / 1000; + + dprintf(STDOUT_FILENO, + " Free blocs : %i\n Inode left : %i\n Space left : %.2fKb\n", + free_blocs, inodes_left, space_left); + return 0; } @@ -511,15 +522,14 @@ char *read_in_file(disk *d, int file_index) { return out; } -int do_cat(disk *disk, char* path_to_file) { - (void)disk; - (void)path_to_file; +int do_cat(disk *disk, char *path_to_file) { if (path_to_file == NULL) { char buffer[4096]; + ssize_t bytes_read; - while (fgets(buffer, 4096, stdin)) { - fprintf(stdout, "%s", buffer); + while ((bytes_read = read(STDIN_FILENO, buffer, sizeof(buffer))) > 0) { + write(STDOUT_FILENO, buffer, bytes_read); } } @@ -542,7 +552,7 @@ int do_cat(disk *disk, char* path_to_file) { return -1; } - printf("%s\n", read_in_file(disk, inode_index)); + dprintf(STDOUT_FILENO, "%s\n", read_in_file(disk, inode_index)); return 1; } @@ -582,8 +592,10 @@ disk create_disk() { memcpy(&d.blocs[0].datas[MAX_INODE_NAME], &root_inode, sizeof(int)); // création de '..' dans '/' - strncpy(&d.blocs[0].datas[MAX_INODE_NAME + sizeof(int)], "..", MAX_INODE_NAME); - memcpy(&d.blocs[0].datas[2*(MAX_INODE_NAME) + sizeof(int)], &root_inode, sizeof(int)); + strncpy(&d.blocs[0].datas[MAX_INODE_NAME + sizeof(int)], "..", + MAX_INODE_NAME); + memcpy(&d.blocs[0].datas[2 * (MAX_INODE_NAME) + sizeof(int)], &root_inode, + sizeof(int)); int test_file_inode = create_file(&d, &d.inodes[0], "test"); write_in_file(&d, test_file_inode, "coucou petit\ntest!!"); diff --git a/src/exec.c b/src/exec.c index 328b404..1b65edf 100644 --- a/src/exec.c +++ b/src/exec.c @@ -1,7 +1,13 @@ /** @file */ #include "exec.h" #include "disk.h" +#include "struct.h" +#include #include +#include + +const char *cmd_list[] = {"ls", "touch", "df", "rm", "rmdir", + "cat", "echo", "cd", 0}; int do_cd(disk *d, char *path) { char full_path[1024] = {0}; @@ -33,7 +39,7 @@ int do_cd(disk *d, char *path) { int do_echo(char **args) { if (args[0] == NULL) { - printf("\n"); + dprintf(STDOUT_FILENO, "\n"); return 1; } @@ -77,11 +83,11 @@ int do_echo(char **args) { } result[pos] = '\0'; - printf("%s\n", result); + dprintf(STDOUT_FILENO, "%s\n", result); return 1; } -int child_process_job(disk *d, char **args) { +int exec_cmd_job(disk *d, char **args) { if (strcmp("ls", args[0]) == 0) { do_ls(d, args[1]); } else if (strcmp("mkdir", args[0]) == 0) { @@ -94,42 +100,74 @@ int child_process_job(disk *d, char **args) { do_df(d); } else if (strcmp("rm", args[0]) == 0) { do_rm(d, args[1]); + persist_on_disk(d); } else if (strcmp("rmdir", args[0]) == 0) { do_rmdir(d, args[1]); - } else if(strcmp("cat", args[0]) == 0) { + persist_on_disk(d); + } else if (strcmp("cat", args[0]) == 0) { do_cat(d, args[1]); } else { - dprintf(STDERR_FILENO, "%s: no such command\n", args[0]); + dprintf(STDERR_FILENO, "%s: command does not exist\n", args[0]); + return 0; } return 1; } -int execute_cmd(disk *d, char **args) { +int spawn_proc(disk *d, int in, int out, command *cmd) { + int pid; - // cas ou l'utilisateur fait CTRD+D - if (args[0] == NULL) { - printf("\n"); + if ((pid = fork()) == 0) { + signal(SIGINT, SIG_DFL); + + if (out != STDOUT_FILENO) { + dup2(out, STDOUT_FILENO); + close(out); + } + + if (in != STDIN_FILENO) { + dup2(in, STDIN_FILENO); + close(in); + } + + return exec_cmd_job(d, cmd->argv); + } + + return pid; +} + +int execute_cmd(disk *d, command **args) { + + // cas ou l'utilisateur fait CTRD+D + if (args == NULL) { + dprintf(STDOUT_FILENO, "\n"); exit(EXIT_SUCCESS); } - if (strcmp(args[0], "cd") == 0) { - return do_cd(d, args[1]); - } else if (strcmp(args[0], "echo") == 0) { - return do_echo(&args[1]); + int args_len = 0; + + for (args_len = 0; args[args_len] != NULL; args_len++) + ; + + int i; + int in, p[2]; + in = 0; + + for (i = 0; i < args_len - 2; i++) { + pipe(p); + spawn_proc(d, in, p[1], args[i]); + close(p[1]); + in = p[0]; } - int pid = fork(); + spawn_proc(d, in, STDOUT_FILENO, args[i]); - if (pid == 1) { - return -1; + if (in != 0) { + close(in); } - if (pid == 0) { - signal(SIGINT, SIG_DFL); - return child_process_job(d, args); - } else { - int status; - waitpid(pid, &status, WUNTRACED); - } - return 1; + int status; + while (waitpid(-1, &status, WUNTRACED) > 0) + ; + + return status; } \ No newline at end of file diff --git a/src/exec.h b/src/exec.h index 8427e8a..9653ad6 100644 --- a/src/exec.h +++ b/src/exec.h @@ -13,5 +13,4 @@ #include #include -int is_builtin_cmd(char *executable); -int execute_cmd(disk *d, char **args); \ No newline at end of file +int execute_cmd(disk *d, command **args); \ No newline at end of file diff --git a/src/parsing.c b/src/parsing.c index a037f91..495503a 100644 --- a/src/parsing.c +++ b/src/parsing.c @@ -1,19 +1,24 @@ /** @file */ #include "parsing.h" +#include "disk.h" +#include "exec.h" +#include "struct.h" #include +#include +#include #include /** - * @brief Attend que l'utilisateur appuie sur entrée pour récupérer la ligne écrite - * puis la renvoi + * @brief Attend que l'utilisateur appuie sur entrée pour récupérer la ligne + * écrite puis la renvoi * @return La ligne écrite par l'utilisateur */ char *read_line() { char c; int i = 0; - - // buffer overflow attention - char *buffer = malloc(BUFSIZE * sizeof(char)); + int j = 1; + + char *buffer = malloc(j * BUFSIZE * sizeof(char)); if (buffer == NULL) { dprintf(STDERR_FILENO, "Line read buffer allocation error !"); exit(EXIT_FAILURE); @@ -22,6 +27,11 @@ char *read_line() { while (1) { c = getchar(); + if (i == BUFSIZE - 1) { + j++; + buffer = realloc(buffer, j * BUFSIZE); + } + if (c == EOF || c == '\n') { buffer[i] = '\0'; return buffer; @@ -29,17 +39,15 @@ char *read_line() { buffer[i] = c; } i++; - // TODO: realoc quand le buffer est dépassé } } /** - * @brief Sépare une ligne par des espaces (pour la ligne "ls -l" ça va renvoyer {"ls", - * "-l"}) + * @brief * @param char *line la ligne à parser * @return la liste des arguments de la commande */ -char **split_line(char *line) { +command **split_line(char *line) { char **args = malloc(BUFSIZE * sizeof(char *)); int i = 0; if (args == NULL) { @@ -56,7 +64,43 @@ char **split_line(char *line) { } args[i++] = NULL; - return args; + if (args[0] == NULL) { + return NULL; + } + + command **cmd_lines = malloc(sizeof(command *)); + if (cmd_lines == NULL) { + dprintf(STDERR_FILENO, "Command struct allocation error !"); + exit(EXIT_FAILURE); + } + + cmd_lines[0] = malloc(sizeof(command)); + cmd_lines[0]->argv = malloc(sizeof(char *)); + + i = 0; + int idx_cmd = 0; + int nbr_args_in_actual_cmd = 0; + while (args[i] != NULL) { + if (strcmp(args[i], "|") == 0) { + cmd_lines[idx_cmd]->argv[nbr_args_in_actual_cmd + 1] = NULL; + idx_cmd++; + cmd_lines[idx_cmd] = malloc(sizeof(command)); + cmd_lines[idx_cmd]->argv = malloc(sizeof(char *)); + nbr_args_in_actual_cmd = 0; + } else { + cmd_lines[idx_cmd]->argv = + realloc(cmd_lines[idx_cmd]->argv, + (nbr_args_in_actual_cmd + 1) * sizeof(char *)); + cmd_lines[idx_cmd]->argv[nbr_args_in_actual_cmd] = strdup(args[i]); + nbr_args_in_actual_cmd++; + } + + i++; + } + cmd_lines[idx_cmd + 1] = malloc(sizeof(command)); + cmd_lines[idx_cmd + 1] = NULL; + + return cmd_lines; } /** @@ -78,7 +122,7 @@ void shell_loop(disk *disk) { char *hostname = get_env_value("HOST"); char *line; - char **args; + command **args; int status = 1; do { @@ -105,10 +149,10 @@ void signal_handler(int sig) { dprintf(STDOUT_FILENO, "%s@%s %s> ", user, hostname, get_env_value("PWD")); } -void open_seyshell(disk* disk) { - signal(SIGINT, signal_handler); // le processus père ne s'arrête pas quand il y a un SIGINT = sigma boy - env* envs = init_envs(); +void open_seyshell(disk *disk) { + signal(SIGINT, signal_handler); // le processus père ne s'arrête pas quand il + // y a un SIGINT = sigma boy + env *envs = init_envs(); shell_loop(disk); free(envs); } - diff --git a/src/struct.h b/src/struct.h index e60687e..1aeb4d0 100644 --- a/src/struct.h +++ b/src/struct.h @@ -37,4 +37,16 @@ typedef struct disk { } disk; // pour 10 inode qui a 30 blocs de chacun 1024 octets, on a 30720 octets, soit -// 30,7 Ko sur le disque \ No newline at end of file +// 30,7 Ko sur le disque + +typedef struct command { + char **argv; +} command; +/* +ce structure de cette façon : +commands[0].argv[0]: ls +commands[0].argv[1]: -l +commands[1].argv[0]: head +commands[2].argv[0]: tail +commands[2].argv[1]: -4 +*/ \ No newline at end of file