Subversion Repositories Kolibri OS

Rev

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

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