Subversion Repositories Kolibri OS

Rev

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