Subversion Repositories Kolibri OS

Rev

Rev 2455 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2011. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  FAT32.INC                                                      ;;
  7. ;;                                                                 ;;
  8. ;;  FAT16/32 functions for KolibriOS                               ;;
  9. ;;                                                                 ;;
  10. ;;  Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it          ;;
  11. ;;                                                                 ;;
  12. ;;  See file COPYING for details                                   ;;
  13. ;;  04.02.2007 LFN create folder - diamond                         ;;
  14. ;;  08.10.2006 LFN delete file/folder - diamond                    ;;
  15. ;;  20.08.2006 LFN set file size (truncate/extend) - diamond       ;;
  16. ;;  17.08.2006 LFN write/append to file - diamond                  ;;
  17. ;;  23.06.2006 LFN start application - diamond                     ;;
  18. ;;  15.06.2006 LFN get/set file/folder info - diamond              ;;
  19. ;;  27.05.2006 LFN create/rewrite file - diamond                   ;;
  20. ;;  04.05.2006 LFN read folder - diamond                           ;;
  21. ;;  29.04.2006 Elimination of hangup after the                     ;;
  22. ;;             expiration hd_wait_timeout -  Mario79               ;;
  23. ;;  23.04.2006 LFN read file - diamond                             ;;
  24. ;;  28.01.2006 find all Fat16/32 partition in all input point      ;;
  25. ;;             to MBR, see file part_set.inc - Mario79             ;;
  26. ;;  15.01.2005 get file size/attr/date, file_append - ATV          ;;
  27. ;;  04.12.2004 skip volume label, file delete bug fixed - ATV      ;;
  28. ;;  29.11.2004 get_free_FAT changed, append dir bug fixed - ATV    ;;
  29. ;;  23.11.2004 don't allow overwrite dir with file - ATV           ;;
  30. ;;  18.11.2004 get_disk_info and more error codes - ATV            ;;
  31. ;;  17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV      ;;
  32. ;;  10.11.2004 removedir clear whole directory structure - ATV     ;;
  33. ;;  08.11.2004 rename - ATV                                        ;;
  34. ;;  30.10.2004 file_read return also dirsize in bytes - ATV        ;;
  35. ;;  20.10.2004 Makedir/Removedir - ATV                             ;;
  36. ;;  14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx)         ;;
  37. ;;  06.9.2004  Fix free space by Mario79 added - MH                ;;
  38. ;;  24.5.2004  Write back buffer for File_write -VT                ;;
  39. ;;  20.5.2004  File_read function to work with syscall 58 - VT     ;;
  40. ;;  30.3.2004  Error parameters at function return - VT            ;;
  41. ;;  01.5.2002  Bugfix in device write - VT                         ;;
  42. ;;  20.5.2002  Hd status check - VT                                ;;
  43. ;;  29.6.2002  Improved fat32 verification - VT                    ;;
  44. ;;                                                                 ;;
  45. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  46.  
  47. $Revision: 2643 $
  48.  
  49.  
  50. cache_max equ 1919      ; max. is 1919*512+0x610000=0x6ffe00
  51.  
  52. ERROR_SUCCESS        = 0
  53. ERROR_DISK_BASE      = 1
  54. ERROR_UNSUPPORTED_FS = 2
  55. ERROR_UNKNOWN_FS     = 3
  56. ERROR_PARTITION      = 4
  57. ERROR_FILE_NOT_FOUND = 5
  58. ERROR_END_OF_FILE    = 6
  59. ERROR_MEMORY_POINTER = 7
  60. ERROR_DISK_FULL      = 8
  61. ERROR_FAT_TABLE      = 9
  62. ERROR_ACCESS_DENIED  = 10
  63. ERROR_DEVICE         = 11
  64.  
  65. PUSHAD_EAX equ [esp+28]
  66. PUSHAD_ECX equ [esp+24]
  67. PUSHAD_EDX equ [esp+20]
  68. PUSHAD_EBX equ [esp+16]
  69. PUSHAD_EBP equ [esp+8]
  70. PUSHAD_ESI equ [esp+4]
  71. PUSHAD_EDI equ [esp+0]
  72.  
  73. ; Internal data for every FAT partition.
  74. struct FAT
  75. p       PARTITION       ; must be the first item
  76. fs_type              db ?
  77. fat16_root           db 0       ; flag for fat16 rootdir
  78. fat_change           db 0       ; 1=fat has changed
  79.                      db ?       ; alignment
  80. Lock                 MUTEX ?    ; currently operations with one partition
  81.                                  ; can not be executed in parallel since the
  82.                                  ; legacy code is not ready; this mutex guards
  83.                                  ; all operations
  84. SECTORS_PER_FAT      dd 0x1f3a
  85. NUMBER_OF_FATS       dd 0x2
  86. SECTORS_PER_CLUSTER  dd 0x8
  87. BYTES_PER_SECTOR     dd 0x200   ; Note: if BPS <> 512 need lots of changes
  88. ROOT_CLUSTER         dd 2       ; first rootdir cluster
  89. FAT_START            dd 0       ; start of fat table
  90. ROOT_START           dd 0       ; start of rootdir (only fat16)
  91. ROOT_SECTORS         dd 0       ; count of rootdir sectors (only fat16)
  92. DATA_START           dd 0       ; start of data area (=first cluster 2)
  93. LAST_CLUSTER         dd 0       ; last availabe cluster
  94. ADR_FSINFO           dd 0       ; used only by fat32
  95.  
  96. fatRESERVED          dd 0x0FFFFFF6
  97. fatBAD               dd 0x0FFFFFF7
  98. fatEND               dd 0x0FFFFFF8
  99. fatMASK              dd 0x0FFFFFFF
  100.  
  101. fatStartScan         dd 2
  102.  
  103. cluster_tmp          dd 0       ; used by analyze_directory
  104.                                 ; and analyze_directory_to_write
  105.  
  106. longname_sec1        dd 0       ; used by analyze_directory to save 2 previous
  107. longname_sec2        dd 0       ; directory sectors for delete long filename
  108.  
  109. fat_in_cache         dd -1
  110.  
  111. fat_cache            rb 512
  112. buffer               rb 512
  113. fsinfo_buffer        rb 512
  114. ends
  115.  
  116. uglobal
  117. align 4
  118. partition_count      dd 0       ; partitions found by set_FAT32_variables
  119.  
  120. hd_error             dd 0       ; set by wait_for_sector_buffer
  121. hd_setup             dd 0
  122. hd_wait_timeout      dd 0
  123.  
  124. cache_search_start   dd 0       ; used by find_empty_slot
  125. endg
  126.  
  127. uglobal
  128. align 4
  129.  Sector512:                      ; label for dev_hdcd.inc
  130.   buffer:
  131.                 times 512 db 0
  132. endg
  133.  
  134. iglobal
  135. align 4
  136. fat_user_functions:
  137.         dd      (fat_user_functions_end - fat_user_functions - 4) / 4
  138.         dd      fat_Read
  139.         dd      fat_ReadFolder
  140.         dd      fat_Rewrite
  141.         dd      fat_Write
  142.         dd      fat_SetFileEnd
  143.         dd      fat_GetFileInfo
  144.         dd      fat_SetFileInfo
  145.         dd      0
  146.         dd      fat_Delete
  147.         dd      fat_CreateFolder
  148. fat_user_functions_end:
  149. endg
  150.  
  151. ; these labels are located before the main function to make
  152. ; most of jumps to these be short
  153. fat_create_partition.free_return0:
  154.         push    ebx
  155.         mov     eax, ebp
  156.         call    free
  157.         pop     ebx
  158.         pop     ebp
  159. fat_create_partition.return0:
  160.         xor     eax, eax
  161.         ret
  162. fat_create_partition:
  163. ; bootsector must have been successfully read
  164.         cmp     dword [esp+4], 1
  165.         jnz     .return0
  166. ; bootsector signature must be correct
  167.         cmp     word [ebx+0x1fe], 0xaa55
  168.         jnz     .return0
  169. ; sectors per cluster must be nonzero
  170.         cmp     byte [ebx+0xd], 0
  171.         jz      .return0
  172. ; bytes per sector must be 0x200
  173.         cmp     word [ebx+0xb], 0x200
  174.         jnz     .return0
  175. ; number of fats must be nonzero
  176.         cmp     byte [ebx+0x10], 0
  177.         jz      .return0
  178. ; The only reason to be invalid partition now is FAT12. Since the test for
  179. ; FAT size requires knowledge of some calculated values, which are also used
  180. ; in the normal operation, let's hope for the best and allocate data now; if
  181. ; it will prove wrong, just deallocate it.
  182.         push    ebx
  183.         push    sizeof.FAT
  184.         pop     eax
  185.         call    malloc
  186.         pop     ebx
  187.         test    eax, eax
  188.         jz      .return0
  189.         mov     ecx, [ebp+8]
  190.         mov     dword [eax+FAT.p.FirstSector], ecx
  191.         mov     ecx, [ebp+12]
  192.         mov     dword [eax+FAT.p.FirstSector+4], ecx
  193.         mov     ecx, [ebp+16]
  194.         mov     dword [eax+FAT.p.Length], ecx
  195.         mov     ecx, [ebp+20]
  196.         mov     dword [eax+FAT.p.Length+4], ecx
  197.         mov     [eax+FAT.p.Disk], esi
  198.         mov     [eax+FAT.p.FSUserFunctions], fat_user_functions
  199.         or      [eax+FAT.fat_in_cache], -1
  200.         mov     [eax+FAT.fat_change], 0
  201.         push    ebp
  202.         mov     ebp, eax
  203.  
  204.         lea     ecx, [ebp+FAT.Lock]
  205.         call    mutex_init
  206.  
  207.         movzx   eax, word [ebx+0xe]     ; sectors reserved
  208.         mov     [ebp+FAT.FAT_START], eax
  209.  
  210.         movzx   eax, byte [ebx+0xd]     ; sectors per cluster
  211.         mov     [ebp+FAT.SECTORS_PER_CLUSTER], eax
  212.  
  213.         movzx   ecx, word [ebx+0xb]     ; bytes per sector
  214.         mov     [ebp+FAT.BYTES_PER_SECTOR], ecx
  215.  
  216.         movzx   eax, word [ebx+0x11]    ; count of rootdir entries (=0 fat32)
  217.         shl     eax, 5                  ; mul 32
  218.         dec     ecx
  219.         add     eax, ecx                ; round up if not equal count
  220.         inc     ecx                     ; bytes per sector
  221.         xor     edx, edx
  222.         div     ecx
  223.         mov     [ebp+FAT.ROOT_SECTORS], eax     ; count of rootdir sectors
  224.  
  225.         movzx   eax, word [ebx+0x16]    ; sectors per fat <65536
  226.         test    eax, eax
  227.         jnz     @f
  228.         mov     eax, [ebx+0x24]         ; sectors per fat
  229. @@:
  230.         mov     [ebp+FAT.SECTORS_PER_FAT], eax
  231.  
  232.         movzx   eax, byte [ebx+0x10]    ; number of fats
  233.         mov     [ebp+FAT.NUMBER_OF_FATS], eax
  234.         imul    eax, [ebp+FAT.SECTORS_PER_FAT]
  235.         add     eax, [ebp+FAT.FAT_START]
  236.         mov     [ebp+FAT.ROOT_START], eax       ; rootdir = fat_start + fat_size * fat_count
  237.         add     eax, [ebp+FAT.ROOT_SECTORS]     ; rootdir sectors should be 0 on fat32
  238.         mov     [ebp+FAT.DATA_START], eax       ; data area = rootdir + rootdir_size
  239.  
  240.         movzx   eax, word [ebx+0x13]    ; total sector count <65536
  241.         test    eax, eax
  242.         jnz     @f
  243.         mov     eax, [ebx+0x20]         ; total sector count
  244. @@:
  245.         mov     dword [ebp+FAT.p.Length], eax
  246.         and     dword [ebp+FAT.p.Length+4], 0
  247.         sub     eax, [ebp+FAT.DATA_START]       ; eax = count of data sectors
  248.         xor     edx, edx
  249.         div     [ebp+FAT.SECTORS_PER_CLUSTER]
  250.         inc     eax
  251.         mov     [ebp+FAT.LAST_CLUSTER], eax
  252.         dec     eax                     ; cluster count
  253.         mov     [ebp+FAT.fatStartScan], 2
  254.  
  255.         ; limits by Microsoft Hardware White Paper v1.03
  256.         cmp     eax, 4085               ; 0xff5
  257.         jb      .free_return0           ; fat12 not supported
  258.         cmp     eax, 65525              ; 0xfff5
  259.         jb      .fat16
  260. .fat32:
  261.         mov     eax, [ebx+0x2c]         ; rootdir cluster
  262.         mov     [ebp+FAT.ROOT_CLUSTER], eax
  263.         movzx   eax, word [ebx+0x30]
  264.         mov     [ebp+FAT.ADR_FSINFO], eax
  265.         push    ebx
  266.         add     ebx, 512
  267.         call    fs_read32_sys
  268.         test    eax, eax
  269.         jnz     @f
  270.         mov     eax, [ebx+0x1ec]
  271.         cmp     eax, -1
  272.         jz      @f
  273.         mov     [ebp+FAT.fatStartScan], eax
  274. @@:
  275.         pop     ebx
  276.         mov     [ebp+FAT.fatRESERVED], 0x0FFFFFF6
  277.         mov     [ebp+FAT.fatBAD], 0x0FFFFFF7
  278.         mov     [ebp+FAT.fatEND], 0x0FFFFFF8
  279.         mov     [ebp+FAT.fatMASK], 0x0FFFFFFF
  280.         mov     al, 32
  281.         mov     [fs_type], al
  282.         mov     [ebp+FAT.fs_type], al
  283.         mov     eax, ebp
  284.         pop     ebp
  285.         ret
  286. .fat16:
  287.         and     [ebp+FAT.ROOT_CLUSTER], 0
  288.         mov     [ebp+FAT.fatRESERVED], 0x0000FFF6
  289.         mov     [ebp+FAT.fatBAD], 0x0000FFF7
  290.         mov     [ebp+FAT.fatEND], 0x0000FFF8
  291.         mov     [ebp+FAT.fatMASK], 0x0000FFFF
  292.         mov     al, 16
  293.         mov     [fs_type], al
  294.         mov     [ebp+FAT.fs_type], al
  295.         mov     eax, ebp
  296.         pop     ebp
  297.         ret
  298.  
  299. set_FAT:
  300. ;--------------------------------
  301. ; input  : EAX = cluster
  302. ;          EDX = value to save
  303. ;          EBP = pointer to FAT structure
  304. ; output : EDX = old value
  305. ;--------------------------------
  306. ; out: CF set <=> error
  307.         push    eax ebx esi
  308.  
  309.         cmp     eax, 2
  310.         jb      sfc_error
  311.         cmp     eax, [ebp+FAT.LAST_CLUSTER]
  312.         ja      sfc_error
  313.         cmp     [ebp+FAT.fs_type], 16
  314.         je      sfc_1
  315.         add     eax, eax
  316.   sfc_1:
  317.         add     eax, eax
  318.         mov     esi, 511
  319.         and     esi, eax        ; esi = position in fat sector
  320.         shr     eax, 9          ; eax = fat sector
  321.         add     eax, [ebp+FAT.FAT_START]
  322.         lea     ebx, [ebp+FAT.fat_cache]
  323.  
  324.         cmp     eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
  325.         je      sfc_in_cache    ; yes
  326.  
  327.         cmp     [ebp+FAT.fat_change], 0; is fat changed?
  328.         je      sfc_no_change   ; no
  329.         call    write_fat_sector; yes. write it into disk
  330.         jc      sfc_error
  331.  
  332.   sfc_no_change:
  333.         mov     [ebp+FAT.fat_in_cache], eax; save fat sector
  334.         call    fs_read32_sys
  335.         test    eax, eax
  336.         jne     sfc_error
  337.  
  338.  
  339.   sfc_in_cache:
  340.         cmp     [ebp+FAT.fs_type], 16
  341.         jne     sfc_test32
  342.  
  343.   sfc_set16:
  344.         xchg    [ebx+esi], dx   ; save new value and get old value
  345.         jmp     sfc_write
  346.  
  347.   sfc_test32:
  348.         mov     eax, [ebp+FAT.fatMASK]
  349.  
  350.   sfc_set32:
  351.         and     edx, eax
  352.         xor     eax, -1         ; mask for high bits
  353.         and     eax, [ebx+esi]  ; get high 4 bits
  354.         or      eax, edx
  355.         mov     edx, [ebx+esi]  ; get old value
  356.         mov     [ebx+esi], eax  ; save new value
  357.  
  358.   sfc_write:
  359.         mov     [ebp+FAT.fat_change], 1; fat has changed
  360.  
  361.   sfc_nonzero:
  362.         and     edx, [ebp+FAT.fatMASK]
  363.  
  364.   sfc_return:
  365.         pop     esi ebx eax
  366.         ret
  367.   sfc_error:
  368.         stc
  369.         jmp     sfc_return
  370.  
  371.  
  372. get_FAT:
  373. ;--------------------------------
  374. ; input  : EAX = cluster
  375. ;          EBP = pointer to FAT structure
  376. ; output : EAX = next cluster
  377. ;--------------------------------
  378. ; out: CF set <=> error
  379.         push    ebx esi
  380.  
  381.         cmp     [ebp+FAT.fs_type], 16
  382.         je      gfc_1
  383.         add     eax, eax
  384.   gfc_1:
  385.         add     eax, eax
  386.         mov     esi, 511
  387.         and     esi, eax        ; esi = position in fat sector
  388.         shr     eax, 9          ; eax = fat sector
  389.         add     eax, [ebp+FAT.FAT_START]
  390.         lea     ebx, [ebp+FAT.fat_cache]
  391.  
  392.         cmp     eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
  393.         je      gfc_in_cache
  394.  
  395.         cmp     [ebp+FAT.fat_change], 0; is fat changed?
  396.         je      gfc_no_change   ; no
  397.         call    write_fat_sector; yes. write it into disk
  398.         jc      hd_error_01
  399.  
  400.   gfc_no_change:
  401.         mov     [ebp+FAT.fat_in_cache], eax
  402.         call    fs_read32_sys
  403.         test    eax, eax
  404.         jne     hd_error_01
  405.  
  406.   gfc_in_cache:
  407.         mov     eax, [ebx+esi]
  408.         and     eax, [ebp+FAT.fatMASK]
  409.   gfc_return:
  410.         pop     esi ebx
  411.         ret
  412.  hd_error_01:
  413.         stc
  414.         jmp     gfc_return
  415.  
  416.  
  417. get_free_FAT:
  418. ;-----------------------------------------------------------
  419. ; output : if CARRY=0 EAX = # first cluster found free
  420. ;          if CARRY=1 disk full
  421. ; Note   : for more speed need to use fat_cache directly
  422. ;-----------------------------------------------------------
  423.         push    ecx
  424.         mov     ecx, [ebp+FAT.LAST_CLUSTER]; counter for full disk
  425.         sub     ecx, 2
  426.         mov     eax, [ebp+FAT.fatStartScan]
  427.         cmp     eax, 2
  428.         jb      gff_reset
  429.  
  430.   gff_test:
  431.         cmp     eax, [ebp+FAT.LAST_CLUSTER]; if above last cluster start at cluster 2
  432.         jbe     gff_in_range
  433.   gff_reset:
  434.         mov     eax, 2
  435.  
  436.   gff_in_range:
  437.         push    eax
  438.         call    get_FAT         ; get cluster state
  439.         jc      gff_not_found_1
  440.  
  441.         test    eax, eax        ; is it free?
  442.         pop     eax
  443.         je      gff_found       ; yes
  444.         inc     eax             ; next cluster
  445.         dec     ecx             ; is all checked?
  446.         jns     gff_test        ; no
  447.  
  448.   gff_not_found:
  449.         pop     ecx             ; yes. disk is full
  450.         stc
  451.         ret
  452.  
  453.   gff_not_found_1:
  454.         pop     eax
  455.         jmp     gff_not_found
  456.  
  457.   gff_found:
  458.         lea     ecx, [eax+1]
  459.         mov     [ebp+FAT.fatStartScan], ecx
  460.         pop     ecx
  461.         clc
  462.         ret
  463.  
  464.  
  465. write_fat_sector:
  466. ;-----------------------------------------------------------
  467. ; write changed fat to disk
  468. ;-----------------------------------------------------------
  469.         push    eax ebx ecx
  470.  
  471.         mov     [ebp+FAT.fat_change], 0
  472.         mov     eax, [ebp+FAT.fat_in_cache]
  473.         cmp     eax, -1
  474.         jz      write_fat_not_used
  475.         lea     ebx, [ebp+FAT.fat_cache]
  476.         mov     ecx, [ebp+FAT.NUMBER_OF_FATS]
  477.  
  478.   write_next_fat:
  479.         push    eax
  480.         call    fs_write32_sys
  481.         test    eax, eax
  482.         pop     eax
  483.         jnz     write_fat_not_used
  484.  
  485.         add     eax, [ebp+FAT.SECTORS_PER_FAT]
  486.         dec     ecx
  487.         jnz     write_next_fat
  488.  
  489.   write_fat_not_used:
  490.         pop     ecx ebx eax
  491.         ret
  492.  
  493.  
  494.  
  495.  
  496.  
  497. bcd2bin:
  498. ;----------------------------------
  499. ; input  : AL=BCD number (eg. 0x11)
  500. ; output : AH=0
  501. ;          AL=decimal number (eg. 11)
  502. ;----------------------------------
  503.         xor     ah, ah
  504.         shl     ax, 4
  505.         shr     al, 4
  506.         aad
  507.         ret
  508.  
  509.  
  510. get_date_for_file:
  511. ;-----------------------------------------------------
  512. ; Get date from CMOS and pack day,month,year in AX
  513. ; DATE   bits  0..4   : day of month 0..31
  514. ;              5..8   : month of year 1..12
  515. ;              9..15  : count of years from 1980
  516. ;-----------------------------------------------------
  517.         mov     al, 0x7 ;day
  518.         out     0x70, al
  519.         in      al, 0x71
  520.         call    bcd2bin
  521.         ror     eax, 5
  522.  
  523.         mov     al, 0x8 ;month
  524.         out     0x70, al
  525.         in      al, 0x71
  526.         call    bcd2bin
  527.         ror     eax, 4
  528.  
  529.         mov     al, 0x9 ;year
  530.         out     0x70, al
  531.         in      al, 0x71
  532.         call    bcd2bin
  533.         add     ax, 20  ;because CMOS return only the two last
  534.                         ;digit (eg. 2000 -> 00 , 2001 -> 01) and we
  535.         rol     eax, 9  ;need the difference with 1980 (eg. 2001-1980)
  536.         ret
  537.  
  538.  
  539. get_time_for_file:
  540. ;-----------------------------------------------------
  541. ; Get time from CMOS and pack hour,minute,second in AX
  542. ; TIME   bits  0..4   : second (the low bit is lost)
  543. ;              5..10  : minute 0..59
  544. ;              11..15 : hour 0..23
  545. ;-----------------------------------------------------
  546.         mov     al, 0x0 ;second
  547.         out     0x70, al
  548.         in      al, 0x71
  549.         call    bcd2bin
  550.         ror     eax, 6
  551.  
  552.         mov     al, 0x2 ;minute
  553.         out     0x70, al
  554.         in      al, 0x71
  555.         call    bcd2bin
  556.         ror     eax, 6
  557.  
  558.         mov     al, 0x4 ;hour
  559.         out     0x70, al
  560.         in      al, 0x71
  561.         call    bcd2bin
  562.         rol     eax, 11
  563.         ret
  564.  
  565.  
  566. set_current_time_for_entry:
  567. ;-----------------------------------------------------
  568. ; Set current time/date for file entry
  569. ; input  : ebx = file entry pointer
  570. ;-----------------------------------------------------
  571.         push    eax
  572.         call    get_time_for_file; update files date/time
  573.         mov     [ebx+22], ax
  574.         call    get_date_for_file
  575.         mov     [ebx+24], ax
  576.         pop     eax
  577.         ret
  578.  
  579.  
  580.  
  581. add_disk_free_space:
  582. ;-----------------------------------------------------
  583. ; input  : ecx = cluster count
  584. ; Note   : negative = remove clusters from free space
  585. ;          positive = add clusters to free space
  586. ;-----------------------------------------------------
  587.         test    ecx, ecx        ; no change
  588.         je      add_dfs_no
  589.         cmp     [ebp+FAT.fs_type], 32  ; free disk space only used by fat32
  590.         jne     add_dfs_no
  591.  
  592.         push    eax ebx
  593.         mov     eax, [ebp+FAT.ADR_FSINFO]
  594.         lea     ebx, [ebp+FAT.fsinfo_buffer]
  595.         call    fs_read32_sys
  596.         test    eax, eax
  597.         jnz     add_not_fs
  598.  
  599.         cmp     dword [ebx+0x1fc], 0xaa550000; check sector id
  600.         jne     add_not_fs
  601.  
  602.         add     [ebx+0x1e8], ecx
  603.         push    [ebp+FAT.fatStartScan]
  604.         pop     dword [ebx+0x1ec]
  605.         mov     eax, [ebp+FAT.ADR_FSINFO]
  606.         call    fs_write32_sys
  607. ;    jc    add_not_fs
  608.  
  609.   add_not_fs:
  610.         pop     ebx eax
  611.  
  612.   add_dfs_no:
  613.         ret
  614.  
  615.  
  616.  
  617. clear_cluster_chain:
  618. ;-----------------------------------------------------
  619. ; input  : eax = first cluster
  620. ;-----------------------------------------------------
  621.         push    eax ecx edx
  622.         xor     ecx, ecx        ; cluster count
  623.  
  624.   clean_new_chain:
  625.         cmp     eax, [ebp+FAT.LAST_CLUSTER]; end of file
  626.         ja      delete_OK
  627.         cmp     eax, 2          ; unfinished fat chain or zero length file
  628.         jb      delete_OK
  629.         cmp     eax, [ebp+FAT.ROOT_CLUSTER]; don't remove root cluster
  630.         jz      delete_OK
  631.  
  632.         xor     edx, edx
  633.         call    set_FAT         ; clear fat entry
  634.         jc      access_denied_01
  635.  
  636.         inc     ecx             ; update cluster count
  637.         mov     eax, edx        ; old cluster
  638.         jmp     clean_new_chain
  639.  
  640.   delete_OK:
  641.         call    add_disk_free_space; add clusters to free disk space
  642.         clc
  643.   access_denied_01:
  644.         pop     edx ecx eax
  645.         ret
  646.  
  647.  
  648. if 0
  649. get_hd_info:
  650. ;-----------------------------------------------------------
  651. ; output : eax = 0 - ok
  652. ;                3 - unknown FS
  653. ;               10 - access denied
  654. ;          edx = cluster size in bytes
  655. ;          ebx = total clusters on disk
  656. ;          ecx = free clusters on disk
  657. ;-----------------------------------------------------------
  658.         cmp     [ebp+FAT.fs_type], 16
  659.         jz      info_fat_ok
  660.         cmp     [ebp+FAT.fs_type], 32
  661.         jz      info_fat_ok
  662.         xor     edx, edx
  663.         xor     ebx, ebx
  664.         xor     ecx, ecx
  665.         mov     eax, ERROR_UNKNOWN_FS
  666.         ret
  667.  
  668.   info_fat_ok:
  669. ;    call  reserve_hd1
  670.  
  671.         xor     ecx, ecx        ; count of free clusters
  672.         mov     eax, 2
  673.         mov     ebx, [ebp+FAT.LAST_CLUSTER]
  674.  
  675.   info_cluster:
  676.         push    eax
  677.         call    get_FAT         ; get cluster info
  678.         jc      info_access_denied
  679.  
  680.         test    eax, eax        ; is it free?
  681.         jnz     info_used       ; no
  682.         inc     ecx
  683.  
  684.   info_used:
  685.         pop     eax
  686.         inc     eax
  687.         cmp     eax, ebx        ; is above last cluster?
  688.         jbe     info_cluster    ; no. test next cluster
  689.  
  690.         dec     ebx             ; cluster count
  691.         imul    edx, [ebp+FAT.SECTORS_PER_CLUSTER], 512; cluster size in bytes
  692.         xor     eax, eax
  693.         ret
  694.  
  695.   info_access_denied:
  696.         add     esp, 4
  697.         xor     edx, edx
  698.         xor     ebx, ebx
  699.         xor     ecx, ecx
  700.         mov     eax, ERROR_ACCESS_DENIED
  701.         ret
  702. end if
  703.  
  704. update_disk:
  705. ;-----------------------------------------------------------
  706. ; write changed fat and cache to disk
  707. ;-----------------------------------------------------------
  708.         cmp     [ebp+FAT.fat_change], 0 ; is fat changed?
  709.         je      upd_no_change
  710.  
  711.         call    write_fat_sector
  712.         jc      update_disk_acces_denied
  713.  
  714.   upd_no_change:
  715.  
  716.         push    esi
  717.         mov     esi, [ebp+PARTITION.Disk]
  718.         call    disk_sync
  719.         pop     esi
  720.   update_disk_acces_denied:
  721.         ret
  722.  
  723. fat_lock:
  724.         lea     ecx, [ebp+FAT.Lock]
  725.         jmp     mutex_lock
  726. fat_unlock:
  727.         lea     ecx, [ebp+FAT.Lock]
  728.         jmp     mutex_unlock
  729.  
  730. ; \begin{diamond}
  731. hd_find_lfn:
  732. ; in: ebp -> FAT structure
  733. ; in: esi+[esp+4] -> name
  734. ; out: CF=1 - file not found, eax=error code
  735. ;      else CF=0 and edi->direntry, eax=sector
  736. ; destroys eax
  737.         push    esi edi
  738.         push    0
  739.         push    0
  740.         push    fat16_root_first
  741.         push    fat16_root_next
  742.         mov     eax, [ebp+FAT.ROOT_CLUSTER]
  743.         cmp     [ebp+FAT.fs_type], 32
  744.         jz      .fat32
  745. .loop:
  746.         call    fat_find_lfn
  747.         jc      .notfound
  748.         cmp     byte [esi], 0
  749.         jz      .found
  750. .continue:
  751.         test    byte [edi+11], 10h
  752.         jz      .notfound
  753.         and     dword [esp+12], 0
  754.         mov     eax, [edi+20-2]
  755.         mov     ax, [edi+26]    ; cluster
  756. .fat32:
  757.         mov     [esp+8], eax
  758.         mov     dword [esp+4], fat_notroot_first
  759.         mov     dword [esp], fat_notroot_next
  760.         jmp     .loop
  761. .notfound:
  762.         add     esp, 16
  763.         pop     edi esi
  764.         stc
  765.         ret     4
  766. .found:
  767.         lea     eax, [esp+4+24]
  768.         cmp     dword [eax], 0
  769.         jz      @f
  770.         mov     esi, [eax]
  771.         and     dword [eax], 0
  772.         jmp     .continue
  773. @@:
  774.         lea     eax, [esp+8]
  775.         cmp     dword [eax], 0
  776.         jz      .root
  777.         call    fat_get_sector
  778.         jmp     .cmn
  779. .root:
  780.         mov     eax, [eax+4]
  781.         add     eax, [ebp+FAT.ROOT_START]
  782. .cmn:
  783.         add     esp, 20         ; CF=0
  784.         pop     esi
  785.         ret     4
  786.  
  787. ;----------------------------------------------------------------
  788. ;
  789. ;  fs_HdRead - LFN variant for reading hard disk
  790. ;
  791. ;  Obsolete, will be replaced with filesystem-specific functions.
  792. ;
  793. ;  esi  points to filename
  794. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  795. ;       may be ebx=0 - start from first byte
  796. ;  ecx  number of bytes to read, 0+
  797. ;  edx  mem location to return data
  798. ;
  799. ;  ret ebx = bytes read or 0xffffffff file not found
  800. ;      eax = 0 ok read or other = errormsg
  801. ;
  802. ;--------------------------------------------------------------
  803. fs_HdRead:
  804.         cmp     [fs_type], 16
  805.         jz      @f
  806.         cmp     [fs_type], 32
  807.         jz      @f
  808.         cmp     [fs_type], 1
  809.         jz      ntfs_HdRead
  810.         cmp     [fs_type], 2
  811.         jz      ext2_HdRead
  812.         or      ebx, -1
  813.         mov     eax, ERROR_UNKNOWN_FS
  814.         ret
  815. @@:
  816.         sub     ebx, 4
  817.         push    ebp
  818.         mov     ebp, [fs_dependent_data_start.partition]
  819.         call    fat_Read
  820.         pop     ebp
  821.         ret
  822.  
  823. ;----------------------------------------------------------------
  824. ; fat_Read - FAT16/32 implementation of reading a file
  825. ; in:  ebp = pointer to FAT structure
  826. ; in:  esi+[esp+4] = name
  827. ; in:  ebx = pointer to parameters from sysfunc 70
  828. ; out: eax, ebx = return values for sysfunc 70
  829. ;----------------------------------------------------------------
  830. fat_Read:
  831.         call    fat_lock
  832.         push    edi
  833.         cmp     byte [esi], 0
  834.         jnz     @f
  835. .noaccess:
  836.         pop     edi
  837. .noaccess_2:
  838.         call    fat_unlock
  839.         or      ebx, -1
  840.         mov     eax, ERROR_ACCESS_DENIED
  841.         ret
  842.  
  843. @@:
  844.         stdcall hd_find_lfn, [esp+4+4]
  845.         jnc     .found
  846.         pop     edi
  847.         push    eax
  848.         call    fat_unlock
  849.         pop     eax
  850.         or      ebx, -1
  851.         ret
  852.  
  853. .found:
  854.         test    byte [edi+11], 0x10; do not allow read directories
  855.         jnz     .noaccess
  856.         cmp     dword [ebx+8], 0
  857.         jz      @f
  858.         xor     ebx, ebx
  859. .reteof:
  860.         call    fat_unlock
  861.         mov     eax, ERROR_END_OF_FILE
  862.         pop     edi
  863.         ret
  864. @@:
  865.         mov     ecx, [ebx+12]   ; size
  866.         mov     edx, [ebx+16]   ; pointer
  867.         mov     ebx, [ebx+4]    ; file offset
  868.         push    edx
  869.         push    0
  870.         mov     eax, [edi+28]
  871.         sub     eax, ebx
  872.         jb      .eof
  873.         cmp     eax, ecx
  874.         jae     @f
  875.         mov     ecx, eax
  876.         mov     byte [esp], 6
  877. @@:
  878.         mov     eax, [edi+20-2]
  879.         mov     ax, [edi+26]
  880. ; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
  881. .new_cluster:
  882.         jecxz   .new_sector
  883.         cmp     eax, 2
  884.         jb      .eof
  885.         cmp     eax, [ebp+FAT.fatRESERVED]
  886.         jae     .eof
  887.         mov     [ebp+FAT.cluster_tmp], eax
  888.         dec     eax
  889.         dec     eax
  890.         mov     edi, [ebp+FAT.SECTORS_PER_CLUSTER]
  891.         imul    eax, edi
  892.         add     eax, [ebp+FAT.DATA_START]
  893. .new_sector:
  894.         test    ecx, ecx
  895.         jz      .done
  896.         sub     ebx, 512
  897.         jae     .skip
  898.         add     ebx, 512
  899.         jnz     .force_buf
  900.         cmp     ecx, 512
  901.         jb      .force_buf
  902. ; we may read directly to given buffer
  903.         push    eax ebx
  904.         mov     ebx, edx
  905.         call    fs_read32_app
  906.         test    eax, eax
  907.         pop     ebx eax
  908.         jne     .noaccess_1
  909.         add     edx, 512
  910.         sub     ecx, 512
  911.         jmp     .skip
  912. .force_buf:
  913. ; we must read sector to temporary buffer and then copy it to destination
  914.         push    eax ebx
  915.         lea     ebx, [ebp+FAT.buffer]
  916.         call    fs_read32_app
  917.         test    eax, eax
  918.         mov     eax, ebx
  919.         pop     ebx
  920.         jne     .noaccess_3
  921.         add     eax, ebx
  922.         push    ecx
  923.         add     ecx, ebx
  924.         cmp     ecx, 512
  925.         jbe     @f
  926.         mov     ecx, 512
  927. @@:
  928.         sub     ecx, ebx
  929.         mov     ebx, edx
  930.         call    memmove
  931.         add     edx, ecx
  932.         sub     [esp], ecx
  933.         pop     ecx
  934.         pop     eax
  935.         xor     ebx, ebx
  936. .skip:
  937.         inc     eax
  938.         dec     edi
  939.         jnz     .new_sector
  940.         mov     eax, [ebp+FAT.cluster_tmp]
  941.         call    get_FAT
  942.         jc      .noaccess_1
  943.  
  944.         jmp     .new_cluster
  945. .noaccess_3:
  946.         pop     eax
  947. .noaccess_1:
  948.         pop     eax
  949.         push    ERROR_DEVICE
  950. .done:
  951.         mov     ebx, edx
  952.         call    fat_unlock
  953.         pop     eax edx edi
  954.         sub     ebx, edx
  955.         ret
  956. .eof:
  957.         mov     ebx, edx
  958.         pop     eax edx
  959.         sub     ebx, edx
  960.         jmp     .reteof
  961.  
  962. ;----------------------------------------------------------------
  963. ;
  964. ;  fs_HdReadFolder - LFN variant for reading hard disk folder
  965. ;
  966. ;  Obsolete, will be replaced with filesystem-specific functions.
  967. ;
  968. ;  esi  points to filename
  969. ;  ebx  pointer to structure 32-bit number = first wanted block, 0+
  970. ;                          & flags (bitfields)
  971. ; flags: bit 0: 0=ANSI names, 1=UNICODE names
  972. ;  ecx  number of blocks to read, 0+
  973. ;  edx  mem location to return data
  974. ;
  975. ;  ret ebx = blocks read or 0xffffffff folder not found
  976. ;      eax = 0 ok read or other = errormsg
  977. ;
  978. ;--------------------------------------------------------------
  979. fs_HdReadFolder:
  980.         cmp     [fs_type], 16
  981.         jz      @f
  982.         cmp     [fs_type], 32
  983.         jz      @f
  984.         cmp     [fs_type], 1
  985.         jz      ntfs_HdReadFolder
  986.         cmp     [fs_type], 2
  987.         jz      ext2_HdReadFolder
  988.         push    ERROR_UNSUPPORTED_FS
  989.         pop     eax
  990.         or      ebx, -1
  991.         ret
  992. @@:
  993.         sub     ebx, 4
  994.         push    ebp
  995.         mov     ebp, [fs_dependent_data_start.partition]
  996.         call    fat_ReadFolder
  997.         pop     ebp
  998.         ret
  999.  
  1000. ;----------------------------------------------------------------
  1001. ; fat_ReadFolder - FAT16/32 implementation of reading a folder
  1002. ; in:  ebp = pointer to FAT structure
  1003. ; in:  esi+[esp+4] = name
  1004. ; in:  ebx = pointer to parameters from sysfunc 70
  1005. ; out: eax, ebx = return values for sysfunc 70
  1006. ;----------------------------------------------------------------
  1007. fat_ReadFolder:
  1008.         call    fat_lock
  1009.         mov     eax, [ebp+FAT.ROOT_CLUSTER]
  1010.         push    edi
  1011.         cmp     byte [esi], 0
  1012.         jz      .doit
  1013.         stdcall hd_find_lfn, [esp+4+4]
  1014.         jnc     .found
  1015.         pop     edi
  1016.         push    eax
  1017.         call    fat_unlock
  1018.         pop     eax
  1019.         or      ebx, -1
  1020.         ret
  1021. .found:
  1022.         test    byte [edi+11], 0x10     ; do not allow read files
  1023.         jnz     .found_dir
  1024.         pop     edi
  1025.         call    fat_unlock
  1026.         or      ebx, -1
  1027.         mov     eax, ERROR_ACCESS_DENIED
  1028.         ret
  1029. .found_dir:
  1030.         mov     eax, [edi+20-2]
  1031.         mov     ax, [edi+26]    ; eax=cluster
  1032. .doit:
  1033.         push    esi
  1034.         sub     esp, 262*2      ; reserve space for LFN
  1035.         push    dword [ebx+8]   ; for fat_get_name: read ANSI/UNICODE name
  1036.         mov     edx, [ebx+16]   ; pointer to buffer
  1037. ; init header
  1038.         push    eax
  1039.         mov     edi, edx
  1040.         mov     ecx, 32/4
  1041.         xor     eax, eax
  1042.         rep stosd
  1043.         pop     eax
  1044.         mov     byte [edx], 1   ; version
  1045.         mov     esi, edi        ; esi points to BDFE
  1046.         mov     ecx, [ebx+12]   ; number of blocks to read
  1047.         mov     ebx, [ebx+4]    ; index of the first block
  1048. .new_cluster:
  1049.         mov     [ebp+FAT.cluster_tmp], eax
  1050.         test    eax, eax
  1051.         jnz     @f
  1052.         cmp     [ebp+FAT.fs_type], 32
  1053.         jz      .notfound
  1054.         mov     eax, [ebp+FAT.ROOT_START]
  1055.         push    [ebp+FAT.ROOT_SECTORS]
  1056.         push    ebx
  1057.         jmp     .new_sector
  1058. @@:
  1059.         dec     eax
  1060.         dec     eax
  1061.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1062.         push    [ebp+FAT.SECTORS_PER_CLUSTER]
  1063.         add     eax, [ebp+FAT.DATA_START]
  1064.         push    ebx
  1065. .new_sector:
  1066.         lea     ebx, [ebp+FAT.buffer]
  1067.         mov     edi, ebx
  1068.         push    eax
  1069.         call    fs_read32_sys
  1070.         test    eax, eax
  1071.         pop     eax
  1072.         jnz     .notfound2
  1073.         add     ebx, 512
  1074.         push    eax
  1075. .l1:
  1076.         push    ebp
  1077.         lea     ebp, [esp+20]
  1078.         call    fat_get_name
  1079.         pop     ebp
  1080.         jc      .l2
  1081.         cmp     byte [edi+11], 0xF
  1082.         jnz     .do_bdfe
  1083.         add     edi, 0x20
  1084.         cmp     edi, ebx
  1085.         jb      .do_bdfe
  1086.         pop     eax
  1087.         inc     eax
  1088.         dec     dword [esp+4]
  1089.         jnz     @f
  1090.         mov     eax, [ebp+FAT.cluster_tmp]
  1091.         test    eax, eax
  1092.         jz      .done
  1093.         call    get_FAT
  1094.         jc      .notfound2
  1095.         cmp     eax, 2
  1096.         jb      .done
  1097.         cmp     eax, [ebp+FAT.fatRESERVED]
  1098.         jae     .done
  1099.         push    eax
  1100.         mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1101.         mov     [esp+8], eax
  1102.         pop     eax
  1103.         mov     [ebp+FAT.cluster_tmp], eax
  1104.         dec     eax
  1105.         dec     eax
  1106.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1107.         add     eax, [ebp+FAT.DATA_START]
  1108. @@:
  1109.         lea     ebx, [ebp+FAT.buffer]
  1110.         mov     edi, ebx
  1111.         push    eax
  1112.         call    fs_read32_sys
  1113.         test    eax, eax
  1114.         pop     eax
  1115.         jnz     .notfound2
  1116.         add     ebx, 512
  1117.         push    eax
  1118. .do_bdfe:
  1119.         inc     dword [edx+8]   ; new file found
  1120.         dec     dword [esp+4]
  1121.         jns     .l2
  1122.         dec     ecx
  1123.         js      .l2
  1124.         inc     dword [edx+4]   ; new file block copied
  1125.         push    ebp
  1126.         lea     ebp, [esp+20]
  1127.         call    fat_entry_to_bdfe
  1128.         pop     ebp
  1129. .l2:
  1130.         add     edi, 0x20
  1131.         cmp     edi, ebx
  1132.         jb      .l1
  1133.         pop     eax
  1134.         inc     eax
  1135.         dec     dword [esp+4]
  1136.         jnz     .new_sector
  1137.         mov     eax, [ebp+FAT.cluster_tmp]
  1138.         test    eax, eax
  1139.         jz      .done
  1140.         call    get_FAT
  1141.         jc      .notfound2
  1142.         cmp     eax, 2
  1143.         jb      .done
  1144.         cmp     eax, [ebp+FAT.fatRESERVED]
  1145.         jae     .done
  1146.         push    eax
  1147.         mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1148.         mov     [esp+8], eax
  1149.         pop     eax
  1150.         pop     ebx
  1151.         add     esp, 4
  1152.         jmp     .new_cluster
  1153. .notfound2:
  1154.         add     esp, 8
  1155. .notfound:
  1156.         add     esp, 262*2+4
  1157.         pop     esi edi
  1158.         mov     ebx, [edx+4]
  1159.         call    fat_unlock
  1160.         mov     eax, ERROR_DEVICE
  1161.         ret
  1162. .done:
  1163.         add     esp, 262*2+4+8
  1164.         mov     ebx, [edx+4]
  1165.         xor     eax, eax
  1166.         dec     ecx
  1167.         js      @f
  1168.         mov     al, ERROR_END_OF_FILE
  1169. @@:
  1170.         push    eax
  1171.         call    fat_unlock
  1172.         pop     eax
  1173.         pop     esi edi
  1174.         ret
  1175.  
  1176. fat16_root_next:
  1177.         push    ecx
  1178.         lea     ecx, [ebp+FAT.buffer+0x200-0x20]
  1179.         cmp     edi, ecx
  1180.         jae     fat16_root_next_sector
  1181.         pop     ecx
  1182.         add     edi, 0x20
  1183.         ret     ; CF=0
  1184. fat16_root_next_sector:
  1185. ; read next sector
  1186.         push    [ebp+FAT.longname_sec2]
  1187.         pop     [ebp+FAT.longname_sec1]
  1188.         mov     ecx, [eax+4]
  1189.         push    ecx
  1190.         add     ecx, [ebp+FAT.ROOT_START]
  1191.         mov     [ebp+FAT.longname_sec2], ecx
  1192.         pop     ecx
  1193.         inc     ecx
  1194.         mov     [eax+4], ecx
  1195.         cmp     ecx, [ebp+FAT.ROOT_SECTORS]
  1196.         pop     ecx
  1197.         jb      fat16_root_first
  1198.         mov     eax, ERROR_FILE_NOT_FOUND
  1199.         stc
  1200.         ret
  1201. fat16_root_first:
  1202.         mov     eax, [eax+4]
  1203.         add     eax, [ebp+FAT.ROOT_START]
  1204.         push    ebx
  1205.         lea     edi, [ebp+FAT.buffer]
  1206.         mov     ebx, edi
  1207.         call    fs_read32_sys
  1208.         pop     ebx
  1209.         test    eax, eax
  1210.         jnz     .readerr
  1211.         ret     ; CF=0
  1212. .readerr:
  1213.         mov     eax, ERROR_DEVICE
  1214.         stc
  1215.         ret
  1216. .notfound:
  1217.         mov     eax, ERROR_FILE_NOT_FOUND
  1218.         stc
  1219.         ret
  1220. fat16_root_begin_write:
  1221.         push    edi eax
  1222.         call    fat16_root_first
  1223.         pop     eax edi
  1224.         ret
  1225. fat16_root_end_write:
  1226.         pusha
  1227.         mov     eax, [eax+4]
  1228.         add     eax, [ebp+FAT.ROOT_START]
  1229.         lea     ebx, [ebp+FAT.buffer]
  1230.         call    fs_write32_sys
  1231.         popa
  1232.         ret
  1233. fat16_root_next_write:
  1234.         push    ecx
  1235.         lea     ecx, [ebp+FAT.buffer+0x200]
  1236.         cmp     edi, ecx
  1237.         jae     @f
  1238.         pop     ecx
  1239.         ret
  1240. @@:
  1241.         call    fat16_root_end_write
  1242.         jmp     fat16_root_next_sector
  1243. fat16_root_extend_dir:
  1244.         stc
  1245.         ret
  1246.  
  1247. fat_notroot_next:
  1248.         push    ecx
  1249.         lea     ecx, [ebp+FAT.buffer+0x200-0x20]
  1250.         cmp     edi, ecx
  1251.         jae     fat_notroot_next_sector
  1252.         pop     ecx
  1253.         add     edi, 0x20
  1254.         ret     ; CF=0
  1255. fat_notroot_next_sector:
  1256.         push    [ebp+FAT.longname_sec2]
  1257.         pop     [ebp+FAT.longname_sec1]
  1258.         push    eax
  1259.         call    fat_get_sector
  1260.         mov     [ebp+FAT.longname_sec2], eax
  1261.         pop     eax
  1262.         mov     ecx, [eax+4]
  1263.         inc     ecx
  1264.         cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1265.         jae     fat_notroot_next_cluster
  1266.         mov     [eax+4], ecx
  1267.         jmp     @f
  1268. fat_notroot_next_cluster:
  1269.         push    eax
  1270.         mov     eax, [eax]
  1271.         call    get_FAT
  1272.         mov     ecx, eax
  1273.         pop     eax
  1274.         jc      fat_notroot_first.deverr
  1275.         cmp     ecx, 2
  1276.         jb      fat_notroot_next_err
  1277.         cmp     ecx, [ebp+FAT.fatRESERVED]
  1278.         jae     fat_notroot_next_err
  1279.         mov     [eax], ecx
  1280.         and     dword [eax+4], 0
  1281. @@:
  1282.         pop     ecx
  1283. fat_notroot_first:
  1284.         call    fat_get_sector
  1285.         push    ebx
  1286.         lea     edi, [ebp+FAT.buffer]
  1287.         mov     ebx, edi
  1288.         call    fs_read32_sys
  1289.         pop     ebx
  1290.         test    eax, eax
  1291.         jz      .ret ; CF=0
  1292.         push    ecx
  1293. .deverr:
  1294.         pop     ecx
  1295.         mov     eax, ERROR_DEVICE
  1296.         stc
  1297. .ret:
  1298.         ret
  1299. fat_notroot_next_err:
  1300.         pop     ecx
  1301.         mov     eax, ERROR_FILE_NOT_FOUND
  1302.         stc
  1303.         ret
  1304. fat_notroot_begin_write:
  1305.         push    eax edi
  1306.         call    fat_notroot_first
  1307.         pop     edi eax
  1308.         ret
  1309. fat_notroot_end_write:
  1310.         call    fat_get_sector
  1311.         push    ebx
  1312.         lea     ebx, [ebp+FAT.buffer]
  1313.         call    fs_write32_sys
  1314.         pop     ebx
  1315.         ret
  1316. fat_notroot_next_write:
  1317.         push    ecx
  1318.         lea     ecx, [ebp+FAT.buffer+0x200]
  1319.         cmp     edi, ecx
  1320.         jae     @f
  1321.         pop     ecx
  1322.         ret
  1323. @@:
  1324.         push    eax
  1325.         call    fat_notroot_end_write
  1326.         pop     eax
  1327.         jmp     fat_notroot_next_sector
  1328. fat_notroot_extend_dir:
  1329.         push    eax
  1330.         call    get_free_FAT
  1331.         jnc     .found
  1332.         pop     eax
  1333.         ret     ; CF=1
  1334. .found:
  1335.         push    edx
  1336.         mov     edx, [ebp+FAT.fatEND]
  1337.         call    set_FAT
  1338.         jc      .writeerr
  1339.         mov     edx, eax
  1340.         mov     eax, [esp+4]
  1341.         mov     eax, [eax]
  1342.         push    edx
  1343.         call    set_FAT
  1344.         pop     edx
  1345.         jnc     @f
  1346. .writeerr:
  1347.         pop     edx
  1348.         pop     eax
  1349.         stc
  1350.         ret
  1351. @@:
  1352.         push    ecx
  1353.         or      ecx, -1
  1354.         call    add_disk_free_space
  1355. ; zero new cluster
  1356.         mov     ecx, 512/4
  1357.         lea     edi, [ebp+FAT.buffer]
  1358.         push    edi
  1359.         xor     eax, eax
  1360.         rep stosd
  1361.         pop     edi
  1362.         pop     ecx
  1363.         mov     eax, [esp+4]
  1364.         mov     [eax], edx
  1365.         and     dword [eax+4], 0
  1366.         pop     edx
  1367.         mov     eax, [eax]
  1368.         dec     eax
  1369.         dec     eax
  1370.         push    ebx ecx
  1371.         mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1372.         imul    eax, ecx
  1373.         add     eax, [ebp+FAT.DATA_START]
  1374.         mov     ebx, edi
  1375. @@:
  1376.         push    eax
  1377.         call    fs_write32_sys
  1378.         pop     eax
  1379.         inc     eax
  1380.         loop    @b
  1381.         pop     ecx ebx eax
  1382.         clc
  1383.         ret
  1384.  
  1385. fat_get_sector:
  1386.         push    ecx
  1387.         mov     ecx, [eax]
  1388.         dec     ecx
  1389.         dec     ecx
  1390.         imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1391.         add     ecx, [ebp+FAT.DATA_START]
  1392.         add     ecx, [eax+4]
  1393.         mov     eax, ecx
  1394.         pop     ecx
  1395.         ret
  1396.  
  1397. ;----------------------------------------------------------------
  1398. ;
  1399. ;  fs_HdRewrite - LFN variant for writing hard disk
  1400. ;
  1401. ;  Obsolete, will be replaced with filesystem-specific functions.
  1402. ;
  1403. ;  esi  points to filename
  1404. ;  ebx  ignored (reserved)
  1405. ;  ecx  number of bytes to write, 0+
  1406. ;  edx  mem location to data
  1407. ;
  1408. ;  ret ebx = number of written bytes
  1409. ;      eax = 0 ok read or other = errormsg
  1410. ;
  1411. ;--------------------------------------------------------------
  1412. fs_HdCreateFolder:
  1413.         mov     al, 1
  1414.         jmp     fs_HdRewrite.common
  1415.  
  1416. fs_HdRewrite:
  1417.         xor     eax, eax
  1418. .common:
  1419.         cmp     [fs_type], 16
  1420.         jz      @f
  1421.         cmp     [fs_type], 32
  1422.         jz      @f
  1423.         cmp     [fs_type], 1
  1424.         jz      ntfs_HdRewrite
  1425.         cmp     [fs_type], 2
  1426.         jz      ext2_HdRewrite
  1427.         mov     eax, ERROR_UNKNOWN_FS
  1428.         xor     ebx, ebx
  1429.         ret
  1430. @@:
  1431.         sub     ebx, 4
  1432.         push    ebp
  1433.         mov     ebp, [fs_dependent_data_start.partition]
  1434.         test    eax, eax
  1435.         mov     eax, fat_CreateFolder
  1436.         jnz     @f
  1437.         mov     eax, fat_Rewrite
  1438. @@:
  1439.         call    eax
  1440.         pop     ebp
  1441.         ret
  1442.  
  1443. fshrad:
  1444.         call    fat_unlock
  1445.         mov     eax, ERROR_ACCESS_DENIED
  1446.         xor     ebx, ebx
  1447.         ret
  1448.  
  1449. ;----------------------------------------------------------------
  1450. ; fat_CreateFolder - FAT16/32 implementation of creating a folder
  1451. ; in:  ebp = pointer to FAT structure
  1452. ; in:  esi+[esp+4] = name
  1453. ; in:  ebx = pointer to parameters from sysfunc 70
  1454. ; out: eax, ebx = return values for sysfunc 70
  1455. ;----------------------------------------------------------------
  1456. fat_CreateFolder:
  1457.         push    1
  1458.         jmp     fat_Rewrite.common
  1459.  
  1460. ;----------------------------------------------------------------
  1461. ; fat_HdRewrite - FAT16/32 implementation of creating a new file
  1462. ; in:  ebp = pointer to FAT structure
  1463. ; in:  esi+[esp+4] = name
  1464. ; in:  ebx = pointer to parameters from sysfunc 70
  1465. ; out: eax, ebx = return values for sysfunc 70
  1466. ;----------------------------------------------------------------
  1467. fat_Rewrite:
  1468.         push    0
  1469. .common:
  1470.         call    fat_lock
  1471.         pop     eax
  1472.         cmp     byte [esi], 0
  1473.         jz      fshrad
  1474.         mov     ecx, [ebx+12]
  1475.         mov     edx, [ebx+16]
  1476.         pushad
  1477.         xor     edi, edi
  1478.         mov     edx, [esp+4+20h]
  1479.         push    esi
  1480.         test    edx, edx
  1481.         jz      @f
  1482.         mov     esi, edx
  1483. @@:
  1484.         lodsb
  1485.         test    al, al
  1486.         jz      @f
  1487.         cmp     al, '/'
  1488.         jnz     @b
  1489.         lea     edi, [esi-1]
  1490.         jmp     @b
  1491. @@:
  1492.         pop     esi
  1493.         test    edi, edi
  1494.         jnz     .noroot
  1495.         test    edx, edx
  1496.         jnz     .hasebp
  1497.         mov     edx, [ebp+FAT.ROOT_CLUSTER]
  1498.         cmp     [ebp+FAT.fs_type], 32
  1499.         jz      .pushnotroot
  1500.         xor     edx, edx
  1501.         push    edx
  1502.         push    fat16_root_extend_dir
  1503.         push    fat16_root_end_write
  1504.         push    fat16_root_next_write
  1505.         push    fat16_root_begin_write
  1506.         push    edx
  1507.         push    edx
  1508.         push    fat16_root_first
  1509.         push    fat16_root_next
  1510.         jmp     .common1
  1511. .hasebp:
  1512.         mov     eax, ERROR_ACCESS_DENIED
  1513.         cmp     byte [edx], 0
  1514.         jz      .ret1
  1515.         stdcall hd_find_lfn, 0
  1516.         mov     esi, [esp+4+20h]
  1517.         jc      .ret1
  1518.         jmp     .common0
  1519. .noroot:
  1520.         mov     eax, ERROR_ACCESS_DENIED
  1521.         cmp     byte [edi+1], 0
  1522.         jz      .ret1
  1523. ; check existence
  1524.         mov     byte [edi], 0
  1525.         push    edi
  1526.         stdcall hd_find_lfn, [esp+4+24h]
  1527.         pop     esi
  1528.         mov     byte [esi], '/'
  1529.         jnc     @f
  1530. .notfound0:
  1531.         mov     eax, ERROR_FILE_NOT_FOUND
  1532. .ret1:
  1533.         mov     [esp+28], eax
  1534.         call    fat_unlock
  1535.         popad
  1536.         xor     ebx, ebx
  1537.         ret
  1538. @@:
  1539.         inc     esi
  1540. .common0:
  1541.         test    byte [edi+11], 0x10     ; must be directory
  1542.         mov     eax, ERROR_ACCESS_DENIED
  1543.         jz      .ret1
  1544.         mov     edx, [edi+20-2]
  1545.         mov     dx, [edi+26]            ; ebp=cluster
  1546.         mov     eax, ERROR_FAT_TABLE
  1547.         cmp     edx, 2
  1548.         jb      .ret1
  1549. .pushnotroot:
  1550.         push    edx
  1551.         push    fat_notroot_extend_dir
  1552.         push    fat_notroot_end_write
  1553.         push    fat_notroot_next_write
  1554.         push    fat_notroot_begin_write
  1555.         push    0
  1556.         push    edx
  1557.         push    fat_notroot_first
  1558.         push    fat_notroot_next
  1559. .common1:
  1560.         call    fat_find_lfn
  1561.         jc      .notfound
  1562. ; found
  1563.         test    byte [edi+11], 10h
  1564.         jz      .exists_file
  1565. ; found directory; if we are creating directory, return OK,
  1566. ;                  if we are creating file, say "access denied"
  1567.         add     esp, 36
  1568.         call    fat_unlock
  1569.         popad
  1570.         test    al, al
  1571.         mov     eax, ERROR_ACCESS_DENIED
  1572.         jz      @f
  1573.         mov     al, 0
  1574. @@:
  1575.         xor     ebx, ebx
  1576.         ret
  1577. .exists_file:
  1578. ; found file; if we are creating directory, return "access denied",
  1579. ;             if we are creating file, delete existing file and continue
  1580.         cmp     byte [esp+36+28], 0
  1581.         jz      @f
  1582.         add     esp, 36
  1583.         call    fat_unlock
  1584.         popad
  1585.         mov     eax, ERROR_ACCESS_DENIED
  1586.         xor     ebx, ebx
  1587.         ret
  1588. @@:
  1589. ; delete FAT chain
  1590.         push    edi
  1591.         xor     eax, eax
  1592.         mov     dword [edi+28], eax     ; zero size
  1593.         xor     ecx, ecx
  1594.         mov     eax, [edi+20-2]
  1595.         mov     ax, [edi+26]
  1596.         mov     word [edi+20], cx
  1597.         mov     word [edi+26], cx
  1598.         test    eax, eax
  1599.         jz      .done1
  1600. @@:
  1601.         cmp     eax, [ebp+FAT.fatRESERVED]
  1602.         jae     .done1
  1603.         push    edx
  1604.         xor     edx, edx
  1605.         call    set_FAT
  1606.         mov     eax, edx
  1607.         pop     edx
  1608.         jc      .done1
  1609.         inc     ecx
  1610.         jmp     @b
  1611. .done1:
  1612.         pop     edi
  1613.         call    get_time_for_file
  1614.         mov     [edi+22], ax
  1615.         call    get_date_for_file
  1616.         mov     [edi+24], ax
  1617.         mov     [edi+18], ax
  1618.         or      byte [edi+11], 20h      ; set 'archive' attribute
  1619.         jmp     .doit
  1620. .notfound:
  1621. ; file is not found; generate short name
  1622.         call    fat_name_is_legal
  1623.         jc      @f
  1624.         add     esp, 36
  1625.         call    fat_unlock
  1626.         popad
  1627.         mov     eax, ERROR_FILE_NOT_FOUND
  1628.         xor     ebx, ebx
  1629.         ret
  1630. @@:
  1631.         sub     esp, 12
  1632.         mov     edi, esp
  1633.         call    fat_gen_short_name
  1634. .test_short_name_loop:
  1635.         push    esi edi ecx
  1636.         mov     esi, edi
  1637.         lea     eax, [esp+12+12+8]
  1638.         mov     edx, [eax+24]
  1639.         mov     [eax], edx
  1640.         and     dword [eax+4], 0
  1641.         call    dword [eax-4]
  1642.         jc      .found
  1643. .test_short_name_entry:
  1644.         cmp     byte [edi+11], 0xF
  1645.         jz      .test_short_name_cont
  1646.         mov     ecx, 11
  1647.         push    esi edi
  1648.         repz cmpsb
  1649.         pop     edi esi
  1650.         jz      .short_name_found
  1651. .test_short_name_cont:
  1652.         lea     eax, [esp+12+12+8]
  1653.         call    dword [eax-8]
  1654.         jnc     .test_short_name_entry
  1655.         jmp     .found
  1656. .short_name_found:
  1657.         pop     ecx edi esi
  1658.         call    fat_next_short_name
  1659.         jnc     .test_short_name_loop
  1660. .disk_full:
  1661.         add     esp, 12+36
  1662.         call    fat_unlock
  1663.         popa
  1664.         mov     eax, ERROR_DISK_FULL
  1665.         xor     ebx, ebx
  1666.         ret
  1667. .found:
  1668.         pop     ecx edi esi
  1669. ; now find space in directory
  1670. ; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
  1671.         mov     al, '~'
  1672.         push    ecx edi
  1673.         mov     ecx, 8
  1674.         repnz scasb
  1675.         push    1
  1676.         pop     eax     ; 1 entry
  1677.         jnz     .notilde
  1678. ; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
  1679.         xor     eax, eax
  1680. @@:
  1681.         cmp     byte [esi], 0
  1682.         jz      @f
  1683.         inc     esi
  1684.         inc     eax
  1685.         jmp     @b
  1686. @@:
  1687.         sub     esi, eax
  1688.         add     eax, 12+13
  1689.         mov     ecx, 13
  1690.         push    edx
  1691.         cdq
  1692.         div     ecx
  1693.         pop     edx
  1694. .notilde:
  1695.         push    -1
  1696.         push    -1
  1697.         push    -1
  1698. ; find <eax> successive entries in directory
  1699.         xor     ecx, ecx
  1700.         push    eax
  1701.         lea     eax, [esp+16+8+12+8]
  1702.         mov     edx, [eax+24]
  1703.         mov     [eax], edx
  1704.         and     dword [eax+4], 0
  1705.         call    dword [eax-4]
  1706.         pop     eax
  1707.         jnc     .scan_dir
  1708. .fsfrfe3:
  1709.         add     esp, 12+8+12+36
  1710.         call    fat_unlock
  1711.         popad
  1712.         mov     eax, ERROR_DEVICE
  1713.         xor     ebx, ebx
  1714.         ret
  1715. .scan_dir:
  1716.         cmp     byte [edi], 0
  1717.         jz      .free
  1718.         cmp     byte [edi], 0xE5
  1719.         jz      .free
  1720.         xor     ecx, ecx
  1721. .scan_cont:
  1722.         push    eax
  1723.         lea     eax, [esp+16+8+12+8]
  1724.         call    dword [eax-8]
  1725.         mov     edx, eax
  1726.         pop     eax
  1727.         jnc     .scan_dir
  1728.         cmp     edx, ERROR_DEVICE
  1729.         jz      .fsfrfe3
  1730.         push    eax
  1731.         lea     eax, [esp+16+8+12+8]
  1732.         call    dword [eax+20]          ; extend directory
  1733.         pop     eax
  1734.         jnc     .scan_dir
  1735.         add     esp, 12+8+12+36
  1736.         call    fat_unlock
  1737.         popad
  1738.         mov     eax, ERROR_DISK_FULL
  1739.         xor     ebx, ebx
  1740.         ret
  1741. .free:
  1742.         test    ecx, ecx
  1743.         jnz     @f
  1744.         mov     [esp], edi
  1745.         mov     ecx, [esp+12+8+12+8]
  1746.         mov     [esp+4], ecx
  1747.         mov     ecx, [esp+12+8+12+12]
  1748.         mov     [esp+8], ecx
  1749.         xor     ecx, ecx
  1750. @@:
  1751.         inc     ecx
  1752.         cmp     ecx, eax
  1753.         jb      .scan_cont
  1754. ; found!
  1755.         push    esi ecx
  1756. ; If creating a directory, allocate one data cluster now and fail immediately
  1757. ; if this is impossible. This prevents from creating an invalid directory entry
  1758. ; on a full disk.
  1759. ; yup, the argument is quite non-intuitive... but what should I do if
  1760. ; the entire function uses such arguments? BTW, it refers to al from pushad,
  1761. ; which in turn is filled with 0 in fat_Rewrite and 1 in fat_CreateFolder.
  1762.         cmp     byte [esp+8+12+8+12+36+28], 0
  1763.         jz      .no.preallocate.folder.data
  1764.         call    get_free_FAT
  1765.         jnc     @f
  1766.         add     esp, 8+12+8
  1767.         jmp     .disk_full
  1768. @@:
  1769.         mov     [esp+8+12+8+12+36+20], eax ; store the cluster somewhere
  1770. .no.preallocate.folder.data:
  1771. ; calculate name checksum
  1772.         mov     esi, [esp+8+12]
  1773.         mov     ecx, 11
  1774.         xor     eax, eax
  1775. @@:
  1776.         ror     al, 1
  1777.         add     al, [esi]
  1778.         inc     esi
  1779.         loop    @b
  1780.         pop     ecx esi
  1781.         pop     edi
  1782.         pop     dword [esp+8+12+12]
  1783.         pop     dword [esp+8+12+12]
  1784. ; edi points to first entry in free chunk
  1785.         dec     ecx
  1786.         jz      .nolfn
  1787.         push    esi
  1788.         push    eax
  1789.         lea     eax, [esp+8+8+12+8]
  1790.         call    dword [eax+8]         ; begin write
  1791.         mov     al, 40h
  1792. .writelfn:
  1793.         or      al, cl
  1794.         mov     esi, [esp+4]
  1795.         push    ecx
  1796.         dec     ecx
  1797.         imul    ecx, 13
  1798.         add     esi, ecx
  1799.         stosb
  1800.         mov     cl, 5
  1801.         call    fs_RamdiskRewrite.read_symbols
  1802.         mov     ax, 0xF
  1803.         stosw
  1804.         mov     al, [esp+4]
  1805.         stosb
  1806.         mov     cl, 6
  1807.         call    fs_RamdiskRewrite.read_symbols
  1808.         xor     eax, eax
  1809.         stosw
  1810.         mov     cl, 2
  1811.         call    fs_RamdiskRewrite.read_symbols
  1812.         pop     ecx
  1813.         lea     eax, [esp+8+8+12+8]
  1814.         call    dword [eax+12]         ; next write
  1815.         xor     eax, eax
  1816.         loop    .writelfn
  1817.         pop     eax
  1818.         pop     esi
  1819. ;        lea     eax, [esp+8+12+8]
  1820. ;        call    dword [eax+16]          ; end write
  1821. .nolfn:
  1822.         xchg    esi, [esp]
  1823.         mov     ecx, 11
  1824.         rep movsb
  1825.         mov     word [edi], 20h         ; attributes
  1826.         sub     edi, 11
  1827.         pop     esi ecx
  1828.         add     esp, 12
  1829.         mov     byte [edi+13], 0        ; tenths of a second at file creation time
  1830.         call    get_time_for_file
  1831.         mov     [edi+14], ax            ; creation time
  1832.         mov     [edi+22], ax            ; last write time
  1833.         call    get_date_for_file
  1834.         mov     [edi+16], ax            ; creation date
  1835.         mov     [edi+24], ax            ; last write date
  1836.         mov     [edi+18], ax            ; last access date
  1837.         xor     ecx, ecx
  1838.         mov     word [edi+20], cx       ; high word of cluster
  1839.         mov     word [edi+26], cx       ; low word of cluster - to be filled
  1840.         mov     dword [edi+28], ecx     ; file size - to be filled
  1841.         cmp     byte [esp+36+28], cl
  1842.         jz      .doit
  1843. ; create directory
  1844.         mov     byte [edi+11], 10h      ; attributes: folder
  1845.         mov     esi, edi
  1846.         lea     eax, [esp+8]
  1847.         call    dword [eax+16]  ; flush directory
  1848.         mov     eax, [esp+36+20] ; extract saved cluster
  1849.         mov     [esp+36+20], edi ; this is needed for calculating arg of add_disk_free_space!
  1850.         push    ecx
  1851.         mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1852.         shl     ecx, 9
  1853.         push    ecx
  1854.         push    edi
  1855.         jmp     .doit2
  1856. .doit:
  1857.         mov     esi, [esp+36+20]
  1858.         lea     eax, [esp+8]
  1859.         call    dword [eax+16]  ; flush directory
  1860.         push    ecx
  1861.         mov     ecx, [esp+4+36+24]
  1862.         push    ecx
  1863.         push    edi
  1864.         test    ecx, ecx
  1865.         jz      .done
  1866.         call    get_free_FAT
  1867.         jc      .diskfull
  1868. .doit2:
  1869.         push    eax
  1870.         mov     [edi+26], ax
  1871.         shr     eax, 16
  1872.         mov     [edi+20], ax
  1873.         lea     eax, [esp+16+8]
  1874.         call    dword [eax+16]  ; flush directory
  1875.         pop     eax
  1876.         push    edx
  1877.         mov     edx, [ebp+FAT.fatEND]
  1878.         call    set_FAT
  1879.         pop     edx
  1880. .write_cluster:
  1881.         push    eax
  1882.         dec     eax
  1883.         dec     eax
  1884.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1885.         add     eax, [ebp+FAT.DATA_START]
  1886.         push    [ebp+FAT.SECTORS_PER_CLUSTER]
  1887. ; write data
  1888. .write_sector:
  1889.         cmp     byte [esp+20+36+28], 0
  1890.         jnz     .writedir
  1891.         mov     ecx, 512
  1892.         cmp     dword [esp+12], ecx
  1893.         jb      .writeshort
  1894. ; we can write directly from given buffer
  1895.         mov     ebx, esi
  1896.         add     esi, ecx
  1897.         jmp     .writecommon
  1898. .writeshort:
  1899.         mov     ecx, [esp+12]
  1900.         push    ecx
  1901.         lea     edi, [ebp+FAT.buffer]
  1902.         mov     ebx, edi
  1903.         rep movsb
  1904. .writedircont:
  1905.         lea     ecx, [ebp+FAT.buffer+0x200]
  1906.         sub     ecx, edi
  1907.         push    eax
  1908.         xor     eax, eax
  1909.         rep stosb
  1910.         pop     eax
  1911.         pop     ecx
  1912. .writecommon:
  1913.         push    eax
  1914.         call    fs_write32_app
  1915.         test    eax, eax
  1916.         pop     eax
  1917.         jnz     .writeerr
  1918.         inc     eax
  1919.         sub     dword [esp+12], ecx
  1920.         jz      .writedone
  1921.         dec     dword [esp]
  1922.         jnz     .write_sector
  1923.         pop     eax
  1924. ; allocate new cluster
  1925.         pop     eax
  1926.         mov     ecx, eax
  1927.         call    get_free_FAT
  1928.         jc      .diskfull
  1929.         push    edx
  1930.         mov     edx, [ebp+FAT.fatEND]
  1931.         call    set_FAT
  1932.         xchg    eax, ecx
  1933.         mov     edx, ecx
  1934.         call    set_FAT
  1935.         pop     edx
  1936.         xchg    eax, ecx
  1937.         jmp     .write_cluster
  1938. .diskfull:
  1939.         mov     eax, ERROR_DISK_FULL
  1940.         jmp     .ret
  1941. .writeerr:
  1942.         pop     eax eax
  1943.         sub     esi, ecx
  1944.         mov     eax, ERROR_DEVICE
  1945.         jmp     .ret
  1946. .writedone:
  1947.         pop     eax eax
  1948. .done:
  1949.         xor     eax, eax
  1950. .ret:
  1951.         pop     edi ecx
  1952.         sub     esi, [esp+4+36+20]
  1953.         mov     [esp+4+36+28], eax
  1954.         mov     [esp+4+36+16], esi
  1955.         lea     eax, [esp+12]
  1956.         call    dword [eax+8]
  1957.         mov     [edi+28], esi
  1958.         call    dword [eax+16]
  1959.         mov     [esp+36+16], ebx
  1960.         lea     eax, [esi+511]
  1961.         shr     eax, 9
  1962.         mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1963.         lea     eax, [eax+ecx-1]
  1964.         xor     edx, edx
  1965.         div     ecx
  1966.         pop     ecx
  1967.         sub     ecx, eax
  1968.         call    add_disk_free_space
  1969.         add     esp, 36
  1970.         call    update_disk
  1971.         call    fat_unlock
  1972.         popad
  1973.         ret
  1974. .writedir:
  1975.         push    512
  1976.         lea     edi, [ebp+FAT.buffer]
  1977.         mov     ebx, edi
  1978.         mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1979.         shl     ecx, 9
  1980.         cmp     ecx, [esp+16]
  1981.         jnz     .writedircont
  1982.         dec     dword [esp+20]
  1983.         push    esi
  1984.         mov     ecx, 32/4
  1985.         rep movsd
  1986.         pop     esi
  1987.         mov     dword [edi-32], '.   '
  1988.         mov     dword [edi-32+4], '    '
  1989.         mov     dword [edi-32+8], '    '
  1990.         mov     byte [edi-32+11], 10h
  1991.         push    esi
  1992.         mov     ecx, 32/4
  1993.         rep movsd
  1994.         pop     esi
  1995.         mov     dword [edi-32], '..  '
  1996.         mov     dword [edi-32+4], '    '
  1997.         mov     dword [edi-32+8], '    '
  1998.         mov     byte [edi-32+11], 10h
  1999.         mov     ecx, [esp+20+36]
  2000.         cmp     ecx, [ebp+FAT.ROOT_CLUSTER]
  2001.         jnz     @f
  2002.         xor     ecx, ecx
  2003. @@:
  2004.         mov     word [edi-32+26], cx
  2005.         shr     ecx, 16
  2006.         mov     [edi-32+20], cx
  2007.         jmp     .writedircont
  2008.  
  2009. ;----------------------------------------------------------------
  2010. ;
  2011. ;  fs_HdWrite - LFN variant for writing to hard disk
  2012. ;
  2013. ;  Obsolete, will be replaced with filesystem-specific functions.
  2014. ;
  2015. ;  esi  points to filename
  2016. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  2017. ;       may be ebx=0 - start from first byte
  2018. ;  ecx  number of bytes to write, 0+
  2019. ;  edx  mem location to data
  2020. ;
  2021. ;  ret ebx = bytes written (maybe 0)
  2022. ;      eax = 0 ok write or other = errormsg
  2023. ;
  2024. ;--------------------------------------------------------------
  2025. fat_Write.access_denied:
  2026.         push    ERROR_ACCESS_DENIED
  2027. fs_HdWrite.ret0:
  2028.         pop     eax
  2029.         xor     ebx, ebx
  2030.         ret
  2031.  
  2032. fs_HdWrite.ret11:
  2033.         push    ERROR_DEVICE
  2034.         jmp     fs_HdWrite.ret0
  2035.  
  2036. fs_HdWrite:
  2037.         cmp     [fs_type], 16
  2038.         jz      @f
  2039.         cmp     [fs_type], 32
  2040.         jz      @f
  2041.         cmp     [fs_type], 1
  2042.         jz      ntfs_HdWrite
  2043.         cmp     [fs_type], 2
  2044.         jz      ext2_HdWrite
  2045.         push    ERROR_UNKNOWN_FS
  2046.         jmp     .ret0
  2047. @@:
  2048.         sub     ebx, 4
  2049.         push    ebp
  2050.         mov     ebp, [fs_dependent_data_start.partition]
  2051.         call    fat_Write
  2052.         pop     ebp
  2053.         ret
  2054.  
  2055. ;----------------------------------------------------------------
  2056. ; fat_Write - FAT16/32 implementation of writing to file
  2057. ; in:  ebp = pointer to FAT structure
  2058. ; in:  esi+[esp+4] = name
  2059. ; in:  ebx = pointer to parameters from sysfunc 70
  2060. ; out: eax, ebx = return values for sysfunc 70
  2061. ;----------------------------------------------------------------
  2062. fat_Write:
  2063.         cmp     byte [esi], 0
  2064.         jz      .access_denied
  2065.         call    fat_lock
  2066.         push    edi
  2067.         stdcall hd_find_lfn, [esp+4+4]
  2068.         jnc     .found
  2069.         pop     edi
  2070.         push    eax
  2071.         call    fat_unlock
  2072.         jmp     fs_HdWrite.ret0
  2073. .found:
  2074. ; FAT does not support files larger than 4GB
  2075.         cmp     dword [ebx+8], 0
  2076.         jz      @f
  2077. .eof:
  2078.         pop     edi
  2079.         push    ERROR_END_OF_FILE
  2080.         call    fat_unlock
  2081.         jmp     fs_HdWrite.ret0
  2082. @@:
  2083.         mov     ecx, [ebx+12]
  2084.         mov     edx, [ebx+16]
  2085.         mov     ebx, [ebx+4]
  2086. ; now edi points to direntry, ebx=start byte to write,
  2087. ; ecx=number of bytes to write, edx=data pointer
  2088.  
  2089. ; extend file if needed
  2090.         add     ecx, ebx
  2091.         jc      .eof    ; FAT does not support files larger than 4GB
  2092.         push    edx
  2093.         push    eax     ; save directory sector
  2094.         push    0       ; return value=0
  2095.  
  2096.         call    get_time_for_file
  2097.         mov     [edi+22], ax            ; last write time
  2098.         call    get_date_for_file
  2099.         mov     [edi+24], ax            ; last write date
  2100.         mov     [edi+18], ax            ; last access date
  2101.  
  2102.         push    dword [edi+28]          ; save current file size
  2103.         cmp     ecx, [edi+28]
  2104.         jbe     .length_ok
  2105.         cmp     ecx, ebx
  2106.         jz      .length_ok
  2107.         call    hd_extend_file
  2108.         jnc     .length_ok
  2109.         mov     [esp+4], eax
  2110. ; hd_extend_file can return three error codes: FAT table error, device error or disk full.
  2111. ; First two cases are fatal errors, in third case we may write some data
  2112.         cmp     al, ERROR_DISK_FULL
  2113.         jz      .disk_full
  2114.         call    fat_unlock
  2115.         pop     eax
  2116.         pop     eax
  2117.         pop     ecx
  2118.         pop     edx
  2119.         pop     edi
  2120.         xor     ebx, ebx
  2121.         ret
  2122. .disk_full:
  2123. ; correct number of bytes to write
  2124.         mov     ecx, [edi+28]
  2125.         cmp     ecx, ebx
  2126.         ja      .length_ok
  2127.         push    0
  2128. .ret:
  2129.         pop     eax
  2130.         sub     edx, [esp+12]
  2131.         mov     ebx, edx        ; ebx=number of written bytes
  2132.         call    update_disk
  2133.         test    eax, eax
  2134.         jz      @f
  2135.         mov     byte [esp+4], ERROR_DEVICE
  2136. @@:
  2137.         call    fat_unlock
  2138.         pop     eax
  2139.         pop     eax
  2140.         pop     ecx
  2141.         pop     edx
  2142.         pop     edi
  2143.         ret
  2144. .length_ok:
  2145.         mov     esi, [edi+28]
  2146.         mov     eax, [edi+20-2]
  2147.         mov     ax, [edi+26]
  2148.         mov     edi, eax        ; edi=current cluster
  2149.         push    0               ; current sector in cluster
  2150. ; save directory
  2151.         mov     eax, [esp+12]
  2152.         push    ebx
  2153.         lea     ebx, [ebp+FAT.buffer]
  2154.         call    fs_write32_sys
  2155.         pop     ebx
  2156.         test    eax, eax
  2157.         jz      @f
  2158. .device_err:
  2159.         mov     byte [esp+8], ERROR_DEVICE
  2160.         jmp     .ret
  2161. .fat_err:
  2162.         mov     byte [esp+8], ERROR_FAT_TABLE
  2163.         jmp     .ret
  2164. @@:
  2165.  
  2166. ; now ebx=start pos, ecx=end pos, both lie inside file
  2167.         sub     ecx, ebx
  2168.         jz      .ret
  2169. .write_loop:
  2170. ; skip unmodified sectors
  2171.         cmp     dword [esp+4], 0x200
  2172.         jb      .modify
  2173.         sub     ebx, 0x200
  2174.         jae     .skip
  2175.         add     ebx, 0x200
  2176. .modify:
  2177. ; get length of data in current sector
  2178.         push    ecx
  2179.         sub     ebx, 0x200
  2180.         jb      .hasdata
  2181.         neg     ebx
  2182.         xor     ecx, ecx
  2183.         jmp     @f
  2184. .hasdata:
  2185.         neg     ebx
  2186.         cmp     ecx, ebx
  2187.         jbe     @f
  2188.         mov     ecx, ebx
  2189. @@:
  2190. ; get current sector number
  2191.         mov     eax, edi
  2192.         dec     eax
  2193.         dec     eax
  2194.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2195.         add     eax, [ebp+FAT.DATA_START]
  2196.         add     eax, [esp+4]
  2197. ; load sector if needed
  2198.         cmp     dword [esp+8], 0        ; we don't need to read uninitialized data
  2199.         jz      .noread
  2200.         cmp     ecx, 0x200      ; we don't need to read sector if it is fully rewritten
  2201.         jz      .noread
  2202.         cmp     ecx, esi        ; (same for the last sector)
  2203.         jz      .noread
  2204.         push    eax ebx
  2205.         lea     ebx, [ebp+FAT.buffer]
  2206.         call    fs_read32_app
  2207.         test    eax, eax
  2208.         pop     ebx eax
  2209.         jz      @f
  2210. .device_err2:
  2211.         pop     ecx
  2212.         jmp     .device_err
  2213. @@:
  2214. .noread:
  2215. ; zero uninitialized data if file was extended (because hd_extend_file does not this)
  2216.         push    eax ecx edi
  2217.         xor     eax, eax
  2218.         mov     ecx, 0x200
  2219.         sub     ecx, [esp+8+12]
  2220.         jbe     @f
  2221.         lea     edi, [ebp+FAT.buffer]
  2222.         add     edi, [esp+8+12]
  2223.         rep stosb
  2224. @@:
  2225. ; zero uninitialized data in the last sector
  2226.         mov     ecx, 0x200
  2227.         sub     ecx, esi
  2228.         jbe     @f
  2229.         lea     edi, [ebp+FAT.buffer+esi]
  2230.         rep stosb
  2231. @@:
  2232.         pop     edi ecx
  2233. ; copy new data
  2234.         mov     eax, edx
  2235.         neg     ebx
  2236.         jecxz   @f
  2237.         lea     ebx, [ebp+FAT.buffer+0x200+ebx]
  2238.         call    memmove
  2239.         xor     ebx, ebx
  2240. @@:
  2241.         pop     eax
  2242. ; save sector
  2243.         push    ebx
  2244.         lea     ebx, [ebp+FAT.buffer]
  2245.         call    fs_write32_app
  2246.         pop     ebx
  2247.         test    eax, eax
  2248.         jnz     .device_err2
  2249.         add     edx, ecx
  2250.         sub     [esp], ecx
  2251.         pop     ecx
  2252.         jz      .ret
  2253. .skip:
  2254. ; next sector
  2255.         pop     eax
  2256.         inc     eax
  2257.         push    eax
  2258.         cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2259.         jb      @f
  2260.         and     dword [esp], 0
  2261.         mov     eax, edi
  2262.         call    get_FAT
  2263.         mov     edi, eax
  2264.         jc      .device_err
  2265.         cmp     edi, 2
  2266.         jb      .fat_err
  2267.         cmp     edi, [ebp+FAT.fatRESERVED]
  2268.         jae     .fat_err
  2269. @@:
  2270.         sub     esi, 0x200
  2271.         jae     @f
  2272.         xor     esi, esi
  2273. @@:
  2274.         sub     dword [esp+4], 0x200
  2275.         jae     @f
  2276.         and     dword [esp+4], 0
  2277. @@:
  2278.         jmp     .write_loop
  2279.  
  2280. hd_extend_file.zero_size:
  2281.         xor     eax, eax
  2282.         jmp     hd_extend_file.start_extend
  2283.  
  2284. ; extends file on hd to given size (new data area is undefined)
  2285. ; in: edi->direntry, ecx=new size
  2286. ; out: CF=0 => OK, eax=0
  2287. ;      CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL or ERROR_DEVICE)
  2288. hd_extend_file:
  2289.         push    esi
  2290.         mov     esi, [ebp+FAT.SECTORS_PER_CLUSTER]
  2291.         imul    esi, [ebp+FAT.BYTES_PER_SECTOR]
  2292.         push    ecx
  2293. ; find the last cluster of file
  2294.         mov     eax, [edi+20-2]
  2295.         mov     ax, [edi+26]
  2296.         mov     ecx, [edi+28]
  2297.         jecxz   .zero_size
  2298. .last_loop:
  2299.         sub     ecx, esi
  2300.         jbe     .last_found
  2301.         call    get_FAT
  2302.         jnc     @f
  2303. .device_err:
  2304.         pop     ecx
  2305. .device_err2:
  2306.         pop     esi
  2307.         push    ERROR_DEVICE
  2308. .ret_err:
  2309.         pop     eax
  2310.         stc
  2311.         ret
  2312. @@:
  2313.         cmp     eax, 2
  2314.         jb      .fat_err
  2315.         cmp     eax, [ebp+FAT.fatRESERVED]
  2316.         jb      .last_loop
  2317. .fat_err:
  2318.         pop     ecx esi
  2319.         push    ERROR_FAT_TABLE
  2320.         jmp     .ret_err
  2321. .last_found:
  2322.         push    eax
  2323.         call    get_FAT
  2324.         jnc     @f
  2325.         pop     eax
  2326.         jmp     .device_err
  2327. @@:
  2328.         cmp     eax, [ebp+FAT.fatRESERVED]
  2329.         pop     eax
  2330.         jb      .fat_err
  2331. ; set length to full number of clusters
  2332.         sub     [edi+28], ecx
  2333. .start_extend:
  2334.         pop     ecx
  2335. ; now do extend
  2336.         push    edx
  2337.         mov     edx, 2          ; start scan from cluster 2
  2338. .extend_loop:
  2339.         cmp     [edi+28], ecx
  2340.         jae     .extend_done
  2341. ; add new cluster
  2342.         push    eax
  2343.         call    get_free_FAT
  2344.         jc      .disk_full
  2345.         mov     edx, [ebp+FAT.fatEND]
  2346.         call    set_FAT
  2347.         mov     edx, eax
  2348.         pop     eax
  2349.         test    eax, eax
  2350.         jz      .first_cluster
  2351.         push    edx
  2352.         call    set_FAT
  2353.         pop     edx
  2354.         jmp     @f
  2355. .first_cluster:
  2356.         ror     edx, 16
  2357.         mov     [edi+20], dx
  2358.         ror     edx, 16
  2359.         mov     [edi+26], dx
  2360. @@:
  2361.         push    ecx
  2362.         mov     ecx, -1
  2363.         call    add_disk_free_space
  2364.         pop     ecx
  2365.         mov     eax, edx
  2366.         add     [edi+28], esi
  2367.         jmp     .extend_loop
  2368. .extend_done:
  2369.         mov     [edi+28], ecx
  2370.         pop     edx esi
  2371.         xor     eax, eax        ; CF=0
  2372.         ret
  2373. .device_err3:
  2374.         pop     edx
  2375.         jmp     .device_err2
  2376. .disk_full:
  2377.         pop     eax edx esi
  2378.         push    ERROR_DISK_FULL
  2379.         pop     eax
  2380.         stc
  2381.         ret
  2382.  
  2383. ;----------------------------------------------------------------
  2384. ;
  2385. ;  fs_HdSetFileEnd - set end of file on hard disk
  2386. ;
  2387. ;  Obsolete, will be replaced with filesystem-specific functions.
  2388. ;
  2389. ;  esi  points to filename
  2390. ;  ebx  points to 64-bit number = new file size
  2391. ;  ecx  ignored (reserved)
  2392. ;  edx  ignored (reserved)
  2393. ;
  2394. ;  ret eax = 0 ok or other = errormsg
  2395. ;
  2396. ;--------------------------------------------------------------
  2397. fs_HdSetFileEnd:
  2398.         cmp     [fs_type], 16
  2399.         jz      @f
  2400.         cmp     [fs_type], 32
  2401.         jz      @f
  2402.         cmp     [fs_type], 1
  2403.         jz      ntfs_HdSetFileEnd
  2404.         cmp     [fs_type], 2
  2405.         jz      ext2_HdSetFileEnd
  2406.         push    ERROR_UNKNOWN_FS
  2407.         pop     eax
  2408.         ret
  2409. @@:
  2410.         sub     ebx, 4
  2411.         push    ebp
  2412.         mov     ebp, [fs_dependent_data_start.partition]
  2413.         call    fat_SetFileEnd
  2414.         pop     ebp
  2415.         ret
  2416.  
  2417. ;----------------------------------------------------------------
  2418. ; fat_SetFileEnd - FAT16/32 implementation of setting end-of-file
  2419. ; in:  ebp = pointer to FAT structure
  2420. ; in:  esi+[esp+4] = name
  2421. ; in:  ebx = pointer to parameters from sysfunc 70
  2422. ; out: eax, ebx = return values for sysfunc 70
  2423. ;----------------------------------------------------------------
  2424. fat_SetFileEnd:
  2425.         call    fat_lock
  2426.         push    edi
  2427.         cmp     byte [esi], 0
  2428.         jnz     @f
  2429. .access_denied:
  2430.         push    ERROR_ACCESS_DENIED
  2431. .ret:
  2432.         call    fat_unlock
  2433.         pop     eax
  2434.         pop     edi
  2435.         ret
  2436. @@:
  2437.         stdcall hd_find_lfn, [esp+4+4]
  2438.         jnc     @f
  2439. .reteax:
  2440.         push    eax
  2441.         jmp     .ret
  2442. @@:
  2443. ; must not be directory
  2444.         test    byte [edi+11], 10h
  2445.         jnz     .access_denied
  2446. ; file size must not exceed 4 Gb
  2447.         cmp     dword [ebx+8], 0
  2448.         jz      @f
  2449.         push    ERROR_END_OF_FILE
  2450.         jmp     .ret
  2451. @@:
  2452.         push    eax     ; save directory sector
  2453. ; set file modification date/time to current
  2454.         call    fat_update_datetime
  2455.         mov     eax, [ebx+4]
  2456.         cmp     eax, [edi+28]
  2457.         jb      .truncate
  2458.         ja      .expand
  2459.         pop     eax
  2460.         lea     ebx, [ebp+FAT.buffer]
  2461.         call    fs_write32_sys
  2462.         pop     edi
  2463.         test    eax, eax
  2464.         jz      @f
  2465.         push    ERROR_DEVICE
  2466.         jmp     .ret
  2467. @@:
  2468.         push    0
  2469.         jmp     .ret
  2470. .expand:
  2471.         push    ebx ebp ecx
  2472.         push    dword [edi+28]  ; save old size
  2473.         mov     ecx, eax
  2474.         call    hd_extend_file
  2475.         push    eax             ; return code
  2476.         jnc     .expand_ok
  2477.         cmp     al, ERROR_DISK_FULL
  2478.         jz      .disk_full
  2479. .pop_ret:
  2480.         call    update_disk
  2481.         pop     eax ecx ecx ebp ebx ecx
  2482.         jmp     .reteax
  2483. .expand_ok:
  2484. .disk_full:
  2485. ; save directory
  2486.         mov     eax, [edi+28]
  2487.         xchg    eax, [esp+20]
  2488.         lea     ebx, [ebp+FAT.buffer]
  2489.         call    fs_write32_sys
  2490.         test    eax, eax
  2491.         mov     eax, [edi+20-2]
  2492.         mov     ax, [edi+26]
  2493.         mov     edi, eax
  2494.         jz      @f
  2495. .pop_ret11:
  2496.         mov     byte [esp], ERROR_DEVICE
  2497.         jmp     .pop_ret
  2498. @@:
  2499.         test    edi, edi
  2500.         jz      .pop_ret
  2501. ; now zero new data
  2502.         push    0
  2503. ; edi=current cluster, [esp]=sector in cluster
  2504. ; [esp+24]=new size, [esp+8]=old size, [esp+4]=return code
  2505. .zero_loop:
  2506.         cmp     edi, 2
  2507.         jb      .error_fat
  2508.         cmp     edi, [ebp+FAT.fatRESERVED]
  2509.         jae     .error_fat
  2510.         sub     dword [esp+8], 0x200
  2511.         jae     .next_cluster
  2512.         lea     eax, [edi-2]
  2513.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2514.         add     eax, [ebp+FAT.DATA_START]
  2515.         add     eax, [esp]
  2516.         cmp     dword [esp+8], -0x200
  2517.         jz      .noread
  2518.         push    eax
  2519.         lea     ebx, [ebp+FAT.buffer]
  2520.         call    fs_read32_app
  2521.         test    eax, eax
  2522.         pop     eax
  2523.         jnz     .err_next
  2524. .noread:
  2525.         mov     ecx, [esp+8]
  2526.         neg     ecx
  2527.         push    edi
  2528.         lea     edi, [ebp+FAT.buffer+0x200]
  2529.         add     edi, [esp+12]
  2530.         push    eax
  2531.         xor     eax, eax
  2532.         mov     [esp+16], eax
  2533.         rep stosb
  2534.         pop     eax
  2535.         pop     edi
  2536.         call    fs_write32_app
  2537.         test    eax, eax
  2538.         jz      .next_cluster
  2539. .err_next:
  2540.         mov     byte [esp+4], ERROR_DEVICE
  2541. .next_cluster:
  2542.         pop     eax
  2543.         sub     dword [esp+20], 0x200
  2544.         jbe     .pop_ret
  2545.         inc     eax
  2546.         push    eax
  2547.         cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2548.         jb      .zero_loop
  2549.         and     dword [esp], 0
  2550.         mov     eax, edi
  2551.         call    get_FAT
  2552.         mov     edi, eax
  2553.         jnc     .zero_loop
  2554.         pop     eax
  2555.         jmp     .pop_ret11
  2556. .truncate:
  2557.         mov     [edi+28], eax
  2558.         push    ecx
  2559.         mov     ecx, [edi+20-2]
  2560.         mov     cx, [edi+26]
  2561.         push    eax
  2562.         test    eax, eax
  2563.         jz      .zero_size
  2564. ; find new last cluster
  2565. @@:
  2566.         cmp     ecx, 2
  2567.         jb      .error_fat2
  2568.         cmp     ecx, [ebp+FAT.fatRESERVED]
  2569.         jae     .error_fat2
  2570.         mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2571.         shl     eax, 9
  2572.         sub     [esp], eax
  2573.         jbe     @f
  2574.         mov     eax, ecx
  2575.         call    get_FAT
  2576.         mov     ecx, eax
  2577.         jnc     @b
  2578. .device_err3:
  2579.         pop     eax ecx eax edi
  2580.         call    update_disk
  2581.         call    fat_unlock
  2582.         push    ERROR_DEVICE
  2583.         pop     eax
  2584.         ret
  2585. @@:
  2586. ; we will zero data at the end of last sector - remember it
  2587.         push    ecx
  2588. ; terminate FAT chain
  2589.         push    edx
  2590.         mov     eax, ecx
  2591.         mov     edx, [ebp+FAT.fatEND]
  2592.         call    set_FAT
  2593.         mov     eax, edx
  2594.         pop     edx
  2595.         jnc     @f
  2596. .device_err4:
  2597.         pop     ecx
  2598.         jmp     .device_err3
  2599. .zero_size:
  2600.         and     word [edi+20], 0
  2601.         and     word [edi+26], 0
  2602.         push    0
  2603.         mov     eax, ecx
  2604. @@:
  2605. ; delete FAT chain
  2606.         call    clear_cluster_chain
  2607.         jc      .device_err4
  2608. ; save directory
  2609.         mov     eax, [esp+12]
  2610.         push    ebx
  2611.         lea     ebx, [ebp+FAT.buffer]
  2612.         call    fs_write32_sys
  2613.         pop     ebx
  2614.         test    eax, eax
  2615.         jnz     .device_err4
  2616. ; zero last sector, ignore errors
  2617.         pop     ecx
  2618.         pop     eax
  2619.         dec     ecx
  2620.         imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  2621.         add     ecx, [ebp+FAT.DATA_START]
  2622.         push    eax
  2623.         sar     eax, 9
  2624.         add     ecx, eax
  2625.         pop     eax
  2626.         and     eax, 0x1FF
  2627.         jz      .truncate_done
  2628.         push    ebx eax
  2629.         mov     eax, ecx
  2630.         lea     ebx, [ebp+FAT.buffer]
  2631.         call    fs_read32_app
  2632.         pop     eax
  2633.         lea     edi, [ebp+FAT.buffer+eax]
  2634.         push    ecx
  2635.         mov     ecx, 0x200
  2636.         sub     ecx, eax
  2637.         xor     eax, eax
  2638.         rep stosb
  2639.         pop     eax
  2640.         call    fs_write32_app
  2641.         pop     ebx
  2642. .truncate_done:
  2643.         pop     ecx eax edi
  2644.         call    update_disk
  2645.         call    fat_unlock
  2646.         xor     eax, eax
  2647.         ret
  2648. .error_fat:
  2649.         pop     eax
  2650.         mov     byte [esp], ERROR_FAT_TABLE
  2651.         jmp     .pop_ret
  2652. .error_fat2:
  2653.         pop     eax ecx eax edi
  2654.         call    update_disk
  2655.         call    fat_unlock
  2656.         push    ERROR_FAT_TABLE
  2657.         pop     eax
  2658.         ret
  2659.  
  2660. fs_HdGetFileInfo:
  2661.         cmp     [fs_type], 16
  2662.         jz      @f
  2663.         cmp     [fs_type], 32
  2664.         jz      @f
  2665.         cmp     [fs_type], 1
  2666.         jz      ntfs_HdGetFileInfo
  2667.         cmp     [fs_type], 2
  2668.         jz      ext2_HdGetFileInfo
  2669.         mov     eax, ERROR_UNKNOWN_FS
  2670.         ret
  2671. @@:
  2672.         sub     ebx, 4
  2673.         push    ebp
  2674.         mov     ebp, [fs_dependent_data_start.partition]
  2675.         call    fat_GetFileInfo
  2676.         pop     ebp
  2677.         ret
  2678.  
  2679. ;----------------------------------------------------------------
  2680. ; fat_GetFileInfo - FAT16/32 implementation of getting file info
  2681. ; in:  ebp = pointer to FAT structure
  2682. ; in:  esi+[esp+4] = name
  2683. ; in:  ebx = pointer to parameters from sysfunc 70
  2684. ; out: eax, ebx = return values for sysfunc 70
  2685. ;----------------------------------------------------------------
  2686. fat_GetFileInfo:
  2687.         cmp     byte [esi], 0
  2688.         jnz     @f
  2689.         mov     eax, 2
  2690.         ret
  2691. @@:
  2692.         push    edi
  2693.         call    fat_lock
  2694.         stdcall hd_find_lfn, [esp+4+4]
  2695.         jc      .error
  2696.         push    ebp
  2697.         xor     ebp, ebp
  2698.         mov     esi, [ebx+16]
  2699.         mov     dword [esi+4], ebp
  2700.         call    fat_entry_to_bdfe2
  2701.         pop     ebp
  2702.         call    fat_unlock
  2703.         xor     eax, eax
  2704.         pop     edi
  2705.         ret
  2706. .error:
  2707.         push    eax
  2708.         call    fat_unlock
  2709.         pop     eax
  2710.         pop     edi
  2711.         ret
  2712.  
  2713. fs_HdSetFileInfo:
  2714.         cmp     [fs_type], 16
  2715.         jz      @f
  2716.         cmp     [fs_type], 32
  2717.         jz      @f
  2718.         cmp     [fs_type], 1
  2719.         jz      ntfs_HdSetFileInfo
  2720.         cmp     [fs_type], 2
  2721.         jz      ext2_HdSetFileInfo
  2722.         mov     eax, ERROR_UNKNOWN_FS
  2723.         ret
  2724. @@:
  2725.         sub     ebx, 4
  2726.         push    ebp
  2727.         mov     ebp, [fs_dependent_data_start.partition]
  2728.         call    fat_SetFileInfo
  2729.         pop     ebp
  2730.         ret
  2731.  
  2732. ;----------------------------------------------------------------
  2733. ; fat_SetFileInfo - FAT16/32 implementation of setting file info
  2734. ; in:  ebp = pointer to FAT structure
  2735. ; in:  esi+[esp+4] = name
  2736. ; in:  ebx = pointer to parameters from sysfunc 70
  2737. ; out: eax, ebx = return values for sysfunc 70
  2738. ;----------------------------------------------------------------
  2739. fat_SetFileInfo:
  2740.         cmp     byte [esi], 0
  2741.         jnz     @f
  2742.         mov     eax, 2
  2743.         ret
  2744. @@:
  2745.         push    edi
  2746.         call    fat_lock
  2747.         stdcall hd_find_lfn, [esp+4+4]
  2748.         jc      .error
  2749.         push    eax
  2750.         mov     edx, [ebx+16]
  2751.         call    bdfe_to_fat_entry
  2752.         pop     eax
  2753.         lea     ebx, [ebp+FAT.buffer]
  2754.         call    fs_write32_sys
  2755.         call    update_disk
  2756.         call    fat_unlock
  2757.         pop     edi
  2758.         xor     eax, eax
  2759.         ret
  2760. .error:
  2761.         push    eax
  2762.         call    fat_unlock
  2763.         pop     eax
  2764.         pop     edi
  2765.         ret
  2766.  
  2767. ;----------------------------------------------------------------
  2768. ;
  2769. ;  fs_HdDelete - delete file or empty folder from hard disk
  2770. ;
  2771. ;  Obsolete, will be replaced with filesystem-specific functions.
  2772. ;
  2773. ;  esi  points to filename
  2774. ;
  2775. ;  ret  eax = 0 ok or other = errormsg
  2776. ;
  2777. ;--------------------------------------------------------------
  2778. fs_HdDelete:
  2779.         cmp     [fs_type], 16
  2780.         jz      @f
  2781.         cmp     [fs_type], 32
  2782.         jz      @f
  2783.         cmp     [fs_type], 1
  2784.         jz      ntfs_HdDelete
  2785.         cmp     [fs_type], 2
  2786.         jz      ext2_HdDelete
  2787.         push    ERROR_UNKNOWN_FS
  2788.         pop     eax
  2789.         ret
  2790. @@:
  2791.         sub     ebx, 4
  2792.         push    ebp
  2793.         mov     ebp, [fs_dependent_data_start.partition]
  2794.         call    fat_Delete
  2795.         pop     ebp
  2796.         ret
  2797.  
  2798. ;----------------------------------------------------------------
  2799. ; fat_Delete - FAT16/32 implementation of deleting a file/folder
  2800. ; in:  ebp = pointer to FAT structure
  2801. ; in:  esi+[esp+4] = name
  2802. ; in:  ebx = pointer to parameters from sysfunc 70
  2803. ; out: eax, ebx = return values for sysfunc 70
  2804. ;----------------------------------------------------------------
  2805. fat_Delete:
  2806.         call    fat_lock
  2807.         cmp     byte [esi], 0
  2808.         jnz     @f
  2809. ; cannot delete root!
  2810. .access_denied:
  2811.         push    ERROR_ACCESS_DENIED
  2812. .pop_ret:
  2813.         call    fat_unlock
  2814.         pop     eax
  2815.         xor     ebx, ebx
  2816.         ret
  2817. @@:
  2818.         and     [ebp+FAT.longname_sec1], 0
  2819.         and     [ebp+FAT.longname_sec2], 0
  2820.         push    edi
  2821.         stdcall hd_find_lfn, [esp+4+4]
  2822.         jnc     .found
  2823.         pop     edi
  2824.         push    ERROR_FILE_NOT_FOUND
  2825.         jmp     .pop_ret
  2826. .found:
  2827.         cmp     dword [edi], '.   '
  2828.         jz      .access_denied2
  2829.         cmp     dword [edi], '..  '
  2830.         jz      .access_denied2
  2831.         test    byte [edi+11], 10h
  2832.         jz      .dodel
  2833. ; we can delete only empty folders!
  2834.         pushad
  2835.         mov     esi, [edi+20-2]
  2836.         mov     si, [edi+26]
  2837.         xor     ecx, ecx
  2838.         lea     eax, [esi-2]
  2839.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2840.         add     eax, [ebp+FAT.DATA_START]
  2841.         lea     ebx, [ebp+FAT.buffer]
  2842.         call    fs_read32_sys
  2843.         test    eax, eax
  2844.         jnz     .err1
  2845.         lea     eax, [ebx+0x200]
  2846.         add     ebx, 2*0x20
  2847. .checkempty:
  2848.         cmp     byte [ebx], 0
  2849.         jz      .empty
  2850.         cmp     byte [ebx], 0xE5
  2851.         jnz     .notempty
  2852.         add     ebx, 0x20
  2853.         cmp     ebx, eax
  2854.         jb      .checkempty
  2855.         inc     ecx
  2856.         cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  2857.         jb      @f
  2858.         mov     eax, esi
  2859.         call    get_FAT
  2860.         jc      .err1
  2861.         mov     esi, eax
  2862.         xor     ecx, ecx
  2863. @@:
  2864.         lea     eax, [esi-2]
  2865.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2866.         add     eax, [ebp+FAT.DATA_START]
  2867.         add     eax, ecx
  2868.         lea     ebx, [ebp+FAT.buffer]
  2869.         call    fs_read32_sys
  2870.         test    eax, eax
  2871.         lea     eax, [ebx+0x200]
  2872.         jz      .checkempty
  2873. .err1:
  2874.         popad
  2875. .err2:
  2876.         pop     edi
  2877.         call    fat_unlock
  2878.         push    ERROR_DEVICE
  2879.         pop     eax
  2880.         ret
  2881. .notempty:
  2882.         popad
  2883. .access_denied2:
  2884.         pop     edi
  2885.         call    fat_unlock
  2886.         push    ERROR_ACCESS_DENIED
  2887.         pop     eax
  2888.         ret
  2889. .empty:
  2890.         popad
  2891.         push    eax ebx
  2892.         lea     ebx, [ebp+FAT.buffer]
  2893.         call    fs_read32_sys
  2894.         test    eax, eax
  2895.         pop     ebx eax
  2896.         jnz     .err2
  2897. .dodel:
  2898.         push    eax
  2899.         mov     eax, [edi+20-2]
  2900.         mov     ax, [edi+26]
  2901.         xchg    eax, [esp]
  2902. ; delete folder entry
  2903.         mov     byte [edi], 0xE5
  2904. ; delete LFN (if present)
  2905. .lfndel:
  2906.         lea     edx, [ebp+FAT.buffer]
  2907.         cmp     edi, edx
  2908.         ja      @f
  2909.         cmp     [ebp+FAT.longname_sec2], 0
  2910.         jz      .lfndone
  2911.         push    [ebp+FAT.longname_sec2]
  2912.         push    [ebp+FAT.longname_sec1]
  2913.         pop     [ebp+FAT.longname_sec2]
  2914.         and     [ebp+FAT.longname_sec1], 0
  2915.         push    ebx
  2916.         mov     ebx, edx
  2917.         call    fs_write32_sys
  2918.         mov     eax, [esp+4]
  2919.         call    fs_read32_sys
  2920.         pop     ebx
  2921.         pop     eax
  2922.         lea     edi, [ebp+FAT.buffer+0x200]
  2923. @@:
  2924.         sub     edi, 0x20
  2925.         cmp     byte [edi], 0xE5
  2926.         jz      .lfndone
  2927.         cmp     byte [edi+11], 0xF
  2928.         jnz     .lfndone
  2929.         mov     byte [edi], 0xE5
  2930.         jmp     .lfndel
  2931. .lfndone:
  2932.         push    ebx
  2933.         lea     ebx, [ebp+FAT.buffer]
  2934.         call    fs_write32_sys
  2935.         pop     ebx
  2936. ; delete FAT chain
  2937.         pop     eax
  2938.         call    clear_cluster_chain
  2939.         call    update_disk
  2940.         call    fat_unlock
  2941.         pop     edi
  2942.         xor     eax, eax
  2943.         ret
  2944.  
  2945. ; \end{diamond}
  2946.