The Unix File System
A file is a file is a file...
• Almost everything is represented as files in Unix: regular files, directories, output device
(monitor,printer), input device (keyboard), pipes, network sockets...
• This consistency is what makes Unix programs powerful.
• For instance, the cat command that usually displays the contents of a file on your screen can be made
to print the file on the printer:
Display on screen:
$lpr < cat hello.cpp
cat doesn't know the difference between the monitor and printer. It's just writing its output to the standard
place: the standard ouput (stdout). In the first case, the stdout points to the screen, and in the second case, it
has been REDIRECTED to the standard input (stdin) of the printer.
• UNIX commands typically input from stdin and output to stdout
• Manipulate stdin and stdout to accomplish other tasks
• Use < to redirect input: lpr < cat hello.cpp
• Use > to redirect output: cat hello.cpp > file2
• Use | (pipe) to connect stdout to stdin: cat hello.cpp | wc -l
• >> appends to existing files: echo more text >> file2
$cat hello.cpp > file2
$cat file2 | wc -l
$echo more text >> file2
$ The Unix File "Tree"
• / represents the root directory
• Each directory contains 0 or more files and subdirectories
• Fully qualified path names begin with root (/) followed by 0 or more subdirectories
• Cannot use / character in filename
• Also don't use '-' (options), '*' and '?' (wild cards) in filenames
The '-' character is often used to pass parameters to commands. For example ls -l gives the detailed listing
of files in the current directory. If you had a file that began with '-', ls and other commands will get very
confused. For a similar reason, '*' and '?' are used as wildcard patterns to match one or more files: ls * lists
all files in the directory.
Example File Tree: (fig 1-1)
• One file system per disk partition.
• A file system can be mounted at any point in the directory tree of another file system.
• u might reside on another disk
Fully qualified and Relative path names
• suppose CWD (current working directory) is /usr/you/
• when you type cat hello.c, hello.c is the relative path
• use relative path and CWD to construct fully qualified path:
/usr/you/hello.c Under the covers: Inodes:
• A directory is really just a special kind of file that contains a list of filenames and inode numbers.
• Many to 1 mapping from directory entry to inode (links, explained later)
• The inode is the building block of the UNIX file system. They contain all kinds of information about
the directory entry, such as:
• The access permission
• The owner and group of the file
• The last access time, modification time
• A list of the disk block numbers where data for the file is stored. If the file is small, direct block
numbers are stored. Larger files require the inode to store block numbers for blocks that contain
more block numbers (indirection).
An example “i-list” for the directory tree in fig1-1:
inode # contents
2 bin 3, homes 6
3 date 4, ls 5
4 contents of date program
5 contents of ls program
6 file1 7, u1 8, u2 9
7 contents of file1
8 reidsfile 10
9 csc209h 11
10 contents of reidsfile
11 A1.doc 12, hello.c 13
12 contents of A1.doc
13 contents of hello.c
the /u/ directory is on another disk, so no inode entry. Hard Links
• Hard link links directory entry to the inode describing the actual item
• Each file has 1 or more hard links.
• Removing a file decrements the link count (at 0, the inode & disk space are freed)
• hard links have equal status. Two links to a file: remove either one, the other one stays.
• create hard links with ln
$ ls -li
1097747 -rw-r--r--1 ken ken 83 Apr 25 00:18 file1
$ ln file1 file2
$ ls -li
1097747 -rw-r--r--2 ken ken 83 Apr 25 00:18 file1
1097747 -rw-r--r--2 ken ken 83 Apr 25 00:18 file2
$ cat file1
$ echo add a line >> file1
$ cat file2
add a line
The i in ls -li tells ls to print the inode # (1st column). The 3rd column is the link count. Notice how it
changes from 1 to 2 after the additional link has been created with ln file1 file2. Note also how a change to
file1 affects file2 as well.
Soft Link (Symlink)
• A Symlink is a file whose content is treated as path name
• File it points to need not exist
• Remove symlink ≠ remove file
• Symlinks can cross filesystems... hard links can't!
Programming the File System
File interfaces in Unix
• Unix has two main mechanisms for managing file access.
• file pointers: standard I/O library (Ch. 11)
• You deal with a pointer to a FILE structure that contains a file descriptor and a buffer.
• Use for regular files (more abstract and portable)
• file descriptors: low-level (Ch. 2)
• Each open file is identified by a small integer.
• Use for pipes, sockets.
You should use the standar I/O library whenever possible. This will make your programs more portable
across different platforms. Use file descriptors only when your program requires Unix specific features. In
general, structure your code so you can isolate platform dependent code - porting programs with platform
dependent code littered everywhere can be a nightmare. stdin,stdout,stderr
• 3 files are automatically opened for any executing program:
Standard in put stdin 0
Standard output stdout 1
Standard error stderr 2
• Reading from stdin by default comes from the keyboard
• Writing to stdout or stderr by default goes to the screen.
File manipulation primitives
• open() opens a file for read/write, or create empty file
• close() must close opened files
• lseek() move to a specific position in a file
• unlink() remove a file
• fcntl() controls file attributes
• int open(const char * pathname,int flags, [mode_t mode]);
• pathname: any valid pathname, relative or absolute
• flags: defined in fcntl.h
O_RDONLY read only
O_WRONLY write only
O_RDWR read write
O_CREAT create if doesn't exist
O_APPEND append to the end of the file
O_TRUNC truncate size to 0 if file exists
O_EXCL fail if file exists already
• mode: Sets the permission of created files. Needed it only if creating files. See notes later in this
• int close(int filedes); Make sure to close files you opened!
There are more...look at the detailed doc for open()
#define PERMISSION 0644 //don't worry about this yet.
const int EXIT_OK = 0; -1;
const int EXIT_ERROR = 1; char * myfile="mynewfile";
filedes = open(myfile,O_WRONLY|O_CREAT,PERMISSION);
printf("couldn't create file!\n");
printf("File opened/created. Proceeding with program...\n");
//be sure to close any file descriptors you open!
• ssize_t read(int filedescriptor,void * buffer, size_t n);
• ssize_t write(int filedescriptor,const void * buffer,size_t n);
• most efficient when moving data in blocks that are multiple of disk block size (512)
• read/write in big chunks where possible, to minimize system calls (can get expensive)
Do not mix in read()/write() calls with ANSI standard IO calls like fread(), fwrite() etc. for the same file.
This is because the ANSI standard IO calls provide for buffering, and so the actual read or write from disk
may not occur immediately after you make the call. By contrast read()/write() reads or writes immediately,
so mixing the two types of I/O routines for the same file is a dangerous practice.
lseek() - random access