Advertisement
LA77

Untitled

Mar 15th, 2025
582
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 27.74 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 65
  7.  
  8. typedef struct SharedContent {
  9.     char *data;
  10.     int refcount;
  11. } SharedContent;
  12.  
  13. typedef struct Inode {
  14.     char name[MAX_FILENAME];
  15.     bool is_directory;
  16.     bool is_symlink;
  17.     SharedContent *shared;
  18.     struct Inode *parent;
  19.     struct Inode *children;
  20.     struct Inode *next;
  21. } Inode;
  22.  
  23. Inode *root;
  24. Inode *cwd;
  25.  
  26. void init_filesystem(void);
  27. void free_inode(Inode *inode);
  28. SharedContent* create_shared_content(const char *initial);
  29. Inode* find_inode_no_symlink(const char *path);
  30. Inode* find_inode_follow(const char *path);
  31. void cmd_ls(char *path);
  32. void cmd_cd(char *path);
  33. void cmd_cat(char *filePath);
  34. void cmd_echo(char *text, char *filename, bool append);
  35. void cmd_touch_single(char *filename);
  36. void cmd_touch(char *args);
  37. void cmd_mkdir(char *args);
  38. void cmd_rm(char *params);
  39. void cmd_find(Inode *dir, const char *path);
  40. void cmd_ln(char *path1, char *path2, bool hard);
  41. void cmd_ln_symlink(char *targetPath, char *linkPath);
  42. void cmd_cp(char *s1, char *s2, bool recursive);
  43. void cmd_mv(char *path1, char *path2);
  44. void process_command(char *command);
  45. void shell_loop(void);
  46.  
  47.  
  48. void init_filesystem() {
  49.     root = (Inode*)calloc(1, sizeof(Inode));
  50.     // Root’s name can be just "/"
  51.     strncpy(root->name, "/", MAX_FILENAME - 1);
  52.     root->name[MAX_FILENAME - 1] = '\0';
  53.     root->is_directory = true;
  54.     root->is_symlink   = false;
  55.     root->shared       = NULL;
  56.     root->parent       = root;  
  57.  
  58.     cwd = root;
  59. }
  60.  
  61. void free_inode(Inode *inode) {
  62.  
  63.     if (inode->shared) {
  64.         inode->shared->refcount--;
  65.         if (inode->shared->refcount <= 0) {
  66.             free(inode->shared->data);
  67.             free(inode->shared);
  68.         }
  69.     }
  70.     free(inode);
  71. }
  72.  
  73. SharedContent* create_shared_content(const char *initial) {
  74.     SharedContent *sc = (SharedContent*)malloc(sizeof(SharedContent));
  75.     sc->refcount = 1;
  76.     if (initial) {
  77.         sc->data = (char*)malloc(strlen(initial) + 1);
  78.         strcpy(sc->data, initial);
  79.     } else {
  80.         sc->data = NULL;
  81.     }
  82.     return sc;
  83. }
  84.  
  85. static void remove_from_parent(Inode *inode);
  86. static void rm_recursive(Inode *inode);
  87.  
  88.  
  89. static void remove_from_parent(Inode *inode) {
  90.     if (!inode || !inode->parent) return;
  91.     Inode *p = inode->parent;
  92.  
  93.     // If it’s the first child
  94.     if (p->children == inode) {
  95.         p->children = inode->next;
  96.     } else {
  97.         // Otherwise find it
  98.         Inode *cur = p->children;
  99.         while (cur && cur->next != inode) {
  100.             cur = cur->next;
  101.         }
  102.         if (cur) {
  103.             cur->next = inode->next;
  104.         }
  105.     }
  106.     inode->parent = NULL;
  107.     inode->next   = NULL;
  108. }
  109.  
  110. static void rm_recursive(Inode *inode) {
  111.     if (!inode) return;
  112.  
  113.     // If directory with children, remove them first
  114.     if (inode->is_directory && inode->children) {
  115.         Inode *child = inode->children;
  116.         while (child) {
  117.             Inode *nxt = child->next;
  118.             rm_recursive(child);
  119.             child = nxt;
  120.         }
  121.     }
  122.  
  123.     if(inode == cwd)
  124.     {
  125.         cwd = root;
  126.     }
  127.  
  128.     remove_from_parent(inode);
  129.     free_inode(inode);
  130. }
  131.  
  132.  
  133. static Inode* linear_find_child(Inode *parent, const char *name) {
  134.     if (!parent->is_directory) return NULL;
  135.     Inode *child = parent->children;
  136.     while (child) {
  137.         if (strcmp(child->name, name) == 0) {
  138.             return child;
  139.         }
  140.         child = child->next;
  141.     }
  142.     return NULL;
  143. }
  144.  
  145.  
  146. Inode* find_inode_no_symlink(const char *path) {
  147.     if (!path) return NULL;
  148.     if (!*path) return cwd;  
  149.  
  150.     // Make a copy for strtok
  151.     char *path_copy = (char*)malloc(strlen(path) + 1);
  152.     strcpy(path_copy, path);
  153.  
  154.     // If path starts with '/', we begin at root, else at cwd
  155.     Inode *current = (path_copy[0] == '/') ? root : cwd;
  156.  
  157.     // Tokenize
  158.     char *component = strtok(path_copy, "/");
  159.     if (!component && path_copy[0] == '/') {
  160.         free(path_copy);
  161.         return root;
  162.     }
  163.  
  164.     while (component) {
  165.         if (strcmp(component, ".") == 0) {
  166.             // stay
  167.         } else if (strcmp(component, "..") == 0) {
  168.             if (current != root)
  169.                 current = current->parent;
  170.         } else {
  171.             // find a child
  172.             Inode *child = linear_find_child(current, component);
  173.             if (!child) {
  174.                 free(path_copy);
  175.                 return NULL;
  176.             }
  177.             current = child;
  178.         }
  179.         component = strtok(NULL, "/");
  180.     }
  181.     free(path_copy);
  182.     return current;
  183. }
  184.  
  185. // Like find_inode_no_symlink but if the final Inode is a symlink, follow it repeatedly (up to 100).
  186. Inode* find_inode_follow(const char *path) {
  187.     if (!path) return NULL;
  188.     Inode *node = find_inode_no_symlink(path);
  189.     if (!node) return NULL;
  190.  
  191.     int symlink_depth = 0;
  192.     while (node->is_symlink) {
  193.         if (!node->shared || !node->shared->data) {
  194.             // broken symlink
  195.             return NULL;
  196.         }
  197.         if (++symlink_depth > 100) {
  198.             // protect from infinite loops
  199.             return NULL;
  200.         }
  201.        
  202.         char *linkTarget = node->shared->data;
  203.         bool isAbs = (linkTarget[0] == '/');
  204.         Inode *startDir = isAbs ? root : node->parent;
  205.  
  206.         // temporarily treat startDir as "cwd"
  207.         Inode *oldCwd = cwd;
  208.         cwd = startDir;
  209.         Inode *resolved = find_inode_no_symlink(linkTarget);
  210.         cwd = oldCwd;
  211.         if (!resolved) return NULL;
  212.         node = resolved;
  213.     }
  214.     return node;
  215. }
  216.  
  217. static int cstring_cmp(const void *p1, const void *p2) {
  218.     const char *s1 = *(const char **)p1;
  219.     const char *s2 = *(const char **)p2;
  220.     return strcmp(s1, s2);
  221. }
  222.  
  223. static int inode_name_cmp(const void *p1, const void *p2) {
  224.     const Inode *i1 = *(const Inode **)p1;
  225.     const Inode *i2 = *(const Inode **)p2;
  226.     return strcmp(i1->name, i2->name);
  227. }
  228.  
  229. // ----------------------------------------------------------------
  230. // Commands
  231. // ----------------------------------------------------------------
  232.  
  233. void cmd_ls(char *path) {
  234.     Inode *dir = cwd;
  235.     if (path && *path) {
  236.         Inode *maybe = find_inode_follow(path);
  237.         if (!maybe) return; // invalid path => no output
  238.         if (!maybe->is_directory) {
  239.            
  240.             printf("%s\n", maybe->name);
  241.             return;
  242.         }
  243.         dir = maybe;
  244.     }
  245.     // Count children
  246.     int count = 0;
  247.     Inode *child = dir->children;
  248.     while (child) {
  249.         count++;
  250.         child = child->next;
  251.     }
  252.     if (count == 0) return;
  253.  
  254.     // Gather child->name in array
  255.     char **names = (char**)malloc(count * sizeof(char*));
  256.     child = dir->children;
  257.     for (int i=0; i<count; i++) {
  258.         names[i] = child->name;
  259.         child = child->next;
  260.     }
  261.     qsort(names, count, sizeof(char*), cstring_cmp);
  262.  
  263.     for (int i=0; i<count; i++) {
  264.         printf("%s\n", names[i]);
  265.     }
  266.     free(names);
  267. }
  268.  
  269. void cmd_cd(char *path) {
  270.     if (!path || !*path) {
  271.         // cd with no args => go to root
  272.         cwd = root;
  273.         return;
  274.     }
  275.     Inode *dest = find_inode_follow(path);
  276.     if (dest && dest->is_directory) {
  277.         cwd = dest;
  278.     }
  279. }
  280.  
  281. void cmd_cat(char *filePath) {
  282.     if (!filePath) return;
  283.     Inode *f = find_inode_follow(filePath);
  284.     if (!f) return;  // doesn’t exist
  285.     if (f->is_directory) return; // cat on a directory => do nothing
  286.     if (f->shared && f->shared->data) {
  287.         printf("%s\n", f->shared->data);
  288.     }
  289. }
  290.  
  291. // Helper for echo overwrite
  292. static void echo_overwrite(char *text, char *filename) {
  293.     if (!text || !filename) return;
  294.     Inode *f = find_inode_follow(filename);
  295.     if (!f) {
  296.        
  297.         Inode *maybe = find_inode_no_symlink(filename);
  298.         if (!maybe) {
  299.  
  300.             cmd_touch_single(filename);
  301.             f = find_inode_follow(filename);
  302.             if (!f) return;
  303.         } else {
  304.            
  305.             return;
  306.         }
  307.     }
  308.     if (f->is_directory) return;
  309.  
  310.     if (!f->shared) {
  311.         f->shared = create_shared_content(NULL);
  312.     } else if (f->shared->data) {
  313.         free(f->shared->data);
  314.         f->shared->data = NULL;
  315.     }
  316.     f->shared->data = (char*)malloc(strlen(text)+1);
  317.     strcpy(f->shared->data, text);
  318. }
  319.  
  320. static void echo_add(char *text, char *filename) {
  321.     if (!text || !filename) return;
  322.     Inode *f = find_inode_follow(filename);
  323.     if (!f) {
  324.         Inode *maybe = find_inode_no_symlink(filename);
  325.         if (!maybe) {
  326.             cmd_touch_single(filename);
  327.             f = find_inode_follow(filename);
  328.             if (!f) return;
  329.         } else {
  330.             return;
  331.         }
  332.     }
  333.     if (f->is_directory) return;
  334.  
  335.     if (!f->shared) {
  336.         f->shared = create_shared_content(NULL);
  337.     }
  338.     if (!f->shared->data) {
  339.         f->shared->data = (char*)malloc(strlen(text)+1);
  340.         strcpy(f->shared->data, text);
  341.     } else {
  342.         size_t oldlen = strlen(f->shared->data);
  343.         size_t newlen = oldlen + strlen(text) + 1;
  344.         char *new_data = (char*)realloc(f->shared->data, newlen);
  345.         if (!new_data) {
  346.            
  347.             free(f->shared->data);
  348.             f->shared->data = NULL;
  349.             return;
  350.         }
  351.         f->shared->data = new_data;
  352.         strcat(f->shared->data, text);
  353.     }
  354. }
  355.  
  356. void cmd_echo(char *text, char *filename, bool append) {
  357.     if (!text || !filename) return;
  358.     if (!append) {
  359.         echo_overwrite(text, filename);
  360.     } else {
  361.         echo_add(text, filename);
  362.     }
  363. }
  364.  
  365. void cmd_touch_single(char *filename) {
  366.     if (!filename || !*filename) return;
  367.     Inode *exists = find_inode_no_symlink(filename);
  368.     if (exists) return;
  369.  
  370.     int idx = -1;
  371.     size_t len = strlen(filename);
  372.     for (size_t i = 0; i < len; i++) {
  373.         if (filename[i] == '/') idx = i;
  374.     }
  375.  
  376.     char *dir_path = NULL;
  377.     char *base_name = NULL;
  378.     if (idx != -1) {
  379.         if (idx == 0) {
  380.             dir_path = strdup("/");
  381.         } else {
  382.             dir_path = (char*)malloc(idx + 1);
  383.             if (dir_path) {
  384.                 strncpy(dir_path, filename, idx);
  385.                 dir_path[idx] = '\0';
  386.             }
  387.         }
  388.         base_name = strdup(filename + idx + 1);
  389.     } else {
  390.         dir_path = strdup("");
  391.         base_name = strdup(filename);
  392.     }
  393.  
  394.     Inode *parent_dir = find_inode_no_symlink(dir_path);
  395.     if (!parent_dir) {
  396.         parent_dir = cwd;
  397.     }
  398.     if (!parent_dir->is_directory) {
  399.         free(dir_path);
  400.         free(base_name);
  401.         return;
  402.     }
  403.  
  404.     Inode *newf = (Inode*)malloc(sizeof(Inode));
  405.     memset(newf, 0, sizeof(Inode));
  406.     strncpy(newf->name, base_name, MAX_FILENAME - 1);
  407.     newf->name[MAX_FILENAME - 1] = '\0';
  408.     newf->is_directory = false;
  409.     newf->is_symlink   = false;
  410.     newf->shared       = create_shared_content(NULL);
  411.     newf->parent       = parent_dir;
  412.  
  413.     newf->next = parent_dir->children;
  414.     parent_dir->children = newf;
  415.  
  416.     free(dir_path);
  417.     free(base_name);
  418. }
  419.  
  420.  
  421. void cmd_touch(char *args) {
  422.     if (!args || !*args) return;
  423.     char *args_copy = strdup(args);
  424.     char *save;
  425.     char *token = strtok_r(args_copy, " ", &save);
  426.     while (token) {
  427.         cmd_touch_single(token);
  428.         token = strtok_r(NULL, " ", &save);
  429.     }
  430.     free(args_copy);
  431. }
  432.  
  433. void _mkdir(char *dirname) {
  434.  
  435.     char *copy = malloc((strlen(dirname) + 1) * sizeof(char));
  436.     strcpy(copy, dirname);
  437.  
  438.     Inode *current = (copy[0] == '/') ? root : cwd;
  439.     char *save;
  440.     char *component = strtok_r(copy, "/", &save);
  441.     while (component) {
  442.         if (strcmp(component, ".") == 0) {
  443.         } else if (strcmp(component, "..") == 0) {
  444.             if (current != root) current = current->parent;
  445.         } else {
  446.  
  447.             Inode *scan = current->children;
  448.             Inode *found = NULL;
  449.             while (scan) {
  450.                 if (scan->is_directory && strcmp(scan->name, component) == 0) {
  451.                     found = scan;
  452.                     break;
  453.                 }
  454.                 scan = scan->next;
  455.             }
  456.             if (found) {
  457.                 current = found;
  458.             } else {
  459.                 Inode *newd = (Inode*)calloc(1, sizeof(Inode));
  460.  
  461.                 strncpy(newd->name, component, MAX_FILENAME - 1);
  462.                 newd->name[MAX_FILENAME - 1] = '\0';
  463.                 newd->is_directory = true;
  464.                 newd->is_symlink   = false;
  465.                 newd->parent       = current;
  466.                 newd->next         = current->children;
  467.                 current->children  = newd;
  468.                 current = newd;
  469.             }
  470.         }
  471.         component = strtok_r(NULL, "/", &save);
  472.     }
  473.     free(copy);
  474. }
  475.  
  476. void cmd_mkdir(char *args) {
  477.  
  478.     char *copy = malloc((strlen(args) + 1) * sizeof(char));
  479.     strcpy(copy, args);
  480.     char *save;
  481.     char *token = strtok_r(copy, " ", &save);
  482.     while (token) {
  483.  
  484.         if (strcmp(token, "-p") == 0) {
  485.         } else {
  486.             _mkdir(token);
  487.         }
  488.         token = strtok_r(NULL, " ", &save);
  489.     }
  490.     free(copy);
  491. }
  492.  
  493. void cmd_rm(char *params) {
  494.     if (!params || !*params) return;
  495.     char *copy = strdup(params);
  496.     char *p = copy;
  497.     while (*p == ' ') p++;
  498.  
  499.     bool recursive_flag = false;
  500.     if (strncmp(p, "-r", 2) == 0 && (p[2] == ' ' || p[2] == '\0')) {
  501.         recursive_flag = true;
  502.         p += 2;
  503.         while (*p == ' ') p++;
  504.     }
  505.  
  506.     while (*p) {
  507.         char *start = p;
  508.         while (*p && *p != ' ') p++;
  509.         bool ended = false;
  510.         if (*p == ' ') {
  511.             *p = '\0';
  512.             p++;
  513.             ended = true;
  514.         }
  515.         if (*start) {
  516.  
  517.             Inode *target = find_inode_no_symlink(start);
  518.             if (target) {
  519.                 if (target->is_directory && !recursive_flag) {
  520.  
  521.                 } else {
  522.                     rm_recursive(target);
  523.                 }
  524.             }
  525.         }
  526.         while (*p == ' ') p++;
  527.         if (!ended && !*p) break;
  528.     }
  529.     free(copy);
  530. }
  531.  
  532.  
  533. void cmd_find(Inode *dir, const char *path) {
  534.     if (!dir || !path) return;
  535.  
  536.     if (strcmp(path, ".") == 0) {
  537.         printf(".\n");
  538.     }
  539.  
  540.     int count = 0;
  541.     Inode *child = dir->children;
  542.     while (child) {
  543.         count++;
  544.         child = child->next;
  545.     }
  546.     if (count == 0) return;
  547.  
  548.     Inode **arr = (Inode**)malloc(count * sizeof(Inode*));
  549.     child = dir->children;
  550.     for (int i = 0; i < count; i++) {
  551.         arr[i] = child;
  552.         child = child->next;
  553.     }
  554.     qsort(arr, count, sizeof(Inode*), inode_name_cmp);
  555.  
  556.     for (int i = 0; i < count; i++) {
  557.         Inode *c = arr[i];
  558.         size_t new_path_len = strlen(path) + 1 /* for "/" */ + strlen(c->name) + 1;
  559.         char *new_path = (char*)malloc(new_path_len);
  560.         if (!new_path) continue;
  561.         snprintf(new_path, new_path_len, "%s/%s", path, c->name);
  562.         printf("%s\n", new_path);
  563.         if (c->is_directory) {
  564.             cmd_find(c, new_path);
  565.         }
  566.         free(new_path);
  567.     }
  568.     free(arr);
  569. }
  570.  
  571. void cmd_ln(char *path1, char *path2, bool hard) {
  572.     // (void)hard;  // unused, but you can keep this line if needed
  573.     if (!path1 || !path2) return;
  574.  
  575.     Inode *source = find_inode_no_symlink(path1);
  576.     if (!source) return;
  577.     if (source->is_directory) {
  578.         return;  // The assignment disallows creating hard links to directories
  579.     }
  580.    
  581.     // Find the slash position
  582.     int idx = -1;
  583.     int len = strlen(path2);
  584.     for (int i = 0; i < len; i++) {
  585.         if (path2[i] == '/') idx = (int)i;
  586.     }
  587.    
  588.     // Allocate dir_path / base_name dynamically
  589.     char *dir_path = NULL;
  590.     char *base_name = NULL;
  591.  
  592.     if (idx != -1) {
  593.         // path2 has at least one slash
  594.         if (idx == 0) {
  595.             // Leading slash => parent directory is "/"
  596.             dir_path = strdup("/");
  597.         } else {
  598.             // Copy everything up to idx
  599.             dir_path = (char*)malloc(idx + 1);
  600.             strncpy(dir_path, path2, idx);
  601.             dir_path[idx] = '\0';
  602.         }
  603.         base_name = strdup(path2 + idx + 1);
  604.     } else {
  605.         // No slash => parent directory is "."
  606.         dir_path = strdup(".");
  607.         base_name = strdup(path2);
  608.     }
  609.  
  610.     Inode *parent_dir = find_inode_no_symlink(dir_path);
  611.     // If parent_dir does not exist, fallback to cwd
  612.     if (!parent_dir) {
  613.         parent_dir = cwd;
  614.     }
  615.     if (!parent_dir->is_directory) {
  616.         free(dir_path);
  617.         free(base_name);
  618.         return;
  619.     }
  620.  
  621.     // Create the new hard link inode
  622.     Inode *new_link = (Inode*)calloc(1, sizeof(Inode));
  623.     strncpy(new_link->name, base_name, MAX_FILENAME - 1);
  624.     new_link->name[MAX_FILENAME - 1] = '\0';
  625.     new_link->is_directory = false;
  626.     new_link->is_symlink   = false;
  627.     new_link->shared       = source->shared;  // share the file data
  628.     if (new_link->shared) {
  629.         new_link->shared->refcount++;
  630.     }
  631.     new_link->parent = parent_dir;
  632.     new_link->next   = parent_dir->children;
  633.     parent_dir->children = new_link;
  634.  
  635.     free(dir_path);
  636.     free(base_name);
  637. }
  638.  
  639. // Symlink creation
  640. void cmd_ln_symlink(char *targetPath, char *linkPath) {
  641.     if (!targetPath || !linkPath) return;
  642.  
  643.     int idx = -1;
  644.     size_t len = strlen(linkPath);
  645.     for (size_t i = 0; i < len; i++) {
  646.         if (linkPath[i] == '/') idx = i;
  647.     }
  648.     char *dir_path = NULL;
  649.     char *file_name = NULL;
  650.     if (idx != -1) {
  651.         if (idx == 0) {
  652.             dir_path = strdup("/");
  653.         } else {
  654.             dir_path = (char*)malloc(idx + 1);
  655.             if (dir_path) {
  656.                 strncpy(dir_path, linkPath, idx);
  657.                 dir_path[idx] = '\0';
  658.             }
  659.         }
  660.         file_name = strdup(linkPath + idx + 1);
  661.     } else {
  662.         dir_path = strdup(".");
  663.         file_name = strdup(linkPath);
  664.     }
  665.  
  666.     Inode *parent_dir = find_inode_no_symlink(dir_path);
  667.     if (!parent_dir) parent_dir = cwd;
  668.     if (!parent_dir->is_directory) {
  669.         free(dir_path);
  670.         free(file_name);
  671.         return;
  672.     }
  673.  
  674.     Inode *new_link = (Inode*)calloc(1, sizeof(Inode));
  675.     strncpy(new_link->name, file_name, MAX_FILENAME - 1);
  676.     new_link->name[MAX_FILENAME - 1] = '\0';
  677.     new_link->is_directory = false;
  678.     new_link->is_symlink   = true;
  679.     new_link->shared       = create_shared_content(targetPath);
  680.     new_link->parent       = parent_dir;
  681.     new_link->next         = parent_dir->children;
  682.     parent_dir->children   = new_link;
  683.  
  684.     free(dir_path);
  685.     free(file_name);
  686. }
  687.  
  688.  
  689. static void copy_file(Inode *src, char *dest_path) {
  690.     if (!src || !dest_path) return;
  691.  
  692.     Inode *dest = find_inode_no_symlink(dest_path);
  693.     if (dest) rm_recursive(dest);
  694.  
  695.     cmd_touch_single(dest_path);
  696.     dest = find_inode_no_symlink(dest_path);
  697.     if (!dest) return;
  698.     if (src->shared && src->shared->data) {
  699.         if (!dest->shared) {
  700.             dest->shared = create_shared_content(NULL);
  701.         } else {
  702.             free(dest->shared->data);
  703.             dest->shared->data = NULL;
  704.         }
  705.         dest->shared->data = (char*)malloc(strlen(src->shared->data)+1);
  706.         strcpy(dest->shared->data, src->shared->data);
  707.     }
  708. }
  709.  
  710. static void copy_directory(Inode *src, Inode *dest_dir) {
  711.     if (!src || !dest_dir) return;
  712.     // For each child in src, replicate
  713.     for (Inode *child = src->children; child; child = child->next) {
  714.         if (child->is_directory) {
  715.             Inode *nd = (Inode*)calloc(1, sizeof(Inode));
  716.             strncpy(nd->name, child->name, MAX_FILENAME - 1);
  717.             nd->name[MAX_FILENAME - 1] = '\0';
  718.             nd->is_directory = true;
  719.             nd->is_symlink   = false;
  720.             nd->parent       = dest_dir;
  721.             nd->next         = dest_dir->children;
  722.             dest_dir->children = nd;
  723.             copy_directory(child, nd);
  724.         } else {
  725.             Inode *nf = (Inode*)calloc(1, sizeof(Inode));
  726.             strncpy(nf->name, child->name, MAX_FILENAME - 1);
  727.             nf->name[MAX_FILENAME - 1] = '\0';
  728.             nf->is_directory = false;
  729.             nf->is_symlink   = child->is_symlink;
  730.             nf->parent       = dest_dir;
  731.             nf->next         = dest_dir->children;
  732.             dest_dir->children = nf;
  733.  
  734.             if (child->shared && child->shared->data) {
  735.                 nf->shared = create_shared_content(child->shared->data);
  736.             } else {
  737.                 nf->shared = create_shared_content(NULL);
  738.             }
  739.         }
  740.     }
  741. }
  742.  
  743. void cmd_cp(char *s1, char *s2, bool recursive) {
  744.     if (!s1 || !s2) return;
  745.     Inode *src = find_inode_follow(s1);
  746.     if (!src) return;
  747.  
  748.     if (src->is_directory) {
  749.         if (!recursive) return;
  750.         Inode *dst = find_inode_no_symlink(s2);
  751.         if (!dst) {
  752.             // create it
  753.             _mkdir(s2);
  754.             dst = find_inode_no_symlink(s2);
  755.             if (!dst) return;
  756.         }
  757.         copy_directory(src, dst);
  758.     } else {
  759.         // copy file
  760.         copy_file(src, s2);
  761.     }
  762. }
  763.  
  764. void cmd_mv(char *path1, char *path2) {
  765.     if (!path1 || !path2) return;
  766.     Inode *file1 = find_inode_no_symlink(path1);
  767.     if (!file1) return;
  768.  
  769.     int last_slash = -1;
  770.     size_t len = strlen(path2);
  771.     for (size_t i = 0; i < len; i++) {
  772.         if (path2[i] == '/') last_slash = i;
  773.     }
  774.     char *dir_path = NULL;
  775.     char *base_name = NULL;
  776.     if (last_slash == -1) {
  777.         dir_path = strdup(".");
  778.         base_name = strdup(path2);
  779.     } else {
  780.         if (last_slash == 0) {
  781.             dir_path = strdup("/");
  782.         } else {
  783.             dir_path = (char*)malloc(last_slash + 1);
  784.             if (dir_path) {
  785.                 strncpy(dir_path, path2, last_slash);
  786.                 dir_path[last_slash] = '\0';
  787.             }
  788.         }
  789.         base_name = strdup(path2 + last_slash + 1);
  790.     }
  791.  
  792.     Inode *new_parent = find_inode_no_symlink(dir_path);
  793.     if (!new_parent) {
  794.         free(dir_path);
  795.         free(base_name);
  796.         return;
  797.     }
  798.     if (!new_parent->is_directory) {
  799.         free(dir_path);
  800.         free(base_name);
  801.         return;
  802.     }
  803.  
  804.     Inode *c = new_parent->children;
  805.     Inode *existing = NULL;
  806.     while (c) {
  807.         if (strcmp(c->name, base_name) == 0) {
  808.             existing = c;
  809.             break;
  810.         }
  811.         c = c->next;
  812.     }
  813.     if (existing) rm_recursive(existing);
  814.  
  815.     remove_from_parent(file1);
  816.     memset(file1->name, 0, MAX_FILENAME);
  817.     strncpy(file1->name, base_name, MAX_FILENAME - 1);
  818.     file1->name[MAX_FILENAME - 1] = '\0';
  819.  
  820.     file1->parent = new_parent;
  821.     file1->next = new_parent->children;
  822.     new_parent->children = file1;
  823.  
  824.     free(dir_path);
  825.     free(base_name);
  826. }
  827.  
  828.  
  829. void process_command(char *command) {
  830.  
  831.     char *localbuf = malloc((strlen(command) + 1) * sizeof(char));
  832.     strcpy(localbuf, command);
  833.  
  834.     // printf("LOCALBUF: %s\n\n", localbuf);
  835.    
  836.     char *cmd = strtok(localbuf, " ");
  837.     if (!cmd) {
  838.         return;
  839.     }
  840.     char *rest = strtok(NULL, "");
  841.     if (rest) {
  842.         while (*rest == ' ') rest++;
  843.     }
  844.     if (strcmp(cmd, "ls") == 0) {
  845.         if (rest && *rest) cmd_ls(rest);
  846.         else cmd_ls(NULL);
  847.     }
  848.     else if (strcmp(cmd, "cd") == 0) {
  849.         if (rest && *rest) cmd_cd(rest);
  850.         else cmd_cd(NULL);
  851.     }
  852.     else if (strcmp(cmd, "cat") == 0) {
  853.         if (rest && *rest) cmd_cat(rest);
  854.     }
  855.     else if (strcmp(cmd, "touch") == 0) {
  856.         if (rest && *rest) cmd_touch(rest);
  857.     }
  858.     else if (strcmp(cmd, "echo") == 0) {
  859.         if (!rest || !*rest) {
  860.             return;
  861.         }
  862.         char *quoteBegin = strchr(rest, '"');
  863.         if (!quoteBegin) {
  864.             return;
  865.         }
  866.         quoteBegin++;
  867.         char *quoteEnd = strchr(quoteBegin, '"');
  868.         if (!quoteEnd) {
  869.             return;
  870.         }
  871.         *quoteEnd = '\0';
  872.         char *afterQuote = quoteEnd + 1;
  873.         while (*afterQuote == ' ') afterQuote++;
  874.         if (!*afterQuote) {
  875.             return;
  876.         }
  877.         char *redir = strtok(afterQuote, " ");
  878.         if (!redir) {
  879.             return;
  880.         }
  881.         char *filename = strtok(NULL, " ");
  882.         if (!filename) {
  883.             return;
  884.         }
  885.         bool append = (strcmp(redir, ">>") == 0);
  886.         cmd_echo(quoteBegin, filename, append);
  887.     }
  888.     else if (strcmp(cmd, "mkdir") == 0) {
  889.         // if (rest && *rest) cmd_mkdir(rest);
  890.     }
  891.     else if (strcmp(cmd, "rm") == 0) {
  892.         // if (rest && *rest) cmd_rm(rest);
  893.     }
  894.     else if (strcmp(cmd, "find") == 0) {
  895.         // cmd_find(cwd, ".");
  896.     }
  897.     else if (strcmp(cmd, "cp") == 0) {
  898.         /*if (!rest || !*rest) {
  899.             return;
  900.         }
  901.         char *local = strdup(rest);
  902.         char *tok = strtok(local, " ");
  903.         if (!tok) {
  904.             free(local);
  905.             return;
  906.         }
  907.         bool recursive = false;
  908.         if (strcmp(tok, "-r") == 0) {
  909.             recursive = true;
  910.             tok = strtok(NULL, " ");
  911.             if (!tok) {
  912.                 free(local);
  913.                 return;
  914.             }
  915.         }
  916.         char *arg1 = tok;
  917.         char *arg2 = strtok(NULL, "");
  918.         if (!arg2 || !*arg2) {
  919.             free(local);
  920.             return;
  921.         }
  922.         while (*arg2 == ' ') arg2++;
  923.         if (!*arg2) {
  924.             free(local);
  925.             return;
  926.         }
  927.         cmd_cp(arg1, arg2, recursive);
  928.         free(local);*/
  929.     }
  930.     else if (strcmp(cmd, "mv") == 0) {
  931.         /*if (!rest || !*rest) {
  932.             return;
  933.         }
  934.         char *local = strdup(rest);
  935.         char *arg1 = strtok(local, " ");
  936.         if (!arg1) {
  937.             free(local);
  938.             return;
  939.         }
  940.         char *arg2 = strtok(NULL, "");
  941.         if (!arg2) {
  942.             free(local);
  943.             return;
  944.         }
  945.         while (*arg2 == ' ') arg2++;
  946.         if (!*arg2) {
  947.             free(local);
  948.             return;
  949.         }
  950.         cmd_mv(arg1, arg2);
  951.         free(local);*/
  952.     }
  953.     else if (strcmp(cmd, "ln") == 0) {
  954.         /*if (!rest || !*rest) {
  955.             return;
  956.         }
  957.         char *local = strdup(rest);
  958.         char *maybeFlag = strtok(local, " ");
  959.         if (!maybeFlag) {
  960.             free(local);
  961.             return;
  962.         }
  963.         if (strcmp(maybeFlag, "-s") == 0) {
  964.             char *path1 = strtok(NULL, " ");
  965.             if (!path1) {
  966.                 free(local);
  967.                 return;
  968.             }
  969.             char *path2 = strtok(NULL, "");
  970.             if (!path2) {
  971.                 free(local);
  972.                 return;
  973.             }
  974.             while (*path2 == ' ') path2++;
  975.             if (!*path2) {
  976.                 free(local);
  977.                 return;
  978.             }
  979.             cmd_ln_symlink(path1, path2);
  980.         } else {
  981.             // Hard link
  982.             char *path2 = strtok(NULL, "");
  983.             if (!path2) {
  984.                 free(local);
  985.                 return;
  986.             }
  987.             while (*path2 == ' ') path2++;
  988.             if (!*path2) {
  989.                 free(local);
  990.                 return;
  991.             }
  992.             cmd_ln(maybeFlag, path2, true);
  993.         }
  994.         free(local);*/
  995.     }
  996.     else if (strcmp(cmd, "exit") == 0) {
  997.         Inode *child = root->children;
  998.         while (child) {
  999.             Inode *nx = child->next;
  1000.             rm_recursive(child);
  1001.             child = nx;
  1002.         }
  1003.         free(localbuf);
  1004.         free_inode(root);
  1005.         exit(0);
  1006.     }
  1007.     free(localbuf);
  1008. }
  1009.  
  1010. void shell_loop() {
  1011.     char *command = NULL;
  1012.     size_t len = 0;
  1013.     while (getline(&command, &len, stdin) != -1) {
  1014.         size_t command_len = strlen(command);
  1015.         if (command_len > 0 && command[command_len - 1] == '\n') {
  1016.             command[command_len - 1] = '\0';
  1017.         }
  1018.         process_command(command);
  1019.     }
  1020.     free(command);
  1021. }
  1022.  
  1023. int main() {
  1024.     init_filesystem();
  1025.     shell_loop();
  1026.     return 0;
  1027. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement