diff --git a/Makefile b/Makefile index 2584e4a..cc9b482 100644 --- a/Makefile +++ b/Makefile @@ -116,6 +116,7 @@ mkfs/mkfs: mkfs/mkfs.c $K/fs.h $K/param.h .PRECIOUS: %.o UPROGS=\ + $U/_man\ $U/_cat\ $U/_echo\ $U/_forktest\ @@ -133,8 +134,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 docs $(UPROGS) + mkfs/mkfs fs.img README.md docs $(UPROGS) -include kernel/*.d user/*.d diff --git a/docs/fogos.gif b/docs/fogos.gif deleted file mode 100644 index e8c8299..0000000 Binary files a/docs/fogos.gif and /dev/null differ diff --git a/docs/man.md b/docs/man.md new file mode 100644 index 0000000..e2c4cb7 --- /dev/null +++ b/docs/man.md @@ -0,0 +1,29 @@ +Instruction Page Manual: man() + +NAME + man: An interface to systems reference manuals + +SYNOPSIS + man[man options] + +DESCRIPTION + Manual instruction framwork for various xv6 functions and programs. Man + allows for easy documentation and help within the operating system, + displaying the requested man page. + +EXAMPLES + man - brings up the man page for man() + + man ls - brings up the man page for ls() + + man man -f grow - brings up the man page for man() then searchs for the + word "grow", showing only lines containing it + +OPTIONS + -f - Flag for find + +HISTORY + 9/23/24 - Creation + +AUTHOR + Written by Daniel Truong 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) diff --git a/user/man.c b/user/man.c new file mode 100644 index 0000000..8fff562 --- /dev/null +++ b/user/man.c @@ -0,0 +1,142 @@ +#include "kernel/types.h" +#include "kernel/stat.h" +#include "user/user.h" +#include "kernel/fcntl.h" +#include "stdbool.h" +#include "stddef.h" + +/*** + * Helped function for the find flag, seeing if the line contains the word + * + * @param line line to be read + * @return true if found, false if not + */ +bool +find(char* line, char* word) +{ + int lineLen = strlen(line); + int wordLen = strlen(word); + int readableLen = lineLen - wordLen; + char *linePtr = line; + char *wordPtr = word; + int count = 0; + + if(readableLen < 0) + return false; + + for(int i = 0; i < readableLen; i++){ + for(int j = 0; j < wordLen; j++){ + if(linePtr[j] != wordPtr[j]) + break; + count++; + } + if(count == wordLen) + return true; + linePtr++; + count = 0; + } + return false; +} + +/*** + * Concatenating function for strings, automatically appends the .md file extension + * + * @param dst destination string to concatenate to + * @param src source string to concatenate from + */ +void +strcat(char *dst, char *src) +{ + int startLen = strlen(dst); + int combLen = strlen(dst) + strlen(src) + 1; + int i = 0; + + for(i = startLen; i < combLen ; i++){ + dst[i] = src[i-startLen]; + } + + dst[i] = '\0'; +} + +/*** + * Man command to print and afind man page + * + * @param path name of wanted manpage + * @param f flag for find functionality + * @param word word wanted to be found + */ +void +man(char *path, bool f, char *word) +{ + int i = 0;int foundLines = 0; + char *arg = path; + uint size = 256; + char *manPage = malloc(size); + if(manPage == NULL){ + exit(0); + } + + char manPath[128]; + char suffix[] = ".md"; + strcat(manPath, "docs/"); + strcat(manPath, arg); + strcat(manPath, suffix); + + int fd = open(manPath, O_RDONLY); + if(fd <= 0){ + printf("Man error: %s\nNo such man page exists\n", manPath); + exit(0); + } + + while(true){ + int bytes = getline(&manPage, &size, fd); + i++; + + if(f == false){ + printf("%s", manPage); + }else if(find(manPage, word)){ + printf("%d:%s", i, manPage); + foundLines++; + } + + if(bytes <= 0){ + break; + } + } + + if(f == true && foundLines == 0) + printf("%s not found in man page", word); + + printf("\n"); + free(manPage); +} + +int +main(int argc, char *argv[]) +{ + if(argc > 1 && strlen(argv[1]) + 8 > 128){ + printf("Man error: Argument exceeds path limit\n"); + exit(0); + }if(argc > 4){ + printf("Man error: Too many arguments, limit of 4\n"); + exit(0); + }if(argc > 2 && strcmp(argv[2], "-f") != 0){ + printf("Man error: Unknown Flag\n"); + exit(0); + }if(argc == 3){ + printf("Man error: Term needed for find\n"); + exit(0); + } + + if(argc < 2){ + man("man", false, NULL); + exit(0); + }else if(argc == 2){ + man(argv[1], false, NULL); + }else if(argc == 4){ + man(argv[1], true, argv[3]); + } + + exit(0); +} +