Представляет ли имя файла каталог - PullRequest
1 голос
/ 29 ноября 2011

У меня есть процедура ниже. Он предназначен для проверки, представляет ли имя файла каталог или нет, установив флаг Carry, если это каталог, и очистив его в противном случае.

Сейчас он работает с файлами и каталогами, с которыми я его тестировал, но я подозреваю, что это простое совпадение, потому что я не смог найти никакой полезной документации по функции stat (), поэтому мне пришлось угадывать.

Мне нужно знать, по какому смещению в структуре я могу определить, является ли файл каталогом или нет, и какое значение означает что. Из моего тестирования я обнаружил, что все мои тестовые файлы имели значение 1 со смещением 20, в то время как каталоги имели либо 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 после and представляется равным 0 для файлов и 64 для каталогов, не должно ли быть наоборот (0 для каталогов)?

mov eax, StatBuf

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

cmp ebx, 0
jne .yes

1 Ответ

1 голос
/ 29 ноября 2011

Вы хотите проверить S_IFDIR в st_mode элементе .Это третий член, и он должен быть однобитовым значением (оно определяется как маска) где-то между [16] th и [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

Поскольку машина маленькаяendian, это говорит нам о том, что это каталог, если для 25-го байта установлен второй по значимости бит.В сборке вы должны прочитать этот байт [eax+25], and с 0x40, а затем сравнить с нолем.

Или вы можете узнать C.

Update1

Выше было выполнено на ОС x86_64.В x86 расположение будет другим.

Update2

Значение ebx после and ebx 0x40 будет ненулевым, если это каталог.

Снова, если выиспользуется C, вам не нужно беспокоиться о том, что ваша платформа.Однако если вы скомпилируете свою программу для 32-битной ОС, она все равно будет корректно работать под 64-битной ОС, если эта ОС поддерживает 32-битные двоичные файлы.Я бы взял этот маршрут, если вы делаете это в сборке.

...