FileSystem.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. // interface to file system
  2. //
  3. // Copyright (c) 2009 Openmoko Inc.
  4. //
  5. // Authors Christopher Hall <hsw@openmoko.com>
  6. //
  7. // Redistribution and use in source and binary forms, with or without
  8. // modification, are permitted provided that the following conditions are
  9. // met:
  10. //
  11. // 1. Redistributions of source code must retain the above copyright
  12. // notice, this list of conditions and the following disclaimer.
  13. //
  14. // 2. Redistributions in binary form must reproduce the above copyright
  15. // notice, this list of conditions and the following disclaimer in
  16. // the documentation and/or other materials provided with the
  17. // distribution.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY
  20. // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  22. // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
  23. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  24. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  25. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  26. // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  27. // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  28. // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  29. // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. #include <stddef.h>
  31. #include <stdbool.h>
  32. #include <string.h>
  33. #include <tff.h>
  34. #include <diskio.h>
  35. #include "forth.h"
  36. #include "FileSystem.h"
  37. #define SizeOfArray(a) (sizeof(a) / sizeof((a)[0]))
  38. // a type that can hold the path to the file
  39. typedef char FilenameType[128 + 1];
  40. // this determines the maximum files that can be open simultaneously
  41. typedef struct {
  42. bool IsOpen;
  43. FIL file;
  44. FilenameType filename;
  45. uint8_t ReadBuffer[1024];
  46. int ReadRemaining;
  47. int ReadOffset;
  48. } FileType;
  49. static FileType FileControlBlock[20];
  50. // this determines the maximum directoriess that can be open simultaneously
  51. typedef struct {
  52. bool IsOpen;
  53. DIR directory;
  54. FilenameType directoryname;
  55. } DirectoryType;
  56. static DirectoryType DirectoryControlBlock[10];
  57. // state for the entire file system
  58. static FATFS TheFileSystem;
  59. static bool ForthBufferToCString(char *buffer, size_t length,
  60. Forth_PointerType SourceBuffer, Forth_CellType SourceLength)
  61. {
  62. if (NULL == buffer || NULL == SourceBuffer) {
  63. return false;
  64. }
  65. if (SourceLength >= length) {
  66. --length;
  67. } else {
  68. length = SourceLength;
  69. }
  70. if (length > 0) {
  71. memcpy(buffer, SourceBuffer, length);
  72. buffer[length] = '\0';
  73. return true;
  74. }
  75. return false;
  76. }
  77. // ensure: 1 <= handle <= array size
  78. static FileType *ValidateFileHandle(Forth_ReturnType *r, Forth_CellType handle)
  79. {
  80. r->rc = FR_OK;
  81. r->result = 0;
  82. if (1 > handle || SizeOfArray(FileControlBlock) < handle) {
  83. r->rc = FR_INVALID_OBJECT;
  84. return NULL;
  85. }
  86. if (!FileControlBlock[handle - 1].IsOpen) {
  87. r->rc = FR_DENIED;
  88. return NULL;
  89. }
  90. return &FileControlBlock[handle - 1];
  91. }
  92. // ensure: 1 <= handle <= array size
  93. static DirectoryType *ValidateDirectoryHandle(Forth_ReturnType *r, Forth_CellType handle)
  94. {
  95. r->rc = FR_OK;
  96. r->result = 0;
  97. if (1 > handle || SizeOfArray(DirectoryControlBlock) < handle) {
  98. r->rc = FR_INVALID_OBJECT;
  99. return NULL;
  100. }
  101. if (!DirectoryControlBlock[handle - 1].IsOpen) {
  102. r->rc = FR_DENIED;
  103. return NULL;
  104. }
  105. return &DirectoryControlBlock[handle - 1];
  106. }
  107. void FileSystem_initialise(void)
  108. {
  109. size_t i = 0;
  110. for (i = 0; i < SizeOfArray(FileControlBlock); i++) {
  111. FileControlBlock[i].IsOpen = false;
  112. FileControlBlock[i].filename[0] = '\0';
  113. }
  114. for (i = 0; i < SizeOfArray(DirectoryControlBlock); i++) {
  115. DirectoryControlBlock[i].IsOpen = false;
  116. DirectoryControlBlock[i].directoryname[0] = '\0';
  117. }
  118. memset(&TheFileSystem, 0, sizeof(TheFileSystem));
  119. {
  120. uint8_t b = 0;
  121. disk_ioctl(0, CTRL_POWER, &b);
  122. disk_initialize(0);
  123. }
  124. f_mount(0, &TheFileSystem); // only possible value is zero
  125. }
  126. // closes all open handles, both files and directories
  127. void FileSystem_CloseAll(void)
  128. {
  129. size_t i = 0;
  130. for (i = 0; i < SizeOfArray(FileControlBlock); i++) {
  131. FileSystem_close(i + 1);
  132. }
  133. for (i = 0; i < SizeOfArray(DirectoryControlBlock); i++) {
  134. FileSystem_CloseDirectory(i + 1);
  135. }
  136. FileSystem_initialise();
  137. }
  138. Forth_ReturnType FileSystem_open(const Forth_PointerType filename, Forth_CellType length, Forth_CellType fam)
  139. {
  140. Forth_ReturnType r = {0, FR_OK};
  141. size_t i = 0;
  142. for (i = 0; i < SizeOfArray(FileControlBlock); i++) {
  143. if (!FileControlBlock[i].IsOpen) {
  144. if (!ForthBufferToCString(FileControlBlock[i].filename,
  145. sizeof(FileControlBlock[i].filename),
  146. filename, length)) {
  147. r.rc = FR_INVALID_NAME;
  148. return r;
  149. }
  150. r.rc = f_open(&FileControlBlock[i].file, FileControlBlock[i].filename, fam);
  151. if (FR_OK == r.rc) {
  152. FileControlBlock[i].IsOpen = true;
  153. FileControlBlock[i].ReadRemaining = 0;
  154. FileControlBlock[i].ReadOffset = 0;
  155. r.result = i + 1; // handle starts at one(1), not zero(0)
  156. return r;
  157. }
  158. break;
  159. }
  160. }
  161. r.rc = FR_DENIED;
  162. return r;
  163. }
  164. Forth_ReturnType FileSystem_rename(const Forth_PointerType OldFilename, Forth_CellType OldLength,
  165. const Forth_PointerType NewFilename, Forth_CellType NewLength)
  166. {
  167. Forth_ReturnType r = {0, FR_OK};
  168. FilenameType TempOldFilename;
  169. FilenameType TempNewFilename;
  170. if (!ForthBufferToCString(TempOldFilename, sizeof(TempOldFilename), OldFilename, OldLength)
  171. || !ForthBufferToCString(TempNewFilename, sizeof(TempNewFilename), NewFilename, NewLength)) {
  172. r.rc = FR_INVALID_NAME;
  173. return r;
  174. }
  175. r.rc = f_rename(TempOldFilename, TempNewFilename);
  176. return r;
  177. }
  178. Forth_ReturnType FileSystem_delete(const Forth_PointerType filename, Forth_CellType length)
  179. {
  180. Forth_ReturnType r = {0, FR_OK};
  181. FilenameType TempFilename;
  182. if (!ForthBufferToCString(TempFilename, sizeof(TempFilename), filename, length)) {
  183. r.rc = FR_INVALID_NAME;
  184. return r;
  185. }
  186. r.rc = f_unlink(TempFilename);
  187. return r;
  188. }
  189. Forth_ReturnType FileSystem_create(const Forth_PointerType filename, Forth_CellType length, Forth_CellType fam)
  190. {
  191. return FileSystem_open(filename, length, fam | FA_CREATE_NEW | FA_CREATE_ALWAYS);
  192. }
  193. Forth_ReturnType FileSystem_close(Forth_CellType handle)
  194. {
  195. Forth_ReturnType r = {0, FR_OK};
  196. FileType *file = ValidateFileHandle(&r, handle);
  197. if (NULL != file) {
  198. r.rc = f_close(&file->file);
  199. file->IsOpen = false;
  200. }
  201. return r;
  202. }
  203. Forth_ReturnType FileSystem_read(Forth_CellType handle, void *buffer, Forth_CellType length)
  204. {
  205. Forth_ReturnType r = {0, FR_OK};
  206. FileType *file = ValidateFileHandle(&r, handle);
  207. if (NULL != file) {
  208. //UINT count = 0;
  209. if (0 == file->ReadRemaining) {
  210. r.rc = f_read(&file->file, file->ReadBuffer, sizeof(file->ReadBuffer), &file->ReadRemaining);
  211. file->ReadOffset = 0;
  212. }
  213. if (length <= file->ReadRemaining) {
  214. r.result = length;
  215. memcpy(buffer, &file->ReadBuffer[file->ReadOffset], length);
  216. file->ReadRemaining -= length;
  217. file->ReadOffset += length;
  218. } else {
  219. r.result = file->ReadRemaining;
  220. memcpy(buffer, &file->ReadBuffer[file->ReadOffset], file->ReadRemaining);
  221. file->ReadRemaining = 0;
  222. file->ReadOffset = 0;
  223. }
  224. //r.rc = f_read(&file->file, buffer, length, &count);
  225. //r.result = count;
  226. }
  227. return r;
  228. }
  229. Forth_ReturnType FileSystem_write(Forth_CellType handle, void *buffer, Forth_CellType length)
  230. {
  231. Forth_ReturnType r = {0, FR_OK};
  232. FileType *file = ValidateFileHandle(&r, handle);
  233. if (NULL != file) {
  234. UINT count = 0;
  235. r.rc = f_write(&file->file, buffer, length, &count);
  236. r.result = count;
  237. }
  238. return r;
  239. }
  240. Forth_ReturnType FileSystem_sync(Forth_CellType handle)
  241. {
  242. Forth_ReturnType r = {0, FR_OK};
  243. FileType *file = ValidateFileHandle(&r, handle);
  244. if (NULL != file) {
  245. r.rc = f_sync(&file->file);
  246. }
  247. return r;
  248. }
  249. Forth_ReturnType FileSystem_lseek(Forth_CellType handle, Forth_CellType pos)
  250. {
  251. Forth_ReturnType r = {0, FR_OK};
  252. FileType *file = ValidateFileHandle(&r, handle);
  253. if (NULL != file) {
  254. r.rc = f_lseek(&file->file, pos);
  255. }
  256. return r;
  257. }
  258. Forth_ReturnType FileSystem_ltell(Forth_CellType handle)
  259. {
  260. Forth_ReturnType r = {0, FR_OK};
  261. FileType *file = ValidateFileHandle(&r, handle);
  262. if (NULL != file) {
  263. // not available :- just error
  264. //r.rc = f_ltell(&file->file, pos);
  265. r.rc = FR_DENIED;
  266. }
  267. return r;
  268. }
  269. Forth_ReturnType FileSystem_lsize(Forth_CellType handle)
  270. {
  271. Forth_ReturnType r = {0, FR_OK};
  272. FileType *file = ValidateFileHandle(&r, handle);
  273. if (NULL != file) {
  274. FILINFO stat;
  275. r.rc = f_stat(file->filename, &stat);
  276. r.result = stat.fsize;
  277. }
  278. return r;
  279. }
  280. Forth_CellType FileSystem_ReadOnly(void)
  281. {
  282. return FA_READ;
  283. }
  284. Forth_CellType FileSystem_ReadWrite(void)
  285. {
  286. return FA_READ | FA_WRITE;
  287. }
  288. Forth_CellType FileSystem_WriteOnly(void)
  289. {
  290. return FA_WRITE;
  291. }
  292. Forth_CellType FileSystem_bin(Forth_CellType fam)
  293. {
  294. return fam;
  295. }
  296. Forth_ReturnType FileSystem_CreateDirectory(const Forth_PointerType directoryname, Forth_CellType length)
  297. {
  298. Forth_ReturnType r = {0, FR_OK};
  299. FilenameType DirectoryNameBuffer;
  300. if (!ForthBufferToCString(DirectoryNameBuffer, sizeof(DirectoryNameBuffer),
  301. directoryname, length)) {
  302. r.rc = FR_INVALID_NAME;
  303. return r;
  304. }
  305. r.rc = f_mkdir(DirectoryNameBuffer);
  306. return r;
  307. }
  308. Forth_ReturnType FileSystem_OpenDirectory(const Forth_PointerType directoryname, Forth_CellType length)
  309. {
  310. Forth_ReturnType r = {0, FR_OK};
  311. size_t i = 0;
  312. for (i = 0; i < SizeOfArray(DirectoryControlBlock); i++) {
  313. if (!DirectoryControlBlock[i].IsOpen) {
  314. if (!ForthBufferToCString(DirectoryControlBlock[i].directoryname,
  315. sizeof(DirectoryControlBlock[i].directoryname),
  316. directoryname, length)) {
  317. r.rc = FR_INVALID_NAME;
  318. return r;
  319. }
  320. r.rc = f_opendir(&DirectoryControlBlock[i].directory, DirectoryControlBlock[i].directoryname);
  321. if (FR_OK == r.rc) {
  322. DirectoryControlBlock[i].IsOpen = true;
  323. r.result = i + 1; // directory handle starts at one(1), not zero(0)
  324. return r;
  325. }
  326. break;
  327. }
  328. }
  329. r.rc = FR_DENIED;
  330. return r;
  331. }
  332. Forth_ReturnType FileSystem_CloseDirectory(Forth_CellType handle)
  333. {
  334. Forth_ReturnType r = {0, FR_OK};
  335. DirectoryType *directory = ValidateDirectoryHandle(&r, handle);
  336. if (NULL != directory) {
  337. //r.rc = f_dirclose(&directory->directory);
  338. directory->IsOpen = false;
  339. }
  340. return r;
  341. }
  342. Forth_ReturnType FileSystem_ReadDirectory(Forth_CellType handle, void *buffer, Forth_CellType length)
  343. {
  344. Forth_ReturnType r = {0, FR_OK};
  345. DirectoryType *directory = ValidateDirectoryHandle(&r, handle);
  346. if (NULL != directory) {
  347. FILINFO info;
  348. r.rc = f_readdir(&directory->directory, &info);
  349. if (FR_OK == r.rc){
  350. size_t count = strlen(info.fname);
  351. if (count > length) {
  352. count = length;
  353. }
  354. if (0 != count) {
  355. memcpy(buffer, info.fname, count);
  356. }
  357. r.result = count;
  358. }
  359. }
  360. return r;
  361. }
  362. Forth_ReturnType FileSystem_AbsoluteRead(Forth_CellType sector, void *buffer, Forth_CellType count)
  363. {
  364. Forth_ReturnType r = {0, FR_OK};
  365. r.rc = disk_read(0, buffer, sector, count);
  366. return r;
  367. }
  368. Forth_ReturnType FileSystem_AbsoluteWrite(Forth_CellType sector, const void *buffer, Forth_CellType count)
  369. {
  370. Forth_ReturnType r = {0, FR_OK};
  371. r.rc = disk_write(0, buffer, sector, count);
  372. return r;
  373. }
  374. // 31-25: Year(0-127 +1980)
  375. // 24-21: Month(1-12)
  376. // 20-16: Day(1-31)
  377. // 15-11: Hour(0-23)
  378. // 10- 5: Minute(0-59)
  379. // 4- 0: Second(0-29 *2)
  380. #define YEAR (2009 - 1980)
  381. #define MONTH 3
  382. #define DAY 30
  383. #define HOUR 17
  384. #define MINUTE 58
  385. #define SECOND 41
  386. DWORD get_fattime (void)
  387. {
  388. return
  389. (YEAR << 25) |
  390. (MONTH << 21) |
  391. (DAY << 16) |
  392. (HOUR << 11) |
  393. (MINUTE << 5) |
  394. (SECOND << 0);
  395. }