|
Hi osxbook,
"Directories don't have hard links on Mac OS X (well, not yet), or on any typical Unix system for that matter."
Oh, but they do, at least on Unix as my post above shows. ls -ld foo is showing that foo's inode has a reference count of 2; the second word of output. And ls -di foo foo/. is showing that both paths have the same inode number, 3107002.
It's true that originally directories could also be hard linked with a system call but this was stopped because confusion could result, including hierarchy cycles. However, the kernel never stopped using hard links on directories, for example to implement .., and if you are writing a filesystem you still set up those hard links when making a directory; I doubt FUSE alters this.
As for Mac OS X altering this aspect, perhaps it does but I doubt it. Here's a test to do on the native, non-FUSE, shipped by Apple, filesystem.
$ mkdir foo
$ cd foo
$ ls -ld .
drwxr-xr-x 2 ralph ralph 4096 2007-03-15 14:29 .
$ touch a b c d e f g h
$ ls -ld .
drwxr-xr-x 2 ralph ralph 4096 2007-03-15 14:29 .
$ mkdir 1 2 3
$ ls -ld .
drwxr-xr-x 5 ralph ralph 4096 2007-03-15 14:29 .
$
Keep an eye on the second word of ls(1)'s output. On a newly created, empty, directory it should be 2. Creating files in the directory doesn't change this. But creating subdirectories does; the link count is incremented because 1/.., 2/.., and 3/.. are all hard links to foo.
Cheers, Ralph.
|
"Oh, but they do,"
First off, when I say "directories don't have hard links", I mean you can't create a hard link to a directory (through link(2)). You are interpreting "hard link" to be synonymous with the link count of a file or directory.
"As for Mac OS X altering this aspect, perhaps it does but I doubt it. Here's a test to do on the native, non-FUSE, shipped by Apple, filesystem."
The native file system on OS X is HFS+ and not UFS. Looks like your example uses UFS, and you also seem to assume that an inode-based "traditional" Unix file system is the only way to do things.
On UFS, which indeed uses "real" inodes, you see the behavior you mentioned. That's because UFS will cause st_nlink to be set to the inode's link count. A brand new directory's inode's link count is 2. The mkdir vnode operation for UFS increments the parent directory's inode's link count. This is why you see what you're seeing.
Now, HFS+ uses a bunch of B-Trees: one for the file system's hierarchical structure (the Catalog), another for attributes, another for extents, and so on. It doesn't use inodes the way you're thinking. In fact, what's reported as the inode number isn't really an inode number, but the node number in the Catalog B-Tree. There are no inodes in HFS+. In particular, the "." and ".." entries are "fake" special cases.
Try your example on HFS+:
As you see, the second word of ls(1)'s output has a different meaning here. It is the number of file system objects within the directory.
How file hard links are implemented on HFS+ is interesting too, but that's another story.
Moreover, if a Mac OS X file system tells the kernel that it doesn't support the nlink field, the kernel will substitute a value of 1.
"for example to implement .., and if you are writing a filesystem you still set up those hard links when making a directory; I doubt FUSE alters this."
MacFUSE is a file system enabler--not a file system itself (well, technically, it is a file system, just a generic one). Specific file systems are free to report whatever they like for st_nlink.
It's actually a bit more complicated on Mac OS X, since there is also the concept of file system attributes. In the man page of getattrlist(2), look for ATTR_DIR_LINKCOUNT and ATTR_FILE_LINKCOUNT.
Hopes this clarifies things.