Subversion Repositories Kolibri OS

Rev

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