2011-10-14 23:38:50 +02:00
|
|
|
; Copyright (c) 2008-2009, diamond
|
|
|
|
; All rights reserved.
|
|
|
|
;
|
|
|
|
; Redistribution and use in source and binary forms, with or without
|
|
|
|
; modification, are permitted provided that the following conditions are met:
|
|
|
|
; * Redistributions of source code must retain the above copyright
|
|
|
|
; notice, this list of conditions and the following disclaimer.
|
|
|
|
; * Redistributions in binary form must reproduce the above copyright
|
|
|
|
; notice, this list of conditions and the following disclaimer in the
|
|
|
|
; documentation and/or other materials provided with the distribution.
|
|
|
|
; * Neither the name of the <organization> nor the
|
|
|
|
; names of its contributors may be used to endorse or promote products
|
|
|
|
; derived from this software without specific prior written permission.
|
|
|
|
;
|
|
|
|
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka <Lrz> ''AS IS'' AND ANY
|
|
|
|
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
; DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
|
|
|
|
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
|
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
|
|
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
;*****************************************************************************
|
|
|
|
|
|
|
|
restore_usa:
|
|
|
|
; Update Sequence Array restore
|
|
|
|
; in: ds:bx -> USA-protected structure
|
|
|
|
push bx
|
|
|
|
lea di, [bx+1feh]
|
|
|
|
mov cx, [bx+6]
|
|
|
|
add bx, [bx+4]
|
|
|
|
dec cx
|
|
|
|
@@:
|
|
|
|
mov ax, [bx+2]
|
|
|
|
mov [di], ax
|
|
|
|
inc bx
|
|
|
|
inc bx
|
|
|
|
add di, 200h
|
|
|
|
loop @b
|
|
|
|
pop bx
|
|
|
|
ret
|
|
|
|
|
|
|
|
find_attr:
|
|
|
|
; in: ds:di->file record, ax=attribute
|
|
|
|
; out: ds:di->attribute or di=0 if not found
|
|
|
|
add di, [di+14h]
|
|
|
|
.1:
|
|
|
|
; attributes' codes are formally dwords, but all of them fit in word
|
|
|
|
cmp word [di], -1
|
|
|
|
jz .notfound
|
|
|
|
cmp word [di], ax
|
|
|
|
jnz .continue
|
|
|
|
; for $DATA attribute, scan only unnamed
|
|
|
|
cmp ax, 80h
|
|
|
|
jnz .found
|
|
|
|
cmp byte [di+9], 0
|
|
|
|
jz .found
|
|
|
|
.continue:
|
|
|
|
add di, [di+4]
|
|
|
|
jmp .1
|
|
|
|
.notfound:
|
|
|
|
xor di, di
|
|
|
|
.found:
|
|
|
|
ret
|
|
|
|
|
|
|
|
process_mcb_nonres:
|
|
|
|
; in: ds:si->attribute, es:di->buffer
|
|
|
|
; out: es:di->buffer end
|
|
|
|
pushad
|
|
|
|
pop di
|
|
|
|
add si, [si+20h]
|
|
|
|
xor ebx, ebx
|
|
|
|
.loop:
|
|
|
|
lodsb
|
|
|
|
test al, al
|
|
|
|
jz .done
|
|
|
|
push invalid_read_request_string
|
|
|
|
movzx cx, al
|
|
|
|
shr cx, 4
|
|
|
|
jz find_error_sp
|
|
|
|
xchg ax, dx
|
|
|
|
and dx, 0Fh
|
|
|
|
jz find_error_sp
|
|
|
|
add si, cx
|
|
|
|
add si, dx
|
|
|
|
pop ax
|
|
|
|
push si
|
|
|
|
dec si
|
|
|
|
movsx eax, byte [si]
|
|
|
|
dec cx
|
|
|
|
jz .l1e
|
|
|
|
.l1:
|
|
|
|
dec si
|
|
|
|
shl eax, 8
|
|
|
|
mov al, [si]
|
|
|
|
loop .l1
|
|
|
|
.l1e:
|
|
|
|
xchg ebp, eax
|
|
|
|
dec si
|
|
|
|
movsx eax, byte [si]
|
|
|
|
mov cx, dx
|
|
|
|
dec cx
|
|
|
|
jz .l2e
|
|
|
|
.l2:
|
|
|
|
dec si
|
|
|
|
shl eax, 8
|
|
|
|
mov al, byte [si]
|
|
|
|
loop .l2
|
|
|
|
.l2e:
|
|
|
|
pop si
|
|
|
|
add ebx, ebp
|
|
|
|
; eax=length, ebx=disk block
|
|
|
|
stosd
|
|
|
|
mov eax, ebx
|
|
|
|
stosd
|
|
|
|
cmp di, 0x8000 - 12
|
|
|
|
jbe .loop
|
|
|
|
..attr_overflow:
|
|
|
|
mov si, fragmented_string
|
|
|
|
jmp find_error_si
|
|
|
|
.done:
|
|
|
|
xor ax, ax
|
|
|
|
stosw
|
|
|
|
stosw
|
|
|
|
push di
|
|
|
|
popad
|
|
|
|
ret
|
|
|
|
|
|
|
|
load_attr:
|
|
|
|
; in: ax=attribute, ds:bx->base record
|
|
|
|
; out: if found: CF=0, attribute loaded to [freeattr], [freeattr] updated,
|
|
|
|
; edx=size of attribute in bytes
|
|
|
|
; out: if not found: CF=1
|
|
|
|
mov di, [bp + freeattr - dat]
|
|
|
|
push ss
|
|
|
|
pop es
|
|
|
|
mov byte [es:di], 1
|
|
|
|
inc di
|
|
|
|
cmp di, 0x8000 - 12
|
|
|
|
ja ..attr_overflow
|
|
|
|
or edx, -1 ; file size is not known yet
|
|
|
|
; scan for attribute
|
|
|
|
push di
|
|
|
|
mov di, bx
|
|
|
|
add di, [di+14h]
|
|
|
|
@@:
|
|
|
|
call find_attr.1
|
|
|
|
test di, di
|
|
|
|
jz .notfound1
|
|
|
|
cmp byte [di+8], 0
|
|
|
|
jnz .nonresident
|
|
|
|
mov si, di
|
|
|
|
pop di
|
|
|
|
push ds
|
|
|
|
jmp .resident
|
|
|
|
.aux_resident:
|
|
|
|
mov ax, ds
|
|
|
|
mov si, di
|
|
|
|
pop di ds bx ds edx
|
|
|
|
push ss
|
|
|
|
pop es
|
|
|
|
push ds
|
|
|
|
mov ds, ax
|
|
|
|
; resident attribute
|
|
|
|
.resident:
|
|
|
|
dec di
|
|
|
|
mov al, 0
|
|
|
|
stosb
|
|
|
|
mov ax, [si+10h]
|
|
|
|
stosw
|
|
|
|
push di
|
|
|
|
add di, ax
|
|
|
|
cmp di, 0x8000 - 12
|
|
|
|
pop di
|
|
|
|
ja ..attr_overflow
|
|
|
|
movzx edx, ax ; length of attribute
|
|
|
|
xchg ax, cx
|
|
|
|
add si, [si+14h]
|
|
|
|
rep movsb
|
|
|
|
mov [bp + freeattr - dat], di
|
|
|
|
pop ds
|
|
|
|
ret
|
|
|
|
.nonresident:
|
|
|
|
; nonresident attribute
|
|
|
|
cmp dword [di+10h], 0
|
|
|
|
jnz @b
|
|
|
|
; read start of data
|
|
|
|
mov si, di
|
|
|
|
mov edx, [di+30h] ; size of attribute
|
|
|
|
pop di
|
|
|
|
call process_mcb_nonres
|
|
|
|
sub di, 4
|
|
|
|
push di
|
|
|
|
.notfound1:
|
|
|
|
pop di
|
|
|
|
push edx
|
|
|
|
; $ATTRIBUTE_LIST is always in base file record
|
|
|
|
cmp ax, 20h
|
|
|
|
jz .nofragmented
|
|
|
|
; try to load $ATTRIBUTE_LIST = 20h
|
|
|
|
push ax
|
|
|
|
mov ax, 20h
|
|
|
|
push [bp + freeattr - dat]
|
|
|
|
mov [bp + freeattr - dat], di
|
|
|
|
push di
|
|
|
|
call load_attr
|
|
|
|
pop di
|
|
|
|
pop [bp + freeattr - dat]
|
|
|
|
pop ax
|
|
|
|
jc .nofragmented
|
|
|
|
push ds bx
|
|
|
|
pusha
|
|
|
|
mov si, di
|
|
|
|
push ss
|
|
|
|
pop ds
|
|
|
|
push 0x8100
|
|
|
|
pop es
|
|
|
|
xor ecx, ecx
|
|
|
|
mov cl, 0x78
|
|
|
|
xor bx, bx
|
|
|
|
push es
|
|
|
|
call read_file_chunk
|
|
|
|
pop ds
|
|
|
|
jc ..found_disk_error
|
|
|
|
test cx, cx
|
|
|
|
jz ..attr_overflow
|
|
|
|
popa
|
|
|
|
push ss
|
|
|
|
pop es
|
|
|
|
xor bx, bx
|
|
|
|
.1:
|
|
|
|
cmp [bx], ax
|
|
|
|
jnz .continue1
|
|
|
|
; only unnamed $DATA attributes!
|
|
|
|
cmp ax, 80h
|
|
|
|
jnz @f
|
|
|
|
cmp byte [bx+6], 0
|
|
|
|
jnz .continue1
|
|
|
|
@@:
|
|
|
|
cmp dword [bx+10h], 0
|
|
|
|
jz .continue1
|
|
|
|
cmp dword [bx+8], 0
|
|
|
|
jnz @f
|
|
|
|
dec di
|
|
|
|
cmp di, [bp + freeattr - dat]
|
|
|
|
lea di, [di+1]
|
|
|
|
jnz .continue1
|
|
|
|
@@:
|
|
|
|
push ds di
|
|
|
|
push ax
|
|
|
|
mov eax, [bx+10h]
|
|
|
|
mov ecx, [bx+8]
|
|
|
|
call read_file_record
|
|
|
|
pop ax
|
|
|
|
mov di, [14h]
|
|
|
|
.2:
|
|
|
|
call find_attr.1
|
|
|
|
cmp byte [di+8], 0
|
|
|
|
jz .aux_resident
|
|
|
|
cmp dword [di+10h], ecx
|
|
|
|
jnz .2
|
|
|
|
mov si, di
|
|
|
|
mov di, sp
|
|
|
|
cmp dword [ss:di+8], -1
|
|
|
|
jnz @f
|
|
|
|
push dword [si+30h] ; size of attribute
|
|
|
|
pop dword [ss:di+8]
|
|
|
|
@@:
|
|
|
|
pop di
|
|
|
|
call process_mcb_nonres
|
|
|
|
sub di, 4
|
|
|
|
pop ds
|
|
|
|
.continue1:
|
|
|
|
add bx, [bx+4]
|
|
|
|
cmp bx, dx
|
|
|
|
jb .1
|
|
|
|
pop bx ds
|
|
|
|
.nofragmented:
|
|
|
|
pop edx
|
|
|
|
dec di
|
|
|
|
cmp di, [bp + freeattr - dat]
|
|
|
|
jnz @f
|
|
|
|
stc
|
|
|
|
ret
|
|
|
|
@@:
|
|
|
|
inc di
|
|
|
|
xor ax, ax
|
|
|
|
stosw
|
|
|
|
stosw
|
|
|
|
mov [bp + freeattr - dat], di
|
|
|
|
ret
|
|
|
|
|
|
|
|
read_file_record:
|
|
|
|
; in: eax = index of record
|
|
|
|
; out: ds:0 -> record
|
|
|
|
; find place in cache
|
|
|
|
push di
|
|
|
|
push si
|
|
|
|
mov si, cache1head
|
|
|
|
call cache_lookup
|
|
|
|
pop si
|
|
|
|
pushf
|
|
|
|
sub di, 3400h
|
|
|
|
shl di, 10-3
|
|
|
|
add di, 0x6000
|
|
|
|
mov ds, di
|
|
|
|
popf
|
|
|
|
pop di
|
|
|
|
jnc .noread
|
|
|
|
; read file record <eax> to ds:0
|
|
|
|
pushad
|
|
|
|
push ds
|
|
|
|
push es
|
|
|
|
movzx ecx, [bp + frs_size - dat]
|
|
|
|
shr cx, 9
|
|
|
|
mul ecx
|
|
|
|
push ds
|
|
|
|
pop es
|
|
|
|
push ss
|
|
|
|
pop ds
|
|
|
|
mov si, 0x4000
|
|
|
|
xor bx, bx
|
|
|
|
push [bp + cur_obj - dat]
|
|
|
|
mov [bp + cur_obj - dat], mft_string
|
|
|
|
push es
|
|
|
|
call read_attr
|
|
|
|
; initialize cache for $INDEX_ALLOCATION for this record
|
|
|
|
pop si
|
|
|
|
push si
|
|
|
|
sub si, 0x6000
|
|
|
|
mov ax, si
|
|
|
|
shr si, 10-3
|
|
|
|
shr ax, 2
|
|
|
|
add si, 3480h
|
|
|
|
add ax, 3500h
|
|
|
|
mov [si], si
|
|
|
|
mov [si+2], si
|
|
|
|
mov [si+4], ax
|
|
|
|
pop ds
|
|
|
|
call restore_usa
|
|
|
|
pop [bp + cur_obj - dat]
|
|
|
|
pop es
|
|
|
|
pop ds
|
|
|
|
popad
|
|
|
|
.noread:
|
|
|
|
ret
|
|
|
|
|
|
|
|
read_attr:
|
|
|
|
; in: eax = offset in sectors, ecx = size in sectors (<10000h), es:bx -> buffer, ds:si -> attribute
|
|
|
|
push invalid_read_request_string
|
|
|
|
cmp byte [si], 0
|
|
|
|
jnz .nonresident
|
|
|
|
cmp eax, 10000h shr 9
|
|
|
|
jae find_error_sp
|
|
|
|
shl ax, 9
|
|
|
|
shl cx, 9
|
|
|
|
cmp ax, [si+2]
|
|
|
|
jae find_error_sp
|
|
|
|
cmp cx, [si+2]
|
|
|
|
ja find_error_sp
|
|
|
|
add si, 3
|
|
|
|
add si, ax
|
|
|
|
mov di, bx
|
|
|
|
rep movsb
|
|
|
|
pop ax
|
|
|
|
ret
|
|
|
|
.nonresident:
|
|
|
|
inc si
|
|
|
|
.loop:
|
|
|
|
mov edx, dword [si]
|
|
|
|
add si, 8
|
|
|
|
test edx, edx
|
|
|
|
jz find_error_sp
|
|
|
|
imul edx, [bp + sect_per_clust - dat]
|
|
|
|
sub eax, edx
|
|
|
|
jnc .loop
|
|
|
|
add eax, edx
|
|
|
|
sub edx, eax
|
|
|
|
push cx
|
|
|
|
cmp ecx, edx
|
|
|
|
jb @f
|
|
|
|
mov cx, dx
|
|
|
|
@@:
|
|
|
|
push bx
|
|
|
|
mov ebx, [si-4]
|
|
|
|
imul ebx, [bp + sect_per_clust - dat]
|
|
|
|
add eax, ebx
|
|
|
|
pop bx
|
|
|
|
call read
|
|
|
|
jc ..found_disk_error
|
|
|
|
mov dx, cx
|
|
|
|
pop cx
|
|
|
|
xor eax, eax
|
|
|
|
sub cx, dx
|
|
|
|
jnz .loop
|
|
|
|
pop ax
|
|
|
|
ret
|
|
|
|
|
|
|
|
load_file_ntfs:
|
|
|
|
; in: ss:bp = 0:dat
|
|
|
|
; in: es:bx = address to load file
|
|
|
|
; in: ds:si -> ASCIIZ name
|
|
|
|
; in: cx = limit in sectors
|
|
|
|
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part has been loaded, bx=2 - file not found
|
|
|
|
; out: dx:ax = file size (0xFFFFFFFF if file not found)
|
|
|
|
push es bx cx
|
|
|
|
mov eax, 5 ; root cluster
|
|
|
|
mov [bp + cur_obj - dat], root_string
|
|
|
|
.parse_dir_loop:
|
|
|
|
push ds si
|
|
|
|
call read_file_record
|
|
|
|
; find attributes $INDEX_ROOT, $INDEX_ALLOCATION, $BITMAP
|
|
|
|
mov ax, [bp + freeattr - dat]
|
|
|
|
mov [bp + index_root - dat], ax
|
|
|
|
mov ax, 90h ; $INDEX_ROOT
|
|
|
|
xor bx, bx
|
|
|
|
call load_attr
|
|
|
|
mov si, noindex_string
|
|
|
|
jc find_error_si
|
|
|
|
mov ax, [bp + freeattr - dat]
|
|
|
|
mov [bp + index_alloc - dat], ax
|
|
|
|
mov ax, 0A0h ; $INDEX_ALLOCATION
|
|
|
|
call load_attr
|
|
|
|
jnc @f
|
|
|
|
mov [bp + index_alloc - dat], bx
|
|
|
|
@@:
|
|
|
|
push ds
|
|
|
|
; search for entry
|
|
|
|
mov si, [bp + index_root - dat]
|
|
|
|
push ss
|
|
|
|
pop ds
|
|
|
|
push 0x8100
|
|
|
|
pop es
|
|
|
|
xor ecx, ecx
|
|
|
|
mov cl, 0x78
|
|
|
|
xor bx, bx
|
|
|
|
push es
|
|
|
|
call read_file_chunk
|
|
|
|
pop ds
|
|
|
|
jc ..found_disk_error
|
|
|
|
test cx, cx
|
|
|
|
jz ..attr_overflow
|
|
|
|
mov si, invalid_read_request_string
|
|
|
|
cmp word [bx+10], 0
|
|
|
|
jnz find_error_si
|
|
|
|
; calculate number of items in cache
|
|
|
|
mov di, [bx+8] ; subnode_size
|
|
|
|
mov ax, 0x4000
|
|
|
|
sub ax, word [bp + frs_size - dat]
|
|
|
|
cwd
|
|
|
|
div di
|
|
|
|
test ax, ax
|
|
|
|
jz find_error_si
|
|
|
|
mov si, invalid_volume_msg
|
|
|
|
test di, 0x1FF
|
|
|
|
jnz find_error_si
|
|
|
|
pop cx
|
|
|
|
mov [bp + cur_index_seg - dat], cx
|
|
|
|
shl ax, 3
|
|
|
|
sub cx, 6000h
|
|
|
|
mov si, cx
|
|
|
|
shr cx, 2
|
|
|
|
shr si, 10-3
|
|
|
|
add cx, ax
|
|
|
|
add si, 3480h
|
|
|
|
mov [bp + cur_index_cache - dat], si
|
|
|
|
add cx, 3500h
|
|
|
|
mov [ss:si+6], cx
|
|
|
|
mov dx, di
|
|
|
|
add bx, 10h
|
|
|
|
.scan_record:
|
|
|
|
add bx, [bx]
|
|
|
|
.scan:
|
|
|
|
test byte [bx+0Ch], 2
|
|
|
|
jnz .look_child
|
|
|
|
movzx cx, byte [bx+50h] ; namelen
|
|
|
|
lea di, [bx+52h] ; name
|
|
|
|
push ds
|
|
|
|
pop es
|
|
|
|
pop si ds
|
|
|
|
push ds si
|
|
|
|
xor ax, ax
|
|
|
|
.1:
|
|
|
|
lodsb
|
|
|
|
cmp al, '/'
|
|
|
|
jnz @f
|
|
|
|
mov al, 0
|
|
|
|
@@:
|
|
|
|
cmp al, 'A'
|
|
|
|
jb .nocapital
|
|
|
|
cmp al, 'Z'
|
|
|
|
ja .nocapital
|
|
|
|
or al, 20h
|
|
|
|
.nocapital:
|
|
|
|
cmp al, 'a'
|
|
|
|
jb .notletter
|
|
|
|
cmp al, 'z'
|
|
|
|
ja .notletter
|
|
|
|
or byte [es:di], 20h
|
|
|
|
.notletter:
|
|
|
|
scasw
|
|
|
|
loopz .1
|
|
|
|
jb .look_child
|
|
|
|
ja @f
|
|
|
|
cmp byte [si], 0
|
|
|
|
jz .file_found
|
|
|
|
cmp byte [si], '/'
|
|
|
|
jz .file_found
|
|
|
|
@@:
|
|
|
|
push es
|
|
|
|
pop ds
|
|
|
|
add bx, [bx+8]
|
|
|
|
jmp .scan
|
|
|
|
.look_child:
|
|
|
|
push es
|
|
|
|
pop ds
|
|
|
|
test byte [bx+0Ch], 1
|
|
|
|
jz .not_found
|
|
|
|
mov si, [bp + index_alloc - dat]
|
|
|
|
test si, si
|
|
|
|
jz .not_found
|
|
|
|
add bx, [bx+8]
|
|
|
|
mov eax, [bx-8]
|
|
|
|
mov es, [bp + cur_index_seg - dat]
|
|
|
|
push si
|
|
|
|
mov si, [bp + cur_index_cache - dat]
|
|
|
|
call cache_lookup
|
|
|
|
pop si
|
|
|
|
pushf
|
|
|
|
mov bx, di
|
|
|
|
mov bh, 0
|
|
|
|
shr bx, 3
|
|
|
|
imul bx, dx
|
|
|
|
add bx, [bp + frs_size - dat]
|
|
|
|
popf
|
|
|
|
jnc .noread
|
|
|
|
push es
|
|
|
|
push dx
|
|
|
|
push ss
|
|
|
|
pop ds
|
|
|
|
movzx ecx, dx
|
|
|
|
shr cx, 9
|
|
|
|
mul [bp + sect_per_clust - dat]
|
|
|
|
call read_attr
|
|
|
|
pop dx
|
|
|
|
pop es
|
|
|
|
push es
|
|
|
|
pop ds
|
|
|
|
call restore_usa
|
|
|
|
.noread:
|
|
|
|
push es
|
|
|
|
pop ds
|
|
|
|
add bx, 18h
|
|
|
|
jmp .scan_record
|
|
|
|
.not_found:
|
|
|
|
pop [bp + cur_obj - dat]
|
|
|
|
mov si, error_not_found
|
|
|
|
jmp find_error_si
|
|
|
|
.file_found:
|
|
|
|
pop [bp + cur_obj - dat]
|
|
|
|
pop cx
|
|
|
|
mov ax, [bp + index_root - dat]
|
|
|
|
mov [bp + freeattr - dat], ax
|
|
|
|
mov eax, [es:bx]
|
|
|
|
test byte [es:bx+48h+3], 10h
|
|
|
|
jz .regular_file
|
|
|
|
cmp byte [si], 0
|
|
|
|
jz ..directory_error
|
|
|
|
inc si
|
|
|
|
jmp .parse_dir_loop
|
|
|
|
.regular_file:
|
|
|
|
cmp byte [si], 0
|
|
|
|
jnz ..notdir_error
|
|
|
|
; read entry
|
|
|
|
call read_file_record
|
|
|
|
xor bx, bx
|
|
|
|
mov ax, 80h
|
|
|
|
call load_attr
|
|
|
|
mov si, nodata_string
|
|
|
|
jc find_error_si
|
|
|
|
mov si, [bp + index_root - dat]
|
|
|
|
mov [bp + freeattr - dat], si
|
|
|
|
push ss
|
|
|
|
pop ds
|
|
|
|
jmp load_file_common_end
|