用于操纵给定路径的递归函数

时间:2012-06-27 22:25:59

标签: c recursion symlink filepath xv6

我正在修改教学操作系统xv6(用c编写)以支持符号链接(AKA快捷方式)。 符号链接是T_SYM类型的文件,其中包含指向其目标的路径。 为此,我编写了一个递归函数,它获取路径和缓冲区并使用“真实”路径填充缓冲区(即,如果路径包含链接,则应该用实际路径替换,并且链接可以在路径中的任何级别。)

基本上,如果我有一个路径a / b / c / d,以及从f到a / b的链接,则以下操作应该是等效的:

cd a / b / c / d

cd f / c / d

现在,编写了代码,但我试图解决的问题是用“/”开始路径的问题(意味着路径是绝对的而不是相对的)。 现在,如果我使用名为/ dir1的路径运行它,它会将其视为dir1(相对而不是绝对)。

这是main函数,它调用递归函数。 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; 
}

这是递归部分。 该函数返回一个inode结构(表示系统中的文件或目录)。它构建了真实路径中的真实路径。 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;
}

我已经尝试了许多方法来做正确但没有成功。如果有人发现问题,我会很高兴听到解决方案。 谢谢, 的Eyal

2 个答案:

答案 0 :(得分:0)

我认为很明显,在运行get_real_path(pathname, name, realpathname, 0, 0)之后,realpathname无法以斜线开头。

如果函数成功执行,memmove(realpath + position, name, strlen(name))确保realpathname开头,因为position变量在第一次调用{{1}时始终包含零}。 我建议像

这样的东西
memmove

P.S。我不确定为什么在执行if(*path == '/') { ip = iget(ROOTDEV, ROOTINO); // ip gets the root realpath[position++] = '/'; } else ip = idup(proc->cwd); // ip gets the current working directory 之前将斜杠放入realpathname,因为此时你并不知道所提供的路径是否是绝对路径。

答案 1 :(得分:0)

好的,发现了问题...... 问题比我想象的更深...... 不知何故,真实路径有时没有明显改变......但原因是这条线: name = newpath;

解决方案是将该行更改为 的strcpy(姓名,NEWPATH);

前一行在名称和realpath之间进行了绑定...如果我们不处理软链接,这可能没问题。取消引用子路径时,此绑定会破坏所有内容。

感谢您的尝试