Advertisement
LA77

Untitled

Mar 13th, 2025
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.67 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdbool.h>
  5.  
  6. #define MAX_FILENAME 60
  7. #define MAX_COMMAND_LENGTH 1024
  8.  
  9. /*
  10. The directory structure is represented as a tree of linked lists.
  11.  
  12. root
  13.  |---- dir1 (root --> children)
  14.  |      |---- file1 (dir1 --> children)
  15.  |      |---- file2 (file1 --> next)
  16.  |      |---- file3 (file2 --> mext)
  17.  |
  18.  |---- dir2 (dir1 --> next)
  19. */
  20.  
  21. typedef struct Inode {
  22.     char name[MAX_FILENAME];
  23.     bool is_directory;
  24.     char *content;  
  25.     struct Inode *parent;
  26.     struct Inode *children;
  27.     struct Inode *next;
  28. } Inode;
  29.  
  30. void free_inode(Inode *inode) {
  31.     if (inode->content) {
  32.         free(inode->content);
  33.     }
  34.     free(inode);
  35. }
  36.  
  37. Inode *root;
  38. Inode *cwd;
  39.  
  40. void init_filesystem() {
  41.     root = (Inode *)malloc(sizeof(Inode));
  42.     strcpy(root->name, "/");
  43.     root->is_directory = true;
  44.     root->content = NULL;
  45.     root->parent = root;
  46.     root->children = NULL;
  47.     root->next = NULL;
  48.     cwd = root;
  49. }
  50.  
  51. void shell_loop() {
  52.  
  53.     char command[MAX_COMMAND_LENGTH];
  54.  
  55.     while (1) {
  56.  
  57.         if (!fgets(command, sizeof(command), stdin)) {
  58.             break;  // Exit on EOF
  59.         }
  60.  
  61.         // Remove the newline character if present
  62.         size_t len = strlen(command);
  63.         if (len > 0 && command[len - 1] == '\n') {
  64.             command[len - 1] = '\0';
  65.         }
  66.  
  67.         process_command(command);
  68.     }
  69. }
  70.  
  71.  
  72. // Parse and execte a single command
  73. void process_command(char *command) {
  74.  
  75.     char copy_of_command[MAX_COMMAND_LENGTH];
  76.     memset(copy_of_command, 0, sizeof(copy_of_command));
  77.     strcpy(copy_of_command, command);
  78.  
  79.     char *cmd = strtok(command, " ");
  80.     if (!cmd) return;
  81.     if (strcmp(cmd, "ls") == 0) {
  82.         cmd_ls(strtok(NULL, " "));
  83.     } else if (strcmp(cmd, "cd") == 0) {
  84.         cmd_cd(strtok(NULL, " "));
  85.     } else if (strcmp(cmd, "touch") == 0) {
  86.         cmd_touch(strtok(NULL, " "));
  87.     } else if (strcmp(cmd, "echo") == 0) {
  88.          char *text = NULL;
  89.         char *redirect = NULL;
  90.         char *filename = NULL;
  91.        
  92.         text = strchr(copy_of_command, '"') + 1; // Find '"' and moe to the next character
  93.         char *end_quote = strchr(text, '"'); // Find the end of the string
  94.         *end_quote = '\0';
  95.         redirect = strtok(end_quote + 1, " ");
  96.         filename = strtok(NULL, " ");
  97.        
  98.         bool append = strcmp(redirect, ">>") == 0;
  99.         cmd_echo(text, filename, append);
  100.  
  101.     } else if (strcmp(cmd, "mkdir") == 0) {
  102.         strtok(NULL, " ");
  103.         cmd_mkdir(strtok(NULL, " "));
  104.     } else if (strcmp(cmd, "rm") == 0) {
  105.         cmd_rm(strtok(NULL, " "));
  106.     } else if (strcmp(cmd, "exit") == 0) {
  107.         cmd_exit();
  108.     } else {
  109.         printf("Unknown command: %s\n", cmd);
  110.     }
  111. }
  112.  
  113. // Returns the inode at the provided path. If it does not exist, it will return NULL
  114. Inode* find_inode(char *path) {
  115.     char *path_copy = malloc(strlen(path) + 1);
  116.     strcpy(path_copy, path);
  117.    
  118.     // If the path doesn't start with a / use cwd
  119.     Inode *current = (path_copy[0] == '/') ? root : cwd;
  120.    
  121.     char *path_component = strtok(path_copy, "/");
  122.    
  123.     // A single /
  124.     if (!path_component && path_copy[0] == '/') {
  125.         free(path_copy);
  126.         return root;
  127.     }
  128.    
  129.     while (path_component) {
  130.         if (strcmp(path_component, ".") == 0) {
  131.             // Do nothing
  132.         } else if (strcmp(path_component, "..") == 0) {
  133.             current = current->parent;
  134.         } else {
  135.             // Search for this name in the children
  136.             Inode *child = current->children;
  137.             bool found = false;
  138.            
  139.             while (child) {
  140.                 if (strcmp(child->name, path_component) == 0) {
  141.                     current = child;
  142.                     found = true;
  143.                     break;
  144.                 }
  145.                 child = child->next;
  146.             }
  147.  
  148.             // Inode not found
  149.             if (!found) {
  150.                 free(path_copy);
  151.                 return NULL;
  152.             }
  153.         }
  154.        
  155.         path_component = strtok(NULL, "/");
  156.     }
  157.    
  158.     free(path_copy);
  159.     return current;
  160. }
  161.  
  162. int asciiOrder(const void *a, const void *b) {
  163.     return strcmp(*(const char **)a, *(const char **)b);
  164. }
  165.  
  166. void cmd_ls(char *path) {
  167.     Inode *dir = cwd;
  168.     if (path) {
  169.         dir = find_inode(path);
  170.     }
  171.    
  172.     Inode *current = dir->children;
  173.     int children_len = 0;
  174.     while (current) {
  175.         children_len++;
  176.         current = current->next;
  177.     }
  178.  
  179.     // Store names in an array
  180.     char **names = malloc(children_len* sizeof(char *));
  181.     current = dir->children;
  182.     for (int i = 0; i < children_len; i++) {
  183.         names[i] = current->name;
  184.         current = current->next;
  185.     }
  186.  
  187.     qsort(names, children_len, sizeof(char *), asciiOrder);
  188. }
  189.  
  190. void cmd_cd(char *path) {
  191.     printf("Executing cd\n");
  192. }
  193.  
  194. void cmd_touch(char *filename)
  195. {
  196.     int idx = 0;
  197.     for(int i = 0; i < strlen(filename); ++ i)
  198.     {
  199.         if(filename[i] == '/')
  200.         {
  201.             idx = i;
  202.         }
  203.     }
  204.  
  205.     int st = 0, st2 = 0;
  206.     char s[strlen(filename - 1)], s2[strlen(filename-1)];
  207.     memset(s, 0, sizeof(s));
  208.     for(int i = idx; i < strlen(filename); ++ i)
  209.     {
  210.         s[st++] = filename[i];
  211.     }
  212.     for(int i = 0; i < idx; ++ i)
  213.     {
  214.         s2[st2++] = filename[i];
  215.     }
  216.     s[st] = '\0';
  217.     s2[st2] = '\0';
  218.  
  219.     Inode *current = find_inode(s2);
  220.  
  221.     if(!current)
  222.         current = cwd;
  223.    
  224.     Inode *save_current;
  225.     if(current->next)
  226.         save_current = current->next;
  227.  
  228.     Inode *new_file = (Inode *)malloc(sizeof(Inode));            
  229.     strcpy(new_file->name, s);
  230.     new_file->is_directory = false;
  231.     new_file->content = NULL;
  232.     new_file->parent = current;
  233.     new_file->children = NULL;
  234.     new_file->next = NULL;
  235.  
  236.     current->next = new_file;
  237.     new_file->next;
  238.     exit(0);
  239.    
  240. }
  241.  
  242. void echo_overwrite (char *text, char *filename) {
  243.  
  244.     Inode *file = find_inode(filename);
  245.  
  246.     if (!file) {
  247.         cmd_touch(filename);
  248.         file = find_inode(filename);
  249.     }
  250.  
  251.     if(file->content) {
  252.         free(file->content);
  253.     }
  254.  
  255.     file->content = malloc(strlen(text) + 1);
  256.     strcpy(file->content, text);
  257. }
  258.  
  259. void cmd_echo(char *text, char *filename, bool append) {
  260.     if (!append) {
  261.         echo_overwrite(text, filename);
  262.     }
  263. }
  264.  
  265. void _mkdir (char *dirname) {
  266.     char *path_copy = malloc(strlen(dirname) + 1);
  267.     strcpy(path_copy, dirname);
  268.  
  269.     Inode *current = path_copy[0] == '/' ? root : cwd;
  270.  
  271.     char* path_component = strtok(path_copy, "/");
  272.  
  273.  
  274.     while (path_component) {
  275.         if (strcmp(path_component, ".") == 0) {
  276.             // Do nothing
  277.         } else if (strcmp(path_component, "..") == 0) {
  278.             current = current->parent;
  279.         } else {
  280.             Inode *save_current = current;
  281.  
  282.             // Find the wether the name exists
  283.             while (current && strcmp(current->name, path_component) != 0) {
  284.                 current = current->next;
  285.             }
  286.  
  287.             // Exists
  288.             if (current) {
  289.                 // Go into this directory;
  290.                 current = current->children;
  291.             } else {
  292.                 // Create new directory
  293.                 Inode *new_dir = (Inode *)malloc(sizeof(Inode));
  294.                
  295.                 strcpy(new_dir->name, path_component);
  296.                 new_dir->is_directory = true;
  297.                 new_dir->content = NULL;
  298.                 new_dir->parent = save_current;
  299.                 new_dir->children = NULL;
  300.                 new_dir->next = save_current->children;
  301.                 save_current->children = new_dir;
  302.                
  303.                 current = new_dir;
  304.             }
  305.            
  306.         }
  307.         path_component = strtok(NULL, "/");
  308.     }
  309.    
  310.     free(path_copy);
  311. }
  312.  
  313. void cmd_mkdir(char *dirnames) {
  314.     char *dirnames_copy = malloc(strlen(dirnames) + 1);
  315.     strcpy(dirnames_copy, dirnames);
  316.  
  317.     char *rest;
  318.     char *dirname = strtok_r(dirnames_copy, " ", &rest);
  319.  
  320.     while (dirname) {
  321.         _mkdir(dirname);
  322.         dirname = strtok_r(NULL, " ", &rest);
  323.     }
  324.    
  325.     free(dirnames_copy);
  326. }
  327.  
  328. void remove_from_parent(Inode *inode){
  329.     Inode *parent = inode->parent;
  330.     if (parent) {
  331.         if (parent->children == inode) {
  332.             parent->children = inode->next;
  333.             return;
  334.         }
  335.  
  336.         Inode *sibling = parent->children;
  337.         while (sibling && sibling->next != inode) {
  338.             sibling = sibling->next;
  339.         }
  340.         if (sibling) {
  341.             sibling->next = inode->next;
  342.         }
  343.     }
  344. }
  345.  
  346. void cmd_mv(char *path1, char *path2) {
  347.     Inode   *file1 = find_inode(path1),
  348.             *file2 = find_inode(path2);
  349.    
  350.     // Remove file1 from its current parent's children
  351.     remove_from_parent(file1);
  352.    
  353.     if (!file1->is_directory) {
  354.  
  355.         // If file doesn't exist, create one
  356.         if (!file2) {
  357.             cmd_touch(path2);
  358.             file2 = find_inode(path2);
  359.         }
  360.        
  361.         // Overwrite it's content with file1
  362.         if(file2->content) {
  363.             free(file2->content);
  364.         }
  365.  
  366.         file2->content = file1->content;
  367.  
  368.         free(file1->name);
  369.         free(file1);
  370.     } else {
  371.         cmd_mkdir(path2);
  372.         file2 = find_inode(path2);
  373.  
  374.         file2->children = file1->children;
  375.  
  376.         // Update the children to point to the new parent
  377.         Inode *child = file2->children;
  378.         while (child) {
  379.             child->parent = file2;
  380.             child = child->next;
  381.         }
  382.  
  383.         free(file1->name);
  384.         free(file1);
  385.     }
  386.  
  387. }
  388.  
  389.  
  390. void rm_recursive(Inode *inode) {
  391.     // Base case: if this is not a directory or has no children, just remove it
  392.     if (!inode->is_directory || !inode->children) {
  393.         remove_from_parent(inode);
  394.         free_inode(inode);
  395.         return;
  396.     }
  397.    
  398.     // Recursive case: remove all children first
  399.     Inode *child = inode->children;
  400.     Inode *next;
  401.    
  402.     while (child) {
  403.         next = child->next;  // Save next pointer before we free the child
  404.         rm_recursive(child);
  405.         child = next;
  406.     }
  407.    
  408.     // Now remove the directory itself
  409.     remove_from_parent(inode);
  410.     free_inode(inode);
  411. }
  412.  
  413. void cmd_rm(char *paths) {
  414.     char *paths_copy = malloc(strlen(paths) + 1);
  415.     strcpy(paths_copy, paths);
  416.  
  417.     char path = strtok(paths_copy, " ");
  418.     while (path) {
  419.         rm_recursive(find_inode(path));
  420.         path = strtok(NULL, "/");
  421.     }
  422.      
  423. }
  424. void cmd_exit() {
  425.     cmd_rm("/");
  426.     free(root);
  427.     free(cwd);
  428.     exit(0);
  429. }
  430.  
  431. int main() {
  432.     init_filesystem();
  433.     shell_loop();
  434.     return 0;
  435. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement