Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdbool.h>
- #define MAX_FILENAME 60
- #define MAX_COMMAND_LENGTH 1024
- /*
- The directory structure is represented as a tree of linked lists.
- root
- |---- dir1 (root --> children)
- | |---- file1 (dir1 --> children)
- | |---- file2 (file1 --> next)
- | |---- file3 (file2 --> mext)
- |
- |---- dir2 (dir1 --> next)
- */
- typedef struct Inode {
- char name[MAX_FILENAME];
- bool is_directory;
- char *content;
- struct Inode *parent;
- struct Inode *children;
- struct Inode *next;
- } Inode;
- void free_inode(Inode *inode) {
- if (inode->content) {
- free(inode->content);
- }
- free(inode);
- }
- Inode *root;
- Inode *cwd;
- void init_filesystem() {
- root = (Inode *)malloc(sizeof(Inode));
- strcpy(root->name, "/");
- root->is_directory = true;
- root->content = NULL;
- root->parent = root;
- root->children = NULL;
- root->next = NULL;
- cwd = root;
- }
- void shell_loop() {
- char command[MAX_COMMAND_LENGTH];
- while (1) {
- if (!fgets(command, sizeof(command), stdin)) {
- break; // Exit on EOF
- }
- // Remove the newline character if present
- size_t len = strlen(command);
- if (len > 0 && command[len - 1] == '\n') {
- command[len - 1] = '\0';
- }
- process_command(command);
- }
- }
- // Parse and execte a single command
- void process_command(char *command) {
- char copy_of_command[MAX_COMMAND_LENGTH];
- memset(copy_of_command, 0, sizeof(copy_of_command));
- strcpy(copy_of_command, command);
- char *cmd = strtok(command, " ");
- if (!cmd) return;
- if (strcmp(cmd, "ls") == 0) {
- cmd_ls(strtok(NULL, " "));
- } else if (strcmp(cmd, "cd") == 0) {
- cmd_cd(strtok(NULL, " "));
- } else if (strcmp(cmd, "touch") == 0) {
- cmd_touch(strtok(NULL, " "));
- } else if (strcmp(cmd, "echo") == 0) {
- char *text = NULL;
- char *redirect = NULL;
- char *filename = NULL;
- text = strchr(copy_of_command, '"') + 1; // Find '"' and moe to the next character
- char *end_quote = strchr(text, '"'); // Find the end of the string
- *end_quote = '\0';
- redirect = strtok(end_quote + 1, " ");
- filename = strtok(NULL, " ");
- bool append = strcmp(redirect, ">>") == 0;
- cmd_echo(text, filename, append);
- } else if (strcmp(cmd, "mkdir") == 0) {
- strtok(NULL, " ");
- cmd_mkdir(strtok(NULL, " "));
- } else if (strcmp(cmd, "rm") == 0) {
- cmd_rm(strtok(NULL, " "));
- } else if (strcmp(cmd, "exit") == 0) {
- cmd_exit();
- } else {
- printf("Unknown command: %s\n", cmd);
- }
- }
- // Returns the inode at the provided path. If it does not exist, it will return NULL
- Inode* find_inode(char *path) {
- char *path_copy = malloc(strlen(path) + 1);
- strcpy(path_copy, path);
- // If the path doesn't start with a / use cwd
- Inode *current = (path_copy[0] == '/') ? root : cwd;
- char *path_component = strtok(path_copy, "/");
- // A single /
- if (!path_component && path_copy[0] == '/') {
- free(path_copy);
- return root;
- }
- while (path_component) {
- if (strcmp(path_component, ".") == 0) {
- // Do nothing
- } else if (strcmp(path_component, "..") == 0) {
- current = current->parent;
- } else {
- // Search for this name in the children
- Inode *child = current->children;
- bool found = false;
- while (child) {
- if (strcmp(child->name, path_component) == 0) {
- current = child;
- found = true;
- break;
- }
- child = child->next;
- }
- // Inode not found
- if (!found) {
- free(path_copy);
- return NULL;
- }
- }
- path_component = strtok(NULL, "/");
- }
- free(path_copy);
- return current;
- }
- int asciiOrder(const void *a, const void *b) {
- return strcmp(*(const char **)a, *(const char **)b);
- }
- void cmd_ls(char *path) {
- Inode *dir = cwd;
- if (path) {
- dir = find_inode(path);
- }
- Inode *current = dir->children;
- int children_len = 0;
- while (current) {
- children_len++;
- current = current->next;
- }
- // Store names in an array
- char **names = malloc(children_len* sizeof(char *));
- current = dir->children;
- for (int i = 0; i < children_len; i++) {
- names[i] = current->name;
- current = current->next;
- }
- qsort(names, children_len, sizeof(char *), asciiOrder);
- }
- void cmd_cd(char *path) {
- printf("Executing cd\n");
- }
- void cmd_touch(char *filename)
- {
- int idx = 0;
- for(int i = 0; i < strlen(filename); ++ i)
- {
- if(filename[i] == '/')
- {
- idx = i;
- }
- }
- int st = 0, st2 = 0;
- char s[strlen(filename - 1)], s2[strlen(filename-1)];
- memset(s, 0, sizeof(s));
- for(int i = idx; i < strlen(filename); ++ i)
- {
- s[st++] = filename[i];
- }
- for(int i = 0; i < idx; ++ i)
- {
- s2[st2++] = filename[i];
- }
- s[st] = '\0';
- s2[st2] = '\0';
- Inode *current = find_inode(s2);
- if(!current)
- current = cwd;
- Inode *save_current;
- if(current->next)
- save_current = current->next;
- Inode *new_file = (Inode *)malloc(sizeof(Inode));
- strcpy(new_file->name, s);
- new_file->is_directory = false;
- new_file->content = NULL;
- new_file->parent = current;
- new_file->children = NULL;
- new_file->next = NULL;
- current->next = new_file;
- new_file->next;
- exit(0);
- }
- void echo_overwrite (char *text, char *filename) {
- Inode *file = find_inode(filename);
- if (!file) {
- cmd_touch(filename);
- file = find_inode(filename);
- }
- if(file->content) {
- free(file->content);
- }
- file->content = malloc(strlen(text) + 1);
- strcpy(file->content, text);
- }
- void cmd_echo(char *text, char *filename, bool append) {
- if (!append) {
- echo_overwrite(text, filename);
- }
- }
- void _mkdir (char *dirname) {
- char *path_copy = malloc(strlen(dirname) + 1);
- strcpy(path_copy, dirname);
- Inode *current = path_copy[0] == '/' ? root : cwd;
- char* path_component = strtok(path_copy, "/");
- while (path_component) {
- if (strcmp(path_component, ".") == 0) {
- // Do nothing
- } else if (strcmp(path_component, "..") == 0) {
- current = current->parent;
- } else {
- Inode *save_current = current;
- // Find the wether the name exists
- while (current && strcmp(current->name, path_component) != 0) {
- current = current->next;
- }
- // Exists
- if (current) {
- // Go into this directory;
- current = current->children;
- } else {
- // Create new directory
- Inode *new_dir = (Inode *)malloc(sizeof(Inode));
- strcpy(new_dir->name, path_component);
- new_dir->is_directory = true;
- new_dir->content = NULL;
- new_dir->parent = save_current;
- new_dir->children = NULL;
- new_dir->next = save_current->children;
- save_current->children = new_dir;
- current = new_dir;
- }
- }
- path_component = strtok(NULL, "/");
- }
- free(path_copy);
- }
- void cmd_mkdir(char *dirnames) {
- char *dirnames_copy = malloc(strlen(dirnames) + 1);
- strcpy(dirnames_copy, dirnames);
- char *rest;
- char *dirname = strtok_r(dirnames_copy, " ", &rest);
- while (dirname) {
- _mkdir(dirname);
- dirname = strtok_r(NULL, " ", &rest);
- }
- free(dirnames_copy);
- }
- void remove_from_parent(Inode *inode){
- Inode *parent = inode->parent;
- if (parent) {
- if (parent->children == inode) {
- parent->children = inode->next;
- return;
- }
- Inode *sibling = parent->children;
- while (sibling && sibling->next != inode) {
- sibling = sibling->next;
- }
- if (sibling) {
- sibling->next = inode->next;
- }
- }
- }
- void cmd_mv(char *path1, char *path2) {
- Inode *file1 = find_inode(path1),
- *file2 = find_inode(path2);
- // Remove file1 from its current parent's children
- remove_from_parent(file1);
- if (!file1->is_directory) {
- // If file doesn't exist, create one
- if (!file2) {
- cmd_touch(path2);
- file2 = find_inode(path2);
- }
- // Overwrite it's content with file1
- if(file2->content) {
- free(file2->content);
- }
- file2->content = file1->content;
- free(file1->name);
- free(file1);
- } else {
- cmd_mkdir(path2);
- file2 = find_inode(path2);
- file2->children = file1->children;
- // Update the children to point to the new parent
- Inode *child = file2->children;
- while (child) {
- child->parent = file2;
- child = child->next;
- }
- free(file1->name);
- free(file1);
- }
- }
- void rm_recursive(Inode *inode) {
- // Base case: if this is not a directory or has no children, just remove it
- if (!inode->is_directory || !inode->children) {
- remove_from_parent(inode);
- free_inode(inode);
- return;
- }
- // Recursive case: remove all children first
- Inode *child = inode->children;
- Inode *next;
- while (child) {
- next = child->next; // Save next pointer before we free the child
- rm_recursive(child);
- child = next;
- }
- // Now remove the directory itself
- remove_from_parent(inode);
- free_inode(inode);
- }
- void cmd_rm(char *paths) {
- char *paths_copy = malloc(strlen(paths) + 1);
- strcpy(paths_copy, paths);
- char path = strtok(paths_copy, " ");
- while (path) {
- rm_recursive(find_inode(path));
- path = strtok(NULL, "/");
- }
- }
- void cmd_exit() {
- cmd_rm("/");
- free(root);
- free(cwd);
- exit(0);
- }
- int main() {
- init_filesystem();
- shell_loop();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement