Ich arbeitete ein bisschen an einer Lösung. Es ist keineswegs optimal, aber zumindest scheint es zu funktionieren. Ich habe die Funktion abspathat erstellt, die einen relativen Pfad in einen absoluten Pfad umwandelt. Dann benutze ich das eingebaute readlinkat um die Symlinks zu reparieren. Die Lösung behandelt Pfade wie "../code.c" "./code.c" "code.c" in "/dir/code.c". Momentan werden jedoch keine Pfade wie z. B. ../dir/../code.c repariert, aber warum sollte jemand einen solchen Pfad erstellen? Es prüft auch nicht, ob die Datei tatsächlich existiert. Fühlen Sie sich frei, diesen Code zu verbessern oder zu tun, was Sie wollen.
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdio.h>
/*****************************************************************************/
char *abspathat(char *dirpath, int dirlen, char *path);
/*****************************************************************************/
static const int MAX_FILEPATH = 4096;
/*****************************************************************************/
char *realpathat(int dirfd, char *dirpath, int dirlen, char *path) {
char *abs = abspathat(dirpath, dirlen, path);
char *buf = malloc(sizeof(char)*MAX_FILEPATH);
ssize_t size = readlinkat(dirfd, abs, buf, MAX_FILEPATH);
char *realpath;
if(size != -1) {
realpath = malloc(sizeof(size+1));
memcpy(realpath, buf, size);
realpath[size] = '\0';
free(abs);
} else {
realpath = abs;
}
free(buf);
return realpath;
}
/*---------------------------------------------------------------------------*/
char *abspathat(char *dirpath, int dirlen, char *path) {
/* If absolute */
if(path[0] == '/') {
return path;
}
int i;
char *right;
int d = 0;
int rlen = strlen(path);
int llen = 0;
if(path[0] == '.') {
if(path[1] == '.' && path[2] == '/') {
for(i = 3, d = 1; path[i] == '.'
&& path[i+1] == '.'
&& path[i+2] == '/'
&& i < rlen; i+=3) {
d++;
}
right = &path[i];
rlen -= i;
} else if(path[1] == '/') {
right = &path[2];
rlen -= 2;
}
} else {
right = &path[0];
}
for(i = dirlen - 1 - (dirpath[dirlen-1] == '/'); d && i; i--) {
if(dirpath[i] == '/') {
d--;
}
}
llen = i+1;
char *cpy = malloc(sizeof(char)*(llen + rlen + 2));
memcpy(cpy, dirpath, llen);
cpy[llen] = '/';
memcpy(cpy+llen+1, right, rlen);
cpy[llen+rlen+1] = '\0';
return cpy;
}
/*---------------------------------------------------------------------------*/
int main(int argc, char *argv[]) {
if(argc == 3) {
char *dirpath = argv[1];
DIR *d = opendir(dirpath);
char *path = argv[2];
char *resolved = realpathat(dirfd(d), dirpath, strlen(dirpath), path);
printf("%s\n", resolved);
} else {
printf("realpathat [directory] [filepath]\n");
}
return 0;
}
Warum nicht jeden Thread eine Zeichenfolge ihres aktuellen Pfads relativ zu Ihrem Startverzeichnis beibehalten? Sie können es jedes Mal anhängen, wenn Sie in ein Unterverzeichnis absteigen, und ein Level entfernen, wenn Sie herauskommen. Normalerweise sehen Sie nur relative Pfade, wie '#include" common/util.h "'. Sie müssen durch die Include-Pfade "-I" gelöst werden, die Sie dem Compiler geben. Ohne diese Informationen sehe ich nicht, wie Sie die vollständigen Pfade trotzdem korrekt auflösen. – e0k
Sie haben Recht, das ist wahrscheinlich die Lösung, mit der ich gehen werde. Es löst nicht Symlinks, aber wirklich wer Symlinks enthalten Dateien ..? Danke, dass du mich gebracht hast - ich denke daran, ich werde das auch reparieren. –
Viele Leute symlink Header. Oder zumindest haben einige der größeren Projekte, an denen ich gearbeitet habe, Header aus verschiedenen Gründen (viele von ihnen nicht sehr gut, aber das ist es, was in 30 Jahren passiert). –