PageRenderTime 41ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/xbmc/filesystem/NptXbmcFile.cpp

https://gitlab.com/sloshedpuppie/LetsGoRetro
C++ | 546 lines | 328 code | 70 blank | 148 comment | 47 complexity | 7d877fc0a643f9956350d2e5db42a8b5 MD5 | raw file
  1. /*****************************************************************
  2. |
  3. | Neptune - Files :: XBMC Implementation
  4. |
  5. | Copyright (c) 2002-2008, Axiomatic Systems, LLC.
  6. | All rights reserved.
  7. |
  8. | Redistribution and use in source and binary forms, with or without
  9. | modification, are permitted provided that the following conditions are met:
  10. | * Redistributions of source code must retain the above copyright
  11. | notice, this list of conditions and the following disclaimer.
  12. | * Redistributions in binary form must reproduce the above copyright
  13. | notice, this list of conditions and the following disclaimer in the
  14. | documentation and/or other materials provided with the distribution.
  15. | * Neither the name of Axiomatic Systems nor the
  16. | names of its contributors may be used to endorse or promote products
  17. | derived from this software without specific prior written permission.
  18. |
  19. | THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
  20. | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. | DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
  23. | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26. | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. |
  30. ****************************************************************/
  31. /*----------------------------------------------------------------------
  32. | includes
  33. +---------------------------------------------------------------------*/
  34. #include <limits>
  35. #include <Neptune/Source/Core/NptDebug.h>
  36. #include <Neptune/Source/Core/NptFile.h>
  37. #include <Neptune/Source/Core/NptStrings.h>
  38. #include <Neptune/Source/Core/NptUtils.h>
  39. #include "File.h"
  40. #include "FileFactory.h"
  41. #include "Util.h"
  42. #include "URL.h"
  43. #ifdef TARGET_WINDOWS
  44. #define S_IWUSR _S_IWRITE
  45. #define S_ISDIR(m) ((m & _S_IFDIR) != 0)
  46. #define S_ISREG(m) ((m & _S_IFREG) != 0)
  47. #endif
  48. using namespace XFILE;
  49. typedef NPT_Reference<IFile> NPT_XbmcFileReference;
  50. /*----------------------------------------------------------------------
  51. | NPT_XbmcFileStream
  52. +---------------------------------------------------------------------*/
  53. class NPT_XbmcFileStream
  54. {
  55. public:
  56. // constructors and destructor
  57. NPT_XbmcFileStream(NPT_XbmcFileReference file) :
  58. m_FileReference(file) {}
  59. // NPT_FileInterface methods
  60. NPT_Result Seek(NPT_Position offset);
  61. NPT_Result Tell(NPT_Position& offset);
  62. NPT_Result Flush();
  63. protected:
  64. // constructors and destructors
  65. virtual ~NPT_XbmcFileStream() {}
  66. // members
  67. NPT_XbmcFileReference m_FileReference;
  68. };
  69. /*----------------------------------------------------------------------
  70. | NPT_XbmcFileStream::Seek
  71. +---------------------------------------------------------------------*/
  72. NPT_Result
  73. NPT_XbmcFileStream::Seek(NPT_Position offset)
  74. {
  75. int64_t result;
  76. result = m_FileReference->Seek(offset, SEEK_SET) ;
  77. if (result >= 0) {
  78. return NPT_SUCCESS;
  79. } else {
  80. return NPT_FAILURE;
  81. }
  82. }
  83. /*----------------------------------------------------------------------
  84. | NPT_XbmcFileStream::Tell
  85. +---------------------------------------------------------------------*/
  86. NPT_Result
  87. NPT_XbmcFileStream::Tell(NPT_Position& offset)
  88. {
  89. int64_t result = m_FileReference->GetPosition();
  90. if (result >= 0) {
  91. offset = (NPT_Position)result;
  92. return NPT_SUCCESS;
  93. } else {
  94. return NPT_FAILURE;
  95. }
  96. }
  97. /*----------------------------------------------------------------------
  98. | NPT_XbmcFileStream::Flush
  99. +---------------------------------------------------------------------*/
  100. NPT_Result
  101. NPT_XbmcFileStream::Flush()
  102. {
  103. m_FileReference->Flush();
  104. return NPT_SUCCESS;
  105. }
  106. /*----------------------------------------------------------------------
  107. | NPT_XbmcFileInputStream
  108. +---------------------------------------------------------------------*/
  109. class NPT_XbmcFileInputStream : public NPT_InputStream,
  110. private NPT_XbmcFileStream
  111. {
  112. public:
  113. // constructors and destructor
  114. NPT_XbmcFileInputStream(NPT_XbmcFileReference& file) :
  115. NPT_XbmcFileStream(file) {}
  116. // NPT_InputStream methods
  117. NPT_Result Read(void* buffer,
  118. NPT_Size bytes_to_read,
  119. NPT_Size* bytes_read);
  120. NPT_Result Seek(NPT_Position offset) {
  121. return NPT_XbmcFileStream::Seek(offset);
  122. }
  123. NPT_Result Tell(NPT_Position& offset) {
  124. return NPT_XbmcFileStream::Tell(offset);
  125. }
  126. NPT_Result GetSize(NPT_LargeSize& size);
  127. NPT_Result GetAvailable(NPT_LargeSize& available);
  128. };
  129. /*----------------------------------------------------------------------
  130. | NPT_XbmcFileInputStream::Read
  131. +---------------------------------------------------------------------*/
  132. NPT_Result
  133. NPT_XbmcFileInputStream::Read(void* buffer,
  134. NPT_Size bytes_to_read,
  135. NPT_Size* bytes_read)
  136. {
  137. unsigned int nb_read;
  138. // check the parameters
  139. if (buffer == NULL) {
  140. return NPT_ERROR_INVALID_PARAMETERS;
  141. }
  142. // read from the file
  143. nb_read = m_FileReference->Read(buffer, bytes_to_read);
  144. if (nb_read > 0) {
  145. if (bytes_read) *bytes_read = (NPT_Size)nb_read;
  146. return NPT_SUCCESS;
  147. } else {
  148. if (bytes_read) *bytes_read = 0;
  149. return NPT_ERROR_EOS;
  150. //} else { // currently no way to indicate failure
  151. // if (bytes_read) *bytes_read = 0;
  152. // return NPT_ERROR_READ_FAILED;
  153. }
  154. }
  155. /*----------------------------------------------------------------------
  156. | NPT_XbmcFileInputStream::GetSize
  157. +---------------------------------------------------------------------*/
  158. NPT_Result
  159. NPT_XbmcFileInputStream::GetSize(NPT_LargeSize& size)
  160. {
  161. size = m_FileReference->GetLength();
  162. return NPT_SUCCESS;
  163. }
  164. /*----------------------------------------------------------------------
  165. | NPT_XbmcFileInputStream::GetAvailable
  166. +---------------------------------------------------------------------*/
  167. NPT_Result
  168. NPT_XbmcFileInputStream::GetAvailable(NPT_LargeSize& available)
  169. {
  170. int64_t offset = m_FileReference->GetPosition();
  171. NPT_LargeSize size = 0;
  172. if (NPT_SUCCEEDED(GetSize(size)) && offset >= 0 && (NPT_LargeSize)offset <= size) {
  173. available = size - offset;
  174. return NPT_SUCCESS;
  175. } else {
  176. available = 0;
  177. return NPT_FAILURE;
  178. }
  179. }
  180. /*----------------------------------------------------------------------
  181. | NPT_XbmcFileOutputStream
  182. +---------------------------------------------------------------------*/
  183. class NPT_XbmcFileOutputStream : public NPT_OutputStream,
  184. private NPT_XbmcFileStream
  185. {
  186. public:
  187. // constructors and destructor
  188. NPT_XbmcFileOutputStream(NPT_XbmcFileReference& file) :
  189. NPT_XbmcFileStream(file) {}
  190. // NPT_OutputStream methods
  191. NPT_Result Write(const void* buffer,
  192. NPT_Size bytes_to_write,
  193. NPT_Size* bytes_written);
  194. NPT_Result Seek(NPT_Position offset) {
  195. return NPT_XbmcFileStream::Seek(offset);
  196. }
  197. NPT_Result Tell(NPT_Position& offset) {
  198. return NPT_XbmcFileStream::Tell(offset);
  199. }
  200. NPT_Result Flush() {
  201. return NPT_XbmcFileStream::Flush();
  202. }
  203. };
  204. /*----------------------------------------------------------------------
  205. | NPT_XbmcFileOutputStream::Write
  206. +---------------------------------------------------------------------*/
  207. NPT_Result
  208. NPT_XbmcFileOutputStream::Write(const void* buffer,
  209. NPT_Size bytes_to_write,
  210. NPT_Size* bytes_written)
  211. {
  212. int nb_written;
  213. nb_written = m_FileReference->Write(buffer, bytes_to_write);
  214. if (nb_written > 0) {
  215. if (bytes_written) *bytes_written = (NPT_Size)nb_written;
  216. return NPT_SUCCESS;
  217. } else {
  218. if (bytes_written) *bytes_written = 0;
  219. return NPT_ERROR_WRITE_FAILED;
  220. }
  221. }
  222. /*----------------------------------------------------------------------
  223. | NPT_XbmcFile
  224. +---------------------------------------------------------------------*/
  225. class NPT_XbmcFile: public NPT_FileInterface
  226. {
  227. public:
  228. // constructors and destructor
  229. NPT_XbmcFile(NPT_File& delegator);
  230. ~NPT_XbmcFile();
  231. // NPT_FileInterface methods
  232. NPT_Result Open(OpenMode mode);
  233. NPT_Result Close();
  234. NPT_Result GetInputStream(NPT_InputStreamReference& stream);
  235. NPT_Result GetOutputStream(NPT_OutputStreamReference& stream);
  236. private:
  237. // members
  238. NPT_File& m_Delegator;
  239. OpenMode m_Mode;
  240. NPT_XbmcFileReference m_FileReference;
  241. };
  242. /*----------------------------------------------------------------------
  243. | NPT_XbmcFile::NPT_XbmcFile
  244. +---------------------------------------------------------------------*/
  245. NPT_XbmcFile::NPT_XbmcFile(NPT_File& delegator) :
  246. m_Delegator(delegator),
  247. m_Mode(0)
  248. {
  249. }
  250. /*----------------------------------------------------------------------
  251. | NPT_XbmcFile::~NPT_XbmcFile
  252. +---------------------------------------------------------------------*/
  253. NPT_XbmcFile::~NPT_XbmcFile()
  254. {
  255. Close();
  256. }
  257. /*----------------------------------------------------------------------
  258. | NPT_XbmcFile::Open
  259. +---------------------------------------------------------------------*/
  260. NPT_Result
  261. NPT_XbmcFile::Open(NPT_File::OpenMode mode)
  262. {
  263. NPT_XbmcFileReference file;
  264. // check if we're already open
  265. if (!m_FileReference.IsNull()) {
  266. return NPT_ERROR_FILE_ALREADY_OPEN;
  267. }
  268. // store the mode
  269. m_Mode = mode;
  270. // check for special names
  271. const char* name = (const char*)m_Delegator.GetPath();
  272. if (NPT_StringsEqual(name, NPT_FILE_STANDARD_INPUT)) {
  273. return NPT_ERROR_FILE_NOT_READABLE;
  274. } else if (NPT_StringsEqual(name, NPT_FILE_STANDARD_OUTPUT)) {
  275. return NPT_ERROR_FILE_NOT_WRITABLE;
  276. } else if (NPT_StringsEqual(name, NPT_FILE_STANDARD_ERROR)) {
  277. return NPT_ERROR_FILE_NOT_WRITABLE;
  278. } else {
  279. file = CFileFactory::CreateLoader(name);
  280. if (file.IsNull()) {
  281. return NPT_ERROR_NO_SUCH_FILE;
  282. }
  283. bool result;
  284. CURL* url = new CURL(name);
  285. // compute mode
  286. if (mode & NPT_FILE_OPEN_MODE_WRITE) {
  287. result = file->OpenForWrite(*url, (mode & NPT_FILE_OPEN_MODE_TRUNCATE)?true:false);
  288. } else {
  289. result = file->Open(*url);
  290. }
  291. delete url;
  292. if (!result) return NPT_ERROR_NO_SUCH_FILE;
  293. }
  294. // store reference
  295. m_FileReference = file;
  296. return NPT_SUCCESS;
  297. }
  298. /*----------------------------------------------------------------------
  299. | NPT_XbmcFile::Close
  300. +---------------------------------------------------------------------*/
  301. NPT_Result
  302. NPT_XbmcFile::Close()
  303. {
  304. // release the file reference
  305. m_FileReference = NULL;
  306. // reset the mode
  307. m_Mode = 0;
  308. return NPT_SUCCESS;
  309. }
  310. /*----------------------------------------------------------------------
  311. | NPT_XbmcFile::GetInputStream
  312. +---------------------------------------------------------------------*/
  313. NPT_Result
  314. NPT_XbmcFile::GetInputStream(NPT_InputStreamReference& stream)
  315. {
  316. // default value
  317. stream = NULL;
  318. // check that the file is open
  319. if (m_FileReference.IsNull()) return NPT_ERROR_FILE_NOT_OPEN;
  320. // check that the mode is compatible
  321. if (!(m_Mode & NPT_FILE_OPEN_MODE_READ)) {
  322. return NPT_ERROR_FILE_NOT_READABLE;
  323. }
  324. // create a stream
  325. stream = new NPT_XbmcFileInputStream(m_FileReference);
  326. return NPT_SUCCESS;
  327. }
  328. /*----------------------------------------------------------------------
  329. | NPT_XbmcFile::GetOutputStream
  330. +---------------------------------------------------------------------*/
  331. NPT_Result
  332. NPT_XbmcFile::GetOutputStream(NPT_OutputStreamReference& stream)
  333. {
  334. // default value
  335. stream = NULL;
  336. // check that the file is open
  337. if (m_FileReference.IsNull()) return NPT_ERROR_FILE_NOT_OPEN;
  338. // check that the mode is compatible
  339. if (!(m_Mode & NPT_FILE_OPEN_MODE_WRITE)) {
  340. return NPT_ERROR_FILE_NOT_WRITABLE;
  341. }
  342. // create a stream
  343. stream = new NPT_XbmcFileOutputStream(m_FileReference);
  344. return NPT_SUCCESS;
  345. }
  346. static NPT_Result
  347. MapErrno(int err) {
  348. switch (err) {
  349. case EACCES: return NPT_ERROR_PERMISSION_DENIED;
  350. case EPERM: return NPT_ERROR_PERMISSION_DENIED;
  351. case ENOENT: return NPT_ERROR_NO_SUCH_FILE;
  352. case ENAMETOOLONG: return NPT_ERROR_INVALID_PARAMETERS;
  353. case EBUSY: return NPT_ERROR_FILE_BUSY;
  354. case EROFS: return NPT_ERROR_FILE_NOT_WRITABLE;
  355. case ENOTDIR: return NPT_ERROR_FILE_NOT_DIRECTORY;
  356. case EEXIST: return NPT_ERROR_FILE_ALREADY_EXISTS;
  357. case ENOSPC: return NPT_ERROR_FILE_NOT_ENOUGH_SPACE;
  358. case ENOTEMPTY: return NPT_ERROR_DIRECTORY_NOT_EMPTY;
  359. default: return NPT_ERROR_ERRNO(err);
  360. }
  361. }
  362. /*----------------------------------------------------------------------
  363. | NPT_FilePath::Separator
  364. +---------------------------------------------------------------------*/
  365. const char* const NPT_FilePath::Separator = "/";
  366. /*----------------------------------------------------------------------
  367. | NPT_File::NPT_File
  368. +---------------------------------------------------------------------*/
  369. NPT_File::NPT_File(const char* path) : m_Path(path)
  370. {
  371. m_Delegate = new NPT_XbmcFile(*this);
  372. }
  373. /*----------------------------------------------------------------------
  374. | NPT_File::operator=
  375. +---------------------------------------------------------------------*/
  376. NPT_File&
  377. NPT_File::operator=(const NPT_File& file)
  378. {
  379. if (this != &file) {
  380. delete m_Delegate;
  381. m_Path = file.m_Path;
  382. m_Delegate = new NPT_XbmcFile(*this);
  383. }
  384. return *this;
  385. }
  386. /*----------------------------------------------------------------------
  387. | NPT_File::GetRoots
  388. +---------------------------------------------------------------------*/
  389. NPT_Result
  390. NPT_File::GetRoots(NPT_List<NPT_String>& roots)
  391. {
  392. return NPT_FAILURE;
  393. }
  394. /*----------------------------------------------------------------------
  395. | NPT_File::CreateDir
  396. +---------------------------------------------------------------------*/
  397. NPT_Result
  398. NPT_File::CreateDir(const char* path)
  399. {
  400. return NPT_ERROR_PERMISSION_DENIED;
  401. }
  402. /*----------------------------------------------------------------------
  403. | NPT_File::RemoveFile
  404. +---------------------------------------------------------------------*/
  405. NPT_Result
  406. NPT_File::RemoveFile(const char* path)
  407. {
  408. return NPT_ERROR_PERMISSION_DENIED;
  409. }
  410. /*----------------------------------------------------------------------
  411. | NPT_File::RemoveDir
  412. +---------------------------------------------------------------------*/
  413. NPT_Result
  414. NPT_File::RemoveDir(const char* path)
  415. {
  416. return NPT_ERROR_PERMISSION_DENIED;
  417. }
  418. /*----------------------------------------------------------------------
  419. | NPT_File::Rename
  420. +---------------------------------------------------------------------*/
  421. NPT_Result
  422. NPT_File::Rename(const char* from_path, const char* to_path)
  423. {
  424. return NPT_ERROR_PERMISSION_DENIED;
  425. }
  426. /*----------------------------------------------------------------------
  427. | NPT_File::ListDir
  428. +---------------------------------------------------------------------*/
  429. NPT_Result
  430. NPT_File::ListDir(const char* path,
  431. NPT_List<NPT_String>& entries,
  432. NPT_Ordinal start /* = 0 */,
  433. NPT_Cardinal max /* = 0 */)
  434. {
  435. return NPT_FAILURE;
  436. }
  437. /*----------------------------------------------------------------------
  438. | NPT_File::GetWorkingDir
  439. +---------------------------------------------------------------------*/
  440. NPT_Result
  441. NPT_File::GetWorkingDir(NPT_String& path)
  442. {
  443. return NPT_FAILURE;
  444. }
  445. /*----------------------------------------------------------------------
  446. | NPT_File::GetInfo
  447. +---------------------------------------------------------------------*/
  448. NPT_Result
  449. NPT_File::GetInfo(const char* path, NPT_FileInfo* info)
  450. {
  451. struct __stat64 stat_buffer = {0};
  452. int result;
  453. if (!info)
  454. return NPT_FAILURE;
  455. NPT_SetMemory(info, 0, sizeof(*info));
  456. result = CFile::Stat(path, &stat_buffer);
  457. if (result !=0) return MapErrno(errno);
  458. if (info)
  459. {
  460. info->m_Size = stat_buffer.st_size;
  461. if (S_ISREG(stat_buffer.st_mode)) {
  462. info->m_Type = NPT_FileInfo::FILE_TYPE_REGULAR;
  463. } else if (S_ISDIR(stat_buffer.st_mode)) {
  464. info->m_Type = NPT_FileInfo::FILE_TYPE_DIRECTORY;
  465. } else {
  466. info->m_Type = NPT_FileInfo::FILE_TYPE_OTHER;
  467. }
  468. info->m_AttributesMask &= NPT_FILE_ATTRIBUTE_READ_ONLY;
  469. if ((stat_buffer.st_mode & S_IWUSR) == 0) {
  470. info->m_Attributes &= NPT_FILE_ATTRIBUTE_READ_ONLY;
  471. }
  472. info->m_CreationTime.SetSeconds(0);
  473. info->m_ModificationTime.SetSeconds(stat_buffer.st_mtime);
  474. }
  475. return NPT_SUCCESS;
  476. }