fileSystemFunctions.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "console/console.h"
  24. #include "console/consoleInternal.h"
  25. #include "console/ast.h"
  26. #include "io/resource/resourceManager.h"
  27. #include "io/fileStream.h"
  28. #include "console/compiler.h"
  29. #include "platform/event.h"
  30. #include "game/gameInterface.h"
  31. #include "platform/platformInput.h"
  32. #include "torqueConfig.h"
  33. #include "memory/frameAllocator.h"
  34. // Buffer for expanding script filenames.
  35. static char scriptFilenameBuffer[1024];
  36. //-------------------------------------- Helper Functions
  37. static void forwardslash(char *str)
  38. {
  39. while(*str)
  40. {
  41. if(*str == '\\')
  42. *str = '/';
  43. str++;
  44. }
  45. }
  46. static void backslash(char *str)
  47. {
  48. while(*str)
  49. {
  50. if(*str == '/')
  51. *str = '\\';
  52. str++;
  53. }
  54. }
  55. //----------------------------------------------------------------
  56. ConsoleFunctionGroupBegin( FileSystem, "Functions allowing you to search for files, read them, write them, and access their properties.");
  57. static ResourceObject *firstMatch = NULL;
  58. ConsoleFunction(findFirstFile, const char *, 2, 2, "( strPattern )\n"
  59. "@param strPattern The string pattern to search for.\n"
  60. "@return Returns a string representing the first file in the directory system matching the given pattern.")
  61. {
  62. TORQUE_UNUSED( argc );
  63. const char *fn = NULL;
  64. firstMatch = NULL;
  65. if(Con::expandPath(scriptFilenameBuffer, sizeof(scriptFilenameBuffer), argv[1]))
  66. firstMatch = ResourceManager->findMatch(scriptFilenameBuffer, &fn, NULL);
  67. if(firstMatch)
  68. return fn;
  69. else
  70. return "";
  71. }
  72. ConsoleFunction(findNextFile, const char *, 2, 2, "( strPattern )\n"
  73. "@param strPattern The string pattern to search for.\n"
  74. "@return Returns the next file matching a search begun in findFirstFile.")
  75. {
  76. TORQUE_UNUSED( argc );
  77. const char *fn = NULL;
  78. if(Con::expandPath(scriptFilenameBuffer, sizeof(scriptFilenameBuffer), argv[1]))
  79. firstMatch = ResourceManager->findMatch(scriptFilenameBuffer, &fn, firstMatch);
  80. else
  81. firstMatch = NULL;
  82. if(firstMatch)
  83. return fn;
  84. else
  85. return "";
  86. }
  87. ConsoleFunction(getFileCount, S32, 2, 2, "(strPattern) \n"
  88. "@param strPattern The string pattern to search for.\n"
  89. "@return Returns the number of files in the directory tree that match the given pattern")
  90. {
  91. TORQUE_UNUSED( argc );
  92. const char* fn;
  93. U32 count = 0;
  94. firstMatch = ResourceManager->findMatch(argv[1], &fn, NULL);
  95. if ( firstMatch )
  96. {
  97. count++;
  98. while ( 1 )
  99. {
  100. firstMatch = ResourceManager->findMatch(argv[1], &fn, firstMatch);
  101. if ( firstMatch )
  102. count++;
  103. else
  104. break;
  105. }
  106. }
  107. return( count );
  108. }
  109. ConsoleFunction(findFirstFileMultiExpr, const char *, 2, 2, "(strPattern)\n"
  110. "@param strPattern The string pattern to search for.\n"
  111. "@return Returns the first file in the directory system matching the given pattern.")
  112. {
  113. TORQUE_UNUSED( argc );
  114. const char *fn = NULL;
  115. firstMatch = NULL;
  116. if(Con::expandPath(scriptFilenameBuffer, sizeof(scriptFilenameBuffer), argv[1]))
  117. firstMatch = ResourceManager->findMatchMultiExprs(scriptFilenameBuffer, &fn, NULL);
  118. if(firstMatch)
  119. return fn;
  120. else
  121. return "";
  122. }
  123. ConsoleFunction(findNextFileMultiExpr, const char *, 2, 2, "(string pattern) Returns the next file matching a search begun in findFirstFile.")
  124. {
  125. TORQUE_UNUSED( argc );
  126. const char *fn = NULL;
  127. if(Con::expandPath(scriptFilenameBuffer, sizeof(scriptFilenameBuffer), argv[1]))
  128. firstMatch = ResourceManager->findMatchMultiExprs(scriptFilenameBuffer, &fn, firstMatch);
  129. else
  130. firstMatch = NULL;
  131. if(firstMatch)
  132. return fn;
  133. else
  134. return "";
  135. }
  136. ConsoleFunction(getFileCountMultiExpr, S32, 2, 2, "(strPattern) \n"
  137. "@param strPattern The string pattern to search for.\n"
  138. "@return Returns the number of files in the directory tree that match the given pattern")
  139. {
  140. TORQUE_UNUSED( argc );
  141. const char* fn;
  142. U32 count = 0;
  143. firstMatch = ResourceManager->findMatchMultiExprs(argv[1], &fn, NULL);
  144. if ( firstMatch )
  145. {
  146. count++;
  147. while ( 1 )
  148. {
  149. firstMatch = ResourceManager->findMatchMultiExprs(argv[1], &fn, firstMatch);
  150. if ( firstMatch )
  151. count++;
  152. else
  153. break;
  154. }
  155. }
  156. return( count );
  157. }
  158. ConsoleFunction(getFileCRC, S32, 2, 2, "(filename)\n"
  159. "@param filename The string representing the file from which to get the CRC\n"
  160. "@return An integer")
  161. {
  162. TORQUE_UNUSED( argc );
  163. U32 crcVal;
  164. Con::expandPath(scriptFilenameBuffer, sizeof(scriptFilenameBuffer), argv[1]);
  165. if(!ResourceManager->getCrc(scriptFilenameBuffer, crcVal))
  166. return(-1);
  167. return(S32(crcVal));
  168. }
  169. ConsoleFunction(isDirectory, bool, 2, 2, "(path)\n @param pathName Path to check.\n @return Returns true if the given path is a folder/directory, false otherwise")
  170. {
  171. bool doesExist = Platform::isDirectory(argv[1]);
  172. if(doesExist)
  173. return true;
  174. return false;
  175. }
  176. ConsoleFunction(isFile, bool, 2, 2, "(fileName)\n"
  177. "@param fileName Filename to check.\n"
  178. "@return Returns true if the given filename is an existing file or false otherwise")
  179. {
  180. Con::expandPath(scriptFilenameBuffer, sizeof(scriptFilenameBuffer), argv[1]);
  181. return bool(ResourceManager->find(scriptFilenameBuffer));
  182. }
  183. ConsoleFunction(isWriteableFileName, bool, 2, 2, "(fileName)\n"
  184. "@param fileName Filename to check.\n"
  185. "@return Returns true if the given filename is an existing file and is not Read-Only or false otherwise")
  186. {
  187. TORQUE_UNUSED( argc );
  188. char filename[1024];
  189. Con::expandPath(filename, sizeof(filename), argv[1]);
  190. if (filename == NULL || *filename == 0)
  191. return false;
  192. // in a writeable directory?
  193. if(!ResourceManager->isValidWriteFileName(filename))
  194. return(false);
  195. // exists?
  196. FileStream fs;
  197. if(!fs.open(filename, FileStream::Read))
  198. return(true);
  199. // writeable? (ReadWrite will create file if it does not exist)
  200. fs.close();
  201. if(!fs.open(filename, FileStream::ReadWrite))
  202. return(false);
  203. return(true);
  204. }
  205. ConsoleFunction(getDirectoryList, const char*, 2, 3, "(strPath, [intDepth])\n"
  206. "@param strPath The path in which to check\n"
  207. "@param intDepth The depth in which to return (default 0 if not specified)\n"
  208. "@return The directory contents")
  209. {
  210. // Grab the full path.
  211. char path[1024];
  212. Platform::makeFullPathName(dStrcmp(argv[1], "/") == 0 ? "" : argv[1], path, sizeof(path));
  213. // Append a trailing backslash if it's not present already.
  214. if (path[dStrlen(path) - 1] != '/')
  215. {
  216. S32 pos = dStrlen(path);
  217. path[pos] = '/';
  218. path[pos + 1] = '\0';
  219. }
  220. // Grab the depth to search.
  221. S32 depth = 0;
  222. if (argc > 2)
  223. depth = dAtoi(argv[2]);
  224. // Dump the directories.
  225. Vector<StringTableEntry> directories;
  226. Platform::dumpDirectories(path, directories, depth, true);
  227. if( directories.empty() )
  228. return "";
  229. // Grab the required buffer length.
  230. S32 length = 0;
  231. for (S32 i = 0; i < directories.size(); i++)
  232. length += dStrlen(directories[i]) + 1;
  233. // Get a return buffer.
  234. char* buffer = Con::getReturnBuffer(length);
  235. char* p = buffer;
  236. // Copy the directory names to the buffer.
  237. for (S32 i = 0; i < directories.size(); i++)
  238. {
  239. dStrcpy(p, directories[i]);
  240. p += dStrlen(directories[i]);
  241. // Tab separated.
  242. p[0] = '\t';
  243. p++;
  244. }
  245. p--;
  246. p[0] = '\0';
  247. return buffer;
  248. }
  249. ConsoleFunction(getFileList, const char*, 2, 2, "(strPath) - Gets all the files in the specified directory.\n"
  250. "@param strPath The path in which to check\n"
  251. "@return A list of files in the specified directory.")
  252. {
  253. // Grab the full path.
  254. char basePath[1024];
  255. Con::expandPath( basePath, sizeof(basePath), argv[1] );
  256. Vector<Platform::FileInfo> files;
  257. if ( !Platform::dumpPath( basePath, files, 0 ) )
  258. {
  259. Con::warnf("Failed to get file list in directory '%s'", basePath );
  260. return "";
  261. }
  262. if ( files.size() == 0 )
  263. return "";
  264. // Grab the required buffer length.
  265. S32 length = 0;
  266. for (S32 i = 0; i < files.size(); i++)
  267. length += dStrlen(files[i].pFileName) + 1;
  268. // Get a return buffer.
  269. char* buffer = Con::getReturnBuffer(length);
  270. char* p = buffer;
  271. // Copy the directory names to the buffer.
  272. for (S32 i = 0; i < files.size(); i++)
  273. {
  274. dStrcpy(p, files[i].pFileName);
  275. p += dStrlen(files[i].pFileName);
  276. // Tab separated.
  277. p[0] = '\t';
  278. p++;
  279. }
  280. p--;
  281. p[0] = '\0';
  282. return buffer;
  283. }
  284. ConsoleFunction(fileSize, S32, 2, 2, "(fileName)\n"
  285. "@param fileName The name of the file to check.\n"
  286. "@return Returns the size of the file as an integer or -1 if file not found")
  287. {
  288. TORQUE_UNUSED( argc );
  289. Con::expandPath(scriptFilenameBuffer, sizeof(scriptFilenameBuffer), argv[1]);
  290. return Platform::getFileSize( scriptFilenameBuffer );
  291. }
  292. ConsoleFunction(fileDelete, bool, 2,2, "(fileName)\n"
  293. "@param fileName Name of the file to remove"
  294. "@return Returns true on success and false on failure")
  295. {
  296. static char fileName[1024];
  297. static char sandboxFileName[1024];
  298. Con::expandPath( fileName, sizeof( fileName ), argv[1] );
  299. Platform::makeFullPathName(fileName, sandboxFileName, sizeof(sandboxFileName));
  300. return Platform::fileDelete(sandboxFileName);
  301. }
  302. ConsoleFunction(directoryDelete, bool, 2,2, "(directoryName)\n"
  303. "@param directoryName Name of the directory to remove"
  304. "@return Returns true on success and false on failure")
  305. {
  306. static char directoryName[1024];
  307. static char sandboxdirectoryName[1024];
  308. Con::expandPath( directoryName, sizeof( directoryName ), argv[1] );
  309. Platform::makeFullPathName(directoryName, sandboxdirectoryName, sizeof(sandboxdirectoryName));
  310. return Platform::deleteDirectory(sandboxdirectoryName);
  311. }
  312. //----------------------------------------------------------------
  313. ConsoleFunction(isValidImageFile, bool, 2, 2, "(string filePath)\n"
  314. "@param filePath Full path of file to check.\n"
  315. "@return Returns true if the given filename is a valid image file or false otherwise")
  316. {
  317. Con::expandPath(scriptFilenameBuffer, sizeof(scriptFilenameBuffer), argv[1]);
  318. // does file exist?
  319. if (!ResourceManager->find(scriptFilenameBuffer))
  320. return false;
  321. const char *ext = dStrrchr(argv[1], '.');
  322. if (!ext)
  323. return false; // no extension
  324. Stream *stream = ResourceManager->openStream(scriptFilenameBuffer);
  325. if(stream == NULL)
  326. return false;
  327. bool ret = false;
  328. if (dStricmp(ext, ".jpg") == 0)
  329. {
  330. U8 bArray[2];
  331. stream->read(2, bArray);
  332. // check header signature
  333. ret = ((bArray[0] == 0xFF) && (bArray[1] == 0xD8));
  334. }
  335. else if (dStricmp(ext, ".png") == 0)
  336. {
  337. int i = 0;
  338. U8 bArray[8];
  339. stream->read(8, bArray);
  340. // check header signature
  341. ret = ((bArray[i++] == 0x89) && (bArray[i++] == 0x50) && (bArray[i++] == 0x4E) && (bArray[i++] == 0x47));
  342. }
  343. ResourceManager->closeStream(stream);
  344. return ret;
  345. }
  346. ConsoleFunction(fileExt, const char *, 2, 2, "(fileName)\n "
  347. "@param Name of file from which to extract extension\n"
  348. "@return A string containing the file's extension (assuming all data after first '.' is the extension) or returns empty string on failure")
  349. {
  350. TORQUE_UNUSED( argc );
  351. const char *ret = dStrrchr(argv[1], '.');
  352. if(ret)
  353. return ret;
  354. return "";
  355. }
  356. ConsoleFunction(fileBase, const char *, 2, 2, "fileBase(fileName)")
  357. {
  358. S32 pathLen = dStrlen( argv[1] );
  359. FrameTemp<char> szPathCopy( pathLen + 1);
  360. dStrcpy( szPathCopy, argv[1] );
  361. forwardslash( szPathCopy );
  362. TORQUE_UNUSED( argc );
  363. const char *path = dStrrchr(szPathCopy, '/');
  364. if(!path)
  365. path = szPathCopy;
  366. else
  367. path++;
  368. char *ret = Con::getReturnBuffer(dStrlen(path) + 1);
  369. dStrcpy(ret, path);
  370. char *ext = dStrrchr(ret, '.');
  371. if(ext)
  372. *ext = 0;
  373. return ret;
  374. }
  375. ConsoleFunction(fileName, const char *, 2, 2, "(filePathName) Extract the filename from the full path description")
  376. {
  377. S32 pathLen = dStrlen( argv[1] );
  378. FrameTemp<char> szPathCopy( pathLen + 1);
  379. dStrcpy( szPathCopy, argv[1] );
  380. forwardslash( szPathCopy );
  381. TORQUE_UNUSED( argc );
  382. const char *name = dStrrchr(szPathCopy, '/');
  383. if(!name)
  384. name = szPathCopy;
  385. else
  386. name++;
  387. char *ret = Con::getReturnBuffer(dStrlen(name));
  388. dStrcpy(ret, name);
  389. return ret;
  390. }
  391. ConsoleFunction(filePath, const char *, 2, 2, "(fileName) Extract the file path from a file's full desciption")
  392. {
  393. S32 pathLen = dStrlen( argv[1] );
  394. FrameTemp<char> szPathCopy( pathLen + 1);
  395. dStrcpy( szPathCopy, argv[1] );
  396. forwardslash( szPathCopy );
  397. TORQUE_UNUSED( argc );
  398. const char *path = dStrrchr(szPathCopy, '/');
  399. if(!path)
  400. return "";
  401. U32 len = path - (char*)szPathCopy;
  402. char *ret = Con::getReturnBuffer(len + 1);
  403. dStrncpy(ret, szPathCopy, len);
  404. ret[len] = 0;
  405. return ret;
  406. }
  407. ConsoleFunction(getCurrentDate, const char *, 2, 2, "(bool reverse) Gets the current date and time.\n"
  408. "@param reverse Determines if the format will be Month/Day/Year/Hour:Min:Seconds or Year/Month/Day/Hour:Min:Seconds")
  409. {
  410. Platform::LocalTime lt;
  411. Platform::getLocalTime(lt);
  412. char temp[128];
  413. if (dAtob(argv[1]))
  414. dSprintf(temp, 256, "%d/%d/%d:%d:%d:%d", lt.year+1900, lt.month+1, lt.monthday, lt.hour, lt.min, lt.sec);
  415. else
  416. dSprintf(temp, 256, "%d/%d/%d:%d:%d:%d", lt.month+1, lt.monthday, lt.year+1900, lt.hour, lt.min, lt.sec);
  417. char* returnBuffer = Con::getReturnBuffer(dStrlen(temp + 1));
  418. dStrcpy(returnBuffer, temp);
  419. return returnBuffer;
  420. }
  421. ConsoleFunction(openFolder, void, 2 ,2,"openFolder(%path);")
  422. {
  423. Platform::openFolder( argv[1] );
  424. }
  425. ConsoleFunction(pathCopy, bool, 3, 4, "pathCopy(fromFile, toFile [, nooverwrite = true])")
  426. {
  427. bool nooverwrite = true;
  428. if( argc > 3 )
  429. nooverwrite = dAtob( argv[3] );
  430. static char fromFile[1024];
  431. static char toFile[1024];
  432. static char qualifiedFromFile[1024];
  433. static char qualifiedToFile[1024];
  434. Con::expandPath( fromFile, sizeof( fromFile ), argv[1] );
  435. Con::expandPath( toFile, sizeof( toFile ), argv[2] );
  436. Platform::makeFullPathName(fromFile, qualifiedFromFile, sizeof(qualifiedFromFile));
  437. Platform::makeFullPathName(toFile, qualifiedToFile, sizeof(qualifiedToFile));
  438. return Platform::pathCopy( qualifiedFromFile, qualifiedToFile, nooverwrite );
  439. }
  440. ConsoleFunction(getCurrentDirectory, const char *, 1, 1, "getCurrentDirectory()")
  441. {
  442. return Platform::getCurrentDirectory();
  443. }
  444. ConsoleFunction( setCurrentDirectory, bool, 2, 2, "setCurrentDirectory(absolutePathName)" )
  445. {
  446. return Platform::setCurrentDirectory( StringTable->insert( argv[1] ) );
  447. }
  448. ConsoleFunction(getExecutableName, const char *, 1, 1, "getExecutableName()")
  449. {
  450. return Platform::getExecutableName();
  451. }
  452. ConsoleFunction(getMainDotCsDir, const char *, 1, 1, "getMainDotCsDir()")
  453. {
  454. return Platform::getMainDotCsDir();
  455. }
  456. ConsoleFunction(makeFullPath, const char *, 2, 3, "(string path, [string currentWorkingDir])")
  457. {
  458. char *buf = Con::getReturnBuffer(512);
  459. Platform::makeFullPathName(argv[1], buf, 512, argc > 2 ? argv[2] : NULL);
  460. return buf;
  461. }
  462. ConsoleFunction(makeRelativePath, const char *, 3, 3, "(string path, string to)")
  463. {
  464. return Platform::makeRelativePathName(argv[1], argv[2]);
  465. }
  466. ConsoleFunction(pathConcat, const char *, 3, 0, "(string path, string file1, [... fileN])")
  467. {
  468. char *buf = Con::getReturnBuffer(1024);
  469. char pathBuf[1024];
  470. dStrcpy(buf, argv[1]);
  471. for(S32 i = 2;i < argc;++i)
  472. {
  473. Platform::makeFullPathName(argv[i], pathBuf, 1024, buf);
  474. dStrcpy(buf, pathBuf);
  475. }
  476. return buf;
  477. }
  478. ConsoleFunction(restartInstance, void, 1, 1, "restartInstance()")
  479. {
  480. Game->setRestart( true );
  481. Platform::postQuitMessage( 0 );
  482. }
  483. ConsoleFunction( createPath, bool, 2,2, "createPath(\"file name or path name\"); creates the path or path to the file name")
  484. {
  485. static char pathName[1024];
  486. Con::expandPath( pathName, sizeof( pathName ), argv[1] );
  487. return Platform::createPath( pathName );
  488. }
  489. ConsoleFunctionGroupEnd( FileSystem );