Advertisement
LA77

Untitled

Mar 13th, 2025
20
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.53 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. #define MAX_CONTENT_SIZE 1024
  9.  
  10. /*
  11. The directory structure is represented as a tree of linked lists.
  12.  
  13. root
  14. |---- dir1 (root --> children)
  15. | |---- file1 (dir1 --> children)
  16. | |---- file2 (file1 --> next)
  17. | |---- file3 (file2 --> mext)
  18. |
  19. |---- dir2 (dir1 --> next)
  20. */
  21.  
  22. typedef struct Inode {
  23. char name[MAX_FILENAME];
  24. bool is_directory;
  25. char *content;
  26. struct Inode *parent;
  27. struct Inode *children;
  28. struct Inode *next;
  29. } Inode;
  30.  
  31. void free_inode(Inode *inode) {
  32. if (inode->content) {
  33. free(inode->content);
  34. }
  35. free(inode);
  36. }
  37.  
  38. Inode *root;
  39. Inode *cwd;
  40.  
  41. void init_filesystem() {
  42. root = (Inode *)malloc(sizeof(Inode));
  43. strcpy(root->name, "/");
  44. root->is_directory = true;
  45. root->content = NULL;
  46. root->parent = root;
  47. root->children = NULL;
  48. root->next = NULL;
  49. cwd = root;
  50. }
  51.  
  52. void shell_loop() {
  53.  
  54. char command[MAX_COMMAND_LENGTH];
  55.  
  56. while (1) {
  57.  
  58. if (!fgets(command, sizeof(command), stdin)) {
  59. break; // Exit on EOF
  60. }
  61.  
  62. // Remove the newline character if present
  63. size_t len = strlen(command);
  64. if (len > 0 && command[len - 1] == '\n') {
  65. command[len - 1] = '\0';
  66. }
  67.  
  68. process_command(command);
  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. if(strlen(copy_of_command) != 2)
  83. {
  84. char dir[strlen(copy_of_command)];
  85. memset(dir, 0, sizeof(dir));
  86.  
  87. int idx = 0;
  88. for(int i = 0; i < strlen(copy_of_command); ++ i)
  89. {
  90. if(copy_of_command[i] == ' ')
  91. {
  92. idx = i + 1;
  93. break;
  94. }
  95. }
  96. strcpy(dir, copy_of_command + idx);
  97. cmd_ls(dir);
  98. }
  99. else {
  100. cmd_ls(strtok(NULL, " "));
  101. }
  102. } else if(strcmp(cmd, "find") == 0){
  103. cmd_find(cwd, ".");
  104. } else if(strcmp(cmd, "cp") == 0) {
  105. int idx = 5;
  106.  
  107. char dir1[strlen(copy_of_command)], dir2[strlen(copy_of_command)];
  108. memset(dir1, 0, sizeof(dir1));
  109. memset(dir2, 0, sizeof(dir2));
  110.  
  111. for(int i = idx; i < strlen(copy_of_command); ++ i)
  112. {
  113. if(copy_of_command[i] == ' ')
  114. {
  115. idx = i + 1;
  116. break;
  117. }
  118. }
  119.  
  120. int cnt = 0;
  121. for(int i = idx; i < strlen(copy_of_command); ++ i)
  122. {
  123. if(copy_of_command[i] == ' ')
  124. {
  125. idx = i + 1;
  126. break;
  127. }
  128. dir1[cnt++] = copy_of_command[i];
  129. }
  130. dir1[cnt] = '\0';
  131.  
  132. strcpy(dir2, copy_of_command + idx);
  133.  
  134. cmd_cp(dir1, dir2);
  135. }
  136. else if(strcmp(cmd, "cat") == 0){
  137. char dir[strlen(copy_of_command)];
  138. memset(dir, 0, sizeof(dir));
  139.  
  140. int idx = 0;
  141. for(int i = 0; i < strlen(copy_of_command); ++ i)
  142. {
  143. if(copy_of_command[i] == ' ')
  144. {
  145. idx = i + 1;
  146. break;
  147. }
  148. }
  149. strcpy(dir, copy_of_command + idx);
  150. cmd_cat(dir);
  151. } else if (strcmp(cmd, "cd") == 0) {
  152.  
  153. if(strlen(copy_of_command) != 2)
  154. {
  155. char dir[strlen(copy_of_command)];
  156. memset(dir, 0, sizeof(dir));
  157.  
  158. int idx = 0;
  159. for(int i = 0; i < strlen(copy_of_command); ++ i)
  160. {
  161. if(copy_of_command[i] == ' ')
  162. {
  163. idx = i + 1;
  164. break;
  165. }
  166. }
  167. strcpy(dir, copy_of_command + idx);
  168. cmd_cd(dir);
  169. }
  170. else
  171. {
  172. cmd_cd(strtok(NULL, " "));
  173. }
  174.  
  175. } else if (strcmp(cmd, "touch") == 0) {
  176.  
  177. char filename[strlen(copy_of_command)];
  178. memset(filename, 0, sizeof(filename));
  179.  
  180. int idx = 0;
  181. for(int i = 0; i < strlen(copy_of_command); ++ i)
  182. {
  183. if(copy_of_command[i] == ' ')
  184. {
  185. idx = i + 1;
  186. break;
  187. }
  188. }
  189. strcpy(filename, copy_of_command + idx);
  190. cmd_touch(filename);
  191.  
  192. } else if (strcmp(cmd, "echo") == 0) {
  193. char *text = NULL;
  194. char *redirect = NULL;
  195. char *filename = NULL;
  196.  
  197. text = strchr(copy_of_command, '"') + 1; // Find '"' and moe to the next character
  198. char *end_quote = strchr(text, '"'); // Find the end of the string
  199. *end_quote = '\0';
  200. redirect = strtok(end_quote + 1, " ");
  201. filename = strtok(NULL, " ");
  202.  
  203. bool append = strcmp(redirect, ">>") == 0;
  204. cmd_echo(text, filename, append);
  205.  
  206. } else if (strcmp(cmd, "mkdir") == 0) {
  207. strtok(NULL, " ");
  208. cmd_mkdir(strtok(NULL, " "));
  209. } else if (strcmp(cmd, "rm") == 0) {
  210. cmd_rm(strtok(NULL, " "));
  211. } else if (strcmp(cmd, "exit") == 0) {
  212. cmd_exit();
  213. } else {
  214. printf("Unknown command: %s\n", cmd);
  215. }
  216. }
  217.  
  218. // Returns the inode at the provided path. If it does not exist, it will return NULL
  219. Inode* find_inode(char *path) {
  220. char *path_copy = malloc(strlen(path) + 1);
  221. strcpy(path_copy, path);
  222.  
  223. // If the path doesn't start with a / use cwd
  224. Inode *current = (path_copy[0] == '/') ? root : cwd;
  225.  
  226. char *path_component = strtok(path_copy, "/");
  227.  
  228. // A single /
  229. if (!path_component && path_copy[0] == '/') {
  230. free(path_copy);
  231. return root;
  232. }
  233.  
  234. while (path_component) {
  235. if (strcmp(path_component, ".") == 0) {
  236. // Do nothing
  237. } else if (strcmp(path_component, "..") == 0) {
  238. current = current->parent;
  239. } else {
  240. // Search for this name in the children
  241. Inode *child = current->children;
  242. bool found = false;
  243.  
  244. while (child) {
  245. if (strcmp(child->name, path_component) == 0) {
  246. current = child;
  247. found = true;
  248. break;
  249. }
  250. child = child->next;
  251. }
  252.  
  253. // Inode not found
  254. if (!found) {
  255. free(path_copy);
  256. return NULL;
  257. }
  258. }
  259.  
  260. path_component = strtok(NULL, "/");
  261. }
  262.  
  263. free(path_copy);
  264. return current;
  265. }
  266.  
  267. void cmd_cat(char *dir)
  268. {
  269. Inode *file = find_inode(dir);
  270.  
  271. if(file->content)
  272. {
  273. printf("%s\n", file->content);
  274. }
  275. }
  276.  
  277. int asciiOrder(const void *a, const void *b) {
  278. return strcmp(*(const char **)a, *(const char **)b);
  279. }
  280.  
  281. void cmd_ls(char *path) {
  282. Inode *dir = cwd;
  283. if(path) {
  284. dir = find_inode(path);
  285. }
  286.  
  287. Inode *current = dir->children;
  288. int children_len = 0;
  289. while (current) {
  290. children_len++;
  291. current = current->next;
  292. }
  293.  
  294. // Store names in an array
  295. char **names = malloc(children_len* sizeof(char *));
  296. current = dir->children;
  297. for (int i = 0; i < children_len; i++) {
  298. names[i] = current->name;
  299. current = current->next;
  300. }
  301.  
  302. qsort(names, children_len, sizeof(char *), asciiOrder);
  303.  
  304. for(int i = 0; i < children_len; ++ i)
  305. {
  306. printf("%s ", names[i]);
  307. }
  308. printf("\n");
  309. }
  310.  
  311. void cmd_cd(char *path) {
  312. if(!path) {
  313. printf("DA\n");
  314. cwd = root;
  315. }
  316. else {
  317. cwd = find_inode(path);
  318. }
  319. }
  320.  
  321. void cmd_touch(char *filename)
  322. {
  323. int idx = -1;
  324.  
  325. // Find the last '/' in the filename to separate directory and file name
  326. for(int i = 0; i < strlen(filename); ++i)
  327. {
  328. if(filename[i] == '/')
  329. {
  330. idx = i;
  331. }
  332. }
  333.  
  334. // Separate the directory path and filename
  335. char dir_path[idx + 1]; // Directory path
  336. char file_name[strlen(filename) - idx];
  337.  
  338. memset(dir_path, 0, sizeof(dir_path));
  339. memset(file_name, 0, sizeof(file_name));
  340.  
  341. // If a '/' is found, split the filename into directory and file name
  342. if (idx != -1) {
  343. strncpy(dir_path, filename, idx);
  344. strcpy(file_name, filename + idx + 1); // Everything after the '/' is the file name
  345. } else {
  346. strcpy(file_name, filename);
  347. }
  348.  
  349. Inode *parent_dir = find_inode(dir_path); // Find the parent directory
  350.  
  351. // If no directory exists, create one (in case directory doesn't exist)
  352. if (!parent_dir) {
  353. parent_dir = cwd; // Default to the current directory
  354. }
  355.  
  356. // Create a new file Inode
  357. Inode *new_file = (Inode *)malloc(sizeof(Inode));
  358. strcpy(new_file->name, file_name);
  359. new_file->is_directory = false;
  360. new_file->content = NULL;
  361. new_file->parent = parent_dir;
  362. new_file->children = NULL;
  363. new_file->next = NULL;
  364.  
  365. // Add the new file to the parent's children list
  366. Inode *old_next = NULL;
  367. if(parent_dir->children)
  368. old_next = parent_dir->children;
  369.  
  370. parent_dir->children = new_file;
  371.  
  372. if(old_next) new_file->next = old_next;
  373. }
  374.  
  375.  
  376. void echo_overwrite (char *text, char *filename) {
  377.  
  378. Inode *file = find_inode(filename);
  379.  
  380. if (!file) {
  381. cmd_touch(filename);
  382. file = find_inode(filename);
  383. }
  384.  
  385. if(file->content) {
  386. free(file->content);
  387. }
  388.  
  389. file->content = malloc(strlen(text) + 1);
  390. strcpy(file->content, text);
  391. }
  392.  
  393. void echo_add(char *text, char *filename)
  394. {
  395. Inode *file = find_inode(filename);
  396.  
  397. if(!file) {
  398. cmd_touch(filename);
  399. file = find_inode(filename);
  400. }
  401. strcat(file->content, text);
  402. }
  403.  
  404.  
  405. void cmd_echo(char *text, char *filename, bool append) {
  406. if (!append) {
  407. echo_overwrite(text, filename);
  408. }
  409. else
  410. {
  411. echo_add(text, filename);
  412. }
  413. }
  414.  
  415. void _mkdir (char *dirname) {
  416. char *path_copy = malloc(strlen(dirname) + 1);
  417. strcpy(path_copy, dirname);
  418.  
  419. Inode *current = path_copy[0] == '/' ? root : cwd;
  420.  
  421. char* path_component = strtok(path_copy, "/");
  422.  
  423.  
  424. while (path_component) {
  425. if (strcmp(path_component, ".") == 0) {
  426. // Do nothing
  427. } else if (strcmp(path_component, "..") == 0) {
  428. current = current->parent;
  429. } else {
  430. Inode *save_current = current;
  431.  
  432. // Find the wether the name exists
  433. while (current && strcmp(current->name, path_component) != 0) {
  434. current = current->next;
  435. }
  436.  
  437. // Exists
  438. if (current) {
  439. // Go into this directory;
  440. current = current->children;
  441. } else {
  442. // Create new directory
  443. Inode *new_dir = (Inode *)malloc(sizeof(Inode));
  444.  
  445. strcpy(new_dir->name, path_component);
  446. new_dir->is_directory = true;
  447. new_dir->content = NULL;
  448. new_dir->parent = save_current;
  449. new_dir->children = NULL;
  450. new_dir->next = save_current->children;
  451. save_current->children = new_dir;
  452.  
  453. current = new_dir;
  454. }
  455.  
  456. }
  457. path_component = strtok(NULL, "/");
  458. }
  459.  
  460. free(path_copy);
  461. }
  462.  
  463. void cmd_mkdir(char *dirnames) {
  464. char *dirnames_copy = malloc(strlen(dirnames) + 1);
  465. strcpy(dirnames_copy, dirnames);
  466.  
  467. char *rest;
  468. char *dirname = strtok_r(dirnames_copy, " ", &rest);
  469.  
  470. while (dirname) {
  471. _mkdir(dirname);
  472. dirname = strtok_r(NULL, " ", &rest);
  473. }
  474.  
  475. free(dirnames_copy);
  476. }
  477.  
  478. void remove_from_parent(Inode *inode){
  479. Inode *parent = inode->parent;
  480. if (parent) {
  481. if (parent->children == inode) {
  482. parent->children = inode->next;
  483. return;
  484. }
  485.  
  486. Inode *sibling = parent->children;
  487. while (sibling && sibling->next != inode) {
  488. sibling = sibling->next;
  489. }
  490. if (sibling) {
  491. sibling->next = inode->next;
  492. }
  493. }
  494. }
  495.  
  496. void cmd_mv(char *path1, char *path2) {
  497. Inode *file1 = find_inode(path1),
  498. *file2 = find_inode(path2);
  499.  
  500. // Remove file1 from its current parent's children
  501. remove_from_parent(file1);
  502.  
  503. if (!file1->is_directory) {
  504.  
  505. // If file doesn't exist, create one
  506. if (!file2) {
  507. cmd_touch(path2);
  508. file2 = find_inode(path2);
  509. }
  510.  
  511. // Overwrite it's content with file1
  512. if(file2->content) {
  513. free(file2->content);
  514. }
  515.  
  516. file2->content = file1->content;
  517.  
  518. free(file1->name);
  519. free(file1);
  520. } else {
  521. cmd_mkdir(path2);
  522. file2 = find_inode(path2);
  523.  
  524. file2->children = file1->children;
  525.  
  526. // Update the children to point to the new parent
  527. Inode *child = file2->children;
  528. while (child) {
  529. child->parent = file2;
  530. child = child->next;
  531. }
  532.  
  533. free(file1->name);
  534. free(file1);
  535. }
  536.  
  537. }
  538.  
  539.  
  540. void rm_recursive(Inode *inode) {
  541. // Base case: if this is not a directory or has no children, just remove it
  542. if (!inode->is_directory || !inode->children) {
  543. remove_from_parent(inode);
  544. free_inode(inode);
  545. return;
  546. }
  547.  
  548. // Recursive case: remove all children first
  549. Inode *child = inode->children;
  550. Inode *next;
  551.  
  552. while (child) {
  553. next = child->next; // Save next pointer before we free the child
  554. rm_recursive(child);
  555. child = next;
  556. }
  557.  
  558. // Now remove the directory itself
  559. remove_from_parent(inode);
  560. free_inode(inode);
  561. }
  562.  
  563. void cmd_rm(char *paths) {
  564. char *paths_copy = malloc(strlen(paths) + 1);
  565. strcpy(paths_copy, paths);
  566.  
  567. char path = strtok(paths_copy, " ");
  568. while (path) {
  569. rm_recursive(find_inode(path));
  570. path = strtok(NULL, "/");
  571. }
  572.  
  573. }
  574. void cmd_exit() {
  575. cmd_rm("/");
  576. free(root);
  577. free(cwd);
  578. exit(0);
  579. }
  580.  
  581. void cmd_find(Inode *inode, const char *path) {
  582. if (!inode) return;
  583.  
  584. if (strcmp(path, ".") == 0) {
  585. printf(".\n");
  586. }
  587.  
  588. Inode *child = inode->children;
  589.  
  590. while (child) {
  591. char new_path[MAX_FILENAME * 10];
  592. snprintf(new_path, sizeof(new_path), "%s/%s", path, child->name);
  593.  
  594. if (child->is_directory) {
  595. printf("%s\n", new_path);
  596. cmd_find(child, new_path);
  597. } else {
  598. printf("%s\n", new_path);
  599. }
  600.  
  601. child = child->next;
  602. }
  603. }
  604.  
  605. void copy_file(Inode *src, Inode *dest_dir) {
  606. printf("DA\n");
  607. // Inode *new_file = (Inode *)malloc(sizeof(Inode));
  608. // strcpy(new_file->name, src->name);
  609. // new_file->is_directory = false;
  610.  
  611. /*if (src->content) {
  612. new_file->content = malloc(strlen(src->content) + 1);
  613. strcpy(new_file->content, src->content);
  614. } else {
  615. new_file->content = NULL;
  616. }
  617.  
  618. new_file->parent = dest_dir;
  619. new_file->children = NULL;
  620. new_file->next = dest_dir->children;
  621. dest_dir->children = new_file;*/
  622. }
  623.  
  624. void copy_directory(Inode *src, Inode *dest_dir) {
  625. printf("DA\n");
  626. Inode *new_dir = (Inode *)malloc(sizeof(Inode));
  627. strcpy(new_dir->name, src->name);
  628. new_dir->is_directory = true;
  629. new_dir->content = NULL;
  630. new_dir->parent = dest_dir;
  631. new_dir->children = NULL;
  632. new_dir->next = dest_dir->children;
  633. dest_dir->children = new_dir;
  634.  
  635. Inode *child = src->children;
  636. while (child) {
  637. if (child->is_directory) {
  638. copy_directory(child, new_dir);
  639. } else {
  640. copy_file(child, new_dir);
  641. }
  642. child = child->next;
  643. }
  644. }
  645.  
  646. void cmd_cp(char *s1, char *s2) {
  647. Inode *src = find_inode(s1);
  648. Inode *dest = find_inode(s2);
  649.  
  650. printf("\n%s\n%s\n", s1, s2);
  651.  
  652. if (src->is_directory) {
  653. // copy_directory(src, dest);
  654. } else {
  655. copy_file(src, dest);
  656. }
  657. }
  658.  
  659.  
  660.  
  661. int main() {
  662. init_filesystem();
  663. shell_loop();
  664. return 0;
  665. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement