Subversion Repositories Kolibri OS

Rev

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

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