Ich suche ein Beispiel für die Verwendung der Realpath-Funktion in einem C-Programm. Ich kann anscheinend keine im Internet oder in einem meiner C-Programmierbücher finden.
Beispiel einer realpath-Funktion in C
Ralf
pmg
-
Notiz
- Das
realpath()
Funktion ist im C-Standard nicht beschrieben- Es wird jedoch beschrieben durch POSIX 1997 und POSIX 2008.
- Das
-
Beispielcode
#include <limits.h> /* PATH_MAX */
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char buf[PATH_MAX]; /* PATH_MAX incudes the \0 so +1 is not required */
char *res = realpath("this_source.c", buf);
if (res) { // or: if (res != NULL)
printf("This source is at %s.\n", buf);
} else {
char* errStr = strerror(errno);
printf("error string: %s\n", errStr);
perror("realpath");
exit(EXIT_FAILURE);
}
return 0;
}
- Bezug
- PATH_MAX definiert in PATH_MAX aus POSIX 1997
- Fehlernr
- strerror
-
PATH_MAX ist die maximale Länge für einen Pfad. Es ist ein seltsames Gizmo; Es gibt garantiert einen Wert _POSIX_PATH_MAX, der der Mindestwert ist, den PATH_MAX haben kann. Viele Systeme haben jedoch eine
<limits.h>
Dadurch wird PATH_MAX nicht festgelegt, was bedeutet, dass es keine vorgeschriebene Grenze für die maximale Länge eines Pfads auf der Maschine gibt. Es kann sowieso auch vom Dateisystem abhängig sein. Sie können also mit sysconf() oder mit pathconf() nach einem Wert suchen, oder Sie können vermuten, dass die meisten vernünftigen Leute keine Pfade verwenden, die länger als 1024 Bytes sind, und diese verwenden.– Jonathan Leffler
13. Oktober 2009 um 22:36 Uhr
-
Sie sollten in Betracht ziehen, anzurufen
free(res);
nach Anrufrealpath
und Abschluss vonres
. Wierealpath
weist den Rückgabewert im Heap zu. Quelle:man realpath
– Dschalal Mostafa
3. März 2016 um 17:44 Uhr
-
@JalalMostafa: POSIX
realpath()
, wie im Link in meiner Antwort beschrieben, weist keinen Speicher zu. Ich vermute, Ihr System ist nicht POSIX-kompatibel. Anrufe POSIX-konformrealpath()
mitNULL
für das 2. Argument ruft UB.– pmg
3. März 2016 um 19:12 Uhr
-
@JalalMostafa: Es gibt eine neue Version der POSIX-Spezifikation (
realpath()
in POSIX 2008) dort kann das 2. Argument NULL sein und dannmalloc()
wird genannt. In meinem Beispiel ist der Puffer ein lokales Array, also kein Grund für einen Aufruffree()
. Danke für die Warnung.– pmg
3. März 2016 um 19:22 Uhr
oho
Einzeilige Build-Befehlszeile
Minimalistisch, aber es macht den Job!
Bauen
gcc -o realpath -x c - <<< $'#include<stdlib.h>\n#include<stdio.h>\nint main(int c,char**v){puts(realpath(v[1],0));}'
Prüfen
$> ./realpath ~/../../../usr/./bin/./awk
/bin/gawk
$> readlink -f ~/../../../usr/./bin/./awk
/bin/gawk
Anforderungen
- gcc zum Kompilieren und Linken
- bash für
<<<
und$' ... \n ... '
Absturz
Meine minimalistische einzeilige Befehlszeile erstellt eine ausführbare Datei realpath
das erzeugt a Segmentation fault
wenn der Pfad nicht existiert. Anstatt zu schreiben if
/else
Um dieses Problem in meiner Antwort zu behandeln, habe ich unten einige Links hinzugefügt, damit Sie einen Blick auf die Busybox-Implementierung von werfen können realpath
und readlink
.
Busybox-Implementierung
Einen vollständigeren Quellcode finden Sie in dieser einfachen Implementierung.
Offizielles Git-Repository
GitHub-Spiegel-Repository
-
/usr/bin/readlink -f erfordert nicht, dass der Pfad existiert. Realpath-API tut dies jedoch. Könnten Sie helfen, zu kommentieren, wie man Readlink in dieser Hinsicht nachahmt?
– SOBenutzer
11. November 2017 um 13:05 Uhr
-
Hallo @SOUser. Danke für deine Rückmeldung. Sie haben Recht, meine minimalistische einzeilige Befehlszeile erstellt eine ausführbare Datei
realpath
das erzeugt aSegmentation fault
wenn Pfad nicht existiert. Anstatt zu schreibenif/else
Blöcke, um dies in meiner Antwort zu handhaben, habe ich Links hinzugefügt, damit Sie einen Blick auf die Busybox-Implementierung von werfen könnenrealpath
undreadlink
. Ich hoffe, Sie wissen den Busybox-Quellcode zu schätzen. Bitte lassen Sie mich wissen, wenn ich helfen kann. Prost– oho
17. November 2017 um 10:04 Uhr
Jonathan Leffler
Was zum realpath()
Die Funktion teilt Ihnen den Pfadnamen einer Datei mit, wenn alle symbolischen Links aufgelöst wurden. Es ist nicht unbedingt ein absoluter Pfadname, wenn der von Ihnen angegebene Wert ein relativer Name ist, aber das hängt teilweise davon ab, ob Sie symbolische Links mit absoluten Namen für den Linkwert durchlaufen – wenn Sie dies tun, ist die Ausgabe schließlich ein absoluter Name . Auch, wenn der relative Name bis zum Stammverzeichnis reicht (oder „jenseits“, wie in „../../../../../..“ wenn nur drei Ebenen tief in der Verzeichnishierarchie).
Möglicherweise haben Sie bereits ein ‘realpath’-Programm auf Ihrem Computer. Hier ist die (nicht standardmäßige) Version, die ich geschrieben habe.
/*
@(#)File: $RCSfile: realpath.c,v $
@(#)Version: $Revision: 1.3 $
@(#)Last changed: $Date: 2007/10/23 20:23:44 $
@(#)Purpose: Command to evaluate realpath(3) on given arguments.
@(#)Author: J Leffler
@(#)Copyright: (C) JLSS 2007
@(#)Product: :PRODUCT:
*/
/*TABSTOP=4*/
#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600
#else
#define _XOPEN_SOURCE 500
#endif /* __STDC_VERSION__ */
#include <unistd.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include "stderr.h"
static const char optstr[] = "hlsV";
static const char usestr[] = "[-hslV] given-path [...]";
static const char hlpstr[] =
" -h Print this help message\n"
" -l Long format: print given-path and real-path\n"
" -s Short format: print just real-path\n"
" -V Print version and exit\n"
;
enum { FMT_LONG, FMT_SHORT };
static int format_type = FMT_LONG;
#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
extern const char jlss_id_realpath_c[];
const char jlss_id_realpath_c[] = "@(#)$Id: realpath.c,v 1.3 2007/10/23 20:23:44 jleffler Exp $";
#endif /* lint */
static int eval_realpath(const char *given)
{
char realname[_POSIX_PATH_MAX];
int rc = 0;
if (realpath(given, realname) == 0)
{
rc = -1;
err_sysrem("failed to resolve real path name for %s\n", given);
}
else if (format_type == FMT_SHORT)
printf("%s\n", realname);
else
printf("%s %s\n", given, realname);
return(rc);
}
int main(int argc, char **argv)
{
int i;
int rc = EXIT_SUCCESS;
int opt;
err_setarg0(argv[0]);
while ((opt = getopt(argc, argv, optstr)) != -1)
{
switch (opt)
{
case 'V':
err_version("REALPATH", &"@(#)$Revision: 1.3 $ ($Date: 2007/10/23 20:23:44 $)"[4]);
break;
case 'h':
err_help(usestr, hlpstr);
break;
case 'l':
format_type = FMT_LONG;
break;
case 's':
format_type = FMT_SHORT;
break;
default:
err_usage(usestr);
break;
}
}
for (i = optind; i < argc; i++)
{
if (eval_realpath(argv[i]) != 0)
rc = EXIT_FAILURE;
}
return(rc);
}
Ich brauchte es, um eine Software zu testen, die die Sicherheit eines Pfads auswertete, und musste sicher sein, dass mein Code den angegebenen Pfad zu demselben aufgelösten Speicherort wie auswertete realpath()
tut. Es wäre wahrscheinlich sinnvoll, es mit einer Option ‚-a‘ zu erweitern, um sicherzustellen, dass Namen absoluten Namen zugeordnet werden (indem dem Ergebnis von vorangestellt wird getcwd()
zu relativen Pfadnamen).
(Der zusätzliche Quellcode ist in my SOQ (Stack Overflow Questions)-Repository auf GitHub als Dateien stderr.c
, stderr.h
und errhelp.c
in dem src/libsoq Unterverzeichnis.)
-
Nein, es tut geben Sie unbedingt einen absoluten Pfadnamen an. Die Dokumentation sagt „Die realpath() Funktion abgeleitet werden soll, von dem Pfadnamen, auf den gezeigt wird Dateinameein absoluter Pfadname, der dieselbe Datei benennt, …”
– Adam Rosenfield
20. August 2011 um 2:46 Uhr
-
Das ist seltsam; Du hast Recht, aber … ich muss irgendwo auf die falsche Idee gekommen sein. Die Schwierigkeit besteht fast vier Jahre nach dem Schreiben des Codes und meistens zwei Jahre nach dem Schreiben der Antwort darin, zu wissen, woher ich die Fehlinformationen habe. Bei obskuren Systemen sind einige Untersuchungen erforderlich.
– Jonathan Leffler
20. August 2011 um 3:08 Uhr
-
Hi. Es ist 2022. Ich versuche, Ihre Antwort zu verstehen. Ich tue
gcc -g -Wall reallink1.c stderr.c stderr.h
es wird nicht kompiliert. Der Fehler istundefined reference to
err_help’` / @JonathanLeffler– jian
21. Juli um 16:37 Uhr
-
@Mark: Entschuldigung – Sie werden brauchen
errhelp.c
too , das in meinem SOQ-Repository verfügbar ist, wie im Ende der Frage dokumentiert. Wenn Sie eine andere nicht standardmäßige Datei benötigen, sollte sich die Quelle/der Header im selben Verzeichnis des Repositorys befinden. Wenn etwas ganz fehlt, lassen Sie es mich bitte wissen.– Jonathan Leffler
21. Juli um 18:14 Uhr