Linux: How could a directory be created without "." and ".."?

6

2

I am not sure if the following issue is specific to busybox: I have an embedded device with busybox installed. From what I understand, when a directory is created, usually 2 hidden files will be automatically created: . to represent the current directory and .. to represent the parent directory. For example, by typing mkdir -p /tmp/normal_dir; cd /tmp/normal_dir; ls -a, the output will be . ...

However, I have seen a case where an existing directory (/tmp/strange_dir) does not show . and ... That is, by typing cd /tmp/strange_dir; ls -a, the output is empty, although navigating to the parent directory still works. That is, by typing cd .., the content is correct.

My question is: How could such a directory without . and .. (like /tmp/strange_dir) be created? I am puzzled.

jonathanzh

Posted 2015-08-18T01:37:44.937

Reputation: 161

Interesting question. Might be better to ask on Unix.SE. My instinct is to stat the directory; does cd strange_dir; stat -l . give anything? – Sean Allred – 2015-08-18T04:03:48.050

Do others directory show .and ..?, maybe what's modified is the ls command, for example by creating an alias ls that internally calls the regular ls but strips from the output the .and ..results. – Javier Mr – 2015-08-18T06:37:32.657

Only '/tmp/strange_dir' has this issue. Typing 'stat -L /tmp/strange_dir' results in an output that is similar to any other directory I have tried. One major observed difference is that the Size is 0 while other directories have Size greater than 0. For example, creating a new directory by using 'mkdir -p' will result in a Size of 40. Maybe Size 0 is the direct cause of not showing '.' and '..'. So the next question might be: How to create a directory with Size equal to 0? – jonathanzh – 2015-08-18T16:33:38.913

Are you sure it's actually a directory and not something else ("Everything is a file")?

– Breakthrough – 2015-08-19T04:54:46.563

@Breakthrough: The OP says that cd /tmp/strange_dir works; that would seem to prove that it is a directory. – Scott – 2015-08-19T09:16:32.213

@Scott not necessarily; it's possible that strange_dir is a symlink to another directory in this case, or it could be something like a hardware device mapped with a pseudo-filesystem, like /proc (see On linux, what does it mean when a directory has size 0 instead of 4096? from Server Fault).

– Breakthrough – 2015-08-19T10:47:29.230

@Breakthrough: It seems to me that you're splitting hairs.  If strange_dir is a symlink, it must be a symlink to a directory, which is where you end up when you cd strange_dir.  And filesystem mount points are still directories — even /proc and /sys have . and .. — although it's true that "autofs" mount points are a bit funky. – Scott – 2015-08-19T13:04:05.170

@Scott @Breakthrough Based on your comments I'm guessing that strange_dir may be related to autofs or pseudo-filesystem. But how to confirm this? – jonathanzh – 2015-08-19T22:28:34.800

(1) IMNSHO, it’s unlikely that you’d have either an autofs or a pseudo-filesystem in /tmp.  Is strange_dir really in /tmp, or are you just saying that for anonymity purposes?  (2) Look in /etc for files whose names begin with auto.  In particular, look at auto.master and any files whose names it lists.  That should give you a clue as to whether you have an autofs.  … (Cont’d) – Scott – 2015-08-20T01:50:28.287

(Cont’d) …  (3) I would suggest that you rename strange_dir (or, if you prefer, delete it).  If you can’t rename or delete it, that may give us a clue as to what it is (i.e., depending on the error message, it might tell us that it might be something special).  If you can rename or delete it, wait for a while and see whether it comes back.  (Try to cd to it, even if it doesn’t appear to exist.)  If it doesn’t come back, reboot and see whether it comes back then.  If it does, that will tell us that it was/is something special.  If it doesn’t come back, it was probably just an anomaly. – Scott – 2015-08-20T01:52:16.223

