web-dev-qa-db-fra.com

Existe-t-il un équivalent du MAX_PATH de WinAPI sous linux/unix?

Si je veux allouer un tableau de caractères (en C) dont la taille est garantie suffisante pour contenir tout chemin absolu valide + nom de fichier, quelle doit être sa taille. 

Sur Win32, il y a le MAX_PATH définir. Quel est l'équivalent pour Unix/Linux?

55
AndrewR

Il y a un PATH_MAX, mais c'est un peu problématique. À partir de la section bugs de la page realpath (3) man:

La version standard POSIX.1-2001 de cette fonction est interrompue par conception, car il est impossible de déterminer une taille appropriée pour le tampon de sortie, chemin_solu. Selon POSIX.1-2001, un tampon de taille PATH_MAX suffit, mais PATH_MAX n'a pas besoin d'être défini constante et peut être obtenue avec pathconf (3) . Et demander pathconf (3) n'aide pas vraiment, car, d'une part POSIX avertit que le résultat de pathconf (3) peut être énorme et ne convient pas à la mémoire de mallocage, et d'autre part pathconf (3) peut renvoyer -1 pour indiquer que PATH_MAX n'est pas délimité.

48
stefanB

Les autres réponses à ce jour semblent toutes aller de soi sur le côté * nix, mais je vais ajouter un avertissement à ce sujet sous Windows.

La documentation vous a menti (par omission). 

MAX_PATH est en effet défini et s'applique probablement même aux fichiers stockés sur FAT ou FAT32. Cependant, tout nom de chemin peut être préfixé par \\?\ pour indiquer à l'API Windows d'ignorer MAX_PATH et de laisser le pilote du système de fichiers se faire sa propre idée. Après cela, les définitions deviennent floues.

Ajoutez à cela le fait que les noms de chemin sont en réalité Unicode (ainsi, UTS-16) et que, lorsque l'API "ANSI" est utilisée, la conversion vers et à partir du nom Unicode interne dépend de nombreux facteurs, notamment de la page de code actuelle. et vous avez une recette pour la confusion.

Une bonne description des règles pour Windows est à MSDN . Les règles sont beaucoup plus compliquées que ce que j'ai résumé ici.

Edit: J'ai changé \\.\ en \\?\ ci-dessus grâce au commentaire de KitsuneYMG.

Les chemins et les espaces de noms Windows sont compliqués. Certains pourraient même dire qu'ils sont trop compliqués. L'une des sources de complexité est que l'API Win32 (et maintenant Win64) est un sous-système reposant sur le système natif Windows NT. 

Un chemin sans préfixe est compatible sur la plus large gamme de plates-formes Windows. S'il est limité à des caractères ASCII 7 bits, il est alors compatible avec le DOS 16 bits à partir de la version 2.0 (à chaque fois que des sous-répertoires ont été introduits, ce qui aurait pu être en fait un DOS 3; mais DOS 1.0 n'avait que la racine les répertoires et le caractère \ n’ont pas de signification particulière).

Le préfixe \\?\ fait en sorte que le solde du nom du chemin d'accès soit transmis textuellement au pilote de système de fichiers approprié, ce qui a pour effet de supprimer la restriction en MAX_PATH caractères. Si le nom de chemin d'accès long se trouve également sur un partage réseau, vous pouvez utiliser un nom UNC étendu avec le préfixe \\?\UNC\server\share\ au lieu du nom UNC normal \\server\share\. L'utilisation de ce préfixe limite la portabilité aux plates-formes Win32 et ultérieures Windows, mais à moins que vous n'ayez besoin de la prise en charge de Windows 16 bits sur du matériel hérité, ce n'est pas un gros problème.

