I just got burned by the 260 character path limitation in Windows. Why did Microsoft decided to limit paths to 3 characters for drive + 256 characters + 1 character for the terminator? Mac OS of the same vintage has a 31 character filename limit but no path limit since the FSSpec stored volume number, refnum, and 31 character filename (Pascal string as length byte + 31 characters). HFS running on 512k of RAM could support long paths, but Windows 3.1 and 95 cannot. Newer versions of Windows can under some limited circumstances break the 260 character path limit, but they are limited by compatibility to Win32 headers.
-
8Probably because they used fixed sized buffers to store things like the current working directory and 256 is a nice round number in binary.– user722Dec 10, 2018 at 18:03
-
5Maximum path size actually supported by NTFS is much bigger (32,000 characters according to the first answer of this question.) 260 character limit is imposed by Windows API any can be easily by-passed with 3rd party software like Total Commander.– wizofworDec 11, 2018 at 8:41
-
1The 32K limit only works with Unicode. For non-Unicode, the limit is 260.– cupDec 11, 2018 at 13:00
-
5The 32K limit is available in Unicode only, because Windows (NT-based, not Windows 95-based) is a Unicode (ok, UCS-2) Operating System, with an ANSI (ok, ASCII plus various 8-bits extensions like CP and MBCS) backward-compatibility layer for functionality that existed in Windows 95-based OSes. Long Paths are a Windows NT-only feature, and so to use it you need to step out of the 8-bit character set compatibility layer.– Euro MicelliDec 11, 2018 at 17:41
-
2Amazingly enough, the DOS LFN API (first exposed by Windows 95) theoretically supports paths longer than 260 characters...– Stephen KittDec 11, 2018 at 20:52
1 Answer
In the Windows world, the MAX_PATH
260-character limit dates back to the introduction of the Win32 APIs; it is for example documented in GetWindowsDirectory
. Before that, Windows (at least in version 3) documented a 144-character limit; see for example GetSystemDirectory
.
As far as why the path limit is 260 characters, the general answer you’ll find on the Internet is backwards compatibility. OK, that’s often the case in computing in general, and on Windows in particular (which is why many 30-year-old Windows programs can still be made to run on modern Windows, at least on 32-bit systems). The question then becomes, backwards compatibility with what?
The obvious answer would be DOS, and perhaps Win16. But DOS has a maximal path limit of 66 characters, constrained by its CDS (current directory structure) which has room for a 67-byte nul-terminated string to store each drive’s path (including drive letter, if appropriate). DOS-based versions of Windows couldn’t change this, since they had to maintain compatibility with DOS programs — imagine being able to store a file in a deeply-nested directory, only to have it be inaccessible from DOS! So the DOS limit doesn’t explain the 256-character limit in Win32. (I’m ignoring network drives here.)
(Incidentally, you can achieve the latter effect by mounting a FAT drive under Linux: Linux allows much longer paths on FAT than DOS or Windows can handle, so you can create directories which are so deeply nested that DOS can’t handle them properly.)
Digging further reveals something interesting; old Windows headers define, in stdlib.h
,
#if defined(__OS2__) || defined(__WIN32__)
#define _MAX_PATH 260
#define _MAX_DRIVE 3
#define _MAX_DIR 256
#define _MAX_FNAME 256
#define _MAX_EXT 256
#else
#define _MAX_PATH 80
#define _MAX_DRIVE 3
#define _MAX_DIR 66
#define _MAX_FNAME 9
#define _MAX_EXT 5
#endif
The 80-byte MAX_PATH
makes sense for DOS and Win16, based on the CDS above: that’s just enough room for a 66-byte path, \
, 12-byte filename (11 bytes stored on disk and .
separator), and a nul terminator.
The interesting part is the other definition: the famous 260-byte limit... defined for Win32, and for OS/2! Reading through the OS/2 APIs doesn’t help much, because they’re all designed to not have documented limits (programs are supposed to call DosQuerySysInfo
with QSV_MAX_PATH_LENGTH
to find the maximum path length), as are in fact most of the Windows APIs (e.g. GetCurrentDirectory
which takes a buffer and allocated length, and indicates the required length if the buffer isn’t big enough). But Inside OS/2, in its description of the file system name space, says
All OS/2 filename and pathname interfaces, such as DosOpen, DosFindNext, and so on, are designed to take name strings of arbitrary length. Applications should use name buffers of at least 256 characters to ensure that a long name is not truncated.
So I get the impression that the 256-character limit is part of OS/2’s legacy, and that when it was chosen, 256 characters was considered sufficient for “name strings of arbitrary length”.
-
What I'd read for rationale early in the life of NT was that, though there was a pathname limit of 64K-1 bytes in the OS itself, it was deemed a requirement that application programmers could continue to allocate fixed-size string buffers, i.e., MAX_PATH needed to exist with some value. The specific value is just "seems reasonable". But that's NT when it became "Windows NT". I don't know whether the same limit applied while it was still "NT OS/2". Dec 12, 2018 at 13:08
-
1Stephen, do you know why the heck it is possible to create a 252-character long file in C:\aaa\ (so the width of the full path will be 259 chars), but only a 255-character long file in C:\ (so the width of the full path will be 258 chars)? superuser.com/questions/1620259/… Jan 25, 2021 at 1:59
-
1Interestingly, DRDOS (up to DRDOS 6) used a different internal data structure for directories, with no limit on path length; it maintained a read-only copy of the CDS for compatibility's sake. It was eventually forced to switch to using the CDS 'for real' to improve compatibility with Windows 3.x; this change was released as an update disk for 6.0, and distributed as standard with 7.0 and later.– john_eMar 18, 2022 at 11:14
-
1@virolino thanks for the interesting question! “buffers of at least 256 characters to ensure that a long name is not truncated” — that means that if you provide a buffer of 256 characters, long names won’t be truncated. Correct OS/2 code isn’t supposed to use
_MAX_PATH
anyway, it’s supposed to callDosQuerySysInfo
;_MAX_PATH
is a compromise. Win32 came after OS/2, so OS/2 can’t be the effect... Mar 7 at 13:02 -
2@virolino put another way, if the maximum path length is x, then a buffer of size x is sufficient, but larger buffers can also be used. Again, on OS/2 this is all a compromise and probably there to allow developers used to writing
char buf[_MAX_PATH]
to continue doing so; the OS/2 SDK was clear on the fact that programs were supposed to query the value at runtime. Win32 first appeared with Windows NT, and finding similarities at least in APIs between that and OS/2 isn’t surprising given NT’s development history. Mar 8 at 13:30