Systems Programming

Laboratory: Directories

Today, we're going to start using system calls, and we'll get some exposure to error handling. (See the notes on System Calls and Error Handling and course Chapter 1 from Marc Rochkind's book (from which much of the notes were derived.) If we get to Exercise 2, we'll also get some exposure to shell scripts.

We'll start our adventure by writing a program to duplicate some of the functionality of ls. You are all familiar with the hierarchical file systems supported by Unix. But what is a directory? In old versions of Unix, a directory was just a file that contained the names of the files in the directory (plus some other information). You could read the file just like any other. On more modern systems, a directory is still a special kind of file, but the format of the file is system-dependent, so you shouldn't open it and read it using the normal file operations (though if you want to experiment, go ahead!). We'll discuss more about the Unix file system model as we go and in later classes.

Exercise 1

Write a program, lsdir, that takes as an argument the name of a directory and lists the files in it. If there is no argument, it lists the contents of the current directory. You will need to use the following system calls:
DIR *opendir(const char *name);
struct dirent *readdir(DIR *dir);
int closedir(DIR *dir);
Note: There is more than one readdir() call. Use the higher-level one defined in section 3 of the manual pages on our Linux machines.

The idea is the same as reading from a file (which is what is actually happening behind the scenes). You open the directory, keep reading until you get what you want (or come to the end), and close the directory. There is also support for rewinding to the beginning and doing random access, but we won't need those today.

Write the first version of your program (call it lsdiropt for optimistic) as simply as possible: don't do any error checking in this version. Study your output. How does it relate to what ls produces? Compare your output to ls -1

Then put in the error handling code, which in this case is a little tricky. readdir() may alter errno during a normal read. If readdir() reaches the end normally, it doesn't change errno, it just returns NULL. Do you see the problem?

How does error checking alter your code? Did you have to change the logic in any significant way?

After you've tried it, have a look at a sample solution.

Exercise 2

Write a shell script called lsdirsort that emits a sorted directory listing.

What is a shell script and how does one write such a thing? A shell script is simply a bunch of shell commands in a file. It turns out that the shell language is pretty powerful (it has conditionals, loops, functions). Of course, there is plenty of idiosyncratic syntax.

To write a syell script you have to:




Author: Mark A. Sheldon
Modified: 28 February 2008