솔루션에 대해 조금 연구했습니다. 결코 최적은 아니지만 최소한 효과가있는 것 같습니다. 상대 경로를 절대 경로로 바꾸는 함수 abspathat을 만들었습니다. 그런 다음 readlinkat에 내장 된 기호 링크를 사용하여 수정합니다. 이 솔루션은 "../code.c" "./code.c" "code.c"와 같은 경로를 "/dir/code.c"로 처리합니다. 그러나 현재는 ../dir/../code.c와 같은 경로를 수정하지 않습니다.하지만 누구나 그러한 경로를 만들 수 있습니다. 파일이 실제로 존재하는지 확인도하지 않습니다. 이 코드를 통해 마음껏 개선하거나 할 수 있습니다.
#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;
}
왜 각 스레드가 시작 디렉토리에 상대적인 현재 경로의 문자열을 유지하지 못하게합니까? 하위 디렉토리로 내려갈 때마다 추가 할 수 있고 나올 때 레벨을 제거 할 수 있습니다. 어쨌든'#include "common/util.h"'와 같은 상대 경로 만 볼 수 있습니다. 그것들은 컴파일러에게주는'-I' 경로를 포함해서 해결되어야합니다. 이 정보가 없으면 어쨌든 전체 경로를 올바르게 해결하는 방법을 알지 못합니다. – e0k
당신이 옳습니다, 아마도 그것은 제가 갈 해결책입니다. 그것은 심볼릭 링크를 풀지는 못하지만 실제로 파일을 포함하는 심볼릭 링크는 누구입니까? 마음을 가져 주셔서 감사합니다. 나는 또한 고칠 것입니다. –
많은 사람들이 심볼릭 링크 헤더를 사용합니다. 또는 적어도 필자가 작업 한 더 큰 프로젝트 중 일부는 다양한 이유로 symlink로 연결된 헤더가 있습니다 (그 중 많은 것은별로 좋지 않지만 30 년이 넘는 기간 동안 발생합니다). –