We can now solve the puzzle from the last page β why is deleting a file called
unlink? The answer runs through directories and a second way to name a file.
39.11 Making Directories
A set of calls create, read, and delete directories. You can never write a
directory directly: its format is file-system metadata, and the file system
keeps sole responsibility for its integrity β you change it only indirectly,
by creating files or directories inside it. To make one, call mkdir().
A freshly made directory is βemptyβ but not truly bare β it always has two
entries: . (dot), referring to itself, and .. (dot-dot), referring to its
parent:
Tip: Be Wary Of Powerful Commands
rm * deletes every file in a directory; rm -rf *
recursively deletes directories and all their contents. Run that by accident
from the wrong place (say, /) and you can erase an entire file system. Great
power, one keystroke away from great harm β tread carefully.39.12 Reading Directories
To read a directory (what ls does) you donβt open() it like a file; you use
opendir(), readdir(), and closedir(), looping one entry at a time:
DIR *dp = opendir(".");
struct dirent *d;
while ((d = readdir(dp)) != NULL) {
printf("%lu %s\n", (unsigned long) d->d_ino, d->d_name);
}
closedir(dp);
Each struct dirent is light β mostly a name and an inode number:
struct dirent {
char d_name[256]; // filename
ino_t d_ino; // inode number
off_t d_off; // offset to the next dirent
unsigned short d_reclen; // length of this record
unsigned char d_type; // type of file
};
Because a directory holds so little per entry, a tool that wants more (size,
ownerβ¦) calls stat() on each file β which is exactly what ls -l does.
39.13 Deleting Directories
You delete an empty directory with rmdir(). It has a safety requirement: the
directory must be empty (contain only . and ..) first. Trying to
rmdir() a non-empty directory simply fails β a guardrail against wiping out a
lot of data with one call.
39.14 Hard Links
Now the payoff. The link(old, new) system call β via the ln program β
creates a hard link hard link A second directory entry pointing at the SAME inode number as an existing file β another equal name for one file, made with link()/ln (no data is copied). Both names are indistinguishable; each raises the inode's link count. Can't span file systems (inode numbers are per-FS) or link to directories.
defined in ch. 39 β open in glossary
: a new directory entry that
points at the same inode number as an existing file. Nothing is copied; you
just get a second human-readable name for one underlying file. ls -i (which
prints inode numbers) proves it:
prompt> ln file file2
prompt> ls -i file file2
67158084 file
67158084 file2
So creating a file is really two steps: make an inode (holding the data
and metadata), and link a name to it in a directory. A hard link just adds
another name β same inode. To track this, the inode holds a
link count link count A reference count inside an inode tracking how many hard links (directory entries) point to it. link() increments it; unlink() decrements it; the file is truly deleted (inode + data freed) only when it hits zero.
defined in ch. 39 β open in glossary
(a reference count of how many names
point at it). unlink() removes one name and decrements the count; the inode
and its data blocks are freed only when the count reaches zero. Watch it
happen:
1echo hello > file
Creating a file does two things: it makes an inode (holding the file's real data + metadata) and links one human-readable name to it in the directory. Link count: 1.
And thereβs the answer to the mystery: the call is unlink(), not delete(),
because removing a name usually doesnβt delete the file β it just unlinks one
of possibly-many names, and only the last unlink (count β 0) truly frees it.
Check yourself: directories and hard links
1.Why can't a program write to a directory directly with write()?
2.A freshly created directory is 'empty', yet it already contains two entries. Which?
3.What restriction does rmdir() impose?
4.What exactly does a hard link (via link()) create?
5.You create a file, then two hard links to it (3 names), then rm two of them. Is the file's data still there?
6.Why is the file-removal system call named unlink() rather than delete()?