Operating Systems - File System

Posted Under: Operating Systems

Ask A Question
DESCRIPTION
Posted
Modified
Viewed 34
This is the C assignment. The instruction is in the README file. We need to run the program via terminal of ubuntu (Use the "make" and "make run"). In this assignment, you need to leave the comment in details on the code. After you are done, you need to help me write 2 writeup. The deadline is Nov 25 ?_________________ ?The first writeup is for this project, the requirement below: 1. A description of your file system 2. Issues you had 3. Detail of how your driver program works. 4. Screen shots showing each of the commands listed in the readme. _________________ ??The second writeup is for individual. I attached the template below. I also attached the "step for file system design" file which can help you design file system.
Attachments
csc415-filesystem-anhduynguyen8598/b_io.c /************************************************************** * Class: CSC-415-0# Fall 2021 * Names: * Student IDs: * GitHub Name: * Group Name: * Project: Basic File System * * File: b_io.c * * Description: Basic File System - Key File I/O Operations * **************************************************************/ #include <stdio.h> #include <unistd.h> #include <stdlib.h> // for malloc #include <string.h> // for memcpy #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "b_io.h" #define MAXFCBS 20 #define B_CHUNK_SIZE 512 typedef struct b_fcb { /** TODO add al the information you need in the file control block **/ char * buf; //holds the open file buffer int index; //holds the current position in the buffer int buflen; //holds how many valid bytes are in the buffer } b_fcb; b_fcb fcbArray[MAXFCBS]; int startup = 0; //Indicates that this has not been initialized //Method to initialize our file system void b_init () { //init fcbArray to all free for (int i = 0; i < MAXFCBS; i++) { fcbArray[i].buf = NULL; //indicates a free fcbArray } startup = 1; } //Method to get a free FCB element b_io_fd b_getFCB () { for (int i = 0; i < MAXFCBS; i++) { if (fcbArray[i].buff == NULL) { return i; //Not thread safe (But do not worry about it for this assignment) } } return (-1); //all in use } // Interface to open a buffered file // Modification of interface for this assignment, flags match the Linux flags for open // O_RDONLY, O_WRONLY, or O_RDWR b_io_fd b_open (char * filename, int flags) { b_io_fd returnFd; //*** TODO ***: Modify to save or set any information needed // // if (startup == 0) b_init(); //Initialize our system returnFd = b_getFCB(); // get our own file descriptor // check for error - all used FCB's return (returnFd); // all set } // Interface to seek function int b_seek (b_io_fd fd, off_t offset, int whence) { if (startup == 0) b_init(); //Initialize our system // check that fd is between 0 and (MAXFCBS-1) if ((fd < 0) || (fd >= MAXFCBS)) { return (-1); //invalid file descriptor } return (0); //Change this } // Interface to write function int b_write (b_io_fd fd, char * buffer, int count) { if (startup == 0) b_init(); //Initialize our system // check that fd is between 0 and (MAXFCBS-1) if ((fd < 0) || (fd >= MAXFCBS)) { return (-1); //invalid file descriptor } return (0); //Change this } // Interface to read a buffer // Filling the callers request is broken into three parts // Part 1 is what can be filled from the current buffer, which may or may not be enough // Part 2 is after using what was left in our buffer there is still 1 or more block // size chunks needed to fill the callers request. This represents the number of // bytes in multiples of the blocksize. // Part 3 is a value less than blocksize which is what remains to copy to the callers buffer // after fulfilling part 1 and part 2. This would always be filled from a refill // of our buffer. // +-------------+------------------------------------------------+--------+ // | | | | // | filled from | filled direct in multiples of the block size | filled | // | existing | | from | // | buffer | |refilled| // | | | buffer | // | | | | // | Part1 | Part 2 | Part3 | // +-------------+------------------------------------------------+--------+ int b_read (b_io_fd fd, char * buffer, int count) { if (startup == 0) b_init(); //Initialize our system // check that fd is between 0 and (MAXFCBS-1) if ((fd < 0) || (fd >= MAXFCBS)) { return (-1); //invalid file descriptor } return (0); //Change this } // Interface to Close the file void b_close (b_io_fd fd) { } csc415-filesystem-anhduynguyen8598/Makefile # File: Standard Makefile for CSC415 # # Description - This make file should be used for all your projects # It should be modified as needed for each homework # # ROOTNAME should be set you your lastname_firstname_HW. Except for # and group projects, this will not change throughout the semester # # HW should be set to the assignment number (i.e. 1, 2, 3, etc.) # # FOPTION can be set to blank (nothing) or to any thing starting with an # underscore (_). This is the suffix of your file name. # # With these three options above set your filename for your homework # assignment will look like: bierman_robert_HW1_main.c # # RUNOPTIONS can be set to default values you want passed into the program # this can also be overridden on the command line # # OBJ - You can append to this line for additional files necessary for # your program, but only when you have multiple files. Follow the convention # but hard code the suffix as needed. # # To Use the Makefile - Edit as above # then from the command line run: make # That command will build your program, and the program will be named the same # as your main c file without an extension. # # You can then execute from the command line: make run # This will actually run your program # # Using the command: make clean # will delete the executable and any object files in your directory. # ROOTNAME=fsshell HW= FOPTION= RUNOPTIONS=SampleVolume 10000000 512 CC=gcc CFLAGS= -g -I. LIBS =pthread DEPS = # Add any additional objects to this list ADDOBJ= fsInit.o ARCH = $(shell uname -m) ifeq ($(ARCH), aarch64) ARCHOBJ=fsLowM1.o else ARCHOBJ=fsLow.o endif OBJ = $(ROOTNAME)$(HW)$(FOPTION).o $(ADDOBJ) $(ARCHOBJ) %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) $(ROOTNAME)$(HW)$(FOPTION): $(OBJ) $(CC) -o $@ $^ $(CFLAGS) -lm -l readline -l $(LIBS) clean: rm $(ROOTNAME)$(HW)$(FOPTION).o $(ADDOBJ) $(ROOTNAME)$(HW)$(FOPTION) run: $(ROOTNAME)$(HW)$(FOPTION) ./$(ROOTNAME)$(HW)$(FOPTION) $(RUNOPTIONS) csc415-filesystem-anhduynguyen8598/fsshell.c /************************************************************** * Class: CSC-415-0# - Fall 2021 * Names: * Student IDs: * GitHub Name: * Group Name: * Project: Basic File System * * File: fsShell.c * * Description: Main driver for file system assignment. * * Make sure to set the #defined on the CMDxxxx_ON from 0 to 1 * when you are ready to test that feature * **************************************************************/ #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <stdio.h> #include <readline/readline.h> #include <readline/history.h> #include <getopt.h> #include <string.h> #include "fsLow.h" #include "mfs.h" #define SINGLE_QUOTE 0x27 #define DOUBLE_QUOTE 0x22 #define BUFFERLEN 200 #define DIRMAX_LEN 4096 /**** SET THESE TO 1 WHEN READY TO TEST THAT COMMAND ****/ #define CMDLS_ON 0 #define CMDCP_ON 0 #define CMDMV_ON 0 #define CMDMD_ON 0 #define CMDRM_ON 0 #define CMDCP2L_ON 0 #define CMDCP2FS_ON 0 #define CMDCD_ON 0 #define CMDPWD_ON 0 typedef struct dispatch_t { char * command; int (*func)(int, char**); char * description; } dispatch_t, * dispatch_p; int cmd_ls (int argcnt, char *argvec[]); int cmd_cp (int argcnt, char *argvec[]); int cmd_mv (int argcnt, char *argvec[]); int cmd_md (int argcnt, char *argvec[]); int cmd_rm (int argcnt, char *argvec[]); int cmd_cp2l (int argcnt, char *argvec[]); int cmd_cp2fs (int argcnt, char *argvec[]); int cmd_cd (int argcnt, char *argvec[]); int cmd_pwd (int argcnt, char *argvec[]); int cmd_history (int argcnt, char *argvec[]); int cmd_help (int argcnt, char *argvec[]); dispatch_t dispatchTable[] = { {"ls", cmd_ls, "Lists the file in a directory"}, {"cp", cmd_cp, "Copies a file - source [dest]"}, {"mv", cmd_mv, "Moves a file - source dest"}, {"md", cmd_md, "Make a new directory"}, {"rm", cmd_rm, "Removes a file or directory"}, {"cp2l", cmd_cp2l, "Copies a file from the test file system to the linux file system"}, {"cp2fs", cmd_cp2fs, "Copies a file from the Linux file system to the test file system"}, {"cd", cmd_cd, "Changes directory"}, {"pwd", cmd_pwd, "Prints the working directory"}, {"history", cmd_history, "Prints out the history"}, {"help", cmd_help, "Prints out help"} }; static int dispatchcount = sizeof (dispatchTable) / sizeof (dispatch_t); // Display files for use by ls command int displayFiles (fdDir * dirp, int flall, int fllong) { #if (CMDLS_ON == 1) if (dirp == NULL) //get out if error return (-1); struct fs_diriteminfo * di; struct fs_stat statbuf; di = fs_readdir (dirp); printf("\n"); while (di != NULL) { if ((di->d_name[0] != '.') || (flall)) //if not all and starts with '.' it is hidden { if (fllong) { fs_stat (di->d_name, &statbuf); printf ("%s %9ld %s\n", fs_isDir(di->d_name)?"D":"-", statbuf.st_size, di->d_name); } else { printf ("%s\n", di->d_name); } } di = fs_readdir (dirp); } fs_closedir (dirp); #endif return 0; } /**************************************************** * ls commmand ****************************************************/ int cmd_ls (int argcnt, char *argvec[]) { #if (CMDLS_ON == 1) int option_index; int c; int fllong; int flall; char cwd[DIRMAX_LEN]; static struct option long_options[] = { /* These options set their assigned flags to value and return 0 */ /* These options don't set flags and return the value */ {"long", no_argument, 0, 'l'}, {"all", no_argument, 0, 'a'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0 } }; option_index = 0; #ifdef __GNU_LIBRARY__ // WORKAROUND // Setting "optind" to 0 triggers initialization of getopt private // structure (holds pointers on data between calls). This helps // to avoid possible memory violation, because data passed to getopt_long() // could be freed between parse() calls. optind = 0; #else // "optind" is used between getopt() calls to get next argument for parsing and should be // initialized before each parsing loop. optind = 1; #endif fllong = 0; flall = 0; while (1) { c = getopt_long(argcnt, argvec, "alh", long_options, &option_index); if (c == -1) break; switch (c) { case 0: //flag was set, ignore printf("Unknown option %s", long_options[option_index].name); if (optarg) printf(" with arg %s", optarg); printf("\n"); break; case 'a': flall = 1; break; case 'l': fllong = 1; break; case 'h': default: printf ("Usage: ls [--all-a] [--long/-l] [pathname]\n"); return (-1); break; } } if (optind < argcnt) { //processing arguments after options for (int k = optind; k < argcnt; k++) { if (fs_isDir(argvec[k])) { fdDir * dirp; dirp = fs_opendir (argvec[k]); displayFiles (dirp, flall, fllong); } else // it is just a file ? { if (fs_isFile (argvec[k])) { //no support for long format here printf ("%s\n", argvec[k]); } else { printf ("%s is not found\n", argvec[k]); } } } } else // no pathname/filename specified - use cwd { char * path = fs_getcwd(cwd, DIRMAX_LEN); //get current working directory fdDir * dirp; dirp = fs_opendir (path); return (displayFiles (dirp, flall, fllong)); } #endif return 0; } /**************************************************** * Copy file commmand ****************************************************/ int cmd_cp (int argcnt, char *argvec[]) { #if (CMDCP_ON == 1) int testfs_src_fd; int testfs_dest_fd; char * src; char * dest; int readcnt; char buf[BUFFERLEN]; switch (argcnt) { case 2: //only one name provided src = argvec[1]; dest = src; break; case 3: src = argvec[1]; dest = argvec[2]; break; default: printf("Usage: cp srcfile [destfile]\n"); return (-1); } testfs_src_fd = b_open (src, O_RDONLY); testfs_dest_fd = b_open (dest, O_WRONLY | O_CREAT | O_TRUNC); do { readcnt = b_read (testfs_src_fd, buf, BUFFERLEN); b_write (testfs_dest_fd, buf, readcnt); } while (readcnt == BUFFERLEN); b_close (testfs_src_fd); b_close (testfs_dest_fd); #endif return 0; } /**************************************************** * Move file commmand ****************************************************/ int cmd_mv (int argcnt, char *argvec[]) { #if (CMDMV_ON == 1) return -99; // **** TODO **** For you to implement #endif return 0; } /**************************************************** * Make Directory commmand ****************************************************/ // Make Directory int cmd_md (int argcnt, char *argvec[]) { #if (CMDMD_ON == 1) if (argcnt != 2) { printf("Usage: md pathname\n"); return -1; } else { return(fs_mkdir(argvec[1], 0777)); } #endif return -1; } /**************************************************** * Remove directory or file commmand ****************************************************/ int cmd_rm (int argcnt, char *argvec[]) { #if (CMDRM_ON == 1) if (argcnt != 2) { printf ("Usage: rm path\n"); return -1; } char * path = argvec[1]; //must determine if file or directory if (fs_isDir (path)) { return (fs_rmdir (path)); } if (fs_isFile (path)) { return (fs_delete(path)); } printf("The path %s is neither a file not a directory\n", path); #endif return -1; } /**************************************************** * Copy file from test file system to Linux commmand ****************************************************/ int cmd_cp2l (int argcnt, char *argvec[]) { #if (CMDCP2L_ON == 1) int testfs_fd; int linux_fd; char * src; char * dest; int readcnt; char buf[BUFFERLEN]; switch (argcnt) { case 2: //only one name provided src = argvec[1]; dest = src; break; case 3: src = argvec[1]; dest = argvec[2]; break; default: printf("Usage: cp2l srcfile [Linuxdestfile]\n"); return (-1); } testfs_fd = b_open (src, O_RDONLY); linux_fd = open (dest, O_WRONLY | O_CREAT | O_TRUNC); do { readcnt = b_read (testfs_fd, buf, BUFFERLEN); write (linux_fd, buf, readcnt); } while (readcnt == BUFFERLEN); b_close (testfs_fd); close (linux_fd); #endif return 0; } /**************************************************** * Copy file from Linux to test file system commmand ****************************************************/ int cmd_cp2fs (int argcnt, char *argvec[]) { #if (CMDCP2FS_ON == 1) int testfs_fd; int linux_fd; char * src; char * dest; int readcnt; char buf[BUFFERLEN]; switch (argcnt) { case 2: //only one name provided src = argvec[1]; dest = src; break; case 3: src = argvec[1]; dest = argvec[2]; break; default: printf("Usage: cp2fs Linuxsrcfile [destfile]\n"); return (-1); } testfs_fd = b_open (dest, O_WRONLY | O_CREAT | O_TRUNC); linux_fd = open (src, O_RDONLY); do { readcnt = read (linux_fd, buf, BUFFERLEN); b_write (testfs_fd, buf, readcnt); } while (readcnt == BUFFERLEN); b_close (testfs_fd); close (linux_fd); #endif return 0; } /**************************************************** * cd commmand ****************************************************/ int cmd_cd (int argcnt, char *argvec[]) { #if (CMDCD_ON == 1) if (argcnt != 2) { printf ("Usage: cd path\n"); return (-1); } char * path = argvec[1]; //argument if (path[0] == '"') { if (path[strlen(path)-1] == '"') { //remove quotes from string path = path + 1; path[strlen(path) - 1] = 0; } } int ret = fs_setcwd (path); if (ret != 0) //error { printf ("Could not change path to %s\n", path); return (ret); } #endif return 0; } /**************************************************** * PWD commmand ****************************************************/ int cmd_pwd (int argcnt, char *argvec[]) { #if (CMDPWD_ON == 1) char * dir_buf = malloc (DIRMAX_LEN +1); char * ptr; ptr = fs_getcwd (dir_buf, DIRMAX_LEN); if (ptr == NULL) //an error occurred { printf ("An error occurred while trying to get the current working directory\n"); } else { printf ("%s\n", ptr); } free (dir_buf); dir_buf = NULL; ptr = NULL; #endif return 0; } /**************************************************** * History commmand ****************************************************/ int cmd_history (int argcnt, char *argvec[]) { HIST_ENTRY * he; int i = 0; for (i = history_base; i <= history_length; i++) { he = history_get(i); if (he != NULL) { printf ("%s\n", he->line); } } return 0; } /**************************************************** * Help commmand ****************************************************/ int cmd_help (int argcnt, char *argvec[]) { for (int i = 0; i < dispatchcount; i++) { printf ("%s\t%s\n", dispatchTable[i].command, dispatchTable[i].description); } return 0; } void processcommand (char * cmd) { int cmdLen; char ** cmdv; //command vector int cmdc; //command count int i, j; cmdLen = strlen(cmd); cmdv = (char **) malloc (sizeof(char *) * ((cmdLen/2)+2)); cmdc = 0; cmdv[cmdc] = cmd; ++cmdc; for (i = 0; i < cmdLen; i++) { switch (cmd[i]) { case ' ': cmd[i] = 0; //NULL terminate prior string while (cmd[i+1] == ' ') // null at end will prevent from overshooting string { i++; } if ((i+1) < cmdLen) //there is still more { cmdv[cmdc] = &cmd[i+1]; ++cmdc; } break; case '\\': ++i; //skip next character break; case DOUBLE_QUOTE: //ignore everything till next quote (unless unterminated) for (j = i+1; j < cmdLen; j++) { if (cmd[j] == '\\') { ++j; //skip next character } else if (cmd[j] == DOUBLE_QUOTE) { break; } } if (j >= cmdLen) { printf("Unterminated string\n"); free(cmdv); cmdv = NULL; return; } i=j; break; case SINGLE_QUOTE: for (j = i+1; j < cmdLen; j++) { if (cmd[j] == '\\') { ++j; //skip next character } else if (cmd[j] == SINGLE_QUOTE) { break; } } if (j >= cmdLen) { printf("Unterminated string\n"); free(cmdv); cmdv = NULL; return; } i=j; break; default: break; } } #ifdef COMMAND_DEBUG for (i = 0; i < cmdc; i++) { printf("%s: length %d\n", cmdv[i], strlen(cmdv[i])); } #endif cmdv[cmdc] = 0; //just be safe - null terminate array of arguments for (i = 0; i < dispatchcount; i++) { if (strcmp(dispatchTable[i].command, cmdv[0]) == 0) { dispatchTable[i].func(cmdc,cmdv); free (cmdv); cmdv = NULL; return; } } printf("%s is not a regonized command.\n", cmdv[0]); cmd_help(cmdc, cmdv); free (cmdv); cmdv = NULL; } int main (int argc, char * argv[]) { char * cmdin; char * cmd; HIST_ENTRY *he; char * filename; uint64_t volumeSize; uint64_t blockSize; int retVal; if (argc > 3) { filename = argv[1]; volumeSize = atoll (argv[2]); blockSize = atoll (argv[3]); } else { printf ("Usage: fsLowDriver volumeFileName volumeSize blockSize\n"); return -1; } retVal = startPartitionSystem (filename, &volumeSize, &blockSize); printf("Opened %s, Volume Size: %llu; BlockSize: %llu; Return %d\n", filename, (ull_t)volumeSize, (ull_t)blockSize, retVal); if (retVal != PART_NOERROR) { printf ("Start Partition Failed: %d\n", retVal); return (retVal); } retVal = initFileSystem (volumeSize / blockSize, blockSize); if (retVal != 0) { printf ("Initialize File System Failed: %d\n", retVal); closePartitionSystem(); return (retVal); } using_history(); stifle_history(200); //max history entries while (1) { cmdin = readline("Prompt > "); #ifdef COMMAND_DEBUG printf ("%s\n", cmdin); #endif cmd = malloc (strlen(cmdin) + 30); strcpy (cmd, cmdin); free (cmdin); cmdin = NULL; if (strcmp (cmd, "exit") == 0) { free (cmd); cmd = NULL; exitFileSystem(); closePartitionSystem(); // exit while loop and terminate shell break; } if ((cmd != NULL) && (strlen(cmd) > 0)) { he = history_get(history_length); if (!((he != NULL) && (strcmp(he->line, cmd)==0))) { add_history(cmd); } processcommand (cmd); } free (cmd); cmd = NULL; } // end while } csc415-filesystem-anhduynguyen8598/fsInit.c /************************************************************** * Class: CSC-415-0# Fall 2021 * Names: * Student IDs: * GitHub Name: * Group Name: * Project: Basic File System * * File: fsInit.c * * Description: Main driver for file system assignment. * * This file is where you will start and initialize your system * **************************************************************/ #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <stdio.h> #include <string.h> #include "fsLow.h" #include "mfs.h" int initFileSystem (uint64_t numberOfBlocks, uint64_t blockSize) { printf ("Initializing File System with %ld blocks with a block size of %ld\n", numberOfBlocks, blockSize); /* TODO: Add any code you need to initialize your file system. */ return 0; } void exitFileSystem () { printf ("System exiting\n"); } csc415-filesystem-anhduynguyen8598/fsLow.h /************************************************************** * Class: CSC-415 * Name: Professor Bierman * Student ID: N/A * Project: Basic File System * * File: fsLow.h * * Description: This file provides the ability to read and write * Logical Blocks and is the main interface for the file system * project. * Note that the layer uses one more block than that presented * to the file organization module. This block is used to * hold the partition information and is not accessible from * any other layer. But, when you use the hexdump utility * you will see that the first block is not part of the volume. * * The file created by this layer represents the physical hard * drive. It presents to the logical layer (your layer) as just * a logical block array (a series of blocks - nominally 512 bytes, * that the logical layer can utilize). * * It is imperative that the logical layer (your layer) first * call startPartitionSystem before using any function and when * finished calls closePartitionSystem() to ensure that the * file that represents the physical drive is properally closed. * **************************************************************/ // // Start Partition System // // This is the first function to call before your filesystem starts // If the filename already exists, then the input values stored in // volSize and blockSize are ignored. If the file does not exist, it will // be created to the specified volume size in units of the block size // (must be power of 2) plus one for the partition header. // // On return // return value 0 = success; // return value -1 = file exists but can not open for write // return value -2 = insufficient space for the volume // volSize will be filled with the volume size // blockSize will be filled with the block size #ifndef uint64_t typedef u_int64_t uint64_t; #endif #ifndef uint32_t typedef u_int32_t uint32_t; #endif typedef unsigned long long ull_t; int startPartitionSystem (char * filename, uint64_t * volSize, uint64_t * blockSize); int closePartitionSystem (); int initFileSystem (uint64_t numberOfBlocks, uint64_t blockSize); void exitFileSystem (); uint64_t LBAwrite (void * buffer, uint64_t lbaCount, uint64_t lbaPosition); uint64_t LBAread (void * buffer, uint64_t lbaCount, uint64_t lbaPosition); #define MINBLOCKSIZE 512 #define PART_SIGNATURE 0x526F626572742042 #define PART_SIGNATURE2 0x4220747265626F52 #define PART_CAPTION "CSC-415 - Operating Systems File System Partition Header\n\n" #define PART_ACTIVE 1 #define PART_INACTIVE 0 #define PART_NOERROR 0 #define PART_ERR_INVALID -4 csc415-filesystem-anhduynguyen8598/fsLow.o csc415-filesystem-anhduynguyen8598/README.md # CSC415 Group Term Assignment - File System This is a GROUP assignment written in C. Only one person on the team needs to submit the project. Over the past month you and your team have been designing components of a file system. You have defined the goals and designed the directory entry structure, the volume structure and the free space. Now it is time to implement your file system. To help I have written the low level LBA based read and write. The routines are in fsLow.o, the necessary header for you to include file is fsLow.h. You do NOT need to understand the code in fsLow, but you do need to understand the header file and the functions. There are 2 key functions: `uint64_t LBAwrite (void * buffer, uint64_t lbaCount, uint64_t lbaPosition);` `uint64_t LBAread (void * buffer, uint64_t lbaCount, uint64_t lbaPosition);` LBAread and LBAwrite take a buffer, a count of LBA blocks and the starting LBA block number (0 based). The buffer must be large enough for the number of blocks * the block size. On return, these function returns the number of **blocks** read or written. In addition, I have written a hexdump utility that will allow you to analyze your volume file in the Hexdump subdirectory. **Your assignment is to write a file system!** You will need to format your volume, create and maintain a free space management system, initialize a root directory and maintain directory information, create, read, write, and delete files, and display info. See below for specifics. I will provide an initial “main” (fsShell.c) that will be the driver to test you file system. Your group can modifiy this driver as needed. The driver will be interactive (with all built in commands) to list directories, create directories, add and remove files, copy files, move files, and two “special commands” one to copy from the normal filesystem to your filesystem and the other from your filesystem to the normal filesystem. You should modify this driver as needed for your filesystem, adding the display/setting of any additional meta data, and other functions you want to add. The shell also calls two function in the file fsInit.c `initFileSystem` and `exitFileSystem` which are routines for you to fill in with whatever initialization and exit code you need for your file system. Some specifics - you need to provide the following interfaces: ``` b_io_fd b_open (char * filename, int flags); int b_read (b_io_fd fd, char * buffer, int count); int b_write (b_io_fd fd, char * buffer, int count); int b_seek (b_io_fd fd, off_t offset, int whence); void b_close (b_io_fd fd); ``` Note that the function are similar to the b_read and b_write you have done, there is a signifigant difference since you do not have the linux open and read to use. You have to have methods of locating files, and knowing which logical block addresses are associated with the file. Directory Functions - see [https://www.thegeekstuff.com/2012/06/c-directory/](https://www.thegeekstuff.com/2012/06/c-directory/) for reference. ``` int fs_mkdir(const char *pathname, mode_t mode); int fs_rmdir(const char *pathname); fdDir * fs_opendir(const char *name); struct fs_diriteminfo *fs_readdir(fdDir *dirp); int fs_closedir(fdDir *dirp); char * fs_getcwd(char *buf, size_t size); int fs_setcwd(char *buf); //linux chdir int fs_isFile(char * path); //return 1 if file, 0 otherwise int fs_isDir(char * path); //return 1 if directory, 0 otherwise int fs_delete(char* filename); //removes a file struct fs_diriteminfo { unsigned short d_reclen; /* length of this record */ unsigned char fileType; char d_name[256]; /* filename max filename is 255 characters */ }; ``` Finally file stats - not all the fields in the structure are needed for this assingment ``` int fs_stat(const char *path, struct fs_stat *buf); struct fs_stat { off_t st_size; /* total size, in bytes */ blksize_t st_blksize; /* blocksize for file system I/O */ blkcnt_t st_blocks; /* number of 512B blocks allocated */ time_t st_accesstime; /* time of last access */ time_t st_modtime; /* time of last modification */ time_t st_createtime; /* time of last status change */ /* add additional attributes here for your file system */ }; ``` These interfaces will also be provided to you in mfs.h. **Note:** You will need to modify mfs.h for the fdDIR strucutre to be what your file system need to maintain and track interation through the directory structure. A shell program designed to demonstrate your file system called fsshell.c is proviced. It has a number of built in functions that will work if you implement the above interfaces, these are: ``` ls - Lists the file in a directory cp - Copies a file - source [dest] mv - Moves a file - source dest md - Make a new directory rm - Removes a file or directory cp2l - Copies a file from the test file system to the linux file system cp2fs - Copies a file from the Linux file system to the test file system cd - Changes directory pwd - Prints the working directory history - Prints out the history help - Prints out help ``` This is deliberately vague, as it is dependent on your filesystem design. And this all you may get initially for a real-world assignment, so if you have questions, please ask. We will discuss some of this in class. For our purposes use 10,000,000 or less (minimum 500,000) bytes for the volume size and 512 bytes per sector. These are the values to pass into startPartitionSystem. What needs to be submitted (via GitHub and iLearn): * All source files (.c and .h) * Modified Driver program (must be a program that just utilizes the header file for your file system). * The Driver program must be named: `fsshell.c` * A make file (named “Makefile”) to build your entire program * A PDF writeup on project that should include (this is also submitted in iLearn): * The github link for your group submission. * A description of your file system * Issues you had * Detail of how your driver program works * Screen shots showing each of the commands listed above * Your volume file (limit 10MB) * There will also be an INDIVIDUAL report (form) to complete. __MACOSX/csc415-filesystem-anhduynguyen8598/._README.md csc415-filesystem-anhduynguyen8598/mfs.h /************************************************************** * Class: CSC-415 * Name: Professor Bierman * Student ID: N/A * Project: Basic File System * * File: mfs.h * * Description: * This is the file system interface. * This is the interface needed by the driver to interact with * your filesystem. * **************************************************************/ #ifndef _MFS_H #define _MFS_H #include <sys/types.h> #include <unistd.h> #include <time.h> #include "b_io.h" #include <dirent.h> #define FT_REGFILE DT_REG #define FT_DIRECTORY DT_DIR #define FT_LINK DT_LNK #ifndef uint64_t typedef u_int64_t uint64_t; #endif #ifndef uint32_t typedef u_int32_t uint32_t; #endif // This structure is returned by fs_readdir to provide the caller with information // about each file as it iterates through a directory struct fs_diriteminfo { unsigned short d_reclen; /* length of this record */ unsigned char fileType; char d_name[256]; /* filename max filename is 255 characters */ }; // This is a private structure used only by fs_opendir, fs_readdir, and fs_closedir // Think of this like a file descriptor but for a directory - one can only read // from a directory. This structure helps you (the file system) keep track of // which directory entry you are currently processing so that everytime the caller // calls the function readdir, you give the next entry in the directory typedef struct { /*****TO DO: Fill in this structure with what your open/read directory needs *****/ unsigned short d_reclen; /*length of this record */ unsigned short dirEntryPosition; /*which directory entry position, like file pos */ uint64_t directoryStartLocation; /*Starting LBA of directory */ } fdDir; // Key directory functions int fs_mkdir(const char *pathname, mode_t mode); int fs_rmdir(const char *pathname); // Directory iteration functions fdDir * fs_opendir(const char *name); struct fs_diriteminfo *fs_readdir(fdDir *dirp); int fs_closedir(fdDir *dirp); // Misc directory functions char * fs_getcwd(char *buf, size_t size); int fs_setcwd(char *buf); //linux chdir int fs_isFile(char * path); //return 1 if file, 0 otherwise int fs_isDir(char * path); //return 1 if directory, 0 otherwise int fs_delete(char* filename); //removes a file // This is the strucutre that is filled in from a call to fs_stat struct fs_stat { off_t st_size; /* total size, in bytes */ blksize_t st_blksize; /* blocksize for file system I/O */ blkcnt_t st_blocks; /* number of 512B blocks allocated */ time_t st_accesstime; /* time of last access */ time_t st_modtime; /* time of last modification */ time_t st_createtime; /* time of last status change */ /* add additional attributes here for your file system */ }; int fs_stat(const char *path, struct fs_stat *buf); #endif csc415-filesystem-anhduynguyen8598/.gitignore # Prerequisites *.d # Object files *.o *.ko *.obj *.elf # Linker output *.ilk *.map *.exp # Precompiled Headers *.gch *.pch # Libraries *.lib *.a *.la *.lo # Shared objects (inc. Windows DLLs) *.dll *.so *.so.* *.dylib # Executables *.exe *.out *.app *.i*86 *.x86_64 *.hex # Debug files *.dSYM/ *.su *.idb *.pdb # Kernel Module Compile Results *.mod* *.cmd .tmp_versions/ modules.order Module.symvers Mkfile.old dkms.conf csc415-filesystem-anhduynguyen8598/b_io.h /************************************************************** * Class: CSC-415-0# Fall 2021 * Names: * Student IDs: * GitHub Name: * Group Name: * Project: Basic File System * * File: b_io.h * * Description: Interface of basic I/O functions * **************************************************************/ #ifndef _B_IO_H #define _B_IO_H #include <fcntl.h> typedef int b_io_fd; b_io_fd b_open (char * filename, int flags); int b_read (b_io_fd fd, char * buffer, int count); int b_write (b_io_fd fd, char * buffer, int count); int b_seek (b_io_fd fd, off_t offset, int whence); void b_close (b_io_fd fd); #endif csc415-filesystem-anhduynguyen8598/fsLowM1.o csc415-filesystem-anhduynguyen8598/Hexdump/hexdump.linux csc415-filesystem-anhduynguyen8598/Hexdump/Makefile # File: Standard Makefile for CSC415 # # Description - This make file should be used for all your projects # It should be modified as needed for each homework # # ROOTNAME should be set you your lastname_firstname_HW. Except for # and group projects, this will not change throughout the semester # # HW should be set to the assignment number (i.e. 1, 2, 3, etc.) # # FOPTION can be set to blank (nothing) or to any thing starting with an # underscore (_). This is the suffix of your file name. # # With these three options above set your filename for your homework # assignment will look like: bierman_robert_HW1_main.c # # RUNOPTIONS can be set to default values you want passed into the program # this can also be overridden on the command line # # OBJ - You can append to this line for additional files necessary for # your program, but only when you have multiple files. Follow the convention # but hard code the suffix as needed. # # To Use the Makefile - Edit as above # then from the command line run: make # That command will build your program, and the program will be named the same # as your main c file without an extension. # # You can then execute from the command line: make run # This will actually run your program # # Using the command: make clean # will delete the executable and any object files in your directory. # ROOTNAME=hexdump HW= FOPTION= RUNOPTIONS= CC=gcc CFLAGS= -g -I. LIBS =pthread DEPS = OBJ = $(ROOTNAME)$(HW)$(FOPTION).o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) $(ROOTNAME)$(HW)$(FOPTION): $(OBJ) $(CC) -o $@ $^ $(CFLAGS) -l $(LIBS) clean: rm *.o $(ROOTNAME)$(HW)$(FOPTION) run: $(ROOTNAME)$(HW)$(FOPTION) ./$(ROOTNAME)$(HW)$(FOPTION) $(RUNOPTIONS) csc415-filesystem-anhduynguyen8598/Hexdump/hexdump.linuxM1 csc415-filesystem-anhduynguyen8598/Hexdump/hexdump.c /**************************************************************************** * hexdump - a program to display a file in hexadecimal and ascii * Such as: * 000020: 19 00 00 00 48 00 00 00 5F 5F 50 41 47 45 5A 45 | ....H...__PAGEZE * * Author: Robert Bierman * Date: March 28, 2020 * Source: hexdump.c * * Primary Purpose: * Written as a utility for CSC-415 Operating Systems, File System project * to allow the dumping of the "drive" file for verification of proper * structure and content. * * copyright 2020 Robert Bierman ****************************************************************************/ // Compilation: gcc hexdump.c -o hexdump #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <getopt.h> #ifndef uint64_t typedef u_int64_t uint64_t; #endif #ifndef uint32_t typedef u_int32_t uint32_t; #endif #define BUFSIZE 4096 //amount read at one time #define BLOCKSIZE 256 // number of bytes printed before a blank line #define LBABLOCKSIZE 512 // display blocks from command line are based on 512 bytes #define VERSION "1.0" // Version // This procedure takes a file name, a starting block and a number of blocks and dumps the // file to stdout. // Output (including the number of blocks) is limited by the length of the file and // partial blocks are counted as a whole block for the header showing how many blocks are // being displayed. // // Checks are done to ensure that blanks are displayed on the last line of the output // if the file only partially uses the last 16 bytes. int processFile (char * filename, uint64_t startBlock, uint64_t numBlocks) { int readbytes; int position = 0; int loops = BUFSIZE / BLOCKSIZE; //number of loops of blocks within one buffer read int offset; int k; uint32_t lbaBlockSize = LBABLOCKSIZE; uint64_t numBytesToStartBlock; uint64_t numBytesToProcess; uint64_t endOfFile; numBytesToProcess = numBlocks * lbaBlockSize; numBytesToStartBlock = startBlock * lbaBlockSize; int fd = open (filename, O_RDONLY); //open the file // Error opening file (common if they don't enter a valid file name) if (fd == -1) { printf ("ERROR: failed to open file '%s'\n", filename); return -2; } endOfFile = lseek(fd, 0, SEEK_END); //will reset seek below if (numBytesToProcess == 0) { numBytesToProcess = endOfFile; //reset numBlocks for the header here numBlocks = ((numBytesToProcess + lbaBlockSize) - 1) / lbaBlockSize; numBlocks = numBlocks - startBlock; } unsigned char * buf = malloc (BUFSIZE); //Allocate the read buffer // Very rare error - something bad if I can not allocate a small buffer if (buf == NULL) { close (fd); printf ("Failed to allocate buffer\n"); return -3; } //Position to the startBlock lseek (fd, numBytesToStartBlock, SEEK_SET); position = numBytesToStartBlock; if (position > endOfFile) //can not start past the end of the filename { printf ("Can not dump file %s, starting at block %llu, past the end of the file.\n\n", filename, (unsigned long long)startBlock); return (-5); } // calculate max blocks we can display from the given start point uint64_t maxBlocks = (((endOfFile - position) + lbaBlockSize) - 1) / lbaBlockSize; if (numBlocks > maxBlocks) numBlocks = maxBlocks; //Proces the file - the do loop goes until we read less bytes than the BUFSIZE printf ("Dumping file %s, starting at block %llu for %llu block%c:\n\n", filename, (unsigned long long)startBlock, (unsigned long long)numBlocks, numBlocks != 1?'s':'\0'); do { if (position >= (numBytesToStartBlock + numBytesToProcess)) goto cleanup; readbytes = read (fd, buf, BUFSIZE); //Read one block offset = 0; //set our offset within the block for (int i = 0; i < loops; i++) //Loop for each "Block" within one buffer read { for (int j = 0; j < BLOCKSIZE/16; j++) //loop j lines for each block { if (position+offset >= (numBytesToStartBlock + numBytesToProcess)) goto cleanup; // Handle if we are at the end of the file and the line will have less // than 16 bytes associated with it. if (offset + 16 > readbytes) { printf ("%06X: ", offset+position); for (k = 0; k < readbytes - offset; k++) { printf ("%02X ", buf[offset + k]); } for (;k < 16; k++) { printf (" "); //Print remaining of the hex output as blanks to fill out the line } printf (" | "); for (k = 0; k < readbytes - offset; k++) { printf ("%c", buf[offset + k] < 32?'.':buf[offset+k]); } printf("\n"); } else { //If a full line, do one print for the full line printf ("%06X: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X | %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", offset+position, buf[offset + 0],buf[offset + 1],buf[offset + 2],buf[offset + 3], buf[offset + 4],buf[offset + 5],buf[offset + 6],buf[offset + 7], buf[offset + 8],buf[offset + 9],buf[offset + 10],buf[offset + 11], buf[offset + 12],buf[offset + 13],buf[offset + 14],buf[offset + 15], buf[offset + 0] < 32?'.':buf[offset + 0], buf[offset + 1] < 32?'.':buf[offset + 1], buf[offset + 2] < 32?'.':buf[offset + 2], buf[offset + 3] < 32?'.':buf[offset + 3], buf[offset + 4] < 32?'.':buf[offset + 4], buf[offset + 5] < 32?'.':buf[offset + 5], buf[offset + 6] < 32?'.':buf[offset + 6], buf[offset + 7] < 32?'.':buf[offset + 7], buf[offset + 8] < 32?'.':buf[offset + 8], buf[offset + 9] < 32?'.':buf[offset + 9], buf[offset + 10] < 32?'.':buf[offset + 10], buf[offset + 11] < 32?'.':buf[offset + 11], buf[offset + 12] < 32?'.':buf[offset + 12], buf[offset + 13] < 32?'.':buf[offset + 13], buf[offset + 14] < 32?'.':buf[offset + 14], buf[offset + 15] < 32?'.':buf[offset + 15]); } //up the offset by 16 for the next line offset = offset + 16; //if greater than the readbytes we have exhausted this buffer if (offset >= readbytes) break; } //print a blank line between each BLOCK printf("\n"); //if greater than the readbytes we have exhausted this buffer if (offset >= readbytes) break; } //Next buffer, increment the overall position within the file. position = position + readbytes; // If we read the number of bytes requested (BUFSIZE), then we have not hit // the end of file yet, and should try to read more. } while (readbytes == BUFSIZE); cleanup: // clean up free (buf); close (fd); return 0; } // processArguments handles the command line using getopt_long to parse the argv array // // It then sets variable and or dispatches the action necessary based on the parameters. // it handles the multiple calls to processFile by iterating on uncontained parameters int processArguments (int argc, char * argv[]) { int c; int digit_optind = 0; uint64_t count, start; count = 0; start = 0; int retval; char * filename = NULL; while (1) { int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"count", required_argument, 0, 'c'}, //forces to c {"start", required_argument, 0, 's'}, //forces to s {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'v'}, {"file", required_argument, 0, 'f'}, {0, 0, 0, 0 } }; c = getopt_long(argc, argv, "c:s:f:vh", long_options, &option_index); if (c == -1) break; switch (c) { case 0: //It is a long option (all converted so should be none) printf("Unknown option %s", long_options[option_index].name); if (optarg) printf(" with arg %s", optarg); printf("\n"); exit (-1); case 'c': count = atol(optarg); break; case 's': start = atol(optarg); break; case 'f': filename = optarg; break; case 'h': printf ("USAGE: hexdump --file <filename> [--count num512ByteBlocks] [--start start512ByteBlock] [--help] [--version]\n"); exit (0); case 'v': printf("hexdump - Version %s; copyright 2020 Robert Bierman\n\n", VERSION); exit (0); case '?': break; default: printf("Unknown option returned character code 0%o ??\n", c); exit (-1); } } //if a file name is already specified - process it if (filename != NULL) { retval = processFile (filename, start, count); if (retval != 0) return (retval); } //additional files (same arguments) if (optind < argc) { while (optind < argc) { retval = processFile (argv[optind++], start, count); if (retval != 0) return (retval); } } return 0; } //Main calls process arguments which in turn calls process file. int main (int argc, char * argv[]) { return (processArguments (argc, argv)); } csc415-filesystem-anhduynguyen8598/Hexdump/hexdump.mac csc415-filesystem-anhduynguyen8598/.git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true precomposeunicode = true [remote "origin"] url = https://github.com/CSC415-Fall2021/csc415-filesystem-anhduynguyen8598.git fetch = +refs/heads/*:refs/remotes/origin/* [branch "main"] remote = origin merge = refs/heads/main csc415-filesystem-anhduynguyen8598/.git/HEAD ref: refs/heads/main csc415-filesystem-anhduynguyen8598/.git/description Unnamed repository; edit this file 'description' to name the repository. csc415-filesystem-anhduynguyen8598/.git/index csc415-filesystem-anhduynguyen8598/.git/packed-refs # pack-refs with: peeled fully-peeled sorted d2e04b562e218a3bea4ab25b0dfdf8c4cc42131a refs/remotes/origin/main csc415-filesystem-anhduynguyen8598/.git/info/exclude # git ls-files --others --exclude-from=.git/info/exclude # Lines that start with '#' are comments. # For a project mostly in C, the following would be a good set of # exclude patterns (uncomment them if you want to use them): # *.[oa] # *~ .DS_Store csc415-filesystem-anhduynguyen8598/.git/logs/HEAD 0000000000000000000000000000000000000000 d2e04b562e218a3bea4ab25b0dfdf8c4cc42131a Duy Nguyen <dnguyen53@mail.sfsu.edu> 1633975810 -0700 clone: from https://github.com/CSC415-Fall2021/csc415-filesystem-anhduynguyen8598.git csc415-filesystem-anhduynguyen8598/.git/hooks/commit-msg.sample #!/bin/sh # # An example hook script to check the commit log message. # Called by "git commit" with one argument, the name of the file # that has the commit message. The hook should exit with non-zero # status after issuing an appropriate message if it wants to stop the # commit. The hook is allowed to edit the commit message file. # # To enable this hook, rename this file to "commit-msg". # Uncomment the below to add a Signed-off-by line to the message. # Doing this in a hook is a bad idea in general, but the prepare-commit-msg # hook is more suited to it. # # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') # grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" # This example catches duplicate Signed-off-by lines. test "" = "$(grep '^Signed-off-by: ' "$1" | sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { echo >&2 Duplicate Signed-off-by lines. exit 1 } csc415-filesystem-anhduynguyen8598/.git/hooks/pre-rebase.sample #!/bin/sh # # Copyright (c) 2006, 2008 Junio C Hamano # # The "pre-rebase" hook is run just before "git rebase" starts doing # its job, and can prevent the command from running by exiting with # non-zero status. # # The hook is called with the following parameters: # # $1 -- the upstream the series was forked from. # $2 -- the branch being rebased (or empty when rebasing the current branch). # # This sample shows how to prevent topic branches that are already # merged to 'next' branch from getting rebased, because allowing it # would result in rebasing already published history. publish=next basebranch="$1" if test "$#" = 2 then topic="refs/heads/$2" else topic=`git symbolic-ref HEAD` || exit 0 ;# we do not interrupt rebasing detached HEAD fi case "$topic" in refs/heads/??/*) ;; *) exit 0 ;# we do not interrupt others. ;; esac # Now we are dealing with a topic branch being rebased # on top of master. Is it OK to rebase it? # Does the topic really exist? git show-ref -q "$topic" || { echo >&2 "No such branch $topic" exit 1 } # Is topic fully merged to master? not_in_master=`git rev-list --pretty=oneline ^master "$topic"` if test -z "$not_in_master" then echo >&2 "$topic is fully merged to master; better remove it." exit 1 ;# we could allow it, but there is no point. fi # Is topic ever merged to next? If so you should not be rebasing it. only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` only_next_2=`git rev-list ^master ${publish} | sort` if test "$only_next_1" = "$only_next_2" then not_in_topic=`git rev-list "^$topic" master` if test -z "$not_in_topic" then echo >&2 "$topic is already up to date with master" exit 1 ;# we could allow it, but there is no point. else exit 0 fi else not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` /usr/bin/perl -e ' my $topic = $ARGV[0]; my $msg = "* $topic has commits already merged to public branch:\n"; my (%not_in_next) = map { /^([0-9a-f]+) /; ($1 => 1); } split(/\n/, $ARGV[1]); for my $elem (map { /^([0-9a-f]+) (.*)$/; [$1 => $2]; } split(/\n/, $ARGV[2])) { if (!exists $not_in_next{$elem->[0]}) { if ($msg) { print STDERR $msg; undef $msg; } print STDERR " $elem->[1]\n"; } } ' "$topic" "$not_in_next" "$not_in_master" exit 1 fi <<\DOC_END This sample hook safeguards topic branches that have been published from being rewound. The workflow assumed here is: * Once a topic branch forks from "master", "master" is never merged into it again (either directly or indirectly). * Once a topic branch is fully cooked and merged into "master", it is deleted. If you need to build on top of it to correct earlier mistakes, a new topic branch is created by forking at the tip of the "master". This is not strictly necessary, but it makes it easier to keep your history simple. * Whenever you need to test or publish your changes to topic branches, merge them into "next" branch. The script, being an example, hardcodes the publish branch name to be "next", but it is trivial to make it configurable via $GIT_DIR/config mechanism. With this workflow, you would want to know: (1) ... if a topic branch has ever been merged to "next". Young topic branches can have stupid mistakes you would rather clean up before publishing, and things that have not been merged into other branches can be easily rebased without affecting other people. But once it is published, you would not want to rewind it. (2) ... if a topic branch has been fully merged to "master". Then you can delete it. More importantly, you should not build on top of it -- other people may already want to change things related to the topic as patches against your "master", so if you need further changes, it is better to fork the topic (perhaps with the same name) afresh from the tip of "master". Let's look at this example: o---o---o---o---o---o---o---o---o---o "next" / / / / / a---a---b A / / / / / / / / c---c---c---c B / / / / \ / / / / b---b C \ / / / / / \ / ---o---o---o---o---o---o---o---o---o---o---o "master" A, B and C are topic branches. * A has one fix since it was merged up to "next". * B has finished. It has been fully merged up to "master" and "next", and is ready to be deleted. * C has not merged to "next" at all. We would want to allow C to be rebased, refuse A, and encourage B to be deleted. To compute (1): git rev-list ^master ^topic next git rev-list ^master next if these match, topic has not merged in next at all. To compute (2): git rev-list master..topic if this is empty, it is fully merged to "master". DOC_END csc415-filesystem-anhduynguyen8598/.git/hooks/pre-commit.sample #!/bin/sh # # An example hook script to verify what is about to be committed. # Called by "git commit" with no arguments. The hook should # exit with non-zero status after issuing an appropriate message if # it wants to stop the commit. # # To enable this hook, rename this file to "pre-commit". if git rev-parse --verify HEAD >/dev/null 2>&1 then against=HEAD else # Initial commit: diff against an empty tree object against=$(git hash-object -t tree /dev/null) fi # If you want to allow non-ASCII filenames set this variable to true. allownonascii=$(git config --type=bool hooks.allownonascii) # Redirect output to stderr. exec 1>&2 # Cross platform projects tend to avoid non-ASCII filenames; prevent # them from being added to the repository. We exploit the fact that the # printable range starts at the space character and ends with tilde. if [ "$allownonascii" != "true" ] && # Note that the use of brackets around a tr range is ok here, (it's # even required, for portability to Solaris 10's /usr/bin/tr), since # the square bracket bytes happen to fall in the designated range. test $(git diff --cached --name-only --diff-filter=A -z $against | LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 then cat <<\EOF Error: Attempt to add a non-ASCII file name. This can cause problems if you want to work with people on other platforms. To be portable it is advisable to rename the file. If you know what you are doing you can disable this check using: git config hooks.allownonascii true EOF exit 1 fi # If there are whitespace errors, print the offending file names and fail. exec git diff-index --check --cached $against -- csc415-filesystem-anhduynguyen8598/.git/hooks/applypatch-msg.sample #!/bin/sh # # An example hook script to check the commit log message taken by # applypatch from an e-mail message. # # The hook should exit with non-zero status after issuing an # appropriate message if it wants to stop the commit. The hook is # allowed to edit the commit message file. # # To enable this hook, rename this file to "applypatch-msg". . git-sh-setup commitmsg="$(git rev-parse --git-path hooks/commit-msg)" test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} : csc415-filesystem-anhduynguyen8598/.git/hooks/fsmonitor-watchman.sample #!/usr/bin/perl use strict; use warnings; use IPC::Open2; # An example hook script to integrate Watchman # (https://facebook.github.io/watchman/) with git to speed up detecting # new and modified files. # # The hook is passed a version (currently 2) and last update token # formatted as a string and outputs to stdout a new update token and # all files that have been modified since the update token. Paths must # be relative to the root of the working tree and separated by a single NUL. # # To enable this hook, rename this file to "query-watchman" and set # 'git config core.fsmonitor .git/hooks/query-watchman' # my ($version, $last_update_token) = @ARGV; # Uncomment for debugging # print STDERR "$0 $version $last_update_token\n"; # Check the hook interface version if ($version ne 2) { die "Unsupported query-fsmonitor hook version '$version'.\n" . "Falling back to scanning...\n"; } my $git_work_tree = get_working_dir(); my $retry = 1; my $json_pkg; eval { require JSON::XS; $json_pkg = "JSON::XS"; 1; } or do { require JSON::PP; $json_pkg = "JSON::PP"; }; launch_watchman(); sub launch_watchman { my $o = watchman_query(); if (is_work_tree_watched($o)) { output_result($o->{clock}, @{$o->{files}}); } } sub output_result { my ($clockid, @files) = @_; # Uncomment for debugging watchman output # open (my $fh, ">", ".git/watchman-output.out"); # binmode $fh, ":utf8"; # print $fh "$clockid\n@files\n"; # close $fh; binmode STDOUT, ":utf8"; print $clockid; print "\0"; local $, = "\0"; print @files; } sub watchman_clock { my $response = qx/watchman clock "$git_work_tree"/; die "Failed to get clock id on '$git_work_tree'.\n" . "Falling back to scanning...\n" if $? != 0; return $json_pkg->new->utf8->decode($response); } sub watchman_query { my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') or die "open2() failed: $!\n" . "Falling back to scanning...\n"; # In the query expression below we're asking for names of files that # changed since $last_update_token but not from the .git folder. # # To accomplish this, we're using the "since" generator to use the # recency index to select candidate nodes and "fields" to limit the # output to file names only. Then we're using the "expression" term to # further constrain the results. if (substr($last_update_token, 0, 1) eq "c") { $last_update_token = "\"$last_update_token\""; } my $query = <<" END"; ["query", "$git_work_tree", { "since": $last_update_token, "fields": ["name"], "expression": ["not", ["dirname", ".git"]] }] END # Uncomment for debugging the watchman query # open (my $fh, ">", ".git/watchman-query.json"); # print $fh $query; # close $fh; print CHLD_IN $query; close CHLD_IN; my $response = do {local $/; <CHLD_OUT>}; # Uncomment for debugging the watch response # open ($fh, ">", ".git/watchman-response.json"); # print $fh $response; # close $fh; die "Watchman: command returned no output.\n" . "Falling back to scanning...\n" if $response eq ""; die "Watchman: command returned invalid output: $response\n" . "Falling back to scanning...\n" unless $response =~ /^\{/; return $json_pkg->new->utf8->decode($response); } sub is_work_tree_watched { my ($output) = @_; my $error = $output->{error}; if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { $retry--; my $response = qx/watchman watch "$git_work_tree"/; die "Failed to make watchman watch '$git_work_tree'.\n" . "Falling back to scanning...\n" if $? != 0; $output = $json_pkg->new->utf8->decode($response); $error = $output->{error}; die "Watchman: $error.\n" . "Falling back to scanning...\n" if $error; # Uncomment for debugging watchman output # open (my $fh, ">", ".git/watchman-output.out"); # close $fh; # Watchman will always return all files on the first query so # return the fast "everything is dirty" flag to git and do the # Watchman query just to get it over with now so we won't pay # the cost in git to look up each individual file. my $o = watchman_clock(); $error = $output->{error}; die "Watchman: $error.\n" . "Falling back to scanning...\n" if $error; output_result($o->{clock}, ("/")); $last_update_token = $o->{clock}; eval { launch_watchman() }; return 0; } die "Watchman: $error.\n" . "Falling back to scanning...\n" if $error; return 1; } sub get_working_dir { my $working_dir; if ($^O =~ 'msys' || $^O =~ 'cygwin') { $working_dir = Win32::GetCwd(); $working_dir =~ tr/\\/\//; } else { require Cwd; $working_dir = Cwd::cwd(); } return $working_dir; } csc415-filesystem-anhduynguyen8598/.git/hooks/pre-receive.sample #!/bin/sh # # An example hook script to make use of push options. # The example simply echoes all push options that start with 'echoback=' # and rejects all pushes when the "reject" push option is used. # # To enable this hook, rename this file to "pre-receive". if test -n "$GIT_PUSH_OPTION_COUNT" then i=0 while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" do eval "value=\$GIT_PUSH_OPTION_$i" case "$value" in echoback=*) echo "echo from the pre-receive-hook: ${value#*=}" >&2 ;; reject) exit 1 esac i=$((i + 1)) done fi csc415-filesystem-anhduynguyen8598/.git/hooks/prepare-commit-msg.sample #!/bin/sh # # An example hook script to prepare the commit log message. # Called by "git commit" with the name of the file that has the # commit message, followed by the description of the commit # message's source. The hook's purpose is to edit the commit # message file. If the hook fails with a non-zero status, # the commit is aborted. # # To enable this hook, rename this file to "prepare-commit-msg". # This hook includes three examples. The first one removes the # "# Please enter the commit message..." help message. # # The second includes the output of "git diff --name-status -r" # into the message, just before the "git status" output. It is # commented because it doesn't cope with --amend or with squashed # commits. # # The third example adds a Signed-off-by line to the message, that can # still be edited. This is rarely a good idea. COMMIT_MSG_FILE=$1 COMMIT_SOURCE=$2 SHA1=$3 /usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" # case "$COMMIT_SOURCE,$SHA1" in # ,|template,) # /usr/bin/perl -i.bak -pe ' # print "\n" . `git diff --cached --name-status -r` # if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; # *) ;; # esac # SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') # git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" # if test -z "$COMMIT_SOURCE" # then # /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" # fi csc415-filesystem-anhduynguyen8598/.git/hooks/post-update.sample #!/bin/sh # # An example hook script to prepare a packed repository for use over # dumb transports. # # To enable this hook, rename this file to "post-update". exec git update-server-info csc415-filesystem-anhduynguyen8598/.git/hooks/pre-merge-commit.sample #!/bin/sh # # An example hook script to verify what is about to be committed. # Called by "git merge" with no arguments. The hook should # exit with non-zero status after issuing an appropriate message to # stderr if it wants to stop the merge commit. # # To enable this hook, rename this file to "pre-merge-commit". . git-sh-setup test -x "$GIT_DIR/hooks/pre-commit" && exec "$GIT_DIR/hooks/pre-commit" : csc415-filesystem-anhduynguyen8598/.git/hooks/pre-applypatch.sample #!/bin/sh # # An example hook script to verify what is about to be committed # by applypatch from an e-mail message. # # The hook should exit with non-zero status after issuing an # appropriate message if it wants to stop the commit. # # To enable this hook, rename this file to "pre-applypatch". . git-sh-setup precommit="$(git rev-parse --git-path hooks/pre-commit)" test -x "$precommit" && exec "$precommit" ${1+"$@"} : csc415-filesystem-anhduynguyen8598/.git/hooks/pre-push.sample #!/bin/sh # An example hook script to verify what is about to be pushed. Called by "git # push" after it has checked the remote status, but before anything has been # pushed. If this script exits with a non-zero status nothing will be pushed. # # This hook is called with the following parameters: # # $1 -- Name of the remote to which the push is being done # $2 -- URL to which the push is being done # # If pushing without using a named remote those arguments will be equal. # # Information about the commits which are being pushed is supplied as lines to # the standard input in the form: # # <local ref> <local oid> <remote ref> <remote oid> # # This sample shows how to prevent push of commits where the log message starts # with "WIP" (work in progress). remote="$1" url="$2" zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0') while read local_ref local_oid remote_ref remote_oid do if test "$local_oid" = "$zero" then # Handle delete : else if test "$remote_oid" = "$zero" then # New branch, examine all commits range="$local_oid" else # Update to existing branch, examine new commits range="$remote_oid..$local_oid" fi # Check for WIP commit commit=$(git rev-list -n 1 --grep '^WIP' "$range") if test -n "$commit" then echo >&2 "Found WIP commit in $local_ref, not pushing" exit 1 fi fi done exit 0 csc415-filesystem-anhduynguyen8598/.git/hooks/update.sample #!/bin/sh # # An example hook script to block unannotated tags from entering. # Called by "git receive-pack" with arguments: refname sha1-old sha1-new # # To enable this hook, rename this file to "update". # # Config # ------ # hooks.allowunannotated # This boolean sets whether unannotated tags will be allowed into the # repository. By default they won't be. # hooks.allowdeletetag # This boolean sets whether deleting tags will be allowed in the # repository. By default they won't be. # hooks.allowmodifytag # This boolean sets whether a tag may be modified after creation. By default # it won't be. # hooks.allowdeletebranch # This boolean sets whether deleting branches will be allowed in the # repository. By default they won't be. # hooks.denycreatebranch # This boolean sets whether remotely creating branches will be denied # in the repository. By default this is allowed. # # --- Command line refname="$1" oldrev="$2" newrev="$3" # --- Safety check if [ -z "$GIT_DIR" ]; then echo "Don't run this script from the command line." >&2 echo " (if you want, you could supply GIT_DIR then run" >&2 echo " $0 <ref> <oldrev> <newrev>)" >&2 exit 1 fi if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then echo "usage: $0 <ref> <oldrev> <newrev>" >&2 exit 1 fi # --- Config allowunannotated=$(git config --type=bool hooks.allowunannotated) allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) denycreatebranch=$(git config --type=bool hooks.denycreatebranch) allowdeletetag=$(git config --type=bool hooks.allowdeletetag) allowmodifytag=$(git config --type=bool hooks.allowmodifytag) # check for no description projectdesc=$(sed -e '1q' "$GIT_DIR/description") case "$projectdesc" in "Unnamed repository"* | "") echo "*** Project description file hasn't been set" >&2 exit 1 ;; esac # --- Check types # if $newrev is 0000...0000, it's a commit to delete a ref. zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0') if [ "$newrev" = "$zero" ]; then newrev_type=delete else newrev_type=$(git cat-file -t $newrev) fi case "$refname","$newrev_type" in refs/tags/*,commit) # un-annotated tag short_refname=${refname##refs/tags/} if [ "$allowunannotated" != "true" ]; then echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 exit 1 fi ;; refs/tags/*,delete) # delete tag if [ "$allowdeletetag" != "true" ]; then echo "*** Deleting a tag is not allowed in this repository" >&2 exit 1 fi ;; refs/tags/*,tag) # annotated tag if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 then echo "*** Tag '$refname' already exists." >&2 echo "*** Modifying a tag is not allowed in this repository." >&2 exit 1 fi ;; refs/heads/*,commit) # branch if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then echo "*** Creating a branch is not allowed in this repository" >&2 exit 1 fi ;; refs/heads/*,delete) # delete branch if [ "$allowdeletebranch" != "true" ]; then echo "*** Deleting a branch is not allowed in this repository" >&2 exit 1 fi ;; refs/remotes/*,commit) # tracking branch ;; refs/remotes/*,delete) # delete tracking branch if [ "$allowdeletebranch" != "true" ]; then echo "*** Deleting a tracking branch is not allowed in this repository" >&2 exit 1 fi ;; *) # Anything else (is there anything else?) echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 exit 1 ;; esac # --- Finished exit 0 csc415-filesystem-anhduynguyen8598/.git/hooks/push-to-checkout.sample #!/bin/sh # An example hook script to update a checked-out tree on a git push. # # This hook is invoked by git-receive-pack(1) when it reacts to git # push and updates reference(s) in its repository, and when the push # tries to update the branch that is currently checked out and the # receive.denyCurrentBranch configuration variable is set to # updateInstead. # # By default, such a push is refused if the working tree and the index # of the remote repository has any difference from the currently # checked out commit; when both the working tree and the index match # the current commit, they are updated to match the newly pushed tip # of the branch. This hook is to be used to override the default # behaviour; however the code below reimplements the default behaviour # as a starting point for convenient modification. # # The hook receives the commit with which the tip of the current # branch is going to be updated: commit=$1 # It can exit with a non-zero status to refuse the push (when it does # so, it must not modify the index or the working tree). die () { echo >&2 "$*" exit 1 } # Or it can make any necessary changes to the working tree and to the # index to bring them to the desired state when the tip of the current # branch is updated to the new commit, and exit with a zero status. # # For example, the hook can simply run git read-tree -u -m HEAD "$1" # in order to emulate git fetch that is run in the reverse direction # with git push, as the two-tree form of git read-tree -u -m is # essentially the same as git switch or git checkout that switches # branches while keeping the local changes in the working tree that do # not interfere with the difference between the branches. # The below is a more-or-less exact translation to shell of the C code # for the default behaviour for git's push-to-checkout hook defined in # the push_to_deploy() function in builtin/receive-pack.c. # # Note that the hook will be executed from the repository directory, # not from the working tree, so if you want to perform operations on # the working tree, you will have to adapt your code accordingly, e.g. # by adding "cd .." or using relative paths. if ! git update-index -q --ignore-submodules --refresh then die "Up-to-date check failed" fi if ! git diff-files --quiet --ignore-submodules -- then die "Working directory has unstaged changes" fi # This is a rough translation of: # # head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX if git cat-file -e HEAD 2>/dev/null then head=HEAD else head=$(git hash-object -t tree --stdin </dev/null) fi if ! git diff-index --quiet --cached --ignore-submodules $head -- then die "Working directory has staged changes" fi if ! git read-tree -u -m "$commit" then die "Could not update working tree to new HEAD" fi csc415-filesystem-anhduynguyen8598/.git/objects/pack/pack-78a2709ac0bbbede70bc7d7c830d2dd1933e90af.pack csc415-filesystem-anhduynguyen8598/.git/objects/pack/pack-78a2709ac0bbbede70bc7d7c830d2dd1933e90af.idx csc415-filesystem-anhduynguyen8598/.git/refs/heads/main d2e04b562e218a3bea4ab25b0dfdf8c4cc42131a csc415-filesystem-anhduynguyen8598/.git/logs/refs/heads/main 0000000000000000000000000000000000000000 d2e04b562e218a3bea4ab25b0dfdf8c4cc42131a Duy Nguyen <dnguyen53@mail.sfsu.edu> 1633975810 -0700 clone: from https://github.com/CSC415-Fall2021/csc415-filesystem-anhduynguyen8598.git csc415-filesystem-anhduynguyen8598/.git/refs/remotes/origin/HEAD ref: refs/remotes/origin/main csc415-filesystem-anhduynguyen8598/.git/logs/refs/remotes/origin/HEAD 0000000000000000000000000000000000000000 d2e04b562e218a3bea4ab25b0dfdf8c4cc42131a Duy Nguyen <dnguyen53@mail.sfsu.edu> 1633975810 -0700 clone: from https://github.com/CSC415-Fall2021/csc415-filesystem-anhduynguyen8598.git CSC-415 – Operating Systems Individual Report 1 Name: ___________________________________ Student ID: __________________________ Term: __________________ Date: __________________ Team Name: ___________________ Regarding You What did you get out of the project? __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ Name (Include yourself in #1) Contribution (1 low, 5 High) Knowledge (1 little, 5 lot) Engagement (1 none, 5 enthusiastic) Communication 1 none, 5 constant) 1 2 3 4 5 CSC-415 – Operating Systems Individual Report 2 What did you struggle with? __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ What was easy for you? __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ Other Comments: __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ Name: Student ID: Term: Date: Team Name: 1: 2: 3: 4: 5: What did you struggle with 1: What was easy for you 1: Other Comments 1: Contribution1: Communication5: Knowledge1: Engagement1: Communication1: Contribution2: Knowledge2: Engagement2: Communication2: Contribution3: Knowledge3: Engagement3: Communication3: Contribution4: Knowledge4: Engagement4: Communication4: Contribution5: Knowledge5: Engagement5: What did you get out of the project 1: Steps for milestone 1: Remember – in order to manipulate anything on disk, you must first bring it into memory 1) Determine if you need to format the volume or not. a. In fsInit is the initFileSystem function where you want to start this code b. Malloc a Block of memory as your VCB pointer and LBAread block 0 c. You now have a pointer to a structure, so look at the signature (magic number) in your structure and see if it matches. d. If it matches you have initialized your volume already – If not you need to initialize it 2) If you need to initialize it a. Initialize the values in your volume control block b. Initialize free space (see that below) c. Initialize the root directory (see that below) d. Set the values returned from above in the VCB e. LBAwrite the VCB to block 0 3) Initialize the Free Space a. Let’s assume you are using a bitmap for your free space management. Given the default size, you will have 19,531 blocks – so you need 19,531 bits or 2,442 bytes or 5 blocks (so from this alone you can see that the free space map is NOT part of the VCB, but rather the VCB would have the block number where your free space starts). b. Before you can initialize the bits, you must have the memory to do so. So malloc the space needed. In this example 5 * blockSize c. Now you have a pointer to at least 2442 bytes (actually 2560 bytes). Now you can first decide where you want to store this free space map (like from block 1 – 5 inclusive), and you know block 0 is the VCB so the first 6 bits should be marked used and the rest marked free. d. Now write that to disk with LBAwrite(theFreeSpaceMap, 5, 1) – that is write 5 blocks starting from block 1 e. Return the starting block number of the free space to the VCB init that called you so it knows how to set the VCB structure variable that indicates where free space starts. Or mark it yourself if the VCB is a global structure. 4) Initialize the Root Directory a. First again, you need memory – how much? b. Decide how many Directory Entries (DE) you want for a directory (at least an initial amount). I will use 50 for this example. c. Now multiply the size of your directory entry by the number of entries. For example, if my directory entry is 60 bytes, I would multiply 60 * 50 = 3000 bytes needed. d. Now you need to determine how many blocks you need. In the example that would be 6 blocks. But wait…. 6 blocks is 3072 bytes and I am only using 3000 bytes, and my directory entry is only 60 bytes, so I can actually fit 51 directory entries in the space of 3072 bytes (now only wasting 12 bytes instead of 72). e. Now you have a pointer to an array of directory entries. Loop through them (in our case for (i = 0; i < 51; i++) and initialize each directory entry structure to be in a known free state. f. Now ask the free space system for 6 blocks. It should return to you the starting block number for those 6 blocks. g. Now set the first directory entry to the “.” Directory. So, the name is “.”, the size is 3060 bytes, it starts at block number (whatever the free space system returned above), the time stamps are the current time, it is a directory, etc. h. Now set the second directory entry to “..”, but since this is the root, it is the same as the “.” except the name is “..” rather than “.” i. Now write the root directory – 6 blocks starting from block (what was returned from the free space allocation). j. Return the starting block number of the root directory (or set it in the VCB yourself) Note – while your system is running you only ever init or read the freespace map once. Keep it in memory so you can manipulate it as needed and when you change it just write it out to disk again so that the disk reflects the current state.
Explanations and Answers 0

No answers posted

Post your Answer - free or at a fee

Login to your tutor account to post an answer

Posting a free answer earns you +20 points.

Login

NB: Post a homework question for free and get answers - free or paid homework help.

Get answers to: Operating Systems - File System or similar questions only at Tutlance.

Related Questions