Subversion Repositories Kolibri OS

Rev

Rev 2434 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2434 Serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2465 Serge 3
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
2434 Serge 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:
1397 turbanoff 655
; convert UTF-8 string to ASCII-string (codepage 866)
656
; in: ecx=length source, esi->source, edi->buffer
2434 Serge 657
; destroys: eax,esi,edi
658
        jecxz   .ret
659
    .start:
660
        lodsw
1397 turbanoff 661
        cmp     al, 0x80
2434 Serge 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
1397 turbanoff 670
        jb      .unk
671
        cmp     ax, 0xd180
672
        jb      .rus1
673
        cmp     ax, 0xd190
2434 Serge 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
 
1378 turbanoff 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
;
2434 Serge 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
1419 turbanoff 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
;
2434 Serge 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