Subversion Repositories Kolibri OS

Rev

Rev 4923 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4923 Rev 5116
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2
;;                                                              ;;
3
;; Contains ext2 initialization, plus syscall handling code.    ;;
3
;; Contains ext2 initialization, plus syscall handling code.    ;;
4
;;                                                              ;;
4
;;                                                              ;;
5
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
5
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
6
;; Distributed under terms of the GNU General Public License    ;;
6
;; Distributed under terms of the GNU General Public License    ;;
7
;;                                                              ;;
7
;;                                                              ;;
8
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9
 
9
 
10
$Revision: 4891 $
10
$Revision: 5089 $
11
 
11
 
12
 
12
 
13
include 'ext2.inc'
13
include 'ext2.inc'
14
include 'blocks.inc'
14
include 'blocks.inc'
15
include 'inode.inc'
15
include 'inode.inc'
16
include 'resource.inc'
16
include 'resource.inc'
17
 
17
 
18
iglobal
18
iglobal
19
align 4
19
align 4
20
ext2_user_functions:
20
ext2_user_functions:
21
        dd      ext2_free
21
        dd      ext2_free
22
        dd      (ext2_user_functions_end - ext2_user_functions - 4) / 4
22
        dd      (ext2_user_functions_end - ext2_user_functions - 4) / 4
23
        dd      ext2_Read
23
        dd      ext2_Read
24
        dd      ext2_ReadFolder
24
        dd      ext2_ReadFolder
25
        dd      ext2_Rewrite
25
        dd      ext2_Rewrite
26
        dd      ext2_Write
26
        dd      ext2_Write
27
        dd      ext2_SetFileEnd
27
        dd      ext2_SetFileEnd
28
        dd      ext2_GetFileInfo
28
        dd      ext2_GetFileInfo
29
        dd      ext2_SetFileInfo
29
        dd      ext2_SetFileInfo
30
        dd      0
30
        dd      0
31
        dd      ext2_Delete
31
        dd      ext2_Delete
32
        dd      ext2_CreateFolder
32
        dd      ext2_CreateFolder
33
ext2_user_functions_end:
33
ext2_user_functions_end:
34
endg
34
endg
35
 
35
 
36
;--------------------------------------------------------------------- 
36
;--------------------------------------------------------------------- 
37
; Locks up an ext2 partition.
37
; Locks up an ext2 partition.
38
; Input:        ebp = pointer to EXTFS.
38
; Input:        ebp = pointer to EXTFS.
39
;---------------------------------------------------------------------
39
;---------------------------------------------------------------------
40
proc ext2_lock
40
proc ext2_lock
41
        lea     ecx, [ebp + EXTFS.lock]
41
        lea     ecx, [ebp + EXTFS.lock]
42
        jmp     mutex_lock
42
        jmp     mutex_lock
43
endp
43
endp
44
 
44
 
45
;--------------------------------------------------------------------- 
45
;--------------------------------------------------------------------- 
46
; Unlocks up an ext2 partition.
46
; Unlocks up an ext2 partition.
47
; Input:        ebp = pointer to EXTFS.
47
; Input:        ebp = pointer to EXTFS.
48
;---------------------------------------------------------------------
48
;---------------------------------------------------------------------
49
proc ext2_unlock
49
proc ext2_unlock
50
        lea     ecx, [ebp + EXTFS.lock]
50
        lea     ecx, [ebp + EXTFS.lock]
51
        jmp     mutex_unlock
51
        jmp     mutex_unlock
52
endp
52
endp
53
 
53
 
54
;---------------------------------------------------------------------
54
;---------------------------------------------------------------------
55
; Check if it's a valid ext* superblock.
55
; Check if it's a valid ext* superblock.
56
; Input:        ebp:       first three fields of PARTITION structure.
56
; Input:        ebp:       first three fields of PARTITION structure.
57
;               ebx + 512: points to 512-bytes buffer that can be used for anything.
57
;               ebx + 512: points to 512-bytes buffer that can be used for anything.
58
; Output:       eax:       clear if can't create partition; set to EXTFS otherwise.
58
; Output:       eax:       clear if can't create partition; set to EXTFS otherwise.
59
;---------------------------------------------------------------------
59
;---------------------------------------------------------------------
60
proc ext2_create_partition
60
proc ext2_create_partition
61
        push    ebx
61
        push    ebx
-
 
62
        cmp     dword [esi+DISK.MediaInfo.SectorSize], 512
-
 
63
        jnz     .fail
62
 
64
 
63
        mov     eax, 2                          ; Superblock starts at 1024-bytes.
65
        mov     eax, 2                          ; Superblock starts at 1024-bytes.
64
        add     ebx, 512                        ; Get pointer to fs-specific buffer.
66
        add     ebx, 512                        ; Get pointer to fs-specific buffer.
65
        call    fs_read32_sys
67
        call    fs_read32_sys
66
        test    eax, eax
68
        test    eax, eax
67
        jnz     .fail
69
        jnz     .fail
68
 
70
 
69
        ; Allowed 1KiB, 2KiB, 4KiB, 8KiB.
71
        ; Allowed 1KiB, 2KiB, 4KiB, 8KiB.
70
        cmp     [ebx + EXT2_SB_STRUC.log_block_size], 3  
72
        cmp     [ebx + EXT2_SB_STRUC.log_block_size], 3  
71
        ja      .fail
73
        ja      .fail
72
 
74
 
73
        cmp     [ebx + EXT2_SB_STRUC.magic], EXT2_SUPER_MAGIC
75
        cmp     [ebx + EXT2_SB_STRUC.magic], EXT2_SUPER_MAGIC
74
        jne     .fail
76
        jne     .fail
75
 
77
 
76
        cmp     [ebx + EXT2_SB_STRUC.state], EXT2_VALID_FS
78
        cmp     [ebx + EXT2_SB_STRUC.state], EXT2_VALID_FS
77
        jne     .fail
79
        jne     .fail
78
 
80
 
79
        ; Can't have no inodes per group.
81
        ; Can't have no inodes per group.
80
        cmp     [ebx + EXT2_SB_STRUC.inodes_per_group], 0
82
        cmp     [ebx + EXT2_SB_STRUC.inodes_per_group], 0
81
        je      .fail
83
        je      .fail
82
 
84
 
83
        ; If incompatible features required, unusable superblock.
85
        ; If incompatible features required, unusable superblock.
84
        mov     eax, [ebx + EXT2_SB_STRUC.feature_incompat] 
86
        mov     eax, [ebx + EXT2_SB_STRUC.feature_incompat] 
85
        test    eax, not EXT4_FEATURE_INCOMPAT_SUPP
87
        test    eax, not EXT4_FEATURE_INCOMPAT_SUPP
86
        jz      .setup
88
        jz      .setup
87
 
89
 
88
    .fail:
90
    .fail:
89
        ; Not a (valid/usable) EXT2 superblock.
91
        ; Not a (valid/usable) EXT2 superblock.
90
        pop     ebx
92
        pop     ebx
91
        xor     eax, eax
93
        xor     eax, eax
92
        ret
94
        ret
93
 
95
 
94
    .setup:
96
    .setup:
95
        movi    eax, sizeof.EXTFS
97
        movi    eax, sizeof.EXTFS
96
        call    malloc
98
        call    malloc
97
        test    eax, eax
99
        test    eax, eax
98
        jz      ext2_create_partition.fail
100
        jz      ext2_create_partition.fail
99
 
101
 
100
        ; Store the first sector field. 
102
        ; Store the first sector field. 
101
        mov     ecx, dword[ebp + PARTITION.FirstSector]
103
        mov     ecx, dword[ebp + PARTITION.FirstSector]
102
        mov     dword[eax + EXTFS.FirstSector], ecx
104
        mov     dword[eax + EXTFS.FirstSector], ecx
103
        mov     ecx, dword [ebp + PARTITION.FirstSector+4]
105
        mov     ecx, dword [ebp + PARTITION.FirstSector+4]
104
        mov     dword [eax + EXTFS.FirstSector+4], ecx
106
        mov     dword [eax + EXTFS.FirstSector+4], ecx
105
 
107
 
106
        ; The length field.
108
        ; The length field.
107
        mov     ecx, dword[ebp + PARTITION.Length]
109
        mov     ecx, dword[ebp + PARTITION.Length]
108
        mov     dword[eax + EXTFS.Length], ecx
110
        mov     dword[eax + EXTFS.Length], ecx
109
        mov     ecx, dword[ebp + PARTITION.Length+4]
111
        mov     ecx, dword[ebp + PARTITION.Length+4]
110
        mov     dword[eax + EXTFS.Length+4], ecx
112
        mov     dword[eax + EXTFS.Length+4], ecx
111
 
113
 
112
        ; The disk field.
114
        ; The disk field.
113
        mov     ecx, [ebp + PARTITION.Disk]
115
        mov     ecx, [ebp + PARTITION.Disk]
114
        mov     [eax + EXTFS.Disk], ecx
116
        mov     [eax + EXTFS.Disk], ecx
115
 
117
 
116
        mov     [eax + EXTFS.FSUserFunctions], ext2_user_functions
118
        mov     [eax + EXTFS.FSUserFunctions], ext2_user_functions
117
 
119
 
118
        push    ebp esi edi
120
        push    ebp esi edi
119
 
121
 
120
        mov     ebp, eax
122
        mov     ebp, eax
121
        lea     ecx, [eax + EXTFS.lock]
123
        lea     ecx, [eax + EXTFS.lock]
122
        call    mutex_init
124
        call    mutex_init
123
 
125
 
124
        ; Copy superblock from buffer to reserved memory.
126
        ; Copy superblock from buffer to reserved memory.
125
        mov     esi, ebx
127
        mov     esi, ebx
126
        lea     edi, [ebp + EXTFS.superblock]
128
        lea     edi, [ebp + EXTFS.superblock]
127
        mov     ecx, 512/4
129
        mov     ecx, 512/4
128
        rep movsd
130
        rep movsd
129
 
131
 
130
        ; Get total groups.
132
        ; Get total groups.
131
        mov     eax, [ebx + EXT2_SB_STRUC.blocks_count]
133
        mov     eax, [ebx + EXT2_SB_STRUC.blocks_count]
132
        sub     eax, [ebx + EXT2_SB_STRUC.first_data_block]
134
        sub     eax, [ebx + EXT2_SB_STRUC.first_data_block]
133
        dec     eax
135
        dec     eax
134
        xor     edx, edx
136
        xor     edx, edx
135
        div     [ebx + EXT2_SB_STRUC.blocks_per_group]
137
        div     [ebx + EXT2_SB_STRUC.blocks_per_group]
136
        inc     eax
138
        inc     eax
137
        mov     [ebp + EXTFS.groups_count], eax
139
        mov     [ebp + EXTFS.groups_count], eax
138
 
140
 
139
        ; Get log(block_size), such that 1,2,3,4 equ 1KiB,2KiB,4KiB,8KiB.
141
        ; Get log(block_size), such that 1,2,3,4 equ 1KiB,2KiB,4KiB,8KiB.
140
        mov     ecx, [ebx + EXT2_SB_STRUC.log_block_size]
142
        mov     ecx, [ebx + EXT2_SB_STRUC.log_block_size]
141
        inc     ecx
143
        inc     ecx
142
        mov     [ebp + EXTFS.log_block_size], ecx
144
        mov     [ebp + EXTFS.log_block_size], ecx
143
 
145
 
144
        ; 512-byte blocks in ext2 blocks.
146
        ; 512-byte blocks in ext2 blocks.
145
        mov     eax, 1
147
        mov     eax, 1
146
        shl     eax, cl
148
        shl     eax, cl
147
        mov     [ebp + EXTFS.count_block_in_block], eax
149
        mov     [ebp + EXTFS.count_block_in_block], eax
148
 
150
 
