私は解決策で少し作業しました。それは決して最適ではありませんが、少なくともそれはうまくいくようです。相対パスを絶対パスに変換する関数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年以上かかることです)。 –