Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 4277 $
  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_FAT_TABLE      = 9 ;deprecated
  20. ERROR_FS_FAIL        = 9
  21. ERROR_ACCESS_DENIED  = 10
  22. ERROR_DEVICE         = 11
  23.  
  24. image_of_eax EQU esp+32
  25. image_of_ebx EQU esp+20
  26.  
  27. ; System function 70 - files with long names (LFN)
  28. ; diamond, 2006
  29.  
  30. iglobal
  31. ; in this table names must be in lowercase
  32. rootdirs:
  33. ;**********************************************
  34.         db      3,'cd0'
  35.         dd      fs_OnCd0
  36.         dd      fs_NextCd
  37.         db      3,'cd1'
  38.         dd      fs_OnCd1
  39.         dd      fs_NextCd
  40.         db      3,'cd2'
  41.         dd      fs_OnCd2
  42.         dd      fs_NextCd
  43.         db      3,'cd3'
  44.         dd      fs_OnCd3
  45.         dd      fs_NextCd
  46. ;***********************************************
  47.         db      0
  48.  
  49.  
  50. virtual_root_query:
  51. ;**********************************************
  52.         dd      fs_HasCd0
  53.         db      'cd0',0
  54.         dd      fs_HasCd1
  55.         db      'cd1',0
  56.         dd      fs_HasCd2
  57.         db      'cd2',0
  58.         dd      fs_HasCd3
  59.         db      'cd3',0
  60. ;**********************************************
  61.         dd      0
  62. endg
  63.  
  64. file_system_lfn_protected:
  65.         pushad
  66.         call    protect_from_terminate
  67.         call    file_system_lfn
  68.         call    unprotect_from_terminate
  69.         popad
  70.         mov     [image_of_eax], eax
  71.         mov     [image_of_ebx], ebx
  72.         ret
  73.  
  74. file_system_lfn:
  75. ; in: ebx->fileinfo block
  76. ; operation codes:
  77. ; 0 : read file
  78. ; 1 : read folder
  79. ; 2 : create/rewrite file
  80. ; 3 : write/append to file
  81. ; 4 : set end of file
  82. ; 5 : get file/directory attributes structure
  83. ; 6 : set file/directory attributes structure
  84. ; 7 : start application
  85. ; 8 : delete file
  86. ; 9 : create directory
  87.  
  88. ; parse file name
  89.         lea     esi, [ebx+20]
  90.         lodsb
  91.         test    al, al
  92.         jnz     @f
  93.         mov     esi, [esi]
  94.         lodsb
  95. @@:
  96.         cmp     al, '/'
  97.         jz      .notcurdir
  98.         dec     esi
  99.         mov     ebp, esi
  100.         test    al, al
  101.         jnz     @f
  102.         xor     ebp, ebp
  103. @@:
  104.         mov     esi, [current_slot]
  105.         mov     esi, [esi+APPDATA.cur_dir]
  106.         jmp     .parse_normal
  107. .notcurdir:
  108.         cmp     byte [esi], 0
  109.         jz      .rootdir
  110.         call    process_replace_file_name
  111. .parse_normal:
  112.         cmp     dword [ebx], 7
  113.         jne     @F
  114.         mov     edx, [ebx+4]
  115.         mov     ebx, [ebx+8]
  116.         call    fs_execute; esi+ebp, ebx, edx
  117.         mov     [image_of_eax], eax
  118.         ret
  119. @@:
  120.         mov     edi, rootdirs-8
  121.         xor     ecx, ecx
  122.         push    esi
  123. .scan1:
  124.         pop     esi
  125.         add     edi, ecx
  126.         scasd
  127.         scasd
  128.         mov     cl, byte [edi]
  129.         test    cl, cl
  130.         jz      .notfound_try
  131.         inc     edi
  132.         push    esi
  133. @@:
  134.         lodsb
  135.         or      al, 20h
  136.         scasb
  137.         loopz   @b
  138.         jnz     .scan1
  139.         lodsb
  140.         cmp     al, '/'
  141.         jz      .found1
  142.         test    al, al
  143.         jnz     .scan1
  144.         pop     eax
  145. ; directory /xxx
  146. .maindir:
  147.         mov     esi, [edi+4]
  148. .maindir_noesi:
  149.         cmp     dword [ebx], 1
  150.         jnz     .access_denied
  151.         xor     eax, eax
  152.         mov     ebp, [ebx+12]                   ;количество блоков для считывания
  153.         mov     edx, [ebx+16]                   ;куда записывать рузельтат
  154.     ;    add     edx, std_application_base_address
  155.         push    dword [ebx+4]   ; first block
  156.         mov     ebx, [ebx+8]    ; flags
  157. ; ebx=flags, [esp]=first block, ebp=number of blocks, edx=return area, esi='Next' handler
  158.         mov     edi, edx
  159.         push    ecx
  160.         mov     ecx, 32/4
  161.         rep stosd
  162.         pop     ecx
  163.         mov     byte [edx], 1   ; version
  164. .maindir_loop:
  165.         call    esi
  166.         jc      .maindir_done
  167.         inc     dword [edx+8]
  168.         dec     dword [esp]
  169.         jns     .maindir_loop
  170.         dec     ebp
  171.         js      .maindir_loop
  172.         inc     dword [edx+4]
  173.         mov     dword [edi], 0x10       ; attributes: folder
  174.         mov     dword [edi+4], 1        ; name type: UNICODE
  175.         push    eax
  176.         xor     eax, eax
  177.         add     edi, 8
  178.         push    ecx
  179.         mov     ecx, 40/4-2
  180.         rep stosd
  181.         pop     ecx
  182.         pop     eax
  183.         push    eax edx
  184. ; convert number in eax to decimal UNICODE string
  185.         push    edi
  186.         push    ecx
  187.         push    -'0'
  188.         mov     ecx, 10
  189. @@:
  190.         xor     edx, edx
  191.         div     ecx
  192.         push    edx
  193.         test    eax, eax
  194.         jnz     @b
  195. @@:
  196.         pop     eax
  197.         add     al, '0'
  198.         stosb
  199.         test    bl, 1           ; UNICODE name?
  200.         jz      .ansi2
  201.         mov     byte [edi], 0
  202.         inc     edi
  203. .ansi2:
  204.         test    al, al
  205.         jnz     @b
  206.         mov     byte [edi-1], 0
  207.         pop     ecx
  208.         pop     edi
  209. ; UNICODE name length is 520 bytes, ANSI - 264
  210.         add     edi, 520
  211.         test    bl, 1
  212.         jnz     @f
  213.         sub     edi, 520-264
  214. @@:
  215.         pop     edx eax
  216.         jmp     .maindir_loop
  217. .maindir_done:
  218.         pop     eax
  219.         mov     ebx, [edx+4]
  220.         xor     eax, eax
  221.         dec     ebp
  222.         js      @f
  223.         mov     al, ERROR_END_OF_FILE
  224. @@:
  225.         mov     [image_of_eax], eax
  226.         mov     [image_of_ebx], ebx
  227.         ret
  228. ; directory /
  229. .rootdir:
  230.         cmp     dword [ebx], 1  ; read folder?
  231.         jz      .readroot
  232. .access_denied:
  233.         mov     dword [image_of_eax], 10      ; access denied
  234.         ret
  235.  
  236. .readroot:
  237. ; virtual root folder - special handler
  238.         mov     ebp, [ebx+12]
  239.         mov     edx, [ebx+16]
  240.     ;    add     edx, std_application_base_address
  241.         push    dword [ebx+4]   ; first block
  242.         mov     ebx, [ebx+8]    ; flags
  243.         xor     eax, eax
  244. ; eax=0, [esp]=first block, ebx=flags, ebp=number of blocks, edx=return area
  245.         mov     edi, edx
  246.         mov     ecx, 32/4
  247.         rep stosd
  248.         mov     byte [edx], 1   ; version
  249.         sub     esp, 16
  250. .readroot_ah_loop2:
  251.         push    edi
  252.         lea     edi, [esp+4]
  253.         call    dyndisk_enum_root
  254.         pop     edi
  255.         test    eax, eax
  256.         jz      .readroot_done_dynamic
  257.         inc     dword [edx+8]
  258.         dec     dword [esp+16]
  259.         jns     .readroot_ah_loop2
  260.         dec     ebp
  261.         js      .readroot_ah_loop2
  262.         push    eax
  263.         xor     eax, eax
  264.         inc     dword [edx+4]
  265.         mov     dword [edi], 0x10       ; attributes: folder
  266.         mov     dword [edi+4], ebx
  267.         add     edi, 8
  268.         mov     ecx, 40/4-2
  269.         rep stosd
  270.         push    esi edi
  271.         lea     esi, [esp+12]
  272. @@:
  273.         lodsb
  274.         stosb
  275.         test    bl, 1
  276.         jz      .ansi3
  277.         mov     byte [edi], 0
  278.         inc     edi
  279. .ansi3:
  280.         test    al, al
  281.         jnz     @b
  282.         pop     edi esi eax
  283.         add     edi, 520
  284.         test    bl, 1
  285.         jnz     .readroot_ah_loop2
  286.         sub     edi, 520-264
  287.         jmp     .readroot_ah_loop2
  288. .readroot_done_dynamic:
  289.         add     esp, 16
  290.         mov     esi, virtual_root_query
  291. .readroot_loop:
  292.         cmp     dword [esi], eax
  293.         jz      .readroot_done
  294.         call    dword [esi]
  295.         add     esi, 4
  296.         test    eax, eax
  297.         jnz     @f
  298. .readroot_next:
  299.         or      ecx, -1
  300.         xchg    esi, edi
  301.         repnz scasb
  302.         xchg    esi, edi
  303.         jmp     .readroot_loop
  304. @@:
  305.         xor     eax, eax
  306.         inc     dword [edx+8]
  307.         dec     dword [esp]
  308.         jns     .readroot_next
  309.         dec     ebp
  310.         js      .readroot_next
  311.         inc     dword [edx+4]
  312.         mov     dword [edi], 0x10       ; attributes: folder
  313.         mov     dword [edi+4], ebx      ; name type: UNICODE
  314.         add     edi, 8
  315.         mov     ecx, 40/4-2
  316.         rep stosd
  317.         push    edi
  318. @@:
  319.         lodsb
  320.         stosb
  321.         test    bl, 1
  322.         jz      .ansi
  323.         mov     byte [edi], 0
  324.         inc     edi
  325. .ansi:
  326.         test    eax, eax
  327.         jnz     @b
  328.         pop     edi
  329.         add     edi, 520
  330.         test    bl, 1
  331.         jnz     .readroot_loop
  332.         sub     edi, 520-264
  333.         jmp     .readroot_loop
  334. .readroot_done:
  335.         pop     eax
  336.         mov     ebx, [edx+4]
  337.         xor     eax, eax
  338.         dec     ebp
  339.         js      @f
  340.         mov     al, ERROR_END_OF_FILE
  341. @@:
  342.         mov     [image_of_eax], eax
  343.         mov     [image_of_ebx], ebx
  344.         ret
  345. .notfound_try:
  346.         call    dyndisk_handler
  347. .notfound:
  348.         mov     dword [image_of_eax], ERROR_FILE_NOT_FOUND
  349.         and     dword [image_of_ebx], 0
  350.         ret
  351.  
  352. .notfounda:
  353.         cmp     edi, esp
  354.         jnz     .notfound
  355.         call    dword [edi+4]
  356.         add     esp, 16
  357.         jmp     .notfound
  358.  
  359. .found1:
  360.         pop     eax
  361.         cmp     byte [esi], 0
  362.         jz      .maindir
  363. .found2:
  364. ; read partition number
  365.         xor     ecx, ecx
  366.         xor     eax, eax
  367. @@:
  368.         lodsb
  369.         cmp     al, '/'
  370.         jz      .done1
  371.         test    al, al
  372.         jz      .done1
  373.         sub     al, '0'
  374.         cmp     al, 9
  375.         ja      .notfounda
  376.         lea     ecx, [ecx*5]
  377.         lea     ecx, [ecx*2+eax]
  378.         jmp     @b
  379. .done1:
  380.         jecxz   .notfounda
  381.         test    al, al
  382.         jnz     @f
  383.         dec     esi
  384. @@:
  385.         cmp     byte [esi], 0
  386.         jnz     @f
  387.         test    ebp, ebp
  388.         jz      @f
  389.         mov     esi, ebp
  390.         xor     ebp, ebp
  391. @@:
  392. ; now [edi] contains handler address, ecx - partition number,
  393. ; esi points to ASCIIZ string - rest of name
  394.         jmp     dword [edi]
  395.  
  396. ; handlers for devices
  397. ; in: ecx = 0 => query virtual directory /xxx
  398. ; in: ecx = partition number
  399. ;     esi -> relative (for device) name
  400. ;     ebx -> fileinfo
  401. ;     ebp = 0 or pointer to rest of name from folder addressed by esi
  402. ; out: [image_of_eax]=image of eax, [image_of_ebx]=image of ebx
  403.  
  404. fs_NotImplemented:
  405.         mov     eax, 2
  406.         ret
  407.  
  408. ;*******************************************************
  409. fs_OnCd0:
  410.         call    reserve_cd
  411.         mov     [ChannelNumber], 1
  412.         mov     [DiskNumber], 0
  413.         push    6
  414.         push    1
  415.         jmp     fs_OnCd
  416. fs_OnCd1:
  417.         call    reserve_cd
  418.         mov     [ChannelNumber], 1
  419.         mov     [DiskNumber], 1
  420.         push    4
  421.         push    2
  422.         jmp     fs_OnCd
  423. fs_OnCd2:
  424.         call    reserve_cd
  425.         mov     [ChannelNumber], 2
  426.         mov     [DiskNumber], 0
  427.         push    2
  428.         push    3
  429.         jmp     fs_OnCd
  430. fs_OnCd3:
  431.         call    reserve_cd
  432.         mov     [ChannelNumber], 2
  433.         mov     [DiskNumber], 1
  434.         push    0
  435.         push    4
  436. fs_OnCd:
  437.         call    reserve_cd_channel
  438.         pop     eax
  439.         mov     [cdpos], eax
  440.         pop     eax
  441.         cmp     ecx, 0x100
  442.         jae     .nf
  443.         push    ecx ebx
  444.         mov     cl, al
  445.         mov     bl, [DRIVE_DATA+1]
  446.         shr     bl, cl
  447.         test    bl, 2
  448.         pop     ebx ecx
  449.  
  450.         jnz     @f
  451. .nf:
  452.         call    free_cd_channel
  453.         and     [cd_status], 0
  454.         mov     dword [image_of_eax], 5       ; not found
  455.         ret
  456. @@:
  457.         mov     ecx, [ebx+12]
  458.         mov     edx, [ebx+16]
  459.     ;    add     edx, std_application_base_address
  460.         mov     eax, [ebx]
  461.         cmp     eax, fs_NumCdServices
  462.         jae     .not_impl
  463.         add     ebx, 4
  464.         call    dword [fs_CdServices + eax*4]
  465.         call    free_cd_channel
  466.         and     [cd_status], 0
  467.         mov     [image_of_eax], eax
  468.         mov     [image_of_ebx], ebx
  469.         ret
  470. .not_impl:
  471.         call    free_cd_channel
  472.         and     [cd_status], 0
  473.         mov     dword [image_of_eax], 2       ; not implemented
  474.         ret
  475.  
  476. fs_CdServices:
  477.         dd      fs_CdRead
  478.         dd      fs_CdReadFolder
  479.         dd      fs_NotImplemented
  480.         dd      fs_NotImplemented
  481.         dd      fs_NotImplemented
  482.         dd      fs_CdGetFileInfo
  483.         dd      fs_NotImplemented
  484.         dd      0
  485.         dd      fs_NotImplemented
  486.         dd      fs_NotImplemented
  487. fs_NumCdServices = ($ - fs_CdServices)/4
  488.  
  489. ;*******************************************************
  490. fs_HasCd0:
  491.         test    byte [DRIVE_DATA+1], 10000000b
  492.         setnz   al
  493.         ret
  494. fs_HasCd1:
  495.         test    byte [DRIVE_DATA+1], 00100000b
  496.         setnz   al
  497.         ret
  498. fs_HasCd2:
  499.         test    byte [DRIVE_DATA+1], 00001000b
  500.         setnz   al
  501.         ret
  502. fs_HasCd3:
  503.         test    byte [DRIVE_DATA+1], 00000010b
  504.         setnz   al
  505.         ret
  506. ;*******************************************************
  507.  
  508. ; fs_NextXXX functions:
  509. ; in: eax = partition number, from which start to scan
  510. ; out: CF=1 => no more partitions
  511. ;      CF=0 => eax=next partition number
  512.  
  513. ;*******************************************************
  514. fs_NextCd:
  515. ; we always have /cdX/1
  516.         test    eax, eax
  517.         stc
  518.         jnz     @f
  519.         mov     al, 1
  520.         clc
  521. @@:
  522.         ret
  523. ;*******************************************************
  524.  
  525. ;-----------------------------------------------------------------------------
  526. process_replace_file_name:
  527. ; in
  528. ; esi - path with filename(f.70)
  529. ;
  530. ; out
  531. ; ebp - full filename
  532.         pushfd
  533.         cli
  534.         mov     ebp, [full_file_name_table]
  535.         xor     edi, edi
  536. .loop:
  537.         cmp     edi, [full_file_name_table.size]
  538.         jae     .notfound
  539.         push    esi edi
  540.         shl     edi, 7 ; edi*128
  541.         add     edi, ebp
  542. @@:
  543.         cmp     byte [edi], 0 ; end of dir_name
  544.         jz      .dest_done
  545.         lodsb
  546.         test    al, al
  547.         jz      .cont
  548.         or      al, 20h ; 32 - space char
  549.         scasb
  550.         jz      @b
  551.         jmp     .cont
  552. .dest_done:
  553.         cmp     byte [esi], 0
  554.         jz      .found
  555.         cmp     byte [esi], '/'
  556.         jnz     .cont
  557.         inc     esi
  558.         jmp     .found
  559. .cont:
  560.         pop     edi esi
  561.         inc     edi
  562.         jmp     .loop
  563. .found:
  564.         pop     edi eax
  565.         shl     edi, 7 ; edi*128
  566.         add     edi, ebp
  567.         mov     ebp, esi
  568.         cmp     byte [esi], 0
  569.         lea     esi, [edi+64]
  570.         jnz     .ret
  571. .notfound:
  572.         xor     ebp, ebp
  573. .ret:
  574.         popfd
  575.         ret
  576. ;-----------------------------------------------------------------------------
  577. uglobal
  578. lock_flag_for_f30_3 rb 1
  579. endg
  580.        
  581. sys_current_directory:
  582. ;       mov     esi, [current_slot]
  583. ;       mov     esi, [esi+APPDATA.cur_dir]
  584. ;       mov     edx, esi
  585.  
  586. ;get length string of appdata.cur_dir
  587.         mov     eax, [current_slot]
  588.         mov     edi, [eax+APPDATA.cur_dir]
  589.  
  590.         dec     ebx
  591.         jz      .set
  592.         dec     ebx
  593.         jz      .get
  594.         dec     ebx
  595.         jz      .mount_additional_directory
  596.         ret
  597.  
  598. .mount_additional_directory:
  599. ; sysfunction 30.2: [for app] eax=30,ebx=3,ecx->dir name+dir path (128)
  600. ; for our code: nothing
  601.  
  602. ; check lock of the function
  603.         cmp     [lock_flag_for_f30_3], 1
  604.         je      @f
  605.        
  606.         mov     esi, ecx
  607.         mov     edi, sysdir_name1
  608. ; copying fake directory name
  609.         mov     ecx, 63
  610.         pushfd
  611.         cli
  612.         cld
  613.         rep movsb
  614. ; terminator of name, in case if we get the inlet trash
  615.         inc     esi
  616.         xor     eax, eax
  617.         stosb
  618. ; copying real directory path for mounting
  619.         mov     ecx, 63
  620.         rep movsb
  621. ; terminator of name, in case if we get the inlet trash
  622.         xor     eax, eax
  623.         stosb
  624. ; increase the pointer of inputs for procedure "process_replace_file_name"        
  625.         mov     [full_file_name_table.size], 2
  626. ; block the ability to call f.30.3 because for one session is necessary
  627. ; for us only once
  628.         mov     [lock_flag_for_f30_3], 1
  629.         popfd
  630. @@:
  631.         ret
  632.        
  633. .get:
  634. ; sysfunction 30.2: [for app] eax=30,ebx=2,ecx->buffer,edx=len
  635. ; for our code: ebx->buffer,ecx=len
  636. max_cur_dir     equ     0x1000
  637.  
  638.         mov     ebx, edi
  639.  
  640.         push    ecx
  641.         push    edi
  642.  
  643.         xor     eax, eax
  644.         mov     ecx, max_cur_dir
  645.  
  646.         repne scasb             ;find zerro at and string
  647.         jnz     .error          ; no zero in cur_dir: internal error, should not happen
  648.  
  649.         sub     edi, ebx        ;lenght for copy
  650.         inc     edi
  651.         mov     [esp+32+8], edi ;return in eax
  652.  
  653.         cmp     edx, edi
  654.         jbe     @f
  655.         mov     edx, edi
  656. @@:
  657. ;source string
  658.         pop     esi
  659. ;destination string
  660.         pop     edi
  661.         cmp     edx, 1
  662.         jbe     .ret
  663.  
  664.         mov     al, '/'         ;start string with '/'
  665.         stosb
  666.         mov     ecx, edx
  667.         rep movsb               ;copy string
  668. .ret:
  669.         ret
  670.  
  671. .error:
  672.         add     esp, 8
  673.         or      dword [esp+32], -1      ;error not found zerro at string ->[eax+APPDATA.cur_dir]
  674.         ret
  675. .set:
  676. ; sysfunction 30.1: [for app] eax=30,ebx=1,ecx->string
  677. ; for our code: ebx->string to set
  678. ; use generic resolver with APPDATA.cur_dir as destination
  679.         push    max_cur_dir     ;0x1000
  680.         push    edi     ;destination
  681.         mov     ebx, ecx
  682.         call    get_full_file_name
  683.         ret
  684.  
  685. ; in: ebx = file name, [esp+4] = destination, [esp+8] = sizeof destination
  686. ; destroys all registers except ebp,esp
  687. get_full_file_name:
  688.         push    ebp
  689.         mov     esi, [current_slot]
  690.         mov     esi, [esi+APPDATA.cur_dir]
  691.         mov     edx, esi
  692. @@:
  693.         inc     esi
  694.         cmp     byte [esi-1], 0
  695.         jnz     @b
  696.         dec     esi
  697.         cmp     byte [ebx], '/'
  698.         jz      .set_absolute
  699. ; string gives relative path
  700.         mov     edi, [esp+8]    ; destination
  701. .relative:
  702.         cmp     byte [ebx], 0
  703.         jz      .set_ok
  704.         cmp     word [ebx], '.'
  705.         jz      .set_ok
  706.         cmp     word [ebx], './'
  707.         jnz     @f
  708.         add     ebx, 2
  709.         jmp     .relative
  710. @@:
  711.         cmp     word [ebx], '..'
  712.         jnz     .doset_relative
  713.         cmp     byte [ebx+2], 0
  714.         jz      @f
  715.         cmp     byte [ebx+2], '/'
  716.         jnz     .doset_relative
  717. @@:
  718.         dec     esi
  719.         cmp     byte [esi], '/'
  720.         jnz     @b
  721.         add     ebx, 3
  722.         jmp     .relative
  723. .set_ok:
  724.         cmp     edx, edi        ; is destination equal to APPDATA.cur_dir?
  725.         jz      .set_ok.cur_dir
  726.         sub     esi, edx
  727.         cmp     esi, [esp+12]
  728.         jb      .set_ok.copy
  729. .fail:
  730.         mov     byte [edi], 0
  731.         xor     eax, eax        ; fail
  732.         pop     ebp
  733.         ret     8
  734. .set_ok.copy:
  735.         mov     ecx, esi
  736.         mov     esi, edx
  737.         rep movsb
  738.         mov     byte [edi], 0
  739. .ret.ok:
  740.         mov     al, 1   ; ok
  741.         pop     ebp
  742.         ret     8
  743. .set_ok.cur_dir:
  744.         mov     byte [esi], 0
  745.         jmp     .ret.ok
  746. .doset_relative:
  747.         cmp     edx, edi
  748.         jz      .doset_relative.cur_dir
  749.         sub     esi, edx
  750.         cmp     esi, [esp+12]
  751.         jae     .fail
  752.         mov     ecx, esi
  753.         mov     esi, edx
  754.         mov     edx, edi
  755.         rep movsb
  756.         jmp     .doset_relative.copy
  757. .doset_relative.cur_dir:
  758.         mov     edi, esi
  759. .doset_relative.copy:
  760.         add     edx, [esp+12]
  761.         mov     byte [edi], '/'
  762.         inc     edi
  763.         cmp     edi, edx
  764.         jae     .overflow
  765. @@:
  766.         mov     al, [ebx]
  767.         inc     ebx
  768.         stosb
  769.         test    al, al
  770.         jz      .ret.ok
  771.         cmp     edi, edx
  772.         jb      @b
  773. .overflow:
  774.         dec     edi
  775.         jmp     .fail
  776. .set_absolute:
  777.         lea     esi, [ebx+1]
  778.         call    process_replace_file_name
  779.         mov     edi, [esp+8]
  780.         mov     edx, [esp+12]
  781.         add     edx, edi
  782. .set_copy:
  783.         lodsb
  784.         stosb
  785.         test    al, al
  786.         jz      .set_part2
  787. .set_copy_cont:
  788.         cmp     edi, edx
  789.         jb      .set_copy
  790.         jmp     .overflow
  791. .set_part2:
  792.         mov     esi, ebp
  793.         xor     ebp, ebp
  794.         test    esi, esi
  795.         jz      .ret.ok
  796.         mov     byte [edi-1], '/'
  797.         jmp     .set_copy_cont
  798.