sur une machine Linux, je veux lire la chaîne cible d'un lien. De la documentation, j'ai trouvé l'échantillon de code suivant (sans traitement d'erreur): p> Le probelm est que sb.st_size renvoie 0 pour des liens sur mon système. P> Alors, comment allouez-en une mémoire de manière dynamique pour readline sur de tels systèmes? p> Merci beaucoup! P> pour référence future. Utilisation des points fabriqués par Jilles: P>
une solution possible: H2>
struct stat sb;
ssize_t r = INT_MAX;
int linkSize = 0;
const int growthRate = 255;
char * linkTarget = NULL;
// get length of the pathname the link points to
if (lstat("/proc/self/exe", &sb) == -1) { // could not lstat: insufficient permissions on directory?
perror("lstat");
return;
}
// read the link target into a string
linkSize = sb.st_size + 1 - growthRate;
while (r >= linkSize) { // i.e. symlink increased in size since lstat() or non-POSIX compliant filesystem
// allocate sufficient memory to hold the link
linkSize += growthRate;
free(linkTarget);
linkTarget = malloc(linkSize);
if (linkTarget == NULL) { // insufficient memory
fprintf(stderr, "setProcessName(): insufficient memory\n");
return;
}
// read the link target into variable linkTarget
r = readlink("/proc/self/exe", linkTarget, linkSize);
if (r < 0) { // readlink failed: link was deleted?
perror("lstat");
return;
}
}
linkTarget[r] = '\0'; // readlink does not null-terminate the string
6 Réponses :
Qu'est-ce que vous essayez exactement d'atteindre avec le LSTAT?
Vous devriez pouvoir obtenir la cible avec juste le suivant P> si vous essayez de Obtenez la longueur de la taille du nom du fichier, je ne pense pas que ST_SIZE est la bonne variable pour cela ... mais c'est peut-être une question différente. P> p>
Cela n'aide pas comme je cherche un moyen d'allouer de manière dynamique la taille requise. Vous limitez implicitement la longueur des chemins à 1024 caractères. Cela suffira dans la plupart des cas - mais il n'ya aucune garantie.
st_size ne donne pas la bonne réponse sur / proc. p>
à la place, vous pouvez Malloc path_max, ou pathconf (_pc_path_max) octets. Cela devrait suffire à la plupart des cas. Si vous voulez pouvoir gérer les chemins plus longtemps que cela, vous pouvez appeler la lecture de lecture dans une boucle et réaffecter votre tampon si la valeur de retour Readlink indique que le tampon est trop court. Notez que de nombreuses autres fonctions POSIX supposent simplement Path_max suffisent. P>
Malheureusement, path_max n'aide pas. Sur mon système, il est 4096 mais sur un système de fichiers ext3, rien ne vous empêche d'avoir des chemins plus longtemps que cela.
POSIX dit que le champ Vous pouvez attribuer un tampon d'une certaine taille, essayez Vous pouvez également utiliser st_size code> pour un lien symbolique doit être réglé sur la longueur du chemin du chemin dans la liaison (sans
'\ 0' code>). Cependant, le système de fichiers
/ proc code> sur Linux n'est pas conforme à POSIX. (Il a plus de violations que celle-ci, comme lors de la lecture de certains fichiers un octet à la fois.) P>
readlink () code> et réessayer avec un tampon plus grand si le tampon n'était pas assez grand (
readlink () code> retourné de nombreux octets comme adapté dans le tampon), jusqu'à ce que le tampon soit suffisamment grand. P>
path_max code> et casser la portabilité vers des systèmes où il n'est pas une constante de temps de compilation ou où le chemin peut être plus long que celui (POSIX permet non plus). P>
Merci pour le point sur le système de fichiers / proc. Je n'étais pas au courant. Donc, st_size "devrait" travailler n'importe où sauf dans / proc. Il semble que une approche itérative doit être utilisée comme solution de retombée pour le code universel.
@Arikraffaelfunke: Au mieux que le champ st_size code> est uniquement indicatif de toute façon, car le lien pourrait être modifié entre le
lstat () code> appel et le
readlink () code > appel. Vous devez donc être prêt à gérer la taille étant insuffisante de toute façon.
Je suis un peu perplexe quant à pourquoi Pour des liens symboliques, l'élément ST_MODE doit contenir des informations significatives lorsqu'il est utilisé avec les macros de type de fichier. Les bits de mode fichier dans ST_MODE sont indéterminés. Les membres de la structure ST_INO, ST_DEV, ST_UID, ST_GID, ST_ATIM, ST_GID, ST_ATIM, ST_CTIM et ST_MTIM doivent avoir des valeurs significatives et la valeur de l'élément ST_NLINK doit être définie sur le nombre de liens (durs) à la liaison symbolique. La valeur de l'élément ST_SIZE doit être réglée sur la longueur du chemin nominal contenu dans la liaison symbolique n'incluant aucun octet nul de terminaison. P>
blockQuote>
Source: http://pubs.opengroup.org/onlinepubs/9699919799/ Fonctions / lstat.html p>
si st_size code> est zéro. PAR POSIX: P>
st_size code> ne fonctionne pas, je pense que votre seule option est d'allouer de manière dynamique un tampon et de continuer à le redimensionner aussi longtemps que la valeur de retour de
readlink code> est égale à la taille de la mémoire tampon. P>
Même si st_size code> fonctionne, la destination de liaison pourrait être modifiée entre le
lstat () code> appel et le
readlink () code> appel.
En effet, auquel cas vous devrez détecter la troncature et réessayer.
the Manpage pour Readlink (2) code>
dit Trondez silencieusement si le tampon est trop petit. Si vous voulez vraiment être illimité (et ne vous dérangerez pas de payer des coûts pour un travail supplémentaire), vous pouvez commencer par une taille d'allocation donnée et continuer à augmenter et à réapprendre le readlink code> appel. Vous pouvez arrêter de développer le tampon lorsque l'appel suivant à
readlink code> renvoie la même chaîne qu'elle a fait pour la dernière itération. P>
Les autres réponses ne le mentionnent pas, mais il y a la fonction realpath code>, qui est exactement ce que vous voulez, qui est spécifié par POSIX.1-2001.
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
int
resolve_link (const char *filename)
{
char *res = realpath(filename, NULL);
if (res == NULL)
{
perror("realpath failed");
return -1;
}
printf("%s -> %s\n", filename, res);
free(res);
return 0;
}
int
main (void)
{
resolve_link("/proc/self/exe");
return 0;
}
J'aimerais que plus de fonctions de bibliothèque avaient la possibilité d'allouer automatiquement le tampon à cordes. Pourquoi n'est-ce pas?