145

Which header file should I invoke with #include to be able to use PATH_MAX as an int for sizing a string?

I want to be able to declare:

char *current_path[PATH_MAX];

But when I do so my compiler (Clang/LLVM on Linux) issues the following error:

recursive_find6.c:29:20: error: use of undeclared identifier 'PATH_MAX'
char *current_path[PATH_MAX];
                   ^

I tried doing a google search but still no luck.

#include <limits.h> Does NOT fix the problem/error.

Am I also correct that the value of PATH_MAX is an int?

haziz
  • 12,994
  • 16
  • 54
  • 75
  • 3
    Please see this question: http://stackoverflow.com/questions/833291/is-there-an-equivalent-to-winapis-max-path-under-linux-unix – Josh Brown Feb 25 '12 at 23:56
  • 24
    You probably want `char current_path[PATH_MAX];` instead of `char *current_path[PATH_MAX];` - you want a string rather than an array of pointers. – John Carter Feb 25 '12 at 23:57
  • or this one http://stackoverflow.com/questions/4267390/path-max-not-declared-when-compiling-on-ubuntu-10-04 – qdii Feb 25 '12 at 23:59

5 Answers5

175

Its in linux/limits.h.
#define PATH_MAX 4096 /* # chars in a path name including nul */

#include <linux/limits.h>

char current_path[PATH_MAX];

PATH_MAX has some flaws as mentioned in this blog (thanks paulsm4)

