Linux 文件名是否表示目录

Linux 文件名是否表示目录,linux,assembly,x86,nasm,Linux,Assembly,X86,Nasm,我有下面的程序。这意味着检查文件名是否表示目录,如果是目录,则设置进位标志,否则清除 现在它可以使用我测试过的文件和目录,但我怀疑这仅仅是巧合,因为我找不到任何关于stat()函数的有用文档,所以我不得不猜测 我需要知道的是,在结构中的哪个偏移量处,我可以找到文件是否为目录,以及哪个值表示什么。从我的测试中,我发现我所有的测试文件在偏移量20处的值都是1,而目录有2或3,但这可能只是巧合,我不知道偏移量20处的值实际上代表什么。可能是什么,也可能什么都没有 另外,我为结构留出了100字节,但我怀

我有下面的程序。这意味着检查文件名是否表示目录,如果是目录,则设置进位标志,否则清除

现在它可以使用我测试过的文件和目录,但我怀疑这仅仅是巧合,因为我找不到任何关于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)

你想检查一下。这是第三个成员,应该是
[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