Subversion Repositories Kolibri OS

Rev

Rev 9698 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
  4. ;;  Distributed under terms of the GNU General Public License.  ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 9734 $
  9.  
  10. ERROR_SUCCESS        = 0
  11. ERROR_DISK_BASE      = 1
  12. ERROR_UNSUPPORTED_FS = 2
  13. ERROR_UNKNOWN_FS     = 3
  14. ERROR_PARTITION      = 4
  15. ERROR_FILE_NOT_FOUND = 5
  16. ERROR_END_OF_FILE    = 6
  17. ERROR_MEMORY_POINTER = 7
  18. ERROR_DISK_FULL      = 8
  19. ERROR_FS_FAIL        = 9
  20. ERROR_ACCESS_DENIED  = 10
  21. ERROR_DEVICE         = 11
  22.  
  23. maxPathLength = 1000h
  24.  
  25. image_of_eax EQU esp+32
  26. image_of_ebx EQU esp+20
  27.  
  28. ; System function 70 security check
  29. align 4
  30. proc file_system_is_operation_safe stdcall, inf_struct_ptr: dword
  31. ; in:
  32. ;      inf_struct_ptr = pointer to information structure was given to sysfn70
  33. ; out: ZF = 1 if operation is safe
  34. ;      ZF = 0 if operation can cause kernel crash
  35.         push    ebx ecx edx
  36.         xor     ecx, ecx ; ecx - length of target buffer
  37.  
  38.         mov     ebx, [inf_struct_ptr]
  39.         mov     edx, [ebx + 16] ; base of target buffer
  40.  
  41.         cmp     dword [ebx], 0 ; if 70.0
  42.         jnz     .case1
  43.         mov     ecx, dword [ebx + 12]
  44.         jmp     .end_switch
  45.  
  46. .case1:
  47.         cmp     dword [ebx], 1 ; if 70.1
  48.         jnz     .case2_3
  49.         ;mov     ecx, 32
  50.         cmp     dword [ebx + 8], 1 ; check encoding
  51.         jbe     .case1_304 ; if encdoing <= 1 i.e cpp866
  52.         mov     ecx, 560 ; if unicode then bdvk block len is 560 bytes
  53.         jmp     .case1_end
  54. .case1_304:
  55.         mov     ecx, 304 ; if cp866 then bdvk block len is 304 bytes
  56. .case1_end:
  57.         imul    ecx, dword [ebx + 12] ; multiply bdvk length by their count
  58.         add     ecx, 32 ; add result header len
  59.         jmp     .end_switch
  60.  
  61. .case2_3:
  62.         cmp     dword [ebx], 3
  63.         ja      .case5 ; if subfn > 3
  64.         mov     ecx, dword [ebx + 12]
  65.         jmp     .end_switch
  66.  
  67. .case5:
  68.         cmp     dword [ebx], 5
  69.         jnz     .case6
  70.         mov     ecx, 40
  71.         jmp     .end_switch
  72.  
  73. .case6:
  74.         cmp     dword [ebx], 6
  75.         jnz     .switch_none
  76.         mov     ecx, 32
  77.         jmp     .end_switch
  78.  
  79. .switch_none:
  80.         cmp     ecx, ecx
  81.         jmp     .ret
  82.      
  83. .end_switch:
  84.         stdcall is_region_userspace, edx, ecx
  85. .ret:
  86.         pop     edx ecx ebx
  87.         ret
  88. endp
  89.  
  90. sys_fileSystemUnicode: ; with user pointer correctness checking
  91. ; in: ebx -> f.80 parameter structure
  92.         stdcall file_system_is_operation_safe, ebx
  93.         jz      @f
  94.  
  95.         DEBUGF  1, "sysfn80 addr error\n"
  96.         mov     dword [image_of_eax], ERROR_MEMORY_POINTER
  97.         ret
  98. @@:
  99.         jmp     fileSystemUnicode
  100.  
  101. ;System function 70
  102. sys_file_system_lfn: ; with user pointer correctness checking
  103. ; in: ebx -> f.70 parameter structure
  104.         stdcall file_system_is_operation_safe, ebx
  105.         jz      @f
  106.  
  107.         DEBUGF  1, "sysfn70 addr error\n"
  108.         mov     dword [image_of_eax], ERROR_MEMORY_POINTER
  109.         ret
  110. @@:
  111.         jmp     file_system_lfn
  112.  
  113. ;file_system_lfn_protected returns values not in registers, but in their images
  114. ;on stack. Make a short wrapper to actually return values in registers.
  115. file_system_lfn_protected_registers:
  116.         pushad
  117.         call    file_system_lfn_protected
  118.         popad
  119.         ret
  120.  
  121. file_system_lfn_protected:
  122.         pushad
  123.         call    protect_from_terminate
  124.         call    file_system_lfn
  125.         call    unprotect_from_terminate
  126.         popad
  127.         mov     [image_of_eax], eax
  128.         mov     [image_of_ebx], ebx
  129.         ret
  130.  
  131. fileSystemUnicode:
  132. ; in: ebx -> f.80 parameter structure
  133.         mov     edi, [ebx+20]
  134.         mov     esi, [ebx+24]
  135.         jmp     @f
  136.  
  137. file_system_lfn:
  138. ; in: ebx -> f.70 parameter structure
  139.         xor     edi, edi
  140.         lea     esi, [ebx+20]
  141.         cmp     byte [esi], 0
  142.         jnz     @f
  143.         mov     esi, [ebx+21]
  144. @@:
  145.         cmp     word [esi], '/'
  146.         jnz     @f
  147.         cmp     edi, 2
  148.         jnz     .rootdir
  149.         cmp     dword[esi], '/'
  150.         jz      .rootdir
  151. @@:
  152.         stdcall kernel_alloc, maxPathLength
  153.         push    eax ebx
  154.         xchg    eax, edi
  155.         call    getFullPath
  156.         pop     ebx ebp
  157.         test    eax, eax
  158.         jz      .notfound
  159.         cmp     dword[ebx], 7   ; start application
  160.         jnz     @f
  161.         mov     edx, [ebx+4]
  162.         mov     ecx, [ebx+8]
  163.         mov     ebx, ebp
  164.         call    fs_execute
  165.         mov     [image_of_eax], eax
  166.         ret
  167.  
  168. @@:
  169.         lea     esi, [ebp+2]
  170.         mov     ax, [esi]
  171.         or      ax, 2020h
  172.         cmp     ax, 'cd'
  173.         jz      .CD
  174.         call    dyndisk_handler ; not returns if success
  175. .notfound:
  176.         stdcall kernel_free, ebp
  177.         mov     dword[image_of_eax], ERROR_FILE_NOT_FOUND
  178.         ret
  179.  
  180. .CD:
  181.         add     esi, 2
  182.         xor     eax, eax
  183.         lodsb       ; disk number
  184.         sub     eax, '0'
  185.         cmp     eax, 10
  186.         jnc     .notfound
  187.         mov     edi, eax
  188.         lodsb
  189.         test    eax, eax
  190.         jz      .maindir
  191.         cmp     al, '/'
  192.         jnz     .notfound
  193.         lodsb       ; partition number
  194.         test    eax, eax
  195.         jz      .maindir
  196.         cmp     al, '1'
  197.         jnz     .notfound
  198.         cmp     byte [esi], '/'
  199.         jnz     @f
  200.         inc     esi
  201. @@:
  202.         call    reserve_cd
  203.         mov     eax, edi
  204.         bt      eax, 0
  205.         setc    [DiskNumber]
  206.         bt      eax, 1
  207.         setc    [ChannelNumber]
  208.         inc     [ChannelNumber]
  209.         inc     eax
  210.         mov     [cdpos], eax
  211.         call    reserve_cd_channel
  212.         mov     eax, edi
  213.         not     eax
  214.         and     eax, 3
  215.         shl     eax, 1
  216.         inc     eax
  217.         shr     edi, 2
  218.         mov     dword[image_of_eax], ERROR_FILE_NOT_FOUND
  219.         bt      [edi*5+DRIVE_DATA+1], ax
  220.         jnc     @f
  221.         mov     ecx, [ebx+12]
  222.         mov     edx, [ebx+16]
  223.         mov     eax, [ebx]
  224.         mov     dword[image_of_eax], ERROR_UNSUPPORTED_FS
  225.         cmp     eax, fs_NumCdServices
  226.         jae     @f
  227.         add     ebx, 4
  228.         push    ebp
  229.         call    dword[fs_CdServices + eax*4]
  230.         pop     ebp
  231.         mov     [image_of_eax], eax
  232.         mov     [image_of_ebx], ebx
  233. @@:
  234.         call    free_cd_channel
  235.         and     [cd_status], 0
  236.         stdcall kernel_free, ebp
  237.         ret
  238.  
  239. .nextCD:
  240.         test    eax, eax    ; partition number
  241.         jnz     @f
  242.         inc     eax     ; /cdX/1
  243.         ret
  244.  
  245. @@:
  246.         stc
  247.         ret
  248.  
  249. .maindir:   ; list partitions
  250.         mov     esi, .nextCD
  251.         xor     ecx, ecx
  252. .maindir_noesi:     ; backjump from dyndisk_handler
  253.         push    ebp
  254.         mov     ebp, ecx
  255.         call    kernel_free
  256.         mov     edi, [ebx+16]   ; buffer
  257.         cmp     byte [ebx], 5
  258.         jz      .deviceInfo
  259.         cmp     byte [ebx], 1   ; read folder?
  260.         jnz     .access_denied
  261.         push    ebp
  262.         pushd   [ebx+4]         ; first block
  263.         mov     ebp, [ebx+12]   ; the number of blocks to read
  264.         mov     ebx, [ebx+8]    ; flags
  265.         mov     ecx, 32/4
  266.         mov     edx, edi
  267.         xor     eax, eax
  268.         rep stosd
  269.         mov     byte [edx], 1   ; version
  270. .maindir_loop:
  271.         call    esi
  272.         jc      .maindir_done
  273.         inc     dword[edx+8]
  274.         dec     dword[esp]
  275.         jns     .maindir_loop
  276.         dec     ebp
  277.         js      .maindir_loop
  278.         inc     dword[edx+4]
  279.         mov     dword[edi], 16      ; attributes: folder
  280.         mov     dword[edi+4], ebx   ; name encoding
  281.         push    eax
  282.         mov     ecx, 32/4
  283.         add     edi, 8
  284.         xor     eax, eax
  285.         rep stosd
  286.         pop     eax
  287.         push    eax edx edi
  288. ; convert number in eax to decimal string
  289.         push    -'0'
  290.         mov     ecx, 10
  291. @@:
  292.         xor     edx, edx
  293.         div     ecx
  294.         push    edx
  295.         test    eax, eax
  296.         jnz     @b
  297.         cmp     ebx, 2
  298.         jz      .uni
  299. @@:
  300.         pop     eax
  301.         add     eax, '0'
  302.         stosb
  303.         test    eax, eax
  304.         jnz     @b
  305.         pop     edi edx eax
  306.         cmp     ebx, 3
  307.         jz      @f
  308.         add     edi, 264
  309.         jmp     .maindir_loop
  310.  
  311. .uni:
  312.         pop     eax
  313.         add     eax, '0'
  314.         stosw
  315.         test    eax, eax
  316.         jnz     .uni
  317.         pop     edi edx eax
  318. @@:
  319.         add     edi, 520
  320.         jmp     .maindir_loop
  321.  
  322. .maindir_done:
  323.         pop     eax eax
  324.         mov     ebx, [edx+4]
  325.         xor     eax, eax
  326.         dec     ebp
  327.         js      @f
  328.         mov     al, ERROR_END_OF_FILE
  329. @@:
  330.         mov     [image_of_eax], eax
  331.         mov     [image_of_ebx], ebx
  332.         ret
  333.  
  334. .access_denied:
  335.         mov     dword[image_of_eax], ERROR_ACCESS_DENIED
  336.         ret
  337.  
  338. .deviceInfo:
  339.         test    ebp, ebp
  340.         jz      @f
  341.         mov     eax, dword[ebp+DISK.MediaInfo.Capacity]
  342.         mov     edx, dword[ebp+DISK.MediaInfo.Capacity+4]
  343.         shld    edx, eax, 9
  344.         shl     eax, 9
  345.         mov     [edi+36], edx
  346.         mov     [edi+32], eax
  347. @@:
  348.         and     dword[image_of_eax], 0
  349.         ret
  350.  
  351. .rootdir:   ; / - virtual root folder
  352.         cmp     byte [ebx], 5
  353.         jz      @b
  354.         cmp     byte [ebx], 1   ; read folder?
  355.         jnz     .access_denied
  356.         mov     ebp, [ebx+12]   ; number of blocks
  357.         mov     edx, [ebx+16]   ; return area
  358.         push    dword[ebx+4]    ; first block
  359.         mov     ebx, [ebx+8]    ; flags
  360.         mov     ecx, 32/4
  361.         mov     edi, edx
  362.         xor     eax, eax
  363.         rep stosd
  364.         mov     byte [edx], 1   ; version
  365.         sub     esp, 16
  366. .rootdir_loop:
  367.         push    edi
  368.         lea     edi, [esp+4]
  369.         call    dyndisk_enum_root
  370.         pop     edi
  371.         test    eax, eax
  372.         jz      .rootdirCD
  373.         inc     dword[edx+8]
  374.         dec     dword[esp+16]
  375.         jns     .rootdir_loop
  376.         dec     ebp
  377.         js      .rootdir_loop
  378.         inc     dword[edx+4]
  379.         mov     dword[edi], 16      ; attributes: folder
  380.         mov     dword[edi+4], ebx   ; name encoding
  381.         push    eax
  382.         mov     ecx, 32/4
  383.         add     edi, 8
  384.         xor     eax, eax
  385.         rep stosd
  386.         push    edi
  387.         lea     esi, [esp+8]
  388.         cmp     ebx, 2
  389.         jz      .uni2
  390. @@:
  391.         lodsb
  392.         stosb
  393.         test    eax, eax
  394.         jnz     @b
  395.         pop     edi eax
  396.         cmp     ebx, 3
  397.         jz      @f
  398.         add     edi, 264
  399.         jmp     .rootdir_loop
  400.  
  401. .uni2:
  402.         lodsb
  403.         stosw
  404.         test    eax, eax
  405.         jnz     .uni2
  406.         pop     edi eax
  407. @@:
  408.         add     edi, 520
  409.         jmp     .rootdir_loop
  410.  
  411. .rootdirCD:
  412.         add     esp, 16
  413.         or      esi, -1
  414. .rootdirCD_loop:
  415.         inc     esi
  416.         cmp     esi, 10
  417.         jnc     .rootdir_done
  418.         mov     eax, esi
  419.         not     eax
  420.         and     eax, 3
  421.         shl     eax, 1
  422.         inc     eax
  423.         mov     ecx, esi
  424.         shr     ecx, 2
  425.         bt      [ecx*5+DRIVE_DATA+1], ax
  426.         jnc     .rootdirCD_loop
  427.         inc     dword[edx+8]
  428.         dec     dword[esp]
  429.         jns     .rootdirCD_loop
  430.         dec     ebp
  431.         js      .rootdirCD_loop
  432.         inc     dword[edx+4]
  433.         mov     dword[edi], 16      ; attributes: folder
  434.         mov     dword[edi+4], ebx   ; name encoding
  435.         mov     ecx, 32/4
  436.         add     edi, 8
  437.         xor     eax, eax
  438.         rep stosd
  439.         mov     eax, esi
  440.         add     eax, '0'
  441.         cmp     ebx, 1
  442.         jz      @f
  443.         mov     word [edi], 'cd'
  444.         mov     [edi+2], ax
  445.         add     edi, 264
  446.         jmp     .rootdirCD_loop
  447.  
  448. @@:
  449.         mov     dword[edi], 640063h
  450.         mov     [edi+4], eax
  451.         add     edi, 520
  452.         jmp     .rootdirCD_loop
  453.  
  454. .rootdir_done:
  455.         pop     eax
  456.         mov     ebx, [edx+4]
  457.         xor     eax, eax
  458.         dec     ebp
  459.         js      @f
  460.         mov     al, ERROR_END_OF_FILE
  461. @@:
  462.         mov     [image_of_eax], eax
  463.         mov     [image_of_ebx], ebx
  464.         ret
  465.  
  466. ;-----------------------------------------------------------------------------
  467. process_replace_file_name:
  468. ; in: [esi] = virtual path
  469. ; out: [esi]+[ebp] = physical path
  470.         xor     edi, edi
  471.         xor     ebp, ebp
  472. .loop:
  473.         cmp     edi, [full_file_name_table.size]
  474.         jae     .notfound
  475.         push    esi edi
  476.         shl     edi, 7
  477.         add     edi, [full_file_name_table]
  478. @@:
  479.         cmp     byte [edi], 0
  480.         jz      .dest_done
  481.         lodsb
  482.         test    al, al
  483.         jz      .cont
  484.         scasb
  485.         jz      @b
  486.         or      al, 20h
  487.         cmp     [edi-1], al
  488.         jz      @b
  489. .cont:
  490.         pop     edi esi
  491.         inc     edi
  492.         jmp     .loop
  493.  
  494. .dest_done:
  495.         cmp     byte [esi], 0
  496.         jz      .found
  497.         cmp     byte [esi], '/'
  498.         jnz     .cont
  499. .found:
  500.         pop     edi eax
  501.         shl     edi, 7
  502.         add     edi, [full_file_name_table]
  503.         mov     ebp, esi
  504.         lea     esi, [edi+64]
  505. .notfound:
  506.         ret
  507.  
  508. ;-----------------------------------------------------------------------------
  509. uglobal
  510. addDirSeal db  ?
  511. endg
  512.  
  513. sys_current_directory:  ; sysfunction 30
  514.         mov     eax, [current_slot]
  515.         mov     edi, [eax+APPDATA.cur_dir]
  516.         xor     eax, eax
  517.         dec     ebx
  518.         jz      .set
  519.         dec     ebx
  520.         jz      .get
  521.         dec     ebx
  522.         jz      .mount_additional_directory
  523.         mov     eax, edx
  524.         dec     ebx
  525.         jz      .set
  526.         mov     eax, esi
  527.         dec     ebx
  528.         jz      .get
  529. @@:
  530.         ret
  531.  
  532. .mount_additional_directory:
  533. ; in: ecx -> dir name+dir path (128)
  534.         mov     al, 1
  535.         xchg    [addDirSeal], al
  536.         test    al, al
  537.         jnz     @b
  538.         mov     esi, ecx
  539.         mov     edi, sysdir_name1
  540.         mov     ecx, 64
  541.         rep movsb   ; copying fake directory name
  542.         mov     byte [edi-1], 0
  543.         mov     cl, 63
  544.         call    cp866toUTF8_string
  545.         mov     byte [edi], 0
  546.         mov     [full_file_name_table.size], 2
  547.         ret
  548.  
  549. .get:
  550. ; in: ecx -> buffer, edx = length, eax = encoding
  551.         stdcall is_region_userspace, ecx, edx
  552.         jz      @f
  553.  
  554.         ; if illegal buffer given
  555.         xor     edx, edx
  556.         jmp     .ret
  557. @@:
  558.  
  559.         mov     esi, edi
  560.         inc     esi
  561.         mov     edi, ecx
  562.         cmp     edx, maxPathLength
  563.         jc      @f
  564.         mov     edx, maxPathLength
  565. @@:
  566.         mov     ecx, edx
  567.         jecxz   .ret
  568.         cmp     eax, 2
  569.         jz      .get16
  570.         cmp     eax, 3
  571.         jz      .get8
  572. @@:
  573.         dec     ecx
  574.         js      @f
  575.         call    utf8to16
  576.         call    uni2ansi_char
  577.         stosb
  578.         test    al, al
  579.         jnz     @b
  580.         sub     edx, ecx
  581. @@:
  582.         mov     byte [edi-1], 0
  583. .ret:
  584.         mov     [esp+32], edx
  585.         ret
  586.  
  587. .get8:
  588.         push    edi
  589.         mov     edi, esi
  590.         xor     eax, eax
  591.         repnz scasb
  592.         sub     edx, ecx
  593.         mov     ecx, edx
  594.         pop     edi
  595.         rep movsb
  596.         jmp     @b
  597.  
  598. .get16:
  599.         shr     ecx, 1
  600.         shr     edx, 1
  601. @@:
  602.         dec     ecx
  603.         js      @f
  604.         call    utf8to16
  605.         stosw
  606.         test    ax, ax
  607.         jnz     @b
  608.         sub     edx, ecx
  609. @@:
  610.         shl     edx, 1
  611.         mov     word [edi-2], 0
  612.         jmp     .ret
  613.  
  614. .set:
  615.         mov     esi, ecx
  616. getFullPath:
  617. ; in: esi -> file path, eax = string encoding, edi -> destination
  618. ; out: UTF-8 string (with marker), eax = length, 0 -> error
  619.         test    eax, eax
  620.         jnz     @f
  621.         cmp     byte [esi], 4
  622.         jnc     @f
  623.         cmp     byte [esi], 0
  624.         jz      @f
  625.         lodsb
  626. @@:
  627.         cmp     byte [esi], '/'
  628.         jnz     .relative
  629.         cmp     eax, 2
  630.         jnz     @f
  631.         cmp     word [esi], '/'
  632.         jnz     .relative
  633.         inc     esi
  634.         inc     esi
  635.         jmp     .start
  636.  
  637. @@:
  638.         inc     esi
  639.         cmp     byte [esi], 4
  640.         jnc     .start
  641.         lodsb
  642.         cmp     byte [esi], '/'
  643.         jnz     .start
  644.         inc     esi
  645. .start:
  646.         push    eax edi
  647.         call    process_replace_file_name
  648.         mov     edi, [esp]
  649.         mov     ecx, maxPathLength
  650.         mov     al, 3
  651.         mov     ah, '/'
  652.         stosw
  653.         sub     ecx, 2
  654.         test    ebp, ebp
  655.         jz      .absolute
  656. @@:
  657.         lodsb
  658.         stosb
  659.         dec     ecx
  660.         test    al, al
  661.         jnz     @b
  662.         mov     esi, ebp
  663.         dec     edi
  664. .absolute:
  665.         cmp     byte [esp+4], 2
  666.         jz      .utf16
  667.         cmp     byte [esp+4], 3
  668.         jz      .utf8
  669.         call    cp866toUTF8_string
  670.         jns     .end
  671.         jmp     .fail
  672.  
  673. .utf8:
  674.         dec     ecx
  675.         js      .fail
  676.         lodsb
  677.         stosb
  678.         test    al, al
  679.         jz      .end
  680.         jmp     .utf8
  681.  
  682. .utf16:
  683.         call    UTF16to8_string
  684.         jns     .end
  685. .fail:
  686.         mov     byte [edi], 0
  687.         pop     eax eax
  688.         xor     eax, eax
  689.         ret
  690.  
  691. .relative:
  692.         push    eax edi
  693.         mov     ebx, esi
  694.         mov     edi, [current_slot]
  695.         mov     edi, [edi+APPDATA.cur_dir]
  696.         mov     edx, edi
  697.         mov     ecx, maxPathLength
  698.         xor     eax, eax
  699.         repnz scasb
  700.         mov     esi, edi
  701.         mov     edi, [esp]
  702.         jecxz   .fail
  703.         cmp     byte [ebx], 0
  704.         jz      .set_ok
  705.         dec     esi
  706.         cmp     edx, edi    ; is destination equal to cur_dir?
  707.         mov     edi, esi
  708.         jz      @f
  709.         mov     edi, [esp]
  710.         mov     ecx, esi
  711.         sub     ecx, edx
  712.         mov     esi, edx
  713.         mov     edx, edi
  714.         rep movsb
  715. @@:
  716.         mov     byte [edi], '/'
  717.         inc     edi
  718.         mov     esi, ebx
  719.         mov     ecx, edx
  720.         add     ecx, maxPathLength
  721.         sub     ecx, edi
  722.         jmp     .absolute
  723.  
  724. .set_ok:
  725.         cmp     edx, edi    ; is destination equal to cur_dir?
  726.         jz      @f
  727.         mov     ecx, esi
  728.         sub     ecx, edx
  729.         mov     esi, edx
  730.         rep movsb
  731. @@:
  732.         pop     eax
  733.         sub     edi, eax
  734.         pop     eax
  735.         mov     eax, edi
  736.         ret
  737.  
  738. .end:
  739.         or      ecx, -1
  740.         mov     edi, [esp]
  741.         xor     eax, eax
  742.         push    edi
  743.         repnz scasb
  744.         not     ecx
  745.         pop     edi
  746. .parse:
  747.         mov     al, '/'
  748.         repnz scasb
  749.         jecxz   @b
  750.         cmp     byte [edi], '.'
  751.         jnz     .parse
  752.         mov     esi, edi
  753. @@:
  754.         lodsw
  755.         sub     ecx, 2
  756.         cmp     ax, './'
  757.         jz      @b
  758.         cmp     ax, '..'
  759.         jnz     @f
  760.         cmp     byte [esi], '/'
  761.         jnz     @f
  762.         mov     edx, ecx
  763.         mov     ecx, edi
  764.         sub     ecx, [esp]
  765.         sub     ecx, 2
  766.         jc      .fail
  767.         sub     edi, 2
  768.         lodsb
  769.         dec     edx
  770.         std
  771.         repnz scasb
  772.         cld
  773.         add     edi, 2
  774.         mov     ecx, edx
  775.         jmp     @b
  776.  
  777. @@:
  778.         sub     esi, 2
  779.         add     ecx, 2
  780.         cmp     esi, edi
  781.         jz      .parse
  782.         push    edi ecx
  783.         rep movsb
  784.         pop     ecx edi
  785.         jmp     .parse
  786.  
  787. include "parse_fn.inc"
  788. include "fs_common.inc"
  789. include "iso9660.inc"   ; read for CD filesystem
  790. include "fat.inc"
  791. include "exfat.inc"
  792. include "ntfs.inc"
  793. include "ext.inc"
  794. include "xfs.asm"
  795.