Subversion Repositories Kolibri OS

Rev

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

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