Subversion Repositories Kolibri OS

Rev

Rev 6856 | Rev 6861 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2013-2016. All rights reserved. ;;
  4. ;;  Distributed under terms of the GNU General Public License.  ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 6859 $
  9.  
  10. ; EXT external functions
  11. ;   in:
  12. ; ebx -> parameter structure of sysfunc 70
  13. ; ebp -> EXTFS structure
  14. ; esi -> path string in UTF-8
  15. ;   out:
  16. ; eax, ebx = return values for sysfunc 70
  17. iglobal
  18. align 4
  19. ext_user_functions:
  20.         dd      ext_free
  21.         dd      (ext_user_functions_end - ext_user_functions - 4) / 4
  22.         dd      ext_ReadFile
  23.         dd      ext_ReadFolder
  24.         dd      ext_CreateFile
  25.         dd      ext_WriteFile
  26.         dd      ext_SetFileEnd
  27.         dd      ext_GetFileInfo
  28.         dd      ext_SetFileInfo
  29.         dd      0
  30.         dd      ext_Delete
  31.         dd      ext_CreateFolder
  32. ext_user_functions_end:
  33. endg
  34.  
  35. struct DIRENTRY
  36. inodeNumber     dd  ?
  37. entryLength     dw  ?
  38. nameLength      db  ?
  39. fileType        db  ?
  40. name            db  ?   ; rb [nameLength]
  41. ends
  42.  
  43. struct INODE
  44. accessMode      dw  ?
  45. UID             dw  ?
  46. fileSize        dd  ?
  47. accessedTime    dd  ?
  48. inodeModified   dd  ?
  49. dataModified    dd  ?
  50. deletedTime     dd  ?
  51. GID             dw  ?
  52. linksCount      dw  ?
  53. sectorsUsed     dd  ?
  54. featureFlags    dd  ?
  55. reserved        dd  ?
  56. blockNumbers    rd  12
  57. addressBlock    dd  ?
  58. doubleAddress   dd  ?
  59. tripleAddress   dd  ?
  60. generation      dd  ?
  61. ACL             dd  ?
  62. fileSizeHigh    dd  ?
  63. ends
  64.  
  65. struct BGDESCR  ; block group descriptor
  66. blockBitmap         dd  ?
  67. inodeBitmap         dd  ?
  68. inodeTable          dd  ?
  69. blocksFree          dw  ?
  70. inodesFree          dw  ?
  71. directoriesCount    dw  ?
  72. reserved            rb  14
  73. ends
  74.  
  75. struct SUPERBLOCK
  76. inodesTotal         dd  ?
  77. blocksTotal         dd  ?
  78. blocksReserved      dd  ?
  79. blocksFree          dd  ?
  80. inodesFree          dd  ?
  81. firstGroupBlock     dd  ?
  82. sectorsPerBlockLog  dd  ?   ; shift for 1024
  83. fragmentSizeLog     dd  ?
  84. blocksPerGroup      dd  ?
  85. fragmentsPerGroup   dd  ?
  86. inodesPerGroup      dd  ?
  87. lastMountTime       dd  ?
  88. lastWriteTime       dd  ?
  89. mountCount          dw  ?
  90. mountMax            dw  ?
  91. magic               dw  ?
  92. state               dw  ?
  93. errorHandling       dw  ?
  94. additionalVersion   dw  ?
  95. lastCheck           dd  ?
  96. checkInterval       dd  ?
  97. creatorOS           dd  ?
  98. dynamicVersionFlag  dd  ?
  99. reservedUID         dw  ?
  100. reservedGID         dw  ?
  101. firstInode          dd  ?
  102. inodeSize           dw  ?
  103. thisBlockGroup      dw  ?
  104. compatibleFlags     dd  ?
  105. incompatibleFlags   dd  ?
  106. RO_compatibleFlags  dd  ?
  107. ends
  108.  
  109. ; ext4 extent tree
  110. struct NODEHEADER       ; tree node header
  111. magic           dw  ?   ; 0xF30A
  112. entriesFolow    dw  ?
  113. entriesMax      dw  ?
  114. currentDepth    dw  ?
  115. generation      dd  ?
  116. ends
  117.  
  118. struct INDEX    ; root/branch
  119. fileBlock       dd  ?
  120. nodeBlock       dd  ?
  121. nodeBlockHigh   dw  ?
  122. reserved        dw  ?
  123. ends
  124.  
  125. struct EXTENT   ; leaf
  126. fileBlock       dd  ?
  127. blocksCount     dw  ?
  128. fsBlockHigh     dw  ?
  129. fsBlock         dd  ?
  130. ends
  131.  
  132. ROOT_INODE = 2
  133. PERMISSIONS = 110110110b
  134. EXTENTS_USED = 80000h
  135. TYPE_MASK = 0F000h
  136. FLAG_FILE = 8000h
  137. DIRECTORY = 4000h
  138. DIR_FLAG_FILE = 1
  139. DIR_DIRECTORY = 2
  140. KOS_HIDDEN = 2
  141. KOS_DIRECTORY = 10h
  142. READ_ONLY = 1
  143.  
  144. ; Implemented "incompatible" features:
  145. ; 2 = have file type in directory entry
  146. ; 40h = extents
  147. ; 200h = flexible block groups
  148. INCOMPATIBLE_SUPPORT = 242h
  149. ; Read only support for "incompatible" features:
  150. INCOMPATIBLE_READ_SUPPORT = 240h
  151.  
  152. ; Implemented "read-only" features:
  153. ; 1 = sparse superblock
  154. ; 2 = 64-bit file size
  155. READ_ONLY_SUPPORT = 3
  156.  
  157. struct EXTFS PARTITION
  158. Lock                MUTEX
  159. mountType           dd  ?
  160. bytesPerBlock       dd  ?
  161. sectorsPerBlock     dd  ?
  162. dwordsPerBlock      dd  ?
  163. dwordsPerBranch     dd  ?   ; dwordsPerBlock ^ 2
  164. mainBlockBuffer     dd  ?
  165. tempBlockBuffer     dd  ?
  166. descriptorTable     dd  ?
  167. descriptorTableEnd  dd  ?
  168. align0  rb  200h-EXTFS.align0
  169. superblock          SUPERBLOCK
  170. align1  rb  400h-EXTFS.align1
  171. rootInodeBuffer     INODE
  172. align2  rb  600h-EXTFS.align2
  173. inodeBuffer         INODE
  174. align3  rb  800h-EXTFS.align3
  175. ends
  176.  
  177. ; mount if it's a valid EXT partition
  178. ext2_create_partition:
  179. ;   in:
  180. ; ebp -> PARTITION structure
  181. ; ebx -> boot sector
  182. ; ebx+512 -> buffer
  183. ;   out:
  184. ; eax -> EXTFS structure, 0 = not EXT
  185.         push    ebx
  186.         cmp     dword [esi+DISK.MediaInfo.SectorSize], 512
  187.         jnz     .fail
  188.         mov     eax, 2
  189.         add     ebx, 512
  190.         call    fs_read32_sys
  191.         test    eax, eax
  192.         jnz     .fail
  193.         cmp     [ebx+SUPERBLOCK.magic], 0xEF53
  194.         jne     .fail
  195.         cmp     [ebx+SUPERBLOCK.state], 1
  196.         ja      .fail
  197.         test    [ebx+SUPERBLOCK.incompatibleFlags], not INCOMPATIBLE_SUPPORT
  198.         jnz     .fail
  199.         cmp     [ebx+SUPERBLOCK.sectorsPerBlockLog], 6  ; 64KB
  200.         ja      .fail
  201.         cmp     [ebx+SUPERBLOCK.inodeSize], 512
  202.         ja      .fail
  203.         cmp     [ebx+SUPERBLOCK.blocksPerGroup], 0
  204.         je      .fail
  205.         cmp     [ebx+SUPERBLOCK.inodesPerGroup], 0
  206.         je      .fail
  207.         movi    eax, sizeof.EXTFS
  208.         call    malloc
  209.         test    eax, eax
  210.         jz      .fail
  211.         mov     ecx, dword [ebp+PARTITION.FirstSector]
  212.         mov     dword [eax+EXTFS.FirstSector], ecx
  213.         mov     ecx, dword [ebp+PARTITION.FirstSector+4]
  214.         mov     dword [eax+EXTFS.FirstSector+4], ecx
  215.         mov     ecx, dword [ebp+PARTITION.Length]
  216.         mov     dword [eax+EXTFS.Length], ecx
  217.         mov     ecx, dword [ebp+PARTITION.Length+4]
  218.         mov     dword [eax+EXTFS.Length+4], ecx
  219.         mov     ecx, [ebp+PARTITION.Disk]
  220.         mov     [eax+EXTFS.Disk], ecx
  221.         mov     [eax+EXTFS.FSUserFunctions], ext_user_functions
  222.  
  223.         push    ebp esi edi
  224.         mov     ebp, eax
  225.         lea     ecx, [eax+EXTFS.Lock]
  226.         call    mutex_init
  227.         mov     esi, ebx
  228.         lea     edi, [ebp+EXTFS.superblock]
  229.         mov     ecx, 512/4
  230.         rep movsd   ; copy superblock
  231.         mov     ecx, [ebx+SUPERBLOCK.sectorsPerBlockLog]
  232.         inc     ecx
  233.         mov     eax, 1
  234.         shl     eax, cl
  235.         mov     [ebp+EXTFS.sectorsPerBlock], eax
  236.         shl     eax, 9
  237.         mov     [ebp+EXTFS.bytesPerBlock], eax
  238.         shl     eax, 1
  239.         push    eax
  240.         shr     eax, 3
  241.         mov     [ebp+EXTFS.dwordsPerBlock], eax
  242.         mul     eax
  243.         mov     [ebp+EXTFS.dwordsPerBranch], eax
  244.         call    kernel_alloc
  245.         test    eax, eax
  246.         jz      .error
  247.         mov     [ebp+EXTFS.mainBlockBuffer], eax
  248.         add     eax, [ebp+EXTFS.bytesPerBlock]
  249.         mov     [ebp+EXTFS.tempBlockBuffer], eax
  250.         mov     [ebp+EXTFS.mountType], 0
  251.         test    [ebx+SUPERBLOCK.RO_compatibleFlags], not READ_ONLY_SUPPORT
  252.         jnz     .read_only
  253.         test    [ebx+SUPERBLOCK.incompatibleFlags], INCOMPATIBLE_READ_SUPPORT
  254.         jz      @f
  255. .read_only:
  256.         or      [ebp+EXTFS.mountType], READ_ONLY
  257. @@:
  258.         mov     eax, [ebx+SUPERBLOCK.inodesTotal]
  259.         dec     eax
  260.         xor     edx, edx
  261.         div     [ebx+SUPERBLOCK.inodesPerGroup]
  262.         inc     eax
  263.         shl     eax, 5
  264.         push    eax eax
  265.         call    kernel_alloc
  266.         pop     ecx
  267.         test    eax, eax
  268.         jz      .error2
  269.         mov     [ebp+EXTFS.descriptorTable], eax
  270.         mov     ebx, eax
  271.         add     eax, ecx
  272.         mov     [ebp+EXTFS.descriptorTableEnd], eax
  273.         mov     eax, [ebp+EXTFS.superblock.firstGroupBlock]
  274.         inc     eax
  275.         mul     [ebp+EXTFS.sectorsPerBlock]
  276.         dec     ecx
  277.         shr     ecx, 9
  278.         inc     ecx
  279.         call    fs_read64_sys
  280.         test    eax, eax
  281.         jnz     @f
  282.         mov     al, ROOT_INODE
  283.         lea     ebx, [ebp+EXTFS.rootInodeBuffer]
  284.         call    readInode
  285.         test    eax, eax
  286.         jnz     @f
  287.         mov     eax, ebp
  288.         pop     edi esi ebp ebx
  289.         ret
  290.  
  291. @@:
  292.         stdcall kernel_free, [ebp+EXTFS.descriptorTable]
  293. .error2:
  294.         stdcall kernel_free, [ebp+EXTFS.mainBlockBuffer]
  295. .error:
  296.         mov     eax, ebp
  297.         call    free
  298.         pop     edi esi ebp
  299. .fail:
  300.         pop     ebx
  301.         xor     eax, eax
  302.         ret
  303.  
  304. ; unmount EXT partition
  305. ext_free:
  306. ; in: eax -> EXTFS structure
  307.         push    eax [eax+EXTFS.mainBlockBuffer]
  308.         stdcall kernel_free, [eax+EXTFS.descriptorTable]
  309.         call    kernel_free
  310.         pop     eax
  311.         jmp     free
  312.  
  313. extfsWriteBlock:
  314.         push    fs_write64_sys
  315.         jmp     @f
  316. ; in: eax = block number, ebx -> buffer
  317. extfsReadBlock:
  318.         push    fs_read64_sys
  319. @@:
  320.         push    ecx edx
  321.         mov     ecx, [ebp+EXTFS.sectorsPerBlock]
  322.         mul     ecx
  323.         call    dword[esp+8]
  324.         pop     edx ecx
  325.         add     esp, 4
  326.         test    eax, eax
  327.         jz      @f
  328.         movi    eax, ERROR_DEVICE
  329.         stc
  330. @@:
  331.         ret
  332.  
  333. extfsWriteDescriptor:
  334. ; in: ebx = block group descriptor
  335.         mov     eax, [ebp+EXTFS.superblock.firstGroupBlock]
  336.         inc     eax
  337.         mul     [ebp+EXTFS.sectorsPerBlock]
  338.         sub     ebx, [ebp+EXTFS.descriptorTable]
  339.         shr     ebx, 9
  340.         add     eax, ebx
  341.         shl     ebx, 9
  342.         add     ebx, [ebp+EXTFS.descriptorTable]
  343.         call    fs_write32_sys
  344.         ret
  345.  
  346. extfsExtentFree:
  347. ; in: eax = first block number, ecx = extent size
  348.         push    ebx edx edi
  349.         sub     eax, [ebp+EXTFS.superblock.firstGroupBlock]
  350.         xor     edx, edx
  351.         mov     ebx, [ebp+EXTFS.superblock.blocksPerGroup]
  352.         div     ebx
  353.         sub     ebx, edx
  354.         sub     ebx, ecx
  355.         jc      .ret
  356.         push    edx
  357.         mov     ebx, [ebp+EXTFS.descriptorTable]
  358.         shl     eax, 5
  359.         add     ebx, eax
  360.         mov     eax, ecx
  361.         mul     [ebp+EXTFS.sectorsPerBlock]
  362.         add     [ebx+BGDESCR.blocksFree], cx
  363.         add     [ebp+EXTFS.superblock.blocksFree], ecx
  364.         sub     [ebp+EXTFS.inodeBuffer.sectorsUsed], eax
  365.         push    [ebx+BGDESCR.blockBitmap]
  366.         call    extfsWriteDescriptor
  367.         pop     eax
  368.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  369.         mov     edx, eax
  370.         call    extfsReadBlock
  371.         pop     eax
  372.         jc      .ret
  373.         push    ebx edx
  374.         mov     edi, eax
  375.         shr     edi, 5
  376.         shl     edi, 2
  377.         add     edi, ebx
  378.         mov     edx, ecx
  379.         and     eax, 31
  380.         jz      .aligned
  381.         mov     ecx, 32
  382.         sub     ecx, eax
  383.         sub     edx, ecx
  384.         jnc     @f
  385.         add     ecx, edx
  386.         xor     edx, edx
  387. @@:
  388.         or      ebx, -1
  389.         shl     ebx, cl
  390.         not     ebx
  391.         mov     ecx, eax
  392.         shl     ebx, cl
  393.         not     ebx
  394.         and     [edi], ebx
  395.         add     edi, 4
  396.         xor     eax, eax
  397. .aligned:
  398.         mov     ecx, edx
  399.         shr     ecx, 5
  400.         rep stosd
  401.         and     edx, 31
  402.         jz      @f
  403.         mov     ecx, edx
  404.         not     eax
  405.         shl     eax, cl
  406.         and     [edi], eax
  407. @@:
  408.         pop     eax ebx
  409.         call    extfsWriteBlock
  410. .ret:
  411.         pop     edi edx ebx
  412.         xor     eax, eax
  413.         ret
  414.  
  415. extfsInodeAlloc:
  416. ; in: eax = parent inode number
  417. ; out: ebx = allocated inode number
  418.         push    ecx edx edi
  419.         dec     eax
  420.         xor     edx, edx
  421.         div     [ebp+EXTFS.superblock.inodesPerGroup]
  422.         mov     ebx, [ebp+EXTFS.descriptorTable]
  423.         shl     eax, 5
  424.         add     ebx, eax
  425.         push    ebx
  426. .test_block_group:
  427.         push    ebx
  428.         cmp     [ebx+BGDESCR.blocksFree], 0
  429.         jz      .next
  430.         cmp     [ebx+BGDESCR.inodesFree], 0
  431.         jz      .next
  432.         dec     [ebx+BGDESCR.inodesFree]
  433.         dec     [ebp+EXTFS.superblock.inodesFree]
  434.         push    [ebx+BGDESCR.inodeBitmap]
  435.         call    extfsWriteDescriptor
  436.         pop     eax
  437.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  438.         mov     edx, eax
  439.         mov     edi, ebx
  440.         call    extfsReadBlock
  441.         jc      .fail
  442.         mov     ecx, [ebp+EXTFS.superblock.inodesPerGroup]
  443.         or      eax, -1
  444.         shr     ecx, 5
  445.         repz scasd
  446.         jz      .next
  447.         sub     edi, 4
  448.         mov     eax, [edi]
  449.         not     eax
  450.         bsf     eax, eax
  451.         bts     [edi], eax
  452.         sub     edi, [ebp+EXTFS.tempBlockBuffer]
  453.         shl     edi, 3
  454.         add     eax, edi
  455.         mov     ecx, eax
  456.         mov     eax, edx
  457.         call    extfsWriteBlock
  458.         pop     eax
  459.         sub     eax, [ebp+EXTFS.descriptorTable]
  460.         shr     eax, 5
  461.         mul     [ebp+EXTFS.superblock.inodesPerGroup]
  462.         lea     ebx, [eax+ecx+1]
  463.         xor     eax, eax
  464. .ret:
  465.         pop     edi edi edx ecx
  466.         ret
  467.  
  468. .next:      ; search forward, then backward
  469.         pop     ebx
  470.         cmp     ebx, [esp]
  471.         jc      .backward
  472.         add     ebx, 32
  473.         cmp     ebx, [ebp+EXTFS.descriptorTableEnd]
  474.         jc      .test_block_group
  475.         mov     ebx, [esp]
  476. .backward:
  477.         sub     ebx, 32
  478.         cmp     ebx, [ebp+EXTFS.descriptorTable]
  479.         jnc     .test_block_group
  480.         movi    eax, ERROR_DISK_FULL
  481.         push    eax
  482. .fail:
  483.         pop     edi
  484.         jmp     .ret
  485.  
  486. extfsExtentAlloc:
  487. ; in: eax = parent inode number, ecx = blocks max
  488. ; out: ebx = first block number, ecx = blocks allocated
  489.         push    edx esi edi ecx
  490.         dec     eax
  491.         xor     edx, edx
  492.         div     [ebp+EXTFS.superblock.inodesPerGroup]
  493.         mov     ebx, [ebp+EXTFS.descriptorTable]
  494.         shl     eax, 5
  495.         add     ebx, eax
  496.         push    ebx
  497. .test_block_group:
  498.         push    ebx
  499.         cmp     [ebx+BGDESCR.blocksFree], 0
  500.         jz      .next
  501.         mov     eax, [ebx+BGDESCR.blockBitmap]
  502.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  503.         mov     edx, eax
  504.         mov     edi, ebx
  505.         call    extfsReadBlock
  506.         jc      .fail
  507.         mov     ecx, [ebp+EXTFS.superblock.blocksPerGroup]
  508.         shr     ecx, 5
  509.         or      eax, -1
  510.         repz scasd
  511.         jz      .next
  512.         mov     esi, edi
  513.         sub     esi, 4
  514.         push    edx ecx
  515.         mov     eax, [esi]
  516.         not     eax
  517.         bsf     ecx, eax
  518.         not     eax
  519.         shr     eax, cl
  520.         shl     eax, cl
  521.         mov     ebx, 32
  522.         bsf     ebx, eax
  523.         sub     ebx, ecx
  524.         mov     eax, [esp+16]
  525.         cmp     ebx, eax
  526.         jc      @f
  527.         mov     ebx, eax
  528. @@:
  529.         or      eax, -1
  530.         cmp     ebx, 32
  531.         jz      @f
  532.         xchg    ebx, ecx
  533.         shl     eax, cl
  534.         not     eax
  535.         xchg    ebx, ecx
  536.         shl     eax, cl
  537. @@:
  538.         or      [esi], eax
  539.         sub     esi, [ebp+EXTFS.tempBlockBuffer]
  540.         shl     esi, 3
  541.         add     esi, ecx
  542.         mov     eax, [esp+16]
  543.         sub     eax, ebx
  544.         mov     [esp+16], ebx
  545.         add     ebx, ecx
  546.         pop     ecx
  547.         test    eax, eax
  548.         jz      .done
  549.         cmp     ebx, 32
  550.         jnz     .done
  551.         jecxz   .done
  552.         mov     ebx, eax
  553.         shr     eax, 5
  554.         inc     eax
  555.         and     ebx, 31
  556.         cmp     ecx, eax
  557.         jnc     @f
  558.         mov     eax, ecx
  559.         mov     bl, 32
  560. @@:
  561.         mov     ecx, eax
  562.         shl     eax, 5
  563.         add     [esp+12], eax
  564.         xor     eax, eax
  565.         push    edi
  566.         repz scasd
  567.         jz      @f
  568.         mov     eax, [edi-4]
  569.         bsf     eax, eax
  570.         xchg    eax, ebx
  571.         test    ecx, ecx
  572.         jnz     @f
  573.         cmp     ebx, eax
  574.         jc      @f
  575.         mov     ebx, eax
  576. @@:
  577.         inc     ecx
  578.         shl     ecx, 5
  579.         sub     ecx, ebx
  580.         sub     [esp+16], ecx
  581.         mov     ecx, edi
  582.         pop     edi
  583.         sub     ecx, edi
  584.         shr     ecx, 2
  585.         dec     ecx
  586.         or      eax, -1
  587.         rep stosd
  588.         mov     ecx, ebx
  589.         jecxz   .done
  590.         neg     ecx
  591.         add     ecx, 32
  592.         shr     eax, cl
  593.         or      [edi], eax
  594. .done:
  595.         pop     eax
  596.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  597.         call    extfsWriteBlock
  598.         mov     ebx, [esp]
  599.         mov     ecx, [esp+8]
  600.         sub     [ebx+BGDESCR.blocksFree], cx
  601.         jnc     @f
  602.         mov     [ebx+BGDESCR.blocksFree], 0
  603. @@:
  604.         sub     [ebp+EXTFS.superblock.blocksFree], ecx
  605.         call    extfsWriteDescriptor
  606.         pop     eax ebx
  607.         sub     eax, [ebp+EXTFS.descriptorTable]
  608.         shr     eax, 5
  609.         mul     [ebp+EXTFS.superblock.blocksPerGroup]
  610.         mov     ebx, eax
  611.         add     ebx, esi
  612.         add     ebx, [ebp+EXTFS.superblock.firstGroupBlock]
  613.         pop     ecx
  614.         mov     eax, ecx
  615.         mul     [ebp+EXTFS.sectorsPerBlock]
  616.         add     [ebp+EXTFS.inodeBuffer.sectorsUsed], eax
  617.         xor     eax, eax
  618. .ret:
  619.         pop     edi esi edx
  620.         ret
  621.  
  622. .next:      ; search forward, then backward
  623.         pop     ebx
  624.         cmp     ebx, [esp]
  625.         jc      .backward
  626.         add     ebx, 32
  627.         cmp     ebx, [ebp+EXTFS.descriptorTableEnd]
  628.         jc      .test_block_group
  629.         mov     ebx, [esp]
  630. .backward:
  631.         sub     ebx, 32
  632.         cmp     ebx, [ebp+EXTFS.descriptorTable]
  633.         jnc     .test_block_group
  634.         movi    eax, ERROR_DISK_FULL
  635.         push    eax
  636. .fail:
  637.         add     esp, 12
  638.         xor     ecx, ecx
  639.         stc
  640.         jmp     .ret
  641.  
  642. extfsGetExtent:
  643. ; in: ecx = starting file block
  644. ; out: eax = first block number, ecx = extent size
  645.         push    ebx edx esi
  646.         lea     esi, [ebp+EXTFS.inodeBuffer]
  647.         test    [esi+INODE.featureFlags], EXTENTS_USED
  648.         jz      .listTreeSearch
  649.         add     esi, INODE.blockNumbers
  650. .extentTreeSearch:
  651.         cmp     word [esi+NODEHEADER.magic], 0xF30A
  652.         jne     .fail
  653.         movzx   ebx, [esi+NODEHEADER.entriesFolow]
  654.         add     esi, sizeof.NODEHEADER
  655.         test    ebx, ebx
  656.         jz      .noBlock
  657.         cmp     word [esi-sizeof.NODEHEADER+NODEHEADER.currentDepth], 0
  658.         je      .leaf_block
  659.         dec     ebx
  660.         jz      .end_search_index
  661. @@:
  662.         cmp     ecx, [esi+sizeof.INDEX+INDEX.fileBlock]
  663.         jb      .end_search_index
  664.         add     esi, sizeof.INDEX
  665.         dec     ebx
  666.         jnz     @b
  667. .end_search_index:
  668.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  669.         mov     eax, [esi+INDEX.nodeBlock]
  670.         call    extfsReadBlock
  671.         jc      .fail2
  672.         mov     esi, ebx
  673.         jmp     .extentTreeSearch
  674.  
  675. .fail:
  676.         movi    eax, ERROR_FS_FAIL
  677.         jmp     .fail2
  678.  
  679. .leaf_block:
  680.         movzx   edx, [esi+EXTENT.blocksCount]
  681.         add     edx, [esi+EXTENT.fileBlock]
  682.         sub     edx, ecx
  683.         ja      .end_search_extent
  684.         add     esi, sizeof.EXTENT
  685.         dec     ebx
  686.         jnz     .leaf_block
  687. .noBlock:
  688.         movi    eax, ERROR_END_OF_FILE
  689. .fail2:
  690.         pop     esi edx ebx
  691.         stc
  692.         ret
  693.  
  694. .end_search_extent:
  695.         sub     ecx, [esi+EXTENT.fileBlock]
  696.         jc      .fail
  697.         add     ecx, [esi+EXTENT.fsBlock]
  698.         mov     eax, ecx
  699.         mov     ecx, edx
  700.         pop     esi edx ebx
  701.         ret
  702.  
  703. .listTreeSearch:
  704.         cmp     ecx, 12
  705.         jb      .get_direct_block
  706.         sub     ecx, 12
  707.         cmp     ecx, [ebp+EXTFS.dwordsPerBlock]
  708.         jb      .get_indirect_block
  709.         sub     ecx, [ebp+EXTFS.dwordsPerBlock]
  710.         cmp     ecx, [ebp+EXTFS.dwordsPerBranch]
  711.         jb      .get_double_indirect_block
  712. ; triply-indirect blocks
  713.         sub     ecx, [ebp+EXTFS.dwordsPerBranch]
  714.         mov     eax, [esi+INODE.tripleAddress]
  715.         test    eax, eax
  716.         jz      .noBlock
  717.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  718.         call    extfsReadBlock
  719.         jc      .fail2
  720.         xor     edx, edx
  721.         mov     eax, ecx
  722.         div     [ebp+EXTFS.dwordsPerBranch]
  723. ; eax = number in triply-indirect block, edx = number in branch
  724.         mov     eax, [ebx+eax*4]
  725.         test    eax, eax
  726.         jz      .noBlock
  727.         call    extfsReadBlock
  728.         jc      .fail2
  729.         mov     eax, edx
  730.         jmp     @f
  731.  
  732. .get_direct_block:
  733.         mov     edx, ecx
  734.         mov     cl, 12
  735.         lea     ebx, [esi+INODE.blockNumbers]
  736.         jmp     .calculateExtent
  737.  
  738. .get_indirect_block:
  739.         mov     eax, [esi+INODE.addressBlock]
  740.         test    eax, eax
  741.         jz      .noBlock
  742.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  743.         call    extfsReadBlock
  744.         jc      .fail2
  745.         mov     edx, ecx
  746.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  747.         jmp     .calculateExtent
  748.  
  749. .get_double_indirect_block:
  750.         mov     eax, [esi+INODE.doubleAddress]
  751.         test    eax, eax
  752.         jz      .noBlock
  753.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  754.         call    extfsReadBlock
  755.         jc      .fail2
  756.         mov     eax, ecx
  757. @@:
  758.         xor     edx, edx
  759.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  760.         div     ecx
  761. ; eax = number in doubly-indirect block, edx = number in indirect block
  762.         mov     eax, [ebx+eax*4]
  763.         test    eax, eax
  764.         jz      .noBlock
  765.         call    extfsReadBlock
  766.         jc      .fail2
  767. .calculateExtent:
  768.         lea     esi, [ebx+edx*4]
  769.         lodsd
  770.         test    eax, eax
  771.         jz      .noBlock
  772.         mov     ebx, eax
  773.         sub     ecx, edx
  774.         xor     edx, edx
  775. @@:
  776.         inc     edx
  777.         dec     ecx
  778.         jz      @f
  779.         lodsd
  780.         sub     eax, ebx
  781.         sub     eax, edx
  782.         jz      @b
  783. @@:
  784.         mov     eax, ebx
  785.         mov     ecx, edx
  786.         pop     esi edx ebx
  787.         clc
  788.         ret
  789.  
  790. getInodeLocation:
  791. ; in: eax = inode number
  792. ; out: eax = inode sector, edx = offset in sector
  793.         dec     eax
  794.         xor     edx, edx
  795.         div     [ebp+EXTFS.superblock.inodesPerGroup]
  796.         shl     eax, 5
  797.         add     eax, [ebp+EXTFS.descriptorTable]
  798.         mov     ebx, [eax+BGDESCR.inodeTable]
  799.         imul    ebx, [ebp+EXTFS.sectorsPerBlock]
  800.         movzx   eax, [ebp+EXTFS.superblock.inodeSize]
  801.         mul     edx
  802.         mov     edx, eax
  803.         shr     eax, 9
  804.         and     edx, 511
  805.         add     eax, ebx
  806.         ret
  807.  
  808. writeInode:
  809. ; in: eax = inode number, ebx -> inode data
  810.         push    edx edi esi ecx ebx eax
  811.         mov     edi, ebx
  812.         call    fsGetTime
  813.         add     eax, 978307200
  814.         mov     [edi+INODE.inodeModified], eax
  815.         pop     eax
  816.         cmp     eax, ROOT_INODE
  817.         jnz     @f
  818.         movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
  819.         mov     esi, edi
  820.         lea     edi, [ebp+EXTFS.rootInodeBuffer]
  821.         rep movsb
  822. @@:
  823.         call    getInodeLocation
  824.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  825.         mov     ecx, eax
  826.         call    fs_read32_sys
  827.         test    eax, eax
  828.         jnz     @f
  829.         mov     eax, ecx
  830.         movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
  831.         mov     edi, edx
  832.         add     edi, ebx
  833.         mov     esi, [esp]
  834.         rep movsb
  835.         call    fs_write32_sys
  836. .ret:
  837.         pop     ebx ecx esi edi edx
  838.         ret
  839.  
  840. @@:
  841.         movi    eax, ERROR_DEVICE
  842.         stc
  843.         jmp     .ret
  844.  
  845. readInode:
  846. ; in: eax = inode number, ebx -> inode buffer
  847.         push    edx edi esi ecx ebx
  848.         mov     edi, ebx
  849.         call    getInodeLocation
  850.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  851.         call    fs_read32_sys
  852.         test    eax, eax
  853.         jnz     @b
  854.         movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
  855.         mov     esi, edx
  856.         add     esi, ebx
  857.         rep movsb
  858.         xor     eax, eax
  859.         pop     ebx ecx esi edi edx
  860.         ret
  861.  
  862. indirectBlockAlloc:
  863. ;   in:
  864. ; edi -> indirect block number
  865. ; ebx = starting extent block
  866. ; ecx = extent size
  867. ; edx = starting file block
  868.         mov     eax, [edi]
  869.         test    eax, eax
  870.         jz      .newBlock
  871.         push    edi ebx ecx
  872.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  873.         call    extfsReadBlock
  874.         jc      .err2
  875.         lea     edi, [ebx+edx*4]
  876.         test    edx, edx
  877.         jz      @f
  878.         cmp     dword[edi-4], 0
  879.         jnz     @f
  880.         pop     ecx ebx edi
  881. .err:
  882.         mov     al, ERROR_FS_FAIL
  883.         stc
  884.         ret
  885.  
  886. .err2:
  887.         pop     ecx ebx edi
  888.         ret
  889.  
  890. .newBlock:
  891.         test    edx, edx
  892.         jnz     .err
  893.         mov     [edi], ebx
  894.         inc     ebx
  895.         dec     ecx
  896.         push    edi ebx ecx
  897.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  898.         mov     edi, [ebp+EXTFS.tempBlockBuffer]
  899.         push    edi
  900.         rep stosd
  901.         pop     edi
  902. @@:
  903.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  904.         sub     ecx, edx
  905.         pop     ebx eax
  906.         sub     ebx, ecx
  907.         jnc     @f
  908.         add     ecx, ebx
  909.         xor     ebx, ebx
  910. @@:
  911.         jecxz   .done
  912.         add     edx, ecx
  913. @@:
  914.         stosd
  915.         inc     eax
  916.         loop    @b
  917. .done:
  918.         pop     edi
  919.         push    eax ebx
  920.         mov     eax, [edi]
  921.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  922.         call    extfsWriteBlock
  923.         pop     ecx ebx
  924.         ret
  925.  
  926. doublyIndirectBlockAlloc:
  927. ;   in:
  928. ; edi -> indirect block number
  929. ; edx = starting file block
  930. ; ebx = starting extent block
  931. ; ecx = extent size
  932. ; [esp+4] = rest of size
  933. ; [esp+8] = parent inode number
  934.         mov     eax, [edi]
  935.         test    eax, eax
  936.         jz      .newBlock
  937.         push    edi ecx ebx
  938.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  939.         call    extfsReadBlock
  940.         jc      .err2
  941.         mov     eax, edx
  942.         xor     edx, edx
  943.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  944.         div     ecx
  945.         lea     edi, [ebx+eax*4]
  946.         pop     ebx
  947.         test    eax, eax
  948.         jz      @f
  949.         cmp     dword[edi-4], 0
  950.         jnz     @f
  951.         pop     ecx edi
  952. .err:
  953.         mov     al, ERROR_FS_FAIL
  954.         stc
  955.         ret
  956.  
  957. .err2:
  958.         pop     ebx ecx edi
  959.         ret
  960.  
  961. .newBlock:
  962.         test    edx, edx
  963.         jnz     .err
  964.         mov     [edi], ebx
  965.         inc     ebx
  966.         dec     ecx
  967.         inc     dword[esp+4]
  968.         push    edi ecx
  969.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  970.         mov     edi, [ebp+EXTFS.mainBlockBuffer]
  971.         push    ecx edi
  972.         rep stosd
  973.         pop     edi ecx
  974. @@:
  975.         sub     ecx, eax
  976.         xchg    [esp], ecx
  977. .loop:
  978.         cmp     dword[edi], 0
  979.         jnz     @f
  980.         inc     dword[esp+12]
  981. @@:
  982.         jecxz   .extentAlloc
  983.         call    indirectBlockAlloc
  984.         jc      .end
  985.         cmp     edx, [ebp+EXTFS.dwordsPerBlock]
  986.         jnz     @b
  987.         add     edi, 4
  988.         xor     edx, edx
  989.         dec     dword[esp]
  990.         jnz     .loop
  991. .end:
  992.         pop     edi edi
  993.         push    ebx eax
  994.         mov     eax, [edi]
  995.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  996.         call    extfsWriteBlock
  997.         pop     ebx
  998.         add     eax, ebx
  999.         xor     ebx, ebx
  1000.         cmp     ebx, eax
  1001.         pop     ebx
  1002.         ret
  1003.  
  1004. .extentAlloc:
  1005.         mov     ecx, [esp+12]
  1006.         xor     eax, eax
  1007.         jecxz   .end
  1008.         mov     eax, [esp+16]
  1009.         call    extfsExtentAlloc
  1010.         jc      .end
  1011.         sub     [esp+12], ecx
  1012.         jmp     @b
  1013.  
  1014. extfsExtendFile:
  1015. ;   in:
  1016. ; [ebp+EXTFS.inodeBuffer] = inode
  1017. ; ecx = inode number
  1018. ; edx:eax = new size
  1019.         push    ebx esi edi ecx
  1020.         lea     esi, [ebp+EXTFS.inodeBuffer]
  1021.         mov     ebx, [esi+INODE.fileSize]
  1022.         mov     ecx, [esi+INODE.fileSizeHigh]
  1023.         cmp     ebx, eax
  1024.         sbb     ecx, edx
  1025.         jnc     .ret
  1026.         mov     ecx, [esi+INODE.fileSizeHigh]
  1027.         mov     [esi+INODE.fileSize], eax
  1028.         mov     [esi+INODE.fileSizeHigh], edx
  1029.         sub     eax, 1
  1030.         sbb     edx, 0
  1031.         div     [ebp+EXTFS.bytesPerBlock]
  1032.         inc     eax
  1033.         xchg    eax, ebx
  1034.         mov     edx, ecx
  1035.         sub     eax, 1
  1036.         sbb     edx, 0
  1037.         jc      @f
  1038.         div     [ebp+EXTFS.bytesPerBlock]
  1039. @@:
  1040.         inc     eax
  1041.         sub     ebx, eax
  1042.         jz      .ret
  1043.         push    ebx
  1044.         mov     edx, eax
  1045. @@:
  1046.         mov     ecx, [esp]
  1047.         mov     eax, [esp+4]
  1048.         test    ecx, ecx
  1049.         jz      .done
  1050.         call    extfsExtentAlloc
  1051.         jc      .errDone
  1052.         sub     [esp], ecx
  1053.         cmp     edx, 12
  1054.         jc      .directBlocks
  1055.         sub     edx, 12
  1056.         cmp     edx, [ebp+EXTFS.dwordsPerBlock]
  1057.         jc      .indirectBlocks
  1058.         sub     edx, [ebp+EXTFS.dwordsPerBlock]
  1059.         cmp     edx, [ebp+EXTFS.dwordsPerBranch]
  1060.         jc      .doublyIndirectBlock
  1061.         sub     edx, [ebp+EXTFS.dwordsPerBranch]
  1062.         jmp     .triplyIndirectBlock
  1063.  
  1064. .newExtent:
  1065.         jmp     @b
  1066.  
  1067. .directBlocks:
  1068.         lea     edi, [esi+INODE.blockNumbers+edx*4]
  1069.         test    edx, edx
  1070.         jz      @f
  1071.         cmp     dword[edi-4], 0
  1072.         jz      .errDone
  1073. @@:
  1074.         mov     eax, ebx
  1075.         mov     ebx, ecx
  1076.         mov     ecx, 12
  1077.         sub     ecx, edx
  1078.         sub     ebx, ecx
  1079.         jnc     @f
  1080.         add     ecx, ebx
  1081.         xor     ebx, ebx
  1082. @@:
  1083.         add     edx, ecx
  1084. @@:
  1085.         stosd
  1086.         inc     eax
  1087.         loop    @b
  1088.         mov     ecx, ebx
  1089.         mov     ebx, eax
  1090.         jecxz   .newExtent
  1091.         xor     edx, edx
  1092. .indirectBlocks:
  1093.         lea     edi, [esi+INODE.addressBlock]
  1094.         cmp     dword[edi], 0
  1095.         jnz     @f
  1096.         inc     dword[esp]
  1097. @@:
  1098.         call    indirectBlockAlloc
  1099.         jc      .errDone
  1100.         add     edx, 12
  1101.         jecxz   .newExtent
  1102.         xor     edx, edx
  1103. .doublyIndirectBlock:
  1104.         lea     edi, [esi+INODE.doubleAddress]
  1105.         call    doublyIndirectBlockAlloc
  1106.         jc      .errDone
  1107.         mov     edx, [ebp+EXTFS.dwordsPerBranch]
  1108.         add     edx, [ebp+EXTFS.dwordsPerBlock]
  1109.         add     edx, 12
  1110.         jecxz   .newExtent
  1111.         xor     edx, edx
  1112. .triplyIndirectBlock:
  1113.         push    ecx ebx edx
  1114.         stdcall kernel_alloc, [ebp+EXTFS.bytesPerBlock]
  1115.         pop     edx
  1116.         mov     esi, eax
  1117.         mov     eax, [ebp+EXTFS.inodeBuffer.tripleAddress]
  1118.         test    eax, eax
  1119.         jz      .newBlock
  1120.         mov     ebx, esi
  1121.         call    extfsReadBlock
  1122.         pop     ebx ecx
  1123.         jc      .errFree
  1124.         mov     eax, edx
  1125.         xor     edx, edx
  1126.         div     [ebp+EXTFS.dwordsPerBranch]
  1127.         lea     edi, [esi+eax*4]
  1128.         test    eax, eax
  1129.         jz      @f
  1130.         cmp     dword[edi-4], 0
  1131.         jnz     @f
  1132.         mov     al, ERROR_FS_FAIL
  1133. .errFree:
  1134.         push    ecx eax
  1135.         stdcall kernel_free, esi
  1136.         pop     eax ecx
  1137. .errDone:
  1138.         imul    ecx, [ebp+EXTFS.sectorsPerBlock]
  1139.         sub     [ebp+EXTFS.inodeBuffer.sectorsUsed], ecx
  1140.         pop     ebx
  1141.         imul    ebx, [ebp+EXTFS.sectorsPerBlock]
  1142.         add     ebx, ecx
  1143.         shl     ebx, 9
  1144.         sub     [ebp+EXTFS.inodeBuffer.fileSize], ebx
  1145.         stc
  1146.         jmp     .ret
  1147.  
  1148. .newBlock:
  1149.         pop     ebx ecx
  1150.         mov     al, ERROR_FS_FAIL
  1151.         test    edx, edx
  1152.         jnz     .errFree
  1153.         mov     [ebp+EXTFS.inodeBuffer.tripleAddress], ebx
  1154.         inc     ebx
  1155.         dec     ecx
  1156.         inc     dword[esp]
  1157.         push    ecx
  1158.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  1159.         mov     edi, esi
  1160.         xor     eax, eax
  1161.         rep stosd
  1162.         mov     edi, esi
  1163.         pop     ecx
  1164. @@:
  1165.         jecxz   .extentAlloc
  1166.         call    doublyIndirectBlockAlloc
  1167.         jc      .errSave
  1168.         add     edi, 4
  1169.         jmp     @b
  1170.  
  1171. .extentAlloc:
  1172.         mov     ecx, [esp]
  1173.         mov     eax, [esp+4]
  1174.         jecxz   @f
  1175.         call    extfsExtentAlloc
  1176.         jc      .errSave
  1177.         sub     [esp], ecx
  1178.         jmp     @b
  1179.  
  1180. @@:
  1181.         mov     eax, [ebp+EXTFS.inodeBuffer.tripleAddress]
  1182.         mov     ebx, esi
  1183.         call    extfsWriteBlock
  1184.         stdcall kernel_free, esi
  1185. .done:
  1186.         xor     eax, eax
  1187.         pop     edi
  1188. .ret:
  1189.         pop     edi edi esi ebx
  1190.         ret
  1191.  
  1192. .errSave:
  1193.         push    eax
  1194.         mov     eax, [ebp+EXTFS.inodeBuffer.tripleAddress]
  1195.         mov     ebx, esi
  1196.         call    extfsWriteBlock
  1197.         pop     eax
  1198.         jmp     .errFree
  1199.  
  1200. freeBlockList:
  1201. ; in: edi -> list of blocks, edx = amount of blocks
  1202. ; out: ebx=0 -> end of list
  1203.         mov     ebx, [edi]
  1204.         test    ebx, ebx
  1205.         jz      .ret
  1206.         xor     eax, eax
  1207.         xor     ecx, ecx
  1208. @@:
  1209.         stosd
  1210.         inc     ecx
  1211.         dec     edx
  1212.         jz      @f
  1213.         mov     eax, [edi]
  1214.         sub     eax, ebx
  1215.         sub     eax, ecx
  1216.         jz      @b
  1217. @@:
  1218.         mov     eax, ebx
  1219.         call    extfsExtentFree
  1220.         test    edx, edx
  1221.         jnz     freeBlockList
  1222. .ret:
  1223.         ret
  1224.  
  1225. freeIndirectBlock:
  1226. ; in: edi -> indirect block number, edx = starting block
  1227. ; out: edi = edi+4, eax=0 -> end
  1228.         pushd   ecx 0 edi edx
  1229.         mov     eax, [edi]
  1230.         test    eax, eax
  1231.         jz      .ret
  1232.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  1233.         call    extfsReadBlock
  1234.         jc      .ret
  1235.         lea     edi, [ebx+edx*4]
  1236.         neg     edx
  1237.         add     edx, [ebp+EXTFS.dwordsPerBlock]
  1238.         call    freeBlockList
  1239.         test    ebx, ebx
  1240.         jz      @f
  1241.         inc     dword[esp+8]
  1242. @@:
  1243.         pop     edx edi
  1244.         mov     eax, [edi]
  1245.         test    edx, edx
  1246.         jnz     @f
  1247.         xor     ecx, ecx
  1248.         inc     ecx
  1249.         call    extfsExtentFree
  1250.         stosd
  1251.         jmp     .done
  1252.  
  1253. @@:
  1254.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  1255.         call    extfsWriteBlock
  1256.         add     edi, 4
  1257. .done:
  1258.         pop     eax ecx
  1259.         xor     edx, edx
  1260.         ret
  1261.  
  1262. .ret:
  1263.         pop     edi edi edx ecx
  1264.         ret
  1265.  
  1266. freeDoublyIndirectBlock:
  1267. ; in: edi -> doubly-indirect block number, edx = starting block
  1268. ; out: edi = edi+4, eax=-1 -> done, eax=0 -> end
  1269.         mov     eax, [edi]
  1270.         test    eax, eax
  1271.         jz      .ret
  1272.         push    ecx eax edx
  1273.         stdcall kernel_alloc, [ebp+EXTFS.bytesPerBlock]
  1274.         mov     ebx, eax
  1275.         pop     edx eax
  1276.         pushd   0 ebx edx
  1277.         call    extfsReadBlock
  1278.         jc      .err
  1279.         mov     eax, edx
  1280.         xor     edx, edx
  1281.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  1282.         div     ecx
  1283.         sub     ecx, eax
  1284.         push    edi
  1285.         lea     edi, [ebx+eax*4]
  1286. @@:
  1287.         call    freeIndirectBlock
  1288.         test    eax, eax
  1289.         jz      .end
  1290.         dec     ecx
  1291.         jnz     @b
  1292.         dec     dword[esp+12]
  1293. .end:
  1294.         pop     edi edx
  1295.         mov     eax, [edi]
  1296.         test    edx, edx
  1297.         jnz     @f
  1298.         xor     ecx, ecx
  1299.         inc     ecx
  1300.         call    extfsExtentFree
  1301.         stosd
  1302.         jmp     .done
  1303.  
  1304. @@:
  1305.         mov     ebx, [esp]
  1306.         call    extfsWriteBlock
  1307.         add     edi, 4
  1308.         jmp     .done
  1309.  
  1310. .err:
  1311.         mov     [esp+8], eax
  1312.         pop     eax
  1313. .done:
  1314.         call    kernel_free
  1315.         pop     eax ecx
  1316. .ret:
  1317.         xor     edx, edx
  1318.         ret
  1319.  
  1320. extfsTruncateFile:
  1321. ; in: edx:eax = new size, [ebp+EXTFS.inodeBuffer] = inode
  1322.         lea     esi, [ebp+EXTFS.inodeBuffer]
  1323.         mov     ecx, edx
  1324.         cmp     eax, [esi+INODE.fileSize]
  1325.         sbb     ecx, [esi+INODE.fileSizeHigh]
  1326.         jnc     .ret
  1327.         mov     [esi+INODE.fileSize], eax
  1328.         mov     [esi+INODE.fileSizeHigh], edx
  1329.         sub     eax, 1
  1330.         sbb     edx, 0
  1331.         jc      @f
  1332.         div     [ebp+EXTFS.bytesPerBlock]
  1333. @@:
  1334.         inc     eax
  1335.         mov     edx, eax
  1336.         cmp     edx, 12
  1337.         jc      .directBlocks
  1338.         sub     edx, 12
  1339.         cmp     edx, [ebp+EXTFS.dwordsPerBlock]
  1340.         jc      .indirectBlocks
  1341.         sub     edx, [ebp+EXTFS.dwordsPerBlock]
  1342.         cmp     edx, [ebp+EXTFS.dwordsPerBranch]
  1343.         jc      .doublyIndirectBlock
  1344.         sub     edx, [ebp+EXTFS.dwordsPerBranch]
  1345.         jmp     .triplyIndirectBlock
  1346.  
  1347. .directBlocks:
  1348.         lea     edi, [esi+INODE.blockNumbers+edx*4]
  1349.         neg     edx
  1350.         add     edx, 12
  1351.         call    freeBlockList
  1352.         test    ebx, ebx
  1353.         jz      .ret
  1354. .indirectBlocks:
  1355.         lea     edi, [esi+INODE.addressBlock]
  1356.         call    freeIndirectBlock
  1357.         test    eax, eax
  1358.         jz      .ret
  1359. .doublyIndirectBlock:
  1360.         lea     edi, [esi+INODE.doubleAddress]
  1361.         call    freeDoublyIndirectBlock
  1362.         test    eax, eax
  1363.         jz      .ret
  1364. .triplyIndirectBlock:
  1365.         mov     eax, [esi+INODE.tripleAddress]
  1366.         test    eax, eax
  1367.         jz      .ret
  1368.         push    eax edx
  1369.         stdcall kernel_alloc, [ebp+EXTFS.bytesPerBlock]
  1370.         mov     ebx, eax
  1371.         pop     edx eax
  1372.         push    ebx eax edx
  1373.         call    extfsReadBlock
  1374.         jc      .err
  1375.         mov     eax, edx
  1376.         xor     edx, edx
  1377.         div     [ebp+EXTFS.dwordsPerBranch]
  1378.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  1379.         sub     ecx, eax
  1380.         lea     edi, [ebx+eax*4]
  1381. @@:
  1382.         call    freeDoublyIndirectBlock
  1383.         test    eax, eax
  1384.         jz      .end
  1385.         dec     ecx
  1386.         jnz     @b
  1387. .end:
  1388.         pop     edx eax
  1389.         test    edx, edx
  1390.         jnz     @f
  1391.         xor     ecx, ecx
  1392.         inc     ecx
  1393.         call    extfsExtentFree
  1394.         mov     [esi+INODE.tripleAddress], eax
  1395.         jmp     .done
  1396.  
  1397. @@:
  1398.         mov     ebx, [esp]
  1399.         call    extfsWriteBlock
  1400.         jmp     .done
  1401.  
  1402. .err:
  1403.         pop     eax eax
  1404. .done:
  1405.         call    kernel_free
  1406. .ret:
  1407.         ret
  1408.  
  1409. linkInode:
  1410. ;   in:
  1411. ; eax = inode on which to link
  1412. ; ebx = inode to link
  1413. ; esi -> name in UTF-8
  1414. ;  dl = file type
  1415.         push    esi edi ebx ecx eax edx
  1416.         call    strlen
  1417.         push    esi ebx ecx
  1418.         lea     esi, [ebp+EXTFS.inodeBuffer]
  1419.         mov     ebx, esi
  1420.         call    readInode
  1421.         jc      .error_inode_read
  1422.         mov     eax, [esi+INODE.fileSize]
  1423.         xor     edx, edx
  1424.         div     [ebp+EXTFS.bytesPerBlock]
  1425.         xor     ecx, ecx
  1426. .searchBlock:
  1427.         push    eax     ; blocks total
  1428.         push    ecx     ; current file block number
  1429.         cmp     eax, ecx
  1430.         jz      .alloc_block
  1431.         call    extfsGetExtent
  1432.         jc      .error_get_inode_block
  1433.         push    eax
  1434.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  1435.         call    extfsReadBlock
  1436.         jc      .error_block_read
  1437.         mov     ecx, [esp+12]
  1438.         add     ecx, 8  ; directory entry size
  1439.         mov     edi, [ebp+EXTFS.tempBlockBuffer]
  1440.         mov     edx, edi
  1441.         add     edx, [ebp+EXTFS.bytesPerBlock]
  1442. .searchSpace:
  1443.         movzx   eax, [edi+DIRENTRY.entryLength]
  1444.         test    eax, eax
  1445.         jz      .zeroLength
  1446.         cmp     [edi+DIRENTRY.inodeNumber], 0
  1447.         je      .unusedEntry
  1448.         movzx   ebx, [edi+DIRENTRY.nameLength]
  1449.         add     ebx, 8+3
  1450.         and     ebx, -4
  1451.         sub     eax, ebx
  1452.         add     edi, ebx
  1453.         cmp     eax, ecx
  1454.         jb      .nextEntry
  1455.         sub     edi, ebx
  1456.         mov     [edi+DIRENTRY.entryLength], bx
  1457.         add     edi, ebx
  1458.         mov     [edi+DIRENTRY.entryLength], ax
  1459.         jmp     .found
  1460.  
  1461. .unusedEntry:
  1462.         cmp     eax, ecx
  1463.         jge     .found
  1464. .nextEntry:
  1465.         add     edi, eax
  1466.         cmp     edi, edx
  1467.         jb      .searchSpace
  1468.         pop     ecx
  1469. @@:
  1470.         pop     ecx eax
  1471.         inc     ecx
  1472.         jmp     .searchBlock
  1473.  
  1474. .zeroLength:
  1475.         mov     eax, edx
  1476.         sub     eax, edi
  1477.         mov     [edi+DIRENTRY.entryLength], ax
  1478.         cmp     eax, ecx
  1479.         jge     .found
  1480.         mov     [edi+DIRENTRY.inodeNumber], 0
  1481.         pop     eax
  1482.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  1483.         call    extfsWriteBlock
  1484.         jmp     @b
  1485.  
  1486. .alloc_block:
  1487.         mov     eax, [esi+INODE.fileSize]
  1488.         add     eax, [ebp+EXTFS.bytesPerBlock]
  1489.         xor     edx, edx
  1490.         mov     ecx, [esp+24]
  1491.         call    extfsExtendFile
  1492.         jc      .error_get_inode_block
  1493.         mov     eax, [esp+24]
  1494.         mov     ebx, esi
  1495.         call    writeInode
  1496.         jc      .error_get_inode_block
  1497.         mov     ecx, [esp]
  1498.         call    extfsGetExtent
  1499.         jc      .error_get_inode_block
  1500.         push    eax
  1501.         mov     edi, [ebp+EXTFS.tempBlockBuffer]
  1502.         mov     eax, [ebp+EXTFS.bytesPerBlock]
  1503.         mov     [edi+DIRENTRY.entryLength], ax
  1504. .found:
  1505.         pop     edx ecx ecx ecx ebx esi
  1506.         mov     [edi+DIRENTRY.inodeNumber], ebx
  1507.         mov     word [edi+DIRENTRY.nameLength], cx
  1508.         sub     eax, 8
  1509.         cmp     ecx, eax
  1510.         adc     ecx, 0
  1511.         test    [ebp+EXTFS.superblock.incompatibleFlags], 2
  1512.         jz      @f
  1513.         mov     eax, [esp]
  1514.         mov     [edi+DIRENTRY.fileType], al
  1515. @@:
  1516.         push    ebx
  1517.         add     edi, 8
  1518.         rep movsb
  1519.         mov     eax, edx
  1520.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  1521.         call    extfsWriteBlock
  1522.         mov     eax, [esp]
  1523.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  1524.         call    readInode
  1525.         jc      .error_block_write
  1526.         pop     eax
  1527.         inc     [ebx+INODE.linksCount]
  1528.         call    writeInode
  1529.         jc      @f
  1530.         xor     eax, eax
  1531. @@:
  1532.         pop     edx ecx ecx ebx edi esi
  1533.         ret
  1534.  
  1535. .error_block_read:
  1536.         pop     ebx
  1537. .error_get_inode_block:
  1538.         pop     ebx ebx
  1539. .error_inode_read:
  1540.         pop     ebx ebx
  1541. .error_block_write:
  1542.         pop     ebx
  1543.         jmp     @b
  1544.  
  1545. unlinkInode:
  1546. ; in: eax = directory inode number, esi = inode to unlink
  1547.         push    edi
  1548.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  1549.         call    readInode
  1550.         jc      .ret
  1551.         xor     ecx, ecx
  1552. .loop:
  1553.         push    ecx
  1554.         call    extfsGetExtent
  1555.         jc      .fail_loop
  1556.         mov     edi, eax
  1557.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  1558.         call    extfsReadBlock
  1559.         jc      .fail_loop
  1560. .first_dir_entry:   ; edi -> block
  1561.         cmp     [ebx+DIRENTRY.inodeNumber], esi
  1562.         jne     @f
  1563.         mov     [ebx+DIRENTRY.inodeNumber], 0
  1564.         mov     word [ebx+DIRENTRY.nameLength], 0   ; fileType = 0
  1565.         jmp     .write_block
  1566.  
  1567. .fail:
  1568.         pop     edi
  1569.         movi    eax, ERROR_FS_FAIL
  1570.         stc
  1571. .fail_loop:
  1572.         pop     edi
  1573.         jmp     .ret
  1574.  
  1575. .next:
  1576.         pop     ecx ecx
  1577.         inc     ecx
  1578.         jmp     .loop
  1579.  
  1580. @@:
  1581.         mov     edx, ebx
  1582.         add     edx, [ebp+EXTFS.bytesPerBlock]
  1583.         push    edx
  1584. @@:
  1585.         movzx   ecx, [ebx+DIRENTRY.entryLength]
  1586.         jecxz   .fail
  1587.         mov     edx, ebx
  1588.         add     ebx, ecx
  1589.         cmp     ebx, [esp]
  1590.         jnc     .next
  1591.         cmp     [ebx+DIRENTRY.inodeNumber], esi
  1592.         jnz     @b
  1593.         mov     cx, [ebx+DIRENTRY.entryLength]
  1594.         add     [edx+DIRENTRY.entryLength], cx
  1595.         pop     eax
  1596. .write_block:
  1597.         pop     eax
  1598.         mov     eax, edi
  1599.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  1600.         call    extfsWriteBlock
  1601. .ret:
  1602.         pop     edi
  1603.         ret
  1604.  
  1605. findInode:
  1606. ; in: esi -> path string in UTF-8
  1607. ;   out:
  1608. ; edi -> file name in UTF-8
  1609. ; esi = last inode number
  1610. ; [ebp+EXTFS.inodeBuffer] = last inode
  1611. ; ecx = parent inode number
  1612. ; CF=1 -> file not found, edi=0 -> error
  1613.         push    esi
  1614.         lea     esi, [ebp+EXTFS.rootInodeBuffer]
  1615.         lea     edi, [ebp+EXTFS.inodeBuffer]
  1616.         movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
  1617.         mov     edx, esi
  1618.         rep movsb
  1619.         pop     esi
  1620.         pushd   ebx 0 ROOT_INODE
  1621.         mov     edi, esi
  1622.         cmp     [edx+INODE.fileSize], 0
  1623.         jz      .not_found
  1624.         cmp     byte [esi], 0
  1625.         jnz     .next_path_part
  1626.         xor     eax, eax
  1627.         pop     esi ecx ebx
  1628.         ret
  1629.  
  1630. @@:
  1631.         pop     esi esi
  1632. .error:
  1633.         pop     esi ecx ebx
  1634.         xor     edi, edi
  1635.         stc
  1636.         ret
  1637.  
  1638. .next_path_part:
  1639.         push    [edx+INODE.fileSize]
  1640.         xor     ecx, ecx
  1641. .folder_block_cycle:
  1642.         push    ecx
  1643.         call    extfsGetExtent
  1644.         jc      @b
  1645.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  1646.         call    extfsReadBlock
  1647.         jc      @b
  1648.         push    esi edx
  1649.         mov     edx, ebx
  1650.         add     edx, [ebp+EXTFS.bytesPerBlock]
  1651. .start_rec:
  1652.         cmp     [ebx+DIRENTRY.inodeNumber], 0
  1653.         jz      .next_rec
  1654.         push    esi
  1655.         movzx   ecx, [ebx+DIRENTRY.nameLength]
  1656.         lea     edi, [ebx+DIRENTRY.name]
  1657.         repz cmpsb
  1658.         jz      .test_find
  1659. @@: ; doesn't match
  1660.         pop     esi
  1661. .next_rec:
  1662.         movzx   ecx, [ebx+DIRENTRY.entryLength]
  1663.         jecxz   .stop
  1664.         add     ebx, ecx
  1665.         cmp     ebx, edx
  1666.         jb      .start_rec
  1667.         jmp     .stop
  1668.  
  1669. .test_find:
  1670.         cmp     byte [esi], 0
  1671.         je      @f
  1672.         cmp     byte [esi], '/'
  1673.         jne     @b
  1674.         inc     esi
  1675. @@:
  1676.         pop     edx
  1677. .stop:
  1678.         pop     edx edi ecx eax
  1679. ; ebx -> matched directory entry, esi -> name without parent, or not changed
  1680.         cmp     edi, esi
  1681.         jnz     @f
  1682.         sub     eax, [ebp+EXTFS.bytesPerBlock]
  1683.         jle     .not_found
  1684.         push    eax
  1685.         inc     ecx
  1686.         jmp     .folder_block_cycle
  1687.  
  1688. @@:
  1689.         pop     eax
  1690.         mov     [esp], eax
  1691.         mov     eax, [ebx+DIRENTRY.inodeNumber]
  1692.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  1693.         push    eax
  1694.         call    readInode
  1695.         jc      .error
  1696.         cmp     byte [esi], 0
  1697.         je      .ret
  1698.         mov     edx, ebx
  1699.         movzx   eax, [ebx+INODE.accessMode]
  1700.         and     eax, TYPE_MASK
  1701.         cmp     eax, DIRECTORY
  1702.         jz      .next_path_part
  1703.         xor     edi, edi    ; path folder is a file
  1704.         jmp     @f
  1705.  
  1706. .not_found:
  1707.         mov     esi, edi
  1708.         call    strlen
  1709.         mov     al, '/'
  1710.         repnz scasb
  1711.         mov     edi, esi
  1712.         jnz     @f
  1713.         xor     edi, edi    ; path folder not found
  1714. @@:
  1715.         movi    eax, ERROR_FILE_NOT_FOUND
  1716.         stc
  1717. .ret:
  1718.         pop     esi ecx ebx
  1719.         ret
  1720.  
  1721. writeSuperblock:
  1722.         push    ebx
  1723.         mov     eax, 2
  1724.         lea     ebx, [ebp+EXTFS.superblock]
  1725.         call    fs_write32_sys
  1726.         pop     ebx
  1727.         ret
  1728.  
  1729. extfsWritingInit:
  1730.         movi    eax, ERROR_UNSUPPORTED_FS
  1731.         test    [ebp+EXTFS.mountType], READ_ONLY
  1732.         jnz     @f
  1733. ext_lock:
  1734.         lea     ecx, [ebp+EXTFS.Lock]
  1735.         jmp     mutex_lock
  1736.  
  1737. @@:
  1738.         pop     ebx
  1739.         xor     ebx, ebx
  1740.         ret
  1741.  
  1742. ext_unlock:
  1743.         lea     ecx, [ebp+EXTFS.Lock]
  1744.         jmp     mutex_unlock
  1745.  
  1746. ;----------------------------------------------------------------
  1747. ext_ReadFolder:
  1748.         call    ext_lock
  1749.         cmp     byte [esi], 0
  1750.         jz      .root_folder
  1751.         call    findInode
  1752.         jc      .error_ret
  1753.         lea     esi, [ebp+EXTFS.inodeBuffer]
  1754.         test    [esi+INODE.accessMode], FLAG_FILE
  1755.         jnz     .error_not_found
  1756.         jmp     @f
  1757.  
  1758. .root_folder:
  1759.         lea     esi, [ebp+EXTFS.rootInodeBuffer]
  1760.         lea     edi, [ebp+EXTFS.inodeBuffer]
  1761.         movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
  1762.         shr     ecx, 2
  1763.         push    edi
  1764.         rep movsd
  1765.         pop     esi
  1766. @@:
  1767.         cmp     [esi+INODE.fileSize], 0
  1768.         je      .error_empty_dir
  1769.         mov     edx, [ebx+16]
  1770.         push    edx         ; [edi+28] result buffer
  1771.         push    0           ; [edi+24] end of the current block in folder
  1772.         pushd   [ebx+12]    ; [edi+20] files to read
  1773.         pushd   [ebx+4]     ; [edi+16] first wanted file
  1774.         pushd   [ebx+8]     ; [edi+12] flags
  1775.         push    0           ; [edi+8]  read files
  1776.         push    0           ; [edi+4]  files in folder
  1777.         push    0           ; [edi]    current block index
  1778.         mov     edi, esp    ; edi -> local variables
  1779.         add     edx, 32
  1780.         xor     ecx, ecx
  1781.         call    extfsGetExtent
  1782.         jc      .error_get_block
  1783.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  1784.         call    extfsReadBlock
  1785.         jc      .error_get_block
  1786.         mov     eax, ebx
  1787.         add     eax, [ebp+EXTFS.bytesPerBlock]
  1788.         mov     [edi+24], eax
  1789.         mov     ecx, [edi+16]
  1790. .find_wanted_start:
  1791.         jecxz   .find_wanted_end
  1792. .find_wanted_cycle:
  1793.         cmp     [ebx+DIRENTRY.inodeNumber], 0
  1794.         jz      @f
  1795.         inc     dword [edi+4]
  1796.         dec     ecx
  1797. @@:
  1798.         movzx   eax, [ebx+DIRENTRY.entryLength]
  1799.         cmp     eax, 12     ; minimum entry length
  1800.         jb      .error_bad_len
  1801.         test    eax, 3      ; length must be aligned
  1802.         jnz     .error_bad_len
  1803.         sub     [esi+INODE.fileSize], eax
  1804.         add     ebx, eax
  1805.         cmp     ebx, [edi+24]
  1806.         jb      .find_wanted_start
  1807.         push    .find_wanted_start
  1808. .end_block: ; read next block
  1809.         cmp     [esi+INODE.fileSize], 0
  1810.         jle     .end_dir
  1811.         inc     dword [edi]
  1812.         push    ecx
  1813.         mov     ecx, [edi]
  1814.         call    extfsGetExtent
  1815.         jc      .error_get_block
  1816.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  1817.         call    extfsReadBlock
  1818.         jc      .error_get_block
  1819.         pop     ecx
  1820.         mov     eax, ebx
  1821.         add     eax, [ebp+EXTFS.bytesPerBlock]
  1822.         mov     [edi+24], eax
  1823.         ret
  1824.  
  1825. .wanted_end:
  1826.         loop    .find_wanted_cycle
  1827. .find_wanted_end:
  1828.         mov     ecx, [edi+20]
  1829. .wanted_start:
  1830.         jecxz   .wanted_end
  1831.         cmp     [ebx+DIRENTRY.inodeNumber], 0
  1832.         jz      .empty_rec
  1833.         inc     dword [edi+8]
  1834.         inc     dword [edi+4]
  1835.         push    ebx edi ecx esi edx edi
  1836.         pushd   [edi+12]
  1837.         mov     edi, edx
  1838.         xor     eax, eax
  1839.         mov     ecx, 40 / 4
  1840.         rep stosd
  1841.         popd    [edx+4] edi
  1842.         mov     eax, [ebx+DIRENTRY.inodeNumber]
  1843.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  1844.         call    readInode
  1845.         jc      .error_read_subinode
  1846.         mov     esi, ebx
  1847.         lea     edi, [edx+8]
  1848.         mov     eax, [ebx+INODE.inodeModified]
  1849.         sub     eax, 978307200  ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
  1850.         call    fsTime2bdfe
  1851.  
  1852.         mov     eax, [esi+INODE.accessedTime]
  1853.         sub     eax, 978307200
  1854.         call    fsTime2bdfe
  1855.  
  1856.         mov     eax, [esi+INODE.dataModified]
  1857.         sub     eax, 978307200
  1858.         call    fsTime2bdfe
  1859.         pop     edx
  1860.         or      dword [edx], KOS_DIRECTORY
  1861.         test    [esi+INODE.accessMode], FLAG_FILE
  1862.         jz      @f
  1863.         xor     dword [edx], KOS_DIRECTORY  ; mark as file
  1864.         mov     eax, [esi+INODE.fileSize]
  1865.         stosd
  1866.         mov     eax, [esi+INODE.fileSizeHigh]
  1867.         stosd
  1868. @@:
  1869.         mov     esi, [esp+12]
  1870.         movzx   ecx, [esi+DIRENTRY.nameLength]
  1871.         lea     esi, [esi+DIRENTRY.name]
  1872.         cmp     byte [esi], '.'
  1873.         jnz     @f
  1874.         or      byte [edx], KOS_HIDDEN
  1875. @@:
  1876.         lea     edi, [edx+40]
  1877.         cmp     byte [edx+4], 3
  1878.         jz      .utf8
  1879.         add     ecx, esi
  1880.         cmp     byte [edx+4], 2
  1881.         jz      .utf16
  1882. @@:
  1883.         call    utf8to16
  1884.         call    uni2ansi_char
  1885.         stosb
  1886.         cmp     esi, ecx
  1887.         jc      @b
  1888.         and     byte [edi], 0
  1889.         add     edx, 40+264
  1890. @@:
  1891.         pop     esi ecx edi ebx
  1892.         dec     ecx
  1893. .empty_rec:
  1894.         movzx   eax, [ebx+DIRENTRY.entryLength]
  1895.         cmp     eax, 12
  1896.         jb      .error_bad_len
  1897.         test    eax, 3
  1898.         jnz     .error_bad_len
  1899.         sub     [esi+INODE.fileSize], eax
  1900.         add     ebx, eax
  1901.         cmp     ebx, [edi+24]
  1902.         jb      .wanted_start
  1903.         push    .wanted_start
  1904.         jmp     .end_block
  1905.  
  1906. .utf8:
  1907.         rep movsb
  1908.         mov     byte [edi], 0
  1909.         add     edx, 40+520
  1910.         jmp     @b
  1911.  
  1912. .utf16:
  1913.         call    utf8to16
  1914.         stosw
  1915.         cmp     esi, ecx
  1916.         jc      .utf16
  1917.         and     word [edi], 0
  1918.         add     edx, 40+520
  1919.         jmp     @b
  1920.  
  1921. .end_dir:
  1922.         call    ext_unlock
  1923.         mov     edx, [edi+28]
  1924.         mov     ebx, [edi+8]
  1925.         mov     ecx, [edi+4]
  1926.         mov     dword [edx], 1  ; version
  1927.         mov     [edx+4], ebx
  1928.         mov     [edx+8], ecx
  1929.         lea     esp, [edi+32]
  1930.         mov     ecx, 20/4
  1931.         lea     edi, [edx+12]
  1932.         xor     eax, eax
  1933.         rep stosd
  1934.         ret
  1935.  
  1936. .error_bad_len:
  1937.         movi    eax, ERROR_FS_FAIL
  1938. .error_read_subinode:
  1939. .error_get_block:
  1940.         lea     esp, [edi+32]
  1941. .error_ret:
  1942.         or      ebx, -1
  1943.         push    eax
  1944.         call    ext_unlock
  1945.         pop     eax
  1946.         ret
  1947.  
  1948. .error_empty_dir:
  1949.         movi    eax, ERROR_FS_FAIL
  1950.         jmp     .error_ret
  1951.  
  1952. .error_not_found:
  1953.         movi    eax, ERROR_FILE_NOT_FOUND
  1954.         jmp     .error_ret
  1955.  
  1956. ;----------------------------------------------------------------
  1957. ext_ReadFile:
  1958.         call    ext_lock
  1959.         call    findInode
  1960.         pushd   0 eax
  1961.         jc      .ret
  1962.         lea     esi, [ebp+EXTFS.inodeBuffer]
  1963.         mov     byte [esp], ERROR_ACCESS_DENIED
  1964.         test    [esi+INODE.accessMode], FLAG_FILE
  1965.         jz      .ret    ; not a file
  1966.         mov     byte [esp], ERROR_END_OF_FILE
  1967.         mov     eax, [esi+INODE.fileSize]
  1968.         mov     edx, [esi+INODE.fileSizeHigh]
  1969.         sub     eax, [ebx+4]
  1970.         sbb     edx, [ebx+8]
  1971.         jc      .ret
  1972.         mov     ecx, [ebx+12]
  1973.         sub     eax, ecx
  1974.         sbb     edx, 0
  1975.         jc      @f
  1976.         xor     eax, eax
  1977.         mov     [esp], eax
  1978. @@:
  1979.         add     ecx, eax
  1980.         mov     eax, [ebx+4]
  1981.         mov     edx, [ebx+8]
  1982.         mov     edi, [ebx+16]
  1983.         div     [ebp+EXTFS.bytesPerBlock]
  1984.         test    edx, edx
  1985.         jz      .aligned
  1986. .piece:
  1987.         push    eax ecx
  1988.         mov     esi, edx
  1989.         mov     ecx, eax
  1990.         call    extfsGetExtent
  1991.         jc      .errorGet
  1992.         mov     ecx, [ebp+EXTFS.sectorsPerBlock]
  1993.         mul     ecx
  1994.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  1995.         call    fs_read64_sys
  1996.         test    eax, eax
  1997.         jnz     .errorRead
  1998.         pop     eax
  1999.         mov     ecx, [ebp+EXTFS.bytesPerBlock]
  2000.         sub     ecx, esi
  2001.         sub     eax, ecx
  2002.         jnc     @f
  2003.         add     ecx, eax
  2004.         xor     eax, eax
  2005. @@:
  2006.         add     esi, ebx
  2007.         add     [esp+8], ecx
  2008.         rep movsb
  2009.         mov     ecx, eax
  2010.         pop     eax
  2011.         inc     eax
  2012.         xor     edx, edx
  2013.         jecxz   .ret
  2014. .aligned:
  2015.         xchg    eax, ecx
  2016.         div     [ebp+EXTFS.bytesPerBlock]
  2017.         push    edx
  2018.         mov     edx, eax
  2019. .writeExtent:
  2020.         test    edx, edx
  2021.         jz      .end
  2022.         push    ecx
  2023.         call    extfsGetExtent
  2024.         jc      .errorGet
  2025.         sub     edx, ecx
  2026.         jnc     @f
  2027.         add     ecx, edx
  2028.         xor     edx, edx
  2029. @@:
  2030.         add     [esp], ecx
  2031.         imul    ecx, [ebp+EXTFS.sectorsPerBlock]
  2032.         mov     ebx, edi
  2033.         push    edx ecx
  2034.         mul     [ebp+EXTFS.sectorsPerBlock]
  2035.         call    fs_read64_sys
  2036.         pop     ecx edx
  2037.         test    eax, eax
  2038.         jnz     .errorRead
  2039.         shl     ecx, 9
  2040.         add     edi, ecx
  2041.         add     [esp+12], ecx
  2042.         pop     ecx
  2043.         jmp     .writeExtent
  2044.  
  2045. .end:
  2046.         mov     eax, ecx
  2047.         pop     ecx
  2048.         jecxz   .ret
  2049.         jmp     .piece
  2050.  
  2051. .errorRead:
  2052.         movi    eax, ERROR_DEVICE
  2053. .errorGet:
  2054.         pop     ebx ebx
  2055.         mov     [esp], eax
  2056. .ret:
  2057.         call    ext_unlock
  2058.         pop     eax ebx
  2059.         ret
  2060.  
  2061. ;----------------------------------------------------------------
  2062. ext_GetFileInfo:
  2063.         call    ext_lock
  2064.         cmp     byte [esi], 0
  2065.         jz      .is_root
  2066.         call    findInode
  2067.         lea     esi, [ebp+EXTFS.inodeBuffer]
  2068.         jnc     @f
  2069.         push    eax
  2070.         call    ext_unlock
  2071.         pop     eax
  2072.         ret
  2073.  
  2074. .is_root:
  2075.         mov     edi, esi
  2076.         lea     esi, [ebp+EXTFS.rootInodeBuffer]
  2077. @@:
  2078.         mov     edx, [ebx+16]
  2079.         mov     bl, [edi]
  2080.         xor     eax, eax
  2081.         mov     edi, edx
  2082.         mov     ecx, 40/4
  2083.         rep stosd
  2084.         cmp     bl, '.'
  2085.         jne     @f
  2086.         or      dword [edx], KOS_HIDDEN
  2087. @@:
  2088.         or      dword [edx], KOS_DIRECTORY
  2089.         test    [esi+INODE.accessMode], FLAG_FILE
  2090.         jz      @f
  2091.         xor     dword [edx], KOS_DIRECTORY  ; mark as file
  2092.         mov     eax, [esi+INODE.fileSize]
  2093.         mov     ebx, [esi+INODE.fileSizeHigh]
  2094.         mov     dword [edx+32], eax
  2095.         mov     dword [edx+36], ebx
  2096. @@:
  2097.         lea     edi, [edx+8]
  2098.         mov     eax, [esi+INODE.inodeModified]
  2099.         sub     eax, 978307200  ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
  2100.         call    fsTime2bdfe
  2101.  
  2102.         mov     eax, [esi+INODE.accessedTime]
  2103.         sub     eax, 978307200
  2104.         call    fsTime2bdfe
  2105.  
  2106.         mov     eax, [esi+INODE.dataModified]
  2107.         sub     eax, 978307200
  2108.         call    fsTime2bdfe
  2109.         call    ext_unlock
  2110.         xor     eax, eax
  2111.         ret
  2112.  
  2113. ;----------------------------------------------------------------
  2114. ext_SetFileInfo:
  2115.         call    extfsWritingInit
  2116.         call    findInode
  2117.         jc      @f
  2118.         push    esi
  2119.         mov     esi, [ebx+16]
  2120.         add     esi, 16
  2121.         lea     edi, [ebp+EXTFS.inodeBuffer]
  2122.         call    fsCalculateTime
  2123.         add     eax, 978307200  ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
  2124.         mov     [edi+INODE.accessedTime], eax
  2125.  
  2126.         add     esi, 8
  2127.         call    fsCalculateTime
  2128.         add     eax, 978307200
  2129.         mov     [edi+INODE.dataModified], eax
  2130.         mov     ebx, edi
  2131.         pop     eax
  2132.         call    writeInode
  2133. @@:
  2134.         push    eax
  2135.         jc      @f
  2136.         call    writeSuperblock
  2137.         mov     esi, [ebp+PARTITION.Disk]
  2138.         call    disk_sync
  2139. @@:
  2140.         call    ext_unlock
  2141.         pop     eax
  2142.         ret
  2143.  
  2144. ;----------------------------------------------------------------
  2145. ext_Delete:
  2146.         call    extfsWritingInit
  2147.         call    findInode
  2148.         jc      .error
  2149.         push    ecx
  2150.         movzx   edi, [ebp+EXTFS.inodeBuffer.accessMode]
  2151.         and     edi, TYPE_MASK
  2152.         cmp     edi, DIRECTORY
  2153.         jne     .file
  2154.         xor     ecx, ecx
  2155. .checkDirectory:
  2156.         push    ecx
  2157.         call    extfsGetExtent
  2158.         jc      .empty
  2159.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  2160.         call    extfsReadBlock
  2161.         jc      .error8
  2162.         mov     edx, ebx
  2163.         add     edx, [ebp+EXTFS.bytesPerBlock]
  2164. .dir_entry:
  2165.         movzx   ecx, [ebx+DIRENTRY.nameLength]
  2166.         mov     ax, word [ebx+DIRENTRY.name]
  2167.         jecxz   @f
  2168.         cmp     al, '.'
  2169.         jnz     .not_empty
  2170.         dec     ecx
  2171.         jz      @f
  2172.         cmp     al, ah
  2173.         jnz     .not_empty
  2174.         dec     ecx
  2175.         jnz     .not_empty
  2176. @@:
  2177.         mov     cx, [ebx+DIRENTRY.entryLength]
  2178.         jecxz   @f
  2179.         add     ebx, ecx
  2180.         cmp     ebx, edx
  2181.         jb      .dir_entry
  2182. @@:
  2183.         pop     ecx
  2184.         inc     ecx
  2185.         jmp     .checkDirectory
  2186.  
  2187. .not_empty:
  2188.         pop     eax eax
  2189.         push    ERROR_ACCESS_DENIED
  2190.         jmp     .ret
  2191.  
  2192. .error8:
  2193.         pop     ebx
  2194. .error4:
  2195.         pop     ebx
  2196. .error:
  2197.         push    eax
  2198.         jmp     .ret
  2199.  
  2200. .empty:
  2201.         pop     ecx ecx
  2202.         cmp     eax, ERROR_END_OF_FILE
  2203.         jnz     .error
  2204.         push    ecx
  2205. .file:
  2206.         mov     eax, ecx
  2207.         call    unlinkInode
  2208.         jc      .error4
  2209.         pop     eax
  2210.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  2211.         cmp     edi, DIRECTORY
  2212.         jnz     @f
  2213.         dec     [ebx+INODE.linksCount]
  2214.         call    writeInode
  2215. @@:
  2216.         mov     eax, esi
  2217.         call    readInode
  2218.         jc      .error
  2219.         dec     [ebx+INODE.linksCount]
  2220.         jz      @f
  2221.         cmp     edi, DIRECTORY
  2222.         jnz     .hardlinks
  2223. @@:
  2224.         push    esi edi
  2225.         xor     eax, eax
  2226.         xor     edx, edx
  2227.         call    extfsTruncateFile   ; free file's data
  2228.         movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
  2229.         lea     edi, [ebp+EXTFS.inodeBuffer]
  2230.         xor     eax, eax
  2231.         push    edi
  2232.         rep stosb
  2233.         call    fsGetTime
  2234.         pop     ebx edi esi
  2235.         add     eax, 978307200
  2236.         mov     [ebx+INODE.deletedTime], eax
  2237.         mov     eax, esi
  2238.         dec     eax
  2239.         xor     edx, edx
  2240.         div     [ebp+EXTFS.superblock.inodesPerGroup]
  2241.         push    edx
  2242.         mov     ebx, [ebp+EXTFS.descriptorTable]
  2243.         shl     eax, 5
  2244.         add     ebx, eax
  2245.         cmp     edi, DIRECTORY
  2246.         jnz     @f
  2247.         dec     [ebx+BGDESCR.directoriesCount]
  2248. @@:
  2249.         inc     [ebx+BGDESCR.inodesFree]
  2250.         push    [ebx+BGDESCR.inodeBitmap]
  2251.         call    extfsWriteDescriptor
  2252.         pop     eax
  2253.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  2254.         mov     ecx, eax
  2255.         call    extfsReadBlock
  2256.         pop     edx
  2257.         jc      .error
  2258.         mov     eax, edx
  2259.         and     edx, 31
  2260.         shr     eax, 5
  2261.         shl     eax, 2
  2262.         add     eax, ebx
  2263.         btr     [eax], edx
  2264.         mov     eax, ecx
  2265.         call    extfsWriteBlock
  2266.         inc     [ebp+EXTFS.superblock.inodesFree]
  2267. .hardlinks:
  2268.         mov     eax, esi
  2269.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  2270.         call    writeInode
  2271.         push    eax
  2272.         call    writeSuperblock
  2273.         mov     esi, [ebp+PARTITION.Disk]
  2274.         call    disk_sync
  2275. .ret:
  2276.         call    ext_unlock
  2277.         xor     ebx, ebx
  2278.         pop     eax
  2279.         ret
  2280.  
  2281. ;----------------------------------------------------------------
  2282. ext_CreateFolder:
  2283.         call    extfsWritingInit
  2284.         call    findInode
  2285.         jnc     .success    ; exist
  2286.         test    edi, edi
  2287.         jz      .error
  2288.         mov     eax, esi
  2289.         call    extfsInodeAlloc
  2290.         jc      .error
  2291.         push    ebx esi edi
  2292.         lea     edi, [ebp+EXTFS.inodeBuffer]
  2293.         movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
  2294.         xor     eax, eax
  2295.         rep stosb
  2296.         call    fsGetTime
  2297.         add     eax, 978307200
  2298.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  2299.         mov     [ebx+INODE.accessedTime], eax
  2300.         mov     [ebx+INODE.dataModified], eax
  2301.         pop     edi esi edx
  2302. ; edx = allocated inode number, edi -> filename, esi = parent inode number
  2303.         mov     [ebx+INODE.accessMode], DIRECTORY or PERMISSIONS
  2304.         mov     eax, edx
  2305.         call    writeInode
  2306.         jc      .error
  2307. ; link to self
  2308.         push    edx esi
  2309.         mov     eax, edx
  2310.         mov     ebx, eax
  2311.         mov     dl, DIR_DIRECTORY
  2312.         mov     esi, self_link
  2313.         call    linkInode
  2314.         pop     esi edx
  2315.         jc      .error
  2316. ; link to parent
  2317.         push    edx esi
  2318.         mov     eax, ebx
  2319.         mov     ebx, esi
  2320.         mov     dl, DIR_DIRECTORY
  2321.         mov     esi, parent_link
  2322.         call    linkInode
  2323.         pop     esi edx
  2324.         jc      .error
  2325. ; link parent to child
  2326.         mov     eax, esi
  2327.         mov     ebx, edx
  2328.         mov     esi, edi
  2329.         mov     dl, DIR_DIRECTORY
  2330.         call    linkInode
  2331.         jc      .error
  2332.         mov     eax, ebx
  2333.         dec     eax
  2334.         xor     edx, edx
  2335.         div     [ebp+EXTFS.superblock.inodesPerGroup]
  2336.         mov     ebx, [ebp+EXTFS.descriptorTable]
  2337.         shl     eax, 5
  2338.         add     ebx, eax
  2339.         inc     [ebx+BGDESCR.directoriesCount]
  2340.         call    extfsWriteDescriptor
  2341. .success:
  2342. .error:
  2343.         push    eax
  2344.         call    writeSuperblock
  2345.         mov     esi, [ebp+PARTITION.Disk]
  2346.         call    disk_sync
  2347.         call    ext_unlock
  2348.         pop     eax
  2349.         ret
  2350.  
  2351. self_link   db ".", 0
  2352. parent_link db "..", 0
  2353.  
  2354. ;----------------------------------------------------------------
  2355. ext_CreateFile:
  2356.         call    extfsWritingInit
  2357.         pushd   0 0 ebx
  2358.         call    findInode
  2359.         jnc     .exist
  2360.         test    edi, edi
  2361.         jz      .error
  2362.         mov     eax, esi
  2363.         call    extfsInodeAlloc
  2364.         jc      .error
  2365.         push    ebx ebx esi edi
  2366.         lea     edi, [ebp+EXTFS.inodeBuffer]
  2367.         movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
  2368.         xor     eax, eax
  2369.         rep stosb
  2370.         call    fsGetTime
  2371.         add     eax, 978307200
  2372.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  2373.         mov     [ebx+INODE.accessedTime], eax
  2374.         mov     [ebx+INODE.dataModified], eax
  2375.         pop     edi esi edx
  2376. ; edx = allocated inode number, edi -> filename, esi = parent inode number
  2377.         mov     [ebx+INODE.accessMode], FLAG_FILE or PERMISSIONS
  2378.         mov     eax, edx
  2379.         call    writeInode
  2380.         jc      .error2
  2381. ; link parent to child
  2382.         mov     eax, esi
  2383.         mov     ebx, edx
  2384.         mov     esi, edi
  2385.         mov     dl, DIR_FLAG_FILE
  2386.         call    linkInode
  2387.         jc      .error2
  2388.         pop     esi ebx
  2389.         mov     eax, [ebx+12]
  2390.         xor     edx, edx
  2391.         jmp     ext_WriteFile.start
  2392.  
  2393. .exist:
  2394.         movi    eax, ERROR_ACCESS_DENIED
  2395.         test    [ebp+EXTFS.inodeBuffer.accessMode], FLAG_FILE
  2396.         jz      .error  ; not a file
  2397.         pop     ebx
  2398.         mov     eax, [ebx+12]
  2399.         xor     edx, edx
  2400.         push    eax edx ebx esi
  2401.         call    extfsTruncateFile
  2402.         pop     esi ebx edx eax
  2403.         jmp     ext_WriteFile.start
  2404.  
  2405. .error2:
  2406.         pop     ebx
  2407. .error:
  2408.         push    eax
  2409.         call    ext_unlock
  2410.         pop     eax ebx ebx ebx
  2411.         ret
  2412.  
  2413. ;----------------------------------------------------------------
  2414. ext_WriteFile:
  2415.         call    extfsWritingInit
  2416.         call    findInode
  2417.         pushd   0 eax
  2418.         jc      .ret
  2419.         mov     byte [esp], ERROR_ACCESS_DENIED
  2420.         test    [ebp+EXTFS.inodeBuffer.accessMode], FLAG_FILE
  2421.         jz      .ret    ; not a file
  2422.         mov     byte [esp], 0
  2423.         mov     eax, [ebx+4]
  2424.         mov     edx, [ebx+8]
  2425.         add     eax, [ebx+12]
  2426.         adc     edx, 0
  2427. .start:
  2428.         push    esi
  2429.         mov     ecx, esi
  2430.         call    extfsExtendFile
  2431.         jc      .errorExtend
  2432.         mov     eax, [ebx+4]
  2433.         mov     edx, [ebx+8]
  2434.         mov     ecx, [ebx+12]
  2435.         mov     esi, [ebx+16]
  2436. .write:
  2437.         div     [ebp+EXTFS.bytesPerBlock]
  2438.         test    edx, edx
  2439.         jz      .aligned
  2440. .piece:
  2441.         mov     ebx, ecx
  2442.         mov     edi, edx
  2443.         mov     ecx, eax
  2444.         push    eax
  2445.         call    extfsGetExtent
  2446.         jc      .errorGet
  2447.         mov     ecx, [ebp+EXTFS.sectorsPerBlock]
  2448.         mul     ecx
  2449.         push    ecx eax ebx
  2450.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  2451.         call    fs_read64_sys
  2452.         test    eax, eax
  2453.         jnz     .errorDevice
  2454.         pop     eax
  2455.         mov     ecx, [ebp+EXTFS.bytesPerBlock]
  2456.         sub     ecx, edi
  2457.         sub     eax, ecx
  2458.         jnc     @f
  2459.         add     ecx, eax
  2460.         xor     eax, eax
  2461. @@:
  2462.         add     edi, ebx
  2463.         add     [esp+20], ecx
  2464.         rep movsb
  2465.         mov     edi, eax
  2466.         pop     eax ecx
  2467.         xor     edx, edx
  2468.         call    fs_write64_sys
  2469.         mov     ecx, edi
  2470.         pop     eax
  2471.         inc     eax
  2472.         xor     edx, edx
  2473.         jecxz   .done
  2474. .aligned:
  2475.         xchg    eax, ecx
  2476.         div     [ebp+EXTFS.bytesPerBlock]
  2477.         push    edx
  2478.         mov     edx, eax
  2479. .writeExtent:
  2480.         test    edx, edx
  2481.         jz      .end
  2482.         push    ecx
  2483.         call    extfsGetExtent
  2484.         jc      .errorGet2
  2485.         sub     edx, ecx
  2486.         jnc     @f
  2487.         add     ecx, edx
  2488.         xor     edx, edx
  2489. @@:
  2490.         add     [esp], ecx
  2491.         imul    ecx, [ebp+EXTFS.sectorsPerBlock]
  2492.         mov     ebx, esi
  2493.         push    edx ecx
  2494.         mul     [ebp+EXTFS.sectorsPerBlock]
  2495.         call    fs_write64_sys
  2496.         test    eax, eax
  2497.         jnz     .errorDevice
  2498.         pop     ebx edx ecx
  2499.         shl     ebx, 9
  2500.         add     esi, ebx
  2501.         add     [esp+12], ebx
  2502.         jmp     .writeExtent
  2503.  
  2504. .end:
  2505.         mov     eax, ecx
  2506.         pop     ecx
  2507.         jecxz   .done
  2508.         jmp     .piece
  2509.  
  2510. .errorDevice:
  2511.         pop     eax eax
  2512.         movi    eax, ERROR_DEVICE
  2513. .errorGet2:
  2514.         pop     ebx
  2515. .errorGet:
  2516.         pop     ebx
  2517. .errorExtend:
  2518.         mov     [esp+4], eax
  2519. .done:
  2520.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  2521.         pop     eax
  2522.         call    writeInode
  2523.         add     [esp], eax
  2524.         call    writeSuperblock
  2525.         mov     esi, [ebp+PARTITION.Disk]
  2526.         call    disk_sync
  2527. .ret:
  2528.         call    ext_unlock
  2529.         pop     eax ebx
  2530.         ret
  2531.  
  2532. .erase:
  2533.         push    eax eax edi
  2534.         mov     eax, ebx
  2535.         jmp     .write
  2536.  
  2537. ;----------------------------------------------------------------
  2538. ext_SetFileEnd:
  2539.         call    extfsWritingInit
  2540.         call    findInode
  2541.         jc      .error2
  2542.         lea     edi, [ebp+EXTFS.inodeBuffer]
  2543.         movi    eax, ERROR_ACCESS_DENIED
  2544.         test    [edi+INODE.accessMode], FLAG_FILE
  2545.         jz      .error2 ; not a file
  2546.         mov     eax, [ebx+4]
  2547.         mov     edx, [ebx+8]
  2548.         mov     ebx, [edi+INODE.fileSize]
  2549.         mov     ecx, [edi+INODE.fileSizeHigh]
  2550.         push    esi ecx
  2551.         cmp     ebx, eax
  2552.         sbb     ecx, edx
  2553.         mov     ecx, esi
  2554.         jnc     @f
  2555.         call    extfsExtendFile
  2556.         pop     esi
  2557.         jc      .error
  2558.         mov     eax, [edi+INODE.fileSize]
  2559.         mov     edx, [edi+INODE.fileSizeHigh]
  2560.         sub     eax, ebx
  2561.         sbb     edx, esi
  2562.         jnz     .done
  2563.         cmp     eax, 1000001h
  2564.         jnc     .done
  2565.         push    eax
  2566.         stdcall kernel_alloc, eax
  2567.         pop     ecx
  2568.         test    eax, eax
  2569.         jz      .error
  2570.         push    ecx
  2571.         add     ecx, 3
  2572.         shr     ecx, 2
  2573.         mov     edx, esi
  2574.         mov     esi, eax
  2575.         mov     edi, eax
  2576.         xor     eax, eax
  2577.         rep stosd
  2578.         pop     ecx edi
  2579.         push    esi
  2580.         call    ext_WriteFile.erase
  2581.         call    kernel_free
  2582.         xor     eax, eax
  2583.         ret
  2584.  
  2585. @@:
  2586.         call    extfsTruncateFile
  2587.         pop     eax
  2588. .done:
  2589.         xor     eax, eax
  2590. .error:
  2591.         xchg    eax, [esp]
  2592.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  2593.         call    writeInode
  2594.         add     [esp], eax
  2595.         call    writeSuperblock
  2596.         mov     esi, [ebp+PARTITION.Disk]
  2597.         call    disk_sync
  2598.         pop     eax
  2599. .error2:
  2600.         push    eax
  2601.         call    ext_unlock
  2602.         pop     eax
  2603.         ret
  2604.