1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;; Copyright (C) KolibriOS team 2013-2016. All rights reserved. ;;
4 ;; Distributed under terms of the GNU General Public License. ;;
6 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10 ; EXT external functions
12 ; ebx -> parameter structure of sysfunc 70
13 ; ebp -> EXTFS structure
14 ; esi -> path string in UTF-8
16 ; eax, ebx = return values for sysfunc 70
21 dd (ext_user_functions_end - ext_user_functions - 8) / 4
33 ext_user_functions_end:
41 name db ? ; rb [nameLength]
66 struct BGDESCR ; block group descriptor
83 sectorsPerBlockLog dd ? ; shift for 1024
86 fragmentsPerGroup dd ?
95 additionalVersion dw ?
99 dynamicVersionFlag dd ?
106 incompatibleFlags dd ?
107 RO_compatibleFlags dd ?
113 struct NODEHEADER ; tree node header
121 struct INDEX ; root/branch
136 EXTENTS_USED = 80000h
146 ; Implemented "incompatible" features:
147 ; 2 = have file type in directory entry
149 ; 200h = flexible block groups
150 INCOMPATIBLE_SUPPORT = 242h
151 ; Read only support for "incompatible" features:
152 INCOMPATIBLE_READ_SUPPORT = 240h
154 ; Implemented "read-only" features:
155 ; 1 = sparse superblock
156 ; 2 = 64-bit file size
157 READ_ONLY_SUPPORT = 3
159 struct EXTFS PARTITION
165 dwordsPerBranch dd ? ; dwordsPerBlock ^ 2
169 descriptorTableEnd dd ?
170 align0 rb 200h-EXTFS.align0
171 superblock SUPERBLOCK
172 align1 rb 400h-EXTFS.align1
173 rootInodeBuffer INODE
174 align2 rb 600h-EXTFS.align2
176 align3 rb 800h-EXTFS.align3
179 ; mount if it's a valid EXT partition
180 ext2_create_partition:
182 ; ebp -> PARTITION structure
186 ; eax -> EXTFS structure, 0 = not EXT
188 cmp dword [esi+DISK.MediaInfo.SectorSize], 512
195 cmp [ebx+SUPERBLOCK.magic], 0xEF53
197 cmp [ebx+SUPERBLOCK.state], 1
199 test [ebx+SUPERBLOCK.incompatibleFlags], not INCOMPATIBLE_SUPPORT
201 cmp [ebx+SUPERBLOCK.sectorsPerBlockLog], 6 ; 64KB
203 cmp [ebx+SUPERBLOCK.inodeSize], 512
205 cmp [ebx+SUPERBLOCK.blocksPerGroup], 0
207 cmp [ebx+SUPERBLOCK.inodesPerGroup], 0
209 movi eax, sizeof.EXTFS
213 mov ecx, dword [ebp+PARTITION.FirstSector]
214 mov dword [eax+EXTFS.FirstSector], ecx
215 mov ecx, dword [ebp+PARTITION.FirstSector+4]
216 mov dword [eax+EXTFS.FirstSector+4], ecx
217 mov ecx, dword [ebp+PARTITION.Length]
218 mov dword [eax+EXTFS.Length], ecx
219 mov ecx, dword [ebp+PARTITION.Length+4]
220 mov dword [eax+EXTFS.Length+4], ecx
221 mov ecx, [ebp+PARTITION.Disk]
222 mov [eax+EXTFS.Disk], ecx
223 mov [eax+EXTFS.FSUserFunctions], ext_user_functions
227 lea ecx, [eax+EXTFS.Lock]
230 lea edi, [ebp+EXTFS.superblock]
232 rep movsd ; copy superblock
233 mov ecx, [ebx+SUPERBLOCK.sectorsPerBlockLog]
237 mov [ebp+EXTFS.sectorsPerBlock], eax
239 mov [ebp+EXTFS.bytesPerBlock], eax
243 mov [ebp+EXTFS.dwordsPerBlock], eax
245 mov [ebp+EXTFS.dwordsPerBranch], eax
249 mov [ebp+EXTFS.mainBlockBuffer], eax
250 add eax, [ebp+EXTFS.bytesPerBlock]
251 mov [ebp+EXTFS.tempBlockBuffer], eax
252 mov [ebp+EXTFS.mountType], 0
253 test [ebx+SUPERBLOCK.RO_compatibleFlags], not READ_ONLY_SUPPORT
255 test [ebx+SUPERBLOCK.incompatibleFlags], INCOMPATIBLE_READ_SUPPORT
258 or [ebp+EXTFS.mountType], READ_ONLY
260 mov eax, [ebx+SUPERBLOCK.inodesTotal]
263 div [ebx+SUPERBLOCK.inodesPerGroup]
271 mov [ebp+EXTFS.descriptorTable], eax
274 mov [ebp+EXTFS.descriptorTableEnd], eax
275 mov eax, [ebp+EXTFS.superblock.firstGroupBlock]
277 mul [ebp+EXTFS.sectorsPerBlock]
285 lea ebx, [ebp+EXTFS.rootInodeBuffer]
294 stdcall kernel_free, [ebp+EXTFS.descriptorTable]
296 stdcall kernel_free, [ebp+EXTFS.mainBlockBuffer]
306 ; unmount EXT partition
308 ; in: eax -> EXTFS structure
309 push eax [eax+EXTFS.mainBlockBuffer]
310 stdcall kernel_free, [eax+EXTFS.descriptorTable]
318 ; in: eax = block number, ebx -> buffer
323 mov ecx, [ebp+EXTFS.sectorsPerBlock]
330 movi eax, ERROR_DEVICE
335 extfsWriteDescriptor:
336 ; in: ebx = block group descriptor
337 mov eax, [ebp+EXTFS.superblock.firstGroupBlock]
339 mul [ebp+EXTFS.sectorsPerBlock]
340 sub ebx, [ebp+EXTFS.descriptorTable]
344 add ebx, [ebp+EXTFS.descriptorTable]
349 ; in: eax = first block number, ecx = extent size
351 sub eax, [ebp+EXTFS.superblock.firstGroupBlock]
353 mov ebx, [ebp+EXTFS.superblock.blocksPerGroup]
359 mov ebx, [ebp+EXTFS.descriptorTable]
363 mul [ebp+EXTFS.sectorsPerBlock]
364 add [ebx+BGDESCR.blocksFree], cx
365 add [ebp+EXTFS.superblock.blocksFree], ecx
366 sub [ebp+EXTFS.inodeBuffer.sectorsUsed], eax
367 push [ebx+BGDESCR.blockBitmap]
368 call extfsWriteDescriptor
370 mov ebx, [ebp+EXTFS.tempBlockBuffer]
418 ; in: eax = parent inode number
419 ; out: ebx = allocated inode number
423 div [ebp+EXTFS.superblock.inodesPerGroup]
424 mov ebx, [ebp+EXTFS.descriptorTable]
430 cmp [ebx+BGDESCR.blocksFree], 0
432 cmp [ebx+BGDESCR.inodesFree], 0
434 dec [ebx+BGDESCR.inodesFree]
435 dec [ebp+EXTFS.superblock.inodesFree]
436 push [ebx+BGDESCR.inodeBitmap]
437 call extfsWriteDescriptor
439 mov ebx, [ebp+EXTFS.tempBlockBuffer]
444 mov ecx, [ebp+EXTFS.superblock.inodesPerGroup]
454 sub edi, [ebp+EXTFS.tempBlockBuffer]
461 sub eax, [ebp+EXTFS.descriptorTable]
463 mul [ebp+EXTFS.superblock.inodesPerGroup]
470 .next: ; search forward, then backward
475 cmp ebx, [ebp+EXTFS.descriptorTableEnd]
480 cmp ebx, [ebp+EXTFS.descriptorTable]
481 jnc .test_block_group
482 movi eax, ERROR_DISK_FULL
489 ; in: eax = parent inode number, ecx = blocks max
490 ; out: ebx = first block number, ecx = blocks allocated
494 div [ebp+EXTFS.superblock.inodesPerGroup]
495 mov ebx, [ebp+EXTFS.descriptorTable]
501 cmp [ebx+BGDESCR.blocksFree], 0
503 mov eax, [ebx+BGDESCR.blockBitmap]
504 mov ebx, [ebp+EXTFS.tempBlockBuffer]
509 mov ecx, [ebp+EXTFS.superblock.blocksPerGroup]
541 sub esi, [ebp+EXTFS.tempBlockBuffer]
598 mov ebx, [ebp+EXTFS.tempBlockBuffer]
602 sub [ebx+BGDESCR.blocksFree], cx
604 mov [ebx+BGDESCR.blocksFree], 0
606 sub [ebp+EXTFS.superblock.blocksFree], ecx
607 call extfsWriteDescriptor
609 sub eax, [ebp+EXTFS.descriptorTable]
611 mul [ebp+EXTFS.superblock.blocksPerGroup]
614 add ebx, [ebp+EXTFS.superblock.firstGroupBlock]
617 mul [ebp+EXTFS.sectorsPerBlock]
618 add [ebp+EXTFS.inodeBuffer.sectorsUsed], eax
624 .next: ; search forward, then backward
629 cmp ebx, [ebp+EXTFS.descriptorTableEnd]
634 cmp ebx, [ebp+EXTFS.descriptorTable]
635 jnc .test_block_group
636 movi eax, ERROR_DISK_FULL
645 ; in: ecx = starting file block
646 ; out: eax = first block number, ecx = extent size
648 lea esi, [ebp+EXTFS.inodeBuffer]
649 test [esi+INODE.featureFlags], EXTENTS_USED
651 add esi, INODE.blockNumbers
653 cmp word [esi+NODEHEADER.magic], 0xF30A
655 movzx ebx, [esi+NODEHEADER.entriesFolow]
656 add esi, sizeof.NODEHEADER
659 cmp word [esi-sizeof.NODEHEADER+NODEHEADER.currentDepth], 0
664 cmp ecx, [esi+sizeof.INDEX+INDEX.fileBlock]
666 add esi, sizeof.INDEX
670 mov ebx, [ebp+EXTFS.tempBlockBuffer]
671 mov eax, [esi+INDEX.nodeBlock]
675 jmp .extentTreeSearch
678 movi eax, ERROR_FS_FAIL
682 movzx edx, [esi+EXTENT.blocksCount]
683 add edx, [esi+EXTENT.fileBlock]
685 ja .end_search_extent
686 add esi, sizeof.EXTENT
690 movi eax, ERROR_END_OF_FILE
697 sub ecx, [esi+EXTENT.fileBlock]
699 add ecx, [esi+EXTENT.fsBlock]
709 cmp ecx, [ebp+EXTFS.dwordsPerBlock]
710 jb .get_indirect_block
711 sub ecx, [ebp+EXTFS.dwordsPerBlock]
712 cmp ecx, [ebp+EXTFS.dwordsPerBranch]
713 jb .get_double_indirect_block
714 ; triply-indirect blocks
715 sub ecx, [ebp+EXTFS.dwordsPerBranch]
716 mov eax, [esi+INODE.tripleAddress]
719 mov ebx, [ebp+EXTFS.tempBlockBuffer]
724 div [ebp+EXTFS.dwordsPerBranch]
725 ; eax = number in triply-indirect block, edx = number in branch
737 lea ebx, [esi+INODE.blockNumbers]
741 mov eax, [esi+INODE.addressBlock]
744 mov ebx, [ebp+EXTFS.tempBlockBuffer]
748 mov ecx, [ebp+EXTFS.dwordsPerBlock]
751 .get_double_indirect_block:
752 mov eax, [esi+INODE.doubleAddress]
755 mov ebx, [ebp+EXTFS.tempBlockBuffer]
761 mov ecx, [ebp+EXTFS.dwordsPerBlock]
763 ; eax = number in doubly-indirect block, edx = number in indirect block
793 ; in: eax = inode number
794 ; out: eax = inode sector, edx = offset in sector
797 div [ebp+EXTFS.superblock.inodesPerGroup]
799 add eax, [ebp+EXTFS.descriptorTable]
800 mov ebx, [eax+BGDESCR.inodeTable]
801 imul ebx, [ebp+EXTFS.sectorsPerBlock]
802 movzx eax, [ebp+EXTFS.superblock.inodeSize]
811 ; in: eax = inode number, ebx -> inode data
812 push edx edi esi ecx ebx eax
816 mov [edi+INODE.inodeModified], eax
820 movzx ecx, [ebp+EXTFS.superblock.inodeSize]
822 lea edi, [ebp+EXTFS.rootInodeBuffer]
825 call getInodeLocation
826 mov ebx, [ebp+EXTFS.tempBlockBuffer]
832 movzx ecx, [ebp+EXTFS.superblock.inodeSize]
839 pop ebx ecx esi edi edx
843 movi eax, ERROR_DEVICE
848 ; in: eax = inode number, ebx -> inode buffer
849 push edx edi esi ecx ebx
851 call getInodeLocation
852 mov ebx, [ebp+EXTFS.tempBlockBuffer]
856 movzx ecx, [ebp+EXTFS.superblock.inodeSize]
861 pop ebx ecx esi edi edx
866 ; edi -> indirect block number
867 ; ebx = starting extent block
869 ; edx = starting file block
874 mov ebx, [ebp+EXTFS.tempBlockBuffer]
884 mov al, ERROR_FS_FAIL
899 mov ecx, [ebp+EXTFS.dwordsPerBlock]
900 mov edi, [ebp+EXTFS.tempBlockBuffer]
905 mov ecx, [ebp+EXTFS.dwordsPerBlock]
923 mov ebx, [ebp+EXTFS.tempBlockBuffer]
928 doublyIndirectBlockAlloc:
930 ; edi -> indirect block number
931 ; edx = starting file block
932 ; ebx = starting extent block
934 ; [esp+4] = rest of size
935 ; [esp+8] = parent inode number
940 mov ebx, [ebp+EXTFS.mainBlockBuffer]
945 mov ecx, [ebp+EXTFS.dwordsPerBlock]
955 mov al, ERROR_FS_FAIL
971 mov ecx, [ebp+EXTFS.dwordsPerBlock]
972 mov edi, [ebp+EXTFS.mainBlockBuffer]
985 call indirectBlockAlloc
987 cmp edx, [ebp+EXTFS.dwordsPerBlock]
997 mov ebx, [ebp+EXTFS.mainBlockBuffer]
1011 call extfsExtentAlloc
1018 ; [ebp+EXTFS.inodeBuffer] = inode
1019 ; ecx = inode number
1020 ; edx:eax = new size
1021 push ebx esi edi ecx
1022 lea esi, [ebp+EXTFS.inodeBuffer]
1023 mov ebx, [esi+INODE.fileSize]
1024 mov ecx, [esi+INODE.fileSizeHigh]
1028 mov ecx, [esi+INODE.fileSizeHigh]
1029 mov [esi+INODE.fileSize], eax
1030 mov [esi+INODE.fileSizeHigh], edx
1033 div [ebp+EXTFS.bytesPerBlock]
1040 div [ebp+EXTFS.bytesPerBlock]
1052 call extfsExtentAlloc
1058 cmp edx, [ebp+EXTFS.dwordsPerBlock]
1060 sub edx, [ebp+EXTFS.dwordsPerBlock]
1061 cmp edx, [ebp+EXTFS.dwordsPerBranch]
1062 jc .doublyIndirectBlock
1063 sub edx, [ebp+EXTFS.dwordsPerBranch]
1064 jmp .triplyIndirectBlock
1070 lea edi, [esi+INODE.blockNumbers+edx*4]
1095 lea edi, [esi+INODE.addressBlock]
1100 call indirectBlockAlloc
1105 .doublyIndirectBlock:
1106 lea edi, [esi+INODE.doubleAddress]
1107 call doublyIndirectBlockAlloc
1109 mov edx, [ebp+EXTFS.dwordsPerBranch]
1110 add edx, [ebp+EXTFS.dwordsPerBlock]
1114 .triplyIndirectBlock:
1116 stdcall kernel_alloc, [ebp+EXTFS.bytesPerBlock]
1119 mov eax, [ebp+EXTFS.inodeBuffer.tripleAddress]
1128 div [ebp+EXTFS.dwordsPerBranch]
1129 lea edi, [esi+eax*4]
1134 mov al, ERROR_FS_FAIL
1137 stdcall kernel_free, esi
1140 imul ecx, [ebp+EXTFS.sectorsPerBlock]
1141 sub [ebp+EXTFS.inodeBuffer.sectorsUsed], ecx
1143 imul ebx, [ebp+EXTFS.sectorsPerBlock]
1146 sub [ebp+EXTFS.inodeBuffer.fileSize], ebx
1152 mov al, ERROR_FS_FAIL
1155 mov [ebp+EXTFS.inodeBuffer.tripleAddress], ebx
1160 mov ecx, [ebp+EXTFS.dwordsPerBlock]
1168 call doublyIndirectBlockAlloc
1177 call extfsExtentAlloc
1183 mov eax, [ebp+EXTFS.inodeBuffer.tripleAddress]
1185 call extfsWriteBlock
1186 stdcall kernel_free, esi
1196 mov eax, [ebp+EXTFS.inodeBuffer.tripleAddress]
1198 call extfsWriteBlock
1203 ; in: edi -> list of blocks, edx = amount of blocks
1204 ; out: ebx=0 -> end of list
1221 call extfsExtentFree
1228 ; in: edi -> indirect block number, edx = starting block
1229 ; out: edi = edi+4, eax=0 -> end
1234 mov ebx, [ebp+EXTFS.mainBlockBuffer]
1237 lea edi, [ebx+edx*4]
1239 add edx, [ebp+EXTFS.dwordsPerBlock]
1251 call extfsExtentFree
1256 mov ebx, [ebp+EXTFS.mainBlockBuffer]
1257 call extfsWriteBlock
1268 freeDoublyIndirectBlock:
1269 ; in: edi -> doubly-indirect block number, edx = starting block
1270 ; out: edi = edi+4, eax=-1 -> done, eax=0 -> end
1275 stdcall kernel_alloc, [ebp+EXTFS.bytesPerBlock]
1283 mov ecx, [ebp+EXTFS.dwordsPerBlock]
1287 lea edi, [ebx+eax*4]
1289 call freeIndirectBlock
1302 call extfsExtentFree
1308 call extfsWriteBlock
1323 ; in: edx:eax = new size, [ebp+EXTFS.inodeBuffer] = inode
1324 lea esi, [ebp+EXTFS.inodeBuffer]
1326 cmp eax, [esi+INODE.fileSize]
1327 sbb ecx, [esi+INODE.fileSizeHigh]
1329 mov [esi+INODE.fileSize], eax
1330 mov [esi+INODE.fileSizeHigh], edx
1334 div [ebp+EXTFS.bytesPerBlock]
1341 cmp edx, [ebp+EXTFS.dwordsPerBlock]
1343 sub edx, [ebp+EXTFS.dwordsPerBlock]
1344 cmp edx, [ebp+EXTFS.dwordsPerBranch]
1345 jc .doublyIndirectBlock
1346 sub edx, [ebp+EXTFS.dwordsPerBranch]
1347 jmp .triplyIndirectBlock
1350 lea edi, [esi+INODE.blockNumbers+edx*4]
1357 lea edi, [esi+INODE.addressBlock]
1358 call freeIndirectBlock
1361 .doublyIndirectBlock:
1362 lea edi, [esi+INODE.doubleAddress]
1363 call freeDoublyIndirectBlock
1366 .triplyIndirectBlock:
1367 mov eax, [esi+INODE.tripleAddress]
1371 stdcall kernel_alloc, [ebp+EXTFS.bytesPerBlock]
1379 div [ebp+EXTFS.dwordsPerBranch]
1380 mov ecx, [ebp+EXTFS.dwordsPerBlock]
1382 lea edi, [ebx+eax*4]
1384 call freeDoublyIndirectBlock
1395 call extfsExtentFree
1396 mov [esi+INODE.tripleAddress], eax
1401 call extfsWriteBlock
1413 ; eax = inode on which to link
1414 ; ebx = inode to link
1415 ; esi -> name in UTF-8
1417 push esi edi ebx ecx eax edx
1420 lea esi, [ebp+EXTFS.inodeBuffer]
1423 jc .error_inode_read
1424 mov eax, [esi+INODE.fileSize]
1426 div [ebp+EXTFS.bytesPerBlock]
1429 push eax ; blocks total
1430 push ecx ; current file block number
1434 jc .error_get_inode_block
1436 mov ebx, [ebp+EXTFS.tempBlockBuffer]
1438 jc .error_block_read
1440 add ecx, 8 ; directory entry size
1441 mov edi, [ebp+EXTFS.tempBlockBuffer]
1443 add edx, [ebp+EXTFS.bytesPerBlock]
1445 movzx eax, [edi+DIRENTRY.entryLength]
1448 cmp [edi+DIRENTRY.inodeNumber], 0
1450 movzx ebx, [edi+DIRENTRY.nameLength]
1458 mov [edi+DIRENTRY.entryLength], bx
1460 mov [edi+DIRENTRY.entryLength], ax
1479 mov [edi+DIRENTRY.entryLength], ax
1482 mov [edi+DIRENTRY.inodeNumber], 0
1484 mov ebx, [ebp+EXTFS.tempBlockBuffer]
1485 call extfsWriteBlock
1489 mov eax, [esi+INODE.fileSize]
1490 add eax, [ebp+EXTFS.bytesPerBlock]
1493 call extfsExtendFile
1494 jc .error_get_inode_block
1498 jc .error_get_inode_block
1501 jc .error_get_inode_block
1503 mov edi, [ebp+EXTFS.tempBlockBuffer]
1504 mov eax, [ebp+EXTFS.bytesPerBlock]
1505 mov [edi+DIRENTRY.entryLength], ax
1507 pop edx ecx ecx ecx ebx esi
1508 mov [edi+DIRENTRY.inodeNumber], ebx
1509 mov word [edi+DIRENTRY.nameLength], cx
1513 test [ebp+EXTFS.superblock.incompatibleFlags], 2
1516 mov [edi+DIRENTRY.fileType], al
1521 mov ebx, [ebp+EXTFS.tempBlockBuffer]
1522 call extfsWriteBlock
1524 pop edx ecx ecx ebx edi esi
1529 .error_get_inode_block:
1536 ; in: eax = directory inode number, esi = inode to unlink
1538 lea ebx, [ebp+EXTFS.inodeBuffer]
1547 mov ebx, [ebp+EXTFS.tempBlockBuffer]
1550 .first_dir_entry: ; edi -> block
1551 cmp [ebx+DIRENTRY.inodeNumber], esi
1553 mov [ebx+DIRENTRY.inodeNumber], 0
1554 mov word [ebx+DIRENTRY.nameLength], 0 ; fileType = 0
1559 movi eax, ERROR_FS_FAIL
1572 add edx, [ebp+EXTFS.bytesPerBlock]
1575 movzx ecx, [ebx+DIRENTRY.entryLength]
1581 cmp [ebx+DIRENTRY.inodeNumber], esi
1583 mov cx, [ebx+DIRENTRY.entryLength]
1584 add [edx+DIRENTRY.entryLength], cx
1589 mov ebx, [ebp+EXTFS.tempBlockBuffer]
1590 call extfsWriteBlock
1596 ; in: esi -> path string in UTF-8
1598 ; edi -> file name in UTF-8
1599 ; esi = last inode number
1600 ; [ebp+EXTFS.inodeBuffer] = last inode
1601 ; ecx = parent inode number
1602 ; CF=1 -> file not found, edi=0 -> error
1604 lea esi, [ebp+EXTFS.rootInodeBuffer]
1605 lea edi, [ebp+EXTFS.inodeBuffer]
1606 movzx ecx, [ebp+EXTFS.superblock.inodeSize]
1610 pushd ebx 0 ROOT_INODE
1612 cmp [edx+INODE.fileSize], 0
1629 push [edx+INODE.fileSize]
1631 .folder_block_cycle:
1635 mov ebx, [ebp+EXTFS.mainBlockBuffer]
1640 add edx, [ebp+EXTFS.bytesPerBlock]
1642 cmp [ebx+DIRENTRY.inodeNumber], 0
1645 movzx ecx, [ebx+DIRENTRY.nameLength]
1646 lea edi, [ebx+DIRENTRY.name]
1652 movzx ecx, [ebx+DIRENTRY.entryLength]
1669 ; ebx -> matched directory entry, esi -> name without parent, or not changed
1672 sub eax, [ebp+EXTFS.bytesPerBlock]
1676 jmp .folder_block_cycle
1681 mov eax, [ebx+DIRENTRY.inodeNumber]
1682 lea ebx, [ebp+EXTFS.inodeBuffer]
1689 movzx eax, [ebx+INODE.accessMode]
1693 xor edi, edi ; path folder is a file
1703 xor edi, edi ; path folder not found
1705 movi eax, ERROR_FILE_NOT_FOUND
1714 lea ebx, [ebp+EXTFS.superblock]
1720 movi eax, ERROR_UNSUPPORTED_FS
1721 test [ebp+EXTFS.mountType], READ_ONLY
1724 lea ecx, [ebp+EXTFS.Lock]
1733 lea ecx, [ebp+EXTFS.Lock]
1736 ;----------------------------------------------------------------
1743 lea esi, [ebp+EXTFS.inodeBuffer]
1744 test [esi+INODE.accessMode], FLAG_FILE
1745 jnz .error_not_found
1749 lea esi, [ebp+EXTFS.rootInodeBuffer]
1750 lea edi, [ebp+EXTFS.inodeBuffer]
1751 movzx ecx, [ebp+EXTFS.superblock.inodeSize]
1757 cmp [esi+INODE.fileSize], 0
1760 push edx ; [edi+28] result buffer
1761 push 0 ; [edi+24] end of the current block in folder
1762 pushd [ebx+12] ; [edi+20] files to read
1763 pushd [ebx+4] ; [edi+16] first wanted file
1764 pushd [ebx+8] ; [edi+12] flags
1765 push 0 ; [edi+8] read files
1766 push 0 ; [edi+4] files in folder
1767 push 0 ; [edi] current block index
1768 mov edi, esp ; edi -> local variables
1773 mov ebx, [ebp+EXTFS.mainBlockBuffer]
1777 add eax, [ebp+EXTFS.bytesPerBlock]
1781 jecxz .find_wanted_end
1783 cmp [ebx+DIRENTRY.inodeNumber], 0
1788 movzx eax, [ebx+DIRENTRY.entryLength]
1789 cmp eax, 12 ; minimum entry length
1791 test eax, 3 ; length must be aligned
1793 sub [esi+INODE.fileSize], eax
1796 jb .find_wanted_start
1797 push .find_wanted_start
1798 .end_block: ; read next block
1799 cmp [esi+INODE.fileSize], 0
1806 mov ebx, [ebp+EXTFS.mainBlockBuffer]
1811 add eax, [ebp+EXTFS.bytesPerBlock]
1816 loop .find_wanted_cycle
1821 cmp [ebx+DIRENTRY.inodeNumber], 0
1825 push ebx edi ecx esi edx edi
1832 mov eax, [ebx+DIRENTRY.inodeNumber]
1833 mov ebx, [ebp+EXTFS.tempBlockBuffer]
1835 jc .error_read_subinode
1838 mov eax, [ebx+INODE.inodeModified]
1839 sub eax, 978307200 ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
1842 mov eax, [esi+INODE.accessedTime]
1846 mov eax, [esi+INODE.dataModified]
1850 or dword [edx], KOS_DIRECTORY
1851 test [esi+INODE.accessMode], FLAG_FILE
1853 xor dword [edx], KOS_DIRECTORY ; mark as file
1854 mov eax, [esi+INODE.fileSize]
1856 mov eax, [esi+INODE.fileSizeHigh]
1860 movzx ecx, [esi+DIRENTRY.nameLength]
1861 lea esi, [esi+DIRENTRY.name]
1864 or byte [edx], KOS_HIDDEN
1884 movzx eax, [ebx+DIRENTRY.entryLength]
1889 sub [esi+INODE.fileSize], eax
1916 mov dword [edx], 1 ; version
1927 movi eax, ERROR_FS_FAIL
1928 .error_read_subinode:
1939 movi eax, ERROR_FS_FAIL
1943 movi eax, ERROR_FILE_NOT_FOUND
1946 ;----------------------------------------------------------------
1952 lea esi, [ebp+EXTFS.inodeBuffer]
1953 mov byte [esp], ERROR_ACCESS_DENIED
1954 test [esi+INODE.accessMode], FLAG_FILE
1955 jz .ret ; not a file
1956 mov byte [esp], ERROR_END_OF_FILE
1957 mov eax, [esi+INODE.fileSize]
1958 mov edx, [esi+INODE.fileSizeHigh]
1973 div [ebp+EXTFS.bytesPerBlock]
1982 mov ecx, [ebp+EXTFS.sectorsPerBlock]
1984 mov ebx, [ebp+EXTFS.mainBlockBuffer]
1989 mov ecx, [ebp+EXTFS.bytesPerBlock]
2006 div [ebp+EXTFS.bytesPerBlock]
2021 imul ecx, [ebp+EXTFS.sectorsPerBlock]
2024 mul [ebp+EXTFS.sectorsPerBlock]
2042 movi eax, ERROR_DEVICE
2051 ;----------------------------------------------------------------
2058 lea esi, [ebp+EXTFS.inodeBuffer]
2067 or dword [edx], KOS_HIDDEN
2069 or dword [edx], KOS_DIRECTORY
2070 test [esi+INODE.accessMode], FLAG_FILE
2072 xor dword [edx], KOS_DIRECTORY ; mark as file
2073 mov eax, [esi+INODE.fileSize]
2074 mov ebx, [esi+INODE.fileSizeHigh]
2075 mov dword [edx+32], eax
2076 mov dword [edx+36], ebx
2079 mov eax, [esi+INODE.inodeModified]
2080 sub eax, 978307200 ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
2083 mov eax, [esi+INODE.accessedTime]
2087 mov eax, [esi+INODE.dataModified]
2099 mov eax, dword[ebp+EXTFS.Length]
2100 mov edx, dword[ebp+EXTFS.Length+4]
2111 lea esi, [ebp+EXTFS.superblock.volumeLabel]
2141 ;----------------------------------------------------------------
2143 call extfsWritingInit
2149 lea edi, [ebp+EXTFS.inodeBuffer]
2150 call fsCalculateTime
2151 add eax, 978307200 ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
2152 mov [edi+INODE.accessedTime], eax
2155 call fsCalculateTime
2157 mov [edi+INODE.dataModified], eax
2164 call writeSuperblock
2165 mov esi, [ebp+PARTITION.Disk]
2172 ;----------------------------------------------------------------
2174 call extfsWritingInit
2178 movzx edi, [ebp+EXTFS.inodeBuffer.accessMode]
2187 mov ebx, [ebp+EXTFS.tempBlockBuffer]
2191 add edx, [ebp+EXTFS.bytesPerBlock]
2193 movzx ecx, [ebx+DIRENTRY.nameLength]
2194 mov ax, word [ebx+DIRENTRY.name]
2205 mov cx, [ebx+DIRENTRY.entryLength]
2217 push ERROR_ACCESS_DENIED
2230 cmp eax, ERROR_END_OF_FILE
2238 lea ebx, [ebp+EXTFS.inodeBuffer]
2241 dec [ebx+INODE.linksCount]
2247 dec [ebx+INODE.linksCount]
2255 call extfsTruncateFile ; free file's data
2256 movzx ecx, [ebp+EXTFS.superblock.inodeSize]
2257 lea edi, [ebp+EXTFS.inodeBuffer]
2264 mov [ebx+INODE.deletedTime], eax
2268 div [ebp+EXTFS.superblock.inodesPerGroup]
2270 mov ebx, [ebp+EXTFS.descriptorTable]
2275 dec [ebx+BGDESCR.directoriesCount]
2277 inc [ebx+BGDESCR.inodesFree]
2278 push [ebx+BGDESCR.inodeBitmap]
2279 call extfsWriteDescriptor
2281 mov ebx, [ebp+EXTFS.tempBlockBuffer]
2293 call extfsWriteBlock
2294 inc [ebp+EXTFS.superblock.inodesFree]
2297 lea ebx, [ebp+EXTFS.inodeBuffer]
2300 call writeSuperblock
2301 mov esi, [ebp+PARTITION.Disk]
2309 ;----------------------------------------------------------------
2311 call extfsWritingInit
2313 jnc .success ; exist
2317 call extfsInodeAlloc
2320 lea edi, [ebp+EXTFS.inodeBuffer]
2321 movzx ecx, [ebp+EXTFS.superblock.inodeSize]
2326 lea ebx, [ebp+EXTFS.inodeBuffer]
2327 mov [ebx+INODE.accessedTime], eax
2328 mov [ebx+INODE.dataModified], eax
2330 ; edx = allocated inode number, edi -> filename, esi = parent inode number
2331 mov [ebx+INODE.accessMode], DIRECTORY or 511
2332 mov byte [ebx+INODE.linksCount], 2
2340 mov dl, DIR_DIRECTORY
2349 mov dl, DIR_DIRECTORY
2350 mov esi, parent_link
2354 ; link parent to child
2359 mov dl, DIR_DIRECTORY
2364 lea ebx, [ebp+EXTFS.inodeBuffer]
2365 inc [ebx+INODE.linksCount]
2373 div [ebp+EXTFS.superblock.inodesPerGroup]
2374 mov ebx, [ebp+EXTFS.descriptorTable]
2377 inc [ebx+BGDESCR.directoriesCount]
2378 call extfsWriteDescriptor
2382 call writeSuperblock
2383 mov esi, [ebp+PARTITION.Disk]
2390 parent_link db "..", 0
2392 ;----------------------------------------------------------------
2394 call extfsWritingInit
2401 call extfsInodeAlloc
2403 push ebx ebx esi edi
2404 lea edi, [ebp+EXTFS.inodeBuffer]
2405 movzx ecx, [ebp+EXTFS.superblock.inodeSize]
2410 lea ebx, [ebp+EXTFS.inodeBuffer]
2411 mov [ebx+INODE.accessedTime], eax
2412 mov [ebx+INODE.dataModified], eax
2414 ; edx = allocated inode number, edi -> filename, esi = parent inode number
2415 mov [ebx+INODE.accessMode], FLAG_FILE or 110110110b
2416 mov byte [ebx+INODE.linksCount], 1
2420 ; link parent to child
2424 mov dl, DIR_FLAG_FILE
2428 lea ebx, [ebp+EXTFS.inodeBuffer]
2434 jmp ext_WriteFile.start
2437 movi eax, ERROR_ACCESS_DENIED
2438 test [ebp+EXTFS.inodeBuffer.accessMode], FLAG_FILE
2439 jz .error ; not a file
2443 push eax edx ebx esi
2444 call extfsTruncateFile
2446 jmp ext_WriteFile.start
2456 ;----------------------------------------------------------------
2458 call extfsWritingInit
2462 mov byte [esp], ERROR_ACCESS_DENIED
2463 test [ebp+EXTFS.inodeBuffer.accessMode], FLAG_FILE
2464 jz .ret ; not a file
2473 call extfsExtendFile
2481 div [ebp+EXTFS.bytesPerBlock]
2491 mov ecx, [ebp+EXTFS.sectorsPerBlock]
2494 mov ebx, [ebp+EXTFS.mainBlockBuffer]
2499 mov ecx, [ebp+EXTFS.bytesPerBlock]
2521 div [ebp+EXTFS.bytesPerBlock]
2536 imul ecx, [ebp+EXTFS.sectorsPerBlock]
2539 mul [ebp+EXTFS.sectorsPerBlock]
2557 movi eax, ERROR_DEVICE
2565 lea ebx, [ebp+EXTFS.inodeBuffer]
2569 call writeSuperblock
2570 mov esi, [ebp+PARTITION.Disk]
2582 ;----------------------------------------------------------------
2584 call extfsWritingInit
2587 lea edi, [ebp+EXTFS.inodeBuffer]
2588 movi eax, ERROR_ACCESS_DENIED
2589 test [edi+INODE.accessMode], FLAG_FILE
2590 jz .error2 ; not a file
2593 mov ebx, [edi+INODE.fileSize]
2594 mov ecx, [edi+INODE.fileSizeHigh]
2600 call extfsExtendFile
2603 mov eax, [edi+INODE.fileSize]
2604 mov edx, [edi+INODE.fileSizeHigh]
2611 stdcall kernel_alloc, eax
2625 call ext_WriteFile.erase
2631 call extfsTruncateFile
2637 lea ebx, [ebp+EXTFS.inodeBuffer]
2640 call writeSuperblock
2641 mov esi, [ebp+PARTITION.Disk]
2650 ;----------------------------------------------------------------
2652 call extfsWritingInit
2666 test [ebp+EXTFS.inodeBuffer.accessMode], DIRECTORY
2677 lea ebx, [ebp+EXTFS.inodeBuffer]
2678 dec [ebx+INODE.linksCount]
2693 lea ebx, [ebp+EXTFS.inodeBuffer]
2694 inc [ebx+INODE.linksCount]
2697 call writeSuperblock
2698 mov esi, [ebp+PARTITION.Disk]