Subversion Repositories Kolibri OS

Rev

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

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