filesystem.bmx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. Strict
  2. Rem
  3. bbdoc: System/File system
  4. End Rem
  5. Module BRL.FileSystem
  6. ModuleInfo "Version: 1.09"
  7. ModuleInfo "Author: Mark Sibly"
  8. ModuleInfo "License: zlib/libpng"
  9. ModuleInfo "Copyright: Blitz Research Ltd"
  10. ModuleInfo "Modserver: BRL"
  11. ModuleInfo "History: 1.09 Release"
  12. ModuleInfo "History: Fixed RealPath breaking win32 //server paths"
  13. ModuleInfo "History: 1.08 Release"
  14. ModuleInfo "History: Rebuild for StdC chmod_ linkage"
  15. ModuleInfo "History: 1.07 Release"
  16. ModuleInfo "History: Fixed RealPath failing with 'hidden' dirs"
  17. ModuleInfo "History: 1.06 Release"
  18. ModuleInfo "History: 1.05 Release"
  19. ModuleInfo "History: Fixed Win32 CreateDir"
  20. ModuleInfo "History: 1.04 Release"
  21. ModuleInfo "History: Cleaned up FixPath and RealPath"
  22. ModuleInfo "History: Added optional resurse parameter to CreateDir"
  23. Import Pub.StdC
  24. Import BRL.BankStream
  25. Const FILETYPE_NONE=0,FILETYPE_FILE=1,FILETYPE_DIR=2
  26. Private
  27. Function _RootPath$( path$ )
  28. ?Win32
  29. If path.StartsWith( "//" )
  30. Return path[ ..path.Find( "/",2 )+1 ]
  31. EndIf
  32. Local i=path.Find( ":" )
  33. If i<>-1 And path.Find( "/" )=i+1 Return path[..i+2]
  34. ?
  35. If path.StartsWith( "/" ) Return "/"
  36. End Function
  37. Function _IsRootPath( path$ )
  38. Return path And _RootPath( path )=path
  39. End Function
  40. Function _IsRealPath( path$ )
  41. Return _RootPath( path )<>""
  42. End Function
  43. ?Win32
  44. Function _CurrentDrive$()
  45. Local cd$=getcwd_()
  46. Local i=cd.Find( ":" )
  47. If i<>-1 Return cd[..i]
  48. End Function
  49. ?
  50. Public
  51. Function FixPath( path$ Var,dirPath=False )
  52. path=path.Replace("\","/")
  53. ?Win32
  54. If path.StartsWith( "//" )
  55. If path.Find( "/",2 )=-1 path:+"/"
  56. Else
  57. Local i=path.Find( ":" )
  58. If i<>-1 And ( i=path.length-1 Or path[i+1]<>Asc(":") )
  59. Local i2=path.Find( "/" )
  60. If i2=-1 Or i2>i+1 path=path[..i+1]+"/"+path[i+1..]
  61. EndIf
  62. EndIf
  63. ?
  64. If dirPath And path.EndsWith( "/" )
  65. If Not _IsRootPath( path ) path=path[..path.length-1]
  66. EndIf
  67. End Function
  68. Rem
  69. bbdoc: Strip directory from a file path
  70. End Rem
  71. Function StripDir$( path$ )
  72. FixPath path
  73. Local i=path.FindLast( "/" )
  74. If i<>-1 Return path[i+1..]
  75. Return path
  76. End Function
  77. Rem
  78. bbdoc: Strip extension from a file path
  79. End Rem
  80. Function StripExt$( path$ )
  81. FixPath path
  82. Local i=path.FindLast( "." )
  83. If i<>-1 And path.Find( "/",i+1 )=-1 Return path[..i]
  84. Return path
  85. End Function
  86. Rem
  87. bbdoc: Strip directory and extension from a file path
  88. End Rem
  89. Function StripAll$( path$ )
  90. Return StripDir( StripExt( path ) )
  91. End Function
  92. Rem
  93. bbdoc: Strip trailing slash from a file path
  94. about:
  95. #StripSlash will not remove the trailing slash from a 'root' path. For example, "/"
  96. or (on Win32 only) "C:/".
  97. End Rem
  98. Function StripSlash$( path$ )
  99. FixPath path
  100. If path.EndsWith( "/" ) And Not _IsRootPath( path ) path=path[..path.length-1]
  101. Return path
  102. End Function
  103. Rem
  104. bbdoc: Extract directory from a file path
  105. End Rem
  106. Function ExtractDir$( path$ )
  107. FixPath path
  108. If path="." Or path=".." Or _IsRootPath( path ) Return path
  109. Local i=path.FindLast( "/" )
  110. If i=-1 Return ""
  111. If _IsRootPath( path[..i+1] ) i:+1
  112. Return path[..i]
  113. End Function
  114. Rem
  115. bbdoc: Extract extension from a file path
  116. End Rem
  117. Function ExtractExt$( path$ )
  118. FixPath path
  119. Local i=path.FindLast( "." )
  120. If i<>-1 And path.Find( "/",i+1 )=-1 Return path[i+1..]
  121. End Function
  122. Rem
  123. bbdoc: Get Current Directory
  124. returns: The current directory
  125. End Rem
  126. Function CurrentDir$()
  127. Local path$=getcwd_()
  128. FixPath path
  129. Return path
  130. End Function
  131. Rem
  132. bbdoc: Get real, absolute path of a file path
  133. End Rem
  134. Function RealPath$( path$ )
  135. ?Win32
  136. If path.StartsWith( "/" ) And Not path.StartsWith( "//" )
  137. path=_CurrentDrive()+":"+path
  138. EndIf
  139. ?
  140. FixPath path
  141. Local cd$=_RootPath( path )
  142. If cd
  143. path=path[cd.length..]
  144. Else
  145. cd=CurrentDir()
  146. EndIf
  147. path:+"/"
  148. While path
  149. Local i=path.Find( "/" )
  150. Local t$=path[..i]
  151. path=path[i+1..]
  152. Select t
  153. Case ""
  154. Case "."
  155. Case ".."
  156. If Not _IsRootPath( cd ) cd=cd[..cd.FindLast("/")]
  157. Default
  158. If Not cd.EndsWith( "/" ) cd:+"/"
  159. cd:+t
  160. End Select
  161. Wend
  162. Return cd
  163. End Function
  164. Rem
  165. bbdoc: Get file type
  166. returns: 0 if file at @path doesn't exist, FILETYPE_FILE (1) if the file is a plain file or FILETYPE_DIR (2) if the file is a directory
  167. End Rem
  168. Function FileType( path$ )
  169. FixPath path
  170. Local mode,size,mtime,ctime
  171. If stat_( path,mode,size,mtime,ctime ) Return 0
  172. Select mode & S_IFMT_
  173. Case S_IFREG_ Return FILETYPE_FILE
  174. Case S_IFDIR_ Return FILETYPE_DIR
  175. End Select
  176. Return FILETYPE_NONE
  177. End Function
  178. Rem
  179. bbdoc: Get file time
  180. returns: The time the file at @path was last modified
  181. End Rem
  182. Function FileTime( path$ )
  183. FixPath path
  184. Local mode,size,mtime,ctime
  185. If stat_( path,mode,size,mtime,ctime ) Return 0
  186. Return mtime
  187. End Function
  188. Rem
  189. bbdoc: Get file size
  190. returns: Size, in bytes, of the file at @path, or -1 if the file does not exist
  191. end rem
  192. Function FileSize( path$ )
  193. FixPath path
  194. Local mode,size,mtime,ctime
  195. If stat_( path,mode,size,mtime,ctime ) Return -1
  196. Return size
  197. End Function
  198. Rem
  199. bbdoc: Get file mode
  200. returns: file mode flags
  201. end rem
  202. Function FileMode( path$ )
  203. FixPath path
  204. Local mode,size,mtime,ctime
  205. If stat_( path,mode,size,mtime,ctime ) Return -1
  206. Return mode & 511
  207. End Function
  208. Rem
  209. bbdoc: Set file mode
  210. end rem
  211. Function SetFileMode( path$,mode )
  212. FixPath path
  213. chmod_ path,mode
  214. End Function
  215. Rem
  216. bbdoc: Create a file
  217. returns: True if successful
  218. End Rem
  219. Function CreateFile( path$ )
  220. FixPath path
  221. remove_ path
  222. Local t=fopen_( path,"wb" )
  223. If t fclose_ t
  224. If FileType( path )=FILETYPE_FILE Return True
  225. End Function
  226. Rem
  227. bbdoc: Create a directory
  228. returns: True if successful
  229. about:
  230. If @recurse is true, any required subdirectories are also created.
  231. End Rem
  232. Function CreateDir( path$,recurse=False )
  233. FixPath path,True
  234. If Not recurse
  235. mkdir_ path,1023
  236. Return FileType(path)=FILETYPE_DIR
  237. EndIf
  238. Local t$
  239. path=RealPath(path)+"/"
  240. While path
  241. Local i=path.find("/")+1
  242. t:+path[..i]
  243. path=path[i..]
  244. Select FileType(t)
  245. Case FILETYPE_DIR
  246. Case FILETYPE_NONE
  247. Local s$=StripSlash(t)
  248. mkdir_ StripSlash(s),1023
  249. If FileType(s)<>FILETYPE_DIR Return False
  250. Default
  251. Return False
  252. End Select
  253. Wend
  254. Return True
  255. End Function
  256. Rem
  257. bbdoc: Delete a file
  258. returns: True if successful
  259. End Rem
  260. Function DeleteFile( path$ )
  261. FixPath path
  262. remove_ path
  263. Return FileType(path)=FILETYPE_NONE
  264. End Function
  265. Rem
  266. bbdoc: Renames a file
  267. returns: True if successful
  268. End Rem
  269. Function RenameFile( oldpath$,newpath$ )
  270. FixPath oldpath
  271. FixPath newpath
  272. Return rename_( oldpath,newpath)=0
  273. End Function
  274. Rem
  275. bbdoc: Copy a file
  276. returns: True if successful
  277. End Rem
  278. Function CopyFile( src$,dst$ )
  279. Local in:TStream=ReadStream( src ),ok
  280. If in
  281. Local out:TStream=WriteStream( dst )
  282. If out
  283. Try
  284. CopyStream in,out
  285. ok=True
  286. Catch ex:TStreamWriteException
  287. End Try
  288. out.Close
  289. EndIf
  290. in.Close
  291. EndIf
  292. Return ok
  293. End Function
  294. Rem
  295. bbdoc: Copy a directory
  296. returns: True if successful
  297. End Rem
  298. Function CopyDir( src$,dst$ )
  299. Function CopyDir_( src$,dst$ )
  300. If FileType( dst )=FILETYPE_NONE CreateDir dst
  301. If FileType( dst )<>FILETYPE_DIR Return False
  302. For Local file$=EachIn LoadDir( src )
  303. Select FileType( src+"/"+file )
  304. Case FILETYPE_DIR
  305. If Not CopyDir_( src+"/"+file,dst+"/"+file ) Return False
  306. Case FILETYPE_FILE
  307. If Not CopyFile( src+"/"+file,dst+"/"+file ) Return False
  308. End Select
  309. Next
  310. Return True
  311. End Function
  312. FixPath src
  313. If FileType( src )<>FILETYPE_DIR Return False
  314. FixPath dst
  315. Return CopyDir_( src,dst )
  316. End Function
  317. Rem
  318. bbdoc: Delete a directory
  319. returns: True if successful
  320. about: Set @recurse to true to delete all subdirectories and files recursively -
  321. but be careful!
  322. End Rem
  323. Function DeleteDir( path$,recurse=False )
  324. FixPath path,True
  325. If recurse
  326. Local dir=ReadDir( path )
  327. If Not dir Return
  328. Repeat
  329. Local t$=NextFile( dir )
  330. If t="" Exit
  331. If t="." Or t=".." Continue
  332. Local f$=path+"/"+t
  333. Select FileType( f )
  334. Case 1 DeleteFile f
  335. Case 2 DeleteDir f,True
  336. End Select
  337. Forever
  338. CloseDir dir
  339. EndIf
  340. rmdir_ path
  341. If FileType( path )=0 Return True
  342. End Function
  343. Rem
  344. bbdoc: Change current directory
  345. returns: True if successful
  346. End Rem
  347. Function ChangeDir( path$ )
  348. FixPath path,True
  349. If chdir_( path )=0 Return True
  350. End Function
  351. Rem
  352. bbdoc: Open a directory
  353. returns: An integer directory handle, or 0 if the directory does not exist
  354. End Rem
  355. Function ReadDir( path$ )
  356. FixPath path,True
  357. Return opendir_( path )
  358. End Function
  359. Rem
  360. bbdoc: Return next file in a directory
  361. returns: File name of next file in directory opened using #ReadDir, or an empty string if there are no more files to read.
  362. End Rem
  363. Function NextFile$( dir )
  364. Return readdir_( dir )
  365. End Function
  366. Rem
  367. bbdoc: Close a directory
  368. End Rem
  369. Function CloseDir( dir )
  370. closedir_ dir
  371. End Function
  372. Rem
  373. bbdoc: Load a directory
  374. returns: A string array containing contents of @dir
  375. about: The @skip_dots parameter, if true, removes the '.' (current) and '..'
  376. (parent) directories from the returned array.
  377. end rem
  378. Function LoadDir$[]( dir$,skip_dots=True )
  379. FixPath dir,True
  380. Local d=ReadDir( dir )
  381. If Not d Return
  382. Local i$[100],n
  383. Repeat
  384. Local f$=NextFile( d )
  385. If Not f Exit
  386. If skip_dots And (f="." Or f="..") Continue
  387. If n=i.length i=i[..n+100]
  388. i[n]=f
  389. n=n+1
  390. Forever
  391. CloseDir d
  392. Return i[..n]
  393. End Function
  394. Rem
  395. bbdoc: Open a file for input and/or output.
  396. about:
  397. This command is similar to the #OpenStream command but will attempt
  398. to cache the contents of the file to ensure serial streams such as
  399. http: based url's are seekable. Use the #CloseStream command when
  400. finished reading and or writing to a Stream returned by #OpenFile.
  401. End Rem
  402. Function OpenFile:TStream( url:Object,readable=True,writeable=True )
  403. Local stream:TStream=OpenStream( url,readable,writeable )
  404. If Not stream Return
  405. If stream.Pos()=-1 Return TBankStream.Create( TBank.Load(stream) )
  406. Return stream
  407. End Function
  408. Rem
  409. bbdoc: Open a file for input.
  410. about:
  411. This command is similar to the #ReadStream command but will attempt
  412. to cache the contents of the file to ensure serial streams such as
  413. http: based url's are seekable. Use the #CloseStream command when
  414. finished reading and or writing to a Stream returned by #OpenFile.
  415. End Rem
  416. Function ReadFile:TStream( url:Object )
  417. Return OpenFile( url,True,False )
  418. End Function
  419. Rem
  420. bbdoc: Open a file for output.
  421. about:
  422. This command is identical to the #WriteStream command.
  423. End Rem
  424. Function WriteFile:TStream( url:Object )
  425. Return OpenFile( url,False,True )
  426. End Function
  427. Rem
  428. bbdoc: Closes a file stream.
  429. about:
  430. After performing file operations on an open file make sure to
  431. close the file stream with either #CloseFile or the identical
  432. #CloseStream command.
  433. End Rem
  434. Function CloseFile( stream:TStream )
  435. stream.Close
  436. End Function