Subversion Repositories Kolibri OS

Rev

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