@Scott (1) The actual directory name is /tmp/pluginshare/nbd/vfs. I used /tmp/strange_dir just for simplicity. (2) There is no file whose name begins with auto under /etc. (3) Trying to rename vfs will result in a message like this: [mv: can't rename 'vfs': Device or resource busy]. The directory is always there after rebooting the device. – jonathanzh – 2015-08-20T17:09:02.857

Thanks for the update. vfs might stand for Virtual File System, which would suggest that this is something magical. The fact that you cannot rename it, and that you get a somewhat unusual error message, tends to confirm that it is something special and not just a fluke. (The fact that it's still there after a reboot, if you couldn't rename it, is unsurprising and doesn't really tell us anything.) I'm running out of ideas; I suggest that you research VFS. If you figure out what you have, please post an answer here. If you don't, maybe you should ask a new question that reflects your research. – Scott – 2015-08-20T18:04:26.983

... and, as Sean Allred suggested (in the first comment), if you do come back and post a new, smarter, more focused question, it might be better on unix.stackexchange. (But pick one site; don't post it on both.) – Scott – 2015-08-20T18:08:30.533

Answers

3

This can happen if you are accessing the directory via a symlink, but the linked directory is removed. For example, in /tmp, let's create a directory and a symlink to that directory:

$ cd /tmp
$ mkdir normal_dir
$ ln -s normal_dir strange_dir

Now, if we navigate to strange_dir, we get the expected output:

$ cd strange_dir
$ ls -a
. ..

If, however, we remove the directory normal_dir without changing the directory, indeed we get an interesting result:

$ rmdir /tmp/normal_dir
$ ls -a

$ ls -al
total 0

So although our link now points to nothing, the working "directory" of the shell is still the same:

$ pwd
/tmp/strange_dir

$ cd /tmp/strange_dir
bash: cd: /tmp/strange_dir: No such file or directory

$ ls -al
total 0

Running stat -L . while our working directory is still at /tmp/strange_dir will now show Size: 0 as discussed in the above comments. Although the output of ls shows nothing now (not even . nor ..), we can still navigate just fine to the parent directory .. in this case, as you outlined:

$ cd ..
$ pwd
/tmp

$ ls -a
. .. strange_dir

Although the symlink still exists, it doesn't point to anything, so we can't cd back into strange_dir at this point, unless the directory /tmp/normal_dir is re-created. To clean up, we can just remove the symlink by calling rm /tmp/strange_dir.

Breakthrough

Posted 2015-08-18T01:37:44.937

Reputation: 32 927

Great explanation about a case where strange_dir can have Size 0 and you can go up to its parent directory. However, my case appears to be different: strange_dir is not a symlink, and I can always go back into it. – jonathanzh – 2015-08-19T16:31:24.713

This really has nothing to do with symbolic links; it is entirely about having your current directory removed (while you are in it).  Please note that my answer already addressed exactly that scenario, with the trivial distinctions that (1) my scenario didn’t involve symlinks, and (2) I used ls -ldi instead of stat -L . to get information on the current directory.  …  Finally, the fact that the OP’s /tmp/strange_dir still exists, and cd /tmp/strange_dir still works, rules out this explanation. – Scott – 2015-08-20T01:56:21.720

@Scott FWIW, I agree with your answer (the upvote you have is from me)... I was just trying to expand on the cases where this may occur. – Breakthrough – 2015-08-20T02:34:20.827

1

It's conceivable that such an aberration could be created if somebody said

mkdir /tmp/strange_dir

at a time when the filesystem was full (i.e., there were no free blocks).  It would still (probably) have been possible to create the strange_dir directory entry in /tmp, because that would require only a few bytes of unused space in one of the blocks already allocated to /tmp.  But it would have been impossible to allocate a block for strange_dir itself, and therefore it would have been impossible to create the . and .. entries.  In such a case, I would expect the mkdir program to remove (unlink) the strange_dir directory entry in /tmp, but software doesn't always do what I expect.

Other possibilities:

  • mkdir got interrupted (terminated) between creating the strange_dir directory entry in /tmp and creating the . and .. entries in strange_dir.  I would expect mkdir to catch the interrupt signal (i.e., Ctrl+C) and clean up after itself, but see above regarding software and my expectations of it.  And, of course, it cannot catch the kill signal or a system crash. 
  • rmdir got interrupted (terminated) between unlinking the . and .. entries in strange_dir and unlinking the strange_dir directory entry in /tmp.

One might expect that the fsck that runs after a crash would detect the strange_dir and do something about it, but ....

Yes, of course, if a directory has a size of 0, that means that it has no blocks allocated to it, and therefore it cannot have any contents (not even little ones like . and ..).

I don't fully understand why cd .. would work when there is no .., but see the discussion in Removing a directory from inside using the command line interface.  It turns out that

mkdir /tmp/strange_dir
cd /tmp/strange_dir
ls -lai                 ← Shows normal . and .., with inode numbers.
rmdir /tmp/strange_dir
pwd                     ← Still reports /tmp/strange_dir
ls -lai                 ← Shows empty directory: Total 0
ls -ldi                 ← Shows . with the same inode number it had before,
                          but with a size of 0 and a link count of 0.
cd ..                   ← Puts you back into /tmp

This situation is not perfectly analogous to the one in this question, because, in this other case, strange_dir is removed from /tmp.  But it suggests that cd .. is special, and sometimes works when there's no obvious mechanism by which it could.

Strange difference between pwd and /bin/pwd suggests a possibility as to how this might work.  The shell keeps track of your current directory.  That is, it keeps track of a best guess as to what your current directory is.  It con be fooled by symbolic links and tricks like

mkdir /tmp/foo
cd /tmp/foo
mv /tmp/foo /tmp/foobar

i.e., it will still think that the current directory is /tmp/foo, and so that's what pwd will report, but pwd -P and /bin/pwd will report /tmp/foobar.  So, it may be that, if chdir("..") fails, the shell computes what it thinks your next-level-up directory should be, and goes there absolutely.  (But I suspect that there's more to it than that.)

Scott

Posted 2015-08-18T01:37:44.937

Reputation: 17 653

0

Thanks for the discussions so far. Following is an explanation from a colleague of mine who is not a member of the Super User community:

/tmp/strange_dir in my case is an NBD/VFS (Network Block Device/Virtual File System) directory. This type of virtual file system differs from more traditional file systems and has its own implementation of the shell commands. So it is not surprising that, when the directory is empty, ls -a shows nothing but cd .. allows going up to its parent directory.

jonathanzh

Posted 2015-08-18T01:37:44.937

Reputation: 161