Subversion Repositories Kolibri OS

Rev

Rev 3500 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;   02.02.2010  turbanoff  - support 70.5                      ;;
  6. ;;   23.01.2010  turbanoff  - support 70.0 70.1                 ;;
  7. ;;   21.06.2013  yogev_ezra - Translate Russian comments        ;;
  8. ;;                                                              ;;
  9. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  10.  
  11. $Revision: 3725 $
  12.  
  13. EXT2_BAD_INO         = 1
  14. EXT2_ROOT_INO        = 2
  15. EXT2_ACL_IDX_INO     = 3
  16. EXT2_ACL_DATA_INO    = 4
  17. EXT2_BOOT_LOADER_INO = 5
  18. EXT2_UNDEL_DIR_INO   = 6
  19.  
  20. ;RUS: флаги, указываемые в inode файла   ;ENG: flags specified in file inode
  21. EXT2_S_IFREG         = 0x8000
  22. EXT2_S_IFDIR         = 0x4000
  23. EXT2_S_IFMT          = 0xF000 ;RUS: маска для типа файла  ;ENG: mask for file type
  24.  
  25. ;RUS: флаги, указываемые в linked list родительской папки
  26. ;ENG: flags specified in linked list of parent folder
  27. EXT2_FT_REG_FILE     = 1     ;RUS: это файл, запись в родительском каталоге
  28.                              ;ENG: this is a file, record in parent catalog
  29. EXT2_FT_DIR          = 2     ;RUS: это папка   ;ENG: this is a folder
  30.  
  31. ;RUS: флаги используемые KolibriOS   ;ENG: flags used by KolibriOS
  32. FS_FT_HIDDEN         = 2
  33. FS_FT_DIR            = 0x10  ;RUS: это папка      ;ENG: this is a folder
  34. FS_FT_ASCII          = 0     ;RUS: имя в ascii    ;ENG: name in ASCII
  35. FS_FT_UNICODE        = 1     ;RUS: имя в unicode  ;ENG: name in UNICODE
  36.  
  37. EXT2_FEATURE_INCOMPAT_FILETYPE = 0x0002 ;RUS: тип файла должен указываться в директории
  38.                                         ;ENG: file type must be specified in the folder
  39. EXT4_FEATURE_INCOMPAT_EXTENTS  = 0x0040 ;RUS: экстенты   ;ENG: extents
  40. EXT4_FEATURE_INCOMPAT_FLEX_BG  = 0x0200 ;RUS: гибкие группы блоков   ;ENG: flexible block groups
  41.  
  42. ;RUS: реализованные ext[234] features   ;ENG: implemented ext[234] features
  43. EXT4_FEATURE_INCOMPAT_SUPP = EXT2_FEATURE_INCOMPAT_FILETYPE \
  44.                           or EXT4_FEATURE_INCOMPAT_EXTENTS \
  45.                           or EXT4_FEATURE_INCOMPAT_FLEX_BG
  46.  
  47. ;RUS: флаги, указываемые для inode в i_flags   ;ENG: flags specified for inode in i_flags
  48. EXT2_EXTENTS_FL      = 0x00080000
  49.  
  50. struct  EXT2_INODE_STRUC
  51.         i_mode          dw ?
  52.         i_uid           dw ?
  53.         i_size          dd ?
  54.         i_atime         dd ?
  55.         i_ctime         dd ?
  56.         i_mtime         dd ?
  57.         i_dtime         dd ?
  58.         i_gid           dw ?
  59.         i_links_count   dw ?
  60.         i_blocks        dd ?
  61.         i_flags         dd ?
  62.         i_osd1          dd ?
  63.         i_block         rd 15
  64.         i_generation    dd ?
  65.         i_file_acl      dd ?
  66.         i_dir_acl       dd ?
  67.         i_faddr         dd ?
  68.         i_osd2          dd ? ; 1..12
  69. ends
  70.  
  71. struct  EXT2_DIR_STRUC
  72.         inode           dd ?
  73.         rec_len         dw ?
  74.         name_len        db ?
  75.         file_type       db ?
  76.         name            db ? ; 0..255
  77. ends
  78.  
  79. struct  EXT2_BLOCK_GROUP_DESC
  80.         block_bitmap            dd ? ;+0
  81.         inode_bitmap            dd ? ;+4
  82.         inode_table             dd ? ;+8
  83.         free_blocks_count       dw ? ;+12
  84.         free_inodes_count       dw ? ;+14
  85.         used_dirs_count         dw ? ;+16
  86.         pad                     dw ? ;+18
  87.         reserved                rb 12;+20
  88. ends
  89.  
  90. struct  EXT2_SB_STRUC
  91.         inodes_count            dd ? ;+0
  92.         blocks_count            dd ? ;+4
  93.         r_block_count           dd ? ;+8
  94.         free_block_count        dd ? ;+12
  95.         free_inodes_count       dd ? ;+16
  96.         first_data_block        dd ? ;+20
  97.         log_block_size          dd ? ;+24
  98.         log_frag_size           dd ? ;+28
  99.         blocks_per_group        dd ? ;+32
  100.         frags_per_group         dd ? ;+36
  101.         inodes_per_group        dd ? ;+40
  102.         mtime                   dd ? ;+44
  103.         wtime                   dd ? ;+48
  104.         mnt_count               dw ? ;+52
  105.         max_mnt_count           dw ? ;+54
  106.         magic                   dw ? ;+56
  107.         state                   dw ? ;+58
  108.         errors                  dw ? ;+60
  109.         minor_rev_level         dw ? ;+62
  110.         lastcheck               dd ? ;+64
  111.         check_intervals         dd ? ;+68
  112.         creator_os              dd ? ;+72
  113.         rev_level               dd ? ;+76
  114.         def_resuid              dw ? ;+80
  115.         def_resgid              dw ? ;+82
  116.         first_ino               dd ? ;+84
  117.         inode_size              dw ? ;+88
  118.         block_group_nr          dw ? ;+90
  119.         feature_compat          dd ? ;+92
  120.         feature_incompat        dd ? ;+96
  121.         feature_ro_compat       dd ? ;+100
  122.         uuid                    rb 16 ;+104
  123.         volume_name             rb 16 ;+120
  124.         last_mounted            rb 64 ;+136
  125.         algo_bitmap             dd ? ;+200
  126.         prealloc_blocks         db ? ;+204
  127.         preallock_dir_blocks    db ? ;+205
  128.         reserved_gdt_blocks     dw ? ;+206
  129.         journal_uuid            rb 16 ;+208
  130.         journal_inum            dd ? ;+224
  131.         journal_dev             dd ? ;+228
  132.         last_orphan             dd ? ;+232
  133.         hash_seed               rd 4 ;+236
  134.         def_hash_version        db ? ;+252
  135.                                 rb 3 ;+253 reserved
  136.         default_mount_options   dd ? ;+256
  137.         first_meta_bg           dd ? ;+260
  138.         mkfs_time               dd ? ;+264
  139.         jnl_blocks              rd 17 ;+268
  140.         blocks_count_hi         dd ? ;+336
  141.         r_blocks_count_hi       dd ? ;+340
  142.         free_blocks_count_hi    dd ? ;+344
  143.         min_extra_isize         dw ? ;+348
  144.         want_extra_isize        dw ? ;+350
  145.         flags                   dd ? ;+352
  146.         raid_stride             dw ? ;+356
  147.         mmp_interval            dw ? ;+358
  148.         mmp_block               dq ? ;+360
  149.         raid_stripe_width       dd ? ;+368
  150.         log_groups_per_flex     db ? ;+372
  151. ends
  152.  
  153. struct EXT4_EXTENT_HEADER       ;RUS: заголовок блока экстентов/индексов
  154.         eh_magic        dw ?    ;RUS: в текущей реализации ext4 должно быть 0xF30A
  155.         eh_entries      dw ?    ;RUS: количество экстентов/индексов в блоке
  156.         eh_max          dw ?    ;RUS: max количество (используется при записи)
  157.         eh_depth        dw ?    ;RUS: глубина дерева (0, если это блок экстентов)
  158.         eh_generation   dd ?    ;???
  159. ends
  160.  
  161. struct EXT4_EXTENT              ;RUS: экстент            ;ENG: extent
  162.         ee_block        dd ?    ;RUS: номер ext4 блока   ;ENG: number of ext4 block
  163.         ee_len          dw ?    ;RUS: длина экстента     ;ENG: extent length
  164.         ee_start_hi     dw ?    ;RUS: старшие 16 бит 48-битного адреса (пока не используются в KOS)
  165.                                 ;ENG: upper 16 bits of the 48-bit address (not used in KolibriOS yet)
  166.         ee_start_lo     dd ?    ;RUS: младшие 32 бита 48-битного адреса
  167.                                 ;ENG: lower 32 bits of the 48-bit address
  168. ends
  169.  
  170. struct EXT4_EXTENT_IDX          ;RUS: индекс - указатель на блок с экстентами/индексами
  171.                                 ;ENG: index - pointer to block of extents/indexes
  172.         ei_block        dd ?    ;RUS: номер ext4 блока   ;ENG: number of ext4 block
  173.         ei_leaf_lo      dd ?    ;RUS: младшие 32 бит 48-битного адреса
  174.                                 ;ENG: lower 32 bits of the 48-bit address
  175.         ei_leaf_hi      dw ?    ;RUS: старшие 16 бит 48-битного адреса (пока не используются в KOS)
  176.                                 ;ENG: upper 16 bits of the 48-bit address (not used in KolibriOS yet)
  177.         ei_unused       dw ?    ;RUS: зарезервировано   ;ENG: reserved
  178. ends
  179.  
  180. ext2_test_superblock:
  181.         cmp     [fs_type], 0x83
  182.         jne     .no
  183.  
  184.         mov     eax, [PARTITION_START]
  185.         add     eax, 2                  ;superblock start at 1024b
  186.         call    hd_read
  187.  
  188.         cmp     [ebx + EXT2_SB_STRUC.log_block_size], 3  ;0,1,2,3
  189.         ja      .no
  190.         cmp     [ebx + EXT2_SB_STRUC.magic], 0xEF53
  191.         jne     .no
  192.         cmp     [ebx + EXT2_SB_STRUC.state], 1        ;EXT_VALID_FS=1
  193.         jne     .no
  194.         cmp     [ebx + EXT2_SB_STRUC.inodes_per_group], 0
  195.         je      .no
  196.        
  197.         mov     eax, [ebx + EXT2_SB_STRUC.feature_incompat]
  198.         test    eax, EXT2_FEATURE_INCOMPAT_FILETYPE
  199.         jz      .no
  200.         test    eax, not EXT4_FEATURE_INCOMPAT_SUPP
  201.         jnz     .no
  202.  
  203.     ; OK, this is correct EXT2 superblock
  204.         clc
  205.         ret
  206.    .no:
  207.     ; No, this superblock isn't EXT2
  208.         stc
  209.         ret
  210.  
  211. ext2_setup:
  212.         mov     [fs_type], 2
  213.  
  214.         push    512
  215.         call    kernel_alloc                            ; mem for superblock
  216.         mov     esi, ebx
  217.         mov     edi, eax
  218.         mov     ecx, 512/4
  219.         rep movsd                                       ; copy sb to reserved mem
  220.         mov     ebx, eax
  221.         mov     [ext2_data.sb], eax
  222.  
  223.         mov     eax, [ebx + EXT2_SB_STRUC.blocks_count]
  224.         sub     eax, [ebx + EXT2_SB_STRUC.first_data_block]
  225.         dec     eax
  226.         xor     edx, edx
  227.         div     [ebx + EXT2_SB_STRUC.blocks_per_group]
  228.         inc     eax
  229.         mov     [ext2_data.groups_count], eax
  230.  
  231.         mov     ecx, [ebx + EXT2_SB_STRUC.log_block_size]
  232.         inc     ecx
  233.         mov     [ext2_data.log_block_size], ecx    ; 1, 2, 3, 4   equ 1kb, 2kb, 4kb, 8kb
  234.  
  235.         mov     eax, 1
  236.         shl     eax, cl
  237.         mov     [ext2_data.count_block_in_block], eax
  238.  
  239.         shl     eax, 7
  240.         mov     [ext2_data.count_pointer_in_block], eax
  241.         mov     edx, eax   ;RUS: потом еще квадрат найдем   ;ENG: we'll find a square later
  242.  
  243.         shl     eax, 2
  244.         mov     [ext2_data.block_size], eax
  245.  
  246.         push    eax eax                                 ; 2 kernel_alloc
  247.  
  248.         mov     eax, edx
  249.         mul     edx
  250.         mov     [ext2_data.count_pointer_in_block_square], eax
  251.  
  252.         call    kernel_alloc
  253.         mov     [ext2_data.ext2_save_block], eax        ; and for temp block
  254.         call    kernel_alloc
  255.         mov     [ext2_data.ext2_temp_block], eax        ; and for get_inode proc
  256.  
  257.         movzx   ebp, word [ebx + EXT2_SB_STRUC.inode_size]
  258.         mov     ecx, [ebx + EXT2_SB_STRUC.blocks_per_group]
  259.  
  260.         mov     [ext2_data.inode_size], ebp
  261.         mov     [ext2_data.blocks_per_group], ecx
  262.  
  263.         push    ebp ebp ebp                             ;3 kernel_alloc
  264.         call    kernel_alloc
  265.         mov     [ext2_data.ext2_save_inode], eax
  266.         call    kernel_alloc
  267.         mov     [ext2_data.ext2_temp_inode], eax
  268.         call    kernel_alloc
  269.         mov     [ext2_data.root_inode], eax
  270.  
  271.         mov     ebx, eax
  272.         mov     eax, EXT2_ROOT_INO
  273.         call    ext2_get_inode                          ; read root inode
  274.  
  275.         jmp     return_from_part_set
  276.  
  277. ;==================================================================
  278. ;read ext2 block form FS to memory
  279. ;in:  eax = i_block (address of block in ext2 terms)
  280. ;     ebx = pointer to return memory
  281. ;out: eax - error code (0 = no_error)
  282. ext2_get_block:
  283.         push    ebx ecx
  284.         mov     ecx, [ext2_data.log_block_size]
  285.         shl     eax, cl
  286.         add     eax, [PARTITION_START]
  287.         mov     ecx, [ext2_data.count_block_in_block]
  288.     @@:
  289.         call    hd_read
  290.         cmp     [hd_error], 0
  291.         jnz     .fail
  292.         inc     eax
  293.         add     ebx, 512
  294.         loop    @B
  295.         xor     eax, eax
  296.     @@:
  297.         pop     ecx ebx
  298.         ret
  299.     .fail:
  300.         mov     eax, ERROR_DEVICE
  301.         jmp     @B
  302.        
  303.  
  304. ;===================================================================
  305. ;RUS: получает номер блока из extent inode                    ;ENG: receives block number from extent inode
  306. ;RUS: in:  ecx = номер блока по порядку                       ;ENG: in:  ecx = consecutive block number
  307. ;RUS:      ebp = адрес extent header`а                        ;ENG:      ebp = address of extent header
  308. ;RUS: out: ecx - адрес очередного блока в случае успеха       ;ENG: out: ecx - address of next block, if successful
  309. ;RUS:      eax - номер ошибки (если равно 0, то ошибки нет)   ;ENG:      eax - error number (0 - no error)
  310. ext4_block_recursive_search:
  311.         cmp     word [ebp + EXT4_EXTENT_HEADER.eh_magic], 0xF30A ;EXT4_EXT_MAGIC
  312.         jne     .fail
  313.        
  314.         movzx   ebx, [ebp + EXT4_EXTENT_HEADER.eh_entries]
  315.         add     ebp, sizeof.EXT4_EXTENT_HEADER
  316.         cmp     word [ebp - sizeof.EXT4_EXTENT_HEADER + EXT4_EXTENT_HEADER.eh_depth], 0
  317.         je      .leaf_block     ;листовой ли это блок?
  318.        
  319.         ;не листовой блок, а индексный ; eax - ext4_extent_idx
  320.         test    ebx, ebx
  321.         jz      .fail               ;пустой индексный блок -> ошибка
  322.  
  323.         ;цикл по индексам экстентов
  324.     @@:
  325.         cmp     ebx, 1              ;у индексов не хранится длина,
  326.         je      .end_search_index   ;поэтому, если остался последний - то это нужный
  327.        
  328.         cmp     ecx, [ebp + EXT4_EXTENT_IDX.ei_block]
  329.         jb      .fail
  330.        
  331.         cmp     ecx, [ebp + sizeof.EXT4_EXTENT_IDX + EXT4_EXTENT_IDX.ei_block] ;блок слeдующего индекса
  332.         jb      .end_search_index ;следующий дальше - значит текущий, то что нам нужен
  333.        
  334.         add     ebp, sizeof.EXT4_EXTENT_IDX
  335.         dec     ebx
  336.         jmp     @B
  337.        
  338.     .end_search_index:
  339.         ;ebp указывает на нужный extent_idx, считываем следующий блок
  340.         mov     ebx, [ext2_data.ext2_temp_block]
  341.         mov     eax, [ebp + EXT4_EXTENT_IDX.ei_leaf_lo]
  342.         call    ext2_get_block
  343.         test    eax, eax
  344.         jnz     .fail
  345.         mov     ebp, ebx
  346.         jmp     ext4_block_recursive_search ;рекурсивно прыгаем в начало
  347.        
  348.     .leaf_block:    ;листовой блок ebp - ext4_extent
  349.         ;цикл по экстентам
  350.     @@:
  351.         test    ebx, ebx
  352.         jz      .fail       ;ни один узел не подошел - ошибка
  353.  
  354.         mov     edx, [ebp + EXT4_EXTENT.ee_block]
  355.         cmp     ecx, edx
  356.         jb      .fail       ;если меньше, значит он был в предыдущих блоках -> ошибка
  357.  
  358.         movzx   edi, [ebp + EXT4_EXTENT.ee_len]
  359.         add     edx, edi
  360.         cmp     ecx, edx
  361.         jb      .end_search_extent     ;нашли нужный блок
  362.        
  363.         add     ebp, sizeof.EXT4_EXTENT
  364.         dec     ebx
  365.         jmp     @B
  366.        
  367.     .end_search_extent:
  368.         mov     edx, [ebp + EXT4_EXTENT.ee_start_lo]
  369.         sub     ecx, [ebp + EXT4_EXTENT.ee_block] ;разница в ext4 блоках
  370.         add     ecx, edx
  371.         xor     eax, eax
  372.         ret
  373.  
  374.     .fail:
  375.         mov     eax, ERROR_FS_FAIL
  376.         ret
  377.  
  378. ;===================================================================
  379. ;получает адрес ext2 блока из inode с определнным номером
  380. ;RUS: in:  ecx = номер блока в inode (0..)   ;ENG: in:  ecx = number of block in inode (0..)
  381. ;RUS:      ebp = адрес inode                 ;ENG:      ebp = inode address
  382. ;RUS: out: ecx = адрес очередного блока      ;ENG: out: ecx = next block address
  383. ;RUS:      eax - error code                  ;ENG:      eax - error code
  384. ext2_get_inode_block:
  385.         test    [ebp + EXT2_INODE_STRUC.i_flags], EXT2_EXTENTS_FL
  386.         jz      @F
  387.  
  388.         pushad
  389.         add     ebp, EXT2_INODE_STRUC.i_block             ;ebp - extent_header
  390.         call    ext4_block_recursive_search
  391.         mov     PUSHAD_ECX, ecx
  392.         mov     PUSHAD_EAX, eax
  393.         popad
  394.         ret
  395.  
  396.     @@:
  397.         cmp     ecx, 12                                         ; 0..11 - direct block address
  398.         jb      .get_direct_block
  399.  
  400.         sub     ecx, 12
  401.         cmp     ecx, [ext2_data.count_pointer_in_block]         ; 12.. - indirect blocks
  402.         jb      .get_indirect_block
  403.  
  404.         sub     ecx, [ext2_data.count_pointer_in_block]
  405.         cmp     ecx, [ext2_data.count_pointer_in_block_square]
  406.         jb      .get_double_indirect_block
  407.  
  408.         sub     ecx, [ext2_data.count_pointer_in_block_square]
  409.     ;triple indirect block
  410.         push    edx ebx
  411.  
  412.         mov     eax, [ebx + EXT2_INODE_STRUC.i_block + 14*4]
  413.         mov     ebx, [ext2_data.ext2_temp_block]
  414.         call    ext2_get_block
  415.         test    eax, eax
  416.         jnz     .fail
  417.  
  418.         xor     edx, edx
  419.         mov     eax, ecx
  420.         div     [ext2_data.count_pointer_in_block_square]
  421.  
  422.     ;RUS: eax - номер в полученном блоке   edx - номер дальше
  423.     ;ENG: eax - current block number, edx - next block number
  424.         mov     eax, [ebx + eax*4]
  425.         call    ext2_get_block
  426.         test    eax, eax
  427.         jnz     .fail
  428.  
  429.         mov     eax, edx
  430.         jmp     @F
  431.  
  432.     .get_double_indirect_block:
  433.         push    edx ebx
  434.  
  435.         mov     eax, [ebp + EXT2_INODE_STRUC.i_block + 13*4]
  436.         mov     ebx, [ext2_data.ext2_temp_block]
  437.         call    ext2_get_block
  438.         test    eax, eax
  439.         jnz     .fail
  440.  
  441.         mov     eax, ecx
  442.     @@:
  443.         xor     edx, edx
  444.         div     [ext2_data.count_pointer_in_block]
  445.  
  446.         mov     eax, [ebx + eax*4]
  447.         call    ext2_get_block
  448.         test    eax, eax
  449.         jnz     .fail
  450.  
  451.         mov     ecx, [ebx + edx*4]
  452.     .fail:
  453.         pop     ebx edx
  454.         ret
  455.  
  456.     .get_indirect_block:
  457.         push    ebx
  458.         mov     eax, [ebp + EXT2_INODE_STRUC.i_block + 12*4]
  459.         mov     ebx, [ext2_data.ext2_temp_block]
  460.         call    ext2_get_block
  461.         test    eax, eax
  462.         jnz     @F          ;RUS: если не было ошибки   ;ENG: if there was no error
  463.  
  464.         mov     ecx, [ebx + ecx*4]   ;RUS: заносим результат   ;ENG: ???
  465.     @@:
  466.         pop     ebx
  467.         ret
  468.  
  469.     .get_direct_block:
  470.         mov     ecx, [ebp + EXT2_INODE_STRUC.i_block + ecx*4]
  471.         xor     eax, eax
  472.         ret
  473.  
  474. ;===================================================================
  475. ;get content inode by num
  476. ;in:  eax = inode_num
  477. ;     ebx = address of inode content
  478. ;out: eax - error code
  479. ext2_get_inode:
  480.         pushad
  481.         mov     edi, ebx   ;сохраним адрес inode
  482.         dec     eax
  483.         xor     edx, edx
  484.        
  485.         mov     ecx, [ext2_data.sb]
  486.         div     [ecx + EXT2_SB_STRUC.inodes_per_group]
  487.  
  488.         push    edx                             ;locale num in group
  489.  
  490.         mov     edx, 32
  491.         mul     edx                             ; address block_group in global_desc_table
  492.  
  493.         ;RUS: в eax - смещение группы с inode-ом относительно начала глобальной дескрипторной таблицы
  494.         ;RUS: найдем блок в котором он находится
  495.         ;ENG: in eax - inode group offset relative to global descriptor table start
  496.         ;ENG: let's find the block this inode is in
  497.         div     [ext2_data.block_size]
  498.         add     eax, [ecx + EXT2_SB_STRUC.first_data_block]
  499.         inc     eax
  500.         mov     ebx, [ext2_data.ext2_temp_block]
  501.         call    ext2_get_block
  502.         test    eax, eax
  503.         jnz     .fail    
  504.  
  505.         add     ebx, edx   ;RUS: локальный номер в блоке   ;ENG: local number inside block
  506.         mov     eax, [ebx + EXT2_BLOCK_GROUP_DESC.inode_table]   ;RUS: номер блока - в терминах ext2
  507.                                                                  ;ENG: block number - in ext2 terms
  508.         mov     ecx, [ext2_data.log_block_size]
  509.         shl     eax, cl
  510.         add     eax, [PARTITION_START]          ;RUS: а старт раздела - в терминах hdd (512)
  511.                                                 ;ENG: partition start - in HDD terms (512)
  512.         ;RUS: eax - указывает на таблицу inode-ов на hdd   ;ENG: eax - points to inode table on HDD
  513.         mov     esi, eax   ;RUS: сохраним его пока в esi   ;ENG: let's save it in esi for now
  514.  
  515.         ;RUS: прибавим локальный адрес inode-а   ;ENG: add local address of inode
  516.         pop     eax                             ; index
  517.         mov     ecx, [ext2_data.inode_size]
  518.         mul     ecx                             ; (index * inode_size)
  519.         mov     ebp, 512
  520.         div     ebp        ;RUS: поделим на размер блока        ;ENG: divide by block size
  521.  
  522.         add     eax, esi   ;RUS: нашли адрес блока для чтения   ;ENG: found block address to read
  523.         mov     ebx, [ext2_data.ext2_temp_block]
  524.         call    hd_read
  525.         cmp     [hd_error], 0
  526.         jnz     .fail
  527.  
  528.         mov     esi, edx         ;RUS: добавим "остаток"   ;ENG: add the "remainder"
  529.         add     esi, ebx         ;RUS: к адресу            ;ENG: to the address
  530.         rep movsb                ;RUS: копируем inode      ;ENG: copy inode
  531.         xor     eax, eax
  532.     .fail:
  533.         mov     PUSHAD_EAX, eax
  534.         popad
  535.         ret
  536.  
  537. ;----------------------------------------------------------------
  538. ;
  539. ;  ext2_HdReadFolder - read disk folder
  540. ;
  541. ;  esi  points to filename
  542. ;  ebx  pointer to structure 32-bit number = first wanted block, 0+
  543. ;                          & flags (bitfields)
  544. ; flags: bit 0: 0=ANSI names, 1=UNICODE names
  545. ;  ecx  number of blocks to read, 0+
  546. ;  edx  mem location to return data
  547. ;
  548. ;  ret ebx = blocks read or 0xffffffff folder not found
  549. ;      eax = 0 ok read or other = errormsg
  550. ;
  551. ;--------------------------------------------------------------
  552. ext2_HdReadFolder:
  553.         cmp     byte [esi], 0
  554.         jz      .root_folder
  555.  
  556.         push    ebx ecx edx
  557.         call    ext2_find_lfn               ;вернет в ebp адрес inode
  558.         pop     edx ecx ebx
  559.         test    eax, eax
  560.         jnz     .error_ret
  561.         test    [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
  562.         jz      .error_not_found
  563.         jmp     @F
  564.  
  565.     .root_folder:
  566.         mov     ebp, [ext2_data.root_inode]
  567.         test    [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
  568.         jz      .error_root
  569.         ;придется копировать inode
  570.         push    ecx
  571.         mov     esi, ebp
  572.         mov     edi, [ext2_data.ext2_save_inode]
  573.         mov     ecx, [ext2_data.inode_size]
  574.         shr     ecx, 2
  575.         mov     ebp, edi
  576.         rep movsd
  577.         pop     ecx
  578.     @@:
  579.         cmp     [ebp + EXT2_INODE_STRUC.i_size], 0 ;папка пуста
  580.         je      .error_empty_dir
  581.        
  582.         push    edx      ;адрес результата              [edi + 28]
  583.         push    0        ;конец очередного блока папки   [edi + 24]
  584.         push    ecx      ;сколько файлов нужно прочитать [edi + 20]
  585.         push    dword [ebx]   ;первый "нужный" файл           [edi + 16]
  586.         push    dword [ebx + 4];флаги                        [edi + 12]
  587.         push    0       ;[EXT2_read_in_folder]     [edi + 8]
  588.         push    0       ;[EXT2_files_in_folder]    [edi + 4]
  589.         push    0       ;номер блока по порядку    [edi]
  590.  
  591.         mov     edi, edx
  592.         mov     ecx, 32/4
  593.         rep stosd                               ; fill header zero
  594.        
  595.         mov     edi, esp                        ; edi - указатель на локальные переменные
  596.         add     edx, 32                         ; edx = current mem for return
  597.  
  598.         xor     ecx, ecx                        ; получим номер первого блока
  599.         call    ext2_get_inode_block
  600.         test    eax, eax
  601.         jnz     .error_get_block
  602.  
  603.         mov     eax, ecx
  604.         mov     ebx, [ext2_data.ext2_save_block]
  605.         call    ext2_get_block                  ; и считываем блок с hdd
  606.         test    eax, eax
  607.         jnz     .error_get_block
  608.  
  609.         mov     esi, ebx                         ; esi = current dir record
  610.         add     ebx, [ext2_data.block_size]
  611.         mov     [edi + 24], ebx               ; запомним конец очередного блока
  612.  
  613.         mov     ecx, [edi + 16]                        ; ecx = first wanted (flags ommited)
  614.  
  615.     .find_wanted_start:
  616.         jecxz   .find_wanted_end
  617.     .find_wanted_cycle:
  618.         cmp     [esi + EXT2_DIR_STRUC.inode], 0     ; if (inode = 0) => not used
  619.         jz      @F
  620.         inc     dword [edi + 4]                        ; EXT2_files_in_folder
  621.         dec     ecx
  622.     @@:
  623.         movzx   ebx, [esi + EXT2_DIR_STRUC.rec_len]
  624.  
  625.         cmp     ebx, 12                                 ; минимальная длина записи
  626.         jb      .error_bad_len
  627.         test    ebx, 0x3                                ; длина записи должна делиться на 4
  628.         jnz     .error_bad_len
  629.  
  630.         sub     [ebp + EXT2_INODE_STRUC.i_size], ebx    ;вычитаем напрямую из структуры inode
  631.         add     esi, ebx                                ; к следующей записи
  632.         cmp     esi, [edi + 24]                        ; сравниваем с концом блока
  633.         jb      .find_wanted_start
  634.  
  635.         push    .find_wanted_start
  636.    .end_block:                                              ;вылетели из цикла
  637.         cmp     [ebp + EXT2_INODE_STRUC.i_size], 0
  638.         jle     .end_dir
  639.  
  640.         inc     dword [edi]                                 ;получаем новый блок
  641.         push    ecx
  642.         mov     ecx, [edi]
  643.         call    ext2_get_inode_block
  644.         test    eax, eax
  645.         jnz     .error_get_block
  646.  
  647.         mov     eax, ecx
  648.         mov     ebx, [ext2_data.ext2_save_block]
  649.         call    ext2_get_block
  650.         test    eax, eax
  651.         jnz     .error_get_block
  652.  
  653.         pop     ecx
  654.         mov     esi, ebx
  655.         add     ebx, [ext2_data.block_size]
  656.         mov     [edi + 24], ebx                            ;запомним конец блока
  657.         ret                                                 ; опять в цикл
  658.  
  659.     .wanted_end:
  660.         loop    .find_wanted_cycle                          ; ecx 0 => -1 нужно посчитать сколько файлов
  661.  
  662.     ;дошли до первого "нужного" файла
  663.     .find_wanted_end:
  664.         mov     ecx, [edi + 20]
  665.     .wanted_start:                                          ; ищем first_wanted+count
  666.         jecxz   .wanted_end
  667.         cmp     [esi + EXT2_DIR_STRUC.inode], 0         ; if (inode = 0) => not used
  668.         jz      .empty_rec
  669.         inc     dword [edi + 8]
  670.         inc     dword [edi + 4]
  671.  
  672.         push    edi ecx
  673.         mov     edi, edx                            ;обнуляем место под очереное имя файла/папки
  674.         xor     eax, eax
  675.         mov     ecx, 40 / 4
  676.         rep stosd
  677.         pop     ecx edi
  678.  
  679.         push    esi edi edx
  680.         mov     eax, [esi + EXT2_DIR_STRUC.inode]             ;получим дочерний inode
  681.         mov     ebx, [ext2_data.ext2_temp_inode]
  682.         call    ext2_get_inode
  683.         test    eax, eax
  684.         jnz     .error_read_subinode
  685.  
  686.         lea     edi, [edx + 8]
  687.  
  688.         mov     eax, [ebx + EXT2_INODE_STRUC.i_ctime]           ; переведем время в ntfs формат
  689.         xor     edx, edx
  690.         add     eax, 3054539008                                     ;(369 * 365 + 89) * 24 * 3600
  691.         adc     edx, 2
  692.         call    ntfs_datetime_to_bdfe.sec
  693.  
  694.         mov     eax, [ebx + EXT2_INODE_STRUC.i_atime]
  695.         xor     edx, edx
  696.         add     eax, 3054539008
  697.         adc     edx, 2
  698.         call    ntfs_datetime_to_bdfe.sec
  699.  
  700.         mov     eax, [ebx + EXT2_INODE_STRUC.i_mtime]
  701.         xor     edx, edx
  702.         add     eax, 3054539008
  703.         adc     edx, 2
  704.         call    ntfs_datetime_to_bdfe.sec
  705.  
  706.         pop     edx                                                 ; пока достаем только буфер
  707.         test    [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR   ; для папки размер
  708.         jnz     @F                                                  ; не возвращаем
  709.  
  710.         mov     eax, [ebx + EXT2_INODE_STRUC.i_size]            ;low size
  711.         stosd
  712.         mov     eax, [ebx + EXT2_INODE_STRUC.i_dir_acl]         ;high size
  713.         stosd
  714.         xor     dword [edx], FS_FT_DIR                              ;помечаем, что это файл(2 раза xor)
  715.     @@:
  716.         xor     dword [edx], FS_FT_DIR                              ;помечаем, что это файл
  717.  
  718.         ;теперь скопируем имя, сконвертировав из UTF-8 в CP866
  719.         push    ecx  ;edi и esi уже сохранены в стеке
  720.         movzx   ecx, [esi + EXT2_DIR_STRUC.name_len]
  721.         lea     edi, [edx + 40]
  722.         lea     esi, [esi + EXT2_DIR_STRUC.name]
  723.         call    utf8_to_cp866
  724.         and     byte [edi], 0
  725.         pop     ecx edi esi
  726.  
  727.         cmp     byte [edx + 40], '.'                    ; в linux файл, начинающийся с точки - скрытый
  728.         jne     @F
  729.         or      dword [edx], FS_FT_HIDDEN
  730.     @@:
  731.  
  732.         add     edx, 40 + 264                           ; go to next record
  733.         dec     ecx                                     ; если запись пустая ecx не надо уменьшать
  734.     .empty_rec:
  735.         movzx   ebx, [esi + EXT2_DIR_STRUC.rec_len]
  736.         cmp     ebx, 12                                 ; минимальная длина записи
  737.         jb      .error_bad_len
  738.         test    ebx, 0x3                                ; длина записи должна делиться на 4
  739.         jnz     .error_bad_len
  740.  
  741.         sub     [ebp + EXT2_INODE_STRUC.i_size], ebx    ;вычитаем напрямую из структуры inode
  742.         add     esi, ebx
  743.         cmp     esi, [edi + 24]                         ;дошли ли до конца блока?
  744.         jb      .wanted_start
  745.  
  746.         push    .wanted_start                           ; дошли
  747.         jmp     .end_block
  748.  
  749.     .end_dir:   ;конец папки, когда еще не дошли до нужного файла
  750.         mov     edx, [edi + 28] ;адрес структуры результата
  751.         mov     ebx, [edi + 8] ;EXT2_read_in_folder
  752.         mov     ecx, [edi + 4] ;EXT2_files_in_folder
  753.         mov     dword [edx], 1    ;version
  754.         mov     [edx + 4], ebx
  755.         mov     [edx + 8], ecx
  756.        
  757.         lea     esp, [edi + 32]
  758.        
  759.         xor     eax, eax        ;RUS: зарезервировано: нули в текущей реализации
  760.                                 ;ENG: reserved: zeros in current implementation
  761.         lea     edi, [edx + 12]
  762.         mov     ecx, 20 / 4
  763.         rep stosd
  764.         ret
  765.  
  766.     .error_bad_len:
  767.         mov     eax, ERROR_FS_FAIL
  768.     .error_read_subinode:
  769.     .error_get_block:
  770.         lea     esp, [edi + 32]
  771.     .error_ret:
  772.         or      ebx, -1
  773.         ret
  774.        
  775.     .error_empty_dir:   ;RUS: inode папки без блоков   ;ENG: inode of folder without blocks
  776.     .error_root:        ;RUS: root - не папка          ;ENG: root is not a folder
  777.         mov     eax, ERROR_FS_FAIL
  778.         jmp     .error_ret
  779.  
  780.     .error_not_found:   ;RUS: файл не найден           ;ENG: file not found
  781.         mov     eax, ERROR_FILE_NOT_FOUND
  782.         jmp     .error_ret
  783.            
  784. ;============================================
  785. ;convert UTF-8 string to ASCII-string (codepage 866)
  786. ;in:  ecx = length source
  787. ;     esi = source
  788. ;     edi = buffer
  789. ; destroys: eax,esi,edi
  790. utf8_to_cp866:
  791.         jecxz   .ret
  792.     .start:
  793.         lodsw
  794.         cmp     al, 0x80
  795.         jb      .ascii
  796.  
  797.         xchg    al, ah              ; big-endian
  798.         cmp     ax, 0xd080
  799.         jz      .yo1
  800.         cmp     ax, 0xd191
  801.         jz      .yo2
  802.         cmp     ax, 0xd090
  803.         jb      .unk
  804.         cmp     ax, 0xd180
  805.         jb      .rus1
  806.         cmp     ax, 0xd190
  807.         jb      .rus2
  808.     .unk:
  809.         mov     al, '_'
  810.         jmp     .doit
  811.     .yo1:
  812.         mov     al, 0xf0    ; Ё capital
  813.         jmp     .doit
  814.     .yo2:
  815.         mov     al, 0xf1    ; ё small
  816.         jmp     .doit
  817.     .rus1:
  818.         sub     ax, 0xd090 - 0x80
  819.         jmp     .doit
  820.     .rus2:
  821.         sub     ax, 0xd18f - 0xEF
  822.     .doit:
  823.         stosb
  824.         sub     ecx, 2
  825.         ja      .start
  826.         ret
  827.  
  828.     .ascii:
  829.         stosb
  830.         dec     esi
  831.         dec     ecx
  832.         jnz     .start
  833.     .ret:
  834.         ret
  835.  
  836. ;----------------------------------------------------------------
  837. ;
  838. ;  ext2_HdRead - read hard disk
  839. ;
  840. ;  esi  points to filename
  841. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  842. ;       may be ebx=0 - start from first byte
  843. ;  ecx  number of bytes to read, 0+
  844. ;  edx  mem location to return data
  845. ;
  846. ;  ret ebx = bytes read or 0xffffffff file not found
  847. ;      eax = 0 ok read or other = errormsg
  848.  
  849. ;--------------------------------------------------------------
  850. ext2_HdRead:
  851.         cmp     byte [esi], 0
  852.         jnz     @F
  853.  
  854.     .this_is_nofile:
  855.         or      ebx, -1
  856.         mov     eax, ERROR_ACCESS_DENIED
  857.         ret
  858.  
  859.     @@:
  860.         push    ecx ebx edx
  861.         call    ext2_find_lfn
  862.         pop     edx ebx ecx
  863.         test    eax, eax
  864.         jz      @F
  865.  
  866.         or      ebx, -1
  867.         mov     eax, ERROR_FILE_NOT_FOUND
  868.         ret
  869.  
  870.     @@:
  871.         mov     ax, [ebp + EXT2_INODE_STRUC.i_mode]
  872.         and     ax, EXT2_S_IFMT     ;оставляем только тип inode в ax
  873.         cmp     ax, EXT2_S_IFREG
  874.         jne     .this_is_nofile
  875.  
  876.         mov     edi, edx            ; edi = pointer to return mem
  877.  
  878.         test    ebx, ebx
  879.         jz      @F
  880.         mov     esi, ebx            ; esi = pointer to first_wanted
  881.         mov     ebx, [esi+4]
  882.         mov     eax, [esi]    ;RUS: ebx : eax - стартовый номер байта   ;ENG: ebx : eax - start byte number
  883.  
  884.         ;RUS: ///// сравним хватит ли нам файла или нет    ;ENG: ///// check if file is big enough for us
  885.         cmp     [ebp + EXT2_INODE_STRUC.i_dir_acl], ebx
  886.         ja      .size_great
  887.         jb      .size_less
  888.  
  889.         cmp     [ebp + EXT2_INODE_STRUC.i_size], eax
  890.         ja      .size_great
  891.  
  892.     .size_less:
  893.         xor     ebx, ebx
  894.         mov     eax, ERROR_END_OF_FILE
  895.         ret
  896.        
  897.     @@:
  898.         xor     ebx, ebx
  899.         xor     eax, eax
  900.     .size_great:
  901.         add     eax, ecx    ;RUS: add to first_wanted кол-во байт для чтения
  902.                             ;ENG: add to first_wanted number of bytes to read
  903.         adc     ebx, 0
  904.  
  905.         cmp     [ebp + EXT2_INODE_STRUC.i_dir_acl], ebx
  906.         ja      .size_great_great
  907.         jb      .size_great_less
  908.         cmp     [ebp + EXT2_INODE_STRUC.i_size], eax
  909.         jae     .size_great_great   ; and if it's equal, no matter where we jump
  910.  
  911.     .size_great_less:
  912.         push    1            ;RUS: читаем по границе размера   ;ENG: reading till the end of file
  913.         mov     ecx, [ebp + EXT2_INODE_STRUC.i_size]
  914.         sub     ecx, [esi]   ;RUS: (размер - старт) = сколько читать   ;ENG: to read = (size - start)
  915.         jmp     @F
  916.  
  917.     .size_great_great:
  918.         push    0            ;RUS: читаем столько, сколько запросили   ;ENG: reading as much as requested
  919.  
  920.     @@:
  921.         ;здесь мы точно знаем сколько байт читать - ecx
  922.         ;edi - return memory
  923.         ;esi -> first wanted
  924.  
  925.         push    ecx                             ;количество считанных байт
  926.         test    esi, esi
  927.         jz      .zero_start
  928.  
  929.         ;получим кусок из первого блока
  930.         mov     edx, [esi+4]
  931.         mov     eax, [esi]
  932.         div     [ext2_data.block_size]
  933.  
  934.         push    eax       ;счетчик блоков ложим в стек
  935.        
  936.         push    ecx
  937.         mov     ecx, eax
  938.         call    ext2_get_inode_block
  939.         test    eax, eax
  940.         jnz     .error_at_first_block
  941.         mov     ebx, [ext2_data.ext2_save_block]
  942.         mov     eax, ecx
  943.         call    ext2_get_block
  944.         test    eax, eax
  945.         jnz     .error_at_first_block
  946.         pop     ecx
  947.         add     ebx, edx
  948.  
  949.         neg     edx
  950.         add     edx, [ext2_data.block_size]     ;RUS: block_size - стартовый байт = сколько байт 1-го блока
  951.                                                 ;ENG: block_size - start byte = number of bytes in 1st block
  952.         cmp     ecx, edx
  953.         jbe     .only_one_block
  954.  
  955.         mov     eax, ecx
  956.         sub     eax, edx
  957.         mov     ecx, edx
  958.  
  959.         mov     esi, ebx
  960.         rep movsb                               ;RUS: кусок 1-го блока   ;ENG: part of 1st block
  961.         jmp     .calc_blocks_count
  962.  
  963.     .zero_start:
  964.         mov     eax, ecx
  965.         push    0                               ;счетчик блоков ложим в стек
  966.         ;теперь в eax кол-во оставшихся байт для чтения
  967.     .calc_blocks_count:
  968.         mov     ebx, edi                        ;чтение блока прям в ->ebx
  969.         xor     edx, edx
  970.         div     [ext2_data.block_size]       ;кол-во байт в последнем блоке (остаток) в edx
  971.         mov     edi, eax                        ;кол-во целых блоков в edi
  972.     @@:
  973.         test    edi, edi
  974.         jz      .finish_block
  975.         inc     dword [esp]
  976.         mov     ecx, [esp]
  977.         call    ext2_get_inode_block
  978.         test    eax, eax
  979.         jnz     .error_at_read_cycle
  980.  
  981.         mov     eax, ecx                        ;а ebx уже забит нужным значением
  982.         call    ext2_get_block
  983.         test    eax, eax
  984.         jnz     .error_at_read_cycle
  985.         add     ebx, [ext2_data.block_size]
  986.  
  987.         dec     edi
  988.         jmp     @B
  989.  
  990.     .finish_block:          ;в edx - кол-во байт в последнем блоке
  991.         test    edx, edx
  992.         jz      .end_read
  993.  
  994.         pop     ecx         ;счетчик блоков -> ecx
  995.         inc     ecx
  996.         call    ext2_get_inode_block
  997.         test    eax, eax
  998.         jnz     .error_at_finish_block
  999.  
  1000.         mov     edi, ebx
  1001.         mov     eax, ecx
  1002.         mov     ebx, [ext2_data.ext2_save_block]
  1003.         call    ext2_get_block
  1004.         test    eax, eax
  1005.         jnz     .error_at_finish_block
  1006.  
  1007.         mov     ecx, edx
  1008.         mov     esi, ebx
  1009.         rep movsb                               ;кусок last блока
  1010.         jmp     @F
  1011.  
  1012.     .end_read:
  1013.         pop     ecx                             ;счетчик блоков, который хранился в стеке
  1014.     @@:
  1015.         pop     ebx                             ;количество считанных байт
  1016.         pop     eax                             ; 1 или 0 - достигли ли конца файла
  1017.         test    eax, eax
  1018.         jz      @F
  1019.  
  1020.         mov     eax, ERROR_END_OF_FILE
  1021.         ret
  1022.     @@:
  1023.         xor     eax, eax
  1024.         ret
  1025.        
  1026.     .only_one_block:
  1027.         mov     esi, ebx
  1028.         rep movsb                               ;кусок last блока
  1029.         jmp     .end_read
  1030.        
  1031.    .error_at_first_block:
  1032.         pop     edx
  1033.    .error_at_read_cycle:
  1034.         pop     ebx
  1035.    .error_at_finish_block:
  1036.         pop     ecx edx
  1037.         or      ebx, -1
  1038.         ret
  1039.  
  1040. ;----------------------------------------------------------------
  1041. ; in:  esi = file path
  1042. ;      ebx = pointer to dir block
  1043. ; out: esi - name without parent or not_changed
  1044. ;      ebx - dir_rec of inode children
  1045. ext2_test_block_by_name:
  1046.         sub     esp, 256        ;EXT2_filename
  1047.         mov     edx, ebx
  1048.         add     edx, [ext2_data.block_size]   ;RUS: запомним конец блока   ;ENG: save block end
  1049.  
  1050.     .start_rec:
  1051.         cmp     [ebx + EXT2_DIR_STRUC.inode], 0
  1052.         jz      .next_rec
  1053.  
  1054.         mov     edi, esp
  1055.         push    esi
  1056.         movzx   ecx, [ebx + EXT2_DIR_STRUC.name_len]
  1057.         lea     esi, [ebx + EXT2_DIR_STRUC.name]
  1058.         call    utf8_to_cp866
  1059.  
  1060.         mov     ecx, edi
  1061.         lea     edi, [esp + 4]
  1062.         sub     ecx, edi   ;RUS: кол-во байт в получившейся строке   ;ENG: number of bytes in resulting string
  1063.  
  1064.         mov     esi, [esp]
  1065.     @@:
  1066.         jecxz   .test_find
  1067.         dec     ecx
  1068.  
  1069.         lodsb
  1070.         call    char_toupper
  1071.  
  1072.         mov     ah, [edi]
  1073.         inc     edi
  1074.         xchg    al, ah
  1075.         call    char_toupper
  1076.         cmp     al, ah
  1077.         je      @B
  1078.     @@:                           ;RUS: не подошло   ;ENG: didn't fit
  1079.         pop     esi
  1080.     .next_rec:
  1081.         movzx   eax, [ebx + EXT2_DIR_STRUC.rec_len]
  1082.         add     ebx, eax          ;RUS: к след. записи      ;ENG: go to next record
  1083.         cmp     ebx, edx          ;RUS: проверим конец ли   ;ENG: check if this is the end
  1084.         jb      .start_rec
  1085.         add     esp, 256
  1086.         ret
  1087.  
  1088.     .test_find:
  1089.         cmp     byte [esi], 0
  1090.         je      .ret              ;RUS: нашли конец         ;ENG: the end reached
  1091.         cmp     byte [esi], '/'
  1092.         jne     @B
  1093.         inc     esi
  1094.     .ret:
  1095.         add     esp, 256 + 4
  1096.         ret
  1097.  
  1098. ;========================
  1099. ;Ищет inode по строке пути
  1100. ;in:  esi = name
  1101. ;out: eax - error code
  1102. ;     ebp = inode
  1103. ;      dl - первый байт из имени файла/папки
  1104. ext2_find_lfn:
  1105.         mov     ebp, [ext2_data.root_inode]
  1106.         cmp     [ebp + EXT2_INODE_STRUC.i_blocks], 0
  1107.         je      .error_empty_root
  1108.        
  1109.     .next_path_part:
  1110.         push    [ebp + EXT2_INODE_STRUC.i_blocks]
  1111.         xor     ecx, ecx
  1112.     .folder_block_cycle:
  1113.         push    ecx
  1114.         call    ext2_get_inode_block
  1115.         test    eax, eax
  1116.         jnz     .error_get_inode_block
  1117.        
  1118.         mov     eax, ecx
  1119.         mov     ebx, [ext2_data.ext2_save_block]        ;ebx = cur dir record
  1120.         call    ext2_get_block
  1121.         test    eax, eax
  1122.         jnz     .error_get_block
  1123.        
  1124.         push    esi
  1125.         call    ext2_test_block_by_name
  1126.         pop     edi ecx
  1127.  
  1128.         cmp     edi, esi             ;RUS: нашли имя?   ;ENG: did we find a name?
  1129.         je      .next_folder_block   ;RUS: не нашли -> к след. блоку   ;ENG: we didn't -> moving to next block
  1130.        
  1131.         cmp     byte [esi], 0   ;RUS: дошли до "конца" пути -> возваращаемся
  1132.                                 ;ENG: reached the "end" of path -> returning
  1133.         jz      .get_inode_ret
  1134.  
  1135.         cmp     [ebx + EXT2_DIR_STRUC.file_type], EXT2_FT_DIR   ;RUS: нашли, но это не папка
  1136.         jne     .not_found                                      ;ENG: found, but it's not a folder
  1137.  
  1138.         mov     eax, [ebx + EXT2_DIR_STRUC.inode]
  1139.         mov     ebx, [ext2_data.ext2_save_inode]   ;RUS: все же папка.   ;ENG: it's a folder afterall
  1140.         call    ext2_get_inode
  1141.         test    eax, eax
  1142.         jnz     .error_get_inode
  1143.         pop     ecx   ;RUS: в стеке лежит кол-во блоков   ;ENG: stack top contains number of blocks
  1144.         mov     ebp, ebx
  1145.         jmp     .next_path_part
  1146.        
  1147.     .next_folder_block:
  1148.         ;к следующему блоку в текущей папке
  1149.         pop     eax                ;RUS: счетчик блоков   ;ENG: blocks counter
  1150.         sub     eax, [ext2_data.count_block_in_block]
  1151.         jle     .not_found
  1152.        
  1153.         push    eax
  1154.         inc     ecx
  1155.         jmp     .folder_block_cycle
  1156.  
  1157.     .not_found:
  1158.         mov     eax, ERROR_FILE_NOT_FOUND
  1159.         ret
  1160.  
  1161.     .get_inode_ret:
  1162.         pop     ecx   ;RUS: в стеке лежит кол-во блоков   ;ENG: stack top contains number of blocks
  1163.         mov     dl, [ebx + EXT2_DIR_STRUC.name]   ;RUS: в dl - первый символ ()   ;ENG: ???
  1164.         mov     eax, [ebx + EXT2_DIR_STRUC.inode]
  1165.         mov     ebx, [ext2_data.ext2_save_inode]
  1166.         call    ext2_get_inode
  1167.         mov     ebp, ebx
  1168.         xor     eax, eax
  1169.         ret
  1170.  
  1171.     .error_get_inode_block:
  1172.     .error_get_block:
  1173.         pop     ecx
  1174.     .error_get_inode:
  1175.         pop     ebx
  1176.     .error_empty_root:
  1177.         mov     eax, ERROR_FS_FAIL
  1178.         ret
  1179.  
  1180. ;----------------------------------------------------------------
  1181. ;ext2_HdGetFileInfo - read file info from block device
  1182. ;
  1183. ;in: esi  points to filename
  1184. ;    edx  mem location to return data
  1185. ;--------------------------------------------------------------
  1186. ext2_HdGetFileInfo:
  1187.         xchg    bx, bx
  1188.         cmp     byte [esi], 0
  1189.         jz      .is_root
  1190.  
  1191.         push    edx
  1192.         call    ext2_find_lfn
  1193.         mov     ebx, edx
  1194.         pop     edx
  1195.         test    eax, eax
  1196.         jz      @F
  1197.         ret
  1198.  
  1199.     .is_root:
  1200.         xor     ebx, ebx      ;RUS: root не может быть скрытым   ;ENG: root cannot be hidden
  1201.         mov     ebp, [ext2_data.root_inode]
  1202.     @@:
  1203.         xor     eax, eax
  1204.         mov     edi, edx
  1205.         mov     ecx, 40/4
  1206.         rep stosd                   ; fill zero
  1207.  
  1208.         cmp     bl, '.'
  1209.         jne     @F
  1210.         or      dword [edx], FS_FT_HIDDEN
  1211.     @@:
  1212.  
  1213.         test    [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
  1214.         jnz     @F
  1215.         mov     eax, [ebp + EXT2_INODE_STRUC.i_size]            ;low size
  1216.         mov     ebx, [ebp + EXT2_INODE_STRUC.i_dir_acl]         ;high size
  1217.         mov     dword [edx+32], eax
  1218.         mov     dword [edx+36], ebx
  1219.         xor     dword [edx], FS_FT_DIR
  1220.     @@:
  1221.         xor     dword [edx], FS_FT_DIR
  1222.  
  1223.         lea     edi, [edx + 8]
  1224.         mov     eax, [ebp + EXT2_INODE_STRUC.i_ctime]
  1225.         xor     edx, edx
  1226.         add     eax, 3054539008
  1227.         adc     edx, 2
  1228.         call    ntfs_datetime_to_bdfe.sec
  1229.  
  1230.         mov     eax, [ebp + EXT2_INODE_STRUC.i_atime]
  1231.         xor     edx, edx
  1232.         add     eax, 3054539008
  1233.         adc     edx, 2
  1234.         call    ntfs_datetime_to_bdfe.sec
  1235.  
  1236.         mov     eax, [ebp + EXT2_INODE_STRUC.i_mtime]
  1237.         xor     edx, edx
  1238.         add     eax, 3054539008
  1239.         adc     edx, 2
  1240.         call    ntfs_datetime_to_bdfe.sec
  1241.  
  1242.         xor     eax, eax
  1243.         ret
  1244.  
  1245. ext2_HdRewrite:
  1246. ext2_HdWrite:
  1247. ext2_HdSetFileEnd:
  1248. ext2_HdSetFileInfo:
  1249. ext2_HdDelete:
  1250. ext2_HdCreateFolder:
  1251.         xor     ebx, ebx
  1252.         mov     eax, ERROR_UNSUPPORTED_FS
  1253.         ret
  1254.