Lab: File System Utilities
CSC 213 - Operating Systems and Parallel Algorithms - Weinman
- Summary:
- You will work at the system level to rebuild common
command line file utilities.
- Assigned:
- Tuesday 2 December
- Due:
- 11:30 PM Monday 8 December
- Objectives:
-
- Practice defensive programming (you can wreck your data with
this assignment)
- Experience new system calls, especially those for manipulating files
and directories
- Collaboration:
- You will complete this lab in teams
as assigned by the instructor.
Exercises
You have now built your own version of a small
shell, and a scheduler to manage processes
it launches. You will now close the loop by implementing several small
file system utilities typically needed by a shell user.
Preliminaries
- Do this laboratory on any MathLAN workstation.
- Copy the starter files to somewhere in
your home directory.
-
$ cp -R ~weinman/public_html/courses/CSC213/2014F/labs/code/filesystems ~/somewhere/
-
As you progress through the lab, a README
file will contain
- a brief description of your implementations,
- statements of correctness (i.e., what cases were used to test each
program and why those completely demonstrate correctness),
- and citations of any sources you used.
Begin a README file now by entering your team members' names.
Note that Emacs has a very convenient minor mode for text files that
will keep your text well wrapped. You may enter this mode by typing
(in Emacs)
-
M-x auto-fill-mode
followed by the return key. (Note: M-x means "meta x",
where meta is typically the Alt key on your keyboard;
the Esc key also typically functions as meta.) You
can also force an update of the wrapping in the paragraph where he
cursor is placed by typing M-q.
Part A: Improving Tanenbaum's file copy
- Review the file mycp.c. Compile it using make and
try using it as you would use the standard cp(1)
program.
- You may have noticed that the program's output is the same-nothing-regardless
of whether the copy is successful. Wherever the code exits with an
error status, modify the code to use perror(3)
whenever possible, or fprintf(3) otherwise,
to print a helpful error message.
- Rather than always creating the new file with the protection mode
0700, use fstat(2) to obtain the
protection mode (i.e., file permissions) of the original file.
Note that creat(2) automatically applies
the process's umask to the protection mode.
- You may have also noticed that mycp.c does not let you copy
a file to a different directory except by typing the path and filename
for the new file:
-
$ ./mycp mycp ../mycp
Modify mycp.c so that you can specify just a directory for
the destination:
-
$ ./mycp mycp ..
$ ls ../mycp
../mycp
- Hint:
- If creating the destination file (out_fd) fails,
then check the errno system variable. If it equals EISDIR,
indicating the destination path names not a file but a directory,
then do the following instead of immediately exiting with an error:
- Get the name of the original file by calling basename(3)
on argv[1].
- Build the destination file name: Use strcpy(3)
and either strcat(3) or pointer arithmetic
to concatenate the destination path, /,
and the source file name.
- Try again to create the destination file using that new file name.
- If successful, proceed with copying blocks from the source file to
the destination file. Otherwise, report the error and exit.
- Update your README to contain the elements listed above*.
Part B: More file system utilities
- Write a program myrm.c, which takes as its sole command-line
argument the name of a file to remove. Use unlink(2)
to remove the file. In this and all programs you write for
this lab, be sure to report errors appropriately to the user.
- Add myrm to the PROGRAMS variable of the Makefile.
- Update your README file with information about myrm.
Be sure to carefully document your test cases (and include tests of
expected errors).
- Write a program mytouch.c, which will be similar to the touch(1)
program:
-
$ ls -l
total 32
-rw------- 1 davisjan mathfac 6 2010-10-08 21:36 foo
-rwx------ 1 davisjan mathfac 217 2010-10-08 20:02 Makefile
-rwx------ 1 davisjan mathfac 7867 2010-10-08 21:28 mycp
-rw------- 1 davisjan mathfac 1611 2010-10-08 21:01 mycp.c
-rwx------ 1 davisjan mathfac 7964 2010-10-08 21:35 mytouch
-rw------- 1 davisjan mathfac 756 2010-10-08 21:35 mytouch.c
$ cat foo
blah!
$ touch foo
$ cat foo
blah!
$ touch bar
$ cat bar
$ ls -l
total 32
-rw------- 1 davisjan mathfac 0 2010-10-08 21:37 bar
-rw------- 1 davisjan mathfac 6 2010-10-08 21:37 foo
-rwx------ 1 davisjan mathfac 217 2010-10-08 20:02 Makefile
-rwx------ 1 davisjan mathfac 7867 2010-10-08 21:28 mycp
-rw------- 1 davisjan mathfac 1611 2010-10-08 21:01 mycp.c
-rwx------ 1 davisjan mathfac 7964 2010-10-08 21:35 mytouch
-rw------- 1 davisjan mathfac 756 2010-10-08 21:35 mytouch.c
$
Here's the basic algorithm:
- Take a filename as the sole command-line argument.
- Try to use utime(2) to update the named
file's modification time to the current system time. (Note that utime
can take a null times parameter.)
- If that fails, and the errno variable indicates that the
file does not exist (cf. utime(2) manual
page, section ERRORS), then create a file with the given
name and then immediately close it. Use a reasonable default protection
mode (document and explain that choice in your README).
- Add mytouch to the PROGRAMS variable of the Makefile.
- Update your README file with information about mytouch.
- Consider how to implement a version of the mv(1)
program, which moves or renames a file. There are three different
approaches: (1) copy the file and then use unlink(2)
to delete the original; (2) use link(2)
to create a hard link from the destination path to the original file,
and then use unlink(2) to delete the original;
(3) use rename(2) to rename the file.
- What are the advantages and disadvantages of these three approaches?
Here are three issues you should consider: performance, system crashes,
and renaming across the mounted file systems in a virtual file system.
Record your answers in your README.
- Using whichever approach you prefer, write a program mymv.c,
which will be similar to the mv(1) program.
As in mycp.c, take as command-line arguments a original file
name followed by a destination path, which is either a file or a directory.
- Add mymv to the PROGRAMS variable of the Makefile.
- Update your README file with other requisite information
about mymv.
- Write a program myls.c, which will be a simple version of
the ls(1) program that lists the names
of the files in a directory, along with each file's size (in bytes).
- If given a command-line argument, your program should list the contents
of the specified directory. Otherwise, list the contents of the current
working directory. Giving more than one command-line argument should
result in an error.
- The kernel interface for reading directory entries does not guarantee
that you will read whole entries, which is rather yucky for the programmer.
Don't use the kernel interface. Instead, use the POSIX library functions
opendir(3), readdir(3),
and closedir(3). To find information about
a file, use the system call stat(2).
- Print the name of each file in the directory. For simplicity, print
one filename per line, followed by a tab, followed by the file's size
in bytes.
- Add myls to the PROGRAMS variable of the Makefile.
- Update your README file with information about myls.
What to turn in
- Your source code (five C files), your Makefile, and your
README
- A single PDF containing (merged)
- Your enscripted C programs, Makefile, and README
- A transcript of your programs' compilations and test runs (including
error handling)
Acknowledgment
This assignment was developed by Janet Davis, where she credits "the
file copy program from Tanenbaum's Modern Operating Systems,
3/e" in the
original.