1

シンボリック リンク (AKA ショートカット) をサポートするために、教訓的な OS xv6 (c で記述) の変更に取り組んでいます。シンボリック リンクは、リンク先へのパスを含むタイプ T_SYM のファイルです。そのために、パスとバッファーを取得し、バッファーを「実際の」パスで埋める再帰関数を作成しました (つまり、パスにリンクが含まれている場合は、実際のパスに置き換える必要があり、リンクは次の場所で発生する可能性があります)。パスの任意のレベル)。

基本的に、パス a/b/c/d と f から a/b へのリンクがある場合、次の操作は同等である必要があります。

CD a/b/c/d

CD f/c/d

これでコードが書かれましたが、私が解決しようとしている問題は、パスが「/」で始まる問題です(パスが絶対パスで相対パスではないことを意味します)。現在、/dir1 という名前のパスで実行すると、dir1 のように扱われます (絶対ではなく相対)。

これはメイン関数であり、再帰関数を呼び出します。pathname は指定されたパスで、buf には実際のパスが含まれます。

int readlink(char *pathname, char *buf, size_t bufsize){
    char name[DIRSIZ];
    char realpathname[100];

    memset(realpathname,0,100);
    realpathname[0] = '/';

    if(get_real_path(pathname, name, realpathname, 0, 0)){
       memmove(buf, realpathname, strlen(realpathname));
       return strlen(realpathname);
    }

    return -1; 
}

これが再帰部分です。この関数は、i ノード構造 (システム内のファイルまたはディレクトリを表す) を返します。realpath 内に実際のパスを構築します。ilock と iunlock は、inode を安全に使用するために使用されています。

struct inode* get_real_path(char *path, char *name, char* realpath, int position){
    struct inode *ip, *next;
    char buf[100];
    char newpath[100];

    if(*path == '/')
        ip = iget(ROOTDEV, ROOTINO);// ip gets the root directory
    else
        ip = idup(proc->cwd); // ip gets the current working directory

    while((path = skipelem(path, name)) != 0){name will get the next directory in the path, path will get the rest of the directories
        ilock(ip);
        if(ip->type != T_DIR){//if ip is a directory
            realpath[position-1] = '\0';
            iunlockput(ip);
            return 0;
        }

        if((next = dirlookup(ip, name, 0)) == 0){//next will get the inode of the next directory
            realpath[position-1] = '\0';
            iunlockput(ip);
            return 0;
        }
        iunlock(ip);

        ilock(next);

        if (next->type == T_SYM){ //if next is a symbolic link
            readi(next, buf, 0, next->size); //buf contains the path inside the symbolic link (which is a path)
            buf[next->size] = 0;
            iunlockput(next);

            next = get_real_path(buf, name, newpath, 0);//call it recursively (might still be a symbolic link)

            if(next == 0){
                realpath[position-1] = '\0';
                iput(ip);

                return 0;
            }

            name = newpath;
            position = 0;
        }     
        else
        iunlock(next);

        memmove(realpath + position, name, strlen(name));
        position += strlen(name);
        realpath[position++]='/';
        realpath[position] = '\0';

        iput(ip);

        ip = next;
    }  
    realpath[position-1] = '\0';

    return ip;
}

私はそれを正しく行うために多くの方法を試しましたが、成功しませんでした。誰かが問題を見つけたら、解決策を聞いてうれしいです。ありがとう、エヤル

4

2 に答える 2

0

わかりました、問題を見つけました...問題は私が思っていたよりも深いものでした...どういうわけか、目に見える理由なしにリアルパスが変更されることがありました...しかし理由は次の行でした:name = newpath;

解決策は、その行をstrcpy(name、newpath);に変更することでした。

前の行は、名前と実パスの間にバインディングを作成しました...これは、ソフトリンクを処理していなかった場合は問題ありません。サブパスを逆参照するとき、このバインディングはすべてを台無しにしました。

試みてくれてありがとう

于 2012-07-01T08:14:20.517 に答える
0

get_real_path(pathname, name, realpathname, 0, 0)を実行した後realpathname、スラッシュで開始できないことは明らかだと思います。

関数が正常に実行された場合、変数は の最初の呼び出しで常にゼロを含むため、 は で始まるmemmove(realpath + position, name, strlen(name))ことを保証します。私は次のようなものを提案しますrealpathnamepositionmemmove

if(*path == '/') {
   ip = iget(ROOTDEV, ROOTINO); // ip gets the root
   realpath[position++] = '/';  
} else
   ip = idup(proc->cwd); // ip gets the current working directory

realpathnamePS を実行する前に にスラッシュを入れる理由がget_real_pathわかりません。この時点では、提供されたパスが絶対パスかどうかわからないからです。

于 2012-06-28T15:47:41.180 に答える