Le préfixe \\.\ est un animal différent. Il permet l'accès aux objets de périphérique au-delà de l'ensemble de périphériques spécialement nommés, automatiquement mappés par Windows en tant que noms de fichiers spéciaux dans chaque dossier de fichiers. Ces noms spéciaux incluent CON, PRN, AUX, NUL, COM1, COM2, COM4, ​​COM5, COM6, COM7, COM7, COM8, COM9, LPT1, LPT2, LPT4, LPT5, LPT6, LPT7, LPT8 et LPT9. Notez que tous ces noms sont spéciaux, qu’une extension soit utilisée ou non, qu’il s’agisse d’une combinaison de majuscules ou de minuscules. Mais il est possible que vous ayez 10 ports COM ou plus installés. Cela se produit rapidement si vous jouez avec des modems USB ou des adaptateurs de port série USB, car chaque port série unique basé sur USB se voit attribuer un nom COMn distinct. Si vous devez accéder au 50ème port série, vous ne pouvez le faire qu'avec le nom \\.\COM50 car COM50 est non un nom spécial comme COM1.

La page MSDN que j'ai citée ci-dessus avait la distinction juste, j'ai simplement tapé le préfixe incorrect dans ma réponse d'origine.

42
RBerteig

Au moins sur Linux, il y a:

  • PATH_MAX (défini dans limits.h)

  • FILENAME_MAX (défini dans stdio.h)

les deux sont définis sur 4096 sur mon système (Linux x86).

Mise à jour:: Quelques informations du manuel de la glibc à ce sujet

Chacune des macros suivantes est définie dans limits.h uniquement si le système a une limite fixe et uniforme pour le paramètre en question. Si le système autorise différentes limites pour des systèmes de fichiers ou des fichiers différents, la macro n'est pas définie; utilisez pathconf ou fpathconf pour connaître la limite applicable à un fichier particulier

18
AndrewR

FILENAME_MAX fait partie de la norme ISO C, il fonctionne sous UNIX et Windows. Cependant, la documentation de la bibliothèque GNU C contient les avertissements suivants:

"Contrairement à PATH_MAX, cette macro est définie même si aucune limite réelle n'est imposée. Dans ce cas, sa valeur est généralement un très grand nombre. C'est toujours le cas sur le système GNU. 

Remarque sur l'utilisation: N'utilisez pas FILENAME_MAX comme taille d'un tableau dans lequel stocker un nom de fichier! Vous ne pouvez pas faire un tableau si gros! Utiliser l'allocation dynamique. "

6
cdarke

Vous pouvez utiliser pathconf() pour déterminer au moment de l'exécution, mais il existe également un préprocesseur PATH_MAX défini dans <limits.h>.

5
unwind

Vous pouvez utiliser la fonction realpath pour allouer un tampon suffisamment grand pour un chemin spécifique. Si vous lui transmettez un pointeur nul en tant que deuxième argument, il allouera un tampon suffisamment grand pour le chemin. La page de manuel explique probablement mieux que moi:

realpath () développe tous les liens symboliques et résout les références aux caractères /./, /../ et aux caractères '/' supplémentaires dans la chaîne terminée par le caractère null, nommée par path, afin de produire un chemin absolu canonique. Le chemin résultant est stocké en tant que chaîne terminée par un caractère NULL, avec un maximum d'octets PATH_MAX, dans la mémoire tampon pointée par resol_path. Le chemin résultant n'aura pas de lien symbolique, /./ ou /../.

Si chemin_solu est spécifié avec la valeur NULL, realpath () utilise malloc (3) pour allouer un tampon d'au plus PATH_MAX octets pour contenir le chemin d'accès résolu et renvoie un pointeur sur ce tampon. L'appelant doit libérer ce tampon en utilisant free (3). 

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

2
user1091954

limites.h

/*
 * File system limits
 *
 * NOTE: Apparently the actual size of PATH_MAX is 260, but a space is
 *       required for the NUL. TODO: Test?
 * NOTE: PATH_MAX is the POSIX equivalent for Microsoft's MAX_PATH; the two
 *       are semantically identical, with a limit of 259 characters for the
 *       path name, plus one for a terminating NUL, for a total of 260.
 */
#define PATH_MAX    260

minwindef.h

#define MAX_PATH 260
0
Puddle