A process’s current working directory defines the starting point for the resolution of relative pathnames referred to by the process. A new process inherits its current working directory from its parent.
A process can retrieve its current working directory using getcwd().
#include <unistd.h>
char *getcwd
(char *cwdbuf, size_t size);
Returns cwdbuf on success, or NULL
on error
The getcwd() function places a null-terminated string containing the absolute pathname of the current working directory into the allocated buffer pointed to by cwdbuf. The caller must allocate the cwdbuf buffer to be at least size bytes in length. (Normally, we would size cwdbuf using the PATH_MAX
constant.)
On success, getcwd() returns a pointer to cwdbuf as its function result. If the pathname for the current working directory exceeds size bytes, then getcwd() returns NULL
, with errno set to ERANGE
.
On Linux/x86-32, getcwd() returns a maximum of 4096 (PATH_MAX
) bytes. If the current working directory (and cwdbuf and size) exceeds this limit, then the pathname is silently truncated, removing complete directory prefixes from the beginning of the string (which is still null-terminated). In other words, we can’t use getcwd() reliably when the length of the absolute pathname for the current working directory exceeds this limit.
In fact, the Linux getcwd() system call internally allocates a virtual memory page for the returned pathname. On the x86-32 architecture, the page size is 4096 bytes, but on architectures with larger page sizes (e.g., Alpha with a page size of 8192 bytes), getcwd() can return larger pathnames.
If the cwdbuf argument is NULL
and size is 0, then the glibc wrapper function for getcwd() allocates a buffer as large as required and returns a pointer to that buffer as its function result. To avoid memory leaks, the caller must later deallocate this buffer with free(). Reliance on this feature should be avoided in portable applications. Most other implementations provide a simpler extension of the SUSv3 specification: if cwdbuf is NULL
, then getcwd() allocates size bytes and uses this buffer to return the result to the caller. The glibc getcwd() implementation also provides this feature.
The GNU C library also provides two other functions for obtaining the current working directory. The BSD-derived getwd(path) function is vulnerable to buffer overruns, since it provides no method of specifying an upper limit for the size of the returned pathname. The get_current_dir_name() function returns a string containing the current working directory name as its function result. This function is easy to use, but it is not portable. For security and portability, getcwd() is preferred over these two functions (as long as we avoid using the GNU extensions).
With suitable permissions (roughly, we own the process or have the CAP_SYS_PTRACE
capability), we can determine the current working directory of any process by reading (readlink()) the contents of the Linux-specific /proc/
PID/cwd
symbolic link.
The chdir() system call changes the calling process’s current working directory to the relative or absolute pathname specified in pathname (which is dereferenced if it is a symbolic link).
#include <unistd.h>
int chdir
(const char *pathname);
Returns 0 on success, or -1 on error
The fchdir() system call does the same as chdir(), except that the directory is specified via a file descriptor previously obtained by opening the directory with open().
#include <unistd.h>
int fchdir
(int fd);
Returns 0 on success, or -1 on error
We can use fchdir() to change the process’s current working directory to another location, and then later return to the original location, as follows:
int fd; fd = open(".", O_RDONLY); /* Remember where we are */ chdir(somepath); /* Go somewhere else */ fchdir(fd); /* Return to original directory */ close(fd);
The equivalent using chdir() is as follows:
char buf[PATH_MAX]; getcwd(buf, PATH_MAX); /* Remember where we are */ chdir(somepath); /* Go somewhere else */ chdir(buf); /* Return to original directory */