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.