Shiplu Mokaddim
  • 56,364
  • 17
  • 141
  • 187
  • 31
    Here's a good link about PATH_MAX ... and why it simply *isn't*: http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html – paulsm4 Feb 26 '12 at 00:13
  • 1
    Wait ... does this mean that PATH_MAX is linux-specific and not part of any standard? – Edward Falk Jun 15 '16 at 16:45
  • 8
    You should probably use ; looks distinctly non-portable. – Edward Falk Jun 15 '16 at 16:51
  • 5
    Beware: PATH_MAX is different from NAME_MAX (and the x-ref'd article in part seems to confuse these two, at least in part). Note: POSIX [``](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html) says: _A definition of one of the symbolic constants in the following list shall be omitted from the `` header […] where the corresponding value is equal to or greater than the stated minimum, but where the value can vary depending on the file to which it is applied. The actual value supported for a specific pathname shall be provided by the pathconf() function._ – Jonathan Leffler Aug 09 '16 at 04:07
  • It also defines: `{NAME_MAX}` • Maximum number of bytes in a filename (not including the terminating null of a filename string). • Minimum Acceptable Value: {_POSIX_NAME_MAX} • Minimum Acceptable Value: {_XOPEN_NAME_MAX} and `{PATH_MAX}` • Maximum number of bytes the implementation will store as a pathname in a user-supplied buffer of unspecified size, including the terminating null character. Minimum number the implementation will accept as the maximum number of bytes in a pathname. • Minimum Acceptable Value: {_POSIX_PATH_MAX} • Minimum Acceptable Value: {_XOPEN_PATH_MAX} – Jonathan Leffler Aug 09 '16 at 04:09
  • 2
    Pathnames are very evil, insecure and path_max is a lie and not even a constant (it might be different on different OS functions). It's a terrible feature and should be replaced ASAP. – Lothar Dec 22 '17 at 19:21
  • 1
    @Lothar What do you suggest we use instead? Path *numbers*? GPS coordinates? – Melab Feb 20 '21 at 20:19
  • @Melab: Very easy to answer. You use dynamic allocated string buffers everywhere and resize them when the API returns a string truncated error. And by the way, on Unix you never use current_path but your own at functions like "openat" with a file descriptor, but explaining why this is even more important than having a global current directory. – Lothar Feb 21 '21 at 11:17
  • @Lothar: You could. But first you would need an application for filenames that are longer than 4k. The only use I've ever seen it put to is a way to hide directories containing porn on an ancient NT 1.1 server I was administering, that got hacked back in the dawn of the Internet. A 4k filename is a pretty user-unfriendly thing. – Robin Davies Aug 30 '21 at 05:36
  • The linked blog post has received 3,266 comments so far and 4 of them were made before this SO answer. – Shiplu Mokaddim Aug 30 '21 at 13:38
19

Be aware, that it is still unclear if PATH_MAX defines a maximum length with or without a trailing nul byte. It may be one or the other on different operating systems. If you can't or don't want to check which case it is during compilation, it's safer to force artificial limit of PATH_MAX - 1. Better safe than sorry. (Obviously, you still need to reserve at least PATH_MAX bytes of memory to buffer the string.)

Mikko Rantalainen
  • 14,132
  • 10
  • 74
  • 112
Kumashiro
  • 199
  • 1
  • 2
  • 5
    > `{PATH_MAX}` Maximum number of bytes in a pathname, including the terminating null character. From POSIX '01. – muh karma Mar 20 '14 at 16:51
  • 11
    Note that POSIX 2008 resolved the confusion — [``](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html) (Rationale): {PATH_MAX} IEEE PASC Interpretation 1003.1 #15 addressed the inconsistency in the standard with the definition of pathname and the description of {PATH_MAX}, allowing application developers to allocate either {PATH_MAX} or {PATH_MAX}+1 bytes. The inconsistency has been removed by correction to the {PATH_MAX} definition to include the null character. With this change, applications that previously allocated {PATH_MAX} bytes will continue to succeed. – Jonathan Leffler Aug 09 '16 at 04:09
  • 3
    Note also that you should not use `PATH_MAX - 1`, but `PATH_MAX + 1`. You do not have to anymore, but you want to add one byte for the `'\0'`. – Alexis Wilke Sep 13 '16 at 23:27
13

The portable way to do it is:

#define _POSIX_C_SOURCE 1
#include <limits.h>

Spec: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html

emersion
  • 393
  • 4
  • 10
  • 1
    And even that's not enough. `PATH_MAX` does not have to be defined: "A definition of one of the symbolic constants in the following list **shall be omitted** from the `` header on specific implementations where the corresponding value is equal to or greater than the stated minimum, but where the value can vary depending on the file to which it is applied. The actual value supported for a specific pathname shall be provided by the `pathconf()` function." Given Linux filesystems support different values, it's probably a violation of the POSIX standard for Linux to define `PATH_MAX`. – Andrew Henle Feb 04 '20 at 13:55
  • What does defining `_POSIX_C_SOURCE` do? I was told that one should **never** define a variable beginning with a `_` in one's program. – vy32 May 07 '21 at 11:34
  • @vy32 `_POSIX_C_SOURCE` is a *feature test macro*. – Flux Dec 02 '21 at 13:22
  • @flux - Okay... so I should not define it? – vy32 Dec 02 '21 at 18:56
  • @vy32 It depends on what you want to do. Please read up on feature test macros. – Flux Dec 03 '21 at 10:08
5

When doing simple C programming, I encountered the same challenge. On your particular Linux system, /usr/include directory contain many , here header files specific to a Linux OS.

find . -name "*.h" | xargs grep PATH_MAX 

You should see several headers defining PATH_MAX; unfortunately this value was defined differently in different headers. Here is a listing from my Ubuntu (I also manually removed some false positive hits from the grep program).

./x86_64-linux-gnu/bits/posix1_lim.h:#define _POSIX_PATH_MAX      256
./X11/InitialI.h:#ifndef PATH_MAX
./X11/InitialI.h:#define PATH_MAX 512
./X11/InitialI.h:#ifndef PATH_MAX
./X11/InitialI.h:#define PATH_MAX MAXPATHLEN
./X11/InitialI.h:#define PATH_MAX 1024
./X11/Xos.h:#  define PATH_MAX 4096
./X11/Xwindows.h:#if defined(WIN32) && (!defined(PATH_MAX) || PATH_MAX < 1024)
./X11/Xwindows.h:# undef PATH_MAX
./X11/Xwindows.h:# define PATH_MAX 1024
./X11/Xosdefs.h:#  ifndef PATH_MAX
./X11/Xosdefs.h:#   define PATH_MAX 4096
./X11/Xosdefs.h:#  ifndef PATH_MAX
./X11/Xosdefs.h:#   define PATH_MAX 1024
./X11/extensions/XKBsrv.h:#define   PATH_MAX MAXPATHLEN
./X11/extensions/XKBsrv.h:#define   PATH_MAX 1024
./python2.7/osdefs.h:#ifndef PATH_MAX
./python2.7/osdefs.h:#define PATH_MAX MAXPATHLEN
./python2.7/osdefs.h:#if defined(PATH_MAX) && PATH_MAX > 1024
./python2.7/osdefs.h:#define MAXPATHLEN PATH_MAX
./linux/limits.h:#define PATH_MAX        4096   /* # chars in a path name including nul */
./linux/btrfs.h:#define BTRFS_INO_LOOKUP_PATH_MAX 4080
./linux/un.h:#define UNIX_PATH_MAX  108

The header /linux/limits.h had the largest number and should be the most authentic one to include. Alternative strategy is to define your own with a different name, say PATHLEN (4080 is long enough for most practical situations). My main point is to learn to use find to look for answers to your question.

Kemin Zhou
  • 6,264
  • 2
  • 48
  • 56
3

PATH_MAX is a system limit. There are three categories about system limits exists in POSIX environment. One of these categories is Pathname Variable Values. System limits which are depend on the file system falls into this category. PATHMAX is also pathname variable value. (so this value can change from file system to file system.) So, PATHNAME limit can be obtained with pathconf()/fpathconf() POSIX functions. This way is portable way of getting PATHNAME limit of spesific file system. Example code is like below:

long
get_pathmax(void)
{
  long pathmax = -1;

  errno = 0;
  pathmax = pathconf("/", _PC_PATH_MAX);
  if (-1 == pathmax)
  {
    if (0 == errno)
    {
#define PATHMAX_INFINITE_GUESS 4096
      pathmax = PATHMAX_INFINITE_GUESS;
    }
    else
    {
      fprintf (stderr, "pathconf() FAILED, %d, %s\n", errno, strerror(errno));
    }
  }

  return pathmax;
}
user3104363
  • 182
  • 1
  • 14
  • Interesting to see what pathconf("\\\\?\\c$",_PC_PATH_MAX) returns on windows. (Filenames starting with "\\?\" in Windows can be up to 32k long. Never a popular feature, for obvious reasons, and also completely unusable for Windows UNC filenames). – Robin Davies Aug 30 '21 at 05:45