Subversion Repositories Kolibri OS

Rev

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