Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

303 Zeilen
7.7KB

  1. /* FatLib Library
  2. * Copyright (C) 2012 by William Greiman
  3. *
  4. * This file is part of the FatLib Library
  5. *
  6. * This Library is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This Library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with the FatLib Library. If not, see
  18. * <http://www.gnu.org/licenses/>.
  19. */
  20. #ifndef DOXYGEN_SHOULD_SKIP_THIS
  21. #include "FatFile.h"
  22. bool FatFile::findSfn(uint8_t sfn[11], uint16_t* index) {
  23. uint16_t free = 0XFFFF;
  24. uint16_t idx;
  25. dir_t* dir;
  26. if (!isDir()) {
  27. DBG_FAIL_MACRO;
  28. goto fail;
  29. }
  30. rewind();
  31. while (m_curPosition < m_fileSize) {
  32. idx = m_curPosition/32;
  33. if ((0XF & idx) == 0) {
  34. dir = readDirCache();
  35. if (!dir) {
  36. DBG_FAIL_MACRO;
  37. goto fail;
  38. }
  39. } else {
  40. m_curPosition += 32;
  41. dir++;
  42. }
  43. // done if last entry
  44. if (dir->name[0] == DIR_NAME_FREE || dir->name[0] == DIR_NAME_DELETED) {
  45. if (free == 0XFFFF) free = idx;
  46. if (dir->name[0] == DIR_NAME_FREE) goto fail;
  47. } else if (DIR_IS_FILE_OR_SUBDIR(dir)) {
  48. if (!memcmp(sfn, dir->name, 11)) {
  49. *index = idx;
  50. return true;
  51. }
  52. }
  53. }
  54. fail:
  55. *index = free;
  56. return false;
  57. }
  58. //------------------------------------------------------------------------------
  59. bool FatFile::createLfn(FatFile* dirFile,
  60. uint16_t bgnIndex, char* name, uint8_t oflag) {
  61. return false;
  62. }
  63. //------------------------------------------------------------------------------
  64. bool FatFile::findLfn(const char* name,
  65. uint16_t *bgnIndex, uint16_t* endIndex) {
  66. bool fill;
  67. bool haveLong = false;
  68. uint8_t ndir;
  69. uint8_t test;
  70. uint16_t lfnBgn;
  71. uint16_t curIndex = 0XFFFF;
  72. uint16_t freeIndex = 0XFFFF;
  73. uint8_t freeCount = 0;
  74. uint8_t freeNeed;
  75. dir_t* dir;
  76. size_t len;
  77. bool is83;
  78. bool foundFree = false;
  79. const char* ptr;
  80. uint8_t name83[11];
  81. if (!isDir()) {
  82. DBG_FAIL_MACRO;
  83. goto fail;
  84. }
  85. is83 = make83Name(name, name83, &ptr);
  86. for (len = 0; name[len] !=0 && name[len] != '/'; len++) {}
  87. // Assume LFN.
  88. freeNeed = (len + 12)/13 + 1;
  89. rewind();
  90. while (1) {
  91. curIndex = m_curPosition/32;
  92. if (m_curPosition == m_fileSize) {
  93. DBG_FAIL_MACRO;
  94. goto fail;
  95. }
  96. // read entry into cache
  97. dir = readDirCache();
  98. if (!dir) {
  99. DBG_FAIL_MACRO;
  100. goto fail;
  101. }
  102. #if 1
  103. if (dir->name[0] == DIR_NAME_DELETED) {
  104. if (!foundFree) {
  105. if (freeIndex == 0XFFFF) {
  106. freeIndex = curIndex;
  107. freeCount = 0;
  108. }
  109. if (++freeCount == freeNeed) {
  110. foundFree = true;
  111. }
  112. }
  113. continue;
  114. } else {
  115. if (!foundFree) freeIndex = 0XFFFF;
  116. }
  117. #endif
  118. if (dir->name[0] == DIR_NAME_FREE) {
  119. DBG_FAIL_MACRO;
  120. goto fail;
  121. }
  122. // skip empty slot or '.' or '..'
  123. if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') {
  124. haveLong = false;
  125. continue;
  126. }
  127. if (DIR_IS_LONG_NAME(dir)) {
  128. ldir_t *ldir = reinterpret_cast<ldir_t*>(dir);
  129. if (!haveLong) {
  130. if ((ldir->ord & LDIR_ORD_LAST_LONG_ENTRY) == 0) continue;
  131. ndir = ldir->ord & ~LDIR_ORD_LAST_LONG_ENTRY;
  132. if (ndir < 1 || ndir > 20) continue;
  133. test = ldir->chksum;
  134. haveLong = true;
  135. lfnBgn = curIndex;
  136. fill = true;
  137. } else if (ldir->ord != --ndir || test != ldir->chksum) {
  138. haveLong = false;
  139. continue;
  140. }
  141. size_t nOff = 13*(ndir -1);
  142. for (int i = 12; i >= 0; i--) {
  143. uint16_t u = lfnChar(ldir, i);
  144. if (fill) {
  145. if (u == 0 || u == 0XFFFF) {
  146. continue;
  147. }
  148. if (len != (nOff + i +1)) {
  149. haveLong = false;
  150. break;
  151. }
  152. fill = false;
  153. }
  154. if (u > 255 || toupper(u) != toupper(name[nOff + i])) {
  155. haveLong = false;
  156. break;
  157. }
  158. }
  159. } else if (DIR_IS_FILE_OR_SUBDIR(dir)) {
  160. if (haveLong) {
  161. uint8_t sum = 0;
  162. for (uint8_t i = 0; i < 11; i++) {
  163. sum = (((sum & 1) << 7) | ((sum & 0xfe) >> 1)) + dir->name[i];
  164. }
  165. if (sum != test || ndir != 1) {
  166. haveLong = false;
  167. }
  168. }
  169. if (haveLong) goto done;
  170. if (is83 && !memcmp(dir->name, name83, sizeof(name83))) {
  171. goto done;
  172. }
  173. } else {
  174. haveLong = false;
  175. }
  176. }
  177. done:
  178. *bgnIndex = haveLong ? lfnBgn : curIndex;
  179. *endIndex = curIndex;
  180. return true;
  181. fail:
  182. *bgnIndex = foundFree ? freeIndex : curIndex;
  183. return false;
  184. }
  185. //------------------------------------------------------------------------------
  186. int FatFile::openNextLFN(FatFile* dirFile,
  187. char* name, size_t size, uint8_t oflag) {
  188. bool fill;
  189. bool haveLong = false;
  190. size_t lfnIn;
  191. uint8_t ndir;
  192. uint8_t test;
  193. dir_t* dir;
  194. uint16_t index;
  195. int rtn;
  196. // Check for valid directory and file is not open.
  197. if (!dirFile->isDir() || isOpen() || size < 13) {
  198. DBG_FAIL_MACRO;
  199. goto fail;
  200. }
  201. while (1) {
  202. // Check for EOF.
  203. if (dirFile->curPosition() == dirFile->fileSize()) goto done;
  204. index = dirFile->curPosition()/32;
  205. // read entry into cache
  206. dir = dirFile->readDirCache();
  207. if (!dir) {
  208. DBG_FAIL_MACRO;
  209. goto fail;
  210. }
  211. // done if last entry
  212. if (dir->name[0] == DIR_NAME_FREE) {
  213. DBG_FAIL_MACRO;
  214. return 0;
  215. }
  216. // skip empty slot or '.' or '..'
  217. if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') {
  218. haveLong = false;
  219. continue;
  220. }
  221. if (DIR_IS_LONG_NAME(dir)) {
  222. ldir_t *ldir = reinterpret_cast<ldir_t*>(dir);
  223. if (!haveLong) {
  224. if ((ldir->ord & LDIR_ORD_LAST_LONG_ENTRY) == 0) continue;
  225. ndir = ldir->ord & ~LDIR_ORD_LAST_LONG_ENTRY;
  226. if (ndir < 1 || ndir > 20) continue;
  227. test = ldir->chksum;
  228. haveLong = true;
  229. rtn = 0;
  230. fill = true;
  231. lfnIn = 13*ndir;
  232. } else if (ldir->ord != --ndir || test != ldir->chksum) {
  233. haveLong = false;
  234. continue;
  235. }
  236. for (int i = 12; i >= 0; i--) {
  237. uint16_t u = lfnChar(ldir, i);
  238. if (fill) {
  239. if (rtn == 0 && u != 0 && u != 0XFFFF) rtn = lfnIn;
  240. if (u == 0 || u == 0XFFFF || lfnIn >= size) {
  241. lfnIn--;
  242. continue;
  243. }
  244. name[lfnIn] = 0;
  245. fill = false;
  246. }
  247. if (lfnIn == 0 || u > 255) {
  248. haveLong = false;
  249. break;
  250. }
  251. name[--lfnIn] = u;
  252. }
  253. } else if (DIR_IS_FILE_OR_SUBDIR(dir)) {
  254. if (haveLong) {
  255. uint8_t sum = 0;
  256. for (uint8_t i = 0; i < 11; i++) {
  257. sum = (((sum & 1) << 7) | ((sum & 0xfe) >> 1)) + dir->name[i];
  258. }
  259. if (sum != test || ndir != 1) {
  260. haveLong = false;
  261. }
  262. }
  263. if (!haveLong) {
  264. rtn = dirName(dir, name);
  265. if (dir->reservedNT) {
  266. uint8_t lowerTest = 0X08;
  267. for (char *ptr = name; *ptr; ptr++) {
  268. if (*ptr == '.') {
  269. lowerTest = 0X10;
  270. continue;
  271. }
  272. if (dir->reservedNT & lowerTest) {
  273. *ptr = tolower(*ptr);
  274. }
  275. }
  276. }
  277. }
  278. if (!openCachedEntry(dirFile, index, oflag)) {
  279. DBG_FAIL_MACRO;
  280. goto fail;
  281. }
  282. return rtn;
  283. } else {
  284. haveLong = false;
  285. }
  286. }
  287. done:
  288. return 0;
  289. fail:
  290. return -1;
  291. }
  292. #endif // DOXYGEN_SHOULD_SKIP_THIS