PROGRAM 3
// filename: file_system.cpp author: anthony f. ortiz // this file contains the declaration and implementation of the file_system // class. // note: directory or file can only be one sector long. // note: one can't create a directory or file for a directory the user // is not in. // headers. #include #include #include #include #include #include // constants. #define max_sectors 100 #define max_entries 31 #define max_user_data 504 #define max_buffer 1000 #define free_entry 'f' #define file_entry 'u' #define directory_entry 'd' #define file_name "filesystem.txt" // file system. class file_system { private: // directory. struct dir { char type; char name [9]; int link; int size; }; // directory sector. struct directory_sector { int back; int frwd; int free; char filler [4]; dir directory [31]; }; // file sector. struct file_sector { int back; int frwd; char user_data [504]; }; // sector. union sector { directory_sector dsector; file_sector fsector; }; // sectors (0-99). sector * sectors; // discriminants (0-99). char * discriminants; // total, total directory, and total file sectors. int total_sectors, total_dsectors, total_fsectors; // current and root directory. int current, root; public: // constructor. file_system (); // destructor. ~file_system (); // initialize sectors. void initialize (); // show disk stats. void stat (); // create directory. void mkdir (char * name); // list directory. void list (); // change directory. void chdir (char * name); // create file. void create (char * name); // display file. void display (char * name); // append text to file. void append (char * name); // copy a file. void copy (char * old_name, char * new_name); // rename a file. void rename (char * old_name, char * new_name); // delete file. void remove (char * name); // find a file or directory. int find (char * name); // is disk full? int disk_full (); // is directory full? int directory_full (); // is current directory empty? int directory_empty (); // save changes to file system. void save (); }; // constructor. file_system :: file_system () { initialize (); } // destructor. file_system :: ~file_system () { // deallocate memory. delete [] sectors; delete [] discriminants; } // initialize sectors. void file_system :: initialize () { // sector index, file link, free list count, free list, buffer, // and file pointer. int i, link, free_count; int * free_list = new int [max_sectors]; char buf [1000]; FILE * fp; // allocate memory for sectors and discriminants. sectors = new sector [max_sectors]; discriminants = new char [max_sectors]; // initialize total, total directory, and total file sectors to 0. total_sectors = total_dsectors = total_fsectors = 0; // intialize root and current to the root sector. root = current = 0; // open file. fp = fopen (file_name, "r"); // initialize file system from a file. if (fp != NULL) { // get next directory sector from file. while (fgets (buf, max_buffer, fp) != NULL) { // initialize directory sector. sscanf (buf, "%i", &i); discriminants [i] = directory_entry; sectors [i].dsector.back = -1; sectors [i].dsector.frwd = -1; sectors [i].dsector.free = -1; // update totals. total_sectors++; total_dsectors++; // initialize directory entries. for (int j = 0; j < max_entries; j++) { // get next directory type from file and initialize. fgets (buf, max_buffer, fp); sscanf (buf, "%c", §ors [i].dsector.directory [j].type); // get rest of directory entry from file and initialize. if (sectors [i].dsector.directory [j].type == directory_entry) { sscanf (buf, "%c %s %i %i", §ors [i].dsector.directory [j].type, §ors [i].dsector.directory [j].name, §ors [i].dsector.directory [j].link, §ors [i].dsector.directory [j].size); } // get rest of file entry from file and initialize. else if (sectors [i].dsector.directory [j].type == file_entry) { sscanf (buf, "%c %s %i %i %s", §ors [i].dsector.directory [j].type, §ors [i].dsector.directory [j].name, §ors [i].dsector.directory [j].link, §ors [i].dsector.directory [j].size); link = sectors [i].dsector.directory [j].link; discriminants [link] = file_entry; sectors [link].fsector.back = -1; sectors [link].fsector.frwd = -1; fgets (buf, max_buffer, fp); sprintf (sectors [link].fsector.user_data, "%s", buf); sectors [link].fsector.user_data [sectors [i].dsector.directory [j].size] = '\0'; // update totals. total_sectors++; total_fsectors++; } // get rest of free entry from file and initialize. else if (sectors [i].dsector.directory [j].type == free_entry) { sscanf (buf, "%c %s %i %i, ", §ors [i].dsector.directory [j].type, §ors [i].dsector.directory [j].name, §ors [i].dsector.directory [j].link, §ors [i].dsector.directory [j].size); } } } // figure out which sectors are free. free_count = 0; for (i = 0; i < max_sectors; i++) { if (discriminants [i] != directory_entry && discriminants [i] != file_entry) { free_list [free_count] = i; free_count++; } } // initialize free list (single entry). if (free_count == 1) { i = 0; sectors [free_list [i]].dsector.back = -1; sectors [free_list [i]].dsector.frwd = -1; sectors [root].dsector.free = free_list [i]; } // initialize free list (more than one entry). else if (free_count > 1) { i = 0; sectors [free_list [i]].dsector.back = -1; sectors [free_list [i]].dsector.frwd = free_list [i + 1]; sectors [root].dsector.free = free_list [i]; for (i = 1; i < free_count - 1; i++) { sectors [free_list [i]].dsector.back = free_list [i - 1]; sectors [free_list [i]].dsector.frwd = free_list [i + 1]; } sectors [free_list [i]].dsector.back = i - 1; sectors [free_list [i]].dsector.frwd = -1; } } // don't initialize file system from a file. else { // initialize sector 0. discriminants [0] = directory_entry; sectors [0].dsector.back = -1; sectors [0].dsector.frwd = -1; sectors [0].dsector.free = 1; for (i = 0; i < max_entries; i++) { sectors [0].dsector.directory [i].type = free_entry; sprintf (sectors [0].dsector.directory [i].name, "%s", "noname"); sectors [0].dsector.directory [i].link = -1; sectors [0].dsector.directory [i].size = -1; } // initialize free sectors. i = 1; discriminants [i] = free_entry; sectors [i].dsector.back = -1; sectors [i].dsector.frwd = i + 1; for (i = 2; i < max_sectors - 1; i++) { discriminants [i] = free_entry; sectors [i].dsector.back = i - 1; sectors [i].dsector.frwd = i + 1; } i = max_sectors - 1; discriminants [i] = free_entry; sectors [i].dsector.back = i - 1; sectors [i].dsector.frwd = -1; } // close file. //fclose (fp); // deallocate memory. delete [] free_list; } // show disk stats. void file_system :: stat () { // display information on the total and type of sectors being used. printf ("there is a total of %i sectors being used for both directories and files.\n\n", total_sectors); printf ("there is a total of %i sectors being used exclusively for directories.\n\n", total_dsectors); printf ("there is a total of %i sectors being used exclusively for files.\n\n", total_fsectors); } // create directory. void file_system :: mkdir (char * name) { // sector number and next free sector. int free, next_free; // disk is full. if (disk_full () == 1) { printf ("there is not enough space on the disk.\n\n"); } // directory is full. else if (directory_full () == 1) { printf ("there is not enough room in the current directory.\n\n"); } // a file or directory by this name already exists. else if (find (name) != -1) { printf ("a directory or file by this name already exists.\n\n"); } // create a new directory. else { // this is the sector number for the new directory. free = sectors [root].dsector.free; // initialize directory entry. for (int i = 0; i < max_entries; i++) { if (sectors [current].dsector.directory [i].type == free_entry) { sectors [current].dsector.directory [i].type = directory_entry; sprintf (sectors [current].dsector.directory [i].name, "%s", name); sectors [current].dsector.directory [i].link = free; sectors [current].dsector.directory [i].size = 1; break; } } // this is the next free sector. next_free = sectors [free].dsector.frwd; // initialize new directory sector. discriminants [free] = directory_entry; sectors [free].dsector.back = -1; sectors [free].dsector.frwd = -1; sectors [free].dsector.free = -1; for (i = 0; i < max_entries; i++) { sectors [free].dsector.directory [i].type = free_entry; sprintf (sectors [free].dsector.directory [i].name, "%s", "noname"); sectors [free].dsector.directory [i].link = -1; sectors [free].dsector.directory [i].size = -1; } // update free sector. sectors [root].dsector.free = next_free; // update totals. total_dsectors++; total_sectors++; } } // list directory. void file_system :: list () { // directory is empty. if (directory_empty () == 1) { printf ("the current directory is empty.\n\n"); } // display directory entries. else { printf ("the current directory includes these files:\n\n"); for (int i = 0; i < max_entries; i++) { if (sectors [current].dsector.directory [i].type == file_entry || sectors [current].dsector.directory [i].type == directory_entry) { printf ("%s %c %i %i\n", sectors [current].dsector.directory [i].name, sectors [current].dsector.directory [i].type, sectors [current].dsector.directory [i].link, sectors [current].dsector.directory [i].size); } } printf ("\n"); } } // change directory. void file_system :: chdir (char * name) { // directory index. int index; // index of directory if it exists. index = find (name); // change current directory to the root directory. if (strcmp (name, "root") == 0) { current = root; } // the directory doesn't exist. else if (index == -1) { printf ("the directory doesn't exist.\n\n"); } // the directory doesn't exist, but a file does. else if (sectors [current].dsector.directory [index].type == file_entry) { printf ("this is not a directory, it is a file.\n\n"); } // change directory. else { current = sectors [current].dsector.directory [index].link; } } // create file. void file_system :: create (char * name) { // file index, sector number, next free sector, and user data. int i, free, next_free; char text [504]; // disk is full. if (disk_full () == 1) { printf ("there is not enough space on the disk.\n\n"); } // directory is full. else if (directory_full () == 1) { printf ("there is not enough room in the current directory.\n\n"); } // a file or directory by this name already exists. else if (find (name) != -1) { printf ("a file or directory by this name already exists.\n\n"); } // create file. else { // get user data from keyboard. printf ("enter text:\n\n"); gets (text); printf ("\n"); // this is the sector number for the new file. free = sectors [root].dsector.free; // initialize file entry. for (i = 0; i < max_entries; i++) { if (sectors [current].dsector.directory [i].type == free_entry) { sectors [current].dsector.directory [i].type = file_entry; sprintf (sectors [current].dsector.directory [i].name, "%s", name); sectors [current].dsector.directory [i].link = free; sectors [current].dsector.directory [i].size = strlen (text); break; } } // this is the next free sector. next_free = sectors [free].fsector.frwd; // initialize new file sector. discriminants [free] = file_entry; sectors [free].fsector.back = -1; sectors [free].fsector.frwd = -1; sprintf (sectors [free].fsector.user_data, "%s", text); // truncate file if it is over max_user_data bytes long. if (sectors [current].dsector.directory [i].size >= max_user_data - 1) { sectors [current].dsector.directory [i].size = max_user_data - 1; sectors [free].fsector.user_data [max_user_data - 1] = '\0'; } // update free sector. sectors [root].dsector.free = next_free; // update totals. total_fsectors++; total_sectors++; } } // display file. void file_system :: display (char * name) { // file index and link. int index, link; // index of file if it exists. index = find (name); // the file doesn't exist. if (index == -1) { printf ("the file doesn't exist.\n\n"); } // the file doesn't exist, but a directory does. else if (sectors [current].dsector.directory [index].type == directory_entry) { printf ("this is not a file, it is a directory.\n\n"); } // display file. else { link = sectors [current].dsector.directory [index].link; printf ("here is the file:\n\n"); printf ("%s", sectors [link].fsector.user_data); printf ("\n\n"); } } // append text to file. void file_system :: append (char * name) { // file index, link, size of file, and user data. int index, link, size; char text [504]; // index of file if it exists. index = find (name); // the file doesn't exist. if (index == -1) { printf ("the file doesn't exist.\n\n"); } // the file doesn't exist, but a directory does. else if (sectors [current].dsector.directory [index].type == directory_entry) { printf ("this is not a file, it is a directory.\n\n"); } // append to file. else { // get user data from keyboard. printf ("enter text:\n\n"); gets (text); printf ("\n"); // append text to end of file. link = sectors [current].dsector.directory [index].link; size = strlen (sectors [link].fsector.user_data); sprintf (sectors [link].fsector.user_data + size, "%s", text); // update size field. size = strlen (sectors [link].fsector.user_data); sectors [current].dsector.directory [index].size = size; // truncate file if it is over max_user_data bytes long. if (sectors [current].dsector.directory [index].size >= max_user_data - 1) { sectors [current].dsector.directory [index].size = max_user_data - 1; sectors [link].fsector.user_data [max_user_data - 1] = '\0'; } } } // copy a file. void file_system :: copy (char * old_name, char * new_name) { // file index, sector number, next free sector, and link number. int index, free, next_free, link; // index of file if it exists. index = find (old_name); // disk is full. if (disk_full () == 1) { printf ("there is not enough space on the disk.\n\n"); } // directory is full. else if (directory_full () == 1) { printf ("there is not enough room in the current directory.\n\n"); } // the file doesn't exist. else if (index == -1) { printf ("this file doesn't exist.\n\n"); } // the file doesn't exist, but a directory does. else if (sectors [current].dsector.directory [index].type == directory_entry) { printf ("this is not a file, it is a directory.\n\n"); } // a file or directory by this name already exists. else if (find (new_name) != -1) { printf ("a file or directory by this name already exists.\n\n"); } // copy the file. else { // this is the sector number for the new file. free = sectors [root].dsector.free; // initialize file entry. for (int i = 0; i < max_entries; i++) { if (sectors [current].dsector.directory [i].type == free_entry) { sectors [current].dsector.directory [i].type = file_entry; sprintf (sectors [current].dsector.directory [i].name, new_name); sectors [current].dsector.directory [i].link = free; sectors [current].dsector.directory [i].size = sectors [current].dsector.directory [index].size; break; } } // this is the next free sector. next_free = sectors [free].fsector.frwd; // initialize new file sector. discriminants [free] = file_entry; sectors [free].fsector.back = -1; sectors [free].fsector.frwd = -1; link = sectors [current].dsector.directory [index].link; sprintf (sectors [free].fsector.user_data, "%s", sectors [link].fsector.user_data); // update free sector. sectors [root].dsector.free = next_free; // update totals. total_fsectors++; total_sectors++; } } // rename a file. void file_system :: rename (char * old_name, char * new_name) { // file index. int index; // index of file if it exists. index = find (old_name); // the file doesn't exist. if (index == -1) { printf ("the file doesn't exist.\n\n"); } // a file or directory of this name already exists. else if (find (new_name) != -1) { printf ("a file or directory by this name already exists.\n\n"); } // the file doesn't exist, but a directory does. else if (sectors [current].dsector.directory [index].type == directory_entry) { printf ("this is not a file, it is a directory.\n\n"); } // rename file. else { sprintf (sectors [current].dsector.directory [index].name, "%s", new_name); } } // delete file. void file_system :: remove (char * name) { // file index, next free sector, and link. int index, free, link; // index of file if it exists. index = find (name); // the file doesn't exist. if (index == -1) { printf ("the file doesn't exist.\n\n"); } // the file doesn't exist, but a directory does. else if (sectors [current].dsector.directory [index].type == directory_entry) { printf ("this is not a file, it is a directory.\n\n"); } // delete file. else { // this is the old free sector number. free = sectors [current].dsector.free; // remove file entry from the directory. sectors [current].dsector.directory [index].type = free_entry; sprintf (sectors [current].dsector.directory [index].name, "%s", "noname"); link = sectors [current].dsector.directory [index].link; sectors [current].dsector.directory [index].link = -1; sectors [current].dsector.directory [index].size = -1; // remove contents from the file. discriminants [link] = free_entry; sprintf (sectors [link].fsector.user_data, "%s", ""); // update free sector. sectors [current].dsector.free = link; sectors [link].dsector.back = -1; sectors [link].dsector.frwd = free; // update totals. total_sectors--; total_fsectors--; } } // find a file or directory. int file_system :: find (char * name) { // return sector number if file or directory exists. otherwise, // return -1. for (int i = 0; i < max_entries; i++) { if (strcmp (name, sectors [current].dsector.directory [i].name) == 0) { return i; } } return -1; } // is disk full? int file_system :: disk_full () { // return 1 if disk if full. otherwise, return 0. if (total_sectors >= max_sectors) { return 1; } return 0; } // is current directory full? int file_system :: directory_full () { // return 1 if directory is full. otherwise, return 0. for (int i = 0; i < max_entries; i++) { if (sectors [current].dsector.directory [i].type == free_entry) { return 0; } } return 1; } // is current directory empty? int file_system :: directory_empty () { // return 1 if directory is empty. otherwise, return 0. for (int i = 0; i < max_entries; i++) { if (sectors [current].dsector.directory [i].type == file_entry || sectors [current].dsector.directory [i].type == directory_entry ) { return 0; } } return 1; } // save changes to file system. void file_system :: save () { // file link, buffer, and file pointer. int link; char buf [1000]; FILE * fp; // open file. fp = fopen (file_name, "w"); // write file system to file. for (int i = 0; i < max_sectors; i++) { // write only directory sectors to file. if (sectors [i].dsector.back == -1 && sectors [i].dsector.frwd == -1 && discriminants [i] == directory_entry) { // initialize directory sector and write directory sector // to file. sprintf (buf, "%i\n", i); fputs (buf, fp); // write directory entries to file. for (int j = 0; j < max_entries; j++) { // initialize directory entry and write directory entry // to file. if (sectors [i].dsector.directory [j].type == directory_entry) { sprintf (buf, "%c %s %i %i\n", sectors [i].dsector.directory [j].type, sectors [i].dsector.directory [j].name, sectors [i].dsector.directory [j].link, sectors [i].dsector.directory [j].size); fputs (buf, fp); } // intialize file entry and write file entry to file. else if (sectors [i].dsector.directory [j].type == file_entry) { link = sectors [i].dsector.directory [j].link; sprintf (buf, "%c %s %i %i\n", sectors [i].dsector.directory [j].type, sectors [i].dsector.directory [j].name, sectors [i].dsector.directory [j].link, sectors [i].dsector.directory [j].size); fputs (buf, fp); sprintf (buf, "%s\n", sectors [link].fsector.user_data); fputs (buf, fp); } // initialize free entry and write free entry to file. else if (sectors [i].dsector.directory [j].type == free_entry) { sprintf (buf, "%c %s %i %i\n", sectors [i].dsector.directory [j].type, sectors [i].dsector.directory [j].name, sectors [i].dsector.directory [j].link, sectors [i].dsector.directory [j].size); fputs (buf, fp); } } } } // close file. fclose (fp); } // main. void main () { // command, option, existing name, new name. char command [1000], option [10], name [10], change_name [10]; // file system. file_system fs; // execute the file system commands. while (1) { // fetch the command. printf ("-> "); fflush (stdin); gets (command); sscanf (command, "%s", &option); printf ("\n"); // execute one of the following commands: stat, mkdir, list, // chdir, create, display, append, copy, rename, delete, save, // or exit. if (strcmp ("stat", option) == 0) { fs.stat (); } else if (strcmp ("mkdir", option) == 0) { sscanf (command, "%s %s", &option, &name); fs.mkdir (name); } else if (strcmp ("list", option) == 0) { fs.list (); } else if (strcmp ("cd", option) == 0) { sscanf (command, "%s %s", &option, &name); fs.chdir (name); } else if (strcmp ("create", option) == 0) { sscanf (command, "%s %s", &option, &name); fs.create (name); } else if (strcmp ("display", option) == 0) { sscanf (command, "%s %s", &option, &name); fs.display (name); } else if (strcmp ("append", option) == 0) { sscanf (command, "%s %s", &option, &name); fs.append (name); } else if (strcmp ("copy", option) == 0) { sscanf (command, "%s %s %s", &option, &name, &change_name); fs.copy (name, change_name); } else if (strcmp ("rename", option) == 0) { sscanf (command, "%s %s %s", &option, &name, &change_name); fs.rename (name, change_name); } else if (strcmp ("delete", option) == 0) { sscanf (command, "%s %s", &option, &name); fs.remove (name); } else if (strcmp ("exit", option) == 0) { break; } else if (strcmp ("save", option) == 0) { fs.save (); } else { printf ("this is not a legal command.\n\n"); } } } // filename: filesystem.out author: anthony f. ortiz -> create f1 enter text: this is file1. -> create f2 enter text: this is file2. -> create f3 enter text: this is file3. -> mkdir d1 -> mkdir d2 -> mkdir d3 -> list the current directory includes these files: f1 u 1 14 f2 u 2 14 f3 u 3 14 d1 d 4 1 d2 d 5 1 d3 d 6 1 -> append f1 enter text: this is file1. -> display f1 here is the file: this is file1. this is file1. -> delete f2 -> rename f3 file3 -> list the current directory includes these files: f1 u 1 30 file3 u 3 14 d1 d 4 1 d2 d 5 1 d3 d 6 1 -> save -> exit
BACK TO CS6560 PAGE.