Tuesday, May 27, 2014

Playing around with getcwd, readpath and readlink

Recently, I had to write some code that dealt with the functions getcwd, readpath and readlink and I noticed a few peculiarities in them. I performed a few small tests and below are my observations(this post is mostly so that I can document for later reference if needed).

A few notes based on what the man pages say.

-=========================]
char *getcwd(char *buf, size_t size);
  1. Return a null terminated string containing an absolute pathname as the cwd
  2. Size should be the length of buf
  3. If length of the cwd > size of buf, NULL is returned, errno is set to ERANGE. An application should check for this error and allocate larger buffers if necessary.
  4. On success, it returns a pointer to buf. 
-=========================]
char *realpath(const char *path, char *resolved_path);
  1. Return a null terminated string, upto a maximum of PATH_MAX bytes in `resolved_path`
  2. if `resolved_path` is NULL, realpath allocates a buffer of upto PATH_MAX bytes and returns a pointer
  3. If function fails to resolve the path, NULL is returned. 
-=========================]
ssize_t readlink(const char *path, char *buf, size_t bufsiz);
  1. Contents of the symbolic link are placed in `buf`, of size `bufsize`.
  2. A null byte is not appended into buf
  3. If the buffer is too small to hold the contents, the results are truncated to bufsize.
-=========================]
A few silly tests

Lets try and create a few 1000 nested directories such that the length of the cwd exceeds 4096. I used this bash script. Interestingly the `pwd` at the end of the script works and prints out a path of length 7022.

We can't cd or ls that directory from home -- we get an error File name too long.

In order to cd into the directory we could use something as :-
for i in `seq 1 1000`; do cd tester; done

Lets try using readlink to resolve /proc/self/cwd using this. Running the code resulted in a "File name too long" error.

Trying to use getcwd to print the current working directory using this, surprisingly works.

Using realpath to resolve the full path of a file in the current directory as shown here, I get an error message Numerical result out of range.