【问题标题】:dtrace: How to get symlink target from filedtrace:如何从文件中获取符号链接目标
【发布时间】:2013-11-18 16:33:44
【问题描述】:

我正在使用 dtrace 记录所有被删除的文件。

是否有可能找出符号链接目标是什么(如果它是符号链接)?我想输出符号链接文件名和目标文件名以备日后需要恢复链接。

我想出的一个解决方案是使用 dtrace "system" 函数来调用我自己的程序,该程序将打印出符号链接目标: system("myprogram %s") 其中 %s 是我要为其打印目标的符号链接的全名。

这工作正常(它是一个非常短的 C 程序并且可以完成这项工作) - 但是有没有办法直接通过 dtrace 获取信息,因为我们正在处理文件,所以我们应该能够查找符号链接目标?

我查看了 fileinfo_t 结构,但它没有符号链接目标: http://docs.oracle.com/cd/E18752_01/html/817-6223/chp-io-args.html#chp-io-fileinfo

到目前为止,这是我的脚本: 这是在 Solaris 10 中。(这是探测 fop_remove 而不是 syscall::unlink 并且其原因是能够在用户没有在调用 rm 时指定目录的情况下获取符号链接目录)。

    #!/usr/sbin/dtrace -s

    #pragma D option quiet

    fbt::fop_remove:entry
    {
           self->dir = stringof(args[0]->v_path);
           self->file = stringof(args[1]);
    }

    fbt::fop_remove:return
    /self->file != NULL/
    {
           printf("%s/%s\n", self->dir, self->file);
           self->file = 0;
           self->dir = 0;
    }

谢谢!

【问题讨论】:

    标签: solaris solaris-10 dtrace


    【解决方案1】:

    在 Solaris VFS 级别(又名vnode_t 结构)上,符号链接目标附加到符号链接本身的节点。这是一个文件系统实现细节。

    对于 UFS 文件系统,如果链接目标的路径名短于 48 字节(UFS 称之为“快速符号链接”),它将与 inode_t 结构内联记录,您可以通过 DTrace 打印该值:

    vnode = args[0];
    inode = (inode_t*)vnode->v_data;
    
    printf("symlink tgt: %47s\n",
        vnode->v_type != VLNK ||
        vnode->v_op != ufs_vnodeops ||
        inode->i_flags & I_FASTSYMLINK == 0 ?
            "[unresolved]" :
            (char *)inode->i_db);
    

    对于其他文件系统 / 在一般情况下,您必须使用 fsinfo::readlink:return(或 fop::fop_readlink:return)探测点来获取目标 - 在访问时,也就是说,它不会(通常)可检索直接来自vnode_t

    【讨论】:

    • 谢谢弗兰克 - 这是 FreeBSD 的吗?我收到 ufs_vnodeopsi_db 的编译错误,它们不是已知的变量或 i_node 的成员。
    • 不——那是 Solaris。我不知道 FreeBSD 的 UFS 是否具有 Solaris UFS 所具有的“快速符号链接”机制(如果合适,直接块指针被重新用于保存符号链接目标路径名)。
    • 碰巧我正在处理的链接比 48 字节长得多。但感谢您澄清这一点。我不确定是否有任何方法可以直接使用文件本身访问目标。
    【解决方案2】:

    我有以下可能的解决方案 - 像你说的那样访问:

    syscall::open:entry /strstr(stringof(copyinstr(arg0)), "mydirectory")!=NULL/ {
        self->file=copyinstr(arg0);
    }
    
    syscall::open:return /self->file != "" && strstr(stringof(fds[arg0].fi_pathname),   "mydirectory")!=NULL / {
        printf("%s %s\n", self-> file, fds[arg0].fi_pathname);
        self -> file=0;
    }
    
    syscall::open:return {
        self -> file=0;
    }
    

    (我在这里将跟踪限制在 mydirectory)。

    因此,这利用了这样一个事实,即在进入时,arg0 是符号链接名称,而在返回时,文件描述符可用于获取路径名,即实际文件的路径名。所以这将是符号链接的目标。 在删除时完成跟踪实际上并不重要,只是记录了符号链接 -> 目标。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-18
      • 1970-01-01
      • 1970-01-01
      • 2017-06-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多