Subversion Repositories Kolibri OS

Rev

Rev 6853 | Rev 6859 | 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: 6856 $
  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.         neg     ecx
  590.         add     ecx, 32
  591.         shr     eax, cl
  592.         or      [edi], eax
  593. .done:
  594.         pop     eax
  595.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  596.         call    extfsWriteBlock
  597.         mov     ebx, [esp]
  598.         mov     ecx, [esp+8]
  599.         sub     [ebx+BGDESCR.blocksFree], cx
  600.         jnc     @f
  601.         mov     [ebx+BGDESCR.blocksFree], 0
  602. @@:
  603.         sub     [ebp+EXTFS.superblock.blocksFree], ecx
  604.         call    extfsWriteDescriptor
  605.         pop     eax ebx
  606.         sub     eax, [ebp+EXTFS.descriptorTable]
  607.         shr     eax, 5
  608.         mul     [ebp+EXTFS.superblock.blocksPerGroup]
  609.         mov     ebx, eax
  610.         add     ebx, esi
  611.         add     ebx, [ebp+EXTFS.superblock.firstGroupBlock]
  612.         pop     ecx
  613.         mov     eax, ecx
  614.         mul     [ebp+EXTFS.sectorsPerBlock]
  615.         add     [ebp+EXTFS.inodeBuffer.sectorsUsed], eax
  616.         xor     eax, eax
  617. .ret:
  618.         pop     edi esi edx
  619.         ret
  620.  
  621. .next:      ; search forward, then backward
  622.         pop     ebx
  623.         cmp     ebx, [esp]
  624.         jc      .backward
  625.         add     ebx, 32
  626.         cmp     ebx, [ebp+EXTFS.descriptorTableEnd]
  627.         jc      .test_block_group
  628.         mov     ebx, [esp]
  629. .backward:
  630.         sub     ebx, 32
  631.         cmp     ebx, [ebp+EXTFS.descriptorTable]
  632.         jnc     .test_block_group
  633.         movi    eax, ERROR_DISK_FULL
  634.         push    eax
  635. .fail:
  636.         add     esp, 12
  637.         xor     ecx, ecx
  638.         stc
  639.         jmp     .ret
  640.  
  641. extfsGetExtent:
  642. ; in: ecx = starting file block
  643. ; out: eax = first block number, ecx = extent size
  644.         push    ebx edx esi
  645.         lea     esi, [ebp+EXTFS.inodeBuffer]
  646.         test    [esi+INODE.featureFlags], EXTENTS_USED
  647.         jz      .listTreeSearch
  648.         add     esi, INODE.blockNumbers
  649. .extentTreeSearch:
  650.         cmp     word [esi+NODEHEADER.magic], 0xF30A
  651.         jne     .fail
  652.         movzx   ebx, [esi+NODEHEADER.entriesFolow]
  653.         add     esi, sizeof.NODEHEADER
  654.         test    ebx, ebx
  655.         jz      .noBlock
  656.         cmp     word [esi-sizeof.NODEHEADER+NODEHEADER.currentDepth], 0
  657.         je      .leaf_block
  658.         dec     ebx
  659.         jz      .end_search_index
  660. @@:
  661.         cmp     ecx, [esi+sizeof.INDEX+INDEX.fileBlock]
  662.         jb      .end_search_index
  663.         add     esi, sizeof.INDEX
  664.         dec     ebx
  665.         jnz     @b
  666. .end_search_index:
  667.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  668.         mov     eax, [esi+INDEX.nodeBlock]
  669.         call    extfsReadBlock
  670.         jc      .fail2
  671.         mov     esi, ebx
  672.         jmp     .extentTreeSearch
  673.  
  674. .fail:
  675.         movi    eax, ERROR_FS_FAIL
  676.         jmp     .fail2
  677.  
  678. .leaf_block:
  679.         movzx   edx, [esi+EXTENT.blocksCount]
  680.         add     edx, [esi+EXTENT.fileBlock]
  681.         sub     edx, ecx
  682.         ja      .end_search_extent
  683.         add     esi, sizeof.EXTENT
  684.         dec     ebx
  685.         jnz     .leaf_block
  686. .noBlock:
  687.         movi    eax, ERROR_END_OF_FILE
  688. .fail2:
  689.         pop     esi edx ebx
  690.         stc
  691.         ret
  692.  
  693. .end_search_extent:
  694.         sub     ecx, [esi+EXTENT.fileBlock]
  695.         jc      .fail
  696.         add     ecx, [esi+EXTENT.fsBlock]
  697.         mov     eax, ecx
  698.         mov     ecx, edx
  699.         pop     esi edx ebx
  700.         ret
  701.  
  702. .listTreeSearch:
  703.         cmp     ecx, 12
  704.         jb      .get_direct_block
  705.         sub     ecx, 12
  706.         cmp     ecx, [ebp+EXTFS.dwordsPerBlock]
  707.         jb      .get_indirect_block
  708.         sub     ecx, [ebp+EXTFS.dwordsPerBlock]
  709.         cmp     ecx, [ebp+EXTFS.dwordsPerBranch]
  710.         jb      .get_double_indirect_block
  711. ; triply-indirect blocks
  712.         sub     ecx, [ebp+EXTFS.dwordsPerBranch]
  713.         mov     eax, [esi+INODE.tripleAddress]
  714.         test    eax, eax
  715.         jz      .noBlock
  716.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  717.         call    extfsReadBlock
  718.         jc      .fail2
  719.         xor     edx, edx
  720.         mov     eax, ecx
  721.         div     [ebp+EXTFS.dwordsPerBranch]
  722. ; eax = number in triply-indirect block, edx = number in branch
  723.         mov     eax, [ebx+eax*4]
  724.         test    eax, eax
  725.         jz      .noBlock
  726.         call    extfsReadBlock
  727.         jc      .fail2
  728.         mov     eax, edx
  729.         jmp     @f
  730.  
  731. .get_direct_block:
  732.         mov     edx, ecx
  733.         mov     cl, 12
  734.         lea     ebx, [esi+INODE.blockNumbers]
  735.         jmp     .calculateExtent
  736.  
  737. .get_indirect_block:
  738.         mov     eax, [esi+INODE.addressBlock]
  739.         test    eax, eax
  740.         jz      .noBlock
  741.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  742.         call    extfsReadBlock
  743.         jc      .fail2
  744.         mov     edx, ecx
  745.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  746.         jmp     .calculateExtent
  747.  
  748. .get_double_indirect_block:
  749.         mov     eax, [esi+INODE.doubleAddress]
  750.         test    eax, eax
  751.         jz      .noBlock
  752.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  753.         call    extfsReadBlock
  754.         jc      .fail2
  755.         mov     eax, ecx
  756. @@:
  757.         xor     edx, edx
  758.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  759.         div     ecx
  760. ; eax = number in doubly-indirect block, edx = number in indirect block
  761.         mov     eax, [ebx+eax*4]
  762.         test    eax, eax
  763.         jz      .noBlock
  764.         call    extfsReadBlock
  765.         jc      .fail2
  766. .calculateExtent:
  767.         lea     esi, [ebx+edx*4]
  768.         lodsd
  769.         test    eax, eax
  770.         jz      .noBlock
  771.         mov     ebx, eax
  772.         sub     ecx, edx
  773.         xor     edx, edx
  774. @@:
  775.         inc     edx
  776.         dec     ecx
  777.         jz      @f
  778.         lodsd
  779.         sub     eax, ebx
  780.         sub     eax, edx
  781.         jz      @b
  782. @@:
  783.         mov     eax, ebx
  784.         mov     ecx, edx
  785.         pop     esi edx ebx
  786.         clc
  787.         ret
  788.  
  789. getInodeLocation:
  790. ; in: eax = inode number
  791. ; out: eax = inode sector, edx = offset in sector
  792.         dec     eax
  793.         xor     edx, edx
  794.         div     [ebp+EXTFS.superblock.inodesPerGroup]
  795.         shl     eax, 5
  796.         add     eax, [ebp+EXTFS.descriptorTable]
  797.         mov     ebx, [eax+BGDESCR.inodeTable]
  798.         imul    ebx, [ebp+EXTFS.sectorsPerBlock]
  799.         movzx   eax, [ebp+EXTFS.superblock.inodeSize]
  800.         mul     edx
  801.         mov     edx, eax
  802.         shr     eax, 9
  803.         and     edx, 511
  804.         add     eax, ebx
  805.         ret
  806.  
  807. writeInode:
  808. ; in: eax = inode number, ebx -> inode data
  809.         push    edx edi esi ecx ebx eax
  810.         mov     edi, ebx
  811.         call    fsGetTime
  812.         add     eax, 978307200
  813.         mov     [edi+INODE.inodeModified], eax
  814.         pop     eax
  815.         cmp     eax, ROOT_INODE
  816.         jnz     @f
  817.         movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
  818.         mov     esi, edi
  819.         lea     edi, [ebp+EXTFS.rootInodeBuffer]
  820.         rep movsb
  821. @@:
  822.         call    getInodeLocation
  823.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  824.         mov     ecx, eax
  825.         call    fs_read32_sys
  826.         test    eax, eax
  827.         jnz     @f
  828.         mov     eax, ecx
  829.         movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
  830.         mov     edi, edx
  831.         add     edi, ebx
  832.         mov     esi, [esp]
  833.         rep movsb
  834.         call    fs_write32_sys
  835. .ret:
  836.         pop     ebx ecx esi edi edx
  837.         ret
  838.  
  839. @@:
  840.         movi    eax, ERROR_DEVICE
  841.         stc
  842.         jmp     .ret
  843.  
  844. readInode:
  845. ; in: eax = inode number, ebx -> inode buffer
  846.         push    edx edi esi ecx ebx
  847.         mov     edi, ebx
  848.         call    getInodeLocation
  849.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  850.         call    fs_read32_sys
  851.         test    eax, eax
  852.         jnz     @b
  853.         movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
  854.         mov     esi, edx
  855.         add     esi, ebx
  856.         rep movsb
  857.         xor     eax, eax
  858.         pop     ebx ecx esi edi edx
  859.         ret
  860.  
  861. indirectBlockAlloc:
  862. ;   in:
  863. ; edi -> indirect block number
  864. ; ebx = starting extent block
  865. ; ecx = extent size
  866. ; edx = starting file block
  867.         mov     eax, [edi]
  868.         test    eax, eax
  869.         jz      .newBlock
  870.         push    edi ebx ecx
  871.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  872.         call    extfsReadBlock
  873.         jc      .err2
  874.         lea     edi, [ebx+edx*4]
  875.         test    edx, edx
  876.         jz      @f
  877.         cmp     dword[edi-4], 0
  878.         jnz     @f
  879.         pop     ecx ebx edi
  880. .err:
  881.         mov     al, ERROR_FS_FAIL
  882.         stc
  883.         ret
  884.  
  885. .err2:
  886.         pop     ecx ebx edi
  887.         ret
  888.  
  889. .newBlock:
  890.         test    edx, edx
  891.         jnz     .err
  892.         mov     [edi], ebx
  893.         inc     ebx
  894.         dec     ecx
  895.         push    edi ebx ecx
  896.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  897.         mov     edi, [ebp+EXTFS.tempBlockBuffer]
  898.         push    edi
  899.         rep stosd
  900.         pop     edi
  901. @@:
  902.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  903.         sub     ecx, edx
  904.         pop     ebx eax
  905.         sub     ebx, ecx
  906.         jnc     @f
  907.         add     ecx, ebx
  908.         xor     ebx, ebx
  909. @@:
  910.         jecxz   .done
  911.         add     edx, ecx
  912. @@:
  913.         stosd
  914.         inc     eax
  915.         loop    @b
  916. .done:
  917.         pop     edi
  918.         push    eax ebx
  919.         mov     eax, [edi]
  920.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  921.         call    extfsWriteBlock
  922.         pop     ecx ebx
  923.         ret
  924.  
  925. doublyIndirectBlockAlloc:
  926. ;   in:
  927. ; edi -> indirect block number
  928. ; edx = starting file block
  929. ; ebx = starting extent block
  930. ; ecx = extent size
  931. ; [esp+4] = rest of size
  932. ; [esp+8] = parent inode number
  933.         mov     eax, [edi]
  934.         test    eax, eax
  935.         jz      .newBlock
  936.         push    edi ecx ebx
  937.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  938.         call    extfsReadBlock
  939.         jc      .err2
  940.         mov     eax, edx
  941.         xor     edx, edx
  942.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  943.         div     ecx
  944.         lea     edi, [ebx+eax*4]
  945.         pop     ebx
  946.         test    eax, eax
  947.         jz      @f
  948.         cmp     dword[edi-4], 0
  949.         jnz     @f
  950.         pop     ecx edi
  951. .err:
  952.         mov     al, ERROR_FS_FAIL
  953.         stc
  954.         ret
  955.  
  956. .err2:
  957.         pop     ebx ecx edi
  958.         ret
  959.  
  960. .newBlock:
  961.         test    edx, edx
  962.         jnz     .err
  963.         mov     [edi], ebx
  964.         inc     ebx
  965.         dec     ecx
  966.         inc     dword[esp+4]
  967.         push    edi ecx
  968.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  969.         mov     edi, [ebp+EXTFS.mainBlockBuffer]
  970.         push    ecx edi
  971.         rep stosd
  972.         pop     edi ecx
  973. @@:
  974.         sub     ecx, eax
  975.         xchg    [esp], ecx
  976. .loop:
  977.         cmp     dword[edi], 0
  978.         jnz     @f
  979.         inc     dword[esp+12]
  980. @@:
  981.         jecxz   .extentAlloc
  982.         call    indirectBlockAlloc
  983.         jc      .end
  984.         cmp     edx, [ebp+EXTFS.dwordsPerBlock]
  985.         jnz     @b
  986.         add     edi, 4
  987.         xor     edx, edx
  988.         dec     dword[esp]
  989.         jnz     .loop
  990. .end:
  991.         pop     edi edi
  992.         push    ebx eax
  993.         mov     eax, [edi]
  994.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  995.         call    extfsWriteBlock
  996.         pop     ebx
  997.         add     eax, ebx
  998.         xor     ebx, ebx
  999.         cmp     ebx, eax
  1000.         pop     ebx
  1001.         ret
  1002.  
  1003. .extentAlloc:
  1004.         mov     ecx, [esp+12]
  1005.         xor     eax, eax
  1006.         jecxz   .end
  1007.         mov     eax, [esp+16]
  1008.         call    extfsExtentAlloc
  1009.         jc      .end
  1010.         sub     [esp+12], ecx
  1011.         jmp     @b
  1012.  
  1013. extfsExtendFile:
  1014. ;   in:
  1015. ; [ebp+EXTFS.inodeBuffer] = inode
  1016. ; ecx = inode number
  1017. ; edx:eax = new size
  1018.         push    ebx esi edi ecx
  1019.         lea     esi, [ebp+EXTFS.inodeBuffer]
  1020.         mov     ebx, [esi+INODE.fileSize]
  1021.         mov     ecx, [esi+INODE.fileSizeHigh]
  1022.         cmp     ebx, eax
  1023.         sbb     ecx, edx
  1024.         jnc     .ret
  1025.         mov     ecx, [esi+INODE.fileSizeHigh]
  1026.         mov     [esi+INODE.fileSize], eax
  1027.         mov     [esi+INODE.fileSizeHigh], edx
  1028.         sub     eax, 1
  1029.         sbb     edx, 0
  1030.         div     [ebp+EXTFS.bytesPerBlock]
  1031.         inc     eax
  1032.         xchg    eax, ebx
  1033.         mov     edx, ecx
  1034.         sub     eax, 1
  1035.         sbb     edx, 0
  1036.         jc      @f
  1037.         div     [ebp+EXTFS.bytesPerBlock]
  1038. @@:
  1039.         inc     eax
  1040.         sub     ebx, eax
  1041.         jz      .ret
  1042.         push    ebx
  1043.         mov     edx, eax
  1044. @@:
  1045.         mov     ecx, [esp]
  1046.         mov     eax, [esp+4]
  1047.         test    ecx, ecx
  1048.         jz      .done
  1049.         call    extfsExtentAlloc
  1050.         jc      .errDone
  1051.         sub     [esp], ecx
  1052.         cmp     edx, 12
  1053.         jc      .directBlocks
  1054.         sub     edx, 12
  1055.         cmp     edx, [ebp+EXTFS.dwordsPerBlock]
  1056.         jc      .indirectBlocks
  1057.         sub     edx, [ebp+EXTFS.dwordsPerBlock]
  1058.         cmp     edx, [ebp+EXTFS.dwordsPerBranch]
  1059.         jc      .doublyIndirectBlock
  1060.         sub     edx, [ebp+EXTFS.dwordsPerBranch]
  1061.         jmp     .triplyIndirectBlock
  1062.  
  1063. .newExtent:
  1064.         jmp     @b
  1065.  
  1066. .directBlocks:
  1067.         lea     edi, [esi+INODE.blockNumbers+edx*4]
  1068.         test    edx, edx
  1069.         jz      @f
  1070.         cmp     dword[edi-4], 0
  1071.         jz      .errDone
  1072. @@:
  1073.         mov     eax, ebx
  1074.         mov     ebx, ecx
  1075.         mov     ecx, 12
  1076.         sub     ecx, edx
  1077.         sub     ebx, ecx
  1078.         jnc     @f
  1079.         add     ecx, ebx
  1080.         xor     ebx, ebx
  1081. @@:
  1082.         add     edx, ecx
  1083. @@:
  1084.         stosd
  1085.         inc     eax
  1086.         loop    @b
  1087.         mov     ecx, ebx
  1088.         mov     ebx, eax
  1089.         jecxz   .newExtent
  1090.         xor     edx, edx
  1091. .indirectBlocks:
  1092.         lea     edi, [esi+INODE.addressBlock]
  1093.         cmp     dword[edi], 0
  1094.         jnz     @f
  1095.         inc     dword[esp]
  1096. @@:
  1097.         call    indirectBlockAlloc
  1098.         jc      .errDone
  1099.         add     edx, 12
  1100.         jecxz   .newExtent
  1101.         xor     edx, edx
  1102. .doublyIndirectBlock:
  1103.         lea     edi, [esi+INODE.doubleAddress]
  1104.         call    doublyIndirectBlockAlloc
  1105.         jc      .errDone
  1106.         mov     edx, [ebp+EXTFS.dwordsPerBranch]
  1107.         add     edx, [ebp+EXTFS.dwordsPerBlock]
  1108.         add     edx, 12
  1109.         jecxz   .newExtent
  1110.         xor     edx, edx
  1111. .triplyIndirectBlock:
  1112.         push    ecx ebx edx
  1113.         stdcall kernel_alloc, [ebp+EXTFS.bytesPerBlock]
  1114.         pop     edx
  1115.         mov     esi, eax
  1116.         mov     eax, [ebp+EXTFS.inodeBuffer.tripleAddress]
  1117.         test    eax, eax
  1118.         jz      .newBlock
  1119.         mov     ebx, esi
  1120.         call    extfsReadBlock
  1121.         pop     ebx ecx
  1122.         jc      .errFree
  1123.         mov     eax, edx
  1124.         xor     edx, edx
  1125.         div     [ebp+EXTFS.dwordsPerBranch]
  1126.         lea     edi, [esi+eax*4]
  1127.         test    eax, eax
  1128.         jz      @f
  1129.         cmp     dword[edi-4], 0
  1130.         jnz     @f
  1131.         mov     al, ERROR_FS_FAIL
  1132. .errFree:
  1133.         push    ecx eax
  1134.         stdcall kernel_free, esi
  1135.         pop     eax ecx
  1136. .errDone:
  1137.         imul    ecx, [ebp+EXTFS.sectorsPerBlock]
  1138.         sub     [ebp+EXTFS.inodeBuffer.sectorsUsed], ecx
  1139.         pop     ebx
  1140.         imul    ebx, [ebp+EXTFS.sectorsPerBlock]
  1141.         add     ebx, ecx
  1142.         shl     ebx, 9
  1143.         sub     [ebp+EXTFS.inodeBuffer.fileSize], ebx
  1144.         stc
  1145.         jmp     .ret
  1146.  
  1147. .newBlock:
  1148.         pop     ebx ecx
  1149.         mov     al, ERROR_FS_FAIL
  1150.         test    edx, edx
  1151.         jnz     .errFree
  1152.         mov     [ebp+EXTFS.inodeBuffer.tripleAddress], ebx
  1153.         inc     ebx
  1154.         dec     ecx
  1155.         inc     dword[esp]
  1156.         push    ecx
  1157.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  1158.         mov     edi, esi
  1159.         xor     eax, eax
  1160.         rep stosd
  1161.         mov     edi, esi
  1162.         pop     ecx
  1163. @@:
  1164.         jecxz   .extentAlloc
  1165.         call    doublyIndirectBlockAlloc
  1166.         jc      .errSave
  1167.         add     edi, 4
  1168.         jmp     @b
  1169.  
  1170. .extentAlloc:
  1171.         mov     ecx, [esp]
  1172.         mov     eax, [esp+4]
  1173.         jecxz   @f
  1174.         call    extfsExtentAlloc
  1175.         jc      .errSave
  1176.         sub     [esp], ecx
  1177.         jmp     @b
  1178.  
  1179. @@:
  1180.         mov     eax, [ebp+EXTFS.inodeBuffer.tripleAddress]
  1181.         mov     ebx, esi
  1182.         call    extfsWriteBlock
  1183.         stdcall kernel_free, esi
  1184. .done:
  1185.         xor     eax, eax
  1186.         pop     edi
  1187. .ret:
  1188.         pop     edi edi esi ebx
  1189.         ret
  1190.  
  1191. .errSave:
  1192.         push    eax
  1193.         mov     eax, [ebp+EXTFS.inodeBuffer.tripleAddress]
  1194.         mov     ebx, esi
  1195.         call    extfsWriteBlock
  1196.         pop     eax
  1197.         jmp     .errFree
  1198.  
  1199. freeBlockList:
  1200. ; in: edi -> list of blocks, edx = amount of blocks
  1201. ; out: ebx=0 -> end of list
  1202.         mov     ebx, [edi]
  1203.         test    ebx, ebx
  1204.         jz      .ret
  1205.         xor     eax, eax
  1206.         xor     ecx, ecx
  1207. @@:
  1208.         stosd
  1209.         inc     ecx
  1210.         dec     edx
  1211.         jz      @f
  1212.         mov     eax, [edi]
  1213.         sub     eax, ebx
  1214.         sub     eax, ecx
  1215.         jz      @b
  1216. @@:
  1217.         mov     eax, ebx
  1218.         call    extfsExtentFree
  1219.         test    edx, edx
  1220.         jnz     freeBlockList
  1221. .ret:
  1222.         ret
  1223.  
  1224. freeIndirectBlock:
  1225. ; in: edi -> indirect block number, edx = starting block
  1226. ; out: edi = edi+4, eax=0 -> end
  1227.         pushd   ecx 0 edi edx
  1228.         mov     eax, [edi]
  1229.         test    eax, eax
  1230.         jz      .ret
  1231.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  1232.         call    extfsReadBlock
  1233.         jc      .ret
  1234.         lea     edi, [ebx+edx*4]
  1235.         neg     edx
  1236.         add     edx, [ebp+EXTFS.dwordsPerBlock]
  1237.         call    freeBlockList
  1238.         test    ebx, ebx
  1239.         jz      @f
  1240.         inc     dword[esp+8]
  1241. @@:
  1242.         pop     edx edi
  1243.         mov     eax, [edi]
  1244.         test    edx, edx
  1245.         jnz     @f
  1246.         xor     ecx, ecx
  1247.         inc     ecx
  1248.         call    extfsExtentFree
  1249.         stosd
  1250.         jmp     .done
  1251.  
  1252. @@:
  1253.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  1254.         call    extfsWriteBlock
  1255.         add     edi, 4
  1256. .done:
  1257.         pop     eax ecx
  1258.         xor     edx, edx
  1259.         ret
  1260.  
  1261. .ret:
  1262.         pop     edi edi edx ecx
  1263.         ret
  1264.  
  1265. freeDoublyIndirectBlock:
  1266. ; in: edi -> doubly-indirect block number, edx = starting block
  1267. ; out: edi = edi+4, eax=-1 -> done, eax=0 -> end
  1268.         mov     eax, [edi]
  1269.         test    eax, eax
  1270.         jz      .ret
  1271.         push    ecx eax edx
  1272.         stdcall kernel_alloc, [ebp+EXTFS.bytesPerBlock]
  1273.         mov     ebx, eax
  1274.         pop     edx eax
  1275.         pushd   0 ebx edx
  1276.         call    extfsReadBlock
  1277.         jc      .err
  1278.         mov     eax, edx
  1279.         xor     edx, edx
  1280.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  1281.         div     ecx
  1282.         sub     ecx, eax
  1283.         push    edi
  1284.         lea     edi, [ebx+eax*4]
  1285. @@:
  1286.         call    freeIndirectBlock
  1287.         test    eax, eax
  1288.         jz      .end
  1289.         dec     ecx
  1290.         jnz     @b
  1291.         dec     dword[esp+12]
  1292. .end:
  1293.         pop     edi edx
  1294.         mov     eax, [edi]
  1295.         test    edx, edx
  1296.         jnz     @f
  1297.         xor     ecx, ecx
  1298.         inc     ecx
  1299.         call    extfsExtentFree
  1300.         stosd
  1301.         jmp     .done
  1302.  
  1303. @@:
  1304.         mov     ebx, [esp]
  1305.         call    extfsWriteBlock
  1306.         add     edi, 4
  1307.         jmp     .done
  1308.  
  1309. .err:
  1310.         mov     [esp+8], eax
  1311.         pop     eax
  1312. .done:
  1313.         call    kernel_free
  1314.         pop     eax ecx
  1315. .ret:
  1316.         xor     edx, edx
  1317.         ret
  1318.  
  1319. extfsTruncateFile:
  1320. ; in: edx:eax = new size, [ebp+EXTFS.inodeBuffer] = inode
  1321.         lea     esi, [ebp+EXTFS.inodeBuffer]
  1322.         mov     ecx, edx
  1323.         cmp     eax, [esi+INODE.fileSize]
  1324.         sbb     ecx, [esi+INODE.fileSizeHigh]
  1325.         jnc     .ret
  1326.         mov     [esi+INODE.fileSize], eax
  1327.         mov     [esi+INODE.fileSizeHigh], edx
  1328.         sub     eax, 1
  1329.         sbb     edx, 0
  1330.         jc      @f
  1331.         div     [ebp+EXTFS.bytesPerBlock]
  1332. @@:
  1333.         inc     eax
  1334.         mov     edx, eax
  1335.         cmp     edx, 12
  1336.         jc      .directBlocks
  1337.         sub     edx, 12
  1338.         cmp     edx, [ebp+EXTFS.dwordsPerBlock]
  1339.         jc      .indirectBlocks
  1340.         sub     edx, [ebp+EXTFS.dwordsPerBlock]
  1341.         cmp     edx, [ebp+EXTFS.dwordsPerBranch]
  1342.         jc      .doublyIndirectBlock
  1343.         sub     edx, [ebp+EXTFS.dwordsPerBranch]
  1344.         jmp     .triplyIndirectBlock
  1345.  
  1346. .directBlocks:
  1347.         lea     edi, [esi+INODE.blockNumbers+edx*4]
  1348.         neg     edx
  1349.         add     edx, 12
  1350.         call    freeBlockList
  1351.         test    ebx, ebx
  1352.         jz      .ret
  1353. .indirectBlocks:
  1354.         lea     edi, [esi+INODE.addressBlock]
  1355.         call    freeIndirectBlock
  1356.         test    eax, eax
  1357.         jz      .ret
  1358. .doublyIndirectBlock:
  1359.         lea     edi, [esi+INODE.doubleAddress]
  1360.         call    freeDoublyIndirectBlock
  1361.         test    eax, eax
  1362.         jz      .ret
  1363. .triplyIndirectBlock:
  1364.         mov     eax, [esi+INODE.tripleAddress]
  1365.         test    eax, eax
  1366.         jz      .ret
  1367.         push    eax edx
  1368.         stdcall kernel_alloc, [ebp+EXTFS.bytesPerBlock]
  1369.         mov     ebx, eax
  1370.         pop     edx eax
  1371.         push    ebx eax edx
  1372.         call    extfsReadBlock
  1373.         jc      .err
  1374.         mov     eax, edx
  1375.         xor     edx, edx
  1376.         div     [ebp+EXTFS.dwordsPerBranch]
  1377.         mov     ecx, [ebp+EXTFS.dwordsPerBlock]
  1378.         sub     ecx, eax
  1379.         lea     edi, [ebx+eax*4]
  1380. @@:
  1381.         call    freeDoublyIndirectBlock
  1382.         test    eax, eax
  1383.         jz      .end
  1384.         dec     ecx
  1385.         jnz     @b
  1386. .end:
  1387.         pop     edx eax
  1388.         test    edx, edx
  1389.         jnz     @f
  1390.         xor     ecx, ecx
  1391.         inc     ecx
  1392.         call    extfsExtentFree
  1393.         mov     [esi+INODE.tripleAddress], eax
  1394.         jmp     .done
  1395.  
  1396. @@:
  1397.         mov     ebx, [esp]
  1398.         call    extfsWriteBlock
  1399.         jmp     .done
  1400.  
  1401. .err:
  1402.         pop     eax eax
  1403. .done:
  1404.         call    kernel_free
  1405. .ret:
  1406.         ret
  1407.  
  1408. linkInode:
  1409. ;   in:
  1410. ; eax = inode on which to link
  1411. ; ebx = inode to link
  1412. ; esi -> name in UTF-8
  1413. ;  dl = file type
  1414.         push    esi edi ebx ecx eax edx
  1415.         call    strlen
  1416.         push    esi ebx ecx
  1417.         lea     esi, [ebp+EXTFS.inodeBuffer]
  1418.         mov     ebx, esi
  1419.         call    readInode
  1420.         jc      .error_inode_read
  1421.         mov     eax, [esi+INODE.fileSize]
  1422.         xor     edx, edx
  1423.         div     [ebp+EXTFS.bytesPerBlock]
  1424.         xor     ecx, ecx
  1425. .searchBlock:
  1426.         push    eax     ; blocks total
  1427.         push    ecx     ; current file block number
  1428.         cmp     eax, ecx
  1429.         jz      .alloc_block
  1430.         call    extfsGetExtent
  1431.         jc      .error_get_inode_block
  1432.         push    eax
  1433.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  1434.         call    extfsReadBlock
  1435.         jc      .error_block_read
  1436.         mov     ecx, [esp+12]
  1437.         add     ecx, 8  ; directory entry size
  1438.         mov     edi, [ebp+EXTFS.tempBlockBuffer]
  1439.         mov     edx, edi
  1440.         add     edx, [ebp+EXTFS.bytesPerBlock]
  1441. .searchSpace:
  1442.         movzx   eax, [edi+DIRENTRY.entryLength]
  1443.         test    eax, eax
  1444.         jz      .zeroLength
  1445.         cmp     [edi+DIRENTRY.inodeNumber], 0
  1446.         je      .unusedEntry
  1447.         movzx   ebx, [edi+DIRENTRY.nameLength]
  1448.         add     ebx, 8+3
  1449.         and     ebx, -4
  1450.         sub     eax, ebx
  1451.         add     edi, ebx
  1452.         cmp     eax, ecx
  1453.         jb      .nextEntry
  1454.         sub     edi, ebx
  1455.         mov     [edi+DIRENTRY.entryLength], bx
  1456.         add     edi, ebx
  1457.         mov     [edi+DIRENTRY.entryLength], ax
  1458.         jmp     .found
  1459.  
  1460. .unusedEntry:
  1461.         cmp     eax, ecx
  1462.         jge     .found
  1463. .nextEntry:
  1464.         add     edi, eax
  1465.         cmp     edi, edx
  1466.         jb      .searchSpace
  1467.         pop     ecx
  1468. @@:
  1469.         pop     ecx eax
  1470.         inc     ecx
  1471.         jmp     .searchBlock
  1472.  
  1473. .zeroLength:
  1474.         mov     eax, edx
  1475.         sub     eax, edi
  1476.         mov     [edi+DIRENTRY.entryLength], ax
  1477.         cmp     eax, ecx
  1478.         jge     .found
  1479.         mov     [edi+DIRENTRY.inodeNumber], 0
  1480.         pop     eax
  1481.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  1482.         call    extfsWriteBlock
  1483.         jmp     @b
  1484.  
  1485. .alloc_block:
  1486.         mov     eax, [esi+INODE.fileSize]
  1487.         add     eax, [ebp+EXTFS.bytesPerBlock]
  1488.         xor     edx, edx
  1489.         mov     ecx, [esp+24]
  1490.         call    extfsExtendFile
  1491.         jc      .error_get_inode_block
  1492.         mov     eax, [esp+24]
  1493.         mov     ebx, esi
  1494.         call    writeInode
  1495.         jc      .error_get_inode_block
  1496.         mov     ecx, [esp]
  1497.         call    extfsGetExtent
  1498.         jc      .error_get_inode_block
  1499.         push    eax
  1500.         mov     edi, [ebp+EXTFS.tempBlockBuffer]
  1501.         mov     eax, [ebp+EXTFS.bytesPerBlock]
  1502.         mov     [edi+DIRENTRY.entryLength], ax
  1503. .found:
  1504.         pop     edx ecx ecx ecx ebx esi
  1505.         mov     [edi+DIRENTRY.inodeNumber], ebx
  1506.         mov     word [edi+DIRENTRY.nameLength], cx
  1507.         sub     eax, 8
  1508.         cmp     ecx, eax
  1509.         adc     ecx, 0
  1510.         test    [ebp+EXTFS.superblock.incompatibleFlags], 2
  1511.         jz      @f
  1512.         mov     eax, [esp]
  1513.         mov     [edi+DIRENTRY.fileType], al
  1514. @@:
  1515.         push    ebx
  1516.         add     edi, 8
  1517.         rep movsb
  1518.         mov     eax, edx
  1519.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  1520.         call    extfsWriteBlock
  1521.         mov     eax, [esp]
  1522.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  1523.         call    readInode
  1524.         jc      .error_block_write
  1525.         pop     eax
  1526.         inc     [ebx+INODE.linksCount]
  1527.         call    writeInode
  1528.         jc      @f
  1529.         xor     eax, eax
  1530. @@:
  1531.         pop     edx ecx ecx ebx edi esi
  1532.         ret
  1533.  
  1534. .error_block_read:
  1535.         pop     ebx
  1536. .error_get_inode_block:
  1537.         pop     ebx ebx
  1538. .error_inode_read:
  1539.         pop     ebx ebx
  1540. .error_block_write:
  1541.         pop     ebx
  1542.         jmp     @b
  1543.  
  1544. unlinkInode:
  1545. ; in: eax = directory inode number, esi = inode to unlink
  1546.         push    edi
  1547.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  1548.         call    readInode
  1549.         jc      .ret
  1550.         xor     ecx, ecx
  1551. .loop:
  1552.         push    ecx
  1553.         call    extfsGetExtent
  1554.         jc      .fail_loop
  1555.         mov     edi, eax
  1556.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  1557.         call    extfsReadBlock
  1558.         jc      .fail_loop
  1559. .first_dir_entry:   ; edi -> block
  1560.         cmp     [ebx+DIRENTRY.inodeNumber], esi
  1561.         jne     @f
  1562.         mov     [ebx+DIRENTRY.inodeNumber], 0
  1563.         mov     word [ebx+DIRENTRY.nameLength], 0   ; fileType = 0
  1564.         jmp     .write_block
  1565.  
  1566. .fail:
  1567.         pop     edi
  1568.         movi    eax, ERROR_FS_FAIL
  1569.         stc
  1570. .fail_loop:
  1571.         pop     edi
  1572.         jmp     .ret
  1573.  
  1574. .next:
  1575.         pop     ecx ecx
  1576.         inc     ecx
  1577.         jmp     .loop
  1578.  
  1579. @@:
  1580.         mov     edx, ebx
  1581.         add     edx, [ebp+EXTFS.bytesPerBlock]
  1582.         push    edx
  1583. @@:
  1584.         movzx   ecx, [ebx+DIRENTRY.entryLength]
  1585.         jecxz   .fail
  1586.         mov     edx, ebx
  1587.         add     ebx, ecx
  1588.         cmp     ebx, [esp]
  1589.         jnc     .next
  1590.         cmp     [ebx+DIRENTRY.inodeNumber], esi
  1591.         jnz     @b
  1592.         mov     cx, [ebx+DIRENTRY.entryLength]
  1593.         add     [edx+DIRENTRY.entryLength], cx
  1594.         pop     eax
  1595. .write_block:
  1596.         pop     eax
  1597.         mov     eax, edi
  1598.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  1599.         call    extfsWriteBlock
  1600. .ret:
  1601.         pop     edi
  1602.         ret
  1603.  
  1604. findInode:
  1605. ; in: esi -> path string in UTF-8
  1606. ;   out:
  1607. ; edi -> file name in UTF-8
  1608. ; esi = last inode number
  1609. ; [ebp+EXTFS.inodeBuffer] = last inode
  1610. ; ecx = parent inode number
  1611. ; CF=1 -> file not found, edi=0 -> error
  1612.         push    esi
  1613.         lea     esi, [ebp+EXTFS.rootInodeBuffer]
  1614.         lea     edi, [ebp+EXTFS.inodeBuffer]
  1615.         movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
  1616.         mov     edx, esi
  1617.         rep movsb
  1618.         pop     esi
  1619.         pushd   ebx 0 ROOT_INODE
  1620.         mov     edi, esi
  1621.         cmp     [edx+INODE.fileSize], 0
  1622.         jz      .not_found
  1623.         cmp     byte [esi], 0
  1624.         jnz     .next_path_part
  1625.         xor     eax, eax
  1626.         pop     esi ecx ebx
  1627.         ret
  1628.  
  1629. @@:
  1630.         pop     esi esi
  1631. .error:
  1632.         pop     esi ecx ebx
  1633.         xor     edi, edi
  1634.         stc
  1635.         ret
  1636.  
  1637. .next_path_part:
  1638.         push    [edx+INODE.fileSize]
  1639.         xor     ecx, ecx
  1640. .folder_block_cycle:
  1641.         push    ecx
  1642.         call    extfsGetExtent
  1643.         jc      @b
  1644.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  1645.         call    extfsReadBlock
  1646.         jc      @b
  1647.         push    esi edx
  1648.         mov     edx, ebx
  1649.         add     edx, [ebp+EXTFS.bytesPerBlock]
  1650. .start_rec:
  1651.         cmp     [ebx+DIRENTRY.inodeNumber], 0
  1652.         jz      .next_rec
  1653.         push    esi
  1654.         movzx   ecx, [ebx+DIRENTRY.nameLength]
  1655.         lea     edi, [ebx+DIRENTRY.name]
  1656.         repz cmpsb
  1657.         jz      .test_find
  1658. @@: ; doesn't match
  1659.         pop     esi
  1660. .next_rec:
  1661.         movzx   ecx, [ebx+DIRENTRY.entryLength]
  1662.         jecxz   .stop
  1663.         add     ebx, ecx
  1664.         cmp     ebx, edx
  1665.         jb      .start_rec
  1666.         jmp     .stop
  1667.  
  1668. .test_find:
  1669.         cmp     byte [esi], 0
  1670.         je      @f
  1671.         cmp     byte [esi], '/'
  1672.         jne     @b
  1673.         inc     esi
  1674. @@:
  1675.         pop     edx
  1676. .stop:
  1677.         pop     edx edi ecx eax
  1678. ; ebx -> matched directory entry, esi -> name without parent, or not changed
  1679.         cmp     edi, esi
  1680.         jnz     @f
  1681.         sub     eax, [ebp+EXTFS.bytesPerBlock]
  1682.         jle     .not_found
  1683.         push    eax
  1684.         inc     ecx
  1685.         jmp     .folder_block_cycle
  1686.  
  1687. @@:
  1688.         pop     eax
  1689.         mov     [esp], eax
  1690.         mov     eax, [ebx+DIRENTRY.inodeNumber]
  1691.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  1692.         push    eax
  1693.         call    readInode
  1694.         jc      .error
  1695.         cmp     byte [esi], 0
  1696.         je      .ret
  1697.         mov     edx, ebx
  1698.         movzx   eax, [ebx+INODE.accessMode]
  1699.         and     eax, TYPE_MASK
  1700.         cmp     eax, DIRECTORY
  1701.         jz      .next_path_part
  1702.         xor     edi, edi    ; path folder is a file
  1703.         jmp     @f
  1704.  
  1705. .not_found:
  1706.         mov     esi, edi
  1707.         call    strlen
  1708.         mov     al, '/'
  1709.         repnz scasb
  1710.         mov     edi, esi
  1711.         jnz     @f
  1712.         xor     edi, edi    ; path folder not found
  1713. @@:
  1714.         movi    eax, ERROR_FILE_NOT_FOUND
  1715.         stc
  1716. .ret:
  1717.         pop     esi ecx ebx
  1718.         ret
  1719.  
  1720. writeSuperblock:
  1721.         push    ebx
  1722.         mov     eax, 2
  1723.         lea     ebx, [ebp+EXTFS.superblock]
  1724.         call    fs_write32_sys
  1725.         pop     ebx
  1726.         ret
  1727.  
  1728. extfsWritingInit:
  1729.         movi    eax, ERROR_UNSUPPORTED_FS
  1730.         test    [ebp+EXTFS.mountType], READ_ONLY
  1731.         jnz     @f
  1732. ext_lock:
  1733.         lea     ecx, [ebp+EXTFS.Lock]
  1734.         jmp     mutex_lock
  1735.  
  1736. @@:
  1737.         pop     ebx
  1738.         xor     ebx, ebx
  1739.         ret
  1740.  
  1741. ext_unlock:
  1742.         lea     ecx, [ebp+EXTFS.Lock]
  1743.         jmp     mutex_unlock
  1744.  
  1745. ;----------------------------------------------------------------
  1746. ext_ReadFolder:
  1747.         call    ext_lock
  1748.         cmp     byte [esi], 0
  1749.         jz      .root_folder
  1750.         call    findInode
  1751.         jc      .error_ret
  1752.         lea     esi, [ebp+EXTFS.inodeBuffer]
  1753.         test    [esi+INODE.accessMode], FLAG_FILE
  1754.         jnz     .error_not_found
  1755.         jmp     @f
  1756.  
  1757. .root_folder:
  1758.         lea     esi, [ebp+EXTFS.rootInodeBuffer]
  1759.         lea     edi, [ebp+EXTFS.inodeBuffer]
  1760.         movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
  1761.         shr     ecx, 2
  1762.         push    edi
  1763.         rep movsd
  1764.         pop     esi
  1765. @@:
  1766.         cmp     [esi+INODE.fileSize], 0
  1767.         je      .error_empty_dir
  1768.         mov     edx, [ebx+16]
  1769.         push    edx         ; [edi+28] result buffer
  1770.         push    0           ; [edi+24] end of the current block in folder
  1771.         pushd   [ebx+12]    ; [edi+20] files to read
  1772.         pushd   [ebx+4]     ; [edi+16] first wanted file
  1773.         pushd   [ebx+8]     ; [edi+12] flags
  1774.         push    0           ; [edi+8]  read files
  1775.         push    0           ; [edi+4]  files in folder
  1776.         push    0           ; [edi]    current block index
  1777.         mov     edi, esp    ; edi -> local variables
  1778.         add     edx, 32
  1779.         xor     ecx, ecx
  1780.         call    extfsGetExtent
  1781.         jc      .error_get_block
  1782.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  1783.         call    extfsReadBlock
  1784.         jc      .error_get_block
  1785.         mov     eax, ebx
  1786.         add     eax, [ebp+EXTFS.bytesPerBlock]
  1787.         mov     [edi+24], eax
  1788.         mov     ecx, [edi+16]
  1789. .find_wanted_start:
  1790.         jecxz   .find_wanted_end
  1791. .find_wanted_cycle:
  1792.         cmp     [ebx+DIRENTRY.inodeNumber], 0
  1793.         jz      @f
  1794.         inc     dword [edi+4]
  1795.         dec     ecx
  1796. @@:
  1797.         movzx   eax, [ebx+DIRENTRY.entryLength]
  1798.         cmp     eax, 12     ; minimum entry length
  1799.         jb      .error_bad_len
  1800.         test    eax, 3      ; length must be aligned
  1801.         jnz     .error_bad_len
  1802.         sub     [esi+INODE.fileSize], eax
  1803.         add     ebx, eax
  1804.         cmp     ebx, [edi+24]
  1805.         jb      .find_wanted_start
  1806.         push    .find_wanted_start
  1807. .end_block: ; read next block
  1808.         cmp     [esi+INODE.fileSize], 0
  1809.         jle     .end_dir
  1810.         inc     dword [edi]
  1811.         push    ecx
  1812.         mov     ecx, [edi]
  1813.         call    extfsGetExtent
  1814.         jc      .error_get_block
  1815.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  1816.         call    extfsReadBlock
  1817.         jc      .error_get_block
  1818.         pop     ecx
  1819.         mov     eax, ebx
  1820.         add     eax, [ebp+EXTFS.bytesPerBlock]
  1821.         mov     [edi+24], eax
  1822.         ret
  1823.  
  1824. .wanted_end:
  1825.         loop    .find_wanted_cycle
  1826. .find_wanted_end:
  1827.         mov     ecx, [edi+20]
  1828. .wanted_start:
  1829.         jecxz   .wanted_end
  1830.         cmp     [ebx+DIRENTRY.inodeNumber], 0
  1831.         jz      .empty_rec
  1832.         inc     dword [edi+8]
  1833.         inc     dword [edi+4]
  1834.         push    ebx edi ecx esi edx edi
  1835.         pushd   [edi+12]
  1836.         mov     edi, edx
  1837.         xor     eax, eax
  1838.         mov     ecx, 40 / 4
  1839.         rep stosd
  1840.         popd    [edx+4] edi
  1841.         mov     eax, [ebx+DIRENTRY.inodeNumber]
  1842.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  1843.         call    readInode
  1844.         jc      .error_read_subinode
  1845.         mov     esi, ebx
  1846.         lea     edi, [edx+8]
  1847.         mov     eax, [ebx+INODE.inodeModified]
  1848.         sub     eax, 978307200  ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
  1849.         call    fsTime2bdfe
  1850.  
  1851.         mov     eax, [esi+INODE.accessedTime]
  1852.         sub     eax, 978307200
  1853.         call    fsTime2bdfe
  1854.  
  1855.         mov     eax, [esi+INODE.dataModified]
  1856.         sub     eax, 978307200
  1857.         call    fsTime2bdfe
  1858.         pop     edx
  1859.         or      dword [edx], KOS_DIRECTORY
  1860.         test    [esi+INODE.accessMode], FLAG_FILE
  1861.         jz      @f
  1862.         xor     dword [edx], KOS_DIRECTORY  ; mark as file
  1863.         mov     eax, [esi+INODE.fileSize]
  1864.         stosd
  1865.         mov     eax, [esi+INODE.fileSizeHigh]
  1866.         stosd
  1867. @@:
  1868.         mov     esi, [esp+12]
  1869.         movzx   ecx, [esi+DIRENTRY.nameLength]
  1870.         lea     esi, [esi+DIRENTRY.name]
  1871.         cmp     byte [esi], '.'
  1872.         jnz     @f
  1873.         or      byte [edx], KOS_HIDDEN
  1874. @@:
  1875.         lea     edi, [edx+40]
  1876.         cmp     byte [edx+4], 3
  1877.         jz      .utf8
  1878.         add     ecx, esi
  1879.         cmp     byte [edx+4], 2
  1880.         jz      .utf16
  1881. @@:
  1882.         call    utf8to16
  1883.         call    uni2ansi_char
  1884.         stosb
  1885.         cmp     esi, ecx
  1886.         jc      @b
  1887.         and     byte [edi], 0
  1888.         add     edx, 40+264
  1889. @@:
  1890.         pop     esi ecx edi ebx
  1891.         dec     ecx
  1892. .empty_rec:
  1893.         movzx   eax, [ebx+DIRENTRY.entryLength]
  1894.         cmp     eax, 12
  1895.         jb      .error_bad_len
  1896.         test    eax, 3
  1897.         jnz     .error_bad_len
  1898.         sub     [esi+INODE.fileSize], eax
  1899.         add     ebx, eax
  1900.         cmp     ebx, [edi+24]
  1901.         jb      .wanted_start
  1902.         push    .wanted_start
  1903.         jmp     .end_block
  1904.  
  1905. .utf8:
  1906.         rep movsb
  1907.         mov     byte [edi], 0
  1908.         add     edx, 40+520
  1909.         jmp     @b
  1910.  
  1911. .utf16:
  1912.         call    utf8to16
  1913.         stosw
  1914.         cmp     esi, ecx
  1915.         jc      .utf16
  1916.         and     word [edi], 0
  1917.         add     edx, 40+520
  1918.         jmp     @b
  1919.  
  1920. .end_dir:
  1921.         call    ext_unlock
  1922.         mov     edx, [edi+28]
  1923.         mov     ebx, [edi+8]
  1924.         mov     ecx, [edi+4]
  1925.         mov     dword [edx], 1  ; version
  1926.         mov     [edx+4], ebx
  1927.         mov     [edx+8], ecx
  1928.         lea     esp, [edi+32]
  1929.         mov     ecx, 20/4
  1930.         lea     edi, [edx+12]
  1931.         xor     eax, eax
  1932.         rep stosd
  1933.         ret
  1934.  
  1935. .error_bad_len:
  1936.         movi    eax, ERROR_FS_FAIL
  1937. .error_read_subinode:
  1938. .error_get_block:
  1939.         lea     esp, [edi+32]
  1940. .error_ret:
  1941.         or      ebx, -1
  1942.         push    eax
  1943.         call    ext_unlock
  1944.         pop     eax
  1945.         ret
  1946.  
  1947. .error_empty_dir:
  1948.         movi    eax, ERROR_FS_FAIL
  1949.         jmp     .error_ret
  1950.  
  1951. .error_not_found:
  1952.         movi    eax, ERROR_FILE_NOT_FOUND
  1953.         jmp     .error_ret
  1954.  
  1955. ;----------------------------------------------------------------
  1956. ext_ReadFile:
  1957.         call    ext_lock
  1958.         call    findInode
  1959.         pushd   0 eax
  1960.         jc      .ret
  1961.         lea     esi, [ebp+EXTFS.inodeBuffer]
  1962.         mov     byte [esp], ERROR_ACCESS_DENIED
  1963.         test    [esi+INODE.accessMode], FLAG_FILE
  1964.         jz      .ret    ; not a file
  1965.         mov     byte [esp], ERROR_END_OF_FILE
  1966.         mov     eax, [esi+INODE.fileSize]
  1967.         mov     edx, [esi+INODE.fileSizeHigh]
  1968.         sub     eax, [ebx+4]
  1969.         sbb     edx, [ebx+8]
  1970.         jc      .ret
  1971.         mov     ecx, [ebx+12]
  1972.         sub     eax, ecx
  1973.         sbb     edx, 0
  1974.         jc      @f
  1975.         xor     eax, eax
  1976.         mov     [esp], eax
  1977. @@:
  1978.         add     ecx, eax
  1979.         mov     eax, [ebx+4]
  1980.         mov     edx, [ebx+8]
  1981.         mov     edi, [ebx+16]
  1982.         div     [ebp+EXTFS.bytesPerBlock]
  1983.         test    edx, edx
  1984.         jz      .aligned
  1985. .piece:
  1986.         push    eax ecx
  1987.         mov     esi, edx
  1988.         mov     ecx, eax
  1989.         call    extfsGetExtent
  1990.         jc      .errorGet
  1991.         mov     ecx, [ebp+EXTFS.sectorsPerBlock]
  1992.         mul     ecx
  1993.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  1994.         call    fs_read64_sys
  1995.         test    eax, eax
  1996.         jnz     .errorRead
  1997.         pop     eax
  1998.         mov     ecx, [ebp+EXTFS.bytesPerBlock]
  1999.         sub     ecx, esi
  2000.         sub     eax, ecx
  2001.         jnc     @f
  2002.         add     ecx, eax
  2003.         xor     eax, eax
  2004. @@:
  2005.         add     esi, ebx
  2006.         add     [esp+8], ecx
  2007.         rep movsb
  2008.         mov     ecx, eax
  2009.         pop     eax
  2010.         inc     eax
  2011.         xor     edx, edx
  2012.         jecxz   .ret
  2013. .aligned:
  2014.         xchg    eax, ecx
  2015.         div     [ebp+EXTFS.bytesPerBlock]
  2016.         push    edx
  2017.         mov     edx, eax
  2018. .writeExtent:
  2019.         test    edx, edx
  2020.         jz      .end
  2021.         push    ecx
  2022.         call    extfsGetExtent
  2023.         jc      .errorGet
  2024.         sub     edx, ecx
  2025.         jnc     @f
  2026.         add     ecx, edx
  2027.         xor     edx, edx
  2028. @@:
  2029.         add     [esp], ecx
  2030.         imul    ecx, [ebp+EXTFS.sectorsPerBlock]
  2031.         mov     ebx, edi
  2032.         push    edx ecx
  2033.         mul     [ebp+EXTFS.sectorsPerBlock]
  2034.         call    fs_read64_sys
  2035.         pop     ecx edx
  2036.         test    eax, eax
  2037.         jnz     .errorRead
  2038.         shl     ecx, 9
  2039.         add     edi, ecx
  2040.         add     [esp+12], ecx
  2041.         pop     ecx
  2042.         jmp     .writeExtent
  2043.  
  2044. .end:
  2045.         mov     eax, ecx
  2046.         pop     ecx
  2047.         jecxz   .ret
  2048.         jmp     .piece
  2049.  
  2050. .errorRead:
  2051.         movi    eax, ERROR_DEVICE
  2052. .errorGet:
  2053.         pop     ebx ebx
  2054.         mov     [esp], eax
  2055. .ret:
  2056.         call    ext_unlock
  2057.         pop     eax ebx
  2058.         ret
  2059.  
  2060. ;----------------------------------------------------------------
  2061. ext_GetFileInfo:
  2062.         call    ext_lock
  2063.         cmp     byte [esi], 0
  2064.         jz      .is_root
  2065.         call    findInode
  2066.         lea     esi, [ebp+EXTFS.inodeBuffer]
  2067.         jnc     @f
  2068.         push    eax
  2069.         call    ext_unlock
  2070.         pop     eax
  2071.         ret
  2072.  
  2073. .is_root:
  2074.         mov     edi, esi
  2075.         lea     esi, [ebp+EXTFS.rootInodeBuffer]
  2076. @@:
  2077.         mov     edx, [ebx+16]
  2078.         mov     bl, [edi]
  2079.         xor     eax, eax
  2080.         mov     edi, edx
  2081.         mov     ecx, 40/4
  2082.         rep stosd
  2083.         cmp     bl, '.'
  2084.         jne     @f
  2085.         or      dword [edx], KOS_HIDDEN
  2086. @@:
  2087.         or      dword [edx], KOS_DIRECTORY
  2088.         test    [esi+INODE.accessMode], FLAG_FILE
  2089.         jz      @f
  2090.         xor     dword [edx], KOS_DIRECTORY  ; mark as file
  2091.         mov     eax, [esi+INODE.fileSize]
  2092.         mov     ebx, [esi+INODE.fileSizeHigh]
  2093.         mov     dword [edx+32], eax
  2094.         mov     dword [edx+36], ebx
  2095. @@:
  2096.         lea     edi, [edx+8]
  2097.         mov     eax, [esi+INODE.inodeModified]
  2098.         sub     eax, 978307200  ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
  2099.         call    fsTime2bdfe
  2100.  
  2101.         mov     eax, [esi+INODE.accessedTime]
  2102.         sub     eax, 978307200
  2103.         call    fsTime2bdfe
  2104.  
  2105.         mov     eax, [esi+INODE.dataModified]
  2106.         sub     eax, 978307200
  2107.         call    fsTime2bdfe
  2108.         call    ext_unlock
  2109.         xor     eax, eax
  2110.         ret
  2111.  
  2112. ;----------------------------------------------------------------
  2113. ext_SetFileInfo:
  2114.         call    extfsWritingInit
  2115.         call    findInode
  2116.         jc      @f
  2117.         push    esi
  2118.         mov     esi, [ebx+16]
  2119.         add     esi, 16
  2120.         lea     edi, [ebp+EXTFS.inodeBuffer]
  2121.         call    fsCalculateTime
  2122.         add     eax, 978307200  ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
  2123.         mov     [edi+INODE.accessedTime], eax
  2124.  
  2125.         add     esi, 8
  2126.         call    fsCalculateTime
  2127.         add     eax, 978307200
  2128.         mov     [edi+INODE.dataModified], eax
  2129.         mov     ebx, edi
  2130.         pop     eax
  2131.         call    writeInode
  2132. @@:
  2133.         push    eax
  2134.         jc      @f
  2135.         call    writeSuperblock
  2136.         mov     esi, [ebp+PARTITION.Disk]
  2137.         call    disk_sync
  2138. @@:
  2139.         call    ext_unlock
  2140.         pop     eax
  2141.         ret
  2142.  
  2143. ;----------------------------------------------------------------
  2144. ext_Delete:
  2145.         call    extfsWritingInit
  2146.         call    findInode
  2147.         jc      .error
  2148.         push    ecx
  2149.         movzx   edi, [ebp+EXTFS.inodeBuffer.accessMode]
  2150.         and     edi, TYPE_MASK
  2151.         cmp     edi, DIRECTORY
  2152.         jne     .file
  2153.         xor     ecx, ecx
  2154. .checkDirectory:
  2155.         push    ecx
  2156.         call    extfsGetExtent
  2157.         jc      .empty
  2158.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  2159.         call    extfsReadBlock
  2160.         jc      .error8
  2161.         mov     edx, ebx
  2162.         add     edx, [ebp+EXTFS.bytesPerBlock]
  2163. .dir_entry:
  2164.         movzx   ecx, [ebx+DIRENTRY.nameLength]
  2165.         mov     ax, word [ebx+DIRENTRY.name]
  2166.         jecxz   @f
  2167.         cmp     al, '.'
  2168.         jnz     .not_empty
  2169.         dec     ecx
  2170.         jz      @f
  2171.         cmp     al, ah
  2172.         jnz     .not_empty
  2173.         dec     ecx
  2174.         jnz     .not_empty
  2175. @@:
  2176.         mov     cx, [ebx+DIRENTRY.entryLength]
  2177.         jecxz   @f
  2178.         add     ebx, ecx
  2179.         cmp     ebx, edx
  2180.         jb      .dir_entry
  2181. @@:
  2182.         pop     ecx
  2183.         inc     ecx
  2184.         jmp     .checkDirectory
  2185.  
  2186. .not_empty:
  2187.         pop     eax eax
  2188.         push    ERROR_ACCESS_DENIED
  2189.         jmp     .ret
  2190.  
  2191. .error8:
  2192.         pop     ebx
  2193. .error4:
  2194.         pop     ebx
  2195. .error:
  2196.         push    eax
  2197.         jmp     .ret
  2198.  
  2199. .empty:
  2200.         pop     ecx ecx
  2201.         cmp     eax, ERROR_END_OF_FILE
  2202.         jnz     .error
  2203.         push    ecx
  2204. .file:
  2205.         mov     eax, ecx
  2206.         call    unlinkInode
  2207.         jc      .error4
  2208.         pop     eax
  2209.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  2210.         cmp     edi, DIRECTORY
  2211.         jnz     @f
  2212.         dec     [ebx+INODE.linksCount]
  2213.         call    writeInode
  2214. @@:
  2215.         mov     eax, esi
  2216.         call    readInode
  2217.         jc      .error
  2218.         dec     [ebx+INODE.linksCount]
  2219.         jz      @f
  2220.         cmp     edi, DIRECTORY
  2221.         jnz     .hardlinks
  2222. @@:
  2223.         push    esi edi
  2224.         xor     eax, eax
  2225.         xor     edx, edx
  2226.         call    extfsTruncateFile   ; free file's data
  2227.         movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
  2228.         lea     edi, [ebp+EXTFS.inodeBuffer]
  2229.         xor     eax, eax
  2230.         push    edi
  2231.         rep stosb
  2232.         call    fsGetTime
  2233.         pop     ebx edi esi
  2234.         add     eax, 978307200
  2235.         mov     [ebx+INODE.deletedTime], eax
  2236.         mov     eax, esi
  2237.         dec     eax
  2238.         xor     edx, edx
  2239.         div     [ebp+EXTFS.superblock.inodesPerGroup]
  2240.         push    edx
  2241.         mov     ebx, [ebp+EXTFS.descriptorTable]
  2242.         shl     eax, 5
  2243.         add     ebx, eax
  2244.         cmp     edi, DIRECTORY
  2245.         jnz     @f
  2246.         dec     [ebx+BGDESCR.directoriesCount]
  2247. @@:
  2248.         inc     [ebx+BGDESCR.inodesFree]
  2249.         push    [ebx+BGDESCR.inodeBitmap]
  2250.         call    extfsWriteDescriptor
  2251.         pop     eax
  2252.         mov     ebx, [ebp+EXTFS.tempBlockBuffer]
  2253.         mov     ecx, eax
  2254.         call    extfsReadBlock
  2255.         pop     edx
  2256.         jc      .error
  2257.         mov     eax, edx
  2258.         and     edx, 31
  2259.         shr     eax, 5
  2260.         shl     eax, 2
  2261.         add     eax, ebx
  2262.         btr     [eax], edx
  2263.         mov     eax, ecx
  2264.         call    extfsWriteBlock
  2265.         inc     [ebp+EXTFS.superblock.inodesFree]
  2266. .hardlinks:
  2267.         mov     eax, esi
  2268.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  2269.         call    writeInode
  2270.         push    eax
  2271.         call    writeSuperblock
  2272.         mov     esi, [ebp+PARTITION.Disk]
  2273.         call    disk_sync
  2274. .ret:
  2275.         call    ext_unlock
  2276.         xor     ebx, ebx
  2277.         pop     eax
  2278.         ret
  2279.  
  2280. ;----------------------------------------------------------------
  2281. ext_CreateFolder:
  2282.         call    extfsWritingInit
  2283.         call    findInode
  2284.         jnc     .success    ; exist
  2285.         test    edi, edi
  2286.         jz      .error
  2287.         mov     eax, esi
  2288.         call    extfsInodeAlloc
  2289.         jc      .error
  2290.         push    ebx esi edi
  2291.         lea     edi, [ebp+EXTFS.inodeBuffer]
  2292.         movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
  2293.         xor     eax, eax
  2294.         rep stosb
  2295.         call    fsGetTime
  2296.         add     eax, 978307200
  2297.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  2298.         mov     [ebx+INODE.accessedTime], eax
  2299.         mov     [ebx+INODE.dataModified], eax
  2300.         pop     edi esi edx
  2301. ; edx = allocated inode number, edi -> filename, esi = parent inode number
  2302.         mov     [ebx+INODE.accessMode], DIRECTORY or PERMISSIONS
  2303.         mov     eax, edx
  2304.         call    writeInode
  2305.         jc      .error
  2306. ; link to self
  2307.         push    edx esi
  2308.         mov     eax, edx
  2309.         mov     ebx, eax
  2310.         mov     dl, DIR_DIRECTORY
  2311.         mov     esi, self_link
  2312.         call    linkInode
  2313.         pop     esi edx
  2314.         jc      .error
  2315. ; link to parent
  2316.         push    edx esi
  2317.         mov     eax, ebx
  2318.         mov     ebx, esi
  2319.         mov     dl, DIR_DIRECTORY
  2320.         mov     esi, parent_link
  2321.         call    linkInode
  2322.         pop     esi edx
  2323.         jc      .error
  2324. ; link parent to child
  2325.         mov     eax, esi
  2326.         mov     ebx, edx
  2327.         mov     esi, edi
  2328.         mov     dl, DIR_DIRECTORY
  2329.         call    linkInode
  2330.         jc      .error
  2331.         mov     eax, ebx
  2332.         dec     eax
  2333.         xor     edx, edx
  2334.         div     [ebp+EXTFS.superblock.inodesPerGroup]
  2335.         mov     ebx, [ebp+EXTFS.descriptorTable]
  2336.         shl     eax, 5
  2337.         add     ebx, eax
  2338.         inc     [ebx+BGDESCR.directoriesCount]
  2339.         call    extfsWriteDescriptor
  2340. .success:
  2341. .error:
  2342.         push    eax
  2343.         call    writeSuperblock
  2344.         mov     esi, [ebp+PARTITION.Disk]
  2345.         call    disk_sync
  2346.         call    ext_unlock
  2347.         pop     eax
  2348.         ret
  2349.  
  2350. self_link   db ".", 0
  2351. parent_link db "..", 0
  2352.  
  2353. ;----------------------------------------------------------------
  2354. ext_CreateFile:
  2355.         call    extfsWritingInit
  2356.         pushd   0 0 ebx
  2357.         call    findInode
  2358.         jnc     .exist
  2359.         test    edi, edi
  2360.         jz      .error
  2361.         mov     eax, esi
  2362.         call    extfsInodeAlloc
  2363.         jc      .error
  2364.         push    ebx ebx esi edi
  2365.         lea     edi, [ebp+EXTFS.inodeBuffer]
  2366.         movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
  2367.         xor     eax, eax
  2368.         rep stosb
  2369.         call    fsGetTime
  2370.         add     eax, 978307200
  2371.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  2372.         mov     [ebx+INODE.accessedTime], eax
  2373.         mov     [ebx+INODE.dataModified], eax
  2374.         pop     edi esi edx
  2375. ; edx = allocated inode number, edi -> filename, esi = parent inode number
  2376.         mov     [ebx+INODE.accessMode], FLAG_FILE or PERMISSIONS
  2377.         mov     eax, edx
  2378.         call    writeInode
  2379.         jc      .error2
  2380. ; link parent to child
  2381.         mov     eax, esi
  2382.         mov     ebx, edx
  2383.         mov     esi, edi
  2384.         mov     dl, DIR_FLAG_FILE
  2385.         call    linkInode
  2386.         jc      .error2
  2387.         pop     esi ebx
  2388.         mov     eax, [ebx+12]
  2389.         xor     edx, edx
  2390.         jmp     ext_WriteFile.start
  2391.  
  2392. .exist:
  2393.         movi    eax, ERROR_ACCESS_DENIED
  2394.         test    [ebp+EXTFS.inodeBuffer.accessMode], FLAG_FILE
  2395.         jz      .error  ; not a file
  2396.         pop     ebx
  2397.         mov     eax, [ebx+12]
  2398.         xor     edx, edx
  2399.         push    eax edx ebx esi
  2400.         call    extfsTruncateFile
  2401.         pop     esi ebx edx eax
  2402.         jmp     ext_WriteFile.start
  2403.  
  2404. .error2:
  2405.         pop     ebx
  2406. .error:
  2407.         push    eax
  2408.         call    ext_unlock
  2409.         pop     eax ebx ebx ebx
  2410.         ret
  2411.  
  2412. ;----------------------------------------------------------------
  2413. ext_WriteFile:
  2414.         call    extfsWritingInit
  2415.         call    findInode
  2416.         pushd   0 eax
  2417.         jc      .ret
  2418.         mov     byte [esp], ERROR_ACCESS_DENIED
  2419.         test    [ebp+EXTFS.inodeBuffer.accessMode], FLAG_FILE
  2420.         jz      .ret    ; not a file
  2421.         mov     byte [esp], 0
  2422.         mov     eax, [ebx+4]
  2423.         mov     edx, [ebx+8]
  2424.         add     eax, [ebx+12]
  2425.         adc     edx, 0
  2426. .start:
  2427.         push    esi
  2428.         mov     ecx, esi
  2429.         call    extfsExtendFile
  2430.         jc      .errorExtend
  2431.         mov     eax, [ebx+4]
  2432.         mov     edx, [ebx+8]
  2433.         mov     ecx, [ebx+12]
  2434.         mov     esi, [ebx+16]
  2435. .write:
  2436.         div     [ebp+EXTFS.bytesPerBlock]
  2437.         test    edx, edx
  2438.         jz      .aligned
  2439. .piece:
  2440.         mov     ebx, ecx
  2441.         mov     edi, edx
  2442.         mov     ecx, eax
  2443.         push    eax
  2444.         call    extfsGetExtent
  2445.         jc      .errorGet
  2446.         mov     ecx, [ebp+EXTFS.sectorsPerBlock]
  2447.         mul     ecx
  2448.         push    ecx eax ebx
  2449.         mov     ebx, [ebp+EXTFS.mainBlockBuffer]
  2450.         call    fs_read64_sys
  2451.         test    eax, eax
  2452.         jnz     .errorDevice
  2453.         pop     eax
  2454.         mov     ecx, [ebp+EXTFS.bytesPerBlock]
  2455.         sub     ecx, edi
  2456.         sub     eax, ecx
  2457.         jnc     @f
  2458.         add     ecx, eax
  2459.         xor     eax, eax
  2460. @@:
  2461.         add     edi, ebx
  2462.         add     [esp+20], ecx
  2463.         rep movsb
  2464.         mov     edi, eax
  2465.         pop     eax ecx
  2466.         xor     edx, edx
  2467.         call    fs_write64_sys
  2468.         mov     ecx, edi
  2469.         pop     eax
  2470.         inc     eax
  2471.         xor     edx, edx
  2472.         jecxz   .done
  2473. .aligned:
  2474.         xchg    eax, ecx
  2475.         div     [ebp+EXTFS.bytesPerBlock]
  2476.         push    edx
  2477.         mov     edx, eax
  2478. .writeExtent:
  2479.         test    edx, edx
  2480.         jz      .end
  2481.         push    ecx
  2482.         call    extfsGetExtent
  2483.         jc      .errorGet2
  2484.         sub     edx, ecx
  2485.         jnc     @f
  2486.         add     ecx, edx
  2487.         xor     edx, edx
  2488. @@:
  2489.         add     [esp], ecx
  2490.         imul    ecx, [ebp+EXTFS.sectorsPerBlock]
  2491.         mov     ebx, esi
  2492.         push    edx ecx
  2493.         mul     [ebp+EXTFS.sectorsPerBlock]
  2494.         call    fs_write64_sys
  2495.         test    eax, eax
  2496.         jnz     .errorDevice
  2497.         pop     ebx edx ecx
  2498.         shl     ebx, 9
  2499.         add     esi, ebx
  2500.         add     [esp+12], ebx
  2501.         jmp     .writeExtent
  2502.  
  2503. .end:
  2504.         mov     eax, ecx
  2505.         pop     ecx
  2506.         jecxz   .done
  2507.         jmp     .piece
  2508.  
  2509. .errorDevice:
  2510.         pop     eax eax
  2511.         movi    eax, ERROR_DEVICE
  2512. .errorGet2:
  2513.         pop     ebx
  2514. .errorGet:
  2515.         pop     ebx
  2516. .errorExtend:
  2517.         mov     [esp+4], eax
  2518. .done:
  2519.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  2520.         pop     eax
  2521.         call    writeInode
  2522.         add     [esp], eax
  2523.         call    writeSuperblock
  2524.         mov     esi, [ebp+PARTITION.Disk]
  2525.         call    disk_sync
  2526. .ret:
  2527.         call    ext_unlock
  2528.         pop     eax ebx
  2529.         ret
  2530.  
  2531. .erase:
  2532.         push    eax eax edi
  2533.         mov     eax, ebx
  2534.         jmp     .write
  2535.  
  2536. ;----------------------------------------------------------------
  2537. ext_SetFileEnd:
  2538.         call    extfsWritingInit
  2539.         call    findInode
  2540.         jc      .error2
  2541.         lea     edi, [ebp+EXTFS.inodeBuffer]
  2542.         movi    eax, ERROR_ACCESS_DENIED
  2543.         test    [edi+INODE.accessMode], FLAG_FILE
  2544.         jz      .error2 ; not a file
  2545.         mov     eax, [ebx+4]
  2546.         mov     edx, [ebx+8]
  2547.         mov     ebx, [edi+INODE.fileSize]
  2548.         mov     ecx, [edi+INODE.fileSizeHigh]
  2549.         push    esi ecx
  2550.         cmp     ebx, eax
  2551.         sbb     ecx, edx
  2552.         mov     ecx, esi
  2553.         jnc     @f
  2554.         call    extfsExtendFile
  2555.         pop     esi
  2556.         jc      .error
  2557.         mov     eax, [edi+INODE.fileSize]
  2558.         mov     edx, [edi+INODE.fileSizeHigh]
  2559.         sub     eax, ebx
  2560.         sbb     edx, esi
  2561.         jnz     .done
  2562.         cmp     eax, 1000001h
  2563.         jnc     .done
  2564.         push    eax
  2565.         stdcall kernel_alloc, eax
  2566.         pop     ecx
  2567.         test    eax, eax
  2568.         jz      .error
  2569.         push    ecx
  2570.         add     ecx, 3
  2571.         shr     ecx, 2
  2572.         mov     edx, esi
  2573.         mov     esi, eax
  2574.         mov     edi, eax
  2575.         xor     eax, eax
  2576.         rep stosd
  2577.         pop     ecx edi
  2578.         push    esi
  2579.         call    ext_WriteFile.erase
  2580.         call    kernel_free
  2581.         xor     eax, eax
  2582.         ret
  2583.  
  2584. @@:
  2585.         call    extfsTruncateFile
  2586.         pop     eax
  2587. .done:
  2588.         xor     eax, eax
  2589. .error:
  2590.         xchg    eax, [esp]
  2591.         lea     ebx, [ebp+EXTFS.inodeBuffer]
  2592.         call    writeInode
  2593.         add     [esp], eax
  2594.         call    writeSuperblock
  2595.         mov     esi, [ebp+PARTITION.Disk]
  2596.         call    disk_sync
  2597.         pop     eax
  2598. .error2:
  2599.         push    eax
  2600.         call    ext_unlock
  2601.         pop     eax
  2602.         ret
  2603.