Subversion Repositories Kolibri OS

Rev

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