Subversion Repositories Kolibri OS

Rev

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

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