Saturday, July 2, 2011

Writing My Own 'ls'

It was the 2nd assignment for System Programming Lab, we had to implement the "ls" directory listing program on our own.

However, it was not a hard task, but it was a bit time consuming, specially when it came around the output formatting for different type of options. We were asked to implement a limited amount of options, and all of those are short options. So, I've implemented accordingly, with some more short options, that the real "ls" has. According to most of my classmates, the real hard part seem to be implementing the "-R" i.e. recursive traversal option. But actually it is quite easy if you know how to implement a DFS algorithm.

So, it's basically simple, you start from starting parameter, use opendir() and readdir() to get the contents of the the directory, process them, and then recursively call on the child directories in a DFS fashion.

Well, there is a catch here. The dirent structure has a field "d_name" which will give you the name of the entry of a specific directory. As we know, in ls, we need various information regarding the entries which can be found using stat() or lstat() calls, which takes the path to the entry as a parameter, but not just the name. So, using the d_name directly will cause you run into troubles pretty easily (as I have seen this mistake was made commonly in lab). Obviously the first time it works if you test it on current directory (most of the cases), because, for the current directory, the relative path is actually just the entry name. So for all the other cases, you will need to provide the full path (also can be the relative path from pwd) to stat() or lstat() whatever you use.

Another thing was to follow or read symbolic links. Well, opendir() by defaults follow symbolic links, and thus this is not a problem at all. For long formatting, we had to print the target entry name as well, and readlink() did that for us. Be careful when using stat(), if a link is pointing to a directory, it will tell you that the link is also a directory, so to test whether it is actually a link, you have to use lstat().

The man page for stat() (as far as I remember, $ man 2 stat) contains a code that will show you how to use the bit flags on st_mode field. To manage everything, I created a switchboard first, then switch specific flags regarding which options are present in the argument list.

There are two more tiny works to do. for the "-1" option, you need to detect whether your output stream is tied to a terminal or not. This can be checked by isatty(fileno(stdout)), if it returns non-zero, then it is a terminal. Also, for some other options, you need to detect whether you are a super user or not. You can use geteuid() i.e. get effective user id to see if it is 0. In case you are not a super user, you will have a non-zero return.

This is pretty much the work, here is my implementation if you think it might help you.


  1. Hello, Zobayer! nice to read your blog :)
    I'm also studying computer, especially informatic engineering. I'm studying in Sepuluh Nopember Institute of Technology, Surabaya Indonesia.
    I hope we can be friend to share knowledge :)

    1. Hello, it's really nice to see someone from other country reading my blog. I would really love to share thoughts with other people very much.