Linux Application Development (paperback) (2nd Edition)

   

14.1. The Current Working Directory

14.1.1. Finding the Current Working Directory

The getcwd() function allows a process to find the name of its current directory relative to the system's root directory.

#include <unistd.h> char * getcwd(char * buf, size_t size);

The first parameter, buf, points to a buffer that is filled in with the path to the current working directory. If the current path is larger than size - 1 bytes long (the -1 allows the path to be '\0' terminated), the function returns an error of ERANGE. If the call succeeds, buf is returned; NULL is returned if an error occurs. Although most modern shells maintain a PWD environment variable that contains the path to the current directory, it does not necessarily have the same value a call to getcwd() would return. PWD often includes path elements that are symbolic links to other directories, but getcwd() always returns a path free from symbolic links.

If the current path is unknown (such as at program startup), the buffer that holds the current directory must be dynamically allocated because the current path may be arbitrarily large. Code that properly reads the current path looks like this:

char * buf; int len = 50; buf = malloc(len); while (!getcwd(buf, len) && errno == ERANGE) { len += 50; buf = realloc(buf, len); }

Linux, along with many other Unix systems, provides a useful extension to the POSIX getcwd() specification. If buf is NULL, the function allocates a buffer large enough to contain the current path through the normal malloc() mechanism. Although the caller must take care to properly free() the result, using this extension can make code look much cleaner than using a loop, as was shown in the earlier example.

BSD's getwd() function is a commonly used alternative to getcwd(), but it suffers from certain defects that led to the development of getcwd().

#include <unistd.h> char * getwd(char * buf);

Like getcwd(), getwd() fills in buf with the current path, although the function has no idea how large buf is. getwd() never writes more than PATH_MAX (defined through <limits.h>) to the buffer, which allows programs to avoid buffer overruns, but does not give the program any mechanism for finding the correct path if it is longer than PATH_MAX bytes![1] This function is supported by Linux only for legacy applications and should not be used by new applications. Instead, use the correct and more portable getcwd() function.

[1] That is right; PATH_MAX is not an actual limit. POSIX considers it indeterminate, which is morally equivalent to "do not use this."

If the current directory path is displayed to users, it is normally a good idea to check the PWD environment variable. If it is set, it contains the path the user thinks he is using (which may contain symbolic links for some of the elements in the path), which is generally what the user would like an application to display. To make this easier, Linux's C library provides the get_current_dir_name() function, which is implemented like this:

char * get_current_dir_name() { char * env = getenv("PWD"); if (env) return strdup(env); else return getcwd(NULL, 0); }

14.1.2. The . and .. Special Files

Every directory, including the root directory, includes two special files, called . and .., which are useful in some circumstances. The first, ., is the same as the current directory. This means that the file names somefile and ./somefile are equivalent.

The other special file name, .., is the current directory's parent directory. For the root directory, .. refers to the root directory itself (because the root directory has no parent).

Both . and .. can be used wherever a directory name can be used. It is common to see symbolic links refer to paths such as ../include/mylib, and file names like /./foo/.././bar/./fubar/../../usr/bin/less are perfectly legal (although admittedly convoluted).[2]

[2] For the curious, that pathname is equivalent to the much simpler /usr/bin/less.

14.1.3. Changing the Current Directory

There are two system calls that change a process's current directory: chdir() and fchdir().

#include <unistd.h> int chdir(const char * pathname); int fchdir(int fd);

The first of these takes the name of a directory as its sole argument; the second takes a file descriptor that is an open directory. In either case, the specified directory is made the current working directory. These functions can fail if their arguments specify a file that is not a directory or if the process does not have proper permissions.


       
     

    Категории