CS 3733 Operating Systems, Spring 2001 Assignments 4 and 5


Assignment 4: Parts 1-5 Due Tuesday, April 3, 2001
Assignment 5: Parts 6-8 Due Tuesday, April 24, 2001

Note:

These assignments are based on synchronization of directories.
The general problem can be stated as follows:

In these assignments we assume the directories are on the same machine.
In the next assignment you will extend this to different machines.


All programs for this assignment will start by printing a line to standard error in the form:
This program was written by ...
All programs should do complete error checking and print appropriate error messages if an error occurs. Error messages should only be printed from main. If another function produces an error, it should return and error code and main should print an appropriate message.

Make a directory called assign45 under your OS course directory for these programs. Make subdirectories of assign45 called testa and testb and fill them using the tar files in /usr/local/courses/cs3733/spring2001/assign4 as follows starting from your assign45 directory:

cd testa
tar -xf /usr/local/courses/cs3733/spring2001/assign45/testa.tar
cd ../testb
tar -xf /usr/local/courses/cs3733/spring2001/assign45/testb.tar
Make sure you do not modify these directories until you get to Part 7.

Use this cover sheet for handing in Assignment 4.

Use this cover sheet for handing in Assignment 5.


Part 1.
Write a program, shownames, that takes one command line argument, the name of a directory. It outputs the names of the ordinary files in the given directory, one per line.

Use Program 3.1 of PUP as a model for getting the names of the files in a directory. Use Example 3.6 as a model for checking the st_mode field of stat. Look in /usr/include/sys/stat.h for a description of the mask for testing for a regular file. Use lstat instead of stat so that it handles symbolic links correctly. You can find copies of the code from the book in /usr/local/courses/cs3733/pup/ch03/raw/

Test this using your testa directory.


Part 2.
Write a program, showtimes, that takes one command line argument, the name of a directory. It outputs the name, size in bytes, and modification time of each ordinary files in the given directory, one per line. To convert the time to an string you can use ctime. Test this on testa.


Part 3.
Write a program, comparedirs, that takes two command line arguments, the names of two directories, dir1 and dir2. For each regular file in dir2 it displays the following information on one line:

The output should appear in tabular form with columns lined up. If there is no file in dir1 with the same name, the 4th and 5th columns should be blank. The action to be taken should be one of the following: None, Replace, No File, Older, Error. These have the following meaning:

Test Part 3 as using testa as the first directory and testb as the second directory.

Note: Be careful when you use ctime twice. ctime stores the returned string in a static area. You may have to take this into account.


Part 4.
Write a program, sendinfo, that takes two command line arguments as parameters. The first is the name of a directory and the second is the name of a named pipe. For each file in the directory, it sends the following information over the named pipe:

When a string is sent, it consists of printing characters terminated with a string terminator (ASCII code 0). When an integer is sent, the high order digit is sent first and again it is terminated by string terminator. After all information is sent a single string terminator is sent indicating end of output. For the type of file, send the string "1" for a regular file and the string "0" for any other type of file.

Test sendinfo by using testa as the directory and in another window, cat the named pipe to a file. Run md5 on that file. For example, if the pipe is called sendpipe you can do the following:

cat sendpipe > send.out
md5 send.out
Write a program called getinfo that takes one command line argument that is the name of a named pipe. It reads information in the form sent by sendinfo and displays it in tabular form with the columns lined up. Display the time both as seconds since the epoch and in ASCII using ctime. Test this by having sendinfo send information about the testa directory.

Now write a program called getinfo1 that does exactly the same thing as getinfo but it reads in everything from the pipe before doing any output. Do not make any assumptions about the number of files involved. You might want to store the information in a linked list of structures.


Part 5.
Write a program called compareinfo that takes two command line arguments. The first is a named pipe and the second is a directory. It reads from the pipe like getinfo1, but instead of printing what has been read, it processes the information and for each file in the named directory and displays information similar to comparedirs, using the second command line argument as dir2 and the info from the pipe for dir1.

Test this by running sendinfo on testa and compareinfo using testb.


Part 6.
Write a function called syncsource that takes two command line arguments that are named pipes. It starts out like compareinfo, using the first named pipe and the current directory, but for each file for which the action is Replace or Send, the following is sent to the second named pipe:

The format for the first three parts is the same as in sendinfo. When the file is sent, there is no terminating output byte since the destination knows exactly how many bytes to read.
Test this by using three windows, one running sendinfo, one running syncsource, and one in which the output of the second pipe is redirected to standard output. When all output is sent, a single string terminator is sent indicating end out output.

This program must work with the syncdest program described in Part 7. Read the description of Part 7 before doing Part 6. Do not make any assumptions about the number or sizes of the files involved.

To test this, make sure you have created two FIFOs, say infopipe and sendpipe. Use three windows. In the first window run comparedir using testa and infopipe:
sendinfo testa infopipe

In the second window, run syncsource from the testb directory:
../syncsource ../infopipe ../sendpipe

In the third window get what is sent to the sendpipe:
cat sendpipe > send.out

Hand in the output generated by running md5 on send.out.


Part 7.
Write a function called syncdest that takes two command line arguments that are named pipes. It starts out like sendinfo using the first named pipe and the current directory. It then reads from the second named pipe expecting data in the format sent by syncsource. For each file it receives, it replaces or creates a file with the given name. It sets the modification and access time of the file to the value it reads from the pipe. See the utime system call for how to do this. If the file is created, it uses permissions 0600. When you open the file to write use the mode
O_WRONLY | O_CREAT | O_TRUNC
to guarantee that the file will be truncated if necessary.

Think about why this will not work with the following algorithm for syncsource from part 6:

Do not solve this problem by modifying how syncdest works.

Also think about when the two pipes are opened by syncsource and syncdest and whether there is a possibility of a deadlock.

Get copies if the scripts checka, checkb, and checka1 from /usr/local/courses/cs3733/spring2001/assign45. Run checka and checkb from your assign4 directory to make sure you have set up testa and testb correctly. Save the output of these. Also execute ls -l testa and ls -l testb and save these.

Now run syncdest in one window in the testa directory and syncsource in another window in the testb directory. Run ls -l testa again and save the output. Also run checka1. Hand in the output generated by all of these. Make sure everything is clearly labeled.

Note that each time you run syncsource and syncdest, testa is modified and so you will need to recreate it again from the tar file before running again. You can uses the remakeab script in /usr/local/courses/cs3733/spring2001/assign45.


Part 8.
Copy syncsource into syncsources and modify it so that after it processes a set of inputs it goes back and processes another one. Modify it so that if it receives a SIGUSR1 signal it displays information about that last transfer that it did, in the format of compareinfo. If it receives a SIGUSR2 signal it displays the following:

Note that now that signals can be received, you need to make sure that all reads and writes will work correctly when interrupted by signals.

You may want to think about temporarily blocking the signals so that a signal is not received while the data to be printed is being updated.

Except for a startup message, the program syncsources should not do any output to standard output or standard error unless an error occurs or it receives a signal. The startup message should include not only your name, but the process ID of the process so that you can easily send signals to it.

Test this using three windows. Run syncdest and syncsources in two windows as in Part 7 and send signals to syncsources from another. Run syncdest several times, using touch to modify files in testb so they will be resent to testa.

Collect together some output to document your tests. Make sure it is clearly labeled and annotated so I can tell what the output means.