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โbufpoints to a bad address. bad address bestie, it's over.EINVALโ thesizeargument is zero andbufis not a null pointer.EINVALโgetwd():bufisNULL.ENAMETOOLONGโgetwd(): the size of the null-terminated absolute pathname string exceedsPATH_MAXbytes.ENOENTโ the current working directory has been unlinked. it's gone. she left. ๐ญENOMEMโ out of memory.ERANGEโ thesizeargument 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-Safeget_current_dir_name()โ Thread safety:MT-Safe env
thread safe and thriving, periodt. ๐
โญ VERSIONS โญ
POSIX.1-2001leaves the behavior ofgetcwd()unspecified ifbufisNULL. unspecified bestie, do with that what you will. ๐ฌPOSIX.1-2001does not define any errors forgetwd().
๐ 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 inPOSIX.1-2008. usegetcwd()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
- Copyright 1993, Thomas Koenig <ig25@rz.uni-karlsruhe.de>
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms