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);
- Return a null terminated string containing an absolute pathname as the cwd
- Size should be the length of buf
- 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.
- On success, it returns a pointer to buf.
char *realpath(const char *path, char *resolved_path);
- Return a null terminated string, upto a maximum of PATH_MAX bytes in `resolved_path`
- if `resolved_path` is NULL, realpath allocates a buffer of upto PATH_MAX bytes and returns a pointer
- If function fails to resolve the path, NULL is returned.
ssize_t readlink(const char *path, char *buf, size_t bufsiz);
- Contents of the symbolic link are placed in `buf`, of size `bufsize`.
- A null byte is not appended into buf
- 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.