FatName.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /**
  2. * Copyright (c) 2011-2022 Bill Greiman
  3. * This file is part of the SdFat library for SD memory cards.
  4. *
  5. * MIT License
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a
  8. * copy of this software and associated documentation files (the "Software"),
  9. * to deal in the Software without restriction, including without limitation
  10. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. * and/or sell copies of the Software, and to permit persons to whom the
  12. * Software is furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included
  15. * in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. * DEALINGS IN THE SOFTWARE.
  24. */
  25. #define DBG_FILE "FatName.cpp"
  26. #include "../common/DebugMacros.h"
  27. #include "../common/FsUtf.h"
  28. #include "FatLib.h"
  29. //------------------------------------------------------------------------------
  30. uint16_t FatFile::getLfnChar(DirLfn_t* ldir, uint8_t i) {
  31. if (i < 5) {
  32. return getLe16(ldir->unicode1 + 2*i);
  33. } else if (i < 11) {
  34. return getLe16(ldir->unicode2 + 2*i - 10);
  35. } else if (i < 13) {
  36. return getLe16(ldir->unicode3 + 2*i - 22);
  37. }
  38. DBG_HALT_IF(i >= 13);
  39. return 0;
  40. }
  41. //------------------------------------------------------------------------------
  42. size_t FatFile::getName(char* name, size_t size) {
  43. #if !USE_LONG_FILE_NAMES
  44. return getSFN(name, size);
  45. #elif USE_UTF8_LONG_NAMES
  46. return getName8(name, size);
  47. #else
  48. return getName7(name, size);
  49. #endif // !USE_LONG_FILE_NAMES
  50. }
  51. //------------------------------------------------------------------------------
  52. size_t FatFile::getName7(char* name, size_t size) {
  53. FatFile dir;
  54. DirLfn_t* ldir;
  55. size_t n = 0;
  56. if (!isOpen()) {
  57. DBG_FAIL_MACRO;
  58. goto fail;
  59. }
  60. if (!isLFN()) {
  61. return getSFN(name, size);
  62. }
  63. if (!dir.openCluster(this)) {
  64. DBG_FAIL_MACRO;
  65. goto fail;
  66. }
  67. for (uint8_t order = 1; order <= m_lfnOrd; order++) {
  68. ldir = reinterpret_cast<DirLfn_t*>(dir.cacheDir(m_dirIndex - order));
  69. if (!ldir) {
  70. DBG_FAIL_MACRO;
  71. goto fail;
  72. }
  73. if (ldir->attributes != FAT_ATTRIB_LONG_NAME ||
  74. order != (ldir->order & 0X1F)) {
  75. DBG_FAIL_MACRO;
  76. goto fail;
  77. }
  78. for (uint8_t i = 0; i < 13; i++) {
  79. uint16_t c = getLfnChar(ldir, i);
  80. if (c == 0) {
  81. goto done;
  82. }
  83. if ((n + 1) >= size) {
  84. DBG_FAIL_MACRO;
  85. goto fail;
  86. }
  87. name[n++] = c >= 0X7F ? '?' : c;
  88. }
  89. }
  90. done:
  91. name[n] = 0;
  92. return n;
  93. fail:
  94. name[0] = '\0';
  95. return 0;
  96. }
  97. //------------------------------------------------------------------------------
  98. size_t FatFile::getName8(char* name, size_t size) {
  99. char* end = name + size;
  100. char* str = name;
  101. char* ptr;
  102. FatFile dir;
  103. DirLfn_t* ldir;
  104. uint16_t hs = 0;
  105. uint32_t cp;
  106. if (!isOpen()) {
  107. DBG_FAIL_MACRO;
  108. goto fail;
  109. }
  110. if (!isLFN()) {
  111. return getSFN(name, size);
  112. }
  113. if (!dir.openCluster(this)) {
  114. DBG_FAIL_MACRO;
  115. goto fail;
  116. }
  117. for (uint8_t order = 1; order <= m_lfnOrd; order++) {
  118. ldir = reinterpret_cast<DirLfn_t*>(dir.cacheDir(m_dirIndex - order));
  119. if (!ldir) {
  120. DBG_FAIL_MACRO;
  121. goto fail;
  122. }
  123. if (ldir->attributes != FAT_ATTRIB_LONG_NAME ||
  124. order != (ldir->order & 0X1F)) {
  125. DBG_FAIL_MACRO;
  126. goto fail;
  127. }
  128. for (uint8_t i = 0; i < 13; i++) {
  129. uint16_t c = getLfnChar(ldir, i);
  130. if (hs) {
  131. if (!FsUtf::isLowSurrogate(c)) {
  132. DBG_FAIL_MACRO;
  133. goto fail;
  134. }
  135. cp = FsUtf::u16ToCp(hs, c);
  136. hs = 0;
  137. } else if (!FsUtf::isSurrogate(c)) {
  138. if (c == 0) {
  139. goto done;
  140. }
  141. cp = c;
  142. } else if (FsUtf::isHighSurrogate(c)) {
  143. hs = c;
  144. continue;
  145. } else {
  146. DBG_FAIL_MACRO;
  147. goto fail;
  148. }
  149. // Save space for zero byte.
  150. ptr = FsUtf::cpToMb(cp, str, end - 1);
  151. if (!ptr) {
  152. DBG_FAIL_MACRO;
  153. goto fail;
  154. }
  155. str = ptr;
  156. }
  157. }
  158. done:
  159. *str = '\0';
  160. return str - name;
  161. fail:
  162. *name = 0;
  163. return 0;
  164. }
  165. //------------------------------------------------------------------------------
  166. size_t FatFile::getSFN(char* name, size_t size) {
  167. char c;
  168. uint8_t j = 0;
  169. uint8_t lcBit = FAT_CASE_LC_BASE;
  170. uint8_t* ptr;
  171. DirFat_t* dir;
  172. if (!isOpen()) {
  173. DBG_FAIL_MACRO;
  174. goto fail;
  175. }
  176. if (isRoot()) {
  177. if (size < 2) {
  178. DBG_FAIL_MACRO;
  179. goto fail;
  180. }
  181. name[0] = '/';
  182. name[1] = '\0';
  183. return 1;
  184. }
  185. // cache entry
  186. dir = cacheDirEntry(FsCache::CACHE_FOR_READ);
  187. if (!dir) {
  188. DBG_FAIL_MACRO;
  189. goto fail;
  190. }
  191. ptr = dir->name;
  192. // format name
  193. for (uint8_t i = 0; i < 12; i++) {
  194. if (i == 8) {
  195. if (*ptr == ' ') {
  196. break;
  197. }
  198. lcBit = FAT_CASE_LC_EXT;
  199. c = '.';
  200. } else {
  201. c = *ptr++;
  202. if ('A' <= c && c <= 'Z' && (lcBit & dir->caseFlags)) {
  203. c += 'a' - 'A';
  204. }
  205. if (c == ' ') {
  206. continue;
  207. }
  208. }
  209. if ((j + 1u) >= size) {
  210. DBG_FAIL_MACRO;
  211. goto fail;
  212. }
  213. name[j++] = c;
  214. }
  215. name[j] = '\0';
  216. return j;
  217. fail:
  218. name[0] = '\0';
  219. return 0;
  220. }
  221. //------------------------------------------------------------------------------
  222. size_t FatFile::printName(print_t* pr) {
  223. #if !USE_LONG_FILE_NAMES
  224. return printSFN(pr);
  225. #elif USE_UTF8_LONG_NAMES
  226. return printName8(pr);
  227. # else // USE_LONG_FILE_NAMES
  228. return printName7(pr);
  229. #endif // !USE_LONG_FILE_NAMES
  230. }
  231. //------------------------------------------------------------------------------
  232. size_t FatFile::printName7(print_t* pr) {
  233. FatFile dir;
  234. DirLfn_t* ldir;
  235. size_t n = 0;
  236. uint8_t buf[13];
  237. uint8_t i;
  238. if (!isOpen()) {
  239. DBG_FAIL_MACRO;
  240. goto fail;
  241. }
  242. if (!isLFN()) {
  243. return printSFN(pr);
  244. }
  245. if (!dir.openCluster(this)) {
  246. DBG_FAIL_MACRO;
  247. goto fail;
  248. }
  249. for (uint8_t order = 1; order <= m_lfnOrd; order++) {
  250. ldir = reinterpret_cast<DirLfn_t*>(dir.cacheDir(m_dirIndex - order));
  251. if (!ldir) {
  252. DBG_FAIL_MACRO;
  253. goto fail;
  254. }
  255. if (ldir->attributes != FAT_ATTRIB_LONG_NAME ||
  256. order != (ldir->order & 0X1F)) {
  257. DBG_FAIL_MACRO;
  258. goto fail;
  259. }
  260. for (i = 0; i < 13; i++) {
  261. uint16_t u = getLfnChar(ldir, i);
  262. if (u == 0) {
  263. // End of name.
  264. break;
  265. }
  266. buf[i] = u < 0X7F ? u : '?';
  267. n++;
  268. }
  269. pr->write(buf, i);
  270. }
  271. return n;
  272. fail:
  273. return 0;
  274. }
  275. //------------------------------------------------------------------------------
  276. size_t FatFile::printName8(print_t *pr) {
  277. FatFile dir;
  278. DirLfn_t* ldir;
  279. uint16_t hs = 0;
  280. uint32_t cp;
  281. size_t n = 0;
  282. char buf[5];
  283. char* end = buf + sizeof(buf);
  284. if (!isOpen()) {
  285. DBG_FAIL_MACRO;
  286. goto fail;
  287. }
  288. if (!isLFN()) {
  289. return printSFN(pr);
  290. }
  291. if (!dir.openCluster(this)) {
  292. DBG_FAIL_MACRO;
  293. goto fail;
  294. }
  295. for (uint8_t order = 1; order <= m_lfnOrd; order++) {
  296. ldir = reinterpret_cast<DirLfn_t*>(dir.cacheDir(m_dirIndex - order));
  297. if (!ldir) {
  298. DBG_FAIL_MACRO;
  299. goto fail;
  300. }
  301. if (ldir->attributes != FAT_ATTRIB_LONG_NAME ||
  302. order != (ldir->order & 0X1F)) {
  303. DBG_FAIL_MACRO;
  304. goto fail;
  305. }
  306. for (uint8_t i = 0; i < 13; i++) {
  307. uint16_t c = getLfnChar(ldir, i);;
  308. if (hs) {
  309. if (!FsUtf::isLowSurrogate(c)) {
  310. DBG_FAIL_MACRO;
  311. goto fail;
  312. }
  313. cp = FsUtf::u16ToCp(hs, c);
  314. hs = 0;
  315. } else if (!FsUtf::isSurrogate(c)) {
  316. if (c == 0) {
  317. break;
  318. }
  319. cp = c;
  320. } else if (FsUtf::isHighSurrogate(c)) {
  321. hs = c;
  322. continue;
  323. } else {
  324. DBG_FAIL_MACRO;
  325. goto fail;
  326. }
  327. char* str = FsUtf::cpToMb(cp, buf, end);
  328. if (!str) {
  329. DBG_FAIL_MACRO;
  330. goto fail;
  331. }
  332. n += pr->write(buf, str - buf);
  333. }
  334. }
  335. return n;
  336. fail:
  337. return 0;
  338. }
  339. //------------------------------------------------------------------------------
  340. size_t FatFile::printSFN(print_t* pr) {
  341. char name[13];
  342. if (!getSFN(name, sizeof(name))) {
  343. DBG_FAIL_MACRO;
  344. goto fail;
  345. }
  346. return pr->write(name);
  347. fail:
  348. return 0;
  349. }