dchaiku.pas 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. {
  2. Double Commander
  3. -------------------------------------------------------------------------
  4. This unit contains Haiku specific functions
  5. Copyright (C) 2022 Alexander Koblov ([email protected])
  6. Permission is hereby granted, free of charge, to any person obtaining
  7. a copy of this software and associated documentation files (the
  8. "Software"), to deal in the Software without restriction, including
  9. without limitation the rights to use, copy, modify, merge, publish,
  10. distribute, sublicense, and/or sell copies of the Software, and to
  11. permit persons to whom the Software is furnished to do so, subject to
  12. the following conditions:
  13. The above copyright notice and this permission notice shall be included
  14. in all copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  18. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  19. CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  20. TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  21. SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. }
  23. unit DCHaiku;
  24. {$mode objfpc}{$H+}
  25. {$packrecords c}
  26. interface
  27. uses
  28. Classes, SysUtils, BaseUnix, Unix;
  29. // fcntl.h
  30. const
  31. O_NOTRAVERSE = $2000;
  32. // TypeConstants.h
  33. const
  34. B_STRING_TYPE = $43535452; // 'CSTR'
  35. // fs_attr.h
  36. type
  37. attr_info = record
  38. type_: cuint32;
  39. size: coff_t;
  40. end;
  41. Tattr_info = attr_info;
  42. Pattr_info = ^attr_info;
  43. function fs_remove_attr(fd: cint; attribute: PAnsiChar): cint; cdecl; external clib;
  44. function fs_stat_attr(fd: cint; attribute: pansichar; attrInfo: Pattr_info): cint; cdecl; external clib;
  45. function fs_open_attr(path: pansichar; attribute: pansichar;
  46. type_: cuint32; openMode: cint): cint; cdecl; external clib;
  47. function fs_fopen_attr(fd: cint; attribute: pansichar;
  48. type_: cuint32; openMode: cint): cint; cdecl; external clib;
  49. function fs_close_attr(fd: cint): cint; cdecl; external clib;
  50. function fs_open_attr_dir(path: pansichar): pDir; cdecl; external clib;
  51. function fs_lopen_attr_dir(path: pansichar): pDir; cdecl; external clib;
  52. function fs_fopen_attr_dir(fd: cint): pDir; cdecl; external clib;
  53. function fs_close_attr_dir(dir: pDir): cint; cdecl; external clib;
  54. function fs_read_attr_dir(dir: pDir): pDirent; cdecl; external clib;
  55. // OS.h
  56. const
  57. B_OS_NAME_LENGTH = 32;
  58. // StorageDefs.h
  59. const
  60. B_FILE_NAME_LENGTH = 256;
  61. // fs_info.h
  62. const
  63. B_FS_IS_READONLY = $00000001;
  64. B_FS_IS_REMOVABLE = $00000002;
  65. B_FS_IS_PERSISTENT = $00000004;
  66. B_FS_IS_SHARED = $00000008;
  67. type
  68. Tfs_info = record
  69. dev: dev_t;
  70. root: ino_t;
  71. flags: cuint32;
  72. block_size: coff_t;
  73. io_size: coff_t;
  74. total_blocks: coff_t;
  75. free_blocks: coff_t;
  76. total_nodes: coff_t;
  77. free_nodes: coff_t;
  78. device_name: array[0..127] of AnsiChar;
  79. volume_name: array[0..Pred(B_FILE_NAME_LENGTH)] of AnsiChar;
  80. fsh_name: array[0..Pred(B_OS_NAME_LENGTH)] of AnsiChar;
  81. end;
  82. Pfs_info = ^Tfs_info;
  83. function dev_for_path(path: PAnsiChar): dev_t; cdecl; external clib;
  84. function next_dev(pos: pcint32): dev_t; cdecl; external clib;
  85. function fs_stat_dev(dev: dev_t; info: Pfs_info): cint; cdecl; external clib;
  86. // FindDirectory.h
  87. const
  88. B_TRASH_DIRECTORY = 1;
  89. B_USER_DIRECTORY = 3000;
  90. B_USER_SETTINGS_DIRECTORY = 3006;
  91. B_USER_DATA_DIRECTORY = 3012;
  92. B_USER_CACHE_DIRECTORY = 3013;
  93. function find_directory(which: cuint32; volume: dev_t; createIt: cbool;
  94. pathString: PAnsiChar; length: cint32): status_t; cdecl; external clib;
  95. function mbFileCopyXattr(const Source, Target: String): Boolean;
  96. function mbFileWriteXattr(const FileName, AttrName, Value: String): Boolean;
  97. function mbFindDirectory(which: cuint32; volume: dev_t; createIt: cbool; out pathString: String): Boolean;
  98. implementation
  99. uses
  100. DCUnix, DCConvertEncoding;
  101. function mbFileOpen(const FileName: String; Flags: cInt): THandle;
  102. begin
  103. repeat
  104. Result:= fpOpen(FileName, Flags or O_CLOEXEC);
  105. until (Result <> -1) or (fpgeterrno <> ESysEINTR);
  106. end;
  107. function mbFileGetXattr(hFile: THandle): TStringArray;
  108. var
  109. DirPtr: pDir;
  110. PtrDirEnt: pDirent;
  111. Index: Integer = 0;
  112. begin
  113. Result:= Default(TStringArray);
  114. DirPtr:= fs_fopen_attr_dir(hFile);
  115. if Assigned(DirPtr) then
  116. try
  117. SetLength(Result, 512);
  118. PtrDirEnt:= fs_read_attr_dir(DirPtr);
  119. while PtrDirEnt <> nil do
  120. begin
  121. Result[Index]:= StrPas(PtrDirEnt^.d_name);
  122. Inc(Index);
  123. if (Index > High(Result)) then
  124. begin
  125. SetLength(Result, Length(Result) * 2);
  126. end;
  127. PtrDirEnt:= fs_read_attr_dir(DirPtr);
  128. end;
  129. finally
  130. fs_close_attr_dir(DirPtr);
  131. end;
  132. SetLength(Result, Index);
  133. end;
  134. function mbFileWriteXattr(const FileName, AttrName, Value: String): Boolean;
  135. var
  136. hAttr: cint;
  137. ALen: Integer;
  138. hTarget: THandle;
  139. begin
  140. hTarget:= mbFileOpen(FileName, O_RDWR or O_NOTRAVERSE);
  141. Result:= (hTarget <> feInvalidHandle);
  142. if Result then
  143. begin
  144. hAttr:= fs_fopen_attr(hTarget, PAnsiChar(AttrName),
  145. B_STRING_TYPE, O_CREAT or O_TRUNC or O_WRONLY);
  146. Result:= (hAttr <> feInvalidHandle);
  147. if Result then
  148. begin
  149. ALen:= Length(Value) + 1;
  150. Result:= (FileWrite(hAttr, PAnsiChar(Value)^, ALen) = ALen);
  151. fs_close_attr(hAttr);
  152. end;
  153. FileClose(hTarget);
  154. end;
  155. end;
  156. function mbFileCopyXattr(const Source, Target: String): Boolean;
  157. var
  158. AData: TBytes;
  159. Index: Integer;
  160. Names: TStringArray;
  161. AttrName: PAnsiChar;
  162. AttrInfo: Tattr_info;
  163. hSource, hTarget: THandle;
  164. function ReadAttr(hFile: cint; attribute: pansichar): Boolean;
  165. var
  166. hAttr: THandle;
  167. begin
  168. hAttr:= fs_fopen_attr(hFile, attribute, attrInfo.type_, O_RDONLY);
  169. Result:= (hAttr <> feInvalidHandle);
  170. if Result then
  171. begin
  172. Result:= (FileRead(hAttr, AData[0], attrInfo.size) = attrInfo.size);
  173. fs_close_attr(hAttr);
  174. end;
  175. end;
  176. function WriteAttr(hFile: cint; attribute: pansichar): Boolean;
  177. var
  178. hAttr: THandle;
  179. begin
  180. hAttr:= fs_fopen_attr(hFile, attribute, attrInfo.type_, O_CREAT or O_WRONLY);
  181. Result:= (hAttr <> feInvalidHandle);
  182. if Result then
  183. begin
  184. Result:= (FileWrite(hAttr, AData[0], attrInfo.size) = attrInfo.size);
  185. fs_close_attr(hAttr);
  186. end;
  187. end;
  188. begin
  189. hSource:= mbFileOpen(Source, O_RDONLY or O_NOTRAVERSE);
  190. Result:= (hSource <> feInvalidHandle);
  191. if Result then
  192. begin
  193. hTarget:= mbFileOpen(Target, O_RDWR or O_NOTRAVERSE);
  194. Result:= (hTarget <> feInvalidHandle);
  195. if Result then
  196. begin
  197. // Remove attributes from target
  198. Names:= mbFileGetXattr(hTarget);
  199. for Index:= 0 to High(Names) do
  200. begin
  201. fs_remove_attr(hTarget, PAnsiChar(Names[Index]));
  202. end;
  203. SetLength(AData, $FFFF);
  204. Names:= mbFileGetXattr(hSource);
  205. for Index:= 0 to High(Names) do
  206. begin
  207. AttrName:= PAnsiChar(Names[Index]);
  208. if (fs_stat_attr(hSource, AttrName, @AttrInfo) >= 0) then
  209. begin
  210. if (AttrInfo.size > Length(AData)) then
  211. begin
  212. SetLength(AData, AttrInfo.size);
  213. end;
  214. Result:= ReadAttr(hSource, AttrName);
  215. if Result then
  216. begin
  217. Result:= WriteAttr(hTarget, AttrName);
  218. if not Result then Break;
  219. end;
  220. end;
  221. end;
  222. FileClose(hTarget);
  223. end;
  224. FileClose(hSource);
  225. end;
  226. end;
  227. function mbFindDirectory(which: cuint32; volume: dev_t; createIt: cbool; out
  228. pathString: String): Boolean;
  229. var
  230. APath: array[0..MAX_PATH] of AnsiChar;
  231. begin
  232. Result:= find_directory(which, volume, createIt, APath, MAX_PATH) >= 0;
  233. if Result then begin
  234. pathString:= CeSysToUtf8(APath);
  235. end;
  236. end;
  237. end.