Linux 文件名是否表示目录
我有下面的程序。这意味着检查文件名是否表示目录,如果是目录,则设置进位标志,否则清除 现在它可以使用我测试过的文件和目录,但我怀疑这仅仅是巧合,因为我找不到任何关于stat()函数的有用文档,所以我不得不猜测 我需要知道的是,在结构中的哪个偏移量处,我可以找到文件是否为目录,以及哪个值表示什么。从我的测试中,我发现我所有的测试文件在偏移量20处的值都是1,而目录有2或3,但这可能只是巧合,我不知道偏移量20处的值实际上代表什么。可能是什么,也可能什么都没有 另外,我为结构留出了100字节,但我怀疑这可能是内存太多了。同样,我真的可以使用一些与汇编相关的文档,而不是C。这里的一切都是关于C的,我能做的最好的事情就是猜测Linux 文件名是否表示目录,linux,assembly,x86,nasm,Linux,Assembly,X86,Nasm,我有下面的程序。这意味着检查文件名是否表示目录,如果是目录,则设置进位标志,否则清除 现在它可以使用我测试过的文件和目录,但我怀疑这仅仅是巧合,因为我找不到任何关于stat()函数的有用文档,所以我不得不猜测 我需要知道的是,在结构中的哪个偏移量处,我可以找到文件是否为目录,以及哪个值表示什么。从我的测试中,我发现我所有的测试文件在偏移量20处的值都是1,而目录有2或3,但这可能只是巧合,我不知道偏移量20处的值实际上代表什么。可能是什么,也可能什么都没有 另外,我为结构留出了100字节,但我怀
...
[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)
你想检查一下。这是第三个成员,应该是[16]
th和[23]
rd字节之间的一个单位值(定义为掩码)。我会提供更多的信息,但我现在在温多兹盒子上
更新0
由于机器是little endian,这告诉我们,如果设置了第25个字节的第二个最高有效位,那么它就是一个目录。在汇编中,您应该读取该字节[eax+25]
,并将其与0x40
进行比较,然后将其与零进行比较
或者你可以学C
更新1
上述操作是在x86_64操作系统上执行的。x86上的位置将不同
更新2
如果是目录,则之后的ebx
和ebx 0x40
的值将不为零
同样,如果您使用C,就不必担心您的平台是什么。但是,如果您为32位操作系统编译程序,如果该操作系统支持32位二进制文件,那么它仍将在64位操作系统下正确运行。如果您是在组装中进行此操作,我会选择此路线。您要检查。这是第三个成员,应该是[16]
th和[23]
rd字节之间的一个单位值(定义为掩码)。我会提供更多的信息,但我现在在温多兹盒子上
更新0
由于机器是little endian,这告诉我们,如果设置了第25个字节的第二个最高有效位,那么它就是一个目录。在汇编中,您应该读取该字节[eax+25]
,并将其与0x40
进行比较,然后将其与零进行比较
或者你可以学C
更新1
上述操作是在x86_64操作系统上执行的。x86上的位置将不同
更新2
如果是目录,则之后的ebx
和ebx 0x40
的值将不为零
同样,如果您使用C,就不必担心您的平台是什么。但是,如果您为32位操作系统编译程序,如果该操作系统支持32位二进制文件,那么它仍将在64位操作系统下正确运行。如果您在汇编中执行此操作,我会选择此路径。如何访问S_IFDIR,或者它的实际值是多少?我应该寻找什么来识别正确的字节?我对这一点还不太熟悉,很多时候当涉及到C库的时候,我都觉得自己在盲目地走@MCXXII:文档都是面向C的一个原因是答案会因机器而异。C编译器通过在系统头中提供适当的定义,将这一切抽象出来。获取系统特定信息的最简单方法是询问C编译器,编写一个短程序,如Matt Joiner在其“Update0”中所写的程序。至于手册页中指定的S_IFDIR
的实际值,即0040000,即16384,即0x4000.Hmm,我得到的偏移量为17。如果两台linux机器之间的偏移量也不同,那么它几乎没有用,不是吗?我现在按照你的建议去做,除了我读了[eax+17]
,它似乎很管用,但我仍然对代码的实际功能没有信心。我知道C,但到目前为止,这似乎对汇编帮助不大。我在汇编中这样做只是为了学习语言,我知道在C或其他高级语言中这样做会更实用,但这不是重点。@MCXXIII:我的错,我是在x64上这样做的。您的字节位置可能是正确的,运行我的C程序仍然可以正确地给出这些信息。@MattJoiner我在问题中添加了我的更正,只是想确定是否正确。只要偏移量在32位Linux上是正确的,它就应该是正常的,不过有没有办法确定系统是32位还是64位,以便在这两个系统上都可以使用正确的值?我如何访问S_IFDIR,或者它的实际值是多少?我应该寻找什么来识别正确的字节?我对这一点还不太熟悉,很多时候当涉及到C库的时候,我都觉得自己在盲目地走@MCXXII:文档都是面向C的一个原因是答案会因机器而异。C编译器通过在系统头中提供适当的定义,将这一切抽象出来。获取系统特定信息的最简单方法是询问C编译器,编写一个短程序,如Matt Joiner在其“Update0”中所写的程序。至于手册页中指定的S_IFDIR
的实际值,即0040000,即16384,即0x4000.Hmm,我得到的偏移量为17。如果两台linux机器之间的偏移量也不同,那么它几乎没有用,不是吗?我现在照你说的做
mov eax, StatBuf
mov ebx, dword [eax+17]
and ebx, 0x40
cmp ebx, 0
jne .yes
#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