CS611
Programming Assignment 6
Fall 2000
Write a set of C functions to implement a simple file manager.
A file is to appear to the user as a symbolically-named, variable-length,
linearly-addressed sequence of bytes.
A read or write operation moves a given number of bytes between a file
and the user's address space.
A file pointer is internally maintained and
indicates the place in the file at which all data transfers begin.
Before a read or write operation may be performed, a logical connection
must be established between the process and the file.
This is known as "opening" the file; the breaking of the connection
is called "closing" the file.
The user must be insulated from the details of the implementation of files.
Files are stored in not-necessarily contiguous sectors of a disk.
Accessing a disk is orders of magnitude slower than accessing main memory.
Therefore, it is necessary to transfer some minimum amount of data
(such as one sector) between main memory and disk for each disk access.
By storing this minimum amount of data in a buffer, many read and write
operations will not require an access to disk.
The file manager supports a group of file systems, one per disk.
The file manager should maintain a single directory for each file system,
which will contain information about the files stored in the system.
The file manager should maintain the following information for every file
in a file system:
- symbolic file name
- file size
- physical location on disk
The symbolic name is 1-9 characters, followed by a period (.), followed
by 1-3 characters (the file type, or "extension").
The valid characters in file names are A through Z, a through z, and
0 through 9.
The file size should be the size of the file in bytes.
Assuming a fixed-sized sector, the size of the file in sectors can be
computed from the size in bytes.
The file manager should be capable of handling files sizes from
0 to 4,294,967,295.
The physical location of the file is the ordered list of sectors
that contain the file.
Assume that a disk has a maximum of 65,536 sectors.
Besides the data that makes up the files, and the above information
associated with each file, the file manager will have to maintain
the following data:
- disk storage maps: which sectors on each disk are in use on the
disk and which are available.
- the buffers for open files: each open file should have one sector
buffered in memory.
- a table of open files: allow a maximum of 20 simultaneously open
files.
The following functions will provide the entry points to the file
manager:
- int createFS(int sectorSize, int sectorCount, DISK disk):
Creates a
new file system on the given disk with the given sector size and total number
of sectors.
Returns 1 if successful and 0 if not.
(Note: You may assume the sector size will always be 256. That is, for
grading purposes the tests will always use a sector size of 256.)
- int bootFS(DISK disk):
Opens an existing file system on the given disk.
Returns 1 if successful and 0 if not.
Only one file system at a time can be "booted". That is, it is an
error if a second file system is booted without first shutting down
the file system that was booted earlier.
- int shutdownFS(DISK disk):
Closes an existing file system on the given disk.
Any persistent data
structures must be written to the disk so that the system can be booted
at a later time.
Returns 1 if successful and 0 if not.
It is an error if the user attempts to shutdown a file system with open
files.
- int openFile(char* name, int mode, DISK disk):
Opens the named file on the given disk
for the given mode and assigns a file descriptor (fd) to it.
The mode must be either READ_MODE, WRITE_MODE or UPDATE_MODE.
(UPDATE_MODE means that both reading and writing is allowed.)
The file pointer for the file is set to the beginning of the file.
If successful, it returns the fd; else it returns -1.
To be successful, the file must exist and must not already be open.
- int createFile(char* name, int mode, DISK disk):
Same as openFile except, if the file exists, it scratches it; and
it will create the file if it doesn't already exist.
It is an error if the file is already open.
- int closeFile(int fd):
Closes the file with the given fd.
If successful, it returns the fd; else it returns -1.
- int readFile(int fd, char* buf, int size):
Reads up to size characters from the file specified by
the fd into the given buffer.
The file pointer is advanced by the amount of data read.
If an error occurs, a -1 is returned.
If end of file is encountered, read returns zero.
Otherwise, the actual number of bytes read is returned.
For the read operation to be successful, the file must have been
opened with either READ_MODE or UPDATE_MODE.
- int writeFile(int fd, char* buf, int size):
Writes size characters starting at buf to the file
specified by the fd.
The file pointer is advanced by the amount of data written.
(Data may be written beyond the end of file: the file length is
extended.)
If an error occurs, -1 is returned.
Otherwise, size is returned.
For the write operation to be successful, the file must have been
opened with either WRITE_MODE or UPDATE_MODE.
- int unlinkFile(char* name, DISK disk):
Delete the file with the given name from the file system on the given disk.
Returns 1 if successful and 0 if not.
It is an error to call unlinkFile on an open file.
- int lseekFile(int fd, int offset, int sense):
Use the given offset to modify the file pointer for the given fd,
under control of sense.
If sense is equal to 0, the pointer is set to offset, which should
be positive.
If sense is equal to 1, the offset is added to the current pointer.
If successful, it returns the fd; else it returns -1.
(An lseek beyond the end of the file is not allowed.)
As you can probably guess, a file descriptor is an index into the
table of opened files.
The file manager will interface to a disk by means of a disk device driver
function:
-
void diskDD(DISK disk, int op, int sectorNumber, char* buffer)
The operation must be either READ_SECTOR or
WRITE_SECTOR and the given sector is either read
into the buffer or the given sector is written from the
given buffer.
This function does not return anything as any error is
fatal, and terminates the program with an error message.
This function will be provided to you.
The internal structure of the file manager is entirely up to
you.
You should give it much thought before starting to code.
One of your design objectives should be to make the most
efficient use of space (both disk and memory) that you
reasonably can.
Also, your design should attempt to minimize file access
time.
The design of the file system will be worth 50 points.
It should be fully documented with a lengthy comment at
the top of the file containing your code.
Each file system entry function will be worth 5 points.
The device driver function and some simple tests will
be available on alberti
in ~cs611/public/prog6.
Your implementation should be performed using C.
Put all your C code in the fs.c file.
Your program will be graded primarily by testing it for correct
functionality.
However, you may lose points if your program is not properly
structured or adequately documented.
Your programs should be submitted for grading from a UNH
CIS Alpha machine (e.g. alberti.unh.edu).
Submit a single file, fs.c.
To turn in this assignment, type:
~cs611/bin/submit prog6 fs.c
Submissions can be checked by typing:
~cs611/bin/scheck prog6
To receive full credit for the assignment, you must turn in your
files prior to 8am on Monday December 11.
Late submissions will be accepted at the penalty of 5% per day up to
one week late.
Remember: as always you are expected to do your own work on this assignment.
Last modified on November 27, 2000.
Comments and questions should be directed to
pjh@cs.unh.edu