This is the web page for Operation Systems at the University of Oklahoma.
CS 3113, Fall 2018, Project 4, Due 11/29/2018 @11:45pm
You now have experience at mapping directory structures onto fixed-sized blocks of bytes on a disk. For this project, we will expand your implementation to allow for the creation of, writing to reading from and deletion of files.
The OUFS data structure is identical to that of project 3. However, you will make use of some of the new components. Specifically, you will:
Remember to read this specification in full. Please post questions in the Project 4 Talk discussion board. For private questions, email cs3113@googlegroups.com.
Task | Percent |
---|---|
Makefile: provides ‘all’ and ‘clean’ | 10% |
Documentation: Proper functional-level and inline documentation. README is thorough and complete. | 40% |
Correctness: This will be assessed by giving your code a range of inputs and matching the expected output. | 50% |
Total | 100% |
This project is worth a total of 250 points. In order to receive all points, you must turn in a correct and correctly documented solution by the deadline. Solutions turned in up to 24 hours late will receive a late penalty.
Your final correctness score will be as follows:
correctness = max(correctness at deadline, correctness within 24 hours - 25 points)
If you pass our ztouch test by Thursday, November 15th @ 11:45pm (two weeks early), then you can earn up to 50 bonus points.
Below, is an implementation check-list for your convenience.
Supporting Materials
Application Programs from Project 3:
New Application Programs:
API: The design of your API is up to you. We gave our API prototypes in project 3 (you may use them or you may not). But, your API will have some of the following functionality:
Your code, executables, makefile and README must all be on your
instance in the /projects/4/
directory.
Please note that this location is NOT under your home directory.
You must also submit your code as project4.tar.gz in Canvas.
The relevant pats of the file system data structure are as follows. Note that you must not make any changes to this structure.
oufs.h (partial):
/**********************************************************************/
// Data block: storage for file contents (project 4!)
typedef struct data_block_s
{
unsigned char data[BLOCK_SIZE];
} DATA_BLOCK;
/**********************************************************************/
// Inode Types
#define IT_NONE 'N'
#define IT_DIRECTORY 'D'
#define IT_FILE 'F'
// Single inode
typedef struct inode_s
{
// IT_NONE, IT_DIRECTORY, IT_FILE
char type;
// Number of directories references to this inode
unsigned char n_references;
// Contents. UNALLOCATED_BLOCK means that this entry is not used
BLOCK_REFERENCE data[BLOCKS_PER_INODE];
// File: size in bytes; Directory: number of directory entries (including . and ..)
unsigned int size;
} INODE;
/**********************************************************************/
// Representing files (project 4!)
typedef struct oufile_s
{
INODE_REFERENCE inode_reference;
char mode;
int offset;
} OUFILE;
Although we describe the executables and the API together, your executable programs will generally be fairly short (only a main() function).
Shell command:
./ztouch <name>
Behavior:
Shell commands:
./zcreate <name>
./zappend <name>
Behavior:
Shell command:
./zmore <name>
Behavior:
Shell command:
./zremove <name>
Behavior:
Shell command:
./zlink <existing> <new_name>
Behavior:
OUFILE* oufs_fopen(char *cwd, char *path, char *mode);
int oufs_fwrite(OUFILE *fp, unsigned char * buf, int len);
Behaves like the POSIX fwrite():
int oufs_fread(OUFILE *fp, unsigned char * buf, int len);
Behaves like the POSIX fread():
Below is an example interaction.
$ ./zformat
$ ./zfilez
./
../
$ echo foo bar baz | ./zappend a.txt
$ ./zfilez
./
../
a.txt
$ ./zmore a.txt
foo bar baz
$ ./zinspect -inode 1
Inode: 1
Type: F
Block 0: 10
Block 1: 65535
Block 2: 65535
Block 3: 65535
Block 4: 65535
Block 5: 65535
Block 6: 65535
Block 7: 65535
Block 8: 65535
Block 9: 65535
Block 10: 65535
Block 11: 65535
Block 12: 65535
Block 13: 65535
Block 14: 65535
Size: 12
$ ./zcreate zformat.c < zformat.c
$ ./zmore a.txt
foo bar baz
$ ./zfilez
./
../
a.txt
zformat.c
$ ./zmore zformat.c
#include <stdio.h>
#include "oufs_lib.h"
int main(int argc, char** argv) {
// Fetch the key environment vars
char cwd[MAX_PATH_LENGTH];
char disk_name[MAX_PATH_LENGTH];
oufs_get_environment(cwd, disk_name);
oufs_format_disk(disk_name);
return(0);
}
$ ./zinspect -inode 2
Inode: 2
Type: F
Block 0: 11
Block 1: 12
Block 2: 65535
Block 3: 65535
Block 4: 65535
Block 5: 65535
Block 6: 65535
Block 7: 65535
Block 8: 65535
Block 9: 65535
Block 10: 65535
Block 11: 65535
Block 12: 65535
Block 13: 65535
Block 14: 65535
Size: 264
$ ./zremove a.txt
$ ./zfilez
./
../
zformat.c
$ ./zinspect -dblock 9
Directory at block 9:
Entry 0: name=".", inode=0
Entry 1: name="..", inode=0
Entry 3: name="zformat.c", inode=2
$ ./zinspect -master
Inode table:
05
00
00
00
00
00
00
Block table:
ff
1b
00
00
00
00
00
00
00
00
00
00
00
00
00
00
$ ./zformat
$ ./zappend zformat.c < zformat.c
$ ./zfilez
./
../
zformat.c
$ ./zmkdir project4
$ ./zmkdir project4/src
$ ./zfilez project4/src
./
../
$ ./zinspect -master
Inode table:
0f
00
00
00
00
00
00
Block table:
ff
3f
00
00
00
00
00
00
00
00
00
00
00
00
00
00
$ ./zlink foo project4/src/bar
Source not found
$ ./zlink zformat.c project4/src/zformat2.c
$ ./zfilez project4/src
./
../
zformat2.c
$ ./zfilez project4/src/zformat2.c
zformat2.c
$ ./zinspect -master
Inode table:
0f
00
00
00
00
00
00
Block table:
ff
3f
00
00
00
00
00
00
00
00
00
00
00
00
00
00
$ ./zmore project4/src
Not a file.
$ ./zmore project4/src/zformat2.c
#include <stdio.h>
#include "oufs_lib.h"
int main(int argc, char** argv) {
// Fetch the key environment vars
char cwd[MAX_PATH_LENGTH];
char disk_name[MAX_PATH_LENGTH];
oufs_get_environment(cwd, disk_name);
oufs_format_disk(disk_name);
return(0);
}
$ ./zremove zformat.c
$ ./zfilez
./
../
project4/
$ ./zinspect -master
Inode table:
0f
00
00
00
00
00
00
Block table:
ff
3f
00
00
00
00
00
00
00
00
00
00
00
00
00
00
$ ./zcat project4/src/zformat2.c
bash: ./zcat: No such file or directory
$ ./zmore project4/src/zformat2.c
#include <stdio.h>
#include "oufs_lib.h"
int main(int argc, char** argv) {
// Fetch the key environment vars
char cwd[MAX_PATH_LENGTH];
char disk_name[MAX_PATH_LENGTH];
oufs_get_environment(cwd, disk_name);
oufs_format_disk(disk_name);
return(0);
}
$ ./zremove project4/src/zformat2.c
$ ./zinspect -master
Inode table:
0d
00
00
00
00
00
00
Block table:
ff
33
00
00
00
00
00
00
00
00
00
00
00
00
00
00
oufs_fclose(): The job of the STDIO fclose() function is to clean up the resources that have been allocated to the open file (including the open file table) and to push cached data out to the disk. Because OUFS does not cache any data (any “system call” leaves the vdisk in a completely consistent state), oufs_fclose() is left to only clean up the OUFS data structure (i.e., it needs to free the memory).
I have seen a couple of implementations where string operations are being used to manipulate the contents of the files in our file system (e.g., using strcat() to copy data into a data block during an oufs_fwrite()). This is problematic in that the string operators are designed for strings only, and a byte value of zero has a special meaning with strings (it is the string terminator). Instead, you should be working at a lower level: copying the bytes one at a time directly, or using memcpy(). And, yes, we will be testing with binary data.
The echo Linux program appends a newline onto the end of the thing that it is echoing. This newline should be preserved when you are zappend’ing or zcreat’ing (i.e., you don’t have to do anything special with this case).