shell and ls command

This commit is contained in:
Guamss 2026-04-27 16:46:30 +02:00
parent ba12753402
commit a43436b20b
12 changed files with 203 additions and 75 deletions

View File

@ -1,7 +1,7 @@
NAME := seyshell
DRIVE := disk
CC := gcc
CFLAGS :=
CFLAGS := -Wall -Wextra -Werror -g
OBJ_DIR := obj
SRC_DIR := src

View File

@ -7,6 +7,5 @@
#define TYPE_NULL 0
#define TYPE_FILE 1
#define TYPE_BINARY 2
#define TYPE_DIRECTORY 3
#define TYPE_SYMBOLIC_LINK 4

View File

@ -1,5 +1,6 @@
/** @file */
#include "disk.h"
#include "env.h"
#include "struct.h"
#include <stdio.h>
#include <stdlib.h>
@ -48,15 +49,12 @@ int find_offset_in_parent_bloc(bloc *parent_bloc) {
return -1;
}
int create_directory(disk *disk, inode *parent, char *dirname) {}
int create_file(disk *disk, inode *parent, char *filename) {
int allocate_node(disk *disk, inode *parent, char *name, char type) {
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;
@ -70,46 +68,42 @@ int create_file(disk *disk, inode *parent, char *filename) {
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);
strncpy(&disk->blocs[p_bloc_idx].datas[offset], name, 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);
init_inode_in_disk(disk, inode_index, type, 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;
}
int create_file(disk *disk, inode *parent, char *filename) {
return allocate_node(disk, parent, filename, TYPE_FILE);
}
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;
int create_directory(disk *disk, inode *parent, char *dirname) {
int new_idx = allocate_node(disk, parent, dirname, TYPE_DIRECTORY);
if (new_idx == -1)
return -1;
int bloc_idx = disk->inodes[new_idx].blocs[0];
int entry_size = MAX_INODE_NAME + sizeof(int);
int p_idx = (int)(parent - disk->inodes);
strncpy(&disk->blocs[bloc_idx].datas[0], ".", MAX_INODE_NAME);
memcpy(&disk->blocs[bloc_idx].datas[MAX_INODE_NAME], &new_idx, sizeof(int));
strncpy(&disk->blocs[bloc_idx].datas[entry_size], "..", MAX_INODE_NAME);
memcpy(&disk->blocs[bloc_idx].datas[entry_size + MAX_INODE_NAME], &p_idx,
sizeof(int));
return new_idx;
}
void write_in_file(disk *d, int file_index, char *data /*, char mode*/) {
@ -133,15 +127,60 @@ void write_in_file(disk *d, int file_index, char *data /*, char mode*/) {
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;
int find_dir_inode_by_name(char *name, int dir_index, disk *d) {
int bloc = d->inodes[dir_index].blocs[0];
for (int i = 0; i < MAX_BYTES_PER_BLOC; i += MAX_INODE_NAME + sizeof(int)) {
char inode_name[MAX_INODE_NAME];
strncpy(inode_name, &d->blocs[bloc].datas[i], MAX_INODE_NAME);
if (strcmp(name, inode_name) == 0) {
int inode_id;
memcpy(&inode_id, &d->blocs[bloc].datas[i + MAX_INODE_NAME], sizeof(int));
return inode_id;
}
}
// TODO: chercher sur tous les blocs possédés
int bloc = dir.blocs[0];
return -1;
}
int do_ls(disk *d, char *path) {
char *path_to_process;
if (path == NULL) {
path_to_process = strdup(get_env_value("PWD"));
} else {
path_to_process = strdup(path);
}
int dir_index = 0;
char *token = strtok(path_to_process, "/");
while (token != NULL) {
dir_index = find_dir_inode_by_name(token, dir_index, d);
if (dir_index == -1) {
dprintf(STDERR_FILENO, "ls: This directory does not exist\n");
free(path_to_process);
return -1;
}
if (d->inodes[dir_index].filetype != TYPE_DIRECTORY) {
dprintf(STDERR_FILENO, "ls: '%s' is not a directory\n", token);
free(path_to_process);
return -1;
}
token = strtok(NULL, "/");
}
inode dir_to_list = d->inodes[dir_index];
int bloc = dir_to_list.blocs[0];
if (bloc == -1) {
free(path_to_process);
return 1;
}
for (int i = 0; i < MAX_BYTES_PER_BLOC; i += MAX_INODE_NAME + sizeof(int)) {
if (d->blocs[bloc].datas[i] != '\0') {
@ -150,6 +189,9 @@ void do_ls(disk *d, int dir_index) {
dprintf(STDOUT_FILENO, "%-16s %d\n", &d->blocs[bloc].datas[i], inode_id);
}
}
free(path_to_process);
return 1;
}
char *read_in_file(disk *d, int file_index) {
@ -163,7 +205,8 @@ char *read_in_file(disk *d, int file_index) {
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) {
while (d->blocs[bloc].datas[c_index] != '\0' ||
c_index < MAX_BYTES_PER_BLOC) {
c_index++;
}
@ -178,9 +221,11 @@ char *read_in_file(disk *d, int file_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");
void init_test_files(disk *d) {
int inode_idx = create_file(d, &d->inodes[0], "test");
write_in_file(d, inode_idx, "Contenu du fichier :)\n");
int dir_idx = create_directory(d, &d->inodes[0], "dir");
create_file(d, &d->inodes[dir_idx], "test1");
}
/**
@ -211,7 +256,7 @@ disk create_disk() {
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);
init_test_files(&d);
int n = fwrite(&d, sizeof(disk), 1, fptr);
if (n == 1) {

View File

@ -5,7 +5,8 @@
#include "const.h"
#include "struct.h"
#include <string.h>
#include "env.h"
disk create_disk();
disk open_disk(char* filename);
void do_ls(disk *d, int dir_index);
int do_ls(disk *d, char* path);

47
src/env.c Normal file
View File

@ -0,0 +1,47 @@
#include "env.h"
env *init_envs() {
env *envs = malloc(sizeof(env) * 3);
if (envs == NULL)
return NULL;
envs[0].key = "PWD";
envs[0].value = "/";
envs[1].key = "USER";
envs[1].value = "guams";
envs[2].key = "HOST";
envs[2].value = "tartempion";
return envs;
}
env *get_instance() {
static env *instance = NULL;
if (instance == NULL) {
instance = init_envs();
}
return instance;
}
int get_env_len(env *envs) {
int i = 0;
while (envs[i].key != NULL) {
i++;
}
return i;
}
char *get_env_value(char *key) {
env *envs = get_instance();
for (int i = 0; i < get_env_len(envs); i++) {
if (strcmp(envs[i].key, key) == 0) {
return envs[i].value;
}
}
return NULL;
}

8
src/env.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include "struct.h"
#include <stdlib.h>
#include <string.h>
char* get_env_value(char* key);
int get_env_len(env *envs);
env* init_envs();

View File

@ -1,18 +1,13 @@
/** @file */
#include "exec.h"
#include "disk.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
// TODO : Tout ce fichier est à changer je pense
int is_builtin_cmd(char *executable) {
(void)executable;
return 0;
}
// à changer parce que je veux pas chercher dans le PATH, je veux juste executer
// les futures primitives qui seront implémentées
int execute_cmd(char **args) {
/*int execute_cmd(char **args) {
if (!is_builtin_cmd(args[0])) {
int pid = fork();
if (pid == -1)
@ -30,4 +25,28 @@ int execute_cmd(char **args) {
}
}
return 1;
}
*/
int child_process_job(disk *d, char **args) {
if (strcmp("ls", args[0]) == 0) {
do_ls(d, args[1]);
}
return 1;
}
int execute_cmd(disk *d, char **args) {
int pid = fork();
if (pid == 1) {
return -1;
}
if (pid == 0) {
child_process_job(d, args);
} else {
int status;
waitpid(pid, &status, WUNTRACED);
}
return 1;
}

View File

@ -1,7 +1,8 @@
/** @file */
#pragma once
#include "disk.h"
#include <stdio.h>
#include <sys/wait.h>
int is_builtin_cmd(char *executable);
int execute_cmd(char **args);
int execute_cmd(disk *d, char **args);

View File

@ -1,24 +1,17 @@
/** @file */
#include "disk.h"
#include "parsing.h"
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[], char *envp[]) {
(void)argc;
(void)argv;
(void)envp;
// shell_loop();
int main() {
disk drive;
if (access("disk", F_OK) == 0) {
drive = open_disk("disk");
do_ls(&drive, 0);
} else
drive = create_disk();
(void)drive;
open_seyshell(&drive);
return EXIT_SUCCESS;
}

View File

@ -1,6 +1,7 @@
/** @file */
#include "parsing.h"
#include "const.h"
#include "env.h"
#include "exec.h"
#include <stdio.h>
#include <stdlib.h>
@ -15,6 +16,8 @@
char *read_line() {
char c;
int i = 0;
// buffer overflow attention
char *buffer = malloc(BUFSIZE * sizeof(char));
if (buffer == NULL) {
dprintf(STDERR_FILENO, "Line read buffer allocation error !");
@ -70,15 +73,14 @@ char **split_line(char *line) {
* @see char** split_line(char *line)
* @see int execute_cmd(char **args)
*/
void shell_loop(void) {
char *user = getenv("USER");
void shell_loop(disk *disk) {
char *user = get_env_value("USER");
char *hostname = malloc(BUFSIZE * sizeof(char));
if (hostname == NULL) {
dprintf(STDERR_FILENO, "Allocation error");
if (user == NULL) {
exit(EXIT_FAILURE);
}
// sur le sgf le hostname se récupèrera pas comme ça donc à changer :)
gethostname(hostname, sizeof(hostname));
char *hostname = get_env_value("HOST");
char *line;
char **args;
@ -86,13 +88,19 @@ void shell_loop(void) {
do {
// ça aussi c'est pas bien, ça sera à changer une fois le sgf fonctionnel
dprintf(STDOUT_FILENO, "%s@%s %s> ", user, hostname, getenv("PWD"));
dprintf(STDOUT_FILENO, "%s@%s %s> ", user, hostname, get_env_value("PWD"));
line = read_line();
args = split_line(line);
status = execute_cmd(args);
status = execute_cmd(disk, args);
free(line);
free(args);
} while (status);
}
void open_seyshell(disk* disk) {
env* envs = init_envs();
shell_loop(disk);
free(envs);
}

View File

@ -1,7 +1,9 @@
/** @file */
#pragma once
#include "env.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "struct.h"
void shell_loop(void);
void open_seyshell(disk* disk);

View File

@ -2,6 +2,11 @@
#pragma once
#include "const.h"
typedef struct env {
char* key;
char* value;
} env;
/**
* @struct inode
* @brief Un inode est un fichier, il possède des permissions, un type