Skip to content

getcwd() vs get_current_dir_name()?

Is it better to use getcwd(NULL, 0) or get_current_dir_name() ? What is common practice ?

My uninformed guess is that a call to getcwd(NULL, 0) may be a better idea since it is possible that the PWD variable is not set…



Is it better to use getcwd(NULL, 0) or get_current_dir_name() ? What is common practice ?

This is operating system specific. I guess you use Linux.

Then, read syscalls(2) and getcwd(3). Study the source code of its implementation in GNU libc or in musl libc

Notice that

  • getcwd takes a buffer of a given known size. In practice, 256 bytes might be often enough, but in principle the buffer should be much bigger. See sysconf(3) and pathconf(3). Accepting getcwd(NULL,0) is an extension equivalent to get_current_dir_name() so uses malloc and could fail. My Debian computer has in /usr/include/linux/limits.h a macro definition #define PATH_MAX 4096 (but 4096, when used as the size of some automatic variable, is a lot for a call frame of any recursive function; look also into nftw(3)).

  • getwd is obsolete since prone to buffer overflow. Don’t use it in 2021.

  • get_current_dir_name uses malloc(3) which could fail.

AFAIK, getcwd(3) should not use the PWD environment variable. It should work if you code your own /sbin/init using it

And sometimes, you can boot a Linux kernel running /bin/bash instead of /sbin/init. In such case, the PWD environment variable is not set. See environ(7) and credentials(7).

Of course, in most other programs, PWD is correctly set (e.g. by GNU bash, whose source code you can study since it is free software)

My personal recommendation

  • assume and document that your program won’t run for file paths larger than e.g. 256 bytes (but be aware that UTF 8 is everywhere in 2021). This assumption could be false for file names which are generated with UUID strings or several IPV6 addresses, and you might want to use C dynamic memory allocation for path below…. so a near equivalent of get_current_dir_name. Don’t forget to free it!

  • code something like:

    char path[256];
    memset (path, 0, sizeof(path));
    if (getcwd(path, sizeof(path)) == NULL) {
      exit(EXIT_FAILURE); // or abort()

Of course, if you code an init-like program for some robot, this is not good enough. Robots on Mars might generate long path names!