Windows has a similarly disastrous situation where most tools and APIs follow MAX_PATH - which is defined to be 260 chars. But that doesn't affect the actual filesystem or syscall interface, just common APIs and tools. This makes it impossible to delete files from windows explorer for example.<p>If you want to fix this you basically have to bypass it by using "\\?\" on the front of the full path. The situation gets messy when you're trying to write an installer with node packages especially.<p><a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath" rel="nofollow">https://msdn.microsoft.com/en-us/library/windows/desktop/aa3...</a>
> The problem is that you can’t meaningfully define a constant like this in a header file. The maximum path size is actually to be something like a filesystem limitation, or at the very least a kernel parameter.<p>AFAIK, "paths" aren't a thing filesystems think about. As far as a filesystem driver is concerned, paths are either—for open/read/write/etc.—plain inodes (a uint64), or—for directory-manipulation calls—an inode plus a ptrdiff_t to index into the dirent list†. The only things that care about NAME_MAX are lookup(2) [get inode given {inode, dirent}], and link(2) [put inode in {inode, dirent}].<p>So it's really only the kernel, through its syscall interface, that cares about paths—and so PATH_MAX is just a representation of the maximum size of a path the kernel is willing to accept in those syscalls. As if they each had a statically-allocated path[PATH_MAX] buffer your path got copied into.<p>† Writing a FUSE filesystem is a great way to learn about what the kernel thinks a filesystem is. It's very different from the userland perspective. For example, from a filesystem driver's perspective, "file descriptors" don't exist! Instead, read(2) and write(2) calls are stateless, each call getting passed a kernel-side io-handle struct that must get re-evaluated for matching permissions on each IO operation. (You can do <i>some</i> up-front evaluation during the open(2) call, but, given that a file's permissions might <i>change</i> while you have a descriptor open to it, there's not much point.)
All the UNIX/Linux/POSIX functions which take output "char *" params without a length should have been moved to deprecated header files a long time ago. Like 1990 or so. It's not too late.
The GNU Hurd approach to PATH_MAX is to set it to something ridiculous like SIZE_MAX, something that cannot possible be allocated, to illustrate to programmers that it is a fiction.<p>I don't think that's necessarily the best approach, but it matches reality more closely than typical Linux/BSD values (1024 or 4096).
This post got me curious, so I did a quick search on macOS 10.12. I found the values defined in "/System/Library/Frameworks/Kernel.framework/Headers/sys/syslimits.h". PATH_MAX is 1024, and NAME_MAX is 255.<p>There's also an amusing todo question that looks like it might've been there for at least close to 20 years now:<p><pre><code> #define OPEN_MAX 10240 /* max open files per process - todo, make a config option? */</code></pre>
The essence of the article: PATH_MAX applies to the syscall interface. It's not related to file systems. Paths aren't a file system thing, but simply a convenient means of addressing files. Basically they are URLs for local resources.<p>And that totally makes sense once you understand that files are basically "objects" (in the OO sense) identified by inodes instead of memory addresses. A file system implements the graph of these objects (linked by special file objects called <i>directories</i>). The fact that one can cross file system boundaries using file paths also indicates that file paths are none of a file system's business.
> <i>This constant</i> [PATH_MAX] <i>is defined by POSIX</i>…<p>Well, it’s <i>allowed</i> by POSIX. A POSIX compatible system doesn’t <i>have</i> to define it if it has no such inherent restriction on path lengths. Indeed, the GNU Hurd does not have such a restriction, and consequently does not define it. This leads to many porting adventures for those trying to compile a program on GNU Hurd, believing their source code to be correct for any POSIX-compliant system.
And to add to the confusion unix domain sockets have a maximal length of something between 92 a 108. That's an implementation detail of platform it's running on. This in particular has been biting me already.
I played around with glibc's getcwd() some time ago. With strace one can easily see how getcwd() works. If the current path is larger than PATH_MAX then the getcwd syscall fails. Then as I recall glibc uses '..'s recursively so it never has to call a syscall with a long relative path.<p>If there is a non-user-readable directory in the path then the fallback method fails but the getcwd syscall works if the path is short enough.<p>Bash also "cheats" by caching the working directory and updating it on 'cd' commands.
If I understand the conclusion of the article right, it's that we <i>should</i> actually just use PATH_MAX? In particular, he points to the glibc implementation of realpath as being very correct. But it (like the man page description of it says), appears to prefer to use the hard-coded value of PATH_MAX, unless that value is unavailable and it is forced to query for the kernel _PC_PATH_MAX value instead.<p>That's not what I would have expected. Did I miss something obvious?
That's tricky indeed. And doing things properly seems quite involved.<p>For now I'll keep my limits.h. At least until I get a real-world bug-reports telling me this is causing real-world issues :)