假如open的文件是个符号链接

一般我们在user space 通过open打开某个字符设备,例如下面的函数就会打开/dev/i2c-x 这个字符设备
int open_i2c_dev(int i2cbus, char *filename, size_t size, int quiet)
{
        int file;

        snprintf(filename, size, "/dev/i2c-%d", i2cbus);
        filename[size - 1] = '\0';
        file = open(filename, O_RDWR);

        if (file < 0 && (errno == ENOENT || errno == ENOTDIR)) {
                sprintf(filename, "/dev/i2c-%d", i2cbus);
                file = open(filename, O_RDWR);
        }
       
        return file;
}

假如已经有/dev/i2c-0.和/dev/i2c-1,这个使用我用ln -sf /dev/i2c-1 /dev/i2c-0.这个时候再用open函数来打开/dev/i2c-0 是open的/dev/i2c-0 还是/dev/i2c-1 呢?
先把结论告诉大家,open的是/dev/i2c-1。原因如下:
do_sys_open->do_filp_open->path_openat
在path_openat 中有一段关键的code如下:
    while (!(error = link_path_walk(s, nd)) &&
        (error = do_last(nd, file, op, &opened)) > 0) {
        nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
        s = trailing_symlink(nd);
        if (IS_ERR(s)) {
            error = PTR_ERR(s);
            break;
        }
    }
这段code中会调用trailing_symlink 来检查当前打开的文件,例如本例子中的/dev/i2c-1 是否是符号链接,如果是符号链接的话
static const char *trailing_symlink(struct nameidata *nd)
{
    const char *s;
    int error = may_follow_link(nd);
    if (unlikely(error))
        return ERR_PTR(error);
    nd->flags |= LOOKUP_PARENT;
    nd->stack[0].name = NULL;
    s = get_link(nd);
    return s ? s : "";
}

会调用may_follow_link 来检查是否有权限来得到符号链接的真实链接,本例中由于是root 用户,肯定和是有权限的,因此这里就找到/dev/i2c-1 指向的真实链接/dev/i2c-0




你可能感兴趣的:(Linux,源码分析)