Subversion Repositories Kolibri OS

Rev

Rev 2465 | 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: 2987 $
  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.         jz      @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_blocks], 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.         add     esi, ebx                                ; к следующей записи
  620.         cmp     esi, [edi + 24]                        ; сравниваем с концом блока
  621.         jb      .find_wanted_start
  622.  
  623.         push    .find_wanted_start
  624.    .end_block:                                              ;вылетели из цикла
  625.         mov     ebx, [ext2_data.count_block_in_block]
  626.         sub     [ebp + EXT2_INODE_STRUC.i_blocks], ebx  ;вычитаем напрямую из структуры inode
  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.         add     esi, ebx
  731.         cmp     esi, [edi + 24]                         ;дошли ли до конца блока?
  732.         jb      .wanted_start
  733.  
  734.         push    .wanted_start                           ; дошли
  735.         jmp     .end_block
  736.  
  737.     .end_dir:   ;конец папки, когда еще не дошли до нужного файла
  738.         mov     edx, [edi + 28] ;адрес структуры результата
  739.         mov     ebx, [edi + 8] ;EXT2_read_in_folder
  740.         mov     ecx, [edi + 4] ;EXT2_files_in_folder
  741.         mov     dword [edx], 1    ;version
  742.         mov     [edx + 4], ebx
  743.         mov     [edx + 8], ecx
  744.        
  745.         lea     esp, [edi + 32]
  746.        
  747.         xor     eax, eax            ;зарезервировано: нули в текущей реализации
  748.         lea     edi, [edx + 12]
  749.         mov     ecx, 20 / 4
  750.         rep stosd
  751.         ret
  752.  
  753.     .error_bad_len:
  754.         mov     eax, ERROR_FS_FAIL
  755.     .error_read_subinode:
  756.     .error_get_block:
  757.         lea     esp, [edi + 32]
  758.     .error_ret:
  759.         or      ebx, -1
  760.         ret
  761.        
  762.     .error_empty_dir:               ;inode папки без блоков
  763.     .error_root:                    ;root - не папка
  764.         mov     eax, ERROR_FS_FAIL
  765.         jmp     .error_ret
  766.  
  767.     .error_not_found:               ;файл не найден
  768.         mov     eax, ERROR_FILE_NOT_FOUND
  769.         jmp     .error_ret
  770.            
  771. ;============================================
  772. ;convert UTF-8 string to ASCII-string (codepage 866)
  773. ;in:  ecx = length source
  774. ;     esi = source
  775. ;     edi = buffer
  776. ; destroys: eax,esi,edi
  777. utf8_to_cp866:
  778.         jecxz   .ret
  779.     .start:
  780.         lodsw
  781.         cmp     al, 0x80
  782.         jb      .ascii
  783.  
  784.         xchg    al, ah              ; big-endian
  785.         cmp     ax, 0xd080
  786.         jz      .yo1
  787.         cmp     ax, 0xd191
  788.         jz      .yo2
  789.         cmp     ax, 0xd090
  790.         jb      .unk
  791.         cmp     ax, 0xd180
  792.         jb      .rus1
  793.         cmp     ax, 0xd190
  794.         jb      .rus2
  795.     .unk:
  796.         mov     al, '_'
  797.         jmp     .doit
  798.     .yo1:
  799.         mov     al, 0xf0    ; Ё capital
  800.         jmp     .doit
  801.     .yo2:
  802.         mov     al, 0xf1    ; ё small
  803.         jmp     .doit
  804.     .rus1:
  805.         sub     ax, 0xd090 - 0x80
  806.         jmp     .doit
  807.     .rus2:
  808.         sub     ax, 0xd18f - 0xEF
  809.     .doit:
  810.         stosb
  811.         sub     ecx, 2
  812.         ja      .start
  813.         ret
  814.  
  815.     .ascii:
  816.         stosb
  817.         dec     esi
  818.         dec     ecx
  819.         jnz     .start
  820.     .ret:
  821.         ret
  822.  
  823. ;----------------------------------------------------------------
  824. ;
  825. ;  ext2_HdRead - read hard disk
  826. ;
  827. ;  esi  points to filename
  828. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  829. ;       may be ebx=0 - start from first byte
  830. ;  ecx  number of bytes to read, 0+
  831. ;  edx  mem location to return data
  832. ;
  833. ;  ret ebx = bytes read or 0xffffffff file not found
  834. ;      eax = 0 ok read or other = errormsg
  835.  
  836. ;--------------------------------------------------------------
  837. ext2_HdRead:
  838.         cmp     byte [esi], 0
  839.         jnz     @F
  840.  
  841.     .this_is_nofile:
  842.         or      ebx, -1
  843.         mov     eax, ERROR_ACCESS_DENIED
  844.         ret
  845.  
  846.     @@:
  847.         push    ecx ebx edx
  848.         call    ext2_find_lfn
  849.         pop     edx ebx ecx
  850.         test    eax, eax
  851.         jz      @F
  852.  
  853.         or      ebx, -1
  854.         mov     eax, ERROR_FILE_NOT_FOUND
  855.         ret
  856.  
  857.     @@:
  858.         mov     ax, [ebp + EXT2_INODE_STRUC.i_mode]
  859.         and     ax, EXT2_S_IFMT     ;оставляем только тип inode в ax
  860.         cmp     ax, EXT2_S_IFREG
  861.         jne     .this_is_nofile
  862.  
  863.         mov     edi, edx            ; edi = pointer to return mem
  864.  
  865.         test    ebx, ebx
  866.         jz      @F
  867.         mov     esi, ebx            ; esi = pointer to first_wanted
  868.         mov     ebx, [esi+4]
  869.         mov     eax, [esi]          ; ebx : eax - стартовый номер байта
  870.  
  871.         ;///// сравним хватит ли нам файла или нет
  872.         cmp     [ebp + EXT2_INODE_STRUC.i_dir_acl], ebx
  873.         ja      .size_great
  874.         jb      .size_less
  875.  
  876.         cmp     [ebp + EXT2_INODE_STRUC.i_size], eax
  877.         ja      .size_great
  878.  
  879.     .size_less:
  880.         xor     ebx, ebx
  881.         mov     eax, ERROR_END_OF_FILE
  882.         ret
  883.        
  884.     @@:
  885.         xor     ebx, ebx
  886.         xor     eax, eax
  887.     .size_great:
  888.         add     eax, ecx                  ;add to first_wanted кол-во байт для чтения
  889.         adc     ebx, 0
  890.  
  891.         cmp     [ebp + EXT2_INODE_STRUC.i_dir_acl], ebx
  892.         ja      .size_great_great
  893.         jb      .size_great_less
  894.         cmp     [ebp + EXT2_INODE_STRUC.i_size], eax
  895.         jae     .size_great_great
  896.  
  897.     .size_great_less:
  898.         push    1
  899. ;        or      [EXT2_files_in_folder], 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. ;        and     [EXT2_files_in_folder], 0       ;читаем столько сколько запросили
  907.  
  908.     @@:
  909.         ;здесь мы точно знаем сколько байт читать - ecx
  910.         ;edi - return memory
  911.         ;esi -> first wanted
  912.  
  913.         push    ecx                             ;количество считанных байт
  914.         test    esi, esi
  915.         jz      .zero_start
  916.  
  917.         ;получим кусок из первого блока
  918.         mov     edx, [esi+4]
  919.         mov     eax, [esi]
  920.         div     [ext2_data.block_size]
  921.  
  922.         push    eax       ;номер блока запоминаем
  923.  
  924.         push    ecx
  925.         mov     ecx, eax
  926.         call    ext2_get_inode_block
  927.         test    eax, eax
  928.         jnz     .error_at_first_block
  929.         mov     ebx, [ext2_data.ext2_save_block]
  930.         mov     eax, ecx
  931.         call    ext2_get_block
  932.         test    eax, eax
  933.         jnz     .error_at_first_block
  934.         pop     ecx
  935.         add     ebx, edx
  936.  
  937.         neg     edx
  938.         add     edx, [ext2_data.block_size]     ;block_size - стартовый байт = сколько байт 1-го блока
  939.         cmp     ecx, edx
  940.         jbe     .only_one_block
  941.  
  942.         mov     eax, ecx
  943.         sub     eax, edx
  944.         mov     ecx, edx
  945.  
  946.         mov     esi, ebx
  947.         rep movsb                               ;кусок 1-го блока
  948.         jmp     .calc_blocks_count
  949.  
  950.     .zero_start:
  951.         mov     eax, ecx
  952.         push    0                               ;счетчик блоков
  953.         ;теперь в eax кол-во оставшихся байт для чтения
  954.     .calc_blocks_count:
  955.         mov     ebx, edi                        ;чтение блока прям в ->ebx
  956.         xor     edx, edx
  957.         div     [ext2_data.block_size]          ;кол-во байт в последнем блоке (остаток) в edx
  958.         mov     edi, eax                        ;кол-во целых блоков в edi
  959.     @@:
  960.         test    edi, edi
  961.         jz      .finish_block
  962.         inc     dword [esp]
  963.         mov     ecx, [esp]
  964.         call    ext2_get_inode_block
  965.         test    eax, eax
  966.         jnz     .error_at_read_cycle
  967.  
  968.         mov     eax, ecx                        ;а ebx уже забит нужным значением
  969.         call    ext2_get_block
  970.         test    eax, eax
  971.         jnz     .error_at_read_cycle
  972.         add     ebx, [ext2_data.block_size]
  973.  
  974.         dec     edi
  975.         jmp     @B
  976.  
  977.     .finish_block:          ;в edx - кол-во байт в последнем блоке
  978.         test    edx, edx
  979.         jz      .end_read
  980.  
  981.         pop     ecx         ;счетчик блоков -> ecx
  982.         inc     ecx
  983.         call    ext2_get_inode_block
  984.         test    eax, eax
  985.         jz      .error_at_finish_block
  986.  
  987.         mov     edi, ebx
  988.         mov     eax, ecx
  989.         mov     ebx, [ext2_data.ext2_save_block]
  990.         call    ext2_get_block
  991.         test    eax, eax
  992.         jnz     .error_at_finish_block
  993.  
  994.         mov     ecx, edx
  995.         mov     esi, ebx
  996.         rep movsb                               ;кусок last блока
  997.     .end_read:
  998.         pop     ebx
  999.         pop     eax
  1000.         test    eax, eax
  1001.         jz      @F
  1002.  
  1003.         mov     eax, ERROR_END_OF_FILE
  1004.         ret
  1005.     @@:
  1006.         xor     eax, eax
  1007.         ret
  1008.        
  1009.     .only_one_block:
  1010.         mov     esi, ebx
  1011.         rep movsb                               ;кусок last блока
  1012.         pop     eax
  1013.         jmp     .end_read
  1014.        
  1015.    .error_at_first_block:
  1016.         pop     edx
  1017.    .error_at_read_cycle:
  1018.         pop     ebx
  1019.    .error_at_finish_block:
  1020.         pop     ecx edx
  1021.         or      ebx, -1
  1022.         ret
  1023.  
  1024. ;----------------------------------------------------------------
  1025. ; in:  esi = file path
  1026. ;      ebx = pointer to dir block
  1027. ; out: esi - name without parent or not_changed
  1028. ;      ebx - dir_rec of inode children
  1029. ext2_test_block_by_name:
  1030.         sub     esp, 256        ;EXT2_filename
  1031.         mov     edx, ebx
  1032.         add     edx, [ext2_data.block_size]       ;запомним конец блока
  1033.  
  1034.     .start_rec:
  1035.         cmp     [ebx + EXT2_DIR_STRUC.inode], 0
  1036.         jz      .next_rec
  1037.  
  1038.         mov     edi, esp
  1039.         push    esi
  1040.         movzx   ecx, [ebx + EXT2_DIR_STRUC.name_len]
  1041.         lea     esi, [ebx + EXT2_DIR_STRUC.name]
  1042.         call    utf8_to_cp866
  1043.  
  1044.         mov     ecx, edi
  1045.         lea     edi, [esp + 4]
  1046.         sub     ecx, edi          ;кол-во байт в получившейся строке
  1047.  
  1048.         mov     esi, [esp]
  1049.     @@:
  1050.         jecxz   .test_find
  1051.         dec     ecx
  1052.  
  1053.         lodsb
  1054.         call    char_toupper
  1055.  
  1056.         mov     ah, [edi]
  1057.         inc     edi
  1058.         xchg    al, ah
  1059.         call    char_toupper
  1060.         cmp     al, ah
  1061.         je      @B
  1062.     @@:                           ;не подошло
  1063.         pop     esi
  1064.     .next_rec:
  1065.         movzx   eax, [ebx + EXT2_DIR_STRUC.rec_len]
  1066.         add     ebx, eax                                    ;к след. записи
  1067.         cmp     ebx, edx                                    ;проверим конец ли
  1068.         jb      .start_rec
  1069.         add     esp, 256
  1070.         ret
  1071.  
  1072.     .test_find:
  1073.         cmp     byte [esi], 0
  1074.         je      .ret                ;нашли конец
  1075.         cmp     byte [esi], '/'
  1076.         jne     @B
  1077.         inc     esi
  1078.     .ret:
  1079.         add     esp, 256 + 4
  1080.         ret
  1081.  
  1082. ;========================
  1083. ;Ищет inode по строке пути
  1084. ;in:  esi = name
  1085. ;out: eax - error code
  1086. ;     ebp = inode
  1087. ;      dl - первый байт из имени файла/папки
  1088. ext2_find_lfn:
  1089.         mov     ebp, [ext2_data.root_inode]
  1090.         cmp     [ebp + EXT2_INODE_STRUC.i_blocks], 0
  1091.         je      .error_empty_root
  1092.        
  1093.     .next_path_part:
  1094.         push    [ebp + EXT2_INODE_STRUC.i_blocks]
  1095.         xor     ecx, ecx
  1096.     .folder_block_cycle:
  1097.         call    ext2_get_inode_block
  1098.         test    eax, eax
  1099.         jnz     .error_get_inode_block
  1100.  
  1101.         mov     eax, ecx
  1102.         mov     ebx, [ext2_data.ext2_save_block]        ;ebx = cur dir record
  1103.         call    ext2_get_block
  1104.         test    eax, eax
  1105.         jnz     .error_get_block
  1106.  
  1107.         push    esi
  1108.         call    ext2_test_block_by_name
  1109.         pop     edi
  1110.  
  1111.         cmp     edi, esi                                ;нашли имя?
  1112.         je      .next_folder_block                      ;не нашли -> к след. блоку
  1113.  
  1114.         cmp     byte [esi], 0                           ;дошли до "конца" пути -> возваращаемся
  1115.         jz      .get_inode_ret
  1116.  
  1117.         cmp     [ebx + EXT2_DIR_STRUC.file_type], EXT2_FT_DIR   ;нашли, но это не папка
  1118.         jne     .not_found
  1119.  
  1120.         mov     eax, [ebx + EXT2_DIR_STRUC.inode]
  1121.         mov     ebx, [ext2_data.ext2_save_inode]                ;все же папка.
  1122.         call    ext2_get_inode
  1123.         test    eax, eax
  1124.         jnz     .error_get_inode
  1125.         pop     ecx                                     ;в стеке лежит кол-во блоков
  1126.         mov     ebp, ebx
  1127.         jmp     .next_path_part
  1128.        
  1129.     .next_folder_block:
  1130.         ;к следующему блоку в текущей папке
  1131.         pop     eax                                     ;счетчик блоков
  1132.         sub     eax, [ext2_data.count_block_in_block]
  1133.         jle     .not_found
  1134.        
  1135.         inc     ecx
  1136.         jmp     .folder_block_cycle
  1137.  
  1138.     .not_found:
  1139.         pop     ebx
  1140.         mov     eax, ERROR_FILE_NOT_FOUND
  1141.         ret
  1142.  
  1143.     .get_inode_ret:
  1144.         pop     ecx                                     ;в стеке лежит кол-во блоков
  1145.         mov     dl, [ebx + EXT2_DIR_STRUC.name]     ;в dl - первый символ ()
  1146.         mov     eax, [ebx + EXT2_DIR_STRUC.inode]
  1147.         mov     ebx, [ext2_data.ext2_save_inode]
  1148.         call    ext2_get_inode
  1149.         mov     ebp, ebx
  1150.         xor     eax, eax
  1151.         ret
  1152.  
  1153.     .error_get_inode_block:
  1154.     .error_get_block:
  1155.     .error_get_inode:
  1156.         pop     ebx
  1157.     .error_empty_root:
  1158.         mov     eax, ERROR_FS_FAIL
  1159.         ret
  1160.  
  1161. ;----------------------------------------------------------------
  1162. ;ext2_HdGetFileInfo - read file info from block device
  1163. ;
  1164. ;in: esi  points to filename
  1165. ;    edx  mem location to return data
  1166. ;--------------------------------------------------------------
  1167. ext2_HdGetFileInfo:
  1168.         xchg    bx, bx
  1169.         cmp     byte [esi], 0
  1170.         jz      .is_root
  1171.  
  1172.         push    edx
  1173.         call    ext2_find_lfn
  1174.         mov     ebx, edx
  1175.         pop     edx
  1176.         test    eax, eax
  1177.         jz      @F
  1178.         ret
  1179.  
  1180.     .is_root:
  1181.         xor     ebx, ebx                        ;root не может быть скрытым
  1182.         mov     ebp, [ext2_data.root_inode]
  1183.     @@:
  1184.         xor     eax, eax
  1185.         mov     edi, edx
  1186.         mov     ecx, 40/4
  1187.         rep stosd                   ; fill zero
  1188.  
  1189.         cmp     bl, '.'
  1190.         jne     @F
  1191.         or      dword [edx], FS_FT_HIDDEN
  1192.     @@:
  1193.  
  1194.         test    [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
  1195.         jnz     @F
  1196.         mov     eax, [ebp + EXT2_INODE_STRUC.i_size]            ;low size
  1197.         mov     ebx, [ebp + EXT2_INODE_STRUC.i_dir_acl]         ;high size
  1198.         mov     dword [edx+32], eax
  1199.         mov     dword [edx+36], ebx
  1200.         xor     dword [edx], FS_FT_DIR
  1201.     @@:
  1202.         xor     dword [edx], FS_FT_DIR
  1203.  
  1204.         lea     edi, [edx + 8]
  1205.         mov     eax, [ebp + EXT2_INODE_STRUC.i_ctime]
  1206.         xor     edx, edx
  1207.         add     eax, 3054539008
  1208.         adc     edx, 2
  1209.         call    ntfs_datetime_to_bdfe.sec
  1210.  
  1211.         mov     eax, [ebp + EXT2_INODE_STRUC.i_atime]
  1212.         xor     edx, edx
  1213.         add     eax, 3054539008
  1214.         adc     edx, 2
  1215.         call    ntfs_datetime_to_bdfe.sec
  1216.  
  1217.         mov     eax, [ebp + EXT2_INODE_STRUC.i_mtime]
  1218.         xor     edx, edx
  1219.         add     eax, 3054539008
  1220.         adc     edx, 2
  1221.         call    ntfs_datetime_to_bdfe.sec
  1222.  
  1223.         xor     eax, eax
  1224.         ret
  1225.  
  1226. ext2_HdRewrite:
  1227. ext2_HdWrite:
  1228. ext2_HdSetFileEnd:
  1229. ext2_HdSetFileInfo:
  1230. ext2_HdDelete:
  1231. ext2_HdCreateFolder:
  1232.         xor     ebx, ebx
  1233.         mov     eax, ERROR_UNSUPPORTED_FS
  1234.         ret
  1235.