Subversion Repositories Kolibri OS

Rev

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

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