Subversion Repositories Kolibri OS

Rev

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

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