From 17d6024c4a0b450c9e123a461a8453319b7831c5 Mon Sep 17 00:00:00 2001 From: Riya Mathur Date: Wed, 18 Sep 2024 19:47:17 -0700 Subject: [PATCH 01/24] Testing commit --- user/tree.c | 1 + 1 file changed, 1 insertion(+) create mode 100644 user/tree.c diff --git a/user/tree.c b/user/tree.c new file mode 100644 index 0000000..45b983b --- /dev/null +++ b/user/tree.c @@ -0,0 +1 @@ +hi From 8daab6e4b5dfdc338949c1cdbc3dcb4319a69e2f Mon Sep 17 00:00:00 2001 From: Suhani Arora Date: Wed, 18 Sep 2024 19:52:54 -0700 Subject: [PATCH 02/24] testing --- test.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 test.txt diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..fc37b3a --- /dev/null +++ b/test.txt @@ -0,0 +1 @@ +Hi - Suhani From aeb7c3de3610df35b829050d0029771a224bca3e Mon Sep 17 00:00:00 2001 From: Chandana Srinivas Date: Thu, 19 Sep 2024 17:28:56 -0700 Subject: [PATCH 03/24] testing tree --- Makefile | 1 + user/tree.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 115 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2584e4a..8dfa3c3 100644 --- a/Makefile +++ b/Makefile @@ -128,6 +128,7 @@ UPROGS=\ $U/_rm\ $U/_sh\ $U/_stressfs\ + $U/_tree\ $U/_usertests\ $U/_grind\ $U/_wc\ diff --git a/user/tree.c b/user/tree.c index 45b983b..9ae1e65 100644 --- a/user/tree.c +++ b/user/tree.c @@ -1 +1,114 @@ -hi +#include "kernel/types.h" +#include "kernel/stat.h" +#include "user/user.h" +#include "kernel/fs.h" +#include "kernel/fcntl.h" + +void tree(char *path, int depth, int *last); + +// Helper function to print the tree lines +void print_tree_prefix(int depth, int *last) { + for (int i = 0; i < depth - 1; i++) { + if (last[i]) + printf(" "); // No vertical bar if this branch is done + else + printf("│ "); // Vertical bar to show continuing branches + } + if (depth > 0) { + if (last[depth - 1]) + printf("└── "); // Last entry in this directory + else + printf("├── "); // Middle entries + } +} + +// Tree function to recursively traverse directories +void tree(char *path, int depth, int *last) { + char buf[512], *p; + int fd; + struct dirent de; + struct stat st; + + // Open the directory or file + if ((fd = open(path, 0)) < 0) { + printf("tree: cannot open %s\n", path); + return; + } + + // Get the status (file/directory) + if (fstat(fd, &st) < 0) { + printf("tree: cannot stat %s\n", path); + close(fd); + return; + } + + if (st.type == T_DIR) { + // Print directory name with tree structure + print_tree_prefix(depth, last); + printf("%s/\n", path); + + // Prepare buffer to traverse directory entries + if (strlen(path) + 1 + DIRSIZ + 1 > sizeof buf) { + printf("tree: path too long\n"); + close(fd); + return; + } + + strcpy(buf, path); + p = buf + strlen(buf); + *p++ = '/'; + + // Count number of entries in the directory to track the last entry + int entry_count = 0; + while (read(fd, &de, sizeof(de)) == sizeof(de)) { + if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) + continue; + entry_count++; + } + + // Reset fd to read directory entries again + close(fd); + fd = open(path, 0); + + // Traverse directory entries and recursively call tree + int i = 0; + while (read(fd, &de, sizeof(de)) == sizeof(de)) { + if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) + continue; + + memmove(p, de.name, strlen(de.name)); + p[strlen(de.name)] = 0; + + // Mark the current entry as the last one in this directory + last[depth] = (i == entry_count - 1); + + // Recursively call tree for this entry + tree(buf, depth + 1, last); + i++; + } + } else { + + // Print file name with tree structure + print_tree_prefix(depth, last); + printf("%s\n", path); + } + + close(fd); +} + + +int main(int argc, char *argv[]) { + char *start_dir = "."; // Default directory is the current directory + if (argc > 1) { + start_dir = argv[1]; // Use provided directory if given + } + + int last[128]; // Array to keep track of the last entry in each level of the tree + memset(last, 0, sizeof(last)); // Initialize all to 0 + + // Call the tree function with the starting directory and depth 0 + tree(start_dir, 0, last); + + exit(0); +} + From 3ad338ee7189a52477f8a919bf0be7d2432b7459 Mon Sep 17 00:00:00 2001 From: Chandana Srinivas Date: Sat, 21 Sep 2024 10:54:19 -0700 Subject: [PATCH 04/24] trying with the last input --- user/tree.c | 82 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/user/tree.c b/user/tree.c index 9ae1e65..8e9fd74 100644 --- a/user/tree.c +++ b/user/tree.c @@ -4,7 +4,7 @@ #include "kernel/fs.h" #include "kernel/fcntl.h" -void tree(char *path, int depth, int *last); +void tree(char *path, int depth, int *last, int *dir_count); // Helper function to print the tree lines void print_tree_prefix(int depth, int *last) { @@ -22,8 +22,14 @@ void print_tree_prefix(int depth, int *last) { } } +// Function to manually concatenate two strings +void my_strcat(char *dest, const char *src) { + while (*dest) dest++; // Move to the end of dest + while ((*dest++ = *src++)); // Copy src to dest +} + // Tree function to recursively traverse directories -void tree(char *path, int depth, int *last) { +void tree(char *path, int depth, int *last, int *dir_count) { char buf[512], *p; int fd; struct dirent de; @@ -35,6 +41,8 @@ void tree(char *path, int depth, int *last) { return; } + printf("Path: %s\n", path); + // Get the status (file/directory) if (fstat(fd, &st) < 0) { printf("tree: cannot stat %s\n", path); @@ -43,9 +51,11 @@ void tree(char *path, int depth, int *last) { } if (st.type == T_DIR) { - // Print directory name with tree structure - print_tree_prefix(depth, last); - printf("%s/\n", path); +// + (*dir_count)++; +// // Print directory name with tree structure +// print_tree_prefix(depth, last); +// printf("%s/\n", path); // Prepare buffer to traverse directory entries if (strlen(path) + 1 + DIRSIZ + 1 > sizeof buf) { @@ -66,33 +76,33 @@ void tree(char *path, int depth, int *last) { entry_count++; } - // Reset fd to read directory entries again - close(fd); - fd = open(path, 0); - - // Traverse directory entries and recursively call tree - int i = 0; - while (read(fd, &de, sizeof(de)) == sizeof(de)) { - if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) - continue; - - memmove(p, de.name, strlen(de.name)); - p[strlen(de.name)] = 0; - - // Mark the current entry as the last one in this directory - last[depth] = (i == entry_count - 1); - - // Recursively call tree for this entry - tree(buf, depth + 1, last); - i++; - } - } else { - - // Print file name with tree structure - print_tree_prefix(depth, last); - printf("%s\n", path); - } - + close(fd); + fd = open(path, 0); + + int i = 0; + while (read(fd, &de, sizeof(de)) == sizeof(de)) { + if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) + continue; + + // Copy the directory entry name to the buffer + memmove(p, de.name, DIRSIZ); + p[DIRSIZ] = 0; + + char new_path[512]; + strcpy(new_path, path); // Copy the base path + new_path[strlen(path)] = '/'; // Add the separator + new_path[strlen(path) + 1] = '\0'; // Ensure proper termination + my_strcat(new_path, de.name); // Append the directory/file name + + // Mark this entry as the last in the directory + last[depth] = (i == entry_count - 1); + + // Recursively call tree on the new path + tree(new_path, depth + 1, last, dir_count); + + i++; + } + } close(fd); } @@ -106,9 +116,15 @@ int main(int argc, char *argv[]) { int last[128]; // Array to keep track of the last entry in each level of the tree memset(last, 0, sizeof(last)); // Initialize all to 0 + int dir_count = 0; // Initialize the directory counter to 0 + // Call the tree function with the starting directory and depth 0 - tree(start_dir, 0, last); + tree(start_dir, 0, last, &dir_count); + + // Print the total number of directories + printf("\nTotal directories: %d\n", dir_count); exit(0); } + From 10def2ba9141b46e1ee154e0b64c85c5a85f12ca Mon Sep 17 00:00:00 2001 From: Chandana Srinivas Date: Sat, 21 Sep 2024 11:21:20 -0700 Subject: [PATCH 05/24] tree.c --- user/tree.c | 130 +++++++++++++++++++++++----------------------------- 1 file changed, 58 insertions(+), 72 deletions(-) diff --git a/user/tree.c b/user/tree.c index 8e9fd74..d7b117b 100644 --- a/user/tree.c +++ b/user/tree.c @@ -4,7 +4,7 @@ #include "kernel/fs.h" #include "kernel/fcntl.h" -void tree(char *path, int depth, int *last, int *dir_count); +void tree(char *path, int depth, int *last); // Helper function to print the tree lines void print_tree_prefix(int depth, int *last) { @@ -18,18 +18,12 @@ void print_tree_prefix(int depth, int *last) { if (last[depth - 1]) printf("└── "); // Last entry in this directory else - printf("├── "); // Middle entries + printf("├── "); // Middle entries. } } -// Function to manually concatenate two strings -void my_strcat(char *dest, const char *src) { - while (*dest) dest++; // Move to the end of dest - while ((*dest++ = *src++)); // Copy src to dest -} - // Tree function to recursively traverse directories -void tree(char *path, int depth, int *last, int *dir_count) { +void tree(char *path, int depth, int *last) { char buf[512], *p; int fd; struct dirent de; @@ -41,8 +35,6 @@ void tree(char *path, int depth, int *last, int *dir_count) { return; } - printf("Path: %s\n", path); - // Get the status (file/directory) if (fstat(fd, &st) < 0) { printf("tree: cannot stat %s\n", path); @@ -50,60 +42,61 @@ void tree(char *path, int depth, int *last, int *dir_count) { return; } + // if the path is a directory if (st.type == T_DIR) { -// - (*dir_count)++; -// // Print directory name with tree structure -// print_tree_prefix(depth, last); -// printf("%s/\n", path); - - // Prepare buffer to traverse directory entries - if (strlen(path) + 1 + DIRSIZ + 1 > sizeof buf) { - printf("tree: path too long\n"); - close(fd); - return; - } - - strcpy(buf, path); - p = buf + strlen(buf); - *p++ = '/'; - - // Count number of entries in the directory to track the last entry - int entry_count = 0; - while (read(fd, &de, sizeof(de)) == sizeof(de)) { - if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) - continue; - entry_count++; - } - - close(fd); - fd = open(path, 0); - - int i = 0; - while (read(fd, &de, sizeof(de)) == sizeof(de)) { - if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) - continue; - - // Copy the directory entry name to the buffer - memmove(p, de.name, DIRSIZ); - p[DIRSIZ] = 0; - - char new_path[512]; - strcpy(new_path, path); // Copy the base path - new_path[strlen(path)] = '/'; // Add the separator - new_path[strlen(path) + 1] = '\0'; // Ensure proper termination - my_strcat(new_path, de.name); // Append the directory/file name - - // Mark this entry as the last in the directory - last[depth] = (i == entry_count - 1); - - // Recursively call tree on the new path - tree(new_path, depth + 1, last, dir_count); - - i++; - } - } - close(fd); + // Print directory name with tree structure + print_tree_prefix(depth, last); + printf("%s/\n", path); + + // Prepare buffer to traverse directory entries + if (strlen(path) + 1 + DIRSIZ + 1 > sizeof buf) { + printf("tree: path too long\n"); + close(fd); + return; + } + + strcpy(buf, path); + p = buf + strlen(buf); + *p++ = '/'; + + printf("buf: %s\n", buf); + + // Count number of entries in the directory to track the last entry + int entry_count = 0; + while (read(fd, &de, sizeof(de)) == sizeof(de)) { + if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) + continue; + entry_count++; + } + close(fd); + fd = open(path, 0); + + // Traverse directory entries and recursively call tree + int i = 0; + + + while (read(fd, &de, sizeof(de)) == sizeof(de)) { + if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) + continue; + + memmove(p, de.name, strlen(de.name)); + p[strlen(de.name)] = 0; + + // Mark the current entry as the last one in this directory + last[depth] = (i == entry_count - 1); + + // Recursively call tree for this entry + tree(buf, depth + 1, last); + i++; + } + } else { + + // Print file name with tree structure + print_tree_prefix(depth, last); + printf("%s\n", path); + } + + close(fd); } @@ -116,15 +109,8 @@ int main(int argc, char *argv[]) { int last[128]; // Array to keep track of the last entry in each level of the tree memset(last, 0, sizeof(last)); // Initialize all to 0 - int dir_count = 0; // Initialize the directory counter to 0 - // Call the tree function with the starting directory and depth 0 - tree(start_dir, 0, last, &dir_count); - - // Print the total number of directories - printf("\nTotal directories: %d\n", dir_count); + tree(start_dir, 0, last); exit(0); } - - From 30798c346a20ab71385be5d91909a90a77b173cb Mon Sep 17 00:00:00 2001 From: Chandana Srinivas Date: Sat, 21 Sep 2024 12:21:30 -0700 Subject: [PATCH 06/24] tree v2 --- user/tree2.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 user/tree2.c diff --git a/user/tree2.c b/user/tree2.c new file mode 100644 index 0000000..2b41ad0 --- /dev/null +++ b/user/tree2.c @@ -0,0 +1,99 @@ +#include "kernel/types.h" +#include "kernel/fs.h" +#include "kernel/stat.h" +#include "user/user.h" + +int dir, file, level = 0, error = 0, flag[6]={0}; +char buf[512]; + +char choice(int sign){ + if(sign == 0) return '|'; + return ' '; +} + +void format(char *name){ + printf("%c", choice(flag[1])); + for(int i = 1;i < level;i++) + printf(" %c", choice(flag[i+1])); + printf("\n"); + for(int i = 1;i < level;i++) + printf("%c ", choice(flag[i])); + printf("+-- %s\n", name); +} + +void tree(char *path){ + char *p; + int fd = open(path, 0); + if(fd < 0){ + error = 1; + return; + } + struct stat st; + fstat(fd, &st); + if(st.type == T_FILE){ + error = 1; + return; + } + if(level==0) printf("\n"); + level++; + struct dirent de; + strcpy(buf, path); + p = buf+strlen(buf); + *p++ = '/'; + read(fd, &de, sizeof(de)); + int cond = 0, val; + while(1){ + if(strcmp(de.name, "..")==0 || strcmp(de.name, ".")==0){ + val = read(fd, &de, sizeof(de)); + cond = (val==0 || strlen(de.name)==0); + if(cond) break; + continue; + } + memmove(p, de.name, DIRSIZ); + p[DIRSIZ] = 0; + format(de.name); + val = read(fd, &de, sizeof(de)); + cond = (val==0 || strlen(de.name)==0); + stat(buf, &st); + if(st.type == T_DIR){ + if(cond) + flag[level] = 1; + if(level > 0) dir++; + tree(buf); + flag[level] = 0; + } + else + file++; + if(cond) break; + } + if(level > 0) + level--; + close(fd); +} + +int main(int argc, char *argv[]) { + int fd[2]; + pipe(fd); + if(fork() == 0){// child + file = 0, dir = 0; + printf("%s", argv[1]); + tree(argv[1]); + if(error == 1) + printf(" [error opening dir]\n"); + printf("\n"); + close(fd[0]); + write(fd[1], &dir, sizeof(int)); + write(fd[1], &file, sizeof(int)); + close(fd[1]); + } + else{// parent + int file_num, dir_num, null; + close(fd[1]); + read(fd[0], &dir_num, sizeof(int)); + read(fd[0], &file_num, sizeof(int)); + close(fd[0]); + printf("%d directories, %d files\n", dir_num, file_num); + wait(&null); + } + exit(0); +} From 757169f084342d3d507356738b671511b66d10ed Mon Sep 17 00:00:00 2001 From: Chandana Srinivas Date: Wed, 25 Sep 2024 13:15:21 -0700 Subject: [PATCH 07/24] tree implementation --- user/tree.c | 76 ++++++++++++++++++++++------------------------------- 1 file changed, 32 insertions(+), 44 deletions(-) diff --git a/user/tree.c b/user/tree.c index d7b117b..d2a4b55 100644 --- a/user/tree.c +++ b/user/tree.c @@ -4,51 +4,29 @@ #include "kernel/fs.h" #include "kernel/fcntl.h" -void tree(char *path, int depth, int *last); +void print_tree_prefix(int depth, int *last); -// Helper function to print the tree lines -void print_tree_prefix(int depth, int *last) { - for (int i = 0; i < depth - 1; i++) { - if (last[i]) - printf(" "); // No vertical bar if this branch is done - else - printf("│ "); // Vertical bar to show continuing branches - } - if (depth > 0) { - if (last[depth - 1]) - printf("└── "); // Last entry in this directory - else - printf("├── "); // Middle entries. - } -} - -// Tree function to recursively traverse directories void tree(char *path, int depth, int *last) { char buf[512], *p; int fd; struct dirent de; struct stat st; - // Open the directory or file if ((fd = open(path, 0)) < 0) { printf("tree: cannot open %s\n", path); return; } - // Get the status (file/directory) if (fstat(fd, &st) < 0) { printf("tree: cannot stat %s\n", path); close(fd); return; } - // if the path is a directory if (st.type == T_DIR) { - // Print directory name with tree structure print_tree_prefix(depth, last); printf("%s/\n", path); - // Prepare buffer to traverse directory entries if (strlen(path) + 1 + DIRSIZ + 1 > sizeof buf) { printf("tree: path too long\n"); close(fd); @@ -59,9 +37,6 @@ void tree(char *path, int depth, int *last) { p = buf + strlen(buf); *p++ = '/'; - printf("buf: %s\n", buf); - - // Count number of entries in the directory to track the last entry int entry_count = 0; while (read(fd, &de, sizeof(de)) == sizeof(de)) { if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) @@ -71,27 +46,25 @@ void tree(char *path, int depth, int *last) { close(fd); fd = open(path, 0); - // Traverse directory entries and recursively call tree int i = 0; - - while (read(fd, &de, sizeof(de)) == sizeof(de)) { if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) continue; - memmove(p, de.name, strlen(de.name)); - p[strlen(de.name)] = 0; + char *saved_p = p; - // Mark the current entry as the last one in this directory - last[depth] = (i == entry_count - 1); + memmove(p, de.name, strlen(de.name)); + p[strlen(de.name)] = 0; - // Recursively call tree for this entry - tree(buf, depth + 1, last); - i++; - } - } else { + last[depth] = (i == entry_count - 1); - // Print file name with tree structure + tree(buf, depth + 1, last); + + p = saved_p; + i++; + } + + } else { print_tree_prefix(depth, last); printf("%s\n", path); } @@ -100,16 +73,31 @@ void tree(char *path, int depth, int *last) { } +void print_tree_prefix(int depth, int *last) { + for (int i = 0; i < depth - 1; i++) { + if (last[i]) + printf(" "); + else + printf("│ "); + } + if (depth > 0) { + if (last[depth - 1]) + printf("└── "); + else + printf("├── "); + } +} + + int main(int argc, char *argv[]) { - char *start_dir = "."; // Default directory is the current directory + char *start_dir = "."; if (argc > 1) { - start_dir = argv[1]; // Use provided directory if given + start_dir = argv[1]; } - int last[128]; // Array to keep track of the last entry in each level of the tree - memset(last, 0, sizeof(last)); // Initialize all to 0 + int last[128]; + memset(last, 0, sizeof(last)); - // Call the tree function with the starting directory and depth 0 tree(start_dir, 0, last); exit(0); From eba83f0bad995fb2d15ef3dc4d1edbe96b41ac24 Mon Sep 17 00:00:00 2001 From: Riya Mathur Date: Wed, 25 Sep 2024 17:09:42 -0700 Subject: [PATCH 08/24] Implemented S flag --- user/tree.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/user/tree.c b/user/tree.c index d2a4b55..ae2aac0 100644 --- a/user/tree.c +++ b/user/tree.c @@ -6,7 +6,7 @@ void print_tree_prefix(int depth, int *last); -void tree(char *path, int depth, int *last) { +void tree(char *path, int depth, int *last, char *file_ext, int show_size) { char buf[512], *p; int fd; struct dirent de; @@ -58,16 +58,22 @@ void tree(char *path, int depth, int *last) { last[depth] = (i == entry_count - 1); - tree(buf, depth + 1, last); + tree(buf, depth + 1, last, file_ext, show_size); p = saved_p; i++; } } else { - print_tree_prefix(depth, last); - printf("%s\n", path); - } + print_tree_prefix(depth, last); + + // If the show_size flag is enabled, print the file size + if (show_size) { + printf("%s (size: %d bytes)\n", path, st.size); + } else { + printf("%s\n", path); + } + } close(fd); } @@ -90,15 +96,27 @@ void print_tree_prefix(int depth, int *last) { int main(int argc, char *argv[]) { - char *start_dir = "."; - if (argc > 1) { - start_dir = argv[1]; + char *start_dir = "."; + char *file_ext = 0; + int show_size = 0; + + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "-F") == 0) { + i++; + file_ext = argv[i]; + printf("File extension: %s\n", file_ext); + } + if (strcmp(argv[i], "-S") == 0) { + show_size = 1; + } else { + start_dir = argv[i]; + } } - + int last[128]; memset(last, 0, sizeof(last)); - tree(start_dir, 0, last); + tree(start_dir, 0, last, file_ext, show_size); exit(0); } From c14f63099a6edd3568f09a36ee74ff4b5f7a8ebb Mon Sep 17 00:00:00 2001 From: Chandana Srinivas Date: Thu, 26 Sep 2024 10:36:24 -0700 Subject: [PATCH 09/24] -C flag implemented --- user/tree.c | 148 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 89 insertions(+), 59 deletions(-) diff --git a/user/tree.c b/user/tree.c index ae2aac0..aae7d2b 100644 --- a/user/tree.c +++ b/user/tree.c @@ -6,7 +6,7 @@ void print_tree_prefix(int depth, int *last); -void tree(char *path, int depth, int *last, char *file_ext, int show_size) { +void tree(char *path, int depth, int *last, char *file_ext, int show_size, int show_count) { char buf[512], *p; int fd; struct dirent de; @@ -24,8 +24,10 @@ void tree(char *path, int depth, int *last, char *file_ext, int show_size) { } if (st.type == T_DIR) { - print_tree_prefix(depth, last); - printf("%s/\n", path); + if (!show_count) { + print_tree_prefix(depth, last); + printf("%s/\n", path); + } if (strlen(path) + 1 + DIRSIZ + 1 > sizeof buf) { printf("tree: path too long\n"); @@ -33,52 +35,76 @@ void tree(char *path, int depth, int *last, char *file_ext, int show_size) { return; } - strcpy(buf, path); - p = buf + strlen(buf); - *p++ = '/'; - - int entry_count = 0; - while (read(fd, &de, sizeof(de)) == sizeof(de)) { - if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) - continue; - entry_count++; - } - close(fd); - fd = open(path, 0); - - int i = 0; - while (read(fd, &de, sizeof(de)) == sizeof(de)) { - if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) - continue; - - char *saved_p = p; - - memmove(p, de.name, strlen(de.name)); - p[strlen(de.name)] = 0; - - last[depth] = (i == entry_count - 1); - - tree(buf, depth + 1, last, file_ext, show_size); - - p = saved_p; - i++; - } - - } else { - print_tree_prefix(depth, last); - - // If the show_size flag is enabled, print the file size - if (show_size) { - printf("%s (size: %d bytes)\n", path, st.size); - } else { - printf("%s\n", path); - } - } - - close(fd); + strcpy(buf, path); + p = buf + strlen(buf); + *p++ = '/'; + + int file_count = 0; + int dir_count = 0; + + while (read(fd, &de, sizeof(de)) == sizeof(de)) { + if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) + continue; + + memmove(p, de.name, strlen(de.name)); + p[strlen(de.name)] = 0; + + if (stat(buf, &st) < 0) { + printf("tree: cannot stat %s\n", buf); + continue; + } + + if (st.type == T_DIR) { + dir_count++; + } else { + file_count++; + } + } + + // -C Flag + if (show_count) { + print_tree_prefix(depth, last); + printf("%s/ [%d directories, %d files]\n", path, dir_count, file_count); + } + + close(fd); + fd = open(path, 0); + + int i = 0; + while (read(fd, &de, sizeof(de)) == sizeof(de)) { + if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) + continue; + + char *saved_p = p; + memmove(p, de.name, strlen(de.name)); + p[strlen(de.name)] = 0; + + last[depth] = (i == dir_count + file_count - 1); + + tree(buf, depth + 1, last, file_ext, show_size, show_count); + + p = saved_p; + i++; + } + } else { + if (!show_count) { + print_tree_prefix(depth, last); + // -S Flag + if (show_size) { + printf("%s (size: %d bytes)\n", path, st.size); + } else { + printf("%s\n", path); + } + } + } + + close(fd); } - + + + + void print_tree_prefix(int depth, int *last) { for (int i = 0; i < depth - 1; i++) { if (last[i]) @@ -95,28 +121,32 @@ void print_tree_prefix(int depth, int *last) { } + int main(int argc, char *argv[]) { char *start_dir = "."; char *file_ext = 0; int show_size = 0; + int show_count = 0; for (int i = 1; i < argc; i++) { - if (strcmp(argv[i], "-F") == 0) { - i++; - file_ext = argv[i]; - printf("File extension: %s\n", file_ext); - } - if (strcmp(argv[i], "-S") == 0) { - show_size = 1; - } else { - start_dir = argv[i]; - } + if (strcmp(argv[i], "-F") == 0) { + i++; + file_ext = argv[i]; + printf("File extension: %s\n", file_ext); + } + if (strcmp(argv[i], "-S") == 0) { + show_size = 1; + } else if (strcmp(argv[i], "-C") == 0) { + show_count = 1; + } else { + start_dir = argv[i]; + } } - + int last[128]; memset(last, 0, sizeof(last)); - tree(start_dir, 0, last, file_ext, show_size); + tree(start_dir, 0, last, file_ext, show_size, show_count); exit(0); } From 008f4bc1016d26453493d47b2f7d84754c787049 Mon Sep 17 00:00:00 2001 From: Chandana Srinivas Date: Thu, 26 Sep 2024 10:38:52 -0700 Subject: [PATCH 10/24] removing tree2.c --- user/tree2.c | 99 ---------------------------------------------------- 1 file changed, 99 deletions(-) delete mode 100644 user/tree2.c diff --git a/user/tree2.c b/user/tree2.c deleted file mode 100644 index 2b41ad0..0000000 --- a/user/tree2.c +++ /dev/null @@ -1,99 +0,0 @@ -#include "kernel/types.h" -#include "kernel/fs.h" -#include "kernel/stat.h" -#include "user/user.h" - -int dir, file, level = 0, error = 0, flag[6]={0}; -char buf[512]; - -char choice(int sign){ - if(sign == 0) return '|'; - return ' '; -} - -void format(char *name){ - printf("%c", choice(flag[1])); - for(int i = 1;i < level;i++) - printf(" %c", choice(flag[i+1])); - printf("\n"); - for(int i = 1;i < level;i++) - printf("%c ", choice(flag[i])); - printf("+-- %s\n", name); -} - -void tree(char *path){ - char *p; - int fd = open(path, 0); - if(fd < 0){ - error = 1; - return; - } - struct stat st; - fstat(fd, &st); - if(st.type == T_FILE){ - error = 1; - return; - } - if(level==0) printf("\n"); - level++; - struct dirent de; - strcpy(buf, path); - p = buf+strlen(buf); - *p++ = '/'; - read(fd, &de, sizeof(de)); - int cond = 0, val; - while(1){ - if(strcmp(de.name, "..")==0 || strcmp(de.name, ".")==0){ - val = read(fd, &de, sizeof(de)); - cond = (val==0 || strlen(de.name)==0); - if(cond) break; - continue; - } - memmove(p, de.name, DIRSIZ); - p[DIRSIZ] = 0; - format(de.name); - val = read(fd, &de, sizeof(de)); - cond = (val==0 || strlen(de.name)==0); - stat(buf, &st); - if(st.type == T_DIR){ - if(cond) - flag[level] = 1; - if(level > 0) dir++; - tree(buf); - flag[level] = 0; - } - else - file++; - if(cond) break; - } - if(level > 0) - level--; - close(fd); -} - -int main(int argc, char *argv[]) { - int fd[2]; - pipe(fd); - if(fork() == 0){// child - file = 0, dir = 0; - printf("%s", argv[1]); - tree(argv[1]); - if(error == 1) - printf(" [error opening dir]\n"); - printf("\n"); - close(fd[0]); - write(fd[1], &dir, sizeof(int)); - write(fd[1], &file, sizeof(int)); - close(fd[1]); - } - else{// parent - int file_num, dir_num, null; - close(fd[1]); - read(fd[0], &dir_num, sizeof(int)); - read(fd[0], &file_num, sizeof(int)); - close(fd[0]); - printf("%d directories, %d files\n", dir_num, file_num); - wait(&null); - } - exit(0); -} From 7436cf2b20b0819c4d65e8b3c323132f62c5ad12 Mon Sep 17 00:00:00 2001 From: Riya Mathur Date: Thu, 26 Sep 2024 11:54:25 -0700 Subject: [PATCH 11/24] Implemented -F flag --- user/tree.c | 219 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 144 insertions(+), 75 deletions(-) diff --git a/user/tree.c b/user/tree.c index aae7d2b..3a34403 100644 --- a/user/tree.c +++ b/user/tree.c @@ -6,6 +6,66 @@ void print_tree_prefix(int depth, int *last); +char* strrchr(const char* s, int c) { + const char* last = 0; + for (; *s; s++) { + if (*s == (char)c) { + last = s; + } + } + return (char*)last; +} + +int contains_valid_file(char *path, char *file_ext) { + char buf[512], *p; + int fd; + struct dirent de; + struct stat st; + + if ((fd = open(path, 0)) < 0) { + return 0; // Cannot open directory + } + + strcpy(buf, path); + p = buf + strlen(buf); + *p++ = '/'; + + while (read(fd, &de, sizeof(de)) == sizeof(de)) { + if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) + continue; + + memmove(p, de.name, strlen(de.name)); + p[strlen(de.name)] = 0; + + if (stat(buf, &st) < 0) { + continue; + } + + // Check if it's a valid file with the correct extension + if (st.type != T_DIR) { + if (file_ext) { + char *dot = strrchr(buf, '.'); + if (dot && strcmp(dot, file_ext) == 0) { + close(fd); + return 1; // Found a matching file + } + } else { + close(fd); + return 1; // No extension filter, so any file is valid + } + } else { + // Recursively check the subdirectories + if (contains_valid_file(buf, file_ext)) { + close(fd); + return 1; + } + } + } + + close(fd); + return 0; // No valid files found +} + void tree(char *path, int depth, int *last, char *file_ext, int show_size, int show_count) { char buf[512], *p; int fd; @@ -24,7 +84,10 @@ void tree(char *path, int depth, int *last, char *file_ext, int show_size, int s } if (st.type == T_DIR) { - if (!show_count) { + // Check if directory contains valid files when -F is applied and count directories and files when -C is applied + int valid_for_print = (file_ext == 0 || contains_valid_file(path, file_ext)); + + if (!show_count && valid_for_print) { print_tree_prefix(depth, last); printf("%s/\n", path); } @@ -35,75 +98,82 @@ void tree(char *path, int depth, int *last, char *file_ext, int show_size, int s return; } - strcpy(buf, path); - p = buf + strlen(buf); - *p++ = '/'; - - int file_count = 0; - int dir_count = 0; - - while (read(fd, &de, sizeof(de)) == sizeof(de)) { - if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) - continue; - - memmove(p, de.name, strlen(de.name)); - p[strlen(de.name)] = 0; - - if (stat(buf, &st) < 0) { - printf("tree: cannot stat %s\n", buf); - continue; - } - - if (st.type == T_DIR) { - dir_count++; - } else { - file_count++; - } - } - - // -C Flag - if (show_count) { - print_tree_prefix(depth, last); - printf("%s/ [%d directories, %d files]\n", path, dir_count, file_count); - } - - close(fd); - fd = open(path, 0); - - int i = 0; - while (read(fd, &de, sizeof(de)) == sizeof(de)) { - if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) - continue; - - char *saved_p = p; - memmove(p, de.name, strlen(de.name)); - p[strlen(de.name)] = 0; - - last[depth] = (i == dir_count + file_count - 1); - - tree(buf, depth + 1, last, file_ext, show_size, show_count); - - p = saved_p; - i++; - } - } else { - if (!show_count) { - print_tree_prefix(depth, last); - // -S Flag - if (show_size) { - printf("%s (size: %d bytes)\n", path, st.size); - } else { - printf("%s\n", path); - } - } - } - - close(fd); -} + strcpy(buf, path); + p = buf + strlen(buf); + *p++ = '/'; - - - + int file_count = 0; + int dir_count = 0; + + // Count directories and files + while (read(fd, &de, sizeof(de)) == sizeof(de)) { + if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) + continue; + + memmove(p, de.name, strlen(de.name)); + p[strlen(de.name)] = 0; + + if (stat(buf, &st) < 0) { + continue; + } + + // Only count files that match the extension if -F is used + if (st.type == T_DIR) { + dir_count++; + } else if (!file_ext || (strrchr(buf, '.') && strcmp(strrchr(buf, '.'), file_ext) == 0)) { + file_count++; + } + } + + // Display count when -C is applied + if (show_count) { + print_tree_prefix(depth, last); + printf("%s/ [%d directories, %d files]\n", path, dir_count, file_count); + } + + close(fd); + fd = open(path, 0); + + int i = 0; + while (read(fd, &de, sizeof(de)) == sizeof(de)) { + if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) + continue; + + char *saved_p = p; + memmove(p, de.name, strlen(de.name)); + p[strlen(de.name)] = 0; + + last[depth] = (i == dir_count + file_count - 1); + + // Recursive call to tree + tree(buf, depth + 1, last, file_ext, show_size, show_count); + + p = saved_p; + i++; + } + } else { + // Handle file-specific logic + if (file_ext) { + char *dot = strrchr(path, '.'); + if (!dot || strcmp(dot, file_ext) != 0) { + close(fd); // Skip files that don't match the extension + return; + } + } + + if (!show_count) { + print_tree_prefix(depth, last); + if (show_size) { + printf("%s (size: %d bytes)\n", path, st.size); + } else { + printf("%s\n", path); + } + } + } + + close(fd); +} + void print_tree_prefix(int depth, int *last) { for (int i = 0; i < depth - 1; i++) { @@ -127,14 +197,13 @@ int main(int argc, char *argv[]) { char *file_ext = 0; int show_size = 0; int show_count = 0; - + + for (int i = 1; i < argc; i++) { - if (strcmp(argv[i], "-F") == 0) { + if (strcmp(argv[i], "-F") == 0 && i + 1 < argc) { + file_ext = argv[i + 1]; i++; - file_ext = argv[i]; - printf("File extension: %s\n", file_ext); - } - if (strcmp(argv[i], "-S") == 0) { + } else if (strcmp(argv[i], "-S") == 0) { show_size = 1; } else if (strcmp(argv[i], "-C") == 0) { show_count = 1; From 6a84e8f3cf816602c6bad5e2af5ef0ade2152c23 Mon Sep 17 00:00:00 2001 From: Suhani Arora <68450051+suhani-arora@users.noreply.github.com> Date: Thu, 26 Sep 2024 13:51:24 -0700 Subject: [PATCH 12/24] adding -L flag to main --- user/tree.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/user/tree.c b/user/tree.c index 3a34403..4315b98 100644 --- a/user/tree.c +++ b/user/tree.c @@ -196,7 +196,8 @@ int main(int argc, char *argv[]) { char *start_dir = "."; char *file_ext = 0; int show_size = 0; - int show_count = 0; + int show_count = 0; + int limit_depth = -1; // -1 = default no limit for (int i = 1; i < argc; i++) { @@ -207,6 +208,9 @@ int main(int argc, char *argv[]) { show_size = 1; } else if (strcmp(argv[i], "-C") == 0) { show_count = 1; + } else if (strcmp(argv[i], "-L") == 0) { + limit_depth = atoi(argv[i+1]); + i++; } else { start_dir = argv[i]; } From 448e8e78ea49e6799816579394cf2464d58fd949 Mon Sep 17 00:00:00 2001 From: Suhani Arora <68450051+suhani-arora@users.noreply.github.com> Date: Thu, 26 Sep 2024 13:54:20 -0700 Subject: [PATCH 13/24] Added -L implementation; needs testing --- user/tree.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/user/tree.c b/user/tree.c index 4315b98..93c3b93 100644 --- a/user/tree.c +++ b/user/tree.c @@ -66,12 +66,16 @@ int contains_valid_file(char *path, char *file_ext) { return 0; // No valid files found } -void tree(char *path, int depth, int *last, char *file_ext, int show_size, int show_count) { +void tree(char *path, int depth, int *last, char *file_ext, int show_size, int show_count, int limit_depth) { char buf[512], *p; int fd; struct dirent de; struct stat st; + if (limit_depth != -1 && depth > limit_depth) { + return; + } + if ((fd = open(path, 0)) < 0) { printf("tree: cannot open %s\n", path); return; @@ -219,7 +223,7 @@ int main(int argc, char *argv[]) { int last[128]; memset(last, 0, sizeof(last)); - tree(start_dir, 0, last, file_ext, show_size, show_count); + tree(start_dir, 0, last, file_ext, show_size, show_count, limit_depth); exit(0); } From c9f021d54ab6706b2a99562bd1cd6cf08aeb773a Mon Sep 17 00:00:00 2001 From: Chandana Srinivas Date: Thu, 26 Sep 2024 14:18:05 -0700 Subject: [PATCH 14/24] implementation of all flags --- user/tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user/tree.c b/user/tree.c index 93c3b93..245a3c3 100644 --- a/user/tree.c +++ b/user/tree.c @@ -150,7 +150,7 @@ void tree(char *path, int depth, int *last, char *file_ext, int show_size, int s last[depth] = (i == dir_count + file_count - 1); // Recursive call to tree - tree(buf, depth + 1, last, file_ext, show_size, show_count); + tree(buf, depth + 1, last, file_ext, show_size, show_count, limit_depth); p = saved_p; i++; From e9d852abdef600b9886f62fa2d0cf565920a657e Mon Sep 17 00:00:00 2001 From: Chandana Srinivas Date: Fri, 27 Sep 2024 11:25:14 -0700 Subject: [PATCH 15/24] final tree implementation --- user/tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user/tree.c b/user/tree.c index 245a3c3..b08d777 100644 --- a/user/tree.c +++ b/user/tree.c @@ -23,7 +23,7 @@ int contains_valid_file(char *path, char *file_ext) { struct stat st; if ((fd = open(path, 0)) < 0) { - return 0; // Cannot open directory + return 0; } strcpy(buf, path); From ff8d898762ece6c38e3c3e33dcb23f71e7ae98b4 Mon Sep 17 00:00:00 2001 From: Chandana Srinivas Date: Fri, 27 Sep 2024 18:01:30 -0700 Subject: [PATCH 16/24] adding javadoc comments to tree.c --- user/tree.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/user/tree.c b/user/tree.c index b08d777..b4fe9e8 100644 --- a/user/tree.c +++ b/user/tree.c @@ -6,6 +6,14 @@ void print_tree_prefix(int depth, int *last); + +/** + * finds the last occurrence of a char in a string + * + * @param s - string to be searched in + * @param c - character to find + * @return - pointer to the last occurrence of the char in the string + */ char* strrchr(const char* s, int c) { const char* last = 0; for (; *s; s++) { @@ -16,6 +24,14 @@ char* strrchr(const char* s, int c) { return (char*)last; } + +/** + * checks if a dir contains a valid file matching the ext + * + * @param path - path of the dir to check + * @param file_ext - file ext to look for + * @return - 1 if a valid file is found and 0 otherwise + */ int contains_valid_file(char *path, char *file_ext) { char buf[512], *p; int fd; @@ -66,6 +82,17 @@ int contains_valid_file(char *path, char *file_ext) { return 0; // No valid files found } + +/** + * recursively traverses and prints the directory structure + * + * @param path - curr directory path + * @param depth - curr depth in the directory tree + * @param last - array indicating if the current node is the last in its level + * @param file_ext - file ext to filter files + * @param show_size - flag indicating whether to display file sizes + * @param show_count - flag indicating whether to display counts of directories and files + */ void tree(char *path, int depth, int *last, char *file_ext, int show_size, int show_count, int limit_depth) { char buf[512], *p; int fd; @@ -178,7 +205,13 @@ void tree(char *path, int depth, int *last, char *file_ext, int show_size, int s close(fd); } - + +/** + * prints the prefix for the current tree level based on depth + * + * @param depth - current depth in the directory tree + * @param last - array indicating if the current node is the last in its level + */ void print_tree_prefix(int depth, int *last) { for (int i = 0; i < depth - 1; i++) { if (last[i]) @@ -195,13 +228,19 @@ void print_tree_prefix(int depth, int *last) { } - +/** + * main function to parse command-line arguments and initiate the tree traversal + * + * @param argc - number of command-line arguments + * @param argv - array of command-line argument strings + * @return - 0 on successful tree traversal and printing + */ int main(int argc, char *argv[]) { char *start_dir = "."; char *file_ext = 0; int show_size = 0; int show_count = 0; - int limit_depth = -1; // -1 = default no limit + int limit_depth = -1; for (int i = 1; i < argc; i++) { From ac22dc02207a9050c00e2ea66a8bf8f41669f88a Mon Sep 17 00:00:00 2001 From: Chandana Srinivas Date: Mon, 30 Sep 2024 12:24:51 -0700 Subject: [PATCH 17/24] adding mkfs.c for testing --- Makefile | 6 ++-- dir1/test.c | 1 + dir2/test.txt | 1 + mkfs/mkfs.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 dir1/test.c create mode 100644 dir2/test.txt diff --git a/Makefile b/Makefile index 8dfa3c3..4316f23 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,8 @@ K=kernel U=user +DIR = dir1 dir2 + OBJS = \ $K/entry.o \ $K/start.o \ @@ -134,8 +136,8 @@ UPROGS=\ $U/_wc\ $U/_zombie\ -fs.img: mkfs/mkfs README.md $(UPROGS) - mkfs/mkfs fs.img README.md $(UPROGS) +fs.img: mkfs/mkfs README.md $(UPROGS) $(DIR) + mkfs/mkfs fs.img README.md $(UPROGS) $(DIR) -include kernel/*.d user/*.d diff --git a/dir1/test.c b/dir1/test.c new file mode 100644 index 0000000..ce01362 --- /dev/null +++ b/dir1/test.c @@ -0,0 +1 @@ +hello diff --git a/dir2/test.txt b/dir2/test.txt new file mode 100644 index 0000000..ce01362 --- /dev/null +++ b/dir2/test.txt @@ -0,0 +1 @@ +hello diff --git a/mkfs/mkfs.c b/mkfs/mkfs.c index 1ec326b..9bbc090 100644 --- a/mkfs/mkfs.c +++ b/mkfs/mkfs.c @@ -4,12 +4,18 @@ #include #include #include +#include +#include +#include +#define dirent xv6_dirent #define stat xv6_stat // avoid clash with host struct stat #include "kernel/types.h" #include "kernel/fs.h" #include "kernel/stat.h" #include "kernel/param.h" +#undef dirent +#undef stat #ifndef static_assert #define static_assert(a, b) do { switch (0) case 0: case (a): ; } while (0) @@ -65,12 +71,88 @@ xint(uint x) return y; } +void +add_file(int parent_fd, uint parentino, char *filename) +{ + uint inum; + int fd; + char buf[BSIZE]; + struct xv6_dirent de; + + if((fd = openat(parent_fd, filename, 0)) < 0) + die(filename); + + inum = ialloc(T_FILE); + + bzero(&de, sizeof(de)); + de.inum = xshort(inum); + strncpy(de.name, filename, DIRSIZ); + iappend(parentino, &de, sizeof(de)); + + ssize_t cc; + while((cc = read(fd, buf, sizeof(buf))) > 0) + iappend(inum, buf, cc); + + close(fd); +} + +uint +add_dir(int level, int parent_fd, uint parentino, char *dirname) +{ + struct xv6_dirent de; + uint dino = ialloc(T_DIR); + bzero(&de, sizeof(de)); + de.inum = xshort(dino); + strcpy(de.name, dirname); + iappend(parentino, &de, sizeof(de)); + + bzero(&de, sizeof(de)); + de.inum = xshort(dino); + strcpy(de.name, "."); + iappend(dino, &de, sizeof(de)); + + bzero(&de, sizeof(de)); + de.inum = xshort(parentino); + strcpy(de.name, ".."); + iappend(dino, &de, sizeof(de)); + + int dir_fd = -1; + if ((dir_fd = openat(parent_fd, dirname, O_RDONLY)) == -1) { + perror("open"); + return dino; + } + + DIR *d = fdopendir(dir_fd); + if (d == NULL) { + perror("fdopendir"); + return dino; + } + + struct dirent *e; + while ((e = readdir(d)) != NULL) { + if (e->d_name[0] == '.') { + continue; + } + + if (e->d_type == DT_REG) { + printf("%*s+ %s\n", level * 2, "", e->d_name); + add_file(dir_fd, dino, e->d_name); + } else if (e->d_type == DT_DIR) { + printf("%*s+ /%s\n", level * 2, "", e->d_name); + add_dir(level + 1, dir_fd, dino, e->d_name); + } + } + close(dir_fd); + + return dino; +} + int main(int argc, char *argv[]) { int i, cc, fd; uint rootino, inum, off; - struct dirent de; + struct xv6_dirent de; char buf[BSIZE]; struct dinode din; @@ -83,7 +165,7 @@ main(int argc, char *argv[]) } assert((BSIZE % sizeof(struct dinode)) == 0); - assert((BSIZE % sizeof(struct dirent)) == 0); + assert((BSIZE % sizeof(struct xv6_dirent)) == 0); fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666); if(fsfd < 0) @@ -128,6 +210,13 @@ main(int argc, char *argv[]) iappend(rootino, &de, sizeof(de)); for(i = 2; i < argc; i++){ + struct stat sb; + stat(argv[i], &sb); + if (S_ISDIR(sb.st_mode)) { + add_dir(0, AT_FDCWD, rootino, argv[i]); + continue; + } + // get rid of "user/" char *shortname; if(strncmp(argv[i], "user/", 5) == 0) From 32e54556a835674519f59239e7374890bbbc2240 Mon Sep 17 00:00:00 2001 From: Chandana Srinivas Date: Thu, 31 Oct 2024 23:22:35 -0700 Subject: [PATCH 18/24] changes based on code review --- user/tree.c | 183 ++++++++++++++++++++++++---------------------------- 1 file changed, 85 insertions(+), 98 deletions(-) diff --git a/user/tree.c b/user/tree.c index b4fe9e8..fab447f 100644 --- a/user/tree.c +++ b/user/tree.c @@ -4,8 +4,50 @@ #include "kernel/fs.h" #include "kernel/fcntl.h" -void print_tree_prefix(int depth, int *last); +/** + * prints the prefix for the current tree level based on depth + * + * @param depth - current depth in the directory tree + * @param last - array indicating if the current node is the last in its level + */ +void print_tree_prefix(int depth, int *last) { + for (int i = 0; i < depth - 1; i++) { + if (last[i]) + printf(" "); + else + printf("│ "); + } + if (depth > 0) { + if (last[depth - 1]) + printf("└── "); + else + printf("├── "); + } +} + +/** + * checks if the directory name is a special directory like "." or ".." + * + * @param name - name of dir to check + * @return 1 - if it is a special dir + */ +int is_special_dir(const char *name) { + return strcmp(name, ".") == 0 || strcmp(name, "..") == 0; +} +/** + * opens the specified dir to read + * + * @param path - path of the dir to open + * @return - file descriptor for the opened dir + */ +int open_directory(const char *path) { + int fd = open(path, 0); + if (fd < 0) { + fprintf(2, "tree: cannot open %s\n", path); + } + return fd; +} /** * finds the last occurrence of a char in a string @@ -24,7 +66,6 @@ char* strrchr(const char* s, int c) { return (char*)last; } - /** * checks if a dir contains a valid file matching the ext * @@ -34,52 +75,42 @@ char* strrchr(const char* s, int c) { */ int contains_valid_file(char *path, char *file_ext) { char buf[512], *p; - int fd; + int fd = open_directory(path); + if (fd < 0) return 0; + struct dirent de; struct stat st; - - if ((fd = open(path, 0)) < 0) { - return 0; - } - strcpy(buf, path); p = buf + strlen(buf); *p++ = '/'; while (read(fd, &de, sizeof(de)) == sizeof(de)) { - if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) + if (de.inum == 0 || is_special_dir(de.name)) continue; memmove(p, de.name, strlen(de.name)); p[strlen(de.name)] = 0; - if (stat(buf, &st) < 0) { - continue; - } + if (stat(buf, &st) < 0) continue; - // Check if it's a valid file with the correct extension if (st.type != T_DIR) { if (file_ext) { char *dot = strrchr(buf, '.'); if (dot && strcmp(dot, file_ext) == 0) { close(fd); - return 1; // Found a matching file + return 1; } } else { - close(fd); - return 1; // No extension filter, so any file is valid - } - } else { - // Recursively check the subdirectories - if (contains_valid_file(buf, file_ext)) { close(fd); return 1; } + } else if (contains_valid_file(buf, file_ext)) { + close(fd); + return 1; } } - close(fd); - return 0; // No valid files found + return 0; } @@ -94,100 +125,72 @@ int contains_valid_file(char *path, char *file_ext) { * @param show_count - flag indicating whether to display counts of directories and files */ void tree(char *path, int depth, int *last, char *file_ext, int show_size, int show_count, int limit_depth) { - char buf[512], *p; - int fd; - struct dirent de; - struct stat st; - - if (limit_depth != -1 && depth > limit_depth) { - return; - } + if (limit_depth != -1 && depth > limit_depth) return; - if ((fd = open(path, 0)) < 0) { - printf("tree: cannot open %s\n", path); - return; - } + int fd = open_directory(path); + if (fd < 0) return; + struct dirent de; + struct stat st; if (fstat(fd, &st) < 0) { - printf("tree: cannot stat %s\n", path); + fprintf(2, "tree: cannot stat %s\n", path); close(fd); return; } - - if (st.type == T_DIR) { - // Check if directory contains valid files when -F is applied and count directories and files when -C is applied + if (st.type == T_DIR) { int valid_for_print = (file_ext == 0 || contains_valid_file(path, file_ext)); - if (!show_count && valid_for_print) { print_tree_prefix(depth, last); printf("%s/\n", path); } - if (strlen(path) + 1 + DIRSIZ + 1 > sizeof buf) { - printf("tree: path too long\n"); - close(fd); - return; - } - + char buf[512], *p; strcpy(buf, path); p = buf + strlen(buf); *p++ = '/'; - int file_count = 0; - int dir_count = 0; + int file_count = 0, dir_count = 0; - // Count directories and files while (read(fd, &de, sizeof(de)) == sizeof(de)) { - if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) + if (de.inum == 0 || is_special_dir(de.name)) continue; memmove(p, de.name, strlen(de.name)); p[strlen(de.name)] = 0; - if (stat(buf, &st) < 0) { - continue; - } + if (stat(buf, &st) < 0) continue; - // Only count files that match the extension if -F is used - if (st.type == T_DIR) { - dir_count++; - } else if (!file_ext || (strrchr(buf, '.') && strcmp(strrchr(buf, '.'), file_ext) == 0)) { - file_count++; - } + if (st.type == T_DIR) dir_count++; + else if (!file_ext || (strrchr(buf, '.') && strcmp(strrchr(buf, '.'), file_ext) == 0)) file_count++; } - // Display count when -C is applied if (show_count) { print_tree_prefix(depth, last); printf("%s/ [%d directories, %d files]\n", path, dir_count, file_count); } close(fd); - fd = open(path, 0); + fd = open_directory(path); + if (fd < 0) return; int i = 0; while (read(fd, &de, sizeof(de)) == sizeof(de)) { - if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) - continue; + if (de.inum == 0 || is_special_dir(de.name)) continue; - char *saved_p = p; + char *saved_p = p; memmove(p, de.name, strlen(de.name)); p[strlen(de.name)] = 0; last[depth] = (i == dir_count + file_count - 1); - - // Recursive call to tree tree(buf, depth + 1, last, file_ext, show_size, show_count, limit_depth); - p = saved_p; i++; } } else { - // Handle file-specific logic if (file_ext) { char *dot = strrchr(path, '.'); if (!dot || strcmp(dot, file_ext) != 0) { - close(fd); // Skip files that don't match the extension + close(fd); return; } } @@ -204,28 +207,6 @@ void tree(char *path, int depth, int *last, char *file_ext, int show_size, int s close(fd); } - - -/** - * prints the prefix for the current tree level based on depth - * - * @param depth - current depth in the directory tree - * @param last - array indicating if the current node is the last in its level - */ -void print_tree_prefix(int depth, int *last) { - for (int i = 0; i < depth - 1; i++) { - if (last[i]) - printf(" "); - else - printf("│ "); - } - if (depth > 0) { - if (last[depth - 1]) - printf("└── "); - else - printf("├── "); - } -} /** @@ -244,16 +225,24 @@ int main(int argc, char *argv[]) { for (int i = 1; i < argc; i++) { - if (strcmp(argv[i], "-F") == 0 && i + 1 < argc) { - file_ext = argv[i + 1]; - i++; + if (strcmp(argv[i], "-F") == 0) { + if (i + 1 < argc) { + file_ext = argv[++i]; + } else { + fprintf(2, "tree: missing argument for -F\n"); + exit(1); + } } else if (strcmp(argv[i], "-S") == 0) { show_size = 1; - } else if (strcmp(argv[i], "-C") == 0) { + } else if (strcmp(argv[i], "-C") == 0) { show_count = 1; } else if (strcmp(argv[i], "-L") == 0) { - limit_depth = atoi(argv[i+1]); - i++; + if (i + 1 < argc) { + limit_depth = atoi(argv[++i]); + } else { + fprintf(2, "tree: missing argument for -L\n"); + exit(1); + } } else { start_dir = argv[i]; } @@ -261,8 +250,6 @@ int main(int argc, char *argv[]) { int last[128]; memset(last, 0, sizeof(last)); - tree(start_dir, 0, last, file_ext, show_size, show_count, limit_depth); - exit(0); } From a71167035c667cd53ad6961530b9ce5de330dca0 Mon Sep 17 00:00:00 2001 From: Chandana Srinivas Date: Thu, 31 Oct 2024 23:34:24 -0700 Subject: [PATCH 19/24] tree implementation revised --- user/tree.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/user/tree.c b/user/tree.c index fab447f..45ab406 100644 --- a/user/tree.c +++ b/user/tree.c @@ -141,10 +141,11 @@ void tree(char *path, int depth, int *last, char *file_ext, int show_size, int s int valid_for_print = (file_ext == 0 || contains_valid_file(path, file_ext)); if (!show_count && valid_for_print) { print_tree_prefix(depth, last); - printf("%s/\n", path); + printf("%s/\n", strrchr(path, '/')); } - char buf[512], *p; + char buf[512] = ""; + char *p; strcpy(buf, path); p = buf + strlen(buf); *p++ = '/'; @@ -198,9 +199,9 @@ void tree(char *path, int depth, int *last, char *file_ext, int show_size, int s if (!show_count) { print_tree_prefix(depth, last); if (show_size) { - printf("%s (size: %d bytes)\n", path, st.size); + printf("%s (size: %d bytes)\n", strrchr(path, '/') + 1, st.size); } else { - printf("%s\n", path); + printf("%s\n", strrchr(path, '/') ); } } } From 2a6b921575e401c1bea6914b5a2351f5e56c1dfb Mon Sep 17 00:00:00 2001 From: Riya Mathur Date: Fri, 1 Nov 2024 10:09:08 -0700 Subject: [PATCH 20/24] Improved error handling for flag parsing --- test.txt | 1 - testfile.txt | 1 + user/tree.c | 44 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 39 insertions(+), 7 deletions(-) delete mode 100644 test.txt create mode 100644 testfile.txt diff --git a/test.txt b/test.txt deleted file mode 100644 index fc37b3a..0000000 --- a/test.txt +++ /dev/null @@ -1 +0,0 @@ -Hi - Suhani diff --git a/testfile.txt b/testfile.txt new file mode 100644 index 0000000..b14df64 --- /dev/null +++ b/testfile.txt @@ -0,0 +1 @@ +Hi diff --git a/user/tree.c b/user/tree.c index 45ab406..8717ee1 100644 --- a/user/tree.c +++ b/user/tree.c @@ -137,7 +137,8 @@ void tree(char *path, int depth, int *last, char *file_ext, int show_size, int s close(fd); return; } - if (st.type == T_DIR) { + + if (st.type == T_DIR) { int valid_for_print = (file_ext == 0 || contains_valid_file(path, file_ext)); if (!show_count && valid_for_print) { print_tree_prefix(depth, last); @@ -153,8 +154,7 @@ void tree(char *path, int depth, int *last, char *file_ext, int show_size, int s int file_count = 0, dir_count = 0; while (read(fd, &de, sizeof(de)) == sizeof(de)) { - if (de.inum == 0 || is_special_dir(de.name)) - continue; + if (de.inum == 0 || is_special_dir(de.name)) continue; memmove(p, de.name, strlen(de.name)); p[strlen(de.name)] = 0; @@ -165,9 +165,33 @@ void tree(char *path, int depth, int *last, char *file_ext, int show_size, int s else if (!file_ext || (strrchr(buf, '.') && strcmp(strrchr(buf, '.'), file_ext) == 0)) file_count++; } - if (show_count) { + if (show_count && show_size) { print_tree_prefix(depth, last); printf("%s/ [%d directories, %d files]\n", path, dir_count, file_count); + + close(fd); + fd = open_directory(path); + if (fd < 0) return; + + while (read(fd, &de, sizeof(de)) == sizeof(de)) { + if (de.inum == 0 || is_special_dir(de.name)) continue; + + memmove(p, de.name, strlen(de.name)); + p[strlen(de.name)] = 0; + + if (stat(buf, &st) < 0) continue; + + if (st.type != T_DIR) { + print_tree_prefix(depth + 1, last); + printf("└── %s (size: %d bytes)\n", de.name, st.size); + } + } + } else if (show_count) { + print_tree_prefix(depth, last); + printf("%s/ [%d directories, %d files]\n", path, dir_count, file_count); + } else if (show_size) { + print_tree_prefix(depth, last); + printf("%s (size: %d bytes)\n", strrchr(path, '/') + 1, st.size); } close(fd); @@ -201,7 +225,7 @@ void tree(char *path, int depth, int *last, char *file_ext, int show_size, int s if (show_size) { printf("%s (size: %d bytes)\n", strrchr(path, '/') + 1, st.size); } else { - printf("%s\n", strrchr(path, '/') ); + printf("%s\n", strrchr(path, '/')); } } } @@ -228,7 +252,12 @@ int main(int argc, char *argv[]) { for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "-F") == 0) { if (i + 1 < argc) { - file_ext = argv[++i]; + if (argv[i+1][0] == '.') { + file_ext = argv[++i]; + } else { + fprintf(2, "tree: invalid value for -F\n"); + exit(1); + } } else { fprintf(2, "tree: missing argument for -F\n"); exit(1); @@ -244,6 +273,9 @@ int main(int argc, char *argv[]) { fprintf(2, "tree: missing argument for -L\n"); exit(1); } + } else if (argv[i][0] == '-') { + fprintf(2, "tree: invalid flag %s\n", argv[i]); + exit(1); } else { start_dir = argv[i]; } From 1e82107432b7951e3e9544fa06e059f656affb17 Mon Sep 17 00:00:00 2001 From: Chandana Srinivas Date: Fri, 1 Nov 2024 10:26:58 -0700 Subject: [PATCH 21/24] cr changes --- user/tree.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/user/tree.c b/user/tree.c index 8717ee1..c4b230c 100644 --- a/user/tree.c +++ b/user/tree.c @@ -10,7 +10,8 @@ * @param depth - current depth in the directory tree * @param last - array indicating if the current node is the last in its level */ -void print_tree_prefix(int depth, int *last) { +void +print_tree_prefix(int depth, int *last) { for (int i = 0; i < depth - 1; i++) { if (last[i]) printf(" "); @@ -31,7 +32,8 @@ void print_tree_prefix(int depth, int *last) { * @param name - name of dir to check * @return 1 - if it is a special dir */ -int is_special_dir(const char *name) { +int +is_special_dir(const char *name) { return strcmp(name, ".") == 0 || strcmp(name, "..") == 0; } @@ -41,7 +43,8 @@ int is_special_dir(const char *name) { * @param path - path of the dir to open * @return - file descriptor for the opened dir */ -int open_directory(const char *path) { +int +open_directory(const char *path) { int fd = open(path, 0); if (fd < 0) { fprintf(2, "tree: cannot open %s\n", path); @@ -56,7 +59,8 @@ int open_directory(const char *path) { * @param c - character to find * @return - pointer to the last occurrence of the char in the string */ -char* strrchr(const char* s, int c) { +char* +strrchr(const char* s, int c) { const char* last = 0; for (; *s; s++) { if (*s == (char)c) { @@ -73,7 +77,8 @@ char* strrchr(const char* s, int c) { * @param file_ext - file ext to look for * @return - 1 if a valid file is found and 0 otherwise */ -int contains_valid_file(char *path, char *file_ext) { +int +contains_valid_file(char *path, char *file_ext) { char buf[512], *p; int fd = open_directory(path); if (fd < 0) return 0; @@ -124,7 +129,8 @@ int contains_valid_file(char *path, char *file_ext) { * @param show_size - flag indicating whether to display file sizes * @param show_count - flag indicating whether to display counts of directories and files */ -void tree(char *path, int depth, int *last, char *file_ext, int show_size, int show_count, int limit_depth) { +void +tree(char *path, int depth, int *last, char *file_ext, int show_size, int show_count, int limit_depth) { if (limit_depth != -1 && depth > limit_depth) return; int fd = open_directory(path); @@ -142,7 +148,7 @@ void tree(char *path, int depth, int *last, char *file_ext, int show_size, int s int valid_for_print = (file_ext == 0 || contains_valid_file(path, file_ext)); if (!show_count && valid_for_print) { print_tree_prefix(depth, last); - printf("%s/\n", strrchr(path, '/')); + printf("%.256s/\n", strrchr(path, '/')); } char buf[512] = ""; @@ -225,7 +231,7 @@ void tree(char *path, int depth, int *last, char *file_ext, int show_size, int s if (show_size) { printf("%s (size: %d bytes)\n", strrchr(path, '/') + 1, st.size); } else { - printf("%s\n", strrchr(path, '/')); + printf("%.256s/\n", strrchr(path, '/')); } } } @@ -241,7 +247,8 @@ void tree(char *path, int depth, int *last, char *file_ext, int show_size, int s * @param argv - array of command-line argument strings * @return - 0 on successful tree traversal and printing */ -int main(int argc, char *argv[]) { +int +main(int argc, char *argv[]) { char *start_dir = "."; char *file_ext = 0; int show_size = 0; From 40fbe27904784bdc88b79bc5603f913382d5a3ef Mon Sep 17 00:00:00 2001 From: Chandana Srinivas Date: Fri, 1 Nov 2024 11:11:14 -0700 Subject: [PATCH 22/24] fix print statements --- user/tree.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/user/tree.c b/user/tree.c index c4b230c..2818488 100644 --- a/user/tree.c +++ b/user/tree.c @@ -148,7 +148,7 @@ tree(char *path, int depth, int *last, char *file_ext, int show_size, int show_c int valid_for_print = (file_ext == 0 || contains_valid_file(path, file_ext)); if (!show_count && valid_for_print) { print_tree_prefix(depth, last); - printf("%.256s/\n", strrchr(path, '/')); + printf("%s/\n", strrchr(path, '/')); } char buf[512] = ""; @@ -197,7 +197,7 @@ tree(char *path, int depth, int *last, char *file_ext, int show_size, int show_c printf("%s/ [%d directories, %d files]\n", path, dir_count, file_count); } else if (show_size) { print_tree_prefix(depth, last); - printf("%s (size: %d bytes)\n", strrchr(path, '/') + 1, st.size); + printf("%s (size: %d bytes)\n", strrchr(path, '/'), st.size); } close(fd); @@ -229,9 +229,9 @@ tree(char *path, int depth, int *last, char *file_ext, int show_size, int show_c if (!show_count) { print_tree_prefix(depth, last); if (show_size) { - printf("%s (size: %d bytes)\n", strrchr(path, '/') + 1, st.size); + printf("%s (size: %d bytes)\n", strrchr(path, '/'), st.size); } else { - printf("%.256s/\n", strrchr(path, '/')); + printf("%s/\n", strrchr(path, '/') ); } } } From e2ffc8f8ad7d291d9ece0ddbd274890fc512cfe9 Mon Sep 17 00:00:00 2001 From: Riya Mathur Date: Fri, 8 Nov 2024 14:47:37 -0800 Subject: [PATCH 23/24] dynamic allocation for nested directories --- user/tree.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/user/tree.c b/user/tree.c index 2818488..9cf6c3e 100644 --- a/user/tree.c +++ b/user/tree.c @@ -79,10 +79,18 @@ strrchr(const char* s, int c) { */ int contains_valid_file(char *path, char *file_ext) { - char buf[512], *p; + char *buf = malloc(512); + if (!buf) { + fprintf(2, "tree: memory allocation failed\n"); + return 0; + } + char *p; int fd = open_directory(path); - if (fd < 0) return 0; - + if (fd < 0) { + free(buf); + return 0; + } + struct dirent de; struct stat st; strcpy(buf, path); @@ -144,6 +152,7 @@ tree(char *path, int depth, int *last, char *file_ext, int show_size, int show_c return; } + if (st.type == T_DIR) { int valid_for_print = (file_ext == 0 || contains_valid_file(path, file_ext)); if (!show_count && valid_for_print) { @@ -151,7 +160,12 @@ tree(char *path, int depth, int *last, char *file_ext, int show_size, int show_c printf("%s/\n", strrchr(path, '/')); } - char buf[512] = ""; + char *buf = malloc(512); + if (!buf) { + fprintf(2, "tree: memory allocation failed\n"); + close(fd); + return; + } char *p; strcpy(buf, path); p = buf + strlen(buf); From fcec5b2e70764bdcab8fd36ac38d616c238bdc30 Mon Sep 17 00:00:00 2001 From: Riya Mathur Date: Fri, 8 Nov 2024 15:03:19 -0800 Subject: [PATCH 24/24] dynamic allocation for nested directories --- user/tree.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/user/tree.c b/user/tree.c index 9cf6c3e..814f719 100644 --- a/user/tree.c +++ b/user/tree.c @@ -122,6 +122,7 @@ contains_valid_file(char *path, char *file_ext) { return 1; } } + free(buf); close(fd); return 0; } @@ -153,6 +154,17 @@ tree(char *path, int depth, int *last, char *file_ext, int show_size, int show_c } + char *buf = malloc(512); + if (!buf) { + fprintf(2, "tree: memory allocation failed\n"); + close(fd); + return; + } + char *p; + strcpy(buf, path); + p = buf + strlen(buf); + *p++ = '/'; + if (st.type == T_DIR) { int valid_for_print = (file_ext == 0 || contains_valid_file(path, file_ext)); if (!show_count && valid_for_print) { @@ -160,17 +172,6 @@ tree(char *path, int depth, int *last, char *file_ext, int show_size, int show_c printf("%s/\n", strrchr(path, '/')); } - char *buf = malloc(512); - if (!buf) { - fprintf(2, "tree: memory allocation failed\n"); - close(fd); - return; - } - char *p; - strcpy(buf, path); - p = buf + strlen(buf); - *p++ = '/'; - int file_count = 0, dir_count = 0; while (read(fd, &de, sizeof(de)) == sizeof(de)) { @@ -249,7 +250,7 @@ tree(char *path, int depth, int *last, char *file_ext, int show_size, int show_c } } } - + free(buf); close(fd); }