Filesystem.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. /*
  2. Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
  3. Permission is hereby granted, free of charge, to any person
  4. obtaining a copy of this software and associated documentation
  5. files (the "Software"), to deal in the Software without
  6. restriction, including without limitation the rights to use,
  7. copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. copies of the Software, and to permit persons to whom the
  9. Software is furnished to do so, subject to the following
  10. conditions:
  11. The above copyright notice and this permission notice shall be
  12. included in all copies or substantial portions of the Software.
  13. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  15. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  17. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  18. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. OTHER DEALINGS IN THE SOFTWARE.
  21. */
  22. #include "Filesystem.h"
  23. #include "Log.h"
  24. #include "OS.h"
  25. #include "FileStream.h"
  26. #include "Config.h"
  27. #ifdef WINDOWS
  28. #undef DeleteFile
  29. #undef CreateDirectory
  30. #endif
  31. namespace crown
  32. {
  33. //-----------------------------------------------------------------------------
  34. Filesystem::Filesystem() :
  35. mIsInit(false),
  36. mRootPath(Str::EMPTY),
  37. mUserPath(Str::EMPTY)
  38. {
  39. }
  40. //-----------------------------------------------------------------------------
  41. Filesystem::~Filesystem()
  42. {
  43. }
  44. //-----------------------------------------------------------------------------
  45. void Filesystem::Init(const char* rootPath, const char* userPath)
  46. {
  47. assert(!mIsInit);
  48. if (Str::StrCmp(rootPath, Str::EMPTY) == 0)
  49. {
  50. // Set working paths
  51. const char* envRootPath = os::get_env("CROWN_ROOT_PATH");
  52. if (envRootPath == Str::EMPTY)
  53. {
  54. mRootPath = os::get_cwd();
  55. }
  56. else
  57. {
  58. mRootPath = envRootPath;
  59. }
  60. }
  61. else
  62. {
  63. mRootPath = rootPath;
  64. }
  65. if (userPath == Str::EMPTY)
  66. {
  67. mUserPath = os::get_home();
  68. }
  69. else
  70. {
  71. mUserPath = userPath;
  72. }
  73. Log::D("Filesystem::Init()");
  74. Log::D("Filesystem: Root path: %s", mRootPath.c_str());
  75. Log::D("Filesystem: User path: %s", mUserPath.c_str());
  76. mIsInit = true;
  77. }
  78. //-----------------------------------------------------------------------------
  79. const char* Filesystem::GetRootPath() const
  80. {
  81. return mRootPath.c_str();
  82. }
  83. //-----------------------------------------------------------------------------
  84. const char* Filesystem::GetUserPath() const
  85. {
  86. return mUserPath.c_str();
  87. }
  88. //-----------------------------------------------------------------------------
  89. void Filesystem::SetUserPath(const char* relativePath)
  90. {
  91. mUserPath = relativePath;
  92. }
  93. //-----------------------------------------------------------------------------
  94. const char* Filesystem::BuildOSPath(const char* basePath, const char* relativePath)
  95. {
  96. static char osPath[1024];
  97. size_t i = 0;
  98. while (*basePath != '\0')
  99. {
  100. osPath[i++] = *basePath;
  101. basePath++;
  102. }
  103. osPath[i++] = '/';
  104. while (*relativePath != '\0')
  105. {
  106. osPath[i++] = *relativePath;
  107. relativePath++;
  108. }
  109. osPath[i] = '\0';
  110. // Replace Crown-specific path separator with OS-speficic one
  111. for (size_t j = 0; j < i; j++)
  112. {
  113. if (osPath[j] == '/')
  114. {
  115. osPath[j] = os::PATH_SEPARATOR;
  116. }
  117. }
  118. return osPath;
  119. }
  120. //-----------------------------------------------------------------------------
  121. bool Filesystem::GetInfo(const char* basePath, const char* relativePath, FilesystemEntry& info)
  122. {
  123. // Entering OS-DEPENDENT-PATH-MODE
  124. // (i.e. osPath is of the form: C:\babbeo\relativePath or /babbeo/relativePath)
  125. const char* osPath = BuildOSPath(basePath, relativePath);
  126. if (os::is_reg(osPath))
  127. {
  128. info.type = FET_FILE;
  129. info.osPath = osPath;
  130. info.relativePath = relativePath;
  131. return true;
  132. }
  133. if (os::is_dir(osPath))
  134. {
  135. info.type = FET_DIR;
  136. info.osPath = osPath;
  137. info.relativePath = relativePath;
  138. return true;
  139. }
  140. return false;
  141. }
  142. //-----------------------------------------------------------------------------
  143. bool Filesystem::Exists(const char* relativePath)
  144. {
  145. FilesystemEntry dummy;
  146. return GetInfo(mRootPath.c_str(), relativePath, dummy);
  147. }
  148. //-----------------------------------------------------------------------------
  149. bool Filesystem::IsFile(const char* relativePath)
  150. {
  151. FilesystemEntry info;
  152. if (GetInfo(mRootPath.c_str(), relativePath, info))
  153. {
  154. return info.type == FET_FILE;
  155. }
  156. return false;
  157. }
  158. //-----------------------------------------------------------------------------
  159. bool Filesystem::IsDir(const char* relativePath)
  160. {
  161. FilesystemEntry info;
  162. if (GetInfo(mRootPath.c_str(), relativePath, info))
  163. {
  164. return info.type == FET_DIR;
  165. }
  166. return false;
  167. }
  168. //-----------------------------------------------------------------------------
  169. bool Filesystem::CreateFile(const char* relativePath)
  170. {
  171. const char* osPath = BuildOSPath(mRootPath.c_str(), relativePath);
  172. return os::mknod(osPath);
  173. }
  174. //-----------------------------------------------------------------------------
  175. bool Filesystem::CreateDir(const char* relativePath)
  176. {
  177. const char* osPath = BuildOSPath(mRootPath.c_str(), relativePath);
  178. return os::mkdir(osPath);
  179. }
  180. //-----------------------------------------------------------------------------
  181. bool Filesystem::DeleteFile(const char* relativePath)
  182. {
  183. const char* osPath = BuildOSPath(mRootPath.c_str(), relativePath);
  184. return os::unlink(osPath);
  185. }
  186. //-----------------------------------------------------------------------------
  187. bool Filesystem::DeleteDir(const char* relativePath)
  188. {
  189. const char* osPath = BuildOSPath(mRootPath.c_str(), relativePath);
  190. return os::rmdir(osPath);
  191. }
  192. //-----------------------------------------------------------------------------
  193. Stream* Filesystem::OpenStream(const char* relativePath, StreamOpenMode openMode)
  194. {
  195. FilesystemEntry info;
  196. Stream* stream;
  197. bool exists = GetInfo(mRootPath.c_str(), relativePath, info);
  198. assert(exists == true && "Filesystem::OpenStream: File does not exist");
  199. assert(info.type != FET_DIR && "Filesystem::OpenStream: Trying to open directory...");
  200. if (info.type == FET_FILE)
  201. {
  202. Log::D("Filesystem::OpenStream: Found %s", info.osPath.c_str());
  203. stream = new FileStream(openMode, info.osPath);
  204. return stream;
  205. }
  206. return NULL;
  207. }
  208. /**
  209. file must exists.
  210. */
  211. Stream* Filesystem::OpenRead(const char* relativePath)
  212. {
  213. (void)relativePath;
  214. return NULL;
  215. }
  216. Stream* Filesystem::OperWrite(const char* relativePath)
  217. {
  218. (void)relativePath;
  219. return NULL;
  220. }
  221. Stream* Filesystem::OpenAppend(const char* relativePath)
  222. {
  223. (void)relativePath;
  224. return NULL;
  225. }
  226. //-----------------------------------------------------------------------------
  227. void Filesystem::Close(Stream* stream)
  228. {
  229. delete stream;
  230. }
  231. //-----------------------------------------------------------------------------
  232. void Filesystem::PrintReport()
  233. {
  234. Log::I("--- Filesystem report ---");
  235. Log::I("Path separator\t: '/'");
  236. Log::I("Root\t\t\t: %s", mRootPath.c_str());
  237. Log::I("User\t\t\t: %s", mUserPath.c_str());
  238. }
  239. ///**
  240. // Returns whether the segment is valid.
  241. //@note
  242. // The rules for valid segments are as follows:
  243. // a) The empty string is not valid.
  244. // b) Any string containing the slash character ('/') is not valid.
  245. // c) Common notations for current ('.') and parent ('..') directory are forbidden.
  246. // d) Any string containing segment or device separator characters on the local file system,
  247. // such as the backslash ('\') and colon (':') on some file systems.
  248. // (Thanks org.eclipse.core.runtime for the documentation ;D).
  249. //@param segment
  250. // The segment to be checked
  251. //@return
  252. // True if the segment is valid, false otherwise
  253. //*/
  254. //bool Filesystem::IsValidSegment(const char* segment)
  255. //{
  256. // size_t segmentLen = Str::StrLen(segment);
  257. // if (segmentLen == 0)
  258. // {
  259. // return false;
  260. // }
  261. // if (segmentLen == 1 && segment[0] == '.')
  262. // {
  263. // return false;
  264. // }
  265. // if (segmentLen == 2 && segment[0] == '.' && segment[1] == '.')
  266. // {
  267. // return false;
  268. // }
  269. // for (size_t i = 0; i < segmentLen; i++)
  270. // {
  271. // if (segment[i] == '/' ||
  272. // segment[i] == '\\' ||
  273. // segment[i] == ':'
  274. // {
  275. // return false;
  276. // }
  277. // }
  278. // return true;
  279. //}
  280. ///**
  281. // Returns whether the path is valid.
  282. //@note
  283. // The rules for valid paths are as follows:
  284. // a) The empty string is not valid.
  285. // b) If the path is absolute, it mustn't contain any leading character.
  286. //@param path
  287. // The path to be checked
  288. //@return
  289. // True if the path is valid, false otherwise
  290. //*/
  291. //bool Filesystem::IsValidPath(const char* path)
  292. //{
  293. // size_t pathLen = Str::StrLen(path);
  294. // if (pathLen == 0)
  295. // {
  296. // return false;
  297. // }
  298. // if (IsRootPath(path))
  299. // {
  300. // return true;
  301. // }
  302. // List<Str> segmentList;
  303. // if (!GetSegments(Str(path), segmentList))
  304. // {
  305. // return false;
  306. // }
  307. // size_t i = 0;
  308. // if (IsAbsolutePath(path) && path[0] != '/')
  309. // {
  310. // i = 1;
  311. // }
  312. // for (; i < segmentList.GetSize(); i++)
  313. // {
  314. // if (!IsValidSegment(segmentList[i].c_str()))
  315. // {
  316. // return false;
  317. // }
  318. // }
  319. // return true;
  320. //}
  321. ///**
  322. // Returns whether the path is absolute.
  323. //@note
  324. // (i.e. starts with Path::SEPARATOR or <a-Z><Path::DEVICE_SEPARATOR><Path::SEPARATOR>).
  325. //@param path
  326. // The path to be checked
  327. //@return
  328. // True if absolute, false otherwise
  329. //*/
  330. //bool Filesystem::IsAbsolutePath(const char* path)
  331. //{
  332. // size_t pathLen;
  333. // pathLen = Str::StrLen(path);
  334. // if (pathLen == 0)
  335. // {
  336. // return false;
  337. // }
  338. // if (path[0] == '/')
  339. // {
  340. // return true;
  341. // }
  342. // if (pathLen < 3)
  343. // {
  344. // return false;
  345. // }
  346. // if (Str::IsAlpha(path[0]) && path[1] == ':' && path[2] == os::PATH_SEPARATOR)
  347. // {
  348. // return true;
  349. // }
  350. // return false;
  351. //}
  352. ///**
  353. // Returns whether the path is the root path.
  354. //@note
  355. // (i.e. starts and ends with Path::SEPARATOR or <a-Z><Path::DEVICE_SEPARATOR><Path::SEPARATOR>).
  356. //@param path
  357. // The path to be checked
  358. //@return
  359. // True if root, false otherwise
  360. //*/
  361. //bool Filesystem::IsRootPath(const char* path)
  362. //{
  363. // size_t pathLen;
  364. // pathLen = Str::StrLen(path);
  365. // if (pathLen == 0)
  366. // {
  367. // return false;
  368. // }
  369. // if (pathLen == 1 && path[0] == PATH_SEPARATOR)
  370. // {
  371. // return true;
  372. // }
  373. // if (pathLen == 3 && Str::IsAlpha(path[0]) && path[1] == DEVICE_SEPARATOR && path[2] == PATH_SEPARATOR)
  374. // {
  375. // return true;
  376. // }
  377. // return false;
  378. //}
  379. ///**
  380. // Returns the pathname of the path.
  381. //@note
  382. // (e.g. /home/babbeo/texture.tga -> /home/babbeo).
  383. //@param path
  384. // The input path
  385. //@param ret
  386. // The output pathname
  387. //@return
  388. // True if success, false otherwise
  389. //*/
  390. //const char* Filesystem::GetPathname(const char* path)
  391. //{
  392. // size_t pathLen;
  393. // pathLen = Str::StrLen(path);
  394. // const char* c = path + pathLen - 1;
  395. // // Ignore any trailing separators
  396. // while (c > path && *c == PATH_SEPARATOR)
  397. // {
  398. // c--;
  399. // }
  400. // // Iterate backwards until first separator
  401. // while (c > path && *c != PATH_SEPARATOR)
  402. // {
  403. // c--;
  404. // }
  405. // //return (c == path) ? c : c - 1;
  406. // return (c == path) ? c + 2 : c;
  407. //}
  408. ///**
  409. // Returns the filename of the path.
  410. //@note
  411. // (e.g. /home/babbeo/texture.tga -> texture.tga).
  412. //@param path
  413. // The input path
  414. //@param ret
  415. // The output filename
  416. //@return
  417. // True if success, false otherwise
  418. //*/
  419. //bool Filesystem::GetFilename(const char* path, char* ret)
  420. //{
  421. // if (IsRootPath(path.c_str()))
  422. // {
  423. // ret = Str("");
  424. // return true;
  425. // }
  426. // RemoveTrailingSeparator(path, ret);
  427. // if (ret.FindLast(PATH_SEPARATOR) != -1)
  428. // {
  429. // ret = path.GetSubstring(path.FindLast(PATH_SEPARATOR) + 1, path.GetLength());
  430. // }
  431. // return true;
  432. //}
  433. ///**
  434. // Returns the basename of the path.
  435. //@note
  436. // (e.g. /home/babbeo/texture.tga -> texture).
  437. //@param path
  438. // The input path
  439. //@param ret
  440. // The output basename
  441. //@return
  442. // True if success, false otherwise
  443. //*/
  444. //bool Filesystem::GetBasename(const char* path, char* ret)
  445. //{
  446. // if (!GetFilename(path, ret))
  447. // {
  448. // return false;
  449. // }
  450. // if (ret.FindLast('.') != -1)
  451. // {
  452. // ret = ret.GetSubstring(0, ret.FindLast('.'));
  453. // }
  454. // return true;
  455. //}
  456. /**
  457. Returns the extension of the path.
  458. @note
  459. (e.g. /home/babbeo/texture.tga -> .tga).
  460. @param path
  461. The input path
  462. @return
  463. The extension.
  464. */
  465. const char* Filesystem::GetExtension(const char* relativePath)
  466. {
  467. assert(relativePath != NULL);
  468. static char extension[32];
  469. int i = Str::FindLast(relativePath, '.');
  470. if (i == -1)
  471. {
  472. return Str::EMPTY;
  473. }
  474. Str::StrCpy(extension, &relativePath[i]);
  475. return extension;
  476. }
  477. ///**
  478. // Returns the segments contained in path.
  479. //@param path
  480. // The input path
  481. //@param ret
  482. // The output list containing path's segments
  483. //@return
  484. // True if success, false otherwise
  485. //*/
  486. //bool Filesystem::GetSegments(const char* path, List<Str>& ret)
  487. //{
  488. // path.Split(PATH_SEPARATOR, ret);
  489. // if (ret.GetSize() > 0)
  490. // {
  491. // return true;
  492. // }
  493. // return false;
  494. //}
  495. ///**
  496. // Fills 'ret' with the same path but without the trailing directory separator.
  497. //@note
  498. // (e.g. /home/babbeo/texture.tga/ -> /home/babbeo/texture.tga).
  499. //@param path
  500. // The input path
  501. //@param ret
  502. // The ouput path
  503. //@return
  504. // True if success, false otherwise
  505. //*/
  506. //bool Filesystem::RemoveTrailingSeparator(const char* path, char* ret)
  507. //{
  508. // if (path.GetLength() == 0 || IsRootPath(path.c_str()))
  509. // {
  510. // ret = path;
  511. // return true;
  512. // }
  513. // if (path[path.GetLength() - 1] == PATH_SEPARATOR)
  514. // {
  515. // ret = path.GetSubstring(0, path.GetLength() - 1);
  516. // return true;
  517. // }
  518. // ret = path;
  519. // return true;
  520. //}
  521. Filesystem filesystem;
  522. Filesystem* GetFilesystem()
  523. {
  524. return &filesystem;
  525. }
  526. } // namespace crown