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.

13
  • 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? Aug 18, 2015 at 4: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, 2015 at 6: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, 2015 at 16:33
  • Are you sure it's actually a directory and not something else ("Everything is a file")? Aug 19, 2015 at 4:54
  • @Breakthrough: The OP says that cd /tmp/strange_dir works; that would seem to prove that it is a directory. Aug 19, 2015 at 9:16

3 Answers 3

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.

3
  • 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, 2015 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. Aug 20, 2015 at 1: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. Aug 20, 2015 at 2: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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .