getcwd(3)

๐Ÿ’– getcwd(3) โ€” bestie's guide to finding out where you actually are ๐Ÿ’–

okay so you want to know your current working directory?? say less. this is the getcwd family from the Library Functions Manual, and honestly? it's giving "where am I" but make it C. let's go. ๐Ÿฆ‹


โœจ NAME โœจ

getcwd, getwd, get_current_dir_name โ€” three functions, one job: get the current working directory. queen behavior only. ๐Ÿ‘‘


๐Ÿ“š LIBRARY ๐Ÿ“š

Standard C library โ€” that's libc, link it with -lc and you're set, bestie. no cap. ๐Ÿ’…


๐ŸŒธ SYNOPSIS ๐ŸŒธ

#include <unistd.h>

char *getcwd(size_t size;
             char buf[size], size_t size);
char *get_current_dir_name(void);

[[deprecated]] char *getwd(char buf[PATH_MAX]);

Feature Test Macro Requirements for glibc (peep feature_test_macros(7) for the lore):

get_current_dir_name():
    _GNU_SOURCE

getwd():
    Since glibc 2.12:
        (_XOPEN_SOURCE >= 500) && ! (_POSIX_C_SOURCE >= 200809L)
            || /* glibc >= 2.19: */ _DEFAULT_SOURCE
            || /* glibc <= 2.19: */ _BSD_SOURCE
    Before glibc 2.12:
        _BSD_SOURCE || _XOPEN_SOURCE >= 500

like why do the macros gotta be so extra?? it's giving bureaucracy ngl. ๐Ÿ˜ญ


๐ŸŽ€ DESCRIPTION ๐ŸŽ€

so basically, these functions hand you a null-terminated string holding an absolute pathname โ€” and that pathname is the current working directory of the calling process. it comes back two ways: as the function's return value, AND through the argument buf, if there even is one. dual delivery, we love to see it. ๐Ÿ’–

getcwd() copies the absolute pathname of the current working directory straight into the array that buf points at, which is size bytes long.

but here's the tea โ˜• โ€” if the absolute pathname of the current working directory, including the terminating null byte, is longer than size bytes?? then NULL comes back and errno gets set to ERANGE. an application should fr check for this error and allocate a bigger buffer if it needs to. don't ignore it, bestie, it will humble you. ๐Ÿ™ˆ

As an extension to the POSIX.1-2001 standard, glibc's getcwd() will allocate that buffer dynamically using malloc(3) if buf is NULL. in that case, the allocated buffer has the length size โ€” unless size is zero, and then buf gets allocated as big as necessary, i.e. whatever it takes. the caller should free(3) the returned buffer. yes YOU. the caller. free it. ๐Ÿซถ

get_current_dir_name() will malloc(3) an array big enough to hold the absolute pathname of the current working directory. and โ€” cute detail โ€” if the environment variable PWD is set, and its value is correct, then that value will be returned. shortcut era. the caller should free(3) the returned buffer too. yes, again. ๐ŸŒˆ

getwd() does NOT malloc(3) any memory. nope. the buf argument should be a pointer to an array at least PATH_MAX bytes long. if the length of the absolute pathname of the current working directory, including the terminating null byte, exceeds PATH_MAX bytes, NULL is returned and errno is set to ENAMETOOLONG. (heads up: on some systems, PATH_MAX may not be a compile-time constant โ€” wild, right โ€” and its value may even depend on the filesystem, see pathconf(3).) and for portability and security reasons, use of getwd() is deprecated. it's giving legacy. we don't stan. ๐Ÿ’€


๐Ÿ’ซ RETURN VALUE ๐Ÿ’ซ

On success, these functions return a pointer to a string containing the pathname of the current working directory. for getcwd() and getwd(), that's the same value as buf. same girl, different outfit. โœจ

On failure, they return NULL and errno is set to indicate the error. and!!! the contents of the array pointed to by buf are undefined on error. undefined. as in, do not read it, do not trust it, do not look at it. ๐Ÿ™ˆ


๐Ÿ”ฅ ERRORS ๐Ÿ”ฅ

okay glow-up time, here's the full error roster:

  • EACCES โ€” permission to read or search a component of the filename was denied. rude, honestly.
  • EFAULT โ€” buf points to a bad address. bad address bestie, it's over.
  • EINVAL โ€” the size argument is zero and buf is not a null pointer.
  • EINVAL โ€” getwd(): buf is NULL.
  • ENAMETOOLONG โ€” getwd(): the size of the null-terminated absolute pathname string exceeds PATH_MAX bytes.
  • ENOENT โ€” the current working directory has been unlinked. it's gone. she left. ๐Ÿ˜ญ
  • ENOMEM โ€” out of memory.
  • ERANGE โ€” the size argument is less than the length of the absolute pathname of the working directory, including the terminating null byte. you need to allocate a bigger array and try again. bigger buffer, bigger dreams. ๐Ÿ’…

