filename是否代表目录

时间:2011-11-29 13:18:47

标签: linux assembly x86 nasm

我有以下程序。它用于检查文件名是否表示目录,如果是目录则设置Carry标志,否则清除它。

现在它适用于我测试过的文件和目录,但我怀疑这只是巧合,因为我找不到有关stat()函数的任何有用文档,所以我不得不猜测。

我需要知道的是结构中的哪个偏移量我可以找到该文件是否是目录,以及哪个值意味着什么。从我的测试中我发现我的所有测试文件在偏移20时的值为1,而目录有2或3,但这可能只是巧合,我不知道偏移20的值实际上代表什么。可以是任何东西,或者什么也不是。

另外,我为结构预留了100个字节,但我怀疑这可能是太多的内存。再一次,我真的可以使用一些与汇编而不是C相关的文档。关于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之后and中的值对于文件看起来是0而对于目录看起来是64,不应该是相反的方式(目录为0)?

mov eax, StatBuf

mov ebx, dword [eax+17]
and ebx, 0x40

cmp ebx, 0
jne .yes

1 个答案:

答案 0 :(得分:1)

您要查看S_IFDIR in the st_mode member。这是第三个成员,应该是[16][23] rd字节之间的单个位值(它被定义为掩码)。我会提供更多信息,但我现在正在使用Windoze盒子。

Update0

#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个字节的第2个最高有效位,它就是一个目录。在汇编中,您应该使用[eax+25]读取此字节and0x40,然后将其与零进行比较。

或者你可以学习C。

UPDATE1

以上是在x86_64 OS上执行的。 x86上的位置会有所不同。

UPDATE2

ebx之后and ebx 0x40的值如果是目录则不为零。

再次,如果你使用C,你不必担心你的平台是什么。但是,如果您为32位操作系统编译程序,如果该操作系统支持32位二进制文​​件,它仍将在64位操作系统下正确运行。如果你在集会中这样做,我会选择这条路线。