在linux / unix下有没有相当于WinAPI的MAX_PATH?
如果我想分配一个字符数组(C),保证足够大,以保存任何有效的绝对path+文件名,它需要多大。
在Win32上,有MAX_PATH定义。 什么是Unix / Linux的等价物?
有一个PATH_MAX
,但有点问题。 从realpath(3)手册页的bug部分:
这个函数的POSIX.1-2001标准版本在devise上被破坏了,因为不可能为输出缓冲区resolve_path确定合适的大小。 根据POSIX.1-2001,一个大小为PATH_MAX的缓冲区就足够了,但是PATH_MAX不一定是一个定义的常量,可能必须使用pathconf(3)来获得。 并且询问pathconf(3)并没有真正的帮助,因为一方面POSIX警告pathconf(3)的结果可能是巨大的,不适用于mallocing内存,另一方面pathconf(3)可能返回-1表示PATH_MAX不受限制 。
到目前为止的其他答案似乎都是关于事物的nix方面,但我会在Windows上添加警告。
你被文件骗了(遗漏)。
MAX_PATH
确实是定义的,甚至可能适用于存储在FAT或FAT32上的文件。 但是,任何path名都可以用\\?\
作为前缀,告诉Windows API忽略MAX_PATH
并让文件系统驱动程序自己决定。 之后,定义变得模糊。
另外,path名实际上是Unicode(以及UTS-16),而当使用“ANSI”API时,与内部Unicode名称的转换取决于一系列因素,包括当前代码页,你有一个混乱的秘诀。
对于Windows的规则的一个很好的描述是在MSDN 。 规则比我在这里总结的要复杂得多。
编辑:我改变\\.\
到\\?\
在上面感谢来自KitsuneYMG的评论。
Windowspath和名称空间很复杂。 有些人甚至可能认为他们太复杂了。 复杂性的一个来源是Win32(现在是Win64)API是一个位于Windows NT本机系统之上的子系统。
没有任何前缀的path在最广泛的Windows平台上是兼容的。 如果限制为7位ASCII字符,那么从2.0版本开始,它就兼容16位DOS(每当引入子目录时,实际上可能在DOS 3中;但是DOS 1.0只有根目录和\
性格没有特别的意义)。
\\?\
前缀会导致path名称的平衡被逐字传递到相应的文件系统驱动程序,这会产生将限制删除到MAX_PATH
字符的效果。 如果长path名称也位于networking共享上,则可以使用扩展的UNC名称,前缀为\\?\UNC\server\share\
而不是普通的UNC名称\\server\share\
。 使用此前缀限制了可移植性到Win32和更高版本的Windows平台,但除非您需要在传统硬件上支持16位Windows,否则这不是一个大问题。
\\.\
前缀是一个不同的动物。 它允许访问超出Windows自动映射的一组特定命名设备的设备对象作为特殊文件名到每个文件夹中。 这些特殊名称包括CON,PRN,AUX,NUL,COM1,COM2,COM3,COM4,COM5,COM6,COM7,COM8,COM9,LPT1,LPT2,LPT3,LPT4,LPT5,LPT6,LPT7,LPT8和LPT9。 请注意,所有这些名称都是特殊的,无论是否使用扩展名,或者是大小写混合。 但有可能你有10个或更多的COM端口安装。 如果使用USB调制解调器或USB串行端口适配器,则会发生这种情况,因为每个唯一的基于USB的串行端口将被分配一个不同的COMn名称。 如果您需要访问第50个串行端口,则只能使用名称\\.\COM50
来执行此操作,因为COM50 不是像COM1 那样的特殊名称。
我上面引用的MSDN页面有正确的区别,我只是在我原来的答案中input了不正确的前缀。
那么,至less在Linux上,有:
-
PATH_MAX
(在limits.h
定义) -
FILENAME_MAX
(在stdio.h
定义)
在我的系统(x86 Linux)上,这两个都设置为4096
。
更新:: 从这个glibc手册的一些信息
下面的每一个macros都是在limits.h中定义的,只有当系统对参数有一个固定的,统一的限制。 如果系统允许不同的文件系统或文件有不同的限制,那么macros是不确定的; 使用pathconf或fpathconf来找出适用于特定文件的限制
FILENAME_MAX是ISO C标准的一部分,适用于UNIX和Windows。 但是,GNU C库文档包含以下警告:
“与PATH_MAX不同的是,即使没有实际限制,也定义了这个macros,在这种情况下,它的值通常是一个非常大的数字,在GNU系统上总是这样。
用法注意:不要使用FILENAME_MAX作为存储文件名的数组的大小! 你不可能制作一个很大的数组! 使用dynamic分配。“
可以使用pathconf()
在运行时找出问题,但在<limits.h>
也有一个PATH_MAX预处理器定义。
你可以使用realpath
函数来为一个特定的path分配一个足够大的缓冲区。 如果你传递一个空指针作为第二个参数,它将为该path分配一个足够大的缓冲区。 手册页可能比我能解释得更好:
realpath()展开所有符号链接,并parsing对由path指定的以null结尾的string中的/./,/../和额外的“/”字符的引用,以生成规范化的绝对path名。 生成的path名存储为由resolved_path指向的缓冲区中以空字符结尾的string,最大为PATH_MAX字节。 得到的path将没有符号链接,/./或/../组件。
如果resolved_path指定为NULL,则realpath()将使用malloc(3)分配高达PATH_MAX字节的缓冲区以保存已parsing的path名,并返回指向此缓冲区的指针。 调用者应该使用free(3)释放这个缓冲区。