Subversion Repositories Kolibri OS

Rev

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

  1. ;;================================================================================================;;
  2. ;;//// libio.asm //// (c) mike.dld, 2006-2008 ////////////////////////////////////////////////////;;
  3. ;;================================================================================================;;
  4. ;;                                                                                                ;;
  5. ;; This file is part of Common development libraries (Libs-Dev).                                  ;;
  6. ;;                                                                                                ;;
  7. ;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
  8. ;; General Public License as published by the Free Software Foundation, either version 3 of the   ;;
  9. ;; License, or (at your option) any later version.                                                ;;
  10. ;;                                                                                                ;;
  11. ;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without  ;;
  12. ;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  ;;
  13. ;; General Public License for more details.                                                       ;;
  14. ;;                                                                                                ;;
  15. ;; You should have received a copy of the GNU General Public License along with Libs-Dev. If not, ;;
  16. ;; see <http://www.gnu.org/licenses/>.                                                            ;;
  17. ;;                                                                                                ;;
  18. ;;================================================================================================;;
  19. ;;                                                                                                ;;
  20. ;; 2007-12-10 (mike.dld)                                                                          ;;
  21. ;;   changes:                                                                                     ;;
  22. ;;     - almost fully incompatible with previous version since return values were changed.        ;;
  23. ;;       now they are more C-like                                                                 ;;
  24. ;;   notes:                                                                                       ;;
  25. ;;     - `file.err` is not yet available                                                          ;;
  26. ;; 2007-09-26 (mike.dld)                                                                          ;;
  27. ;;   changes:                                                                                     ;;
  28. ;;     - modified `file.size` a bit (according to changes in FileInfo struct)                     ;;
  29. ;;     - added `file.find_first`, `file.find_next`, `file.find_close`                             ;;
  30. ;;   notes:                                                                                       ;;
  31. ;;     - `file.aux.match_wildcard` is exported only for testing purposes, don't                   ;;
  32. ;;       use it since it may be removed or renamed in next versions                               ;;
  33. ;;                                                                                                ;;
  34. ;;================================================================================================;;
  35.  
  36.  
  37. format MS COFF
  38.  
  39. public @EXPORT as 'EXPORTS'
  40.  
  41. include '../../../../proc32.inc'
  42. include '../../../../macros.inc'
  43. purge section;mov,add,sub
  44.  
  45. include 'libio.inc'
  46. include 'libio_p.inc'
  47.  
  48. section '.flat' code readable align 16
  49.  
  50. mem.alloc   dd ?
  51. mem.free    dd ?
  52. mem.realloc dd ?
  53. dll.load    dd ?
  54.  
  55. ;;================================================================================================;;
  56. proc lib_init ;///////////////////////////////////////////////////////////////////////////////////;;
  57. ;;------------------------------------------------------------------------------------------------;;
  58. ;? Library entry point (called after library load)                                                ;;
  59. ;;------------------------------------------------------------------------------------------------;;
  60. ;> eax = pointer to memory allocation routine                                                     ;;
  61. ;> ebx = pointer to memory freeing routine                                                        ;;
  62. ;> ecx = pointer to memory reallocation routine                                                   ;;
  63. ;> edx = pointer to library loading routine                                                       ;;
  64. ;;------------------------------------------------------------------------------------------------;;
  65. ;< eax = 1 (fail) / 0 (ok) (library initialization result)                                        ;;
  66. ;;================================================================================================;;
  67.         mov     [mem.alloc], eax
  68.         mov     [mem.free], ebx
  69.         mov     [mem.realloc], ecx
  70.         mov     [dll.load], edx
  71.         xor     eax, eax
  72.         ret
  73. endp
  74.  
  75. ;;================================================================================================;;
  76. proc file.aux.match_wildcard _str, _wcard ;///////////////////////////////////////////////////////;;
  77. ;;------------------------------------------------------------------------------------------------;;
  78. ;? Match string against wildcard                                                                  ;;
  79. ;? Based on http://user.cs.tu-berlin.de/~schintke/references/wildcards/                           ;;
  80. ;? 1997-2001 (c) Florian Schintke                                                                 ;;
  81. ;;------------------------------------------------------------------------------------------------;;
  82. ;> _str = pointer to string (filename in most cases)                                              ;;
  83. ;> _wcard = pointer to string (mask expressed using wilcards (?, *, [..]))                        ;;
  84. ;;------------------------------------------------------------------------------------------------;;
  85. ;< eax = false / true (match result)                                                              ;;
  86. ;;================================================================================================;;
  87.         push    ecx edx esi edi
  88.         mov     dl, 1 ; fit
  89.         mov     esi, [_wcard]
  90.         mov     edi, [_str]
  91.   .loop_wildcard:
  92.         mov     al, [esi]
  93.         or      al, al
  94.         jz      .loop_wildcard_exit
  95.         or      dl, dl
  96.         jz      .loop_wildcard_exit
  97.         cmp     byte[edi], 0
  98.         je      .loop_wildcard_exit
  99.  
  100.         cmp     al, '['
  101.         je      .process_set
  102.         cmp     al, '?'
  103.         je      .process_question
  104.         cmp     al, '*'
  105.         je      .process_asterisk
  106.  
  107.         xor     dl, dl
  108.         cmp     [edi], al
  109.         jne     @f
  110.         inc     dl
  111.     @@: inc     edi
  112.  
  113.   .loop_wildcard_next:
  114.         inc     esi
  115.         jmp     .loop_wildcard
  116.  
  117.  
  118.   .process_set:
  119.         inc     esi
  120.         xor     dl, dl ; fit
  121.         xor     dh, dh ; negation
  122.         mov     cl, 1  ; at_beginning
  123.         cmp     byte[esi], '^'
  124.         jne     .loop_set_wildcard
  125.         inc     dh
  126.         inc     esi
  127.  
  128.     .loop_set_wildcard:
  129.         mov     al, [esi]
  130.         cmp     al, ']'
  131.         jne     @f
  132.         or      cl, cl
  133.         jz      .loop_set_wildcard_exit
  134.     @@: or      dl, dl
  135.         jnz     .loop_set_wildcard_fit
  136.         cmp     al, '-'
  137.         jne     .loop_set_wildcard_not_range
  138.         mov     ch, [esi - 1]
  139.         cmp     [esi + 1], ch
  140.         jbe     .loop_set_wildcard_not_range
  141.         cmp     byte[esi + 1], ']'
  142.         je      .loop_set_wildcard_not_range
  143.         or      cl, cl
  144.         jnz     .loop_set_wildcard_not_range
  145.         cmp     [edi], ch
  146.         jb      .loop_set_wildcard_fit
  147.         mov     ch, [esi + 1]
  148.         cmp     [edi], ch
  149.         ja      .loop_set_wildcard_fit
  150.         mov     dl, 1
  151.         inc     esi
  152.         jmp     .loop_set_wildcard_fit
  153.  
  154.     .loop_set_wildcard_not_range:
  155.         cmp     [edi], al
  156.         jne     .loop_set_wildcard_fit
  157.         mov     dl, 1
  158.  
  159.     .loop_set_wildcard_fit:
  160.         inc     esi
  161.         xor     cl, cl
  162.         jmp     .loop_set_wildcard
  163.  
  164.     .loop_set_wildcard_exit:
  165.         or      dh, dh
  166.         jz      @f
  167.         xor     dl, 1
  168.     @@: or      dl, dl
  169.         jz      @f
  170.         inc     edi
  171.     @@:
  172.         jmp     .loop_wildcard_next
  173.  
  174.   .process_question:
  175.         inc     edi
  176.         jmp     .loop_wildcard_next
  177.  
  178.   .process_asterisk:
  179.         mov     dl, 1
  180.         inc     esi
  181.  
  182.     .loop_asterisk_del_shit:
  183.         lodsb
  184.         cmp     byte[edi], 0
  185.         je      .loop_asterisk_del_shit_exit
  186.         cmp     al, '?'
  187.         jne     @f
  188.         inc     edi
  189.         jmp     .loop_asterisk_del_shit
  190.     @@: cmp     al, '*'
  191.         je      .loop_asterisk_del_shit
  192.  
  193.     .loop_asterisk_del_shit_exit:
  194.  
  195.     @@: cmp     al, '*'
  196.         jne     @f
  197.         lodsb
  198.         jmp     @b
  199.     @@:
  200.         dec     esi
  201.         cmp     byte[edi], 0
  202.         jne     .process_asterisk_skip_exit
  203.         xor     dl, dl
  204.         or      al, al
  205.         jnz     @f
  206.         inc     dl
  207.     @@: dec     esi
  208.         jmp     .loop_wildcard_next
  209.  
  210.     .process_asterisk_skip_exit:
  211.         stdcall file.aux.match_wildcard, edi, esi
  212.         or      eax, eax
  213.         jnz     .process_asterisk_not_match
  214.  
  215.     .loop_asterisk_match:
  216.         inc     edi
  217.  
  218.     .loop_asterisk_char_match:
  219.         mov     al, [esi]
  220.         cmp     [edi], al
  221.         je      .loop_asterisk_char_match_exit
  222.         cmp     byte[esi], '['
  223.         je      .loop_asterisk_char_match_exit
  224.         cmp     byte[edi], 0
  225.         je      .loop_asterisk_char_match_exit
  226.         inc     edi
  227.         jmp     .loop_asterisk_char_match
  228.  
  229.     .loop_asterisk_char_match_exit:
  230.         cmp     byte[edi], 0
  231.         je      @f
  232.         stdcall file.aux.match_wildcard, edi, esi
  233.         or      eax, eax
  234.         jnz     .loop_asterisk_match_exit
  235.         jmp     .loop_asterisk_match
  236.     @@:
  237.         xor     dl, dl
  238.  
  239.     .loop_asterisk_match_exit:
  240.  
  241.     .process_asterisk_not_match:
  242.         cmp     byte[esi], 0
  243.         jne     @f
  244.         cmp     byte[edi], 0
  245.         jne     @f
  246.         mov     dl, 1
  247.     @@:
  248.         dec     esi
  249.         jmp     .loop_wildcard_next
  250.  
  251.   .loop_wildcard_exit:
  252.         or      dl, dl
  253.         jz      .exit
  254.     @@: cmp     byte[esi], '*'
  255.         jne     .exit
  256.         inc     esi
  257.         jmp     @b
  258.  
  259.   .exit:
  260.         cmp     byte[esi], 0
  261.         je      @f
  262.         xor     dl, dl
  263.     @@: cmp     byte[edi], 0
  264.         je      @f
  265.         xor     dl, dl
  266.     @@:
  267.         movzx   eax, dl
  268.  
  269.         pop     edi esi edx ecx
  270.         ret
  271. endp
  272.  
  273. ;;================================================================================================;;
  274. proc file.aux.find_matching_file _ffb ;///////////////////////////////////////////////////////////;;
  275. ;;------------------------------------------------------------------------------------------------;;
  276. ;? Find file with matching attributes (`FindFileBlock.Options.Attributes`) and mask               ;;
  277. ;? (`FindFileBlock.Options.Mask`) starting from Nth (`FindFileBlock.InfoBlock.Position`) file in  ;;
  278. ;? directory (`FindFileBlock.InfoBlock.FileName`)                                                 ;;
  279. ;;------------------------------------------------------------------------------------------------;;
  280. ;> _ffb = pointer to FindFileBlock                                                                ;;
  281. ;;------------------------------------------------------------------------------------------------;;
  282. ;< eax = 0 (error) / pointer to `FileInfo` with matched file data                                 ;;
  283. ;;================================================================================================;;
  284.         push    ebx edx
  285.         mov     edx, [_ffb]
  286.   .loop_find:
  287.         lea     ebx, [edx + FindFileBlock.InfoBlock]
  288.         mcall   70
  289.         or      eax, eax
  290.         jnz     .loop_find_error
  291.         mov     eax, [edx + FindFileBlock.Info.Attributes]
  292.         and     eax, [edx + FindFileBlock.Options.Attributes]
  293.         jz      .loop_find_next
  294.         lea     eax, [edx + FindFileBlock.Info.FileName]
  295.         stdcall file.aux.match_wildcard, eax, [edx + FindFileBlock.Options.Mask]
  296.         or      eax, eax
  297.         jnz     .loop_find_exit
  298.  
  299.   .loop_find_next:
  300.         inc     [edx + FindFileBlock.InfoBlock.Position]
  301.         jmp     .loop_find
  302.  
  303.   .loop_find_error:
  304.         xor     eax, eax
  305.         pop     edx ebx
  306.         ret
  307.  
  308.   .loop_find_exit:
  309.         lea     eax, [edx + FindFileBlock.Info]
  310.         pop     edx ebx
  311.         ret
  312. endp
  313.  
  314. ;;================================================================================================;;
  315. proc file.find_first _dir, _mask, _attr ;/////////////////////////////////////////////////////////;;
  316. ;;------------------------------------------------------------------------------------------------;;
  317. ;? Find first file with matching attributes and mask in specified directory                       ;;
  318. ;;------------------------------------------------------------------------------------------------;;
  319. ;> _dir = pointer to string (directory path to search in)                                         ;;
  320. ;> _mask = pointer to string (file mask, with use of wildcards)                                   ;;
  321. ;> _attr = file attributes mask (combination of FA_* constants)                                   ;;
  322. ;;------------------------------------------------------------------------------------------------;;
  323. ;< eax = 0 (error) / pointer to `FileInfo` with matched file data (acts as find descriptor)       ;;
  324. ;;================================================================================================;;
  325.         push    ebx edx
  326.  
  327.         invoke  mem.alloc, sizeof.FindFileBlock
  328.         or      eax, eax
  329.         jz      .exit.error
  330.         mov     edx, eax
  331.         mov     ebx, [_attr]
  332.         mov     [edx + FindFileBlock.Options.Attributes], ebx
  333.         mov     ebx, [_mask]
  334.         mov     [edx + FindFileBlock.Options.Mask], ebx
  335.  
  336.         lea     ebx, [edx + FindFileBlock.InfoBlock]
  337.         mov     [ebx + FileInfoBlock.Function], F70_READ_D
  338.         mov     [ebx + FileInfoBlock.Count], 1
  339.         lea     eax, [edx + FindFileBlock.Header]
  340.         mov     [ebx + FileInfoBlock.Buffer], eax
  341.         mov     eax, [_dir]
  342.         mov     [ebx + FileInfoBlock.FileName], eax
  343.  
  344.         stdcall file.aux.find_matching_file, edx
  345.         pop     edx ebx
  346.         ret
  347.  
  348.   .exit.error:
  349.         xor     eax, eax
  350.         pop     edx ebx
  351.         ret
  352. endp
  353.  
  354. ;;================================================================================================;;
  355. proc file.find_next _findd ;//////////////////////////////////////////////////////////////////////;;
  356. ;;------------------------------------------------------------------------------------------------;;
  357. ;? Find next file matching criteria                                                               ;;
  358. ;;------------------------------------------------------------------------------------------------;;
  359. ;> _findd = find descriptor (see `file.find_first`)                                               ;;
  360. ;;------------------------------------------------------------------------------------------------;;
  361. ;< eax = 0 (error) / pointer to `FileInfo` with matched file data (acts as find descriptor)       ;;
  362. ;;================================================================================================;;
  363.         mov     eax, [_findd]
  364.         add     eax, -sizeof.FileInfoHeader
  365.         inc     [eax + FindFileBlock.InfoBlock.Position]
  366.         stdcall file.aux.find_matching_file, eax
  367.         ret
  368. endp
  369.  
  370. ;;================================================================================================;;
  371. proc file.find_close _findd ;/////////////////////////////////////////////////////////////////////;;
  372. ;;------------------------------------------------------------------------------------------------;;
  373. ;? Close find descriptor and free memory                                                          ;;
  374. ;;------------------------------------------------------------------------------------------------;;
  375. ;> _findd = find descriptor (see `file.find_first`)                                               ;;
  376. ;;------------------------------------------------------------------------------------------------;;
  377. ;< eax = result of memory freeing routine                                                         ;;
  378. ;;================================================================================================;;
  379.         mov     eax, [_findd]
  380.         add     eax, -sizeof.FileInfoHeader
  381.         invoke  mem.free, eax
  382.         ret
  383. endp
  384.  
  385. ;;================================================================================================;;
  386. proc file.size _name ;////////////////////////////////////////////////////////////////////////////;;
  387. ;;------------------------------------------------------------------------------------------------;;
  388. ;? Get file size                                                                                  ;;
  389. ;;------------------------------------------------------------------------------------------------;;
  390. ;> _name = path to file (full or relative)                                                        ;;
  391. ;;------------------------------------------------------------------------------------------------;;
  392. ;< eax = -1 (error) / file size (in bytes, up to 2G)                                              ;;
  393. ;;------------------------------------------------------------------------------------------------;;
  394. ;# call `file.err` to obtain extended error information                                           ;;
  395. ;;================================================================================================;;
  396. locals
  397.   loc_info FileInfoBlock
  398. endl
  399.  
  400.         lea     ebx, [loc_info]
  401.         invoke  mem.alloc, 40
  402.         push    eax
  403.         mov     [ebx + FileInfoBlock.Function], F70_GETATTR_FD
  404.         mov     [ebx + FileInfoBlock.Buffer], eax
  405.         mov     byte[ebx + FileInfoBlock.FileName - 1], 0
  406.         mov     eax, [_name]
  407.         mov     [ebx + FileInfoBlock.FileName], eax
  408.         mcall   70
  409.         pop     ebx
  410.         push    eax
  411.         mov     eax, ebx
  412.         mov     ebx, [ebx + FileInfo.FileSizeLow]
  413.         invoke  mem.free, eax
  414.         pop     eax
  415.         ret
  416. endp
  417.  
  418. ;;================================================================================================;;
  419. proc file.open _name, _mode ;/////////////////////////////////////////////////////////////////////;;
  420. ;;------------------------------------------------------------------------------------------------;;
  421. ;? Open file                                                                                      ;;
  422. ;;------------------------------------------------------------------------------------------------;;
  423. ;> _name = path to file (full or relative)                                                        ;;
  424. ;> _mode = mode to open file in (combination of O_* constants)                                    ;;
  425. ;;------------------------------------------------------------------------------------------------;;
  426. ;< eax = 0 (error) / file descriptor                                                              ;;
  427. ;;------------------------------------------------------------------------------------------------;;
  428. ;# call `file.err` to obtain extended error information                                           ;;
  429. ;;================================================================================================;;
  430. locals
  431.   loc_info FileInfoBlock
  432.   loc_buf  rb 40
  433. endl
  434.  
  435.         push    ebx esi edi
  436.  
  437.         xor     ebx, ebx
  438.         invoke  mem.alloc, sizeof.InternalFileInfo
  439.         or      eax, eax
  440.         jz      .exit_error
  441.         mov     ebx, eax
  442.         push    [_mode]
  443.         pop     [ebx + InternalFileInfo.Mode]
  444.         mov     [ebx + InternalFileInfo.Position], 0
  445.         lea     edi, [ebx + InternalFileInfo.FileName]
  446.         mov     esi, [_name]
  447.         mov     ecx, 260 / 4
  448.         cld
  449.         rep     movsd
  450.  
  451.   .get_info:
  452.         push    ebx
  453.         mov     [loc_info.Function], F70_GETATTR_FD
  454.         lea     eax, [loc_buf]
  455.         mov     [loc_info.Buffer], eax
  456.         mov     byte[loc_info.FileName - 1], 0
  457.         mov     eax, [_name]
  458.         mov     [loc_info.FileName], eax
  459.         lea     ebx, [loc_info]
  460.         mcall   70
  461.         pop     ebx
  462.         or      eax, eax
  463.         jz      @f
  464.         cmp     eax, 6
  465.         jne     .exit_error.ex
  466.     @@:
  467.         mov     eax, ebx
  468.         pop     edi esi ebx
  469.         ret
  470.  
  471.   .exit_error.ex:
  472.         test    [_mode], O_CREATE
  473.         jz      .exit_error
  474.         push    ebx
  475.         mov     [loc_info.Function], F70_CREATE_F
  476.         xor     eax, eax
  477.         mov     [loc_info.Position], eax
  478.         mov     [loc_info.Flags], eax
  479.         mov     [loc_info.Count], eax
  480.         lea     ebx, [loc_info]
  481.         mcall   70
  482.         pop     ebx
  483.         or      eax, eax
  484.         jz      .get_info
  485.  
  486.   .exit_error:
  487.         invoke  mem.free, ebx
  488.         xor     eax, eax
  489.         pop     edi esi ebx
  490.         ret
  491. endp
  492.  
  493. ;;================================================================================================;;
  494. proc file.read _filed, _buf, _buflen ;////////////////////////////////////////////////////////////;;
  495. ;;------------------------------------------------------------------------------------------------;;
  496. ;? Read data from file                                                                            ;;
  497. ;;------------------------------------------------------------------------------------------------;;
  498. ;> _filed = file descriptor (see `file.open`)                                                     ;;
  499. ;> _buf = pointer to buffer to put read data to                                                   ;;
  500. ;> _buflen = buffer size (number of bytes to be read from file)                                   ;;
  501. ;;------------------------------------------------------------------------------------------------;;
  502. ;< eax = -1 (error) / number of bytes read                                                        ;;
  503. ;;------------------------------------------------------------------------------------------------;;
  504. ;# call `file.err` to obtain extended error information                                           ;;
  505. ;;================================================================================================;;
  506. locals
  507.   loc_info FileInfoBlock
  508. endl
  509.  
  510.         push    ebx esi edi
  511.  
  512.         mov     ebx, [_filed]
  513.         test    [ebx + InternalFileInfo.Mode], O_READ
  514.         jz      .exit_error
  515.  
  516.         xor     eax, eax
  517.         mov     [loc_info.Function], F70_READ_F
  518.         mov     [loc_info.Flags], eax
  519.         mov     byte[loc_info.FileName - 1], al
  520.         push    [ebx+InternalFileInfo.Position] [_buflen] [_buf]
  521.         pop     [loc_info.Buffer] [loc_info.Count] [loc_info.Position]
  522.         lea     eax, [ebx + InternalFileInfo.FileName]
  523.         mov     [loc_info.FileName], eax
  524.         lea     ebx, [loc_info]
  525.         mcall   70
  526.         or      eax, eax
  527.         jz      @f
  528.         cmp     eax, 6
  529.         jne     .exit_error
  530.     @@:
  531.         mov     eax, ebx
  532.         mov     ebx, [_filed]
  533.         add     [ebx + InternalFileInfo.Position], eax
  534.         pop     edi esi ebx
  535.         ret
  536.  
  537.   .exit_error:
  538.         or      eax, -1
  539.         pop     edi esi ebx
  540.         ret
  541. endp
  542.  
  543. ;;================================================================================================;;
  544. proc file.write _filed, _buf, _buflen ;///////////////////////////////////////////////////////////;;
  545. ;;------------------------------------------------------------------------------------------------;;
  546. ;? Write data to file                                                                             ;;
  547. ;;------------------------------------------------------------------------------------------------;;
  548. ;> _filed = file descriptor (see `file.open`)                                                     ;;
  549. ;> _buf = pointer to buffer to get write data from                                                ;;
  550. ;> _buflen = buffer size (number of bytes to be written to file)                                  ;;
  551. ;;------------------------------------------------------------------------------------------------;;
  552. ;< eax = -1 (error) / number of bytes written                                                     ;;
  553. ;;------------------------------------------------------------------------------------------------;;
  554. ;# call `file.err` to obtain extended error information                                           ;;
  555. ;;================================================================================================;;
  556. locals
  557.   loc_info FileInfoBlock
  558. endl
  559.  
  560.         push    ebx esi edi
  561.  
  562.         mov     ebx, [_filed]
  563.         test    [ebx + InternalFileInfo.Mode], O_WRITE
  564.         jz      .exit_error
  565.  
  566.         stdcall file.eof?, [_filed]
  567.         or      eax, eax
  568.         js      .exit_error
  569.         jz      @f
  570.         stdcall file.truncate, [_filed]
  571.     @@:
  572.         mov     [loc_info.Function], F70_WRITE_F
  573.         xor     eax, eax
  574.         mov     [loc_info.Flags], eax
  575.         mov     byte[loc_info.FileName - 1], al
  576.         push    [ebx + InternalFileInfo.Position] [_buflen] [_buf]
  577.         pop     [loc_info.Buffer] [loc_info.Count] [loc_info.Position]
  578.         lea     eax, [ebx + InternalFileInfo.FileName]
  579.         mov     [loc_info.FileName], eax
  580.         lea     ebx, [loc_info]
  581.         mcall   70
  582.         or      eax, eax
  583.         jnz     .exit_error
  584.     @@:
  585.         mov     eax, ebx
  586.         mov     ebx, [_filed]
  587.         add     [ebx + InternalFileInfo.Position],eax
  588.         pop     edi esi ebx
  589.         ret
  590.  
  591.   .exit_error:
  592.         or      eax, -1
  593.         pop     edi esi ebx
  594.         ret
  595. endp
  596.  
  597. ;;================================================================================================;;
  598. proc file.seek _filed, _where, _origin ;//////////////////////////////////////////////////////////;;
  599. ;;------------------------------------------------------------------------------------------------;;
  600. ;? Set file pointer position                                                                      ;;
  601. ;;------------------------------------------------------------------------------------------------;;
  602. ;> _filed = file descriptor (see `file.open`)                                                     ;;
  603. ;> _where = position in file (in bytes) counted from specified origin                             ;;
  604. ;> _origin = origin from where to set the position (one of SEEK_* constants)                      ;;
  605. ;>   SEEK_SET - from beginning of file                                                            ;;
  606. ;>   SEEK_CUR - from current pointer position                                                     ;;
  607. ;>   SEEK_END - from end of file                                                                  ;;
  608. ;;------------------------------------------------------------------------------------------------;;
  609. ;< eax = -1 (error) / 0                                                                           ;;
  610. ;;------------------------------------------------------------------------------------------------;;
  611. ;# call `file.err` to obtain extended error information                                           ;;
  612. ;;================================================================================================;;
  613.         push    ebx ecx edx
  614.  
  615.         mov     ecx, [_filed]
  616.         lea     eax, [ecx + InternalFileInfo.FileName]
  617.         stdcall file.size, eax
  618.         or      eax, eax
  619.         jnz     .exit_error
  620.         mov     edx, [_where]
  621.         cmp     [_origin], SEEK_SET
  622.         jne     .n_set
  623.         mov     [ecx + InternalFileInfo.Position], edx
  624.         jmp     .exit_ok
  625.  
  626.   .n_set:
  627.         cmp     [_origin], SEEK_CUR
  628.         jne     .n_cur
  629.         add     [ecx + InternalFileInfo.Position], edx
  630.         jmp     .exit_ok
  631.  
  632.   .n_cur:
  633.         cmp     [_origin], SEEK_END
  634.         jne     .exit_error
  635.         neg     edx
  636.         add     edx, ebx
  637.         mov     [ecx + InternalFileInfo.Position], edx
  638.  
  639.   .exit_ok:
  640.  
  641.         cmp     [ecx + InternalFileInfo.Position], 0
  642.         jge     @f
  643.         mov     [ecx + InternalFileInfo.Position], 0
  644.     @@:
  645. ;       cmp     ebx, [ecx+InternalFileInfo.Position]
  646. ;       jae     @f
  647. ;       mov     [ecx + InternalFileInfo.Position], ebx
  648. ;   @@:
  649.         xor     eax, eax
  650.         pop     edx ecx ebx
  651.         ret
  652.  
  653.   .exit_error:
  654.         or      eax, -1
  655.         pop     edx ecx ebx
  656.         ret
  657. endp
  658.  
  659. ;;================================================================================================;;
  660. proc file.eof? _filed ;///////////////////////////////////////////////////////////////////////////;;
  661. ;;------------------------------------------------------------------------------------------------;;
  662. ;? Determine if file pointer is at the end of file                                                ;;
  663. ;;------------------------------------------------------------------------------------------------;;
  664. ;> _filed = file descriptor (see `file.open`)                                                     ;;
  665. ;;------------------------------------------------------------------------------------------------;;
  666. ;< eax = false / true                                                                             ;;
  667. ;;------------------------------------------------------------------------------------------------;;
  668. ;# call `file.err` to obtain extended error information                                           ;;
  669. ;;================================================================================================;;
  670.         push    ebx ecx
  671.  
  672.         mov     ecx, [_filed]
  673.         lea     eax, [ecx + InternalFileInfo.FileName]
  674.         stdcall file.size, eax
  675.         or      eax, eax
  676.         jnz     .exit_error
  677.  
  678.         xor     eax, eax
  679.         cmp     [ecx + InternalFileInfo.Position], ebx
  680.         jb      @f
  681.         inc     eax
  682.     @@: pop     ecx ebx
  683.         ret
  684.  
  685.   .exit_error:
  686.         or      eax, -1
  687.         pop     ecx ebx
  688.         ret
  689. endp
  690.  
  691. ;;================================================================================================;;
  692. proc file.truncate _filed ;///////////////////////////////////////////////////////////////////////;;
  693. ;;------------------------------------------------------------------------------------------------;;
  694. ;? Truncate file size to current file pointer position                                            ;;
  695. ;;------------------------------------------------------------------------------------------------;;
  696. ;> _filed = file descriptor (see `file.open`)                                                     ;;
  697. ;;------------------------------------------------------------------------------------------------;;
  698. ;< eax = -1 (error) / 0                                                                           ;;
  699. ;;------------------------------------------------------------------------------------------------;;
  700. ;# call `file.err` to obtain extended error information                                           ;;
  701. ;;================================================================================================;;
  702. locals
  703.   loc_info FileInfoBlock
  704. endl
  705.  
  706.         push    ebx esi edi
  707.  
  708.         mov     ebx, [_filed]
  709.         test    [ebx + InternalFileInfo.Mode], O_WRITE
  710.         jz      .exit_error
  711.  
  712.         mov     [loc_info.Function], F70_SETSIZE_F
  713.         mov     eax, [ebx + InternalFileInfo.Position]
  714.         mov     [loc_info.Position], eax
  715.         xor     eax, eax
  716.         mov     [loc_info.Flags], eax
  717.         mov     [loc_info.Count], eax
  718.         mov     [loc_info.Buffer], eax
  719.         mov     byte[loc_info.FileName - 1], al
  720.         lea     eax, [ebx + InternalFileInfo.FileName]
  721.         mov     [loc_info.FileName], eax
  722.         lea     ebx, [loc_info]
  723.         mcall   70
  724.         cmp     eax, 2
  725.         je      .exit_error
  726.         cmp     eax, 8
  727.         je      .exit_error
  728.     @@: xor     eax, eax
  729.         pop     edi esi ebx
  730.         ret
  731.  
  732.   .exit_error:
  733.         or      eax, -1
  734.         pop     edi esi ebx
  735.         ret
  736. endp
  737.  
  738. file.seteof equ file.truncate
  739.  
  740. ;;================================================================================================;;
  741. proc file.tell _filed ;///////////////////////////////////////////////////////////////////////////;;
  742. ;;------------------------------------------------------------------------------------------------;;
  743. ;? Get current file pointer position                                                              ;;
  744. ;;------------------------------------------------------------------------------------------------;;
  745. ;> _filed = file descriptor (see `file.open`)                                                     ;;
  746. ;;------------------------------------------------------------------------------------------------;;
  747. ;< eax = -1 (error) / file pointer position                                                       ;;
  748. ;;------------------------------------------------------------------------------------------------;;
  749. ;# call `file.err` to obtain extended error information                                           ;;
  750. ;;================================================================================================;;
  751.         mov     eax, [_filed]
  752.         mov     eax, [eax + InternalFileInfo.Position]
  753.         ret
  754. endp
  755.  
  756. ;;================================================================================================;;
  757. proc file.close _filed ;//////////////////////////////////////////////////////////////////////////;;
  758. ;;------------------------------------------------------------------------------------------------;;
  759. ;? Close file                                                                                     ;;
  760. ;;------------------------------------------------------------------------------------------------;;
  761. ;> _filed = file descriptor (see `file.open`)                                                     ;;
  762. ;;------------------------------------------------------------------------------------------------;;
  763. ;< eax = -1 (error) / file pointer position                                                       ;;
  764. ;;------------------------------------------------------------------------------------------------;;
  765. ;# call `file.err` to obtain extended error information                                           ;;
  766. ;;================================================================================================;;
  767.         mov     eax, [_filed]
  768.         mov     [eax + InternalFileInfo.Mode], 0
  769.         mov     [eax + InternalFileInfo.FileName], 0
  770.         invoke  mem.free, eax
  771.         xor     eax, eax
  772.         ret
  773. endp
  774.  
  775.  
  776. ;;================================================================================================;;
  777. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  778. ;;================================================================================================;;
  779. ;! Exported functions section                                                                     ;;
  780. ;;================================================================================================;;
  781. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  782. ;;================================================================================================;;
  783.  
  784.  
  785. align 16
  786. @EXPORT:
  787.  
  788. export                                        \
  789.         lib_init        , 'lib_init'        , \
  790.         0x00030003      , 'version'         , \
  791.         file.find_first , 'file.find_first' , \
  792.         file.find_next  , 'file.find_next'  , \
  793.         file.find_close , 'file.find_close' , \
  794.         file.size       , 'file.size'       , \
  795.         file.open       , 'file.open'       , \
  796.         file.read       , 'file.read'       , \
  797.         file.write      , 'file.write'      , \
  798.         file.seek       , 'file.seek'       , \
  799.         file.tell       , 'file.tell'       , \
  800.         file.eof?       , 'file.eof?'       , \
  801.         file.seteof     , 'file.seteof'     , \
  802.         file.truncate   , 'file.truncate'   , \
  803.         file.close      , 'file.close'
  804.