下一页 上一页 目录

11. 第三个示例:Fortune

这个示例需要一些 C 编程知识。大多数 UNIX/Linux 软件是用 C 语言编写的,对于任何认真对待软件安装的人来说,学习至少一点 C 语言肯定是有益的。

臭名昭著的 fortune 程序在每次 Linux 启动时都会显示一句幽默的格言,即“幸运饼干”。不幸的是(双关语),尝试在带有 2.0.30 内核的 Red Hat 发行版上构建 fortune 会产生致命错误。

~/fortune# make all


gcc -O2 -Wall -fomit-frame-pointer -pipe   -c fortune.c -o
fortune.o
fortune.c: In function `add_dir':
fortune.c:551: structure has no member named `d_namlen'
fortune.c:553: structure has no member named `d_namlen'
make[1]: *** [fortune.o] Error 1
make[1]: Leaving directory `/home/thegrendel/for/fortune/fortune'
make: *** [fortune-bin] Error 2

查看 fortune.c,相关的行是这些。

   if (dirent->d_namlen == 0)
            continue;
        name = copy(dirent->d_name, dirent->d_namlen);

我们需要找到结构 dirent,但它没有在 fortune.c 文件中声明,并且 grep dirent 也没有在任何其他源文件中显示它。然而,在 fortune.c 的顶部,有以下行。

#include <dirent.h>

这似乎是一个系统库包含文件,因此,查找 dirent.h 的逻辑位置是在 /usr/include 中。实际上,/usr/include 中确实存在一个 dirent.h 文件,但该文件不包含 dirent 结构的声明。但是,其中引用了另一个 dirent.h 文件。

#include <linux/dirent.h>

最后,转到 /usr/include/linux/dirent.h,我们找到了所需的结构声明。

struct dirent {
        long            d_ino;
        __kernel_off_t  d_off;
        unsigned short  d_reclen;
        char            d_name[256]; /* We must not include
limits.h! */
};

果然,结构声明不包含 d_namelen,但是有一些“候选项”可以作为它的等价物。其中最有可能的是 d_reclen,因为这个结构成员可能表示某种长度,并且它是一个短整型。另一种可能性 d_ino,根据其名称和类型判断,可能是一个 inode 号。事实上,我们可能正在处理一个“目录项”结构,而这些元素代表文件的属性,它的名称、inode 和长度(以块为单位)。这似乎验证了我们的猜测。

让我们编辑 fortune.c 文件,并将第 551 行和 553 行中的两个 d_namelen 引用更改为 d_reclen。再次尝试 make all成功。它构建时没有错误。我们现在可以从 fortune 中获得我们的“廉价刺激”了。


下一页 上一页 目录