6

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.

Sean Allred
  • 1,182
  • 2
  • 11
  • 32
jonathanzh
  • 161
  • 2
  • 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 Aug 18 '15 at 04:03
  • 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 Aug 18 '15 at 06:37
  • 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 Aug 18 '15 at 16:33
  • Are you sure it's actually a directory and not something else (["Everything is a file"](https://en.wikipedia.org/wiki/Everything_is_a_file))? – Breakthrough Aug 19 '15 at 04:54
  • @Breakthrough: The OP says that `cd /tmp/strange_dir` works; that would seem to prove that it is a directory. – Scott - Слава Україні Aug 19 '15 at 09:16
  • @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?](http://serverfault.com/q/232093/178593) from Server Fault). – Breakthrough Aug 19 '15 at 10:47
  • @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 - Слава Україні Aug 19 '15 at 13:04
  • @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 Aug 19 '15 at 22:28
  • (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 - Слава Україні Aug 20 '15 at 01:50
  • (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 - Слава Україні Aug 20 '15 at 01:52
  • @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 Aug 20 '15 at 17:09
  • 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 - Слава Україні Aug 20 '15 at 18:04
  • ... 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 - Слава Україні Aug 20 '15 at 18:08

3 Answers3

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
  • 34,227
  • 10
  • 105
  • 149
  • 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 Aug 19 '15 at 16:31
  • 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 - Слава Україні Aug 20 '15 at 01:56
  • @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 Aug 20 '15 at 02:34
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.)

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
  • 161
  • 2