๐Ÿฆ‹ ATTRIBUTES ๐Ÿฆ‹

for an explanation of the terms used in this section, see attributes(7). here's the vibe check:

  • getcwd(), getwd() โ€” Thread safety: MT-Safe
  • get_current_dir_name() โ€” Thread safety: MT-Safe env

thread safe and thriving, periodt. ๐Ÿ‘‘


โญ VERSIONS โญ

  • POSIX.1-2001 leaves the behavior of getcwd() unspecified if buf is NULL. unspecified bestie, do with that what you will. ๐Ÿ˜ฌ
  • POSIX.1-2001 does not define any errors for getwd().

๐ŸŒˆ VERSIONS โ€” C library/kernel differences ๐ŸŒˆ

On Linux, the kernel provides a getcwd() system call, which the functions described in this page will use if possible. the system call takes the same arguments as the library function of the same name, but it's limited to returning at most PATH_MAX bytes. (before Linux 3.12, the limit on the size of the returned pathname was the system page size. on many architectures, PATH_MAX and the system page size are both 4096 bytes, but a few architectures have a larger page size.) if the length of the pathname of the current working directory exceeds this limit, then the system call fails with the error ENAMETOOLONG. in that case, the library functions fall back to a (slower) alternative implementation that returns the full pathname. it's giving plan B but make it work. ๐Ÿ’ช

Following a change in Linux 2.6.36, the pathname returned by the getcwd() system call will be prefixed with the string "(unreachable)" if the current directory is not below the root directory of the current process (e.g., because the process set a new filesystem root using chroot(2) without changing its current directory into the new root). such behavior can also be caused by an unprivileged user by changing the current directory into another mount namespace. when dealing with pathnames from untrusted sources, callers of the functions described in this page (before glibc 2.27) or the raw getcwd() system call should consider checking whether the returned pathname starts with '/' or '(' to avoid misinterpreting an unreachable path as a relative pathname. ๐Ÿšจ

seriously though โ€” if you're reading paths from untrusted sources, CHECK THAT FIRST CHARACTER. it's giving security bug energy and it is not the moment. ๐Ÿ™

๐ŸŽ€ STANDARDS ๐ŸŽ€

  • getcwd() โ€” POSIX.1-2008.
  • get_current_dir_name() โ€” GNU.
  • getwd() โ€” None. nope. nothing. nada. ๐Ÿ’€

๐Ÿ’œ HISTORY ๐Ÿ’œ

  • getcwd() โ€” POSIX.1-2001.
  • getwd() โ€” POSIX.1-2001, but marked LEGACY. Removed in POSIX.1-2008. use getcwd() instead, bestie, I'm begging. ๐Ÿ™

Under Linux, these functions make use of the getcwd() system call (available since Linux 2.1.92). on older systems they would query /proc/self/cwd. if both the system call and the proc filesystem are missing, a generic implementation is called. only in that case can these calls fail under Linux with EACCES. like, only then. so rare. iconic scarcity. โœจ


๐Ÿงš NOTES ๐Ÿงš

these functions are often used to save the location of the current working directory for the purpose of returning to it later. but hear me out โ€” opening the current directory (".") and calling fchdir(2) to return is usually a faster and more reliable alternative when sufficiently many file descriptors are available, especially on platforms other than Linux. save-and-restore but smarter. main character move. ๐ŸŒŸ


๐Ÿ’€ BUGS ๐Ÿ’€

since the Linux 2.6.36 change that added "(unreachable)" in the circumstances described above, the glibc implementation of getcwd() has failed to conform to POSIX and returned a relative pathname when the API contract requires an absolute pathname. with glibc 2.27 onwards this is corrected; calling getcwd() from such a pathname will now result in failure with ENOENT. so like, fixed, but also now it just. fails. which is its own whole thing. ๐Ÿ˜ญ


๐Ÿ‘‘ SEE ALSO ๐Ÿ‘‘

pwd(1), chdir(2), fchdir(2), open(2), unlink(2), free(3), malloc(3)

go read those next, bestie, you'll be unstoppable. ๐Ÿ’…


and that's the whole page!! this one came from Linux man-pages 6.20, dated 2026-02-08. ty for reading my little getcwd TED talk, now go free(3) your buffers and hydrate. mwah. ๐Ÿซถ๐Ÿ’–โœจ

๐Ÿ“ฆ where this page comes from
  • arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • ๐Ÿ“œ the page's license: Linux-man-pages-copyleft
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms