Ben-Gurion University of the Negev, Operating Systems 2014

OPERATING SYSTEMS, ASSIGNMENT 4 SYSTEM

SUBMISSION DATE: 15/06/2014 23:59

In this assignment you are requested to extend the of xv6. xv6 implements a -like file system, and when running on top of QEMU, stores its data on a virtual IDE disk (fs.img) for persistence. To get familiar with xv6’s file system design and capabilities, it is recommended to Chapter 5 of the xv6 book.

Assignment overview

The assignment consists of the following parts:

1. “Hacking” the xv6’s file system. This part includes expanding the maximal supported by the file system, and adding support for symbolic links.

2. File tagging (bonus). In this part you are to add support for adding key-value pairs to files.

3. application. In this part you are to implement a find application that searches the file system for files matching specified criteria.

Task 0: Running xv6

Begin by downloading our revision of xv6 from the os142 svn repository:

a shell and traverse to the desired working .  Check-out the project files using svn by calling: svn checkout http://bgu-os-142-xv6.googlecode.com/svn/trunk ass4

 Build xv6 by calling: make  Run xv6 on top of QEMU by calling: make qemu  When working through a remote connection to the department’s computers use: screen make qemu-nox

1 Ben-Gurion University of the Negev, Operating Systems 2014

P A R T 1: " H A C K IN G " T H E X V 6 F IL E S Y S T E M

XV6, as a variant of Unix, uses the same file system architecture based on i-nodes. In both of these systems the maximal size of files is fixed and predetermined. The i-node structure in xv6 contains 12 direct pointers to data blocks and another single indirect pointer. Each data block is of size 512 bytes, totaling 6KB pointed to by the direct pointers. The indirect pointer points to a block which maps additional 128 blocks. This one level of indirection gives access to 64KB of additional data. Due to this structure we are able to use files of size up to 70KB.

Expanding the maximal file size

In this part you are to extend the i-node structure in order to support files of size up to 8MB. Do this by adding a double indirection layer to the i-nodes. This requires changing the i-node structure, as well as the disk representation of i-nodes (dinode).

Hint: the file mkfs.c is written using standard C libraries and is built and executed by the makefile outside of xv6 to create the virtual drive, fs.img. One of its tasks is to the superblock, which contains metadata characterizing the file system. You will have to modify the contents of the superblock to be consistent with the changes you make. The virtual disk, fs.img, should contain at least 215 blocks (totaling 16MB).

Hint: the size of the dinode structure should be a divisor of the block size, i.e. an integer number of dinodes should fit in a block. You may want to add padding for this purpose.

Sanity

Write a simple user application which creates a of size 1MB and writes a notification message to the screen after writing the first 12 direct blocks, after writing the single indirect blocks, and after writing the double indirect blocks. The purpose of this application is to test your implementation, and in case it contains bugs, help you identify where the bugs are. You are free to change the output or add additional printings as you see fit.

The output should look something like:

Finished writing 6KB (direct) Finished writing 70KB (single indirect) Finished writing 1MB

Adding support for symbolic links

Xv6 supports hard links via the user space program . Hard links allow different file names to reference the same actual file by using the same i-node number. For example, when a hard named "b.txt" is created for a file named "a.txt", both "a.txt" and "b.txt" refer to the same file (data) on disk. Changes made to “a.txt” are reflected in “b.txt” and vice versa. Deleting one will not affect the other (it will only decrease the link count).

In this task you will expand the program ln to support symbolic links, also referred to as soft links. When a new symbolic link is created, it doesn't share the same i-node as the pointed file (target). Instead, a new file is created and a new i-node is assigned to it. The contents of the new symbolic link file will contain the to the target.

2 Ben-Gurion University of the Negev, Operating Systems 2014

Notice that symbolic links are a special type of files, and should be assigned a unique enumeration value in the file type enum. Also, symbolic links can point to any type of file: regular file, directory and even another symbolic link. Furthermore, they can be either absolute or relative. Naturally, moving a relative link to a different location will result in a broken link.

The following syntax should be used to create a symbolic link:

ln –s old_path new_path

Example: ln –s /home/os/a.txt /home/algo/b.txt

Will create the new symbolic link /home/algo/b.txt and it will point to the existing file /home/os/a.txt

The following system calls should be implemented to support symbolic links:

int symlink(const char *oldpath, const char *newpath);

symlink() creates a symbolic link, whose name is specified by the parameter newpath, and which points to the file whose name is specified by the parameter oldpath. The latter can be of any type or may not even exist. symlink() returns 0 upon success, and a negative integer upon failure.

int readlink (const char *pathname, char *buf, size_t bufsiz);

readlink() reads the name of the file to which the symbolic link points. The name of the link is specified by the parameter pathname. The target path is stored in the buffer buf, whose size is specified by bufsiz. readlink() returns the number of bytes which have been placed in the buffer buf, or the value -1 upon failure. readlink() should dereference any symbolic links encountered in the path (that is, the returned name should not be a name of a symbolic link).

Protection from loops

Symbolic links to directories may cause infinite loops. We shall tackle this issue in the same manner as done in UNIX, by limiting the degree of a chain of links to 16. I.e. when retrieving the target of a link, which points to a link, which points to a link, and so on… The max number of jumps we will allow is 16. Longer chains will be considered as loops.

Extending sym-link support

Extend the user applications to handle symbolic links as if it were the target file. I.e. cat some_link should display the contents of the target file, to which the symbolic link some_link points. Notice – we always dereference symbolic links in the path as long as it is not the file name (for example, when Path = “a/b/c.txt”, where a and c.txt are symbolic links, we will always dereference a but c.txt will be dereferenced only if requested). To do so you will need to change the open, chdir and exec system calls so that: open – by default dereferences symbolic links, add a mode to ignore dereferences. chdir / exec – by default dereference symbolic links.

The application should list symbolic links as they are, so it must open those files without the dereference mode.

3 Ben-Gurion University of the Negev, Operating Systems 2014

P A R T 2 : File Locking

Linux systems allow the user to control access to files using a permission system. This system tags every file with different privileges according to users or groups. In xv6, however, this mechanism was not implemented. In order to add some kind of security measure you will implement a file protection mechanism based on passwords. Each i-node will now have a field to hold a password, which is made up of up to 10 ASCII characters (including ‘\0’). The file protection mechanism will allow the user to password-protect and unprotect a file or to temporary unlock a protected file for use of a given process. Only files can be protected (T_FILE). The following system calls should be implemented in order to support file protection: int fprot (const char *pathname, const char* password); fprot() adds the password to the i-node of the given pathname. If the file is already open by any process or already protected then the operation will fail (return a negative number). Once the file is protected any access to it via open, exec,ect… should fail. Notice that the operation should only succeed for files. int funprot (const char *pathname, const char* password); funprot() compares the given password to the password written on the i-node of the given pathname. If it is equal to the password, the password will be removed, thus making the file unprotected. The operation will fail only if the i-node had a password and it does not fit the given one. int funlock (const char *pathname, const char* password); funlock(), unlocks the file for use of only the process id that called it. In this way it is different from funprot, which affects all the processes that may want to use the file. After a process unlocks a file it is able to use operations like open or exec on that file (even though the file remains protected). You may use the fact that the number of i-nodes and processes in the system is fixed. Notice that -ing a process should preserve unlocked files in the new process. Make sure to clear unlocked files when processes die (process ids are recycled).

Sanity test

Write a program that receives 2 arguments, a password and a path. The program should act as follows. 1. Protect the file in the given path with the given password. 2. Use fork: Child process: a. Unlock the file b. Open the file and print its content. c. the file.

4 Ben-Gurion University of the Negev, Operating Systems 2014 Parent process: a. Wait for child process to die. b. Open the file in the given path. c. If the open failed, write failed to open file. d. Unprotect the file. After that try and read the file using the cat command. Also, try and leave the file protected and then read from it with cat (cat should fail).

5 Ben-Gurion University of the Negev, Operating Systems 2014

PA R T 3 : F IN D A P P L I C A T I O N

The Find application is required by POSIX, and is found in many UNIX-like systems. It is used to search the file system for files matching user-specified criteria, and apply a user- specified action on each matching file. It is a very useful application and you are requested to implement a (very) simplistic version of it.

The syntax of find which you are to implement is: find

The path argument, which is the only mandatory argument, specifies the location where the search should begin and descend from. In case the provided path is a file and not a directory, then only the specified file will be tested for the specified criteria. The rest of the arguments are optional and are explained below. The output of find should be the full paths of all matches.

Options

-follow Dereference symbolic links. If a symbolic link is encountered, apply tests to the target of the link. If a symbolic link points to a directory, then descend into it.

-help Print a summary of the command-line usage of find and exit.

Predicates

-name All files named (exactly, no wildcards) filename.

-size (+/-)n File is of size n (exactly), +n (more than n), -n (less than n).

-type c File is of type c: d directory f regular file s soft (symbolic) link

6 Ben-Gurion University of the Negev, Operating Systems 2014

Examples find / –type d -name xv6 Search the whole file system for directories named “xv6”.

find /src –name xv6 Search /src and all its subdirectories recursively for files, directories and links named “xv6”.

find / –f –size +1000000 Find all files having size greater than 1000000 bytes.

Submission guidelines

Assignment due date: 15/06/2014 23:59

Notice that the due date will not be postponed and that frontal grading begins right after the due date.

Make sure that your Makefile is properly updated and that your code compiles with no warnings whatsoever. We strongly recommend documenting your code changes with comments – these are often handy when discussing your code with the graders.

Due to our constrained resources, assignments are only allowed in pairs. Please note this important point and try to match up with a partner as soon as possible.

Submissions are only allowed through the submission system. To avoid submitting a large number of xv6 builds you are required to submit an svn patch (i.e. a file which patches the original xv6 and applies all your changes).

Tip: although graders will only apply your latest patch file, the submission system supports multiple uploads. Use this feature often and make sure you upload patches of your current work even if you haven’t completed the assignment.

Finally, you should note that graders are instructed to examine your code on lab computers only (!) - Test your code on lab computers prior to submission.

Enjoy!

7