The basic rules are the same for this assignment as they were for the third assignment: you may work on this assignment either by yourself or with a single project partner (i.e., a group of two people doing a single project). If two people partner on a project, include both names and CATS accounts in any files either of you modified. A project team should only hand in one copy of their assignment; the person whose handin directory isn't being used should submit a single file called partner containing the name and CATS account of both project members into her directory. Partners will be required to do a little extra work: the items designated [Partners/Extra Credit] are required for people working with partners and extra credit for those working alone. The grade received by each project partner will be the same.
And, as with the previous assignment: you may now discuss your design with other members of the class. However, if you do so, you must follow the Gilligan's Island rule - you may bring no notes of any kind to or from the discussion and you must wait at least 1/2 hour before sitting down to work on your code. Furthermore, you must note in your design document any discussions that you had, with whom you had them, and what you discussed. Reminder: you cannot share code, view other's code, or allow others to view your code. Failure to comply with this will be considered a violation of the ethics portion of this class, with all that implies.
As with other projects, the following suggestions apply:
The goal of this project is to implement a simple file system in DLXOS. The file system should have the following features:
The OS hasn't changed, so you can continue to use the code you've been working on. But if you've had trouble getting things to work you may want to start fresh with a clean copy of the OS.
Your file system calls will be integrated into DLXOS in filesys.c. There are routines called FsDlxRead(), and so on for the other calls you need to implement. You need to modify these calls to use the file system you are designing. Your routines will automatically be called when you call FsOpen() with a filename that starts with "dlx:". For example, calling FsOpen() on the file "dlx:/foo" will result in FsDlxOpen() being called with the file /foo. Other calls (except for FsDelete()) are switched automatically based on the file ID set in FsOpen(), which remembers which file system (Unix or DLXOS) the file was opened in.
For this assignment, you'll be reading and writing blocks from a file called (by default) dlxdisk (you should allow its name to be supplied by the -B argument passed to the OS) using the normal file system calls from within DLXOS (open() , read(), write(), etc.). You should treat the dlxdisk file as a "raw disk" on which to build your file system. Your OS need not initialize the disk; you may write a regular program (running in Unix) to set up any initial data structures on dlxdisk that your OS might need. Your disk should be persistent if you shut down DLXOS and restart it, DLXOS should still be able to use the file system with all of the changes that the previous run made to the file system (creates, writes, deletes, etc.).
File blocks should be 1KB (1024 bytes) long. This means that a read() call to read bytes from the DLXOS disk looks like this:
#define DLX_DISK_BLOCKSIZE 1024
unsigned char buf[DLX_DISK_BLOCKSIZE];
nbytes = read(dlxdiskfd, buf, DLX_DISK_BLOCKSIZE);
Write calls look about the same.
Your file system will need to keep track of free disk blocks. Use a bitmap. In managing your bitmap, you should try to ensure that the file system remains consistent as much as possible (i.e., doesn't allocate a block to two different files). You should always err on the side of safety, preferring to lose blocks (a block is free but not included in a file) rather than allowing a block to be allocated twice. The order in which you do things is particularly important, so at each step of your algorithms, try to think of what would happen if the power were suddenly interrupted - a free block marked as allocated (not too bad), or an allocated block marked as free (very bad).
You should look at the memory bitmap mechanisms for hints on how to implement something similar for file blocks.
You must support a single directory that can accommodate file names of up to 80 characters. You may not waste space a 4 character file name shouldn't occupy 80 characters of space in the directory. For each file in the directory, you should store the file name and a pointer to the index block for the file. This information can be used to read and write the individual blocks of a file. Of course, the directory itself is like a file, and uses an index block to store pointers to all of its blocks. The directory's index block should be stored at a location that the file system knows how to find in other words, the file system should automatically translate "/" into a fixed location for the directory's index block.
The root directory, as in Unix, is referred to as "/". This means that the call to open the file foo in DLXOS is FsOpen("dlx:/foo", ...). Similar naming applies to the delete call.
The first 32-bit word of the index block contains the size of the file in bytes. The remainder of the index block is filled with as many 32-bit block numbers as needed to point to all of the blocks in the file.
There are three possible flags to open: read, write, and create. The read and write flags are used to indicate which operations are permitted on an open file. The create flag is set by the caller when the user wants to create a file if it's not already found. If create isn't set and the file isn't found, an error should be returned. If create is set and the file doesn't yet exist, it should be created with 0 size. Much of the open code is already written for you.
Reading files is self-explanatory. Your file system simply needs to find the appropriate data and read it in. Writing is a bit more complex you may need to allocate a new block. Otherwise, data is written as you'd expect.
File reads and writes need not be on file block boundaries.
Seeks in the DLXOS file system work just the way seeks work in Unix. A seek updates the "current" pointer but doesn't transfer data. Seeks past of the end of the file fail and return a (negative) error code.
Your file system should catch errors and return appropriate error codes. Possible errors you may want to catch include:
You need to write a DLX user program to list all of the files in the (single) directory. You need not list file sizes, though you're certainly allowed to. Keep in mind that listing file sizes will likely require an additional call similar to the Unix stat() system call....
As with other projects, you'll need to hand in your design documentation and your code. Because your code may include both operating system code, user programs, and Unix programs, please make sure your Makefile builds them separately. For this project, you'll need to be particularly careful because you might have programs that need to be compiled with regular (not DLX) gcc. Do not hand in dlxdisk!
For extra credit, you may implement the following features. As usual, the required portion of your code should be substantially working before you attempt extra credit. Please include a list of the extra credit features you've implemented in your README file so we can test them.
REMEMBER: Do not submit object files, extra assembler files, or executables. Every file in the submit directory that could be generated automatically by the compiler or assembler will result in a 5 point deduction from your programming assignment grade.