我有以下程序。它的目的是检查一个文件名是否代表一个目录,如果它是一个目录就设置进位标志,否则清除它。
现在它适用于我测试过的文件和目录,但我怀疑这只是巧合,因为我找不到任何关于 stat() 函数的有用文档,所以我不得不进行猜测。
我需要知道的是我可以在结构中的哪个偏移处找到文件是否是目录,以及哪个值表示什么。从我的测试中,我发现我所有的测试文件在偏移量 20 处的值为 1,而目录有 2 或 3,但这可能只是巧合,我不知道偏移量 20 处的值实际代表什么。可以是任何东西,也可以什么都不是。
此外,我为该结构预留了 100 个字节,但我怀疑这可能是太多内存了。同样,我真的可以为此使用一些与汇编而不是 C 相关的文档。那里的一切都是关于 C 的,我能做的最好的事情就是猜测。
...
[SECTION .bss]
StatBuf resb 100
...
isdir:
pushad
push StatBuf
push eax ; Filename passed in eax
call stat
add esp, 8
cmp eax, 0 ; stat returns 0 on success
jne .error ; -1 (not 0) on failure
mov eax, StatBuf ; Stats stored in StatBuf
cmp byte [eax+20], 1 ; Guess: All files have value 1 at offset 20?
jne .yes ; Guess: Dirs either 2 or 3?
clc ; Not a directory
jmp .done
.yes:
stc ; File is a directory
jmp .done
.error:
clc ; Error, not a directory
jmp .done
.done:
popad
ret
更新 0
我现在执行以下操作,它似乎再次起作用,但我不确定它是否真的正确。在 和
之后的 ebx
中的值对于文件似乎是 0,对于目录似乎是 64,难道不应该是相反的(目录为 0)吗?
mov eax, StatBuf
mov ebx, dword [eax+17]
and ebx, 0x40
cmp ebx, 0
jne .yes
最佳答案
您想检查 S_IFDIR
in the st_mode
member .这是第三个成员,应该是 [16]
th 和 [23]
rd 字节之间的单个位值(它被定义为掩码)。我会提供更多信息,但我现在正在使用 Windoze 框。
更新0
#include <sys/stat.h>
#include <stdio.h>
#include <stddef.h>
main() {
printf("st_mode offset = %zu\n", offsetof(struct stat, st_mode));
printf("S_IFDIR mask = %x\n", S_IFDIR);
}
执行给我:
matt@stanley:~$ gcc -o mask /home/matt/Desktop/mask.c
matt@stanley:~$ ./mask
st_mode offset = 24
S_IFDIR mask = 4000
由于机器是小尾数法,这告诉我们如果设置了第 25 个字节的第二个最高有效位,它就是一个目录。在汇编中你应该读取这个字节[eax+25]
,和
它与0x40
,然后与零比较。
或者你可以学习 C。
更新1
以上是在 x86_64 操作系统上执行的。该位置在 x86 上会有所不同。
更新2
和 ebx 0x40
之后的 ebx
的值如果是目录则为非零。
同样,如果您使用 C,则无需担心您的平台是什么。但是,如果您为 32 位操作系统编译程序,如果该操作系统支持 32 位二进制文件,它仍然可以在 64 位操作系统下正确运行。如果您在汇编中这样做,我会选择这条路线。
关于linux - 文件名是否代表一个目录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8311398/