filesystem.bmx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. SuperStrict
  2. Rem
  3. bbdoc: System/File system
  4. End Rem
  5. Module BRL.FileSystem
  6. ModuleInfo "Version: 1.13"
  7. ModuleInfo "Author: Mark Sibly"
  8. ModuleInfo "License: zlib/libpng"
  9. ModuleInfo "Copyright: Blitz Research Ltd"
  10. ModuleInfo "Modserver: BRL"
  11. ModuleInfo "History: 1.13"
  12. ModuleInfo "History: Added SetFileTime"
  13. ModuleInfo "History: Added MaxIO file tree walking"
  14. ModuleInfo "History: 1.12"
  15. ModuleInfo "History: Added file tree walker"
  16. ModuleInfo "History: 1.11"
  17. ModuleInfo "History: Added optional parameter timetype to FileTime"
  18. ModuleInfo "History: 1.10"
  19. ModuleInfo "History: Module is now SuperStrict"
  20. ModuleInfo "History: 1.09 Release"
  21. ModuleInfo "History: Fixed RealPath breaking win32 //server paths"
  22. ModuleInfo "History: 1.08 Release"
  23. ModuleInfo "History: Rebuild for StdC chmod_ linkage"
  24. ModuleInfo "History: 1.07 Release"
  25. ModuleInfo "History: Fixed RealPath failing with 'hidden' dirs"
  26. ModuleInfo "History: 1.06 Release"
  27. ModuleInfo "History: 1.05 Release"
  28. ModuleInfo "History: Fixed Win32 CreateDir"
  29. ModuleInfo "History: 1.04 Release"
  30. ModuleInfo "History: Cleaned up FixPath and RealPath"
  31. ModuleInfo "History: Added optional resurse parameter to CreateDir"
  32. Import Pub.StdC
  33. Import BRL.BankStream
  34. Import "glue.c"
  35. Const FILETYPE_NONE:Int=0,FILETYPE_FILE:Int=1,FILETYPE_DIR:Int=2,FILETYPE_SYM:Int=3
  36. Const FILETIME_MODIFIED:Int=0,FILETIME_CREATED:Int=1,FILETIME_ACCESSED:Int=2
  37. Private
  38. Function _RootPath:String( path:String )
  39. If MaxIO.ioInitialized Then
  40. Return "/"
  41. End If
  42. ?Win32
  43. If path.StartsWith( "//" )
  44. Return path[ ..path.Find( "/",2 )+1 ]
  45. EndIf
  46. Local i:Int=path.Find( ":" )
  47. If i<>-1 And path.Find( "/" )=i+1 Return path[..i+2]
  48. ?
  49. If path.StartsWith( "/" ) Return "/"
  50. End Function
  51. Function _IsRootPath:Int( path:String )
  52. Return path And _RootPath( path )=path
  53. End Function
  54. Function _IsRealPath:Int( path:String )
  55. Return _RootPath( path )<>""
  56. End Function
  57. ?Win32
  58. Function _CurrentDrive:String()
  59. Local cd:String=getcwd_()
  60. Local i:Int=cd.Find( ":" )
  61. If i<>-1 Return cd[..i]
  62. End Function
  63. ?
  64. Public
  65. Function FixPath( path:String Var,dirPath:Int=False )
  66. path=path.Replace("\","/")
  67. If Not MaxIO.ioInitialized Then
  68. ?Win32
  69. If path.StartsWith( "//" )
  70. If path.Find( "/",2 )=-1 path:+"/"
  71. Else
  72. Local i:Int=path.Find( ":" )
  73. If i<>-1 And ( i=path.length-1 Or path[i+1]<>Asc(":") )
  74. Local i2:Int=path.Find( "/" )
  75. If i2=-1 Or i2>i+1 path=path[..i+1]+"/"+path[i+1..]
  76. EndIf
  77. EndIf
  78. ?
  79. End If
  80. If dirPath And path.EndsWith( "/" )
  81. If Not _IsRootPath( path ) path=path[..path.length-1]
  82. EndIf
  83. End Function
  84. Rem
  85. bbdoc: Strips the directory from a file path
  86. End Rem
  87. Function StripDir:String( path:String )
  88. FixPath path
  89. Local i:Int=path.FindLast( "/" )
  90. If i<>-1 Return path[i+1..]
  91. Return path
  92. End Function
  93. Rem
  94. bbdoc: Strips the extension from a file path
  95. End Rem
  96. Function StripExt:String( path:String )
  97. FixPath path
  98. Local i:Int=path.FindLast( "." )
  99. If i<>-1 And path.Find( "/",i+1 )=-1 Return path[..i]
  100. Return path
  101. End Function
  102. Rem
  103. bbdoc: Strips the directory and extension from a file path
  104. End Rem
  105. Function StripAll:String( path:String )
  106. Return StripDir( StripExt( path ) )
  107. End Function
  108. Rem
  109. bbdoc: Strips trailing slash from a file path
  110. about:
  111. #StripSlash will not remove the trailing slash from a 'root' path. For example, "/"
  112. or (on Win32 only) "C:/".
  113. End Rem
  114. Function StripSlash:String( path:String )
  115. FixPath path
  116. If path.EndsWith( "/" ) And Not _IsRootPath( path ) path=path[..path.length-1]
  117. Return path
  118. End Function
  119. Rem
  120. bbdoc: Extracts the directory from a file path
  121. End Rem
  122. Function ExtractDir:String( path:String )
  123. FixPath path
  124. If path="." Or path=".." Or _IsRootPath( path ) Return path
  125. Local i:Int=path.FindLast( "/" )
  126. If i=-1 Return ""
  127. If _IsRootPath( path[..i+1] ) i:+1
  128. Return path[..i]
  129. End Function
  130. Rem
  131. bbdoc: Extracts the extension from a file path
  132. End Rem
  133. Function ExtractExt:String( path:String )
  134. FixPath path
  135. Local i:Int=path.FindLast( "." )
  136. If i<>-1 And path.Find( "/",i+1 )=-1 Return path[i+1..]
  137. End Function
  138. Rem
  139. bbdoc: Gets the Current Directory
  140. returns: The current directory
  141. End Rem
  142. Function CurrentDir:String()
  143. If MaxIO.ioInitialized Then
  144. Return "/"
  145. End If
  146. Local path:String=getcwd_()
  147. FixPath path
  148. Return path
  149. End Function
  150. Rem
  151. bbdoc: Gets the real, absolute path of a file path
  152. End Rem
  153. Function RealPath:String( path:String )
  154. ?Win32
  155. If Not MaxIO.ioInitialized And path.StartsWith( "/" ) And Not path.StartsWith( "//" )
  156. path=_CurrentDrive()+":"+path
  157. EndIf
  158. ?
  159. FixPath path
  160. Local cd:String=_RootPath( path )
  161. If cd
  162. If Not MaxIO.ioInitialized Then
  163. path=path[cd.length..]
  164. End If
  165. Else
  166. cd=CurrentDir()
  167. EndIf
  168. path:+"/"
  169. While path
  170. Local i:Int=path.Find( "/" )
  171. Local t:String=path[..i]
  172. path=path[i+1..]
  173. Select t
  174. Case ""
  175. Case "."
  176. Case ".."
  177. If Not _IsRootPath( cd ) cd=cd[..cd.FindLast("/")]
  178. Default
  179. If Not cd.EndsWith( "/" ) cd:+"/"
  180. cd:+t
  181. End Select
  182. Wend
  183. Return cd
  184. End Function
  185. Rem
  186. bbdoc: Gets the file type
  187. 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
  188. End Rem
  189. Function FileType:Int( path:String )
  190. FixPath path
  191. If MaxIO.ioInitialized Then
  192. Local stat:SMaxIO_Stat
  193. If Not MaxIO.Stat(path, stat) Return 0
  194. Select stat._filetype
  195. Case EMaxIOFileType.REGULAR Return FILETYPE_FILE
  196. Case EMaxIOFileType.DIRECTORY Return FILETYPE_DIR
  197. End Select
  198. Else
  199. Local Mode:Int,size:Long,mtime:Int,ctime:Int,atime:Int
  200. If stat_( path,Mode,size,mtime,ctime,atime ) Return 0
  201. Select Mode & S_IFMT_
  202. Case S_IFREG_ Return FILETYPE_FILE
  203. Case S_IFDIR_ Return FILETYPE_DIR
  204. End Select
  205. End If
  206. Return FILETYPE_NONE
  207. End Function
  208. Rem
  209. bbdoc: Checks if a file or directory exists
  210. returns: #True if the file or directory at @path exists
  211. about: Use #FileType to check if the file is a directory or a plain file.
  212. End Rem
  213. Function FileExists:Int( path:String )
  214. Return FileType( path ) <> FILETYPE_NONE
  215. End Function
  216. Rem
  217. bbdoc: Gets file time
  218. returns: The time the file at @path was last modified.
  219. End Rem
  220. Function FileTime:Long( path:String, timetype:Int=FILETIME_MODIFIED )
  221. FixPath path
  222. If MaxIO.ioInitialized Then
  223. Local stat:SMaxIO_Stat
  224. If Not MaxIO.Stat(path, stat) Return 0
  225. Select timetype
  226. Case FILETIME_CREATED
  227. Return stat._createtime
  228. Case FILETIME_MODIFIED
  229. Return stat._modtime
  230. Case FILETIME_ACCESSED
  231. Return stat._accesstime
  232. EndSelect
  233. Else
  234. Local Mode:Int,size:Long,mtime:Int,ctime:Int,atime:Int
  235. If stat_( path,Mode,size,mtime,ctime,atime ) Return 0
  236. Select timetype
  237. Case FILETIME_CREATED
  238. Return ctime
  239. Case FILETIME_MODIFIED
  240. Return mtime
  241. Case FILETIME_ACCESSED
  242. Return atime
  243. EndSelect
  244. End If
  245. End Function
  246. Rem
  247. bbdoc: Sets the file modified or last accessed time.
  248. about: @time should be number of seconds since epoch.
  249. End Rem
  250. Function SetFileTime( path:String, time:Long, timeType:Int=FILETIME_MODIFIED)
  251. FixPath path
  252. If MaxIO.ioInitialized Then
  253. ' Not available
  254. Else
  255. Select timetype
  256. Case FILETIME_MODIFIED
  257. utime_(path, timeType, time)
  258. Case FILETIME_ACCESSED
  259. utime_(path, timeType, time)
  260. End Select
  261. End If
  262. End Function
  263. Rem
  264. bbdoc: Sets the file modified or last accessed time.
  265. about: @dateTime is the basic DateTime struct defined in pub.stdc .
  266. End Rem
  267. Function SetFileTime( path:String, dateTime:SDateTime, timeType:Int=FILETIME_MODIFIED)
  268. SetFileTime(path, dateTime.ToEpochSecs(), timeType)
  269. End Function
  270. Rem
  271. bbdoc: Gets file time
  272. returns: The time the file at @path was last modified as SDatetime struct.
  273. End Rem
  274. Function FileDateTime:SDateTime( path:String, timetype:Int=FILETIME_MODIFIED )
  275. Return SDateTime.FromEpoch( FileTime(path, timetype) )
  276. End Function
  277. Rem
  278. bbdoc: Sets the file modified or last accessed time.
  279. about: @dateTime is the basic DateTime struct defined in pub.stdc .
  280. End Rem
  281. Function SetFileDateTime( path:String, dateTime:SDateTime, timeType:Int=FILETIME_MODIFIED)
  282. SetFileTime(path, dateTime.ToEpochSecs(), timeType)
  283. End Function
  284. Rem
  285. bbdoc: Gets the file size
  286. returns: The size, in bytes, of the file at @path, or -1 if the file does not exist
  287. End Rem
  288. Function FileSize:Long( path:String )
  289. FixPath path
  290. If MaxIO.ioInitialized Then
  291. Local stat:SMaxIO_Stat
  292. If Not MaxIO.Stat(path, stat) Return -1
  293. Return stat._filesize
  294. Else
  295. Local Mode:Int,size:Long,mtime:Int,ctime:Int,atime:Int
  296. If stat_( path,Mode,size,mtime,ctime,atime ) Return -1
  297. Return size
  298. End If
  299. End Function
  300. Rem
  301. bbdoc: Gets the file mode
  302. returns: The file mode flags
  303. End Rem
  304. Function FileMode:Int( path:String )
  305. FixPath path
  306. If Not MaxIO.ioInitialized Then
  307. Local Mode:Int,size:Long,mtime:Int,ctime:Int,atime:Int
  308. If stat_( path,Mode,size,mtime,ctime,atime ) Return -1
  309. Return Mode & 511
  310. End If
  311. End Function
  312. Rem
  313. bbdoc: Sets file mode
  314. End Rem
  315. Function SetFileMode( path:String,Mode:Int )
  316. FixPath path
  317. If Not MaxIO.ioInitialized Then
  318. chmod_ path,Mode
  319. End If
  320. End Function
  321. Rem
  322. bbdoc: Creates a file
  323. returns: #True if successful
  324. End Rem
  325. Function CreateFile:Int( path:String )
  326. FixPath path
  327. If MaxIO.ioInitialized Then
  328. MaxIO.DeletePath(path)
  329. Local t:Byte Ptr = MaxIO.OpenWrite(path)
  330. If t MaxIO.Close(t)
  331. Else
  332. remove_ path
  333. Local t:Byte Ptr=fopen_( path,"wb" )
  334. If t fclose_ t
  335. End If
  336. If FileType( path )=FILETYPE_FILE Return True
  337. End Function
  338. Rem
  339. bbdoc: Creates a directory
  340. returns: #True if successful
  341. about:
  342. If @recurse is #True, any required subdirectories are also created.
  343. End Rem
  344. Function CreateDir:Int( path:String,recurse:Int=False )
  345. FixPath path,True
  346. If MaxIO.ioInitialized Then
  347. Return MaxIO.MkDir(path)
  348. Else
  349. If Not recurse
  350. mkdir_ path,1023
  351. Return FileType(path)=FILETYPE_DIR
  352. EndIf
  353. Local t:String
  354. path=RealPath(path)+"/"
  355. While path
  356. Local i:Int=path.find("/")+1
  357. t:+path[..i]
  358. path=path[i..]
  359. Select FileType(t)
  360. Case FILETYPE_DIR
  361. Case FILETYPE_NONE
  362. Local s:String=StripSlash(t)
  363. mkdir_ StripSlash(s),1023
  364. If FileType(s)<>FILETYPE_DIR Return False
  365. Default
  366. Return False
  367. End Select
  368. Wend
  369. Return True
  370. End If
  371. End Function
  372. Rem
  373. bbdoc: Deletes a file
  374. returns: #True if successful
  375. End Rem
  376. Function DeleteFile:Int( path:String )
  377. FixPath path
  378. If MaxIO.ioInitialized Then
  379. MaxIO.DeletePath(path)
  380. Else
  381. remove_ path
  382. End If
  383. Return FileType(path)=FILETYPE_NONE
  384. End Function
  385. Rem
  386. bbdoc: Renames a file
  387. returns: #True if successful
  388. End Rem
  389. Function RenameFile:Int( oldpath:String,newpath:String )
  390. If MaxIO.ioInitialized Then
  391. Return False
  392. End If
  393. FixPath oldpath
  394. FixPath newpath
  395. Return rename_( oldpath,newpath)=0
  396. End Function
  397. Rem
  398. bbdoc: Copies a file
  399. returns: #True if successful
  400. End Rem
  401. Function CopyFile:Int( src:String,dst:String )
  402. Local in:TStream=ReadStream( src ),ok:Int
  403. If in
  404. Local out:TStream=WriteStream( dst )
  405. If out
  406. Try
  407. CopyStream in,out
  408. ok=True
  409. Catch ex:TStreamWriteException
  410. End Try
  411. out.Close
  412. EndIf
  413. in.Close
  414. EndIf
  415. Return ok
  416. End Function
  417. Rem
  418. bbdoc: Copies a directory
  419. returns: #True if successful
  420. End Rem
  421. Function CopyDir:Int( src:String,dst:String )
  422. Function CopyDir_:Int( src:String,dst:String )
  423. If FileType( dst )=FILETYPE_NONE CreateDir dst
  424. If FileType( dst )<>FILETYPE_DIR Return False
  425. For Local file:String=EachIn LoadDir( src )
  426. Select FileType( src+"/"+file )
  427. Case FILETYPE_DIR
  428. If Not CopyDir_( src+"/"+file,dst+"/"+file ) Return False
  429. Case FILETYPE_FILE
  430. If Not CopyFile( src+"/"+file,dst+"/"+file ) Return False
  431. End Select
  432. Next
  433. Return True
  434. End Function
  435. FixPath src
  436. If FileType( src )<>FILETYPE_DIR Return False
  437. FixPath dst
  438. Return CopyDir_( src,dst )
  439. End Function
  440. Rem
  441. bbdoc: Deletes a directory
  442. returns: #True if successful
  443. about: Set @recurse to #True to delete all subdirectories and files recursively -
  444. but be careful!
  445. End Rem
  446. Function DeleteDir:Int( path:String,recurse:Int=False )
  447. FixPath path,True
  448. If recurse
  449. Local dir:Byte Ptr=ReadDir( path )
  450. If Not dir Return False
  451. Repeat
  452. Local t:String=NextFile( dir )
  453. If t="" Exit
  454. If t="." Or t=".." Continue
  455. Local f:String=path+"/"+t
  456. Select FileType( f )
  457. Case 1 DeleteFile f
  458. Case 2 DeleteDir f,True
  459. End Select
  460. Forever
  461. CloseDir dir
  462. EndIf
  463. If MaxIO.ioInitialized Then
  464. MaxIO.DeletePath(path)
  465. Else
  466. rmdir_ path
  467. EndIf
  468. If FileType( path )=0 Return True
  469. End Function
  470. Rem
  471. bbdoc: Changes the current directory
  472. returns: True if successful
  473. End Rem
  474. Function ChangeDir:Int( path:String )
  475. If MaxIO.ioInitialized Then
  476. Return False
  477. Else
  478. FixPath path,True
  479. If chdir_( path )=0 Return True
  480. End If
  481. End Function
  482. Rem
  483. bbdoc: Opens a directory
  484. returns: A directory handle, or #Null if the directory does not exist
  485. about: Use #NextFile to get the next file in the directory.
  486. The directory must be closed with #CloseDir.
  487. End Rem
  488. Function ReadDir:Byte Ptr( path:String )
  489. FixPath path,True
  490. If MaxIO.ioInitialized Then
  491. Return bmx_blitzio_readdir(path)
  492. Else
  493. Return opendir_( path )
  494. End If
  495. End Function
  496. Rem
  497. bbdoc: Returns the next file in a directory
  498. returns: File name of next file in the directory opened using #ReadDir, or an empty #String if there are no more files to read.
  499. End Rem
  500. Function NextFile:String( dir:Byte Ptr )
  501. If MaxIO.ioInitialized Then
  502. Return bmx_blitzio_nextFile(dir)
  503. Else
  504. Return readdir_( dir )
  505. End If
  506. End Function
  507. Rem
  508. bbdoc: Closes a directory.
  509. about: Closes a directory opened with #ReadDir.
  510. End Rem
  511. Function CloseDir( dir:Byte Ptr )
  512. If MaxIO.ioInitialized Then
  513. bmx_blitzio_closeDir(dir)
  514. Else
  515. closedir_ dir
  516. End If
  517. End Function
  518. Rem
  519. bbdoc: Loads a directory
  520. returns: A string array containing contents of @dir
  521. about: The @skip_dots parameter, if true, removes the '.' (current) and '..'
  522. (parent) directories from the returned array.
  523. End Rem
  524. Function LoadDir:String[]( dir:String,skip_dots:Int=True )
  525. FixPath dir,True
  526. Local d:Byte Ptr=ReadDir( dir )
  527. If Not d Return Null
  528. Local i:String[100],n:Int
  529. Repeat
  530. Local f:String=NextFile( d )
  531. If Not f Exit
  532. If skip_dots And (f="." Or f="..") Continue
  533. If n=i.length i=i[..n+100]
  534. i[n]=f
  535. n=n+1
  536. Forever
  537. CloseDir d
  538. Return i[..n]
  539. End Function
  540. Rem
  541. bbdoc: Opens a file for input and/or output.
  542. about:
  543. This command is similar to the #OpenStream command but will attempt
  544. to cache the contents of the file to ensure serial streams such as
  545. http: based url's are seekable. Use the #CloseStream command when
  546. finished reading and or writing to a Stream returned by #OpenFile.
  547. End Rem
  548. Function OpenFile:TStream( url:Object,readable:Int=True,writeable:Int=True )
  549. Local stream:TStream=OpenStream( url,readable,writeable )
  550. If Not stream Return Null
  551. If stream.Pos()=-1 Return TBankStream.Create( TBank.Load(stream) )
  552. Return stream
  553. End Function
  554. Rem
  555. bbdoc: Opens a file For Input.
  556. about:
  557. This command is similar to the #ReadStream command but will attempt
  558. to cache the contents of the file to ensure serial streams such as
  559. http: based url's are seekable. Use the #CloseStream command when
  560. finished reading and or writing to a Stream returned by #OpenFile.
  561. End Rem
  562. Function ReadFile:TStream( url:Object )
  563. Return OpenFile( url,True,False )
  564. End Function
  565. Rem
  566. bbdoc: Opens a file for output.
  567. about:
  568. This command is identical to the #WriteStream command.
  569. End Rem
  570. Function WriteFile:TStream( url:Object )
  571. Return OpenFile( url,False,True )
  572. End Function
  573. Rem
  574. bbdoc: Closes a file stream.
  575. about:
  576. After performing file operations on an open file make sure to
  577. close the file stream with either #CloseFile or the identical
  578. #CloseStream command.
  579. End Rem
  580. Function CloseFile( stream:TStream )
  581. stream.Close
  582. End Function
  583. Rem
  584. bbdoc: Walks a file tree.
  585. End Rem
  586. Function WalkFileTree:Int(path:String, fileWalker:IFileWalker, options:EFileWalkOption = EFileWalkOption.None, maxDepth:Int = 0)
  587. FixPath(path)
  588. If MaxIO.ioInitialized Then
  589. If FileType(path) = FILETYPE_DIR Then
  590. Return FSWalkFileTree(path, fileWalker, options, 0, maxDepth)
  591. End If
  592. Else
  593. Return bmx_filesystem_walkfiletree(path, _walkfile, fileWalker, options, maxDepth)
  594. End If
  595. End Function
  596. Rem
  597. bbdoc: An interface for file tree traversal.
  598. End rem
  599. Interface IFileWalker
  600. Rem
  601. bbdoc: Called once for each file/folder traversed.
  602. about: Return EFileWalkResult.OK to continue the tree traversal, or EFileWalkResult.Terminate to exit early.
  603. The contents of @attributes is only valid for the duration of the call.
  604. End Rem
  605. Method WalkFile:EFileWalkResult(attributes:SFileAttributes Var)
  606. End Interface
  607. Rem
  608. bbdoc: File attributes
  609. End rem
  610. Struct SFileAttributes
  611. ?win32
  612. Field StaticArray name:Short[8192]
  613. ?not win32
  614. Field StaticArray name:Byte[8192]
  615. ?
  616. Field fileType:Short
  617. Field depth:Short
  618. Rem
  619. bbdoc: The size, in bytes, of the file.
  620. End Rem
  621. Field size:ULong
  622. Field creationTime:Int
  623. Field modifiedTime:Int
  624. Rem
  625. bbdoc: Returns the name of the file/directory.
  626. End rem
  627. Method GetName:String()
  628. ?win32
  629. Return String.FromWString(name)
  630. ?not win32
  631. Return String.FromUTF8String(name)
  632. ?
  633. End Method
  634. Method IsRegularFile:Int()
  635. Return fileType = FILETYPE_FILE
  636. End Method
  637. Method IsDirectory:Int()
  638. Return fileType = FILETYPE_DIR
  639. End Method
  640. Method IsSymbolicLink:Int()
  641. Return fileType = FILETYPE_SYM
  642. End Method
  643. End Struct
  644. Rem
  645. bbdoc:
  646. End rem
  647. Enum EFileWalkOption
  648. None
  649. FollowLinks
  650. End Enum
  651. Rem
  652. bbdoc:
  653. End rem
  654. Enum EFileWalkResult
  655. OK
  656. Terminate
  657. SkipSubtree
  658. SkipSiblings
  659. End Enum
  660. Private
  661. Function _walkFile:EFileWalkResult(fileWalker:IFileWalker, attributes:SFileAttributes Var) { nomangle }
  662. Return fileWalker.WalkFile(attributes)
  663. End Function
  664. Function FSWalkFileTree:Int(dir:string, fileWalker:IFileWalker, options:EFileWalkOption, depth:Int, maxDepth:Int)
  665. Local attributes:SFileAttributes
  666. ApplyAttributes(dir, depth, VarPtr attributes)
  667. Local res:EFileWalkResult = fileWalker.WalkFile(attributes)
  668. If res = EFileWalkResult.Terminate Then
  669. Return 1
  670. End If
  671. Local d:Byte Ptr = ReadDir(dir)
  672. If d Then
  673. Local f:String = NextFile(d)
  674. While f
  675. Local path:String = dir + "/" + f
  676. If ApplyAttributes(path, depth + 1, VarPtr attributes) Then
  677. If attributes.fileType = FILETYPE_DIR Then
  678. Local ret:Int = FSWalkFileTree(path, fileWalker, options, depth + 1, maxDepth)
  679. If ret Then
  680. CloseDir(d)
  681. Return ret
  682. End If
  683. Else
  684. res = fileWalker.WalkFile(attributes)
  685. If res = EFileWalkResult.Terminate Then
  686. CloseDir(d)
  687. Return 1
  688. End If
  689. End If
  690. End IF
  691. f = NextFile(d)
  692. Wend
  693. CloseDir(d)
  694. End If
  695. End Function
  696. Function ApplyAttributes:Int(path:String, depth:Int, attributes:SFileAttributes Ptr)
  697. Local stat:SMaxIO_Stat
  698. If Not MaxIO.Stat(path, stat) Then
  699. Return False
  700. End If
  701. Select stat._filetype
  702. Case EMaxIOFileType.REGULAR
  703. attributes.fileType = FILETYPE_FILE
  704. Case EMaxIOFileType.DIRECTORY
  705. attributes.fileType = FILETYPE_DIR
  706. Case EMaxIOFileType.SYMLINK
  707. attributes.fileType = FILETYPE_SYM
  708. End Select
  709. Local length:Size_T = 8192
  710. ?win32
  711. path.ToWStringBuffer(attributes.name, length)
  712. ?not win32
  713. path.ToUTF8StringBuffer(attributes.name, length)
  714. ?
  715. attributes.depth = depth
  716. attributes.size = stat._filesize
  717. attributes.creationTime = stat._createtime
  718. attributes.modifiedTime = stat._modtime
  719. Return True
  720. End Function
  721. Extern
  722. Function bmx_filesystem_walkfiletree:Int(path:String, callback:EFileWalkResult(fileWalker:IFileWalker, attributes:SFileAttributes Var), walker:IFileWalker, options:EFileWalkOption, maxDepth:Int)
  723. End Extern