2009-05-07 20 views
53

Si quiero asignar una matriz char (en C) que garantice que sea lo suficientemente grande como para contener cualquier ruta de acceso absoluta válida + nombre de archivo, qué tan grande debe ser.¿Hay un equivalente a MAX_PATH de WinAPI en Linux/Unix?

En Win32, existe la definición MAX_PATH. ¿Cuál es el equivalente para Unix/Linux?

Respuesta

47

Hay un PATH_MAX, pero es un poco problemático. Desde la sección de errores de la página realpath(3) hombre:

El POSIX.1-2001 versión estándar de esta función se rompe por diseño, ya que es imposible determinar un tamaño adecuado para el búfer de salida , resolved_path. Según POSIX.1-2001 un tampón de tamaño PATH_MAX basta, pero PATH_MAX no tiene por qué ser un definido constante, y puede tener que ser obtenido utilizando pathconf(3). Y pidiendo pathconf(3) realmente no ayuda, ya que, por un lado, POSIX advierte que el resultado de pathconf(3) puede ser enorme y inadecuado para mallocing memoria, y por otro lado pathconf(3) puede devolver -1 para indicar que PATH_MAX no es limitado.

16

Bueno, en Linux, al menos, hay:

  • PATH_MAX (definido en limits.h)

  • FILENAME_MAX (definido en stdio.h)

ambos están situados a 4096 en mi sistema (x86 Linux).

Actualización:: Some info from the glibc manual on this

Cada una de las siguientes macros se define en limits.h sólo si el sistema tiene un límite fijo, uniforme para el parámetro en cuestión. Si el sistema permite que los diferentes sistemas de archivos o archivos tengan límites diferentes, entonces la macro no está definida; utilizar pathconf o fpathconf para averiguar el límite que se aplica a un archivo en particular

+0

que parece una portabilidad no-no. – Tom

+2

Supongo que el máximo podría variar según el tipo de sistema de archivos que esté utilizando, lo que implicaría una verificación de tiempo de ejecución, no una constante en tiempo de compilación. – AndrewR

5

Puede utilizar pathconf() de averiguar en tiempo de ejecución, pero también hay un preprocesador PATH_MAX definen en <limits.h>.

39

Las otras respuestas hasta ahora parecen estar a punto sobre el lado * nix de las cosas, pero añadiré una advertencia al respecto en Windows.

La documentación le ha mentido (por omisión).

MAX_PATH está definido de hecho, y probablemente incluso se aplica a archivos almacenados en FAT o FAT32. Sin embargo, cualquier nombre de ruta puede tener el prefijo \\?\ para indicarle a la API de Windows que ignore MAX_PATH y deje que el controlador del sistema de archivos tome una decisión. Después de eso, las definiciones se vuelven borrosas.

Agregue a la mezcla el hecho de que los nombres de las rutas son realmente Unicode (bueno, UTS-16) y que cuando se utiliza la API "ANSI" la conversión ay desde el nombre Unicode interno depende de un montón de factores que incluyen la página de códigos actual, y tienes una receta para la confusión.

Una buena descripción de las reglas para Windows está en MSDN. Las reglas son mucho más complicadas de lo que he resumido aquí.

Editar: me cambió \\.\-\\?\ en los anteriores gracias al comentario de KitsuneYMG.

Las rutas de Windows y los espacios de nombres son complicados. Algunos incluso podrían argumentar que son demasiado complicados. Una fuente de complejidad es que la API Win32 (y ahora Win64) es un subsistema que se ubica sobre el sistema nativo de Windows NT.

Una ruta sin ningún prefijo es compatible en la más amplia gama de plataformas de Windows. Si está restringido a caracteres ASCII de 7 bits, entonces es compatible con DOS de 16 bits desde la versión 2.0 (cuando se introdujeron subdirectorios, que en realidad podrían haber estado en DOS 3, pero DOS 1.0 solo tenía directorios raíz y el \ el personaje no tenía un significado especial).

El prefijo \\?\ hace que el balance del nombre de ruta se transmita textualmente al controlador del sistema de archivos apropiado, que es el que produce el efecto de eliminar la restricción a MAX_PATH caracteres. Si el nombre de ruta larga también está en un recurso compartido de red, puede usar un nombre UNC extendido para él con el prefijo \\?\UNC\server\share\ en lugar del nombre UNC normal \\server\share\. El uso de este prefijo restringe la portabilidad a las plataformas Win32 y posteriores de Windows, pero a menos que necesite soporte para Windows de 16 bits en hardware heredado, eso no es un gran problema.

El prefijo \\.\ es un animal diferente. Permite el acceso a los objetos del dispositivo más allá del conjunto de dispositivos con nombre especial que son asignados automáticamente por Windows como nombres de archivo especiales en cada carpeta de archivos. Esos nombres especiales incluyen CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, ​​COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8 y LPT9. Tenga en cuenta que todos esos nombres son especiales ya sea que se use o no una extensión, o en cualquier combinación de mayúsculas o minúsculas. Pero es posible que tenga 10 o más puertos COM instalados. Esto sucede rápidamente si juega con módems USB o adaptadores de puerto serie USB, ya que a cada puerto serie único basado en USB se le asignará un nombre COMn distinto. Si necesita acceder al puerto serial número 50, entonces solo puede hacerlo con el nombre \\.\COM50 porque COM50 es no un nombre especial como COM1.

La página de MSDN que mencioné anteriormente tenía la distinción correcta, simplemente escribí el prefijo incorrecto en mi respuesta original.

+1

Bastante seguro que te refieres a '\\? \' – KitsuneYMG

+0

@KitsuneYMG, a la derecha. Cité el prefijo equivocado. Está fijo ahora, junto con una digresión sobre cuál es la distinción. – RBerteig

+0

\\. \ No es el prefijo para las canalizaciones con nombre? –

6

FILENAME_MAX es parte del estándar ISO C, funciona en UNIX y Windows. Sin embargo, la documentación de la biblioteca GNU C contiene las siguientes advertencias:

"A diferencia de PATH_MAX, esta macro se define incluso si no se impone un límite real. En tal caso, su valor suele ser un número muy grande. el caso en el sistema GNU

Nota de uso: ¡No use FILENAME_MAX como el tamaño de una matriz en la que almacenar un nombre de archivo! ¡No puede hacer una matriz tan grande! Utilice la asignación dinámica. "

2

Puede usar la función realpath para asignar un búfer lo suficientemente grande para una ruta específica.Si le pasa un puntero nulo como segundo argumento, asignará un búfer lo suficientemente grande para la ruta. La página del manual explica, probablemente, mejor que puedo:

realpath() se expande todos los enlaces simbólicos y resuelve referencias a /./, /../ y caracteres '/' extra en la cadena terminada en cero nombrado por ruta para producir un nombre de ruta absoluto canonicalizado. El nombre de ruta resultante se almacena como una cadena terminada en nulo, hasta un máximo de bytes PATH_MAX, en el búfer al que apunta resolve_path. La ruta resultante no tendrá ningún enlace simbólico, /./ o /../ componentes.

Si ruta_resuelta se especifica como NULL, entonces realpath() utiliza malloc (3) para asignar un búfer de hasta PATH_MAX bytes para mantener la ruta de acceso resuelta, y devuelve un puntero a este búfer. La persona que llama debería desasignar este búfer usando free (3).

http://linux.die.net/man/3/realpath

Cuestiones relacionadas