149
        ; Get block_size/4 (we'll find square later).
151
        ; Get block_size/4 (we'll find square later).
150
        shl     eax, 7
152
        shl     eax, 7
151
        mov     [ebp + EXTFS.count_pointer_in_block], eax
153
        mov     [ebp + EXTFS.count_pointer_in_block], eax
152
        mov     edx, eax
154
        mov     edx, eax
153
 
155
 
154
        ; Get block size.
156
        ; Get block size.
155
        shl     eax, 2
157
        shl     eax, 2
156
        mov     [ebp + EXTFS.block_size], eax
158
        mov     [ebp + EXTFS.block_size], eax
157
 
159
 
158
        ; Save block size for 2 kernel_alloc calls.
160
        ; Save block size for 2 kernel_alloc calls.
159
        push    eax eax
161
        push    eax eax
160
 
162
 
161
        mov     eax, edx
163
        mov     eax, edx
162
        mul     edx
164
        mul     edx
163
        mov     [ebp + EXTFS.count_pointer_in_block_square], eax
165
        mov     [ebp + EXTFS.count_pointer_in_block_square], eax
164
 
166
 
165
        ; Have temporary block storage for get_inode procedure, and one for global procedure.
167
        ; Have temporary block storage for get_inode procedure, and one for global procedure.
166
        KERNEL_ALLOC [ebp + EXTFS.ext2_save_block], .error
168
        KERNEL_ALLOC [ebp + EXTFS.ext2_save_block], .error
167
        KERNEL_ALLOC [ebp + EXTFS.ext2_temp_block], .error
169
        KERNEL_ALLOC [ebp + EXTFS.ext2_temp_block], .error
168
        
170
        
169
        mov     [ebp + EXTFS.partition_flags], 0x00000000
171
        mov     [ebp + EXTFS.partition_flags], 0x00000000
170
        mov     eax, [ebx + EXT2_SB_STRUC.feature_ro_compat]
172
        mov     eax, [ebx + EXT2_SB_STRUC.feature_ro_compat]
171
        and     eax, not EXT2_FEATURE_RO_COMPAT_SUPP
173
        and     eax, not EXT2_FEATURE_RO_COMPAT_SUPP
172
        jnz     .read_only
174
        jnz     .read_only
173
 
175
 
174
        mov     eax, [ebx + EXT2_SB_STRUC.feature_incompat]
176
        mov     eax, [ebx + EXT2_SB_STRUC.feature_incompat]
175
        and     eax, EXT4_FEATURE_INCOMPAT_W_NOT_SUPP
177
        and     eax, EXT4_FEATURE_INCOMPAT_W_NOT_SUPP
176
        jz      @F
178
        jz      @F
177
 
179
 
178
    .read_only:
180
    .read_only:
179
        ; Mark as read-only.
181
        ; Mark as read-only.
180
        or      [ebp + EXTFS.partition_flags], EXT2_RO
182
        or      [ebp + EXTFS.partition_flags], EXT2_RO
181
    @@:
183
    @@:
182
        mov     ecx, [ebx + EXT2_SB_STRUC.blocks_per_group]
184
        mov     ecx, [ebx + EXT2_SB_STRUC.blocks_per_group]
183
        mov     [ebp + EXTFS.blocks_per_group], ecx
185
        mov     [ebp + EXTFS.blocks_per_group], ecx
184
 
186
 
185
        movzx   ecx, word[ebx + EXT2_SB_STRUC.inode_size]
187
        movzx   ecx, word[ebx + EXT2_SB_STRUC.inode_size]
186
        mov     [ebp + EXTFS.inode_size], ecx
188
        mov     [ebp + EXTFS.inode_size], ecx
187
 
189
 
188
        ; Allocate for three inodes (loop would be overkill).
190
        ; Allocate for three inodes (loop would be overkill).
189
        push    ecx ecx ecx
191
        push    ecx ecx ecx
190
 
192
 
191
        KERNEL_ALLOC [ebp + EXTFS.ext2_save_inode], .error
193
        KERNEL_ALLOC [ebp + EXTFS.ext2_save_inode], .error
192
        KERNEL_ALLOC [ebp + EXTFS.ext2_temp_inode], .error
194
        KERNEL_ALLOC [ebp + EXTFS.ext2_temp_inode], .error
193
        KERNEL_ALLOC [ebp + EXTFS.root_inode], .error
195
        KERNEL_ALLOC [ebp + EXTFS.root_inode], .error
194
 
196
 
195
        ; Read root inode.
197
        ; Read root inode.
196
        mov     ebx, eax
198
        mov     ebx, eax
197
        mov     eax, EXT2_ROOT_INO
199
        mov     eax, EXT2_ROOT_INO
198
        call    ext2_inode_read
200
        call    ext2_inode_read
199
 
201
 
200
        test    eax, eax
202
        test    eax, eax
201
        jnz     .error
203
        jnz     .error
202
 
204
 
203
        ;call    ext2_sb_update
205
        ;call    ext2_sb_update
204
        ; Sync the disk.
206
        ; Sync the disk.
205
        ;mov     esi, [ebp + PARTITION.Disk]
207
        ;mov     esi, [ebp + PARTITION.Disk]
206
        ;call    disk_sync                       ; eax contains error code, if any.
208
        ;call    disk_sync                       ; eax contains error code, if any.
207
 
209
 
208
        mov     eax, ebp                        ; Return pointer to EXTFS.
210
        mov     eax, ebp                        ; Return pointer to EXTFS.
209
        pop     edi esi ebp ebx
211
        pop     edi esi ebp ebx
210
        ret
212
        ret
211
 
213
 
212
    ; Error in setting up.
214
    ; Error in setting up.
213
    .error:        
215
    .error:        
214
        ; Free save block.
216
        ; Free save block.
215
        KERNEL_FREE [ebp + EXTFS.ext2_save_block], .fail
217
        KERNEL_FREE [ebp + EXTFS.ext2_save_block], .fail
216
 
218
 
217
        ; Temporary block.
219
        ; Temporary block.
218
        KERNEL_FREE [ebp + EXTFS.ext2_temp_block], .fail
220
        KERNEL_FREE [ebp + EXTFS.ext2_temp_block], .fail
219
 
221
 
220
        ; All inodes.
222
        ; All inodes.
221
        KERNEL_FREE [ebp + EXTFS.ext2_save_inode], .fail
223
        KERNEL_FREE [ebp + EXTFS.ext2_save_inode], .fail
222
        KERNEL_FREE [ebp + EXTFS.ext2_temp_inode], .fail
224
        KERNEL_FREE [ebp + EXTFS.ext2_temp_inode], .fail
223
        KERNEL_FREE [ebp + EXTFS.root_inode], .fail
225
        KERNEL_FREE [ebp + EXTFS.root_inode], .fail
224
 
226
 
225
        mov     eax, ebp
227
        mov     eax, ebp
226
        call    free
228
        call    free
227
 
229
 
228
        jmp     .fail
230
        jmp     .fail
229
endp
231
endp
230
 
232
 
231
; FUNCTIONS PROVIDED BY SYSCALLS.
233
; FUNCTIONS PROVIDED BY SYSCALLS.
232
 
234
 
233
;---------------------------------------------------------------------
235
;---------------------------------------------------------------------
234
; Frees up all ext2 structures.
236
; Frees up all ext2 structures.
235
; Input:        eax = pointer to EXTFS.
237
; Input:        eax = pointer to EXTFS.
236
;---------------------------------------------------------------------
238
;---------------------------------------------------------------------
237
proc ext2_free
239
proc ext2_free
238
        push    ebp
240
        push    ebp
239
 
241
 
240
        xchg    ebp, eax
242
        xchg    ebp, eax
241
        stdcall kernel_free, [ebp+EXTFS.ext2_save_block]
243
        stdcall kernel_free, [ebp+EXTFS.ext2_save_block]
242
        stdcall kernel_free, [ebp+EXTFS.ext2_temp_block]
244
        stdcall kernel_free, [ebp+EXTFS.ext2_temp_block]
243
        stdcall kernel_free, [ebp+EXTFS.ext2_save_inode]
245
        stdcall kernel_free, [ebp+EXTFS.ext2_save_inode]
244
        stdcall kernel_free, [ebp+EXTFS.ext2_temp_inode]
246
        stdcall kernel_free, [ebp+EXTFS.ext2_temp_inode]
245
        stdcall kernel_free, [ebp+EXTFS.root_inode]
247
        stdcall kernel_free, [ebp+EXTFS.root_inode]
246
 
248
 
247
        xchg    ebp, eax
249
        xchg    ebp, eax
248
        call    free
250
        call    free
249
 
251
 
250
        pop     ebp
252
        pop     ebp
251
        ret
253
        ret
252
endp
254
endp
253
 
255
 
254
;---------------------------------------------------------------------
256
;---------------------------------------------------------------------
255
; Read disk folder.
257
; Read disk folder.
256
; Input:        ebp = pointer to EXTFS structure.
258
; Input:        ebp = pointer to EXTFS structure.
257
;               esi + [esp + 4] = file name.
259
;               esi + [esp + 4] = file name.
258
;               ebx = pointer to parameters from sysfunc 70.
260
;               ebx = pointer to parameters from sysfunc 70.
259
; Output:       ebx = blocks read (or 0xFFFFFFFF, folder not found)
261
; Output:       ebx = blocks read (or 0xFFFFFFFF, folder not found)
260
;               eax = error code (0 implies no error)
262
;               eax = error code (0 implies no error)
261
;---------------------------------------------------------------------
263
;---------------------------------------------------------------------
262
ext2_ReadFolder:
264
ext2_ReadFolder:
263
        ;DEBUGF  1, "Reading folder.\n"
265
        ;DEBUGF  1, "Reading folder.\n"
264
        call    ext2_lock
266
        call    ext2_lock
265
        cmp     byte [esi], 0
267
        cmp     byte [esi], 0
266
        jz      .root_folder
268
        jz      .root_folder
267
 
269
 
268
        push    ebx
270
        push    ebx
269
        stdcall ext2_inode_find, [esp + 4 + 4]            ; Get inode.
271
        stdcall ext2_inode_find, [esp + 4 + 4]            ; Get inode.
270
        pop     ebx
272
        pop     ebx
271
 
273
 
272
        mov     esi, [ebp + EXTFS.ext2_save_inode]
274
        mov     esi, [ebp + EXTFS.ext2_save_inode]
273
        test    eax, eax
275
        test    eax, eax
274
        jnz     .error_ret
276
        jnz     .error_ret
275
 
277
 
276
        ; If not a directory, then return with error.
278
        ; If not a directory, then return with error.
277
        test    [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
279
        test    [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
278
        jz      .error_not_found
280
        jz      .error_not_found
279
        jmp     @F
281
        jmp     @F
280
 
282
 
281
    .root_folder:
283
    .root_folder:
282
        mov     esi, [ebp + EXTFS.root_inode]
284
        mov     esi, [ebp + EXTFS.root_inode]
283
        test    [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
285
        test    [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
284
        jz      .error_root
286
        jz      .error_root
285
 
287
 
286
        ; Copy the inode.
288
        ; Copy the inode.
287
        mov     edi, [ebp + EXTFS.ext2_save_inode]
289
        mov     edi, [ebp + EXTFS.ext2_save_inode]
288
        mov     ecx, [ebp + EXTFS.inode_size]
290
        mov     ecx, [ebp + EXTFS.inode_size]
289
        shr     ecx, 2
291
        shr     ecx, 2
290
        
292
        
291
        push    edi
293
        push    edi
292
        rep movsd
294
        rep movsd
293
        pop     esi
295
        pop     esi
294
 
296
 
295
    @@:
297
    @@:
296
        cmp     [esi + EXT2_INODE_STRUC.i_size], 0      ; Folder is empty.
298
        cmp     [esi + EXT2_INODE_STRUC.i_size], 0      ; Folder is empty.
297
        je      .error_empty_dir
299
        je      .error_empty_dir
298
        
300
        
299
        mov     edx, [ebx + 16]
301
        mov     edx, [ebx + 16]
300
        push    edx                                     ; Result address [edi + 28].
302
        push    edx                                     ; Result address [edi + 28].
301
        push    0                                       ; End of the current block in folder [edi + 24]
303
        push    0                                       ; End of the current block in folder [edi + 24]
302
        push    dword[ebx + 12]                         ; Blocks to read [edi + 20]
304
        push    dword[ebx + 12]                         ; Blocks to read [edi + 20]
303
        push    dword[ebx + 4]                          ; The first wanted file [edi + 16]
305
        push    dword[ebx + 4]                          ; The first wanted file [edi + 16]
304
        push    dword[ebx + 8]                          ; Flags [edi + 12]
306
        push    dword[ebx + 8]                          ; Flags [edi + 12]
305
        push    0                                       ; Read files [edi + 8]
307
        push    0                                       ; Read files [edi + 8]
306
        push    0                                       ; Files in folder [edi + 4]
308
        push    0                                       ; Files in folder [edi + 4]
307
        push    0                                       ; Number of blocks read in dir (and current block index) [edi]
309
        push    0                                       ; Number of blocks read in dir (and current block index) [edi]
308
 
310
 
309
        ; Fill header with zeroes.
311
        ; Fill header with zeroes.
310
        mov     edi, edx
312
        mov     edi, edx
311
        mov     ecx, 32/4
313
        mov     ecx, 32/4
312
        rep stosd
314
        rep stosd
313
        
315
        
314
        mov     edi, esp                                ; edi = pointer to local variables.
316
        mov     edi, esp                                ; edi = pointer to local variables.
315
        add     edx, 32                                 ; edx = mem to return.
317
        add     edx, 32                                 ; edx = mem to return.
316
 
318
 
317
        xor     ecx, ecx                                ; Get number of first block.
319
        xor     ecx, ecx                                ; Get number of first block.
318
        call    ext2_inode_get_block
320
        call    ext2_inode_get_block
319
        test    eax, eax
321
        test    eax, eax
320
        jnz     .error_get_block
322
        jnz     .error_get_block
321
 
323
 
322
        mov     eax, ecx
324
        mov     eax, ecx
323
        mov     ebx, [ebp + EXTFS.ext2_save_block]
325
        mov     ebx, [ebp + EXTFS.ext2_save_block]
324
        call    ext2_block_read                          ; Read the block.
326
        call    ext2_block_read                          ; Read the block.
325
        test    eax, eax
327
        test    eax, eax
326
        jnz     .error_get_block
328
        jnz     .error_get_block
327
 
329
 
328
        mov     eax, ebx                                ; esi: current directory record
330
        mov     eax, ebx                                ; esi: current directory record
329
        add     eax, [ebp + EXTFS.block_size]
331
        add     eax, [ebp + EXTFS.block_size]
330
        
332
        
331
        mov     [edi + 24], eax
333
        mov     [edi + 24], eax
332
 
334
 
333
        mov     ecx, [edi + 16]                         ; ecx = first wanted (flags ommited)
335
        mov     ecx, [edi + 16]                         ; ecx = first wanted (flags ommited)
334
 
336
 
335
    .find_wanted_start:
337
    .find_wanted_start:
336
        jecxz   .find_wanted_end
338
        jecxz   .find_wanted_end
337
        
339
        
338
    .find_wanted_cycle:
340
    .find_wanted_cycle:
339
        cmp     [ebx + EXT2_DIR_STRUC.inode], 0         ; Don't count unused inode in total files.
341
        cmp     [ebx + EXT2_DIR_STRUC.inode], 0         ; Don't count unused inode in total files.
340
        jz      @F
342
        jz      @F
341
 
343
 
342
        inc     dword [edi + 4]                         ; EXT2 files in folder.
344
        inc     dword [edi + 4]                         ; EXT2 files in folder.
343
        dec     ecx
345
        dec     ecx
344
    @@:
346
    @@:
345
        movzx   eax, [ebx + EXT2_DIR_STRUC.rec_len]
347
        movzx   eax, [ebx + EXT2_DIR_STRUC.rec_len]
346
        
348
        
347
        cmp     eax, 12                                 ; Minimum record length.
349
        cmp     eax, 12                                 ; Minimum record length.
348
        jb      .error_bad_len
350
        jb      .error_bad_len
349
        test    eax, 0x3                                ; Record length must be divisible by four.
351
        test    eax, 0x3                                ; Record length must be divisible by four.
350
        jnz     .error_bad_len
352
        jnz     .error_bad_len
351
 
353
 
352
        sub     [esi + EXT2_INODE_STRUC.i_size], eax    ; Subtract "processed record" length directly from inode.
354
        sub     [esi + EXT2_INODE_STRUC.i_size], eax    ; Subtract "processed record" length directly from inode.
353
        add     ebx, eax                                ; Go to next record.
355
        add     ebx, eax                                ; Go to next record.
354
        cmp     ebx, [edi + 24]                         ; If not reached the next block, continue.
356
        cmp     ebx, [edi + 24]                         ; If not reached the next block, continue.
355
        jb      .find_wanted_start
357
        jb      .find_wanted_start
356
 
358
 
357
        push    .find_wanted_start
359
        push    .find_wanted_start
358
   .end_block:                                          ; Get the next block.
360
   .end_block:                                          ; Get the next block.
359
        cmp     [esi + EXT2_INODE_STRUC.i_size], 0
361
        cmp     [esi + EXT2_INODE_STRUC.i_size], 0
360
        jle     .end_dir
362
        jle     .end_dir
361
 
363
 
362
        inc     dword [edi]                             ; Number of blocks read.
364
        inc     dword [edi]                             ; Number of blocks read.
363
        
365
        
364
        ; Read the next block.
366
        ; Read the next block.
365
        push    ecx
367
        push    ecx
366
        mov     ecx, [edi]
368
        mov     ecx, [edi]
367
        call    ext2_inode_get_block
369
        call    ext2_inode_get_block
368
        test    eax, eax
370
        test    eax, eax
369
        jnz     .error_get_block
371
        jnz     .error_get_block
370
 
372
 
371
        mov     eax, ecx
373
        mov     eax, ecx
372
        mov     ebx, [ebp + EXTFS.ext2_save_block]
374
        mov     ebx, [ebp + EXTFS.ext2_save_block]
373
        call    ext2_block_read
375
        call    ext2_block_read
374
        test    eax, eax
376
        test    eax, eax
375
        jnz     .error_get_block
377
        jnz     .error_get_block
376
        pop     ecx
378
        pop     ecx
377
 
379
 
378
        mov     eax, ebx
380
        mov     eax, ebx
379
        add     eax, [ebp + EXTFS.block_size]
381
        add     eax, [ebp + EXTFS.block_size]
380
        mov     [edi + 24], eax                         ; Update the end of the current block variable.  
382
        mov     [edi + 24], eax                         ; Update the end of the current block variable.  
381
        ret
383
        ret
382
 
384
 
383
    .wanted_end:
385
    .wanted_end:
384
        loop    .find_wanted_cycle                      ; Skip files till we reach wanted one.
386
        loop    .find_wanted_cycle                      ; Skip files till we reach wanted one.
385
        
387
        
386
    ; First requisite file.
388
    ; First requisite file.
387
    .find_wanted_end:
389
    .find_wanted_end:
388
        mov     ecx, [edi + 20]
390
        mov     ecx, [edi + 20]
389
    .wanted_start:                                      ; Look for first_wanted + count.
391
    .wanted_start:                                      ; Look for first_wanted + count.
390
        jecxz   .wanted_end
392
        jecxz   .wanted_end
391
 
393
 
392
        cmp     [ebx + EXT2_DIR_STRUC.inode], 0         ; if (inode == 0): not used;
394
        cmp     [ebx + EXT2_DIR_STRUC.inode], 0         ; if (inode == 0): not used;
393
        jz      .empty_rec
395
        jz      .empty_rec
394
 
396
 
395
        ; Increment "files in dir" and "read files" count.
397
        ; Increment "files in dir" and "read files" count.
396
        inc     dword [edi + 8]
398
        inc     dword [edi + 8]
397
        inc     dword [edi + 4]
399
        inc     dword [edi + 4]
398
 
400
 
399
        push    edi ecx
401
        push    edi ecx
400
        mov     edi, edx                                ; Zero out till the name field.
402
        mov     edi, edx                                ; Zero out till the name field.
401
        xor     eax, eax
403
        xor     eax, eax
402
        mov     ecx, 40 / 4
404
        mov     ecx, 40 / 4
403
        rep stosd
405
        rep stosd
404
        pop     ecx edi
406
        pop     ecx edi
405
 
407
 
406
        push    ebx edi edx
408
        push    ebx edi edx
407
        mov     eax, [ebx + EXT2_DIR_STRUC.inode]       ; Get the child inode.
409
        mov     eax, [ebx + EXT2_DIR_STRUC.inode]       ; Get the child inode.
408
        mov     ebx, [ebp + EXTFS.ext2_temp_inode]
410
        mov     ebx, [ebp + EXTFS.ext2_temp_inode]
409
        call    ext2_inode_read
411
        call    ext2_inode_read
410
        test    eax, eax
412
        test    eax, eax
411
        jnz     .error_read_subinode
413
        jnz     .error_read_subinode
412
 
414
 
413
        lea     edi, [edx + 8]
415
        lea     edi, [edx + 8]
414
 
416
 
415
        mov     eax, [ebx + EXT2_INODE_STRUC.i_ctime]   ; Convert time in NTFS format.
417
        mov     eax, [ebx + EXT2_INODE_STRUC.i_ctime]   ; Convert time in NTFS format.
416
        xor     edx, edx
418
        xor     edx, edx
417
        add     eax, 3054539008                         ; (369 * 365 + 89) * 24 * 3600
419
        add     eax, 3054539008                         ; (369 * 365 + 89) * 24 * 3600
418
        adc     edx, 2
420
        adc     edx, 2
419
        call    ntfs_datetime_to_bdfe.sec
421
        call    ntfs_datetime_to_bdfe.sec
420
 
422
 
421
        mov     eax, [ebx + EXT2_INODE_STRUC.i_atime]
423
        mov     eax, [ebx + EXT2_INODE_STRUC.i_atime]
422
        xor     edx, edx
424
        xor     edx, edx
423
        add     eax, 3054539008
425
        add     eax, 3054539008
424
        adc     edx, 2
426
        adc     edx, 2
425
        call    ntfs_datetime_to_bdfe.sec
427
        call    ntfs_datetime_to_bdfe.sec
426
 
428
 
427
        mov     eax, [ebx + EXT2_INODE_STRUC.i_mtime]
429
        mov     eax, [ebx + EXT2_INODE_STRUC.i_mtime]
428
        xor     edx, edx
430
        xor     edx, edx
429
        add     eax, 3054539008
431
        add     eax, 3054539008
430
        adc     edx, 2
432
        adc     edx, 2
431
        call    ntfs_datetime_to_bdfe.sec
433
        call    ntfs_datetime_to_bdfe.sec
432
 
434
 
433
        pop     edx
435
        pop     edx
434
        test    [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR ; If folder, don't report size.
436
        test    [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR ; If folder, don't report size.
435
        jnz     @F
437
        jnz     @F
436
 
438
 
437
        mov     eax, [ebx + EXT2_INODE_STRUC.i_size]    ; Low size
439
        mov     eax, [ebx + EXT2_INODE_STRUC.i_size]    ; Low size
438
        stosd
440
        stosd
439
        mov     eax, [ebx + EXT2_INODE_STRUC.i_dir_acl] ; High size
441
        mov     eax, [ebx + EXT2_INODE_STRUC.i_dir_acl] ; High size
440
        stosd
442
        stosd
441
 
443
 
442
        xor     dword [edx], FS_FT_DIR                  ; Mark as file.
444
        xor     dword [edx], FS_FT_DIR                  ; Mark as file.
443
    @@:
445
    @@:
444
        xor     dword [edx], FS_FT_DIR                  ; Mark as directory.
446
        xor     dword [edx], FS_FT_DIR                  ; Mark as directory.
445
 
447
 
446
        ; Copy name after converting from UTF-8 to CP866.
448
        ; Copy name after converting from UTF-8 to CP866.
447
        push    ecx esi
449
        push    ecx esi
448
        mov     esi, [esp + 12]
450
        mov     esi, [esp + 12]
449
        movzx   ecx, [esi + EXT2_DIR_STRUC.name_len]
451
        movzx   ecx, [esi + EXT2_DIR_STRUC.name_len]
450
        lea     edi, [edx + 40]
452
        lea     edi, [edx + 40]
451
        lea     esi, [esi + EXT2_DIR_STRUC.name]
453
        lea     esi, [esi + EXT2_DIR_STRUC.name]
452
        call    utf8_to_cp866
454
        call    utf8_to_cp866
453
        and     byte [edi], 0
455
        and     byte [edi], 0
454
        pop     esi ecx edi ebx
456
        pop     esi ecx edi ebx
455
 
457
 
456
        cmp     byte [edx + 40], '.'                    ; If it begins with ".", mark it as hidden.
458
        cmp     byte [edx + 40], '.'                    ; If it begins with ".", mark it as hidden.
457
        jne     @F
459
        jne     @F
458
        or      dword [edx], FS_FT_HIDDEN
460
        or      dword [edx], FS_FT_HIDDEN
459
    
461
    
460
    @@:
462
    @@:
461
        add     edx, 40 + 264                           ; Go to next record.
463
        add     edx, 40 + 264                           ; Go to next record.
462
        dec     ecx
464
        dec     ecx
463
    .empty_rec:
465
    .empty_rec:
464
        movzx   eax, [ebx + EXT2_DIR_STRUC.rec_len]
466
        movzx   eax, [ebx + EXT2_DIR_STRUC.rec_len]
465
 
467
 
466
        cmp     eax, 12                                 ; Illegal length.
468
        cmp     eax, 12                                 ; Illegal length.
467
        jb      .error_bad_len
469
        jb      .error_bad_len
468
        test    eax, 0x3                                ; Not a multiple of four.
470
        test    eax, 0x3                                ; Not a multiple of four.
469
        jnz     .error_bad_len
471
        jnz     .error_bad_len
470
 
472
 
471
        sub     [esi + EXT2_INODE_STRUC.i_size], eax    ; Subtract directly from the inode.
473
        sub     [esi + EXT2_INODE_STRUC.i_size], eax    ; Subtract directly from the inode.
472
        add     ebx, eax     
474
        add     ebx, eax     
473
        cmp     ebx, [edi + 24]                         ; Are we at the end of the block?
475
        cmp     ebx, [edi + 24]                         ; Are we at the end of the block?
474
        jb      .wanted_start
476
        jb      .wanted_start
475
 
477
 
476
        push    .wanted_start 
478
        push    .wanted_start 
477
        jmp     .end_block
479
        jmp     .end_block
478
 
480
 
479
    .end_dir:                                           ; End of the directory.
481
    .end_dir:                                           ; End of the directory.
480
        call    ext2_unlock
482
        call    ext2_unlock
481
        mov     edx, [edi + 28]                         ; Address of where to return data.
483
        mov     edx, [edi + 28]                         ; Address of where to return data.
482
        mov     ebx, [edi + 8]                          ; EXT2_read_in_folder
484
        mov     ebx, [edi + 8]                          ; EXT2_read_in_folder
483
        mov     ecx, [edi + 4]                          ; EXT2_files_in_folder
485
        mov     ecx, [edi + 4]                          ; EXT2_files_in_folder
484
        mov     dword [edx], 1                          ; Version
486
        mov     dword [edx], 1                          ; Version
485
        mov     [edx + 4], ebx
487
        mov     [edx + 4], ebx
486
        mov     [edx + 8], ecx
488
        mov     [edx + 8], ecx
487
        
489
        
488
        lea     esp, [edi + 32]
490
        lea     esp, [edi + 32]
489
        
491
        
490
        xor     eax, eax                                ; Reserved in current implementation.
492
        xor     eax, eax                                ; Reserved in current implementation.
491
        lea     edi, [edx + 12]
493
        lea     edi, [edx + 12]
492
        mov     ecx, 20 / 4
494
        mov     ecx, 20 / 4
493
        rep stosd
495
        rep stosd
494
 
496
 
495
        ;DEBUGF  1, "Returning with: %x.\n", eax
497
        ;DEBUGF  1, "Returning with: %x.\n", eax
496
        ret
498
        ret
497
 
499
 
498
    .error_bad_len:
500
    .error_bad_len:
499
        mov     eax, ERROR_FS_FAIL
501
        mov     eax, ERROR_FS_FAIL
500
 
502
 
501
    .error_read_subinode:
503
    .error_read_subinode:
502
    .error_get_block:
504
    .error_get_block:
503
        ; Fix the stack.
505
        ; Fix the stack.
504
        lea     esp, [edi + 32]
506
        lea     esp, [edi + 32]
505
 
507
 
506
    .error_ret:
508
    .error_ret:
507
        or      ebx, -1
509
        or      ebx, -1
508
        push    eax
510
        push    eax
509
        call    ext2_unlock
511
        call    ext2_unlock
510
        pop     eax
512
        pop     eax
511
        ;DEBUGF  1, "Returning with: %x.\n", eax
513
        ;DEBUGF  1, "Returning with: %x.\n", eax
512
        ret
514
        ret
513
        
515
        
514
    .error_empty_dir:                                   ; inode of folder without blocks.
516
    .error_empty_dir:                                   ; inode of folder without blocks.
515
    .error_root:                                        ; Root has to be a folder.
517
    .error_root:                                        ; Root has to be a folder.
516
        mov     eax, ERROR_FS_FAIL
518
        mov     eax, ERROR_FS_FAIL
517
        jmp     .error_ret
519
        jmp     .error_ret
518
 
520
 
519
    .error_not_found:                                   ; Directory not found.
521
    .error_not_found:                                   ; Directory not found.
520
        mov     eax, ERROR_FILE_NOT_FOUND
522
        mov     eax, ERROR_FILE_NOT_FOUND
521
        jmp     .error_ret
523
        jmp     .error_ret
522
 
524
 
523
;---------------------------------------------------------------------
525
;---------------------------------------------------------------------
524
; Read file from the hard disk.
526
; Read file from the hard disk.
525
; Input:        esi + [esp + 4] = points to file name.
527
; Input:        esi + [esp + 4] = points to file name.
526
;               ebx = pointer to paramteres from sysfunc 70.
528
;               ebx = pointer to paramteres from sysfunc 70.
527
;               ebp = pointer to EXTFS structure.
529
;               ebp = pointer to EXTFS structure.
528
; Output:       ebx = bytes read (0xFFFFFFFF -> file not found)
530
; Output:       ebx = bytes read (0xFFFFFFFF -> file not found)
529
;               eax = error code (0 implies no error)
531
;               eax = error code (0 implies no error)
530
;---------------------------------------------------------------------
532
;---------------------------------------------------------------------
531
ext2_Read:
533
ext2_Read:
532
        ;DEBUGF  1, "Attempting read.\n"
534
        ;DEBUGF  1, "Attempting read.\n"
533
        call    ext2_lock
535
        call    ext2_lock
534
        cmp     byte [esi], 0
536
        cmp     byte [esi], 0
535
        jnz     @F
537
        jnz     @F
536
 
538
 
537
    .this_is_nofile:
539
    .this_is_nofile:
538
        call    ext2_unlock
540
        call    ext2_unlock
539
        or      ebx, -1
541
        or      ebx, -1
540
        mov     eax, ERROR_ACCESS_DENIED
542
        mov     eax, ERROR_ACCESS_DENIED
541
        ret
543
        ret
542
 
544
 
543
    @@:
545
    @@:
544
        push    ebx
546
        push    ebx
545
        stdcall ext2_inode_find, [esp + 4 + 4]
547
        stdcall ext2_inode_find, [esp + 4 + 4]
546
        pop     ebx
548
        pop     ebx
547
 
549
 
548
        mov     esi, [ebp + EXTFS.ext2_save_inode]
550
        mov     esi, [ebp + EXTFS.ext2_save_inode]
549
        test    eax, eax
551
        test    eax, eax
550
        jz      @F
552
        jz      @F
551
 
553
 
552
        call    ext2_unlock
554
        call    ext2_unlock
553
        or      ebx, -1
555
        or      ebx, -1
554
        mov     eax, ERROR_FILE_NOT_FOUND
556
        mov     eax, ERROR_FILE_NOT_FOUND
555
        ret
557
        ret
556
 
558
 
557
    @@:
559
    @@:
558
        mov     ax, [esi + EXT2_INODE_STRUC.i_mode]
560
        mov     ax, [esi + EXT2_INODE_STRUC.i_mode]
559
        and     ax, EXT2_S_IFMT                         ; Leave the file format in AX.
561
        and     ax, EXT2_S_IFMT                         ; Leave the file format in AX.
560
 
562
 
561
        ; Check if file.
563
        ; Check if file.
562
        cmp     ax, EXT2_S_IFREG
564
        cmp     ax, EXT2_S_IFREG
563
        jne     .this_is_nofile
565
        jne     .this_is_nofile
564
 
566
 
565
        mov     edi, [ebx + 16]
567
        mov     edi, [ebx + 16]
566
        mov     ecx, [ebx + 12]
568
        mov     ecx, [ebx + 12]
567
 
569
 
568
        mov     eax, [ebx + 4]
570
        mov     eax, [ebx + 4]
569
        mov     edx, [ebx + 8]                          ; edx:eax = start byte number.
571
        mov     edx, [ebx + 8]                          ; edx:eax = start byte number.
570
 
572
 
571
        ; Check if file is big enough for us.
573
        ; Check if file is big enough for us.
572
        cmp     [esi + EXT2_INODE_STRUC.i_dir_acl], edx
574
        cmp     [esi + EXT2_INODE_STRUC.i_dir_acl], edx
573
        ja      .size_greater
575
        ja      .size_greater
574
        jb      .size_less
576
        jb      .size_less
575
 
577
 
576
        cmp     [esi + EXT2_INODE_STRUC.i_size], eax
578
        cmp     [esi + EXT2_INODE_STRUC.i_size], eax
577
        ja      .size_greater
579
        ja      .size_greater
578
 
580
 
579
    .size_less:
581
    .size_less:
580
        call    ext2_unlock
582
        call    ext2_unlock
581
        xor     ebx, ebx
583
        xor     ebx, ebx
582
        mov     eax, ERROR_END_OF_FILE
584
        mov     eax, ERROR_END_OF_FILE
583
        ret
585
        ret
584
        
586
        
585
    @@:
587
    @@:
586
    .size_greater:
588
    .size_greater:
587
        add     eax, ecx                                ; Get last byte.
589
        add     eax, ecx                                ; Get last byte.
588
        adc     edx, 0
590
        adc     edx, 0
589
 
591
 
590
        ; Check if we've to read whole file, or till requested.
592
        ; Check if we've to read whole file, or till requested.
591
        cmp     [esi + EXT2_INODE_STRUC.i_dir_acl], edx
593
        cmp     [esi + EXT2_INODE_STRUC.i_dir_acl], edx
592
        ja      .read_till_requested
594
        ja      .read_till_requested
593
        jb      .read_whole_file
595
        jb      .read_whole_file
594
        cmp     [esi + EXT2_INODE_STRUC.i_size], eax
596
        cmp     [esi + EXT2_INODE_STRUC.i_size], eax
595
        jae     .read_till_requested
597
        jae     .read_till_requested
596
 
598
 
597
    .read_whole_file:
599
    .read_whole_file:
598
        push    1                                       ; Read till the end of file.
600
        push    1                                       ; Read till the end of file.
599
        mov     ecx, [esi + EXT2_INODE_STRUC.i_size]
601
        mov     ecx, [esi + EXT2_INODE_STRUC.i_size]
600
        sub     ecx, [ebx + 4]                          ; To read = (size - starting byte)
602
        sub     ecx, [ebx + 4]                          ; To read = (size - starting byte)
601
        jmp     @F
603
        jmp     @F
602
 
604
 
603
    .read_till_requested:
605
    .read_till_requested:
604
        push    0                                       ; Read as much as requested.
606
        push    0                                       ; Read as much as requested.
605
 
607
 
606
    @@:
608
    @@:
607
        ; ecx = bytes to read.
609
        ; ecx = bytes to read.
608
        ; edi = return memory
610
        ; edi = return memory
609
        ; [esi] = starting byte.
611
        ; [esi] = starting byte.
610
 
612
 
611
        push    ecx                                     ; Number of bytes to read.
613
        push    ecx                                     ; Number of bytes to read.
612
        
614
        
613
        ; Get part of the first block.
615
        ; Get part of the first block.
614
        mov     edx, [ebx + 8]
616
        mov     edx, [ebx + 8]
615
        mov     eax, [ebx + 4]
617
        mov     eax, [ebx + 4]
616
        div     [ebp + EXTFS.block_size]
618
        div     [ebp + EXTFS.block_size]
617
 
619
 
618
        push    eax                                     ; Save block counter to stack.
620
        push    eax                                     ; Save block counter to stack.
619
        
621
        
620
        push    ecx
622
        push    ecx
621
        mov     ecx, eax
623
        mov     ecx, eax
622
        call    ext2_inode_get_block
624
        call    ext2_inode_get_block
623
        test    eax, eax
625
        test    eax, eax
624
        jnz     .error_at_first_block
626
        jnz     .error_at_first_block
625
 
627
 
626
        mov     ebx, [ebp + EXTFS.ext2_save_block]
628
        mov     ebx, [ebp + EXTFS.ext2_save_block]
627
        mov     eax, ecx
629
        mov     eax, ecx
628
        call    ext2_block_read
630
        call    ext2_block_read
629
        test    eax, eax
631
        test    eax, eax
630
        jnz     .error_at_first_block
632
        jnz     .error_at_first_block
631
 
633
 
632
        pop     ecx
634
        pop     ecx
633
        ; Get index inside block.
635
        ; Get index inside block.
634
        add     ebx, edx
636
        add     ebx, edx
635
 
637
 
636
        neg     edx
638
        neg     edx
637
        add     edx, [ebp + EXTFS.block_size]          ; Get number of bytes in this block.
639
        add     edx, [ebp + EXTFS.block_size]          ; Get number of bytes in this block.
638
 
640
 
639
        ; If it's smaller than total bytes to read, then only one block.
641
        ; If it's smaller than total bytes to read, then only one block.
640
        cmp     ecx, edx
642
        cmp     ecx, edx
641
        jbe     .only_one_block
643
        jbe     .only_one_block
642
 
644
 
643
        mov     eax, ecx
645
        mov     eax, ecx
644
        sub     eax, edx
646
        sub     eax, edx
645
        mov     ecx, edx
647
        mov     ecx, edx
646
 
648
 
647
        push    esi
649
        push    esi
648
        mov     esi, ebx
650
        mov     esi, ebx
649
        rep movsb                                       ; Copy part of 1st block.
651
        rep movsb                                       ; Copy part of 1st block.
650
        pop     esi
652
        pop     esi
651
 
653
 
652
        ; eax -> bytes to read.
654
        ; eax -> bytes to read.
653
    .calc_blocks_count:
655
    .calc_blocks_count:
654
        mov     ebx, edi                                ; Read the block in ebx.
656
        mov     ebx, edi                                ; Read the block in ebx.
655
        xor     edx, edx
657
        xor     edx, edx
656
        div     [ebp + EXTFS.block_size]                ; Get number of bytes in last block in edx.
658
        div     [ebp + EXTFS.block_size]                ; Get number of bytes in last block in edx.
657
        mov     edi, eax                                ; Get number of blocks in edi.
659
        mov     edi, eax                                ; Get number of blocks in edi.
658
 
660
 
659
    @@:
661
    @@:
660
        ; Test if all blocks are done.
662
        ; Test if all blocks are done.
661
        test    edi, edi
663
        test    edi, edi
662
        jz      .finish_block
664
        jz      .finish_block
663
        
665
        
664
        inc     dword [esp]
666
        inc     dword [esp]
665
        mov     ecx, [esp]
667
        mov     ecx, [esp]
666
        call    ext2_inode_get_block
668
        call    ext2_inode_get_block
667
 
669
 
668
        test    eax, eax
670
        test    eax, eax
669
        jnz     .error_at_read_cycle
671
        jnz     .error_at_read_cycle
670
 
672
 
671
        mov     eax, ecx                                ; ebx already contains desired values.
673
        mov     eax, ecx                                ; ebx already contains desired values.
672
        call    ext2_block_read
674
        call    ext2_block_read
673
 
675
 
674
        test    eax, eax
676
        test    eax, eax
675
        jnz     .error_at_read_cycle
677
        jnz     .error_at_read_cycle
676
 
678
 
677
        add     ebx, [ebp + EXTFS.block_size]
679
        add     ebx, [ebp + EXTFS.block_size]
678
 
680
 
679
        dec     edi
681
        dec     edi
680
        jmp     @B
682
        jmp     @B
681
 
683
 
682
    ; In edx -- number of bytes in the last block.
684
    ; In edx -- number of bytes in the last block.
683
    .finish_block:          
685
    .finish_block:          
684
        test    edx, edx
686
        test    edx, edx
685
        jz      .end_read
687
        jz      .end_read
686
 
688
 
687
        pop     ecx                                     ; Pop block counter in ECX.
689
        pop     ecx                                     ; Pop block counter in ECX.
688
        inc     ecx
690
        inc     ecx
689
        call    ext2_inode_get_block
691
        call    ext2_inode_get_block
690
        
692
        
691
        test    eax, eax
693
        test    eax, eax
692
        jnz     .error_at_finish_block
694
        jnz     .error_at_finish_block
693
 
695
 
694
        mov     edi, ebx
696
        mov     edi, ebx
695
        mov     eax, ecx
697
        mov     eax, ecx
696
        mov     ebx, [ebp + EXTFS.ext2_save_block]
698
        mov     ebx, [ebp + EXTFS.ext2_save_block]
697
        call    ext2_block_read
699
        call    ext2_block_read
698
 
700
 
699
        test    eax, eax
701
        test    eax, eax
700
        jnz     .error_at_finish_block
702
        jnz     .error_at_finish_block
701
 
703
 
702
        mov     ecx, edx
704
        mov     ecx, edx
703
        mov     esi, ebx
705
        mov     esi, ebx
704
        rep movsb                                       ; Copy last piece of block.
706
        rep movsb                                       ; Copy last piece of block.
705
        jmp     @F
707
        jmp     @F
706
 
708
 
707
    .end_read:
709
    .end_read:
708
        pop     ecx                                     ; Pop block counter in ECX.
710
        pop     ecx                                     ; Pop block counter in ECX.
709
    @@:
711
    @@:
710
        pop     ebx                                     ; Number of bytes read.
712
        pop     ebx                                     ; Number of bytes read.
711
        call    ext2_unlock
713
        call    ext2_unlock
712
        pop     eax                                     ; If we were asked to read more, say EOF.
714
        pop     eax                                     ; If we were asked to read more, say EOF.
713
        test    eax, eax
715
        test    eax, eax
714
        jz      @F
716
        jz      @F
715
 
717
 
716
        mov     eax, ERROR_END_OF_FILE
718
        mov     eax, ERROR_END_OF_FILE
717
        ret
719
        ret
718
    @@:
720
    @@:
719
        xor     eax, eax
721
        xor     eax, eax
720
        ;DEBUGF  1, "Returning with: %x.\n", eax
722
        ;DEBUGF  1, "Returning with: %x.\n", eax
721
        ret
723
        ret
722
        
724
        
723
    .only_one_block:
725
    .only_one_block:
724
        mov     esi, ebx
726
        mov     esi, ebx
725
        rep movsb                                       ; Copy last piece of block.
727
        rep movsb                                       ; Copy last piece of block.
726
        jmp     .end_read
728
        jmp     .end_read
727
        
729
        
728
    .error_at_first_block:
730
    .error_at_first_block:
729
        pop     edx
731
        pop     edx
730
    .error_at_read_cycle:
732
    .error_at_read_cycle:
731
        pop     ebx
733
        pop     ebx
732
    .error_at_finish_block:
734
    .error_at_finish_block:
733
        pop     ecx edx
735
        pop     ecx edx
734
        or      ebx, -1
736
        or      ebx, -1
735
        push    eax
737
        push    eax
736
        call    ext2_unlock
738
        call    ext2_unlock
737
        pop     eax
739
        pop     eax
738
 
740
 
739
        ;DEBUGF  1, "Returning with: %x.\n", eax
741
        ;DEBUGF  1, "Returning with: %x.\n", eax
740
        ret
742
        ret
741
 
743
 
742
;---------------------------------------------------------------------
744
;---------------------------------------------------------------------
743
; Read file information from block device.
745
; Read file information from block device.
744
; Input:        esi + [esp + 4] = file name.
746
; Input:        esi + [esp + 4] = file name.
745
;               ebx = pointer to paramteres from sysfunc 70.
747
;               ebx = pointer to paramteres from sysfunc 70.
746
;               ebp = pointer to EXTFS structure.
748
;               ebp = pointer to EXTFS structure.
747
; Output:       eax = error code.
749
; Output:       eax = error code.
748
;---------------------------------------------------------------------
750
;---------------------------------------------------------------------
749
ext2_GetFileInfo:
751
ext2_GetFileInfo:
750
        ;DEBUGF  1, "Calling for file info, for: %s.\n", esi
752
        ;DEBUGF  1, "Calling for file info, for: %s.\n", esi
751
        call    ext2_lock
753
        call    ext2_lock
752
        mov     edx, [ebx + 16]
754
        mov     edx, [ebx + 16]
753
        cmp     byte [esi], 0
755
        cmp     byte [esi], 0
754
        jz      .is_root
756
        jz      .is_root
755
 
757
 
756
        push    edx
758
        push    edx
757
        stdcall ext2_inode_find, [esp + 4 + 4]
759
        stdcall ext2_inode_find, [esp + 4 + 4]
758
        mov     ebx, edx
760
        mov     ebx, edx
759
        pop     edx
761
        pop     edx
760
        
762
        
761
        mov     esi, [ebp + EXTFS.ext2_save_inode]
763
        mov     esi, [ebp + EXTFS.ext2_save_inode]
762
        test    eax, eax
764
        test    eax, eax
763
        jz      @F
765
        jz      @F
764
 
766
 
765
        push    eax
767
        push    eax
766
        call    ext2_unlock
768
        call    ext2_unlock
767
        pop     eax
769
        pop     eax
768
        ;DEBUGF  1, "Returning with: %x.\n", eax
770
        ;DEBUGF  1, "Returning with: %x.\n", eax
769
        ret
771
        ret
770
 
772
 
771
    .is_root:      
773
    .is_root:      
772
        xor     ebx, ebx                                ; Clear out first char, since we don't want to set hidden flag on root.
774
        xor     ebx, ebx                                ; Clear out first char, since we don't want to set hidden flag on root.
773
        mov     esi, [ebp + EXTFS.root_inode]
775
        mov     esi, [ebp + EXTFS.root_inode]
774
 
776
 
775
    @@:
777
    @@:
776
        xor     eax, eax
778
        xor     eax, eax
777
        mov     edi, edx
779
        mov     edi, edx
778
        mov     ecx, 40/4
780
        mov     ecx, 40/4
779
        rep stosd                                       ; Zero fill buffer.
781
        rep stosd                                       ; Zero fill buffer.
780
 
782
 
781
        cmp     bl, '.'
783
        cmp     bl, '.'
782
        jne     @F
784
        jne     @F
783
        or      dword [edx], FS_FT_HIDDEN
785
        or      dword [edx], FS_FT_HIDDEN
784
 
786
 
785
    @@:
787
    @@:
786
        test    [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
788
        test    [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
787
        jnz     @F                                      ; If a directory, don't put in file size.
789
        jnz     @F                                      ; If a directory, don't put in file size.
788
 
790
 
789
        mov     eax, [esi + EXT2_INODE_STRUC.i_size]    ; Low file size.
791
        mov     eax, [esi + EXT2_INODE_STRUC.i_size]    ; Low file size.
790
        mov     ebx, [esi + EXT2_INODE_STRUC.i_dir_acl] ; High file size.
792
        mov     ebx, [esi + EXT2_INODE_STRUC.i_dir_acl] ; High file size.
791
        mov     dword [edx+32], eax
793
        mov     dword [edx+32], eax
792
        mov     dword [edx+36], ebx
794
        mov     dword [edx+36], ebx
793
 
795
 
794
        xor     dword [edx], FS_FT_DIR                  ; Next XOR will clean this, to mark it as a file.
796
        xor     dword [edx], FS_FT_DIR                  ; Next XOR will clean this, to mark it as a file.
795
    @@:
797
    @@:
796
        xor     dword [edx], FS_FT_DIR                  ; Mark as directory.
798
        xor     dword [edx], FS_FT_DIR                  ; Mark as directory.
797
 
799
 
798
        lea     edi, [edx + 8]
800
        lea     edi, [edx + 8]
799
 
801
 
800
        ; Store all time.
802
        ; Store all time.
801
        mov     eax, [esi + EXT2_INODE_STRUC.i_ctime]
803
        mov     eax, [esi + EXT2_INODE_STRUC.i_ctime]
802
        xor     edx, edx
804
        xor     edx, edx
803
        add     eax, 3054539008
805
        add     eax, 3054539008
804
        adc     edx, 2
806
        adc     edx, 2
805
        call    ntfs_datetime_to_bdfe.sec
807
        call    ntfs_datetime_to_bdfe.sec
806
 
808
 
807
        mov     eax, [esi + EXT2_INODE_STRUC.i_atime]
809
        mov     eax, [esi + EXT2_INODE_STRUC.i_atime]
808
        xor     edx, edx
810
        xor     edx, edx
809
        add     eax, 3054539008
811
        add     eax, 3054539008
810
        adc     edx, 2
812
        adc     edx, 2
811
        call    ntfs_datetime_to_bdfe.sec
813
        call    ntfs_datetime_to_bdfe.sec
812
 
814
 
813
        mov     eax, [esi + EXT2_INODE_STRUC.i_mtime]
815
        mov     eax, [esi + EXT2_INODE_STRUC.i_mtime]
814
        xor     edx, edx
816
        xor     edx, edx
815
        add     eax, 3054539008
817
        add     eax, 3054539008
816
        adc     edx, 2
818
        adc     edx, 2
817
        call    ntfs_datetime_to_bdfe.sec
819
        call    ntfs_datetime_to_bdfe.sec
818
 
820
 
819
        call    ext2_unlock
821
        call    ext2_unlock
820
        xor     eax, eax
822
        xor     eax, eax
821
        ;DEBUGF  1, "Returning with: %x.\n", eax
823
        ;DEBUGF  1, "Returning with: %x.\n", eax
822
        ret
824
        ret
823
 
825
 
824
;---------------------------------------------------------------------
826
;---------------------------------------------------------------------
825
; Set file information for block device.
827
; Set file information for block device.
826
; Input:        esi + [esp + 4] = file name.
828
; Input:        esi + [esp + 4] = file name.
827
;               ebx = pointer to paramteres from sysfunc 70.
829
;               ebx = pointer to paramteres from sysfunc 70.
828
;               ebp = pointer to EXTFS structure.
830
;               ebp = pointer to EXTFS structure.
829
; Output:       eax = error code.
831
; Output:       eax = error code.
830
;---------------------------------------------------------------------
832
;---------------------------------------------------------------------
831
ext2_SetFileInfo:
833
ext2_SetFileInfo:
832
        test    [ebp + EXTFS.partition_flags], EXT2_RO
834
        test    [ebp + EXTFS.partition_flags], EXT2_RO
833
        jz      @F
835
        jz      @F
834
 
836
 
835
        mov     eax, ERROR_UNSUPPORTED_FS
837
        mov     eax, ERROR_UNSUPPORTED_FS
836
        ret
838
        ret
837
 
839
 
838
    @@:    
840
    @@:    
839
        push    edx esi edi ebx
841
        push    edx esi edi ebx
840
        call    ext2_lock
842
        call    ext2_lock
841
        mov     edx, [ebx + 16]
843
        mov     edx, [ebx + 16]
842
 
844
 
843
        ; Is this read-only?
845
        ; Is this read-only?
844
        test    [ebp + EXTFS.partition_flags], EXT2_RO
846
        test    [ebp + EXTFS.partition_flags], EXT2_RO
845
        jnz     .fail
847
        jnz     .fail
846
 
848
 
847
        ; Not supported for root.
849
        ; Not supported for root.
848
        cmp     byte [esi], 0
850
        cmp     byte [esi], 0
849
        je      .fail
851
        je      .fail
850
 
852
 
851
    .get_inode:
853
    .get_inode:
852
        push    edx
854
        push    edx
853
        stdcall ext2_inode_find, [esp + 4 + 20]
855
        stdcall ext2_inode_find, [esp + 4 + 20]
854
        pop     edx
856
        pop     edx
855
 
857
 
856
        test    eax, eax
858
        test    eax, eax
857
        jnz     @F
859
        jnz     @F
858
 
860
 
859
        ; Save inode number.
861
        ; Save inode number.
860
        push    esi
862
        push    esi
861
        mov     esi, [ebp + EXTFS.ext2_save_inode]
863
        mov     esi, [ebp + EXTFS.ext2_save_inode]
862
 
864
 
863
        ; From the BDFE, we ignore read-only file flags, hidden file flags;
865
        ; From the BDFE, we ignore read-only file flags, hidden file flags;
864
        ; We ignore system file flags, file was archived or not.
866
        ; We ignore system file flags, file was archived or not.
865
 
867
 
866
        ; Also ignored is file creation time. ext2 stores "inode modification"
868
        ; Also ignored is file creation time. ext2 stores "inode modification"
867
        ; time in the ctime field, which is updated by the respective inode_write
869
        ; time in the ctime field, which is updated by the respective inode_write
868
        ; procedure, and any writes on it would be overwritten anyway.
870
        ; procedure, and any writes on it would be overwritten anyway.
869
 
871
 
870
        ; Access time.
872
        ; Access time.
871
        lea     edi, [esi + EXT2_INODE_STRUC.i_atime]
873
        lea     edi, [esi + EXT2_INODE_STRUC.i_atime]
872
        lea     esi, [edx + 16]
874
        lea     esi, [edx + 16]
873
        call    bdfe_to_unix_time
875
        call    bdfe_to_unix_time
874
 
876
 
875
        ; Modification time.
877
        ; Modification time.
876
        add     esi, 8
878
        add     esi, 8
877
        add     edi, 8
879
        add     edi, 8
878
        call    bdfe_to_unix_time
880
        call    bdfe_to_unix_time
879
 
881
 
880
        mov     ebx, [ebp + EXTFS.ext2_save_inode] ; Get address of inode into ebx.
882
        mov     ebx, [ebp + EXTFS.ext2_save_inode] ; Get address of inode into ebx.
881
        pop     eax                             ; Get inode number in eax.
883
        pop     eax                             ; Get inode number in eax.
882
        call    ext2_inode_write                ; eax contains error code, if any.
884
        call    ext2_inode_write                ; eax contains error code, if any.
883
        test    eax, eax
885
        test    eax, eax
884
        jnz     @F
886
        jnz     @F
885
 
887
 
886
        call    ext2_sb_update
888
        call    ext2_sb_update
887
        ; Sync the disk.
889
        ; Sync the disk.
888
        mov     esi, [ebp + PARTITION.Disk]
890
        mov     esi, [ebp + PARTITION.Disk]
889
        call    disk_sync                       ; eax contains error code, if any.
891
        call    disk_sync                       ; eax contains error code, if any.
890
 
892
 
891
    @@:
893
    @@:
892
        push    eax
894
        push    eax
893
        call    ext2_unlock
895
        call    ext2_unlock
894
        pop     eax
896
        pop     eax
895
 
897
 
896
        pop     ebx edi esi edx
898
        pop     ebx edi esi edx
897
        ret
899
        ret
898
 
900
 
899
    .fail:
901
    .fail:
900
        call    ext2_sb_update
902
        call    ext2_sb_update
901
        ; Sync the disk.
903
        ; Sync the disk.
902
        mov     esi, [ebp + PARTITION.Disk]
904
        mov     esi, [ebp + PARTITION.Disk]
903
        call    disk_sync                       ; eax contains error code, if any.
905
        call    disk_sync                       ; eax contains error code, if any.
904
 
906
 
905
        mov     eax, ERROR_UNSUPPORTED_FS
907
        mov     eax, ERROR_UNSUPPORTED_FS
906
        jmp     @B
908
        jmp     @B
907
 
909
 
908
;---------------------------------------------------------------------
910
;---------------------------------------------------------------------
909
; Set file information for block device.
911
; Set file information for block device.
910
; Input:        esi + [esp + 4] = file name.
912
; Input:        esi + [esp + 4] = file name.
911
;               ebx = pointer to paramteres from sysfunc 70.
913
;               ebx = pointer to paramteres from sysfunc 70.
912
;               ebp = pointer to EXTFS structure.
914
;               ebp = pointer to EXTFS structure.
913
; Output:       eax = error code.
915
; Output:       eax = error code.
914
;---------------------------------------------------------------------
916
;---------------------------------------------------------------------
915
ext2_Delete:
917
ext2_Delete:
916
        ;DEBUGF  1, "Attempting Delete.\n"
918
        ;DEBUGF  1, "Attempting Delete.\n"
917
        test    [ebp + EXTFS.partition_flags], EXT2_RO
919
        test    [ebp + EXTFS.partition_flags], EXT2_RO
918
        jz      @F
920
        jz      @F
919
 
921
 
920
        mov     eax, ERROR_UNSUPPORTED_FS
922
        mov     eax, ERROR_UNSUPPORTED_FS
921
        ret
923
        ret
922
 
924
 
923
    @@:    
925
    @@:    
924
        push    ebx ecx edx esi edi
926
        push    ebx ecx edx esi edi
925
        call    ext2_lock
927
        call    ext2_lock
926
 
928
 
927
        add     esi, [esp + 20 + 4]
929
        add     esi, [esp + 20 + 4]
928
 
930
 
929
        ; Can't delete root.
931
        ; Can't delete root.
930
        cmp     byte [esi], 0
932
        cmp     byte [esi], 0
931
        jz      .error_access_denied
933
        jz      .error_access_denied
932
 
934
 
933
        push    esi 
935
        push    esi 
934
        stdcall ext2_inode_find, 0
936
        stdcall ext2_inode_find, 0
935
        mov     ebx, esi
937
        mov     ebx, esi
936
        pop     esi
938
        pop     esi
937
 
939
 
938
        test    eax, eax
940
        test    eax, eax
939
        jnz     .error_access_denied
941
        jnz     .error_access_denied
940
 
942
 
941
        mov     edx, [ebp + EXTFS.ext2_save_inode]
943
        mov     edx, [ebp + EXTFS.ext2_save_inode]
942
        movzx   edx, [edx + EXT2_INODE_STRUC.i_mode]
944
        movzx   edx, [edx + EXT2_INODE_STRUC.i_mode]
943
        and     edx, EXT2_S_IFMT                                ; Get the mask.
945
        and     edx, EXT2_S_IFMT                                ; Get the mask.
944
        cmp     edx, EXT2_S_IFDIR
946
        cmp     edx, EXT2_S_IFDIR
945
        jne     @F                                              ; If not a directory, we don't need to check if it's empty.
947
        jne     @F                                              ; If not a directory, we don't need to check if it's empty.
946
 
948
 
947
        call    ext2_dir_empty                                  ; 0 means directory is empty.
949
        call    ext2_dir_empty                                  ; 0 means directory is empty.
948
 
950
 
949
        test    eax, eax
951
        test    eax, eax
950
        jnz     .error_access_denied
952
        jnz     .error_access_denied
951
 
953
 
952
    @@:
954
    @@:
953
        ; Find parent.
955
        ; Find parent.
954
        call    ext2_inode_find_parent
956
        call    ext2_inode_find_parent
955
        test    eax, eax
957
        test    eax, eax
956
        jnz     .error_access_denied
958
        jnz     .error_access_denied
957
        mov     eax, esi
959
        mov     eax, esi
958
 
960
 
959
        ; Save file/dir & parent inode.
961
        ; Save file/dir & parent inode.
960
        push    ebx eax
962
        push    ebx eax
961
 
963
 
962
        cmp     edx, EXT2_S_IFDIR
964
        cmp     edx, EXT2_S_IFDIR
963
        jne     @F      
965
        jne     @F      
964
 
966
 
965
        ; Unlink '.'
967
        ; Unlink '.'
966
        mov     eax, [esp + 4]
968
        mov     eax, [esp + 4]
967
        call    ext2_inode_unlink
969
        call    ext2_inode_unlink
968
        cmp     eax, 0xFFFFFFFF
970
        cmp     eax, 0xFFFFFFFF
969
        je      .error_stack8
971
        je      .error_stack8
970
 
972
 
971
        ; Unlink '..'
973
        ; Unlink '..'
972
        mov     eax, [esp + 4]
974
        mov     eax, [esp + 4]
973
        mov     ebx, [esp]
975
        mov     ebx, [esp]
974
        call    ext2_inode_unlink
976
        call    ext2_inode_unlink
975
        cmp     eax, 0xFFFFFFFF
977
        cmp     eax, 0xFFFFFFFF
976
        je      .error_stack8
978
        je      .error_stack8
977
 
979
 
978
    @@:
980
    @@:
979
        pop     eax
981
        pop     eax
980
        mov     ebx, [esp]
982
        mov     ebx, [esp]
981
        ; Unlink the inode.
983
        ; Unlink the inode.
982
        call    ext2_inode_unlink
984
        call    ext2_inode_unlink
983
        cmp     eax, 0xFFFFFFFF
985
        cmp     eax, 0xFFFFFFFF
984
        je      .error_stack4
986
        je      .error_stack4
985
        
987
        
986
        ; If hardlinks aren't zero, shouldn't completely free.
988
        ; If hardlinks aren't zero, shouldn't completely free.
987
        test    eax, eax
989
        test    eax, eax
988
        jz      @F
990
        jz      @F
989
 
991
 
990
        add     esp, 4
992
        add     esp, 4
991
        jmp     .disk_sync
993
        jmp     .disk_sync
992
 
994
 
993
    @@:
995
    @@:
994
        ; Read the inode.
996
        ; Read the inode.
995
        mov     eax, [esp]
997
        mov     eax, [esp]
996
        mov     ebx, [ebp + EXTFS.ext2_save_inode]
998
        mov     ebx, [ebp + EXTFS.ext2_save_inode]
997
        call    ext2_inode_read
999
        call    ext2_inode_read
998
        test    eax, eax
1000
        test    eax, eax
999
        jnz     .error_stack4
1001
        jnz     .error_stack4
1000
        
1002
        
1001
        ; Free inode data.
1003
        ; Free inode data.
1002
        mov     esi, [ebp + EXTFS.ext2_save_inode]
1004
        mov     esi, [ebp + EXTFS.ext2_save_inode]
1003
        xor     ecx, ecx
1005
        xor     ecx, ecx
1004
 
1006
 
1005
    @@:
1007
    @@:
1006
        push    ecx
1008
        push    ecx
1007
        call    ext2_inode_get_block
1009
        call    ext2_inode_get_block
1008
        test    eax, eax
1010
        test    eax, eax
1009
        jnz     .error_stack8
1011
        jnz     .error_stack8
1010
        mov     eax, ecx
1012
        mov     eax, ecx
1011
        pop     ecx
1013
        pop     ecx
1012
 
1014
 
1013
        ; If 0, we're done.
1015
        ; If 0, we're done.
1014
        test    eax, eax
1016
        test    eax, eax
1015
        jz      @F
1017
        jz      @F
1016
 
1018
 
1017
        call    ext2_block_free
1019
        call    ext2_block_free
1018
        test    eax, eax
1020
        test    eax, eax
1019
        jnz     .error_stack4
1021
        jnz     .error_stack4
1020
 
1022
 
1021
        inc     ecx
1023
        inc     ecx
1022
        jmp     @B
1024
        jmp     @B
1023
 
1025
 
1024
    @@:
1026
    @@:
1025
        ; Free indirect blocks.
1027
        ; Free indirect blocks.
1026
        call    ext2_inode_free_indirect_blocks
1028
        call    ext2_inode_free_indirect_blocks
1027
        test    eax, eax
1029
        test    eax, eax
1028
        jnz     .error_stack4
1030
        jnz     .error_stack4
1029
 
1031
 
1030
        ; Clear the inode, and add deletion time.
1032
        ; Clear the inode, and add deletion time.
1031
        mov     edi, [ebp + EXTFS.ext2_save_inode]
1033
        mov     edi, [ebp + EXTFS.ext2_save_inode]
1032
        xor     eax, eax
1034
        xor     eax, eax
1033
        mov     ecx, [ebp + EXTFS.inode_size]
1035
        mov     ecx, [ebp + EXTFS.inode_size]
1034
        rep stosb
1036
        rep stosb
1035
 
1037
 
1036
        mov     edi, [ebp + EXTFS.ext2_save_inode]
1038
        mov     edi, [ebp + EXTFS.ext2_save_inode]
1037
        add     edi, EXT2_INODE_STRUC.i_dtime
1039
        add     edi, EXT2_INODE_STRUC.i_dtime
1038
        call    current_unix_time
1040
        call    current_unix_time
1039
 
1041
 
1040
        ; Write the inode.
1042
        ; Write the inode.
1041
        mov     eax, [esp]
1043
        mov     eax, [esp]
1042
        mov     ebx, [ebp + EXTFS.ext2_save_inode]
1044
        mov     ebx, [ebp + EXTFS.ext2_save_inode]
1043
        call    ext2_inode_write
1045
        call    ext2_inode_write
1044
        test    eax, eax
1046
        test    eax, eax
1045
        jnz     .error_stack4
1047
        jnz     .error_stack4
1046
 
1048
 
1047
        ; Check if directory.
1049
        ; Check if directory.
1048
        cmp     edx, EXT2_S_IFDIR
1050
        cmp     edx, EXT2_S_IFDIR
1049
        jne     @F
1051
        jne     @F
1050
 
1052
 
1051
        ; If it is, decrement used_dirs_count.
1053
        ; If it is, decrement used_dirs_count.
1052
 
1054
 
1053
        ; Get block group.
1055
        ; Get block group.
1054
        mov     eax, [esp]
1056
        mov     eax, [esp]
1055
        dec     eax
1057
        dec     eax
1056
        xor     edx, edx
1058
        xor     edx, edx
1057
        div     [ebp + EXTFS.superblock + EXT2_SB_STRUC.inodes_per_group]
1059
        div     [ebp + EXTFS.superblock + EXT2_SB_STRUC.inodes_per_group]
1058
 
1060
 
1059
        push    eax
1061
        push    eax
1060
        call    ext2_bg_read_desc
1062
        call    ext2_bg_read_desc
1061
        test    eax, eax
1063
        test    eax, eax
1062
        jz      .error_stack8
1064
        jz      .error_stack8
1063
 
1065
 
1064
        dec     [eax + EXT2_BLOCK_GROUP_DESC.used_dirs_count]
1066
        dec     [eax + EXT2_BLOCK_GROUP_DESC.used_dirs_count]
1065
        
1067
        
1066
        pop     eax
1068
        pop     eax
1067
        call    ext2_bg_write_desc
1069
        call    ext2_bg_write_desc
1068
 
1070
 
1069
    @@:
1071
    @@:
1070
        pop     eax
1072
        pop     eax
1071
        call    ext2_inode_free
1073
        call    ext2_inode_free
1072
        test    eax, eax
1074
        test    eax, eax
1073
        jnz     .error_access_denied
1075
        jnz     .error_access_denied
1074
 
1076
 
1075
    .disk_sync:
1077
    .disk_sync:
1076
        call    ext2_sb_update
1078
        call    ext2_sb_update
1077
 
1079
 
1078
        ; Sync the disk.
1080
        ; Sync the disk.
1079
        mov     esi, [ebp + PARTITION.Disk]
1081
        mov     esi, [ebp + PARTITION.Disk]
1080
        call    disk_sync                       ; eax contains error code, if any.
1082
        call    disk_sync                       ; eax contains error code, if any.
1081
 
1083
 
1082
    .return:    
1084
    .return:    
1083
        push    eax
1085
        push    eax
1084
        call    ext2_unlock
1086
        call    ext2_unlock
1085
        pop     eax
1087
        pop     eax
1086
 
1088
 
1087
        pop     edi esi edx ecx ebx
1089
        pop     edi esi edx ecx ebx
1088
        ;DEBUGF  1, "And returning with: %x.\n", eax
1090
        ;DEBUGF  1, "And returning with: %x.\n", eax
1089
        ret
1091
        ret
1090
 
1092
 
1091
    .error_stack8:
1093
    .error_stack8:
1092
        add     esp, 4
1094
        add     esp, 4
1093
    .error_stack4:
1095
    .error_stack4:
1094
        add     esp, 4
1096
        add     esp, 4
1095
    .error_access_denied:
1097
    .error_access_denied:
1096
        call    ext2_sb_update
1098
        call    ext2_sb_update
1097
 
1099
 
1098
        ; Sync the disk.
1100
        ; Sync the disk.
1099
        mov     esi, [ebp + PARTITION.Disk]
1101
        mov     esi, [ebp + PARTITION.Disk]
1100
        call    disk_sync                       ; eax contains error code, if any.
1102
        call    disk_sync                       ; eax contains error code, if any.
1101
 
1103
 
1102
        mov     eax, ERROR_ACCESS_DENIED
1104
        mov     eax, ERROR_ACCESS_DENIED
1103
        jmp     .return
1105
        jmp     .return
1104
 
1106
 
1105
;---------------------------------------------------------------------
1107
;---------------------------------------------------------------------
1106
; Set file information for block device.
1108
; Set file information for block device.
1107
; Input:        esi + [esp + 4] = file name.
1109
; Input:        esi + [esp + 4] = file name.
1108
;               ebx = pointer to paramteres from sysfunc 70.
1110
;               ebx = pointer to paramteres from sysfunc 70.
1109
;               ebp = pointer to EXTFS structure.
1111
;               ebp = pointer to EXTFS structure.
1110
; Output:       eax = error code.
1112
; Output:       eax = error code.
1111
;---------------------------------------------------------------------
1113
;---------------------------------------------------------------------
1112
ext2_CreateFolder:
1114
ext2_CreateFolder:
1113
        ;DEBUGF  1, "Attempting to create folder.\n"
1115
        ;DEBUGF  1, "Attempting to create folder.\n"
1114
        test    [ebp + EXTFS.partition_flags], EXT2_RO
1116
        test    [ebp + EXTFS.partition_flags], EXT2_RO
1115
        jz      @F
1117
        jz      @F
1116
 
1118
 
1117
        mov     eax, ERROR_UNSUPPORTED_FS
1119
        mov     eax, ERROR_UNSUPPORTED_FS
1118
        ret
1120
        ret
1119
 
1121
 
1120
    @@:    
1122
    @@:    
1121
        push    ebx ecx edx esi edi
1123
        push    ebx ecx edx esi edi
1122
        call    ext2_lock
1124
        call    ext2_lock
1123
 
1125
 
1124
        add     esi, [esp + 20 + 4]
1126
        add     esi, [esp + 20 + 4]
1125
 
1127
 
1126
        ; Can't create root, but for CreateFolder already existing directory is success.
1128
        ; Can't create root, but for CreateFolder already existing directory is success.
1127
        cmp     byte [esi], 0
1129
        cmp     byte [esi], 0
1128
        jz      .success
1130
        jz      .success
1129
 
1131
 
1130
        push    esi 
1132
        push    esi 
1131
        stdcall ext2_inode_find, 0
1133
        stdcall ext2_inode_find, 0
1132
        pop     esi
1134
        pop     esi
1133
 
1135
 
1134
        ; If the directory is there, we've succeeded.
1136
        ; If the directory is there, we've succeeded.
1135
        test    eax, eax
1137
        test    eax, eax
1136
        jz      .success
1138
        jz      .success
1137
 
1139
 
1138
        ; Find parent.
1140
        ; Find parent.
1139
        call    ext2_inode_find_parent
1141
        call    ext2_inode_find_parent
1140
        test    eax, eax
1142
        test    eax, eax
1141
        jnz     .error
1143
        jnz     .error
1142
 
1144
 
1143
        ; Inode ID for preference.
1145
        ; Inode ID for preference.
1144
        mov     eax, esi
1146
        mov     eax, esi
1145
        call    ext2_inode_alloc
1147
        call    ext2_inode_alloc
1146
        test    eax, eax
1148
        test    eax, eax
1147
        jnz     .error_full
1149
        jnz     .error_full
1148
 
1150
 
1149
        ; Save allocated inode in EDX; filename is in EDI; parent ID in ESI.
1151
        ; Save allocated inode in EDX; filename is in EDI; parent ID in ESI.
1150
        mov     edx, ebx
1152
        mov     edx, ebx
1151
 
1153
 
1152
        push    edi
1154
        push    edi
1153
 
1155
 
1154
        xor     al, al
1156
        xor     al, al
1155
        mov     edi, [ebp + EXTFS.ext2_temp_inode]
1157
        mov     edi, [ebp + EXTFS.ext2_temp_inode]
1156
        mov     ecx, [ebp + EXTFS.inode_size]
1158
        mov     ecx, [ebp + EXTFS.inode_size]
1157
        rep stosb
1159
        rep stosb
1158
 
1160
 
1159
        mov     edi, [ebp + EXTFS.ext2_temp_inode]
1161
        mov     edi, [ebp + EXTFS.ext2_temp_inode]
1160
        add     edi, EXT2_INODE_STRUC.i_atime
1162
        add     edi, EXT2_INODE_STRUC.i_atime
1161
        call    current_unix_time
1163
        call    current_unix_time
1162
 
1164
 
1163
        add     edi, 8
1165
        add     edi, 8
1164
        call    current_unix_time
1166
        call    current_unix_time
1165
 
1167
 
1166
        pop     edi
1168
        pop     edi
1167
 
1169
 
1168
        mov     ebx, [ebp + EXTFS.ext2_temp_inode]
1170
        mov     ebx, [ebp + EXTFS.ext2_temp_inode]
1169
        mov     [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR or PERMISSIONS
1171
        mov     [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR or PERMISSIONS
1170
        mov     eax, edx
1172
        mov     eax, edx
1171
        call    ext2_inode_write
1173
        call    ext2_inode_write
1172
        test    eax, eax
1174
        test    eax, eax
1173
        jnz     .error
1175
        jnz     .error
1174
 
1176
 
1175
        ; Link to self.
1177
        ; Link to self.
1176
        push    edx esi
1178
        push    edx esi
1177
 
1179
 
1178
        mov     eax, edx
1180
        mov     eax, edx
1179
        mov     ebx, eax
1181
        mov     ebx, eax
1180
        mov     dl, EXT2_FT_DIR
1182
        mov     dl, EXT2_FT_DIR
1181
        mov     esi, self_link
1183
        mov     esi, self_link
1182
        call    ext2_inode_link
1184
        call    ext2_inode_link
1183
 
1185
 
1184
        pop     esi edx
1186
        pop     esi edx
1185
 
1187
 
1186
        test    eax, eax
1188
        test    eax, eax
1187
        jnz     .error
1189
        jnz     .error
1188
 
1190
 
1189
        ; Link to parent.
1191
        ; Link to parent.
1190
        push    edx esi
1192
        push    edx esi
1191
 
1193
 
1192
        mov     eax, ebx
1194
        mov     eax, ebx
1193
        mov     ebx, esi
1195
        mov     ebx, esi
1194
        mov     dl, EXT2_FT_DIR
1196
        mov     dl, EXT2_FT_DIR
1195
        mov     esi, parent_link
1197
        mov     esi, parent_link
1196
        call    ext2_inode_link
1198
        call    ext2_inode_link
1197
 
1199
 
1198
        pop     esi edx
1200
        pop     esi edx
1199
 
1201
 
1200
        test    eax, eax
1202
        test    eax, eax
1201
        jnz     .error
1203
        jnz     .error
1202
 
1204
 
1203
        ; Link parent to child.
1205
        ; Link parent to child.
1204
        mov     eax, esi
1206
        mov     eax, esi
1205
        mov     ebx, edx
1207
        mov     ebx, edx
1206
        mov     esi, edi
1208
        mov     esi, edi
1207
        mov     dl, EXT2_FT_DIR
1209
        mov     dl, EXT2_FT_DIR
1208
        call    ext2_inode_link
1210
        call    ext2_inode_link
1209
        test    eax, eax
1211
        test    eax, eax
1210
        jnz     .error
1212
        jnz     .error
1211
 
1213
 
1212
        ; Get block group descriptor for allocated inode's block.
1214
        ; Get block group descriptor for allocated inode's block.
1213
        mov     eax, ebx
1215
        mov     eax, ebx
1214
        dec     eax
1216
        dec     eax
1215
        xor     edx, edx
1217
        xor     edx, edx
1216
        
1218
        
1217
        ; EAX = block group.
1219
        ; EAX = block group.
1218
        div     [ebp + EXTFS.superblock + EXT2_SB_STRUC.inodes_per_group]
1220
        div     [ebp + EXTFS.superblock + EXT2_SB_STRUC.inodes_per_group]
1219
        mov     edx, eax
1221
        mov     edx, eax
1220
 
1222
 
1221
        call    ext2_bg_read_desc
1223
        call    ext2_bg_read_desc
1222
        test    eax, eax
1224
        test    eax, eax
1223
        jz      .error
1225
        jz      .error
1224
 
1226
 
1225
        inc     [eax + EXT2_BLOCK_GROUP_DESC.used_dirs_count]
1227
        inc     [eax + EXT2_BLOCK_GROUP_DESC.used_dirs_count]
1226
        mov     eax, edx
1228
        mov     eax, edx
1227
        call    ext2_bg_write_desc
1229
        call    ext2_bg_write_desc
1228
        test    eax, eax
1230
        test    eax, eax
1229
        jnz     .error
1231
        jnz     .error
1230
 
1232
 
1231
    .success:
1233
    .success:
1232
        call    ext2_sb_update
1234
        call    ext2_sb_update
1233
 
1235
 
1234
        ; Sync the disk.
1236
        ; Sync the disk.
1235
        mov     esi, [ebp + PARTITION.Disk]
1237
        mov     esi, [ebp + PARTITION.Disk]
1236
        call    disk_sync                       ; eax contains error code, if any.
1238
        call    disk_sync                       ; eax contains error code, if any.
1237
 
1239
 
1238
    .return:
1240
    .return:
1239
        push    eax
1241
        push    eax
1240
        call    ext2_unlock
1242
        call    ext2_unlock
1241
        pop     eax
1243
        pop     eax
1242
 
1244
 
1243
        pop     edi esi edx ecx ebx
1245
        pop     edi esi edx ecx ebx
1244
        ;DEBUGF  1, "Returning with: %x.\n", eax
1246
        ;DEBUGF  1, "Returning with: %x.\n", eax
1245
        ret
1247
        ret
1246
 
1248
 
1247
    .error:
1249
    .error:
1248
        call    ext2_sb_update
1250
        call    ext2_sb_update
1249
 
1251
 
1250
        ; Sync the disk.
1252
        ; Sync the disk.
1251
        mov     esi, [ebp + PARTITION.Disk]
1253
        mov     esi, [ebp + PARTITION.Disk]
1252
        call    disk_sync                       ; eax contains error code, if any.
1254
        call    disk_sync                       ; eax contains error code, if any.
1253
        
1255
        
1254
        mov     eax, ERROR_ACCESS_DENIED
1256
        mov     eax, ERROR_ACCESS_DENIED
1255
        jmp     .return
1257
        jmp     .return
1256
 
1258
 
1257
    .error_full:
1259
    .error_full:
1258
        mov     eax, ERROR_DISK_FULL
1260
        mov     eax, ERROR_DISK_FULL
1259
        jmp     .return
1261
        jmp     .return
1260
 
1262
 
1261
self_link   db ".", 0
1263
self_link   db ".", 0
1262
parent_link db "..", 0
1264
parent_link db "..", 0
1263
 
1265
 
1264
;---------------------------------------------------------------------
1266
;---------------------------------------------------------------------
1265
; Rewrite a file.
1267
; Rewrite a file.
1266
; Input:        esi + [esp + 4] = file name.
1268
; Input:        esi + [esp + 4] = file name.
1267
;               ebx = pointer to paramteres from sysfunc 70.
1269
;               ebx = pointer to paramteres from sysfunc 70.
1268
;               ebp = pointer to EXTFS structure.
1270
;               ebp = pointer to EXTFS structure.
1269
; Output:       eax = error code.
1271
; Output:       eax = error code.
1270
;               ebx = bytes written.
1272
;               ebx = bytes written.
1271
;---------------------------------------------------------------------
1273
;---------------------------------------------------------------------
1272
ext2_Rewrite:
1274
ext2_Rewrite:
1273
        ;DEBUGF  1, "Attempting Rewrite.\n"
1275
        ;DEBUGF  1, "Attempting Rewrite.\n"
1274
        test    [ebp + EXTFS.partition_flags], EXT2_RO
1276
        test    [ebp + EXTFS.partition_flags], EXT2_RO
1275
        jz      @F
1277
        jz      @F
1276
 
1278
 
1277
        mov     eax, ERROR_UNSUPPORTED_FS
1279
        mov     eax, ERROR_UNSUPPORTED_FS
1278
        ret
1280
        ret
1279
 
1281
 
1280
    @@:
1282
    @@:
1281
        push    ecx edx esi edi
1283
        push    ecx edx esi edi
1282
        pushad
1284
        pushad
1283
 
1285
 
1284
        call    ext2_lock
1286
        call    ext2_lock
1285
 
1287
 
1286
        add     esi, [esp + 16 + 32 + 4]
1288
        add     esi, [esp + 16 + 32 + 4]
1287
        ; Can't create root.
1289
        ; Can't create root.
1288
        cmp     byte [esi], 0
1290
        cmp     byte [esi], 0
1289
        jz      .error_access_denied
1291
        jz      .error_access_denied
1290
 
1292
 
1291
        push    esi 
1293
        push    esi 
1292
        stdcall ext2_inode_find, 0
1294
        stdcall ext2_inode_find, 0
1293
        pop     esi
1295
        pop     esi
1294
 
1296
 
1295
        ; If the file is there, delete it.
1297
        ; If the file is there, delete it.
1296
        test    eax, eax
1298
        test    eax, eax
1297
        jnz     @F
1299
        jnz     @F
1298
 
1300
 
1299
        pushad
1301
        pushad
1300
 
1302
 
1301
        push    eax
1303
        push    eax
1302
        call    ext2_unlock
1304
        call    ext2_unlock
1303
        pop     eax
1305
        pop     eax
1304
 
1306
 
1305
        push    dword 0x00000000
1307
        push    dword 0x00000000
1306
        call    ext2_Delete
1308
        call    ext2_Delete
1307
        add     esp, 4
1309
        add     esp, 4
1308
 
1310
 
1309
        push    eax
1311
        push    eax
1310
        call    ext2_lock
1312
        call    ext2_lock
1311
        pop     eax
1313
        pop     eax
1312
 
1314
 
1313
        test    eax, eax
1315
        test    eax, eax
1314
        jnz     .error_access_denied_delete
1316
        jnz     .error_access_denied_delete
1315
 
1317
 
1316
        popad
1318
        popad
1317
    @@:
1319
    @@:
1318
        ; Find parent.
1320
        ; Find parent.
1319
        call    ext2_inode_find_parent
1321
        call    ext2_inode_find_parent
1320
        test    eax, eax
1322
        test    eax, eax
1321
        jnz     .error_access_denied
1323
        jnz     .error_access_denied
1322
 
1324
 
1323
        ; Inode ID for preference.
1325
        ; Inode ID for preference.
1324
        mov     eax, esi
1326
        mov     eax, esi
1325
        call    ext2_inode_alloc
1327
        call    ext2_inode_alloc
1326
        test    eax, eax
1328
        test    eax, eax
1327
        jnz     .error_full
1329
        jnz     .error_full
1328
 
1330
 
1329
        ; Save allocated inode in EDX; filename is in EDI; parent ID in ESI.
1331
        ; Save allocated inode in EDX; filename is in EDI; parent ID in ESI.
1330
        mov     edx, ebx
1332
        mov     edx, ebx
1331
 
1333
 
1332
        push    edi
1334
        push    edi
1333
 
1335
 
1334
        xor     al, al
1336
        xor     al, al
1335
        mov     edi, [ebp + EXTFS.ext2_temp_inode]
1337
        mov     edi, [ebp + EXTFS.ext2_temp_inode]
1336
        mov     ecx, [ebp + EXTFS.inode_size]
1338
        mov     ecx, [ebp + EXTFS.inode_size]
1337
        rep stosb
1339
        rep stosb
1338
 
1340
 
1339
        mov     edi, [ebp + EXTFS.ext2_temp_inode]
1341
        mov     edi, [ebp + EXTFS.ext2_temp_inode]
1340
        add     edi, EXT2_INODE_STRUC.i_atime
1342
        add     edi, EXT2_INODE_STRUC.i_atime
1341
        call    current_unix_time
1343
        call    current_unix_time
1342
 
1344
 
1343
        add     edi, 8
1345
        add     edi, 8
1344
        call    current_unix_time
1346
        call    current_unix_time
1345
 
1347
 
1346
        pop     edi
1348
        pop     edi
1347
 
1349
 
1348
        mov     ebx, [ebp + EXTFS.ext2_temp_inode]
1350
        mov     ebx, [ebp + EXTFS.ext2_temp_inode]
1349
        mov     [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFREG or PERMISSIONS
1351
        mov     [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFREG or PERMISSIONS
1350
        mov     eax, edx
1352
        mov     eax, edx
1351
        call    ext2_inode_write
1353
        call    ext2_inode_write
1352
        test    eax, eax
1354
        test    eax, eax
1353
        jnz     .error
1355
        jnz     .error
1354
 
1356
 
1355
        ; Link parent to child.
1357
        ; Link parent to child.
1356
        mov     eax, esi
1358
        mov     eax, esi
1357
        mov     ebx, edx
1359
        mov     ebx, edx
1358
        mov     esi, edi
1360
        mov     esi, edi
1359
        mov     dl, EXT2_FT_REG_FILE
1361
        mov     dl, EXT2_FT_REG_FILE
1360
        call    ext2_inode_link
1362
        call    ext2_inode_link
1361
        test    eax, eax
1363
        test    eax, eax
1362
        jnz     .error
1364
        jnz     .error
1363
 
1365
 
1364
        popad
1366
        popad
1365
        push    eax
1367
        push    eax
1366
        call    ext2_unlock
1368
        call    ext2_unlock
1367
        pop     eax
1369
        pop     eax
1368
 
1370
 
1369
        push    dword 0x00000000
1371
        push    dword 0x00000000
1370
        call    ext2_Write
1372
        call    ext2_Write
1371
        add     esp, 4
1373
        add     esp, 4
1372
 
1374
 
1373
        push    eax
1375
        push    eax
1374
        call    ext2_lock
1376
        call    ext2_lock
1375
        pop     eax
1377
        pop     eax
1376
 
1378
 
1377
    .success:
1379
    .success:
1378
        push    eax
1380
        push    eax
1379
        call    ext2_sb_update
1381
        call    ext2_sb_update
1380
 
1382
 
1381
        ; Sync the disk.
1383
        ; Sync the disk.
1382
        mov     esi, [ebp + PARTITION.Disk]
1384
        mov     esi, [ebp + PARTITION.Disk]
1383
        call    disk_sync                       ; eax contains error code, if any.
1385
        call    disk_sync                       ; eax contains error code, if any.
1384
        pop     eax
1386
        pop     eax
1385
 
1387
 
1386
    .return:
1388
    .return:
1387
        push    eax
1389
        push    eax
1388
        call    ext2_unlock
1390
        call    ext2_unlock
1389
        pop     eax
1391
        pop     eax
1390
 
1392
 
1391
        pop     edi esi edx ecx
1393
        pop     edi esi edx ecx
1392
 
1394
 
1393
        ;DEBUGF  1, "And returning with: %x.\n", eax
1395
        ;DEBUGF  1, "And returning with: %x.\n", eax
1394
        ret
1396
        ret
1395
 
1397
 
1396
    .error:       
1398
    .error:       
1397
        mov     eax, ERROR_ACCESS_DENIED
1399
        mov     eax, ERROR_ACCESS_DENIED
1398
        jmp     .success
1400
        jmp     .success
1399
 
1401
 
1400
    .error_access_denied_delete:
1402
    .error_access_denied_delete:
1401
        popad
1403
        popad
1402
 
1404
 
1403
    .error_access_denied:
1405
    .error_access_denied:
1404
        popad
1406
        popad
1405
        xor     ebx, ebx
1407
        xor     ebx, ebx
1406
 
1408
 
1407
        mov     eax, ERROR_ACCESS_DENIED
1409
        mov     eax, ERROR_ACCESS_DENIED
1408
        jmp     .return
1410
        jmp     .return
1409
 
1411
 
1410
    .error_full:
1412
    .error_full:
1411
        popad
1413
        popad
1412
        xor     ebx, ebx
1414
        xor     ebx, ebx
1413
 
1415
 
1414
        mov     eax, ERROR_DISK_FULL
1416
        mov     eax, ERROR_DISK_FULL
1415
        jmp     .return
1417
        jmp     .return
1416
 
1418
 
1417
;---------------------------------------------------------------------
1419
;---------------------------------------------------------------------
1418
; Write to a file.
1420
; Write to a file.
1419
; Input:        esi + [esp + 4] = file name.
1421
; Input:        esi + [esp + 4] = file name.
1420
;               ebx = pointer to paramteres from sysfunc 70.
1422
;               ebx = pointer to paramteres from sysfunc 70.
1421
;               ebp = pointer to EXTFS structure.
1423
;               ebp = pointer to EXTFS structure.
1422
; Output:       eax = error code.
1424
; Output:       eax = error code.
1423
;               ebx = number of bytes written.
1425
;               ebx = number of bytes written.
1424
;---------------------------------------------------------------------
1426
;---------------------------------------------------------------------
1425
ext2_Write:
1427
ext2_Write:
1426
        ;DEBUGF 1, "Attempting write, "
1428
        ;DEBUGF 1, "Attempting write, "
1427
        test    [ebp + EXTFS.partition_flags], EXT2_RO
1429
        test    [ebp + EXTFS.partition_flags], EXT2_RO
1428
        jz      @F
1430
        jz      @F
1429
 
1431
 
1430
        mov     eax, ERROR_UNSUPPORTED_FS
1432
        mov     eax, ERROR_UNSUPPORTED_FS
1431
        ret
1433
        ret
1432
 
1434
 
1433
    @@:    
1435
    @@:    
1434
        push    ecx edx esi edi
1436
        push    ecx edx esi edi
1435
        call    ext2_lock
1437
        call    ext2_lock
1436
 
1438
 
1437
        add     esi, [esp + 16 + 4]
1439
        add     esi, [esp + 16 + 4]
1438
 
1440
 
1439
        ; Can't write to root.
1441
        ; Can't write to root.
1440
        cmp     byte [esi], 0
1442
        cmp     byte [esi], 0
1441
        jz      .error
1443
        jz      .error
1442
 
1444
 
1443
        push    ebx ecx edx
1445
        push    ebx ecx edx
1444
        stdcall ext2_inode_find, 0
1446
        stdcall ext2_inode_find, 0
1445
        pop     edx ecx ebx
1447
        pop     edx ecx ebx
1446
        ; If file not there, error.
1448
        ; If file not there, error.
1447
        xor     ecx, ecx
1449
        xor     ecx, ecx
1448
        test    eax, eax
1450
        test    eax, eax
1449
        jnz     .error_file_not_found
1451
        jnz     .error_file_not_found
1450
 
1452
 
1451
        ; Save the inode.
1453
        ; Save the inode.
1452
        push    esi
1454
        push    esi
1453
 
1455
 
1454
        ; Check if it's a file.
1456
        ; Check if it's a file.
1455
        mov     edx, [ebp + EXTFS.ext2_save_inode]
1457
        mov     edx, [ebp + EXTFS.ext2_save_inode]
1456
        test    [edx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFREG
1458
        test    [edx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFREG
1457
        jz      .error
1459
        jz      .error
1458
 
1460
 
1459
        mov     eax, esi
1461
        mov     eax, esi
1460
        mov     ecx, [ebx + 4]
1462
        mov     ecx, [ebx + 4]
1461
 
1463
 
1462
        call    ext2_inode_extend
1464
        call    ext2_inode_extend
1463
        xor     ecx, ecx
1465
        xor     ecx, ecx
1464
        test    eax, eax
1466
        test    eax, eax
1465
        jnz     .error_device
1467
        jnz     .error_device
1466
 
1468
 
1467
        ; ECX contains the size to write, and ESI points to it.
1469
        ; ECX contains the size to write, and ESI points to it.
1468
        mov     ecx, [ebx + 0x0C]
1470
        mov     ecx, [ebx + 0x0C]
1469
        mov     esi, [ebx + 0x10]
1471
        mov     esi, [ebx + 0x10]
1470
 
1472
 
1471
        ; Save the size of the inode.
1473
        ; Save the size of the inode.
1472
        mov     eax, [edx + EXT2_INODE_STRUC.i_size]
1474
        mov     eax, [edx + EXT2_INODE_STRUC.i_size]
1473
        push    eax
1475
        push    eax
1474
 
1476
 
1475
        xor     edx, edx
1477
        xor     edx, edx
1476
        div     [ebp + EXTFS.block_size]
1478
        div     [ebp + EXTFS.block_size]
1477
 
1479
 
1478
        test    edx, edx
1480
        test    edx, edx
1479
        jz      .start_aligned
1481
        jz      .start_aligned
1480
 
1482
 
1481
        ; Start isn't aligned, so deal with the non-aligned bytes.
1483
        ; Start isn't aligned, so deal with the non-aligned bytes.
1482
        mov     ebx, [ebp + EXTFS.block_size]
1484
        mov     ebx, [ebp + EXTFS.block_size]
1483
        sub     ebx, edx
1485
        sub     ebx, edx
1484
 
1486
 
1485
        cmp     ebx, ecx
1487
        cmp     ebx, ecx
1486
        jbe     @F
1488
        jbe     @F
1487
 
1489
 
1488
        ; If the size to copy fits in current block, limit to that, instead of the entire block.
1490
        ; If the size to copy fits in current block, limit to that, instead of the entire block.
1489
        mov     ebx, ecx
1491
        mov     ebx, ecx
1490
 
1492
 
1491
    @@:
1493
    @@:
1492
        ; Copy EBX bytes, in EAX indexed block.
1494
        ; Copy EBX bytes, in EAX indexed block.
1493
        push    eax
1495
        push    eax
1494
        call    ext2_inode_read_entry
1496
        call    ext2_inode_read_entry
1495
        test    eax, eax
1497
        test    eax, eax
1496
        pop     eax
1498
        pop     eax
1497
        jnz     .error_inode_size
1499
        jnz     .error_inode_size
1498
 
1500
 
1499
        push    ecx
1501
        push    ecx
1500
        
1502
        
1501
        mov     ecx, ebx
1503
        mov     ecx, ebx
1502
        mov     edi, ebx
1504
        mov     edi, ebx
1503
        add     edi, edx
1505
        add     edi, edx
1504
        rep movsb
1506
        rep movsb
1505
 
1507
 
1506
        pop     ecx
1508
        pop     ecx
1507
 
1509
 
1508
        ; Write the block.
1510
        ; Write the block.
1509
        call    ext2_inode_write_entry
1511
        call    ext2_inode_write_entry
1510
        test    eax, eax
1512
        test    eax, eax
1511
        jnz     .error_inode_size
1513
        jnz     .error_inode_size
1512
 
1514
 
1513
        add     [esp], ebx
1515
        add     [esp], ebx
1514
        sub     ecx, ebx
1516
        sub     ecx, ebx
1515
        jz      .write_inode
1517
        jz      .write_inode
1516
 
1518
 
1517
    .start_aligned:
1519
    .start_aligned:
1518
        cmp     ecx, [ebp + EXTFS.block_size]
1520
        cmp     ecx, [ebp + EXTFS.block_size]
1519
        jb      @F
1521
        jb      @F
1520
 
1522
 
1521
        mov     eax, [esp]
1523
        mov     eax, [esp]
1522
        xor     edx, edx
1524
        xor     edx, edx
1523
        div     [ebp + EXTFS.block_size]
1525
        div     [ebp + EXTFS.block_size]
1524
 
1526
 
1525
        push    eax
1527
        push    eax
1526
        mov     edx, [esp + 8]
1528
        mov     edx, [esp + 8]
1527
        call    ext2_inode_blank_entry
1529
        call    ext2_inode_blank_entry
1528
        test    eax, eax
1530
        test    eax, eax
1529
        pop     eax
1531
        pop     eax
1530
        jnz     .error_inode_size
1532
        jnz     .error_inode_size
1531
 
1533
 
1532
        push    ecx
1534
        push    ecx
1533
 
1535
 
1534
        mov     ecx, [ebp + EXTFS.block_size]
1536
        mov     ecx, [ebp + EXTFS.block_size]
1535
        mov     edi, [ebp + EXTFS.ext2_save_block]
1537
        mov     edi, [ebp + EXTFS.ext2_save_block]
1536
        rep movsb
1538
        rep movsb
1537
 
1539
 
1538
        pop     ecx
1540
        pop     ecx
1539
 
1541
 
1540
        call    ext2_inode_write_entry
1542
        call    ext2_inode_write_entry
1541
        test    eax, eax
1543
        test    eax, eax
1542
        jnz     .error_inode_size
1544
        jnz     .error_inode_size
1543
 
1545
 
1544
        mov     eax, [ebp + EXTFS.block_size]
1546
        mov     eax, [ebp + EXTFS.block_size]
1545
        sub     ecx, eax
1547
        sub     ecx, eax
1546
        add     [esp], eax
1548
        add     [esp], eax
1547
        jmp     .start_aligned        
1549
        jmp     .start_aligned        
1548
 
1550
 
1549
    ; Handle the remaining bytes.
1551
    ; Handle the remaining bytes.
1550
    @@:
1552
    @@:
1551
        test    ecx, ecx
1553
        test    ecx, ecx
1552
        jz      .write_inode
1554
        jz      .write_inode
1553
 
1555
 
1554
        mov     eax, [esp]
1556
        mov     eax, [esp]
1555
        xor     edx, edx
1557
        xor     edx, edx
1556
        div     [ebp + EXTFS.block_size]
1558
        div     [ebp + EXTFS.block_size]
1557
 
1559
 
1558
        push    eax
1560
        push    eax
1559
        call    ext2_inode_read_entry
1561
        call    ext2_inode_read_entry
1560
        test    eax, eax
1562
        test    eax, eax
1561
        pop     eax
1563
        pop     eax
1562
        jz      @F
1564
        jz      @F
1563
 
1565
 
1564
        push    eax
1566
        push    eax
1565
        mov     edx, [esp + 8]
1567
        mov     edx, [esp + 8]
1566
 
1568
 
1567
        call    ext2_inode_blank_entry
1569
        call    ext2_inode_blank_entry
1568
        test    eax, eax
1570
        test    eax, eax
1569
        pop     eax
1571
        pop     eax
1570
        jnz     .error_inode_size
1572
        jnz     .error_inode_size
1571
 
1573
 
1572
    @@:
1574
    @@:
1573
        push    ecx
1575
        push    ecx
1574
        mov     edi, [ebp + EXTFS.ext2_save_block]
1576
        mov     edi, [ebp + EXTFS.ext2_save_block]
1575
        rep movsb
1577
        rep movsb
1576
        pop     ecx
1578
        pop     ecx
1577
 
1579
 
1578
        call    ext2_inode_write_entry
1580
        call    ext2_inode_write_entry
1579
        test    eax, eax
1581
        test    eax, eax
1580
        jnz     .error_inode_size
1582
        jnz     .error_inode_size
1581
 
1583
 
1582
        add     [esp], ecx
1584
        add     [esp], ecx
1583
        xor     ecx, ecx
1585
        xor     ecx, ecx
1584
 
1586
 
1585
    .write_inode:
1587
    .write_inode:
1586
        mov     ebx, [ebp + EXTFS.ext2_temp_inode]
1588
        mov     ebx, [ebp + EXTFS.ext2_temp_inode]
1587
        pop     eax
1589
        pop     eax
1588
        mov     [ebx + EXT2_INODE_STRUC.i_size], eax
1590
        mov     [ebx + EXT2_INODE_STRUC.i_size], eax
1589
        mov     eax, [esp]
1591
        mov     eax, [esp]
1590
 
1592
 
1591
        call    ext2_inode_write
1593
        call    ext2_inode_write
1592
        test    eax, eax
1594
        test    eax, eax
1593
        jnz     .error_device
1595
        jnz     .error_device
1594
 
1596
 
1595
    .success:
1597
    .success:
1596
        call    ext2_sb_update
1598
        call    ext2_sb_update
1597
 
1599
 
1598
        ; Sync the disk.
1600
        ; Sync the disk.
1599
        mov     esi, [ebp + PARTITION.Disk]
1601
        mov     esi, [ebp + PARTITION.Disk]
1600
        call    disk_sync                       ; eax contains error code, if any.
1602
        call    disk_sync                       ; eax contains error code, if any.
1601
 
1603
 
1602
    .return:
1604
    .return:
1603
        push    eax
1605
        push    eax
1604
        call    ext2_unlock
1606
        call    ext2_unlock
1605
        pop     eax
1607
        pop     eax
1606
 
1608
 
1607
        add     esp, 4
1609
        add     esp, 4
1608
 
1610
 
1609
        mov     ebx, [esp + 12]
1611
        mov     ebx, [esp + 12]
1610
        sub     ebx, ecx
1612
        sub     ebx, ecx
1611
        pop     edi esi edx ecx
1613
        pop     edi esi edx ecx
1612
 
1614
 
1613
        ;DEBUGF  1, "and returning with: %x.\n", eax
1615
        ;DEBUGF  1, "and returning with: %x.\n", eax
1614
        ret
1616
        ret
1615
 
1617
 
1616
    .error:
1618
    .error:
1617
        mov     eax, ERROR_ACCESS_DENIED
1619
        mov     eax, ERROR_ACCESS_DENIED
1618
        jmp     .return
1620
        jmp     .return
1619
 
1621
 
1620
    .error_file_not_found:
1622
    .error_file_not_found:
1621
        mov     eax, ERROR_FILE_NOT_FOUND
1623
        mov     eax, ERROR_FILE_NOT_FOUND
1622
        jmp     .return
1624
        jmp     .return
1623
 
1625
 
1624
    .error_inode_size:
1626
    .error_inode_size:
1625
        mov     ebx, [ebp + EXTFS.ext2_temp_inode]
1627
        mov     ebx, [ebp + EXTFS.ext2_temp_inode]
1626
        pop     eax
1628
        pop     eax
1627
        mov     [ebx + EXT2_INODE_STRUC.i_size], eax
1629
        mov     [ebx + EXT2_INODE_STRUC.i_size], eax
1628
        mov     eax, [esp]
1630
        mov     eax, [esp]
1629
 
1631
 
1630
        call    ext2_inode_write
1632
        call    ext2_inode_write
1631
 
1633
 
1632
    .error_device:        
1634
    .error_device:        
1633
        call    ext2_sb_update
1635
        call    ext2_sb_update
1634
 
1636
 
1635
        ; Sync the disk.
1637
        ; Sync the disk.
1636
        mov     esi, [ebp + PARTITION.Disk]
1638
        mov     esi, [ebp + PARTITION.Disk]
1637
        call    disk_sync                       ; eax contains error code, if any.
1639
        call    disk_sync                       ; eax contains error code, if any.
1638
 
1640
 
1639
        mov     eax, ERROR_DEVICE
1641
        mov     eax, ERROR_DEVICE
1640
        jmp     .return
1642
        jmp     .return
1641
 
1643
 
1642
;---------------------------------------------------------------------
1644
;---------------------------------------------------------------------
1643
; Set the end of a file.
1645
; Set the end of a file.
1644
; Input:        esi + [esp + 4] = file name.
1646
; Input:        esi + [esp + 4] = file name.
1645
;               ebx = pointer to paramteres from sysfunc 70.
1647
;               ebx = pointer to paramteres from sysfunc 70.
1646
;               ebp = pointer to EXTFS structure.
1648
;               ebp = pointer to EXTFS structure.
1647
; Output:       eax = error code.
1649
; Output:       eax = error code.
1648
;---------------------------------------------------------------------
1650
;---------------------------------------------------------------------
1649
ext2_SetFileEnd:
1651
ext2_SetFileEnd:
1650
        test    [ebp + EXTFS.partition_flags], EXT2_RO
1652
        test    [ebp + EXTFS.partition_flags], EXT2_RO
1651
        jz      @F
1653
        jz      @F
1652
 
1654
 
1653
        mov     eax, ERROR_UNSUPPORTED_FS
1655
        mov     eax, ERROR_UNSUPPORTED_FS
1654
        ret
1656
        ret
1655
 
1657
 
1656
    @@:    
1658
    @@:    
1657
        push    ebx ecx edx esi edi
1659
        push    ebx ecx edx esi edi
1658
        call    ext2_lock
1660
        call    ext2_lock
1659
 
1661
 
1660
        add     esi, [esp + 20 + 4]
1662
        add     esi, [esp + 20 + 4]
1661
 
1663
 
1662
        ; Can't write to root.
1664
        ; Can't write to root.
1663
        cmp     byte [esi], 0
1665
        cmp     byte [esi], 0
1664
        jz      .error
1666
        jz      .error
1665
 
1667
 
1666
        stdcall ext2_inode_find, 0
1668
        stdcall ext2_inode_find, 0
1667
        ; If file not there, error.
1669
        ; If file not there, error.
1668
        test    eax, eax
1670
        test    eax, eax
1669
        jnz     .error_file_not_found
1671
        jnz     .error_file_not_found
1670
 
1672
 
1671
        ; Check if it's a file.
1673
        ; Check if it's a file.
1672
        mov     edx, [ebp + EXTFS.ext2_save_inode]
1674
        mov     edx, [ebp + EXTFS.ext2_save_inode]
1673
        cmp     [edx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFREG
1675
        cmp     [edx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFREG
1674
        jne     .error
1676
        jne     .error
1675
 
1677
 
1676
        mov     eax, esi
1678
        mov     eax, esi
1677
        mov     ecx, [ebx + 4]
1679
        mov     ecx, [ebx + 4]
1678
        call    ext2_inode_extend
1680
        call    ext2_inode_extend
1679
        test    eax, eax
1681
        test    eax, eax
1680
        jnz     .error_disk_full
1682
        jnz     .error_disk_full
1681
 
1683
 
1682
        mov     eax, esi
1684
        mov     eax, esi
1683
        call    ext2_inode_truncate
1685
        call    ext2_inode_truncate
1684
        test    eax, eax
1686
        test    eax, eax
1685
        jnz     .error_disk_full
1687
        jnz     .error_disk_full
1686
 
1688
 
1687
        mov     eax, esi
1689
        mov     eax, esi
1688
        mov     ebx, [ebp + EXTFS.ext2_temp_inode]
1690
        mov     ebx, [ebp + EXTFS.ext2_temp_inode]
1689
        call    ext2_inode_write
1691
        call    ext2_inode_write
1690
 
1692
 
1691
        call    ext2_sb_update
1693
        call    ext2_sb_update
1692
 
1694
 
1693
        ; Sync the disk.
1695
        ; Sync the disk.
1694
        mov     esi, [ebp + PARTITION.Disk]
1696
        mov     esi, [ebp + PARTITION.Disk]
1695
        call    disk_sync                       ; eax contains error code, if any.
1697
        call    disk_sync                       ; eax contains error code, if any.
1696
 
1698
 
1697
    .return:
1699
    .return:
1698
        push    eax
1700
        push    eax
1699
        call    ext2_unlock
1701
        call    ext2_unlock
1700
        pop     eax
1702
        pop     eax
1701
 
1703
 
1702
        pop     edi esi edx ecx ebx
1704
        pop     edi esi edx ecx ebx
1703
        ret
1705
        ret
1704
 
1706
 
1705
    .error:
1707
    .error:
1706
        mov     eax, ERROR_ACCESS_DENIED
1708
        mov     eax, ERROR_ACCESS_DENIED
1707
        jmp     .return
1709
        jmp     .return
1708
 
1710
 
1709
    .error_file_not_found:
1711
    .error_file_not_found:
1710
        mov     eax, ERROR_FILE_NOT_FOUND
1712
        mov     eax, ERROR_FILE_NOT_FOUND
1711
        jmp     .return
1713
        jmp     .return
1712
 
1714
 
1713
    .error_disk_full:        
1715
    .error_disk_full:        
1714
        call    ext2_sb_update
1716
        call    ext2_sb_update
1715
 
1717
 
1716
        ; Sync the disk.
1718
        ; Sync the disk.
1717
        mov     esi, [ebp + PARTITION.Disk]
1719
        mov     esi, [ebp + PARTITION.Disk]
1718
        call    disk_sync                       ; eax contains error code, if any.
1720
        call    disk_sync                       ; eax contains error code, if any.
1719
 
1721
 
1720
        mov     eax, ERROR_DISK_FULL
1722
        mov     eax, ERROR_DISK_FULL
1721
        jmp     .return
1723
        jmp     .return