lfs.c 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696
  1. /*
  2. * The little filesystem
  3. *
  4. * Copyright (c) 2017 Christopher Haster
  5. * Distributed under the MIT license
  6. */
  7. #include "lfs.h"
  8. #include "lfs_util.h"
  9. #include <string.h>
  10. #include <stdbool.h>
  11. #include <stdlib.h>
  12. /// Block device operations ///
  13. static int lfs_bd_flush(lfs_t *lfs) {
  14. if (lfs->pcache.off != -1) {
  15. int err = lfs->cfg->prog(lfs->cfg, lfs->pcache.block,
  16. lfs->pcache.off, lfs->cfg->prog_size,
  17. lfs->pcache.buffer);
  18. if (err) {
  19. return err;
  20. }
  21. lfs->pcache.off = -1;
  22. }
  23. return 0;
  24. }
  25. static int lfs_bd_read(lfs_t *lfs, lfs_block_t block,
  26. lfs_off_t off, lfs_size_t size, void *buffer) {
  27. uint8_t *data = buffer;
  28. // flush overlapping programs
  29. while (size > 0) {
  30. if (block == lfs->pcache.block && off >= lfs->pcache.off &&
  31. off < lfs->pcache.off + lfs->cfg->prog_size) {
  32. // is already in cache?
  33. lfs_size_t diff = lfs_min(size,
  34. lfs->cfg->prog_size - (off-lfs->pcache.off));
  35. memcpy(data, &lfs->pcache.buffer[off-lfs->pcache.off], diff);
  36. data += diff;
  37. off += diff;
  38. size -= diff;
  39. continue;
  40. } else if (block == lfs->rcache.block && off >= lfs->rcache.off &&
  41. off < lfs->rcache.off + lfs->cfg->read_size) {
  42. // is already in cache?
  43. lfs_size_t diff = lfs_min(size,
  44. lfs->cfg->read_size - (off-lfs->rcache.off));
  45. memcpy(data, &lfs->rcache.buffer[off-lfs->rcache.off], diff);
  46. data += diff;
  47. off += diff;
  48. size -= diff;
  49. continue;
  50. }
  51. // write out pending programs
  52. int err = lfs_bd_flush(lfs);
  53. if (err) {
  54. return err;
  55. }
  56. if (off % lfs->cfg->read_size == 0 &&
  57. size >= lfs->cfg->read_size) {
  58. // bypass cache?
  59. lfs_size_t diff = size - (size % lfs->cfg->read_size);
  60. int err = lfs->cfg->read(lfs->cfg, block, off, diff, data);
  61. if (err) {
  62. return err;
  63. }
  64. data += diff;
  65. off += diff;
  66. size -= diff;
  67. continue;
  68. }
  69. // load to cache, first condition can no longer fail
  70. lfs->rcache.block = block;
  71. lfs->rcache.off = off - (off % lfs->cfg->read_size);
  72. err = lfs->cfg->read(lfs->cfg, lfs->rcache.block,
  73. lfs->rcache.off, lfs->cfg->read_size,
  74. lfs->rcache.buffer);
  75. if (err) {
  76. return err;
  77. }
  78. }
  79. return 0;
  80. }
  81. static int lfs_bd_prog(lfs_t *lfs, lfs_block_t block,
  82. lfs_off_t off, lfs_size_t size, const void *buffer) {
  83. const uint8_t *data = buffer;
  84. if (block == lfs->rcache.block) {
  85. // invalidate read cache
  86. lfs->rcache.off = -1;
  87. }
  88. while (size > 0) {
  89. if (block == lfs->pcache.block && off >= lfs->pcache.off &&
  90. off < lfs->pcache.off + lfs->cfg->prog_size) {
  91. // is already in cache?
  92. lfs_size_t diff = lfs_min(size,
  93. lfs->cfg->prog_size - (off-lfs->pcache.off));
  94. memcpy(&lfs->pcache.buffer[off-lfs->pcache.off], data, diff);
  95. data += diff;
  96. off += diff;
  97. size -= diff;
  98. continue;
  99. }
  100. // write out pending programs
  101. int err = lfs_bd_flush(lfs);
  102. if (err) {
  103. return err;
  104. }
  105. if (off % lfs->cfg->prog_size == 0 &&
  106. size >= lfs->cfg->prog_size) {
  107. // bypass cache?
  108. lfs_size_t diff = size - (size % lfs->cfg->prog_size);
  109. int err = lfs->cfg->prog(lfs->cfg, block, off, diff, data);
  110. if (err) {
  111. return err;
  112. }
  113. data += diff;
  114. off += diff;
  115. size -= diff;
  116. continue;
  117. }
  118. // prepare cache, first condition can no longer fail
  119. lfs->pcache.block = block;
  120. lfs->pcache.off = off - (off % lfs->cfg->prog_size);
  121. }
  122. return 0;
  123. }
  124. static int lfs_bd_erase(lfs_t *lfs, lfs_block_t block) {
  125. return lfs->cfg->erase(lfs->cfg, block);
  126. }
  127. static int lfs_bd_sync(lfs_t *lfs) {
  128. int err = lfs_bd_flush(lfs);
  129. if (err) {
  130. return err;
  131. }
  132. return lfs->cfg->sync(lfs->cfg);
  133. }
  134. static int lfs_bd_cmp(lfs_t *lfs, lfs_block_t block,
  135. lfs_off_t off, lfs_size_t size, const void *buffer) {
  136. const uint8_t *data = buffer;
  137. for (lfs_off_t i = 0; i < size; i++) {
  138. uint8_t c;
  139. int err = lfs_bd_read(lfs, block, off+i, 1, &c);
  140. if (err) {
  141. return err;
  142. }
  143. if (c != data[i]) {
  144. return false;
  145. }
  146. }
  147. return true;
  148. }
  149. /// Block allocator ///
  150. static int lfs_alloc_lookahead(void *p, lfs_block_t block) {
  151. lfs_t *lfs = p;
  152. lfs_block_t off = (block - lfs->free.start) % lfs->cfg->block_count;
  153. if (off < lfs->cfg->lookahead) {
  154. lfs->free.lookahead[off / 32] |= 1U << (off % 32);
  155. }
  156. return 0;
  157. }
  158. static int lfs_alloc_scan(lfs_t *lfs, lfs_block_t *block) {
  159. lfs_block_t end = lfs->free.start + lfs->cfg->block_count;
  160. while (true) {
  161. while (lfs->free.off < lfs->cfg->lookahead) {
  162. lfs_block_t off = lfs->free.off;
  163. lfs->free.off += 1;
  164. if (!(lfs->free.lookahead[off / 32] & (1U << (off % 32)))) {
  165. // found a free block
  166. *block = (lfs->free.start + off) % lfs->cfg->block_count;
  167. return 0;
  168. }
  169. }
  170. // could not find block
  171. lfs->free.start += lfs->cfg->lookahead;
  172. lfs->free.off = 0;
  173. if (lfs_scmp(lfs->free.start, end) > 0) {
  174. return LFS_ERROR_NO_SPACE;
  175. }
  176. // find mask of free blocks from tree
  177. memset(lfs->free.lookahead, 0, lfs->cfg->lookahead/8);
  178. int err = lfs_traverse(lfs, lfs_alloc_lookahead, lfs);
  179. if (err) {
  180. return err;
  181. }
  182. }
  183. }
  184. static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
  185. // try to scan for free block
  186. int err = lfs_alloc_scan(lfs, block);
  187. if (err != LFS_ERROR_NO_SPACE) {
  188. return err;
  189. }
  190. // still can't allocate a block? check for orphans
  191. err = lfs_deorphan(lfs);
  192. if (err) {
  193. return err;
  194. }
  195. // scan again or die trying
  196. return lfs_alloc_scan(lfs, block);
  197. }
  198. /// Metadata pair and directory operations ///
  199. static inline void lfs_pairswap(lfs_block_t pair[2]) {
  200. lfs_block_t t = pair[0];
  201. pair[0] = pair[1];
  202. pair[1] = t;
  203. }
  204. static inline bool lfs_pairisnull(const lfs_block_t pair[2]) {
  205. return !pair[0] || !pair[1];
  206. }
  207. static inline int lfs_paircmp(
  208. const lfs_block_t paira[2],
  209. const lfs_block_t pairb[2]) {
  210. return !((paira[0] == pairb[0] && paira[1] == pairb[1]) ||
  211. (paira[0] == pairb[1] && paira[1] == pairb[0]));
  212. }
  213. static int lfs_dir_alloc(lfs_t *lfs, lfs_dir_t *dir) {
  214. // Allocate pair of dir blocks
  215. for (int i = 0; i < 2; i++) {
  216. int err = lfs_alloc(lfs, &dir->pair[i]);
  217. if (err) {
  218. return err;
  219. }
  220. }
  221. // Rather than clobbering one of the blocks we just pretend
  222. // the revision may be valid
  223. int err = lfs_bd_read(lfs, dir->pair[0], 0, 4, &dir->d.rev);
  224. if (err) {
  225. return err;
  226. }
  227. // Set defaults
  228. dir->d.rev += 1;
  229. dir->d.size = sizeof(dir->d);
  230. dir->d.tail[0] = 0;
  231. dir->d.tail[1] = 0;
  232. dir->off = sizeof(dir->d);
  233. // Don't write out yet, let caller take care of that
  234. return 0;
  235. }
  236. static int lfs_dir_fetch(lfs_t *lfs,
  237. lfs_dir_t *dir, const lfs_block_t pair[2]) {
  238. // copy out pair, otherwise may be aliasing dir
  239. const lfs_block_t tpair[2] = {pair[0], pair[1]};
  240. bool valid = false;
  241. // check both blocks for the most recent revision
  242. for (int i = 0; i < 2; i++) {
  243. struct lfs_disk_dir test;
  244. int err = lfs_bd_read(lfs, tpair[i], 0, sizeof(test), &test);
  245. if (err) {
  246. return err;
  247. }
  248. if (valid && lfs_scmp(test.rev, dir->d.rev) < 0) {
  249. continue;
  250. }
  251. uint32_t crc = 0xffffffff;
  252. crc = lfs_crc(crc, sizeof(test), &test);
  253. for (lfs_off_t j = sizeof(test); j < lfs->cfg->block_size; j += 4) {
  254. uint32_t word;
  255. int err = lfs_bd_read(lfs, tpair[i], j, 4, &word);
  256. if (err) {
  257. return err;
  258. }
  259. crc = lfs_crc(crc, 4, &word);
  260. }
  261. if (crc != 0) {
  262. continue;
  263. }
  264. valid = true;
  265. // setup dir in case it's valid
  266. dir->pair[0] = tpair[(i+0) % 2];
  267. dir->pair[1] = tpair[(i+1) % 2];
  268. dir->off = sizeof(dir->d);
  269. dir->d = test;
  270. }
  271. if (!valid) {
  272. LFS_ERROR("Corrupted dir pair at %d %d", tpair[0], tpair[1]);
  273. return LFS_ERROR_CORRUPT;
  274. }
  275. return 0;
  276. }
  277. static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir,
  278. const lfs_entry_t *entry, const void *data) {
  279. dir->d.rev += 1;
  280. lfs_pairswap(dir->pair);
  281. int err = lfs_bd_erase(lfs, dir->pair[0]);
  282. if (err) {
  283. return err;
  284. }
  285. uint32_t crc = 0xffffffff;
  286. crc = lfs_crc(crc, sizeof(dir->d), &dir->d);
  287. err = lfs_bd_prog(lfs, dir->pair[0], 0, sizeof(dir->d), &dir->d);
  288. if (err) {
  289. return err;
  290. }
  291. lfs_off_t off = sizeof(dir->d);
  292. lfs_size_t size = 0x7fffffff & dir->d.size;
  293. while (off < size) {
  294. if (entry && off == entry->off) {
  295. crc = lfs_crc(crc, sizeof(entry->d), &entry->d);
  296. int err = lfs_bd_prog(lfs, dir->pair[0],
  297. off, sizeof(entry->d), &entry->d);
  298. if (err) {
  299. return err;
  300. }
  301. off += sizeof(entry->d);
  302. if (data) {
  303. crc = lfs_crc(crc, entry->d.len - sizeof(entry->d), data);
  304. int err = lfs_bd_prog(lfs, dir->pair[0],
  305. off, entry->d.len - sizeof(entry->d), data);
  306. if (err) {
  307. return err;
  308. }
  309. off += entry->d.len - sizeof(entry->d);
  310. }
  311. } else {
  312. uint8_t data;
  313. int err = lfs_bd_read(lfs, dir->pair[1], off, 1, &data);
  314. if (err) {
  315. return err;
  316. }
  317. crc = lfs_crc(crc, 1, &data);
  318. err = lfs_bd_prog(lfs, dir->pair[0], off, 1, &data);
  319. if (err) {
  320. return err;
  321. }
  322. off += 1;
  323. }
  324. }
  325. while (off < lfs->cfg->block_size-4) {
  326. uint8_t data = 0xff;
  327. crc = lfs_crc(crc, 1, &data);
  328. err = lfs_bd_prog(lfs, dir->pair[0], off, 1, &data);
  329. if (err) {
  330. return err;
  331. }
  332. off += 1;
  333. }
  334. err = lfs_bd_prog(lfs, dir->pair[0], lfs->cfg->block_size-4, 4, &crc);
  335. if (err) {
  336. return err;
  337. }
  338. return lfs_bd_sync(lfs);
  339. }
  340. static int lfs_dir_shift(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
  341. dir->d.rev += 1;
  342. dir->d.size -= entry->d.len;
  343. lfs_pairswap(dir->pair);
  344. int err = lfs_bd_erase(lfs, dir->pair[0]);
  345. if (err) {
  346. return err;
  347. }
  348. uint32_t crc = 0xffffffff;
  349. crc = lfs_crc(crc, sizeof(dir->d), &dir->d);
  350. err = lfs_bd_prog(lfs, dir->pair[0], 0, sizeof(dir->d), &dir->d);
  351. if (err) {
  352. return err;
  353. }
  354. lfs_off_t woff = sizeof(dir->d);
  355. lfs_off_t roff = sizeof(dir->d);
  356. lfs_size_t size = 0x7fffffff & dir->d.size;
  357. while (woff < size) {
  358. if (roff == entry->off) {
  359. roff += entry->d.len;
  360. } else {
  361. uint8_t data;
  362. int err = lfs_bd_read(lfs, dir->pair[1], roff, 1, &data);
  363. if (err) {
  364. return err;
  365. }
  366. crc = lfs_crc(crc, 1, (void*)&data);
  367. err = lfs_bd_prog(lfs, dir->pair[0], woff, 1, &data);
  368. if (err) {
  369. return err;
  370. }
  371. woff += 1;
  372. roff += 1;
  373. }
  374. }
  375. while (woff < lfs->cfg->block_size-4) {
  376. uint8_t data = 0xff;
  377. crc = lfs_crc(crc, 1, &data);
  378. err = lfs_bd_prog(lfs, dir->pair[0], woff, 1, &data);
  379. if (err) {
  380. return err;
  381. }
  382. woff += 1;
  383. }
  384. err = lfs_bd_prog(lfs, dir->pair[0], lfs->cfg->block_size-4, 4, &crc);
  385. if (err) {
  386. return err;
  387. }
  388. return lfs_bd_sync(lfs);
  389. }
  390. static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
  391. lfs_entry_t *entry, const void *data) {
  392. // check if we fit, if top bit is set we do not and move on
  393. while (true) {
  394. if (dir->d.size + entry->d.len <= lfs->cfg->block_size - 4) {
  395. entry->pair[0] = dir->pair[0];
  396. entry->pair[1] = dir->pair[1];
  397. entry->off = dir->d.size;
  398. dir->d.size += entry->d.len;
  399. return lfs_dir_commit(lfs, dir, entry, data);
  400. }
  401. if (!(0x80000000 & dir->d.size)) {
  402. lfs_dir_t newdir;
  403. int err = lfs_dir_alloc(lfs, &newdir);
  404. if (err) {
  405. return err;
  406. }
  407. newdir.d.tail[0] = dir->d.tail[0];
  408. newdir.d.tail[1] = dir->d.tail[1];
  409. entry->pair[0] = newdir.pair[0];
  410. entry->pair[1] = newdir.pair[1];
  411. entry->off = newdir.d.size;
  412. newdir.d.size += entry->d.len;
  413. err = lfs_dir_commit(lfs, &newdir, entry, data);
  414. if (err) {
  415. return err;
  416. }
  417. dir->d.size |= 0x80000000;
  418. dir->d.tail[0] = newdir.pair[0];
  419. dir->d.tail[1] = newdir.pair[1];
  420. return lfs_dir_commit(lfs, dir, NULL, NULL);
  421. }
  422. int err = lfs_dir_fetch(lfs, dir, dir->d.tail);
  423. if (err) {
  424. return err;
  425. }
  426. }
  427. }
  428. static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
  429. // either shift out the one entry or remove the whole dir block
  430. if (dir->d.size == sizeof(dir->d)) {
  431. lfs_dir_t pdir;
  432. int err = lfs_dir_fetch(lfs, &pdir, lfs->root);
  433. if (err) {
  434. return err;
  435. }
  436. while (lfs_paircmp(pdir.d.tail, dir->pair) != 0) {
  437. int err = lfs_dir_fetch(lfs, &pdir, pdir.d.tail);
  438. if (err) {
  439. return err;
  440. }
  441. }
  442. // TODO easier check for head block? (common case)
  443. if (!(pdir.d.size & 0x80000000)) {
  444. return lfs_dir_shift(lfs, dir, entry);
  445. } else {
  446. pdir.d.tail[0] = dir->d.tail[0];
  447. pdir.d.tail[1] = dir->d.tail[1];
  448. return lfs_dir_commit(lfs, &pdir, NULL, NULL);
  449. }
  450. } else {
  451. return lfs_dir_shift(lfs, dir, entry);
  452. }
  453. }
  454. static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
  455. while (true) {
  456. if (dir->off + sizeof(entry->d) > (0x7fffffff & dir->d.size)) {
  457. if (!(0x80000000 & dir->d.size)) {
  458. entry->pair[0] = dir->pair[0];
  459. entry->pair[1] = dir->pair[1];
  460. entry->off = dir->off;
  461. return LFS_ERROR_NO_ENTRY;
  462. }
  463. int err = lfs_dir_fetch(lfs, dir, dir->d.tail);
  464. if (err) {
  465. return err;
  466. }
  467. dir->off = sizeof(dir->d);
  468. dir->pos += sizeof(dir->d);
  469. continue;
  470. }
  471. int err = lfs_bd_read(lfs, dir->pair[0], dir->off,
  472. sizeof(entry->d), &entry->d);
  473. if (err) {
  474. return err;
  475. }
  476. dir->off += entry->d.len;
  477. dir->pos += entry->d.len;
  478. if ((0xff & entry->d.type) == LFS_TYPE_REG ||
  479. (0xff & entry->d.type) == LFS_TYPE_DIR) {
  480. entry->pair[0] = dir->pair[0];
  481. entry->pair[1] = dir->pair[1];
  482. entry->off = dir->off - entry->d.len;
  483. return 0;
  484. }
  485. }
  486. }
  487. static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
  488. lfs_entry_t *entry, const char **path) {
  489. const char *pathname = *path;
  490. size_t pathlen;
  491. while (true) {
  492. nextname:
  493. // skip slashes
  494. pathname += strspn(pathname, "/");
  495. pathlen = strcspn(pathname, "/");
  496. // skip '.' and root '..'
  497. if ((pathlen == 1 && memcmp(pathname, ".", 1) == 0) ||
  498. (pathlen == 2 && memcmp(pathname, "..", 2) == 0)) {
  499. pathname += pathlen;
  500. goto nextname;
  501. }
  502. // skip if matched by '..' in name
  503. const char *suffix = pathname + pathlen;
  504. size_t sufflen;
  505. int depth = 1;
  506. while (true) {
  507. suffix += strspn(suffix, "/");
  508. sufflen = strcspn(suffix, "/");
  509. if (sufflen == 0) {
  510. break;
  511. }
  512. if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) {
  513. depth -= 1;
  514. if (depth == 0) {
  515. pathname = suffix + sufflen;
  516. goto nextname;
  517. }
  518. } else {
  519. depth += 1;
  520. }
  521. suffix += sufflen;
  522. }
  523. // find path
  524. while (true) {
  525. int err = lfs_dir_next(lfs, dir, entry);
  526. if (err) {
  527. return err;
  528. }
  529. if (entry->d.len - sizeof(entry->d) != pathlen) {
  530. continue;
  531. }
  532. int ret = lfs_bd_cmp(lfs, dir->pair[0],
  533. entry->off + sizeof(entry->d), pathlen, pathname);
  534. if (ret < 0) {
  535. return ret;
  536. }
  537. // Found match
  538. if (ret == true) {
  539. break;
  540. }
  541. }
  542. pathname += pathlen;
  543. pathname += strspn(pathname, "/");
  544. if (pathname[0] == '\0') {
  545. return 0;
  546. }
  547. // continue on if we hit a directory
  548. if (entry->d.type != LFS_TYPE_DIR) {
  549. return LFS_ERROR_NOT_DIR;
  550. }
  551. int err = lfs_dir_fetch(lfs, dir, entry->d.u.dir);
  552. if (err) {
  553. return err;
  554. }
  555. *path = pathname;
  556. }
  557. return 0;
  558. }
  559. /// Top level directory operations ///
  560. int lfs_mkdir(lfs_t *lfs, const char *path) {
  561. // fetch parent directory
  562. lfs_dir_t cwd;
  563. int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
  564. if (err) {
  565. return err;
  566. }
  567. lfs_entry_t entry;
  568. err = lfs_dir_find(lfs, &cwd, &entry, &path);
  569. if (err != LFS_ERROR_NO_ENTRY) {
  570. return err ? err : LFS_ERROR_EXISTS;
  571. }
  572. // Build up new directory
  573. lfs_dir_t dir;
  574. err = lfs_dir_alloc(lfs, &dir);
  575. if (err) {
  576. return err;
  577. }
  578. dir.d.tail[0] = cwd.d.tail[0];
  579. dir.d.tail[1] = cwd.d.tail[1];
  580. err = lfs_dir_commit(lfs, &dir, NULL, NULL);
  581. if (err) {
  582. return err;
  583. }
  584. entry.d.type = LFS_TYPE_DIR;
  585. entry.d.len = sizeof(entry.d) + strlen(path);
  586. entry.d.u.dir[0] = dir.pair[0];
  587. entry.d.u.dir[1] = dir.pair[1];
  588. cwd.d.tail[0] = dir.pair[0];
  589. cwd.d.tail[1] = dir.pair[1];
  590. return lfs_dir_append(lfs, &cwd, &entry, path);
  591. }
  592. int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
  593. dir->pair[0] = lfs->root[0];
  594. dir->pair[1] = lfs->root[1];
  595. int err = lfs_dir_fetch(lfs, dir, dir->pair);
  596. if (err) {
  597. return err;
  598. }
  599. if (strspn(path, "/.") == strlen(path)) {
  600. // can only be something like '/././../.'
  601. dir->head[0] = dir->pair[0];
  602. dir->head[1] = dir->pair[1];
  603. dir->pos = sizeof(dir->d) - 2;
  604. dir->off = sizeof(dir->d);
  605. return 0;
  606. }
  607. lfs_entry_t entry;
  608. err = lfs_dir_find(lfs, dir, &entry, &path);
  609. if (err) {
  610. return err;
  611. } else if (entry.d.type != LFS_TYPE_DIR) {
  612. return LFS_ERROR_NOT_DIR;
  613. }
  614. err = lfs_dir_fetch(lfs, dir, entry.d.u.dir);
  615. if (err) {
  616. return err;
  617. }
  618. // setup head dir
  619. // special offset for '.' and '..'
  620. dir->head[0] = dir->pair[0];
  621. dir->head[1] = dir->pair[1];
  622. dir->pos = sizeof(dir->d) - 2;
  623. dir->off = sizeof(dir->d);
  624. return 0;
  625. }
  626. int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir) {
  627. // Do nothing, dir is always synchronized
  628. return 0;
  629. }
  630. int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
  631. memset(info, 0, sizeof(*info));
  632. // special offset for '.' and '..'
  633. if (dir->pos == sizeof(dir->d) - 2) {
  634. info->type = LFS_TYPE_DIR;
  635. strcpy(info->name, ".");
  636. dir->pos += 1;
  637. return 1;
  638. } else if (dir->pos == sizeof(dir->d) - 1) {
  639. info->type = LFS_TYPE_DIR;
  640. strcpy(info->name, "..");
  641. dir->pos += 1;
  642. return 1;
  643. }
  644. lfs_entry_t entry;
  645. int err = lfs_dir_next(lfs, dir, &entry);
  646. if (err) {
  647. return (err == LFS_ERROR_NO_ENTRY) ? 0 : err;
  648. }
  649. info->type = entry.d.type & 0xff;
  650. if (info->type == LFS_TYPE_REG) {
  651. info->size = entry.d.u.file.size;
  652. }
  653. err = lfs_bd_read(lfs, dir->pair[0], entry.off + sizeof(entry.d),
  654. entry.d.len - sizeof(entry.d), info->name);
  655. if (err) {
  656. return err;
  657. }
  658. return 1;
  659. }
  660. int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) {
  661. // simply walk from head dir
  662. int err = lfs_dir_rewind(lfs, dir);
  663. if (err) {
  664. return err;
  665. }
  666. dir->pos = off;
  667. while (off > (0x7fffffff & dir->d.size)) {
  668. off -= 0x7fffffff & dir->d.size;
  669. if (!(0x80000000 & dir->d.size)) {
  670. return LFS_ERROR_INVALID;
  671. }
  672. int err = lfs_dir_fetch(lfs, dir, dir->d.tail);
  673. if (err) {
  674. return err;
  675. }
  676. }
  677. dir->off = off;
  678. return 0;
  679. }
  680. lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir) {
  681. return dir->pos;
  682. }
  683. int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir) {
  684. // reload the head dir
  685. int err = lfs_dir_fetch(lfs, dir, dir->head);
  686. if (err) {
  687. return err;
  688. }
  689. dir->pair[0] = dir->head[0];
  690. dir->pair[1] = dir->head[1];
  691. dir->pos = sizeof(dir->d) - 2;
  692. dir->off = sizeof(dir->d);
  693. return 0;
  694. }
  695. /// Index list operations ///
  696. static int lfs_index(lfs_t *lfs, lfs_off_t *off) {
  697. lfs_off_t i = 0;
  698. while (*off >= lfs->cfg->block_size) {
  699. i += 1;
  700. *off -= lfs->cfg->block_size;
  701. *off += 4*lfs_min(lfs_ctz(i)+1, lfs->words-1);
  702. }
  703. return i;
  704. }
  705. static int lfs_index_find(lfs_t *lfs, lfs_block_t head, lfs_size_t size,
  706. lfs_size_t pos, lfs_block_t *block, lfs_off_t *off) {
  707. if (size == 0) {
  708. *block = 0;
  709. *off = 0;
  710. return 0;
  711. }
  712. lfs_off_t current = lfs_index(lfs, &(lfs_off_t){size-1});
  713. lfs_off_t target = lfs_index(lfs, &pos);
  714. while (current > target) {
  715. lfs_size_t skip = lfs_min(
  716. lfs_npw2(current-target+1) - 1,
  717. lfs_min(lfs_ctz(current)+1, lfs->words-1) - 1);
  718. int err = lfs_bd_read(lfs, head, 4*skip, 4, &head);
  719. if (err) {
  720. return err;
  721. }
  722. current -= 1 << skip;
  723. }
  724. *block = head;
  725. *off = pos;
  726. return 0;
  727. }
  728. static int lfs_index_extend(lfs_t *lfs,
  729. lfs_block_t head, lfs_size_t size,
  730. lfs_off_t *block, lfs_block_t *off) {
  731. // go ahead and grab a block
  732. int err = lfs_alloc(lfs, block);
  733. if (err) {
  734. return err;
  735. }
  736. err = lfs_bd_erase(lfs, *block);
  737. if (err) {
  738. return err;
  739. }
  740. if (size == 0) {
  741. *off = 0;
  742. return 0;
  743. }
  744. size -= 1;
  745. lfs_off_t index = lfs_index(lfs, &size);
  746. size += 1;
  747. // just copy out the last block if it is incomplete
  748. if (size != lfs->cfg->block_size) {
  749. for (lfs_off_t i = 0; i < size; i++) {
  750. uint8_t data;
  751. int err = lfs_bd_read(lfs, head, i, 1, &data);
  752. if (err) {
  753. return err;
  754. }
  755. err = lfs_bd_prog(lfs, *block, i, 1, &data);
  756. if (err) {
  757. return err;
  758. }
  759. }
  760. *off = size;
  761. return 0;
  762. }
  763. // append block
  764. index += 1;
  765. lfs_size_t skips = lfs_min(lfs_ctz(index)+1, lfs->words-1);
  766. for (lfs_off_t i = 0; i < skips; i++) {
  767. int err = lfs_bd_prog(lfs, *block, 4*i, 4, &head);
  768. if (err) {
  769. return err;
  770. }
  771. if (i != skips-1) {
  772. err = lfs_bd_read(lfs, head, 4*i, 4, &head);
  773. if (err) {
  774. return err;
  775. }
  776. }
  777. }
  778. *off = 4*skips;
  779. return 0;
  780. }
  781. static int lfs_index_traverse(lfs_t *lfs,
  782. lfs_block_t head, lfs_size_t size,
  783. int (*cb)(void*, lfs_block_t), void *data) {
  784. if (size == 0) {
  785. return 0;
  786. }
  787. lfs_off_t index = lfs_index(lfs, &(lfs_off_t){size-1});
  788. while (true) {
  789. int err = cb(data, head);
  790. if (err) {
  791. return err;
  792. }
  793. if (index == 0) {
  794. return 0;
  795. }
  796. err = lfs_bd_read(lfs, head, 0, 4, &head);
  797. if (err) {
  798. return err;
  799. }
  800. index -= 1;
  801. }
  802. return 0;
  803. }
  804. /// Top level file operations ///
  805. int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
  806. const char *path, int flags) {
  807. file->flags = flags;
  808. // Allocate entry for file if it doesn't exist
  809. // TODO check open files
  810. lfs_dir_t cwd;
  811. int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
  812. if (err) {
  813. return err;
  814. }
  815. err = lfs_dir_find(lfs, &cwd, &file->entry, &path);
  816. if (err && err != LFS_ERROR_NO_ENTRY) {
  817. return err;
  818. }
  819. if (err == LFS_ERROR_NO_ENTRY) {
  820. if (!(flags & LFS_O_CREAT)) {
  821. return LFS_ERROR_NO_ENTRY;
  822. }
  823. // create entry to remember name
  824. file->entry.d.type = LFS_TYPE_REG;
  825. file->entry.d.len = sizeof(file->entry.d) + strlen(path);
  826. file->entry.d.u.file.head = 0;
  827. file->entry.d.u.file.size = 0;
  828. err = lfs_dir_append(lfs, &cwd, &file->entry, path);
  829. if (err) {
  830. return err;
  831. }
  832. } else if (file->entry.d.type == LFS_TYPE_DIR) {
  833. return LFS_ERROR_IS_DIR;
  834. } else if (flags & LFS_O_EXCL) {
  835. return LFS_ERROR_EXISTS;
  836. }
  837. file->wpos = 0;
  838. file->wblock = 0;
  839. file->rpos = 0;
  840. file->rblock = 0;
  841. if (flags & LFS_O_TRUNC) {
  842. file->entry.d.u.file.head = 0;
  843. file->entry.d.u.file.size = 0;
  844. }
  845. if (flags & LFS_O_APPEND) {
  846. file->wpos = file->entry.d.u.file.size;
  847. }
  848. return 0;
  849. }
  850. int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
  851. return lfs_file_sync(lfs, file);
  852. }
  853. static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
  854. if (file->wblock == 0) {
  855. // already in sync, may be rdonly
  856. return 0;
  857. }
  858. // copy over anything after the file
  859. lfs_off_t oldrpos = file->rpos;
  860. lfs_off_t oldwpos = file->wpos;
  861. file->rpos = file->wpos;
  862. file->rblock = 0;
  863. while (file->wpos < file->entry.d.u.file.size) {
  864. uint8_t data;
  865. lfs_ssize_t res = lfs_file_read(lfs, file, &data, 1);
  866. if (res < 0) {
  867. return res;
  868. }
  869. res = lfs_file_write(lfs, file, &data, 1);
  870. if (res < 0) {
  871. return res;
  872. }
  873. }
  874. // actual file updates
  875. file->entry.d.u.file.head = file->wblock;
  876. file->entry.d.u.file.size = file->wpos;
  877. file->rpos = oldrpos;
  878. file->rblock = 0;
  879. file->wpos = oldwpos;
  880. file->wblock = 0;
  881. return 0;
  882. }
  883. int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
  884. if (file->wblock == 0) {
  885. // already in sync, may be rdonly
  886. return 0;
  887. }
  888. int err = lfs_file_flush(lfs, file);
  889. if (err) {
  890. return err;
  891. }
  892. // update dir entry
  893. lfs_dir_t cwd;
  894. err = lfs_dir_fetch(lfs, &cwd, file->entry.pair);
  895. if (err) {
  896. return err;
  897. }
  898. return lfs_dir_commit(lfs, &cwd, &file->entry, NULL);
  899. }
  900. lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
  901. const void *buffer, lfs_size_t size) {
  902. const uint8_t *data = buffer;
  903. lfs_size_t nsize = size;
  904. if ((file->flags & 3) == LFS_O_RDONLY) {
  905. return LFS_ERROR_INVALID;
  906. }
  907. while (nsize > 0) {
  908. // check if we need a new block
  909. if (!file->wblock || file->woff == lfs->cfg->block_size) {
  910. if (!file->wblock) {
  911. // find out which block we're extending from
  912. int err = lfs_index_find(lfs,
  913. file->entry.d.u.file.head, file->entry.d.u.file.size,
  914. file->wpos, &file->wblock, &file->woff);
  915. if (err) {
  916. return err;
  917. }
  918. }
  919. // extend file with new blocks
  920. int err = lfs_index_extend(lfs, file->wblock, file->wpos,
  921. &file->wblock, &file->woff);
  922. if (err) {
  923. return err;
  924. }
  925. }
  926. // program as much as we can in current block
  927. lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->woff);
  928. int err = lfs_bd_prog(lfs, file->wblock, file->woff, diff, data);
  929. if (err) {
  930. return err;
  931. }
  932. file->wpos += diff;
  933. file->woff += diff;
  934. data += diff;
  935. nsize -= diff;
  936. if (file->flags & LFS_O_APPEND) {
  937. file->entry.d.u.file.head = file->wblock;
  938. file->entry.d.u.file.size = file->wpos;
  939. }
  940. }
  941. if (file->flags & LFS_O_SYNC) {
  942. int err = lfs_file_sync(lfs, file);
  943. if (err) {
  944. return err;
  945. }
  946. }
  947. return size;
  948. }
  949. lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
  950. void *buffer, lfs_size_t size) {
  951. uint8_t *data = buffer;
  952. size = lfs_min(size, file->entry.d.u.file.size - file->rpos);
  953. lfs_size_t nsize = size;
  954. if ((file->flags & 3) == LFS_O_WRONLY) {
  955. return LFS_ERROR_INVALID;
  956. }
  957. while (nsize > 0) {
  958. // check if we need a new block
  959. if (!file->rblock || file->roff == lfs->cfg->block_size) {
  960. int err = lfs_index_find(lfs,
  961. file->entry.d.u.file.head, file->entry.d.u.file.size,
  962. file->rpos, &file->rblock, &file->roff);
  963. if (err) {
  964. return err;
  965. }
  966. }
  967. // read as much as we can in current block
  968. lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->roff);
  969. int err = lfs_bd_read(lfs, file->rblock, file->roff, diff, data);
  970. if (err) {
  971. return err;
  972. }
  973. file->rpos += diff;
  974. file->roff += diff;
  975. data += diff;
  976. nsize -= diff;
  977. }
  978. return size;
  979. }
  980. lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
  981. lfs_soff_t off, int whence) {
  982. // write out everything beforehand, may be noop if rdonly
  983. int err = lfs_file_flush(lfs, file);
  984. if (err) {
  985. return err;
  986. }
  987. // rpos is always correct pos, even in append mode
  988. // TODO keep rpos and wpos together?
  989. lfs_off_t prev = file->rpos;
  990. file->rblock = 0;
  991. switch (whence) {
  992. case LFS_SEEK_SET:
  993. file->rpos = off;
  994. break;
  995. case LFS_SEEK_CUR:
  996. file->rpos = file->rpos + off;
  997. break;
  998. case LFS_SEEK_END:
  999. file->rpos = file->entry.d.u.file.size + off;
  1000. break;
  1001. }
  1002. if (!(file->flags & LFS_O_APPEND)) {
  1003. file->wpos = file->rpos;
  1004. file->wblock = 0;
  1005. }
  1006. return prev;
  1007. }
  1008. lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) {
  1009. return lfs_max(file->wpos, file->entry.d.u.file.size);
  1010. }
  1011. lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file) {
  1012. return file->rpos;
  1013. }
  1014. int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file) {
  1015. lfs_soff_t res = lfs_file_seek(lfs, file, 0, LFS_SEEK_SET);
  1016. if (res < 0) {
  1017. return res;
  1018. }
  1019. return 0;
  1020. }
  1021. /// Generic filesystem operations ///
  1022. static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
  1023. lfs->cfg = cfg;
  1024. lfs->words = lfs->cfg->block_size / sizeof(uint32_t);
  1025. // setup read cache
  1026. lfs->rcache.off = -1;
  1027. if (lfs->cfg->read_buffer) {
  1028. lfs->rcache.buffer = lfs->cfg->read_buffer;
  1029. } else {
  1030. lfs->rcache.buffer = malloc(lfs->cfg->read_size);
  1031. if (!lfs->rcache.buffer) {
  1032. return LFS_ERROR_NO_MEM;
  1033. }
  1034. }
  1035. // setup program cache
  1036. lfs->pcache.off = -1;
  1037. if (lfs->cfg->prog_buffer) {
  1038. lfs->pcache.buffer = lfs->cfg->prog_buffer;
  1039. } else {
  1040. lfs->pcache.buffer = malloc(lfs->cfg->prog_size);
  1041. if (!lfs->pcache.buffer) {
  1042. return LFS_ERROR_NO_MEM;
  1043. }
  1044. }
  1045. // setup lookahead
  1046. if (lfs->cfg->lookahead_buffer) {
  1047. lfs->free.lookahead = lfs->cfg->lookahead_buffer;
  1048. } else {
  1049. lfs->free.lookahead = malloc(lfs->cfg->lookahead/8);
  1050. if (!lfs->free.lookahead) {
  1051. return LFS_ERROR_NO_MEM;
  1052. }
  1053. }
  1054. return 0;
  1055. }
  1056. static int lfs_deinit(lfs_t *lfs) {
  1057. // Free allocated memory
  1058. if (!lfs->cfg->read_buffer) {
  1059. free(lfs->rcache.buffer);
  1060. }
  1061. if (!lfs->cfg->prog_buffer) {
  1062. free(lfs->pcache.buffer);
  1063. }
  1064. return 0;
  1065. }
  1066. int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
  1067. int err = lfs_init(lfs, cfg);
  1068. if (err) {
  1069. return err;
  1070. }
  1071. // Create free lookahead
  1072. memset(lfs->free.lookahead, 0, lfs->cfg->lookahead/8);
  1073. lfs->free.start = 0;
  1074. lfs->free.off = 0;
  1075. // Create superblock dir
  1076. lfs_dir_t superdir;
  1077. err = lfs_dir_alloc(lfs, &superdir);
  1078. if (err) {
  1079. return err;
  1080. }
  1081. // Write root directory
  1082. lfs_dir_t root;
  1083. err = lfs_dir_alloc(lfs, &root);
  1084. if (err) {
  1085. return err;
  1086. }
  1087. err = lfs_dir_commit(lfs, &root, NULL, NULL);
  1088. if (err) {
  1089. return err;
  1090. }
  1091. lfs->root[0] = root.pair[0];
  1092. lfs->root[1] = root.pair[1];
  1093. // Write superblocks
  1094. lfs_superblock_t superblock = {
  1095. .off = sizeof(superdir.d),
  1096. .d.type = LFS_TYPE_SUPERBLOCK,
  1097. .d.len = sizeof(superblock.d),
  1098. .d.version = 0x00000001,
  1099. .d.magic = {"littlefs"},
  1100. .d.block_size = lfs->cfg->block_size,
  1101. .d.block_count = lfs->cfg->block_count,
  1102. .d.root = {lfs->root[0], lfs->root[1]},
  1103. };
  1104. superdir.d.tail[0] = root.pair[0];
  1105. superdir.d.tail[1] = root.pair[1];
  1106. superdir.d.size += sizeof(superdir.d);
  1107. for (int i = 0; i < 2; i++) {
  1108. // Write both pairs for extra safety, do some finagling to pretend
  1109. // the superblock is an entry
  1110. int err = lfs_dir_commit(lfs, &superdir,
  1111. (const lfs_entry_t*)&superblock,
  1112. (const struct lfs_disk_entry*)&superblock.d + 1);
  1113. if (err) {
  1114. LFS_ERROR("Failed to write superblock at %d", superdir.pair[0]);
  1115. return err;
  1116. }
  1117. }
  1118. // sanity check that fetch works
  1119. err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1});
  1120. if (err) {
  1121. return err;
  1122. }
  1123. return lfs_deinit(lfs);
  1124. }
  1125. int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
  1126. int err = lfs_init(lfs, cfg);
  1127. if (err) {
  1128. return err;
  1129. }
  1130. // setup free lookahead
  1131. lfs->free.start = -lfs->cfg->lookahead;
  1132. lfs->free.off = lfs->cfg->lookahead;
  1133. // load superblock
  1134. lfs_dir_t dir;
  1135. lfs_superblock_t superblock;
  1136. err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1});
  1137. if (!err) {
  1138. err = lfs_bd_read(lfs, dir.pair[0],
  1139. sizeof(dir.d), sizeof(superblock.d), &superblock.d);
  1140. }
  1141. if (err == LFS_ERROR_CORRUPT ||
  1142. memcmp(superblock.d.magic, "littlefs", 8) != 0) {
  1143. LFS_ERROR("Invalid superblock at %d %d", dir.pair[0], dir.pair[1]);
  1144. return LFS_ERROR_CORRUPT;
  1145. }
  1146. if (superblock.d.version > 0x0000ffff) {
  1147. LFS_ERROR("Invalid version %d.%d\n",
  1148. 0xffff & (superblock.d.version >> 16),
  1149. 0xffff & (superblock.d.version >> 0));
  1150. }
  1151. lfs->root[0] = superblock.d.root[0];
  1152. lfs->root[1] = superblock.d.root[1];
  1153. return err;
  1154. }
  1155. int lfs_unmount(lfs_t *lfs) {
  1156. return lfs_deinit(lfs);
  1157. }
  1158. int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) {
  1159. // iterate over metadata pairs
  1160. lfs_dir_t dir;
  1161. lfs_file_t file;
  1162. lfs_block_t cwd[2] = {0, 1};
  1163. while (true) {
  1164. for (int i = 0; i < 2; i++) {
  1165. int err = cb(data, cwd[i]);
  1166. if (err) {
  1167. return err;
  1168. }
  1169. }
  1170. int err = lfs_dir_fetch(lfs, &dir, cwd);
  1171. if (err) {
  1172. return err;
  1173. }
  1174. // iterate over contents
  1175. while ((0x7fffffff & dir.d.size) >= dir.off + sizeof(file.entry.d)) {
  1176. int err = lfs_bd_read(lfs, dir.pair[0], dir.off,
  1177. sizeof(file.entry.d), &file.entry.d);
  1178. if (err) {
  1179. return err;
  1180. }
  1181. dir.off += file.entry.d.len;
  1182. if ((0xf & file.entry.d.type) == LFS_TYPE_REG) {
  1183. if (file.entry.d.u.file.size < lfs->cfg->block_size) {
  1184. int err = cb(data, file.entry.d.u.file.head);
  1185. if (err) {
  1186. return err;
  1187. }
  1188. } else {
  1189. int err = lfs_index_traverse(lfs,
  1190. file.entry.d.u.file.head,
  1191. file.entry.d.u.file.size,
  1192. cb, data);
  1193. if (err) {
  1194. return err;
  1195. }
  1196. }
  1197. }
  1198. }
  1199. cwd[0] = dir.d.tail[0];
  1200. cwd[1] = dir.d.tail[1];
  1201. if (!cwd[0]) {
  1202. return 0;
  1203. }
  1204. }
  1205. }
  1206. static int lfs_parent(lfs_t *lfs, const lfs_block_t dir[2]) {
  1207. // iterate over all directory directory entries
  1208. lfs_dir_t parent = {
  1209. .d.tail[0] = lfs->root[0],
  1210. .d.tail[1] = lfs->root[1],
  1211. };
  1212. while (parent.d.tail[0]) {
  1213. lfs_entry_t entry;
  1214. int err = lfs_dir_fetch(lfs, &parent, parent.d.tail);
  1215. if (err) {
  1216. return err;
  1217. }
  1218. while (true) {
  1219. int err = lfs_dir_next(lfs, &parent, &entry);
  1220. if (err && err != LFS_ERROR_NO_ENTRY) {
  1221. return err;
  1222. }
  1223. if (err == LFS_ERROR_NO_ENTRY) {
  1224. break;
  1225. }
  1226. if ((0xf & entry.d.type) == LFS_TYPE_DIR &&
  1227. lfs_paircmp(entry.d.u.dir, dir) == 0) {
  1228. return true;
  1229. }
  1230. }
  1231. }
  1232. return false;
  1233. }
  1234. int lfs_deorphan(lfs_t *lfs) {
  1235. // iterate over all directories
  1236. lfs_dir_t pdir;
  1237. lfs_dir_t cdir;
  1238. // skip root
  1239. int err = lfs_dir_fetch(lfs, &pdir, lfs->root);
  1240. if (err) {
  1241. return err;
  1242. }
  1243. while (pdir.d.tail[0]) {
  1244. int err = lfs_dir_fetch(lfs, &cdir, pdir.d.tail);
  1245. if (err) {
  1246. return err;
  1247. }
  1248. // check if we have a parent
  1249. int parent = lfs_parent(lfs, pdir.d.tail);
  1250. if (parent < 0) {
  1251. return parent;
  1252. }
  1253. if (!parent) {
  1254. // we are an orphan
  1255. LFS_INFO("Orphan %d %d", pdir.d.tail[0], pdir.d.tail[1]);
  1256. pdir.d.tail[0] = cdir.d.tail[0];
  1257. pdir.d.tail[1] = cdir.d.tail[1];
  1258. err = lfs_dir_commit(lfs, &pdir, NULL, NULL);
  1259. if (err) {
  1260. return err;
  1261. }
  1262. break;
  1263. }
  1264. memcpy(&pdir, &cdir, sizeof(pdir));
  1265. }
  1266. return 0;
  1267. }
  1268. int lfs_remove(lfs_t *lfs, const char *path) {
  1269. lfs_dir_t cwd;
  1270. int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
  1271. if (err) {
  1272. return err;
  1273. }
  1274. lfs_entry_t entry;
  1275. err = lfs_dir_find(lfs, &cwd, &entry, &path);
  1276. if (err) {
  1277. return err;
  1278. }
  1279. lfs_dir_t dir;
  1280. if (entry.d.type == LFS_TYPE_DIR) {
  1281. // must be empty before removal, checking size
  1282. // without masking top bit checks for any case where
  1283. // dir is not empty
  1284. int err = lfs_dir_fetch(lfs, &dir, entry.d.u.dir);
  1285. if (err) {
  1286. return err;
  1287. } else if (dir.d.size != sizeof(dir.d)) {
  1288. return LFS_ERROR_INVALID;
  1289. }
  1290. }
  1291. // remove the entry
  1292. err = lfs_dir_remove(lfs, &cwd, &entry);
  1293. if (err) {
  1294. return err;
  1295. }
  1296. // if we were a directory, just run a deorphan step, this should
  1297. // collect us, although is expensive
  1298. if (entry.d.type == LFS_TYPE_DIR) {
  1299. int err = lfs_deorphan(lfs);
  1300. if (err) {
  1301. return err;
  1302. }
  1303. }
  1304. return 0;
  1305. }
  1306. int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
  1307. // find old entry
  1308. lfs_dir_t oldcwd;
  1309. int err = lfs_dir_fetch(lfs, &oldcwd, lfs->root);
  1310. if (err) {
  1311. return err;
  1312. }
  1313. lfs_entry_t oldentry;
  1314. err = lfs_dir_find(lfs, &oldcwd, &oldentry, &oldpath);
  1315. if (err) {
  1316. return err;
  1317. }
  1318. // allocate new entry
  1319. lfs_dir_t newcwd;
  1320. err = lfs_dir_fetch(lfs, &newcwd, lfs->root);
  1321. if (err) {
  1322. return err;
  1323. }
  1324. lfs_entry_t preventry;
  1325. err = lfs_dir_find(lfs, &newcwd, &preventry, &newpath);
  1326. if (err && err != LFS_ERROR_NO_ENTRY) {
  1327. return err;
  1328. }
  1329. bool prevexists = (err != LFS_ERROR_NO_ENTRY);
  1330. // must have same type
  1331. if (prevexists && preventry.d.type != oldentry.d.type) {
  1332. return LFS_ERROR_INVALID;
  1333. }
  1334. lfs_dir_t dir;
  1335. if (prevexists && preventry.d.type == LFS_TYPE_DIR) {
  1336. // must be empty before removal, checking size
  1337. // without masking top bit checks for any case where
  1338. // dir is not empty
  1339. int err = lfs_dir_fetch(lfs, &dir, preventry.d.u.dir);
  1340. if (err) {
  1341. return err;
  1342. } else if (dir.d.size != sizeof(dir.d)) {
  1343. return LFS_ERROR_INVALID;
  1344. }
  1345. }
  1346. // move to new location
  1347. lfs_entry_t newentry = preventry;
  1348. newentry.d = oldentry.d;
  1349. newentry.d.len = sizeof(newentry.d) + strlen(newpath);
  1350. if (prevexists) {
  1351. int err = lfs_dir_commit(lfs, &newcwd, &newentry, newpath);
  1352. if (err) {
  1353. return err;
  1354. }
  1355. } else {
  1356. int err = lfs_dir_append(lfs, &newcwd, &newentry, newpath);
  1357. if (err) {
  1358. return err;
  1359. }
  1360. }
  1361. // fetch again in case newcwd == oldcwd
  1362. // TODO handle this better?
  1363. err = lfs_dir_fetch(lfs, &oldcwd, oldcwd.pair);
  1364. if (err) {
  1365. return err;
  1366. }
  1367. err = lfs_dir_find(lfs, &oldcwd, &oldentry, &oldpath);
  1368. if (err) {
  1369. return err;
  1370. }
  1371. // remove from old location
  1372. err = lfs_dir_remove(lfs, &oldcwd, &oldentry);
  1373. if (err) {
  1374. return err;
  1375. }
  1376. // if we were a directory, just run a deorphan step, this should
  1377. // collect us, although is expensive
  1378. if (prevexists && preventry.d.type == LFS_TYPE_DIR) {
  1379. int err = lfs_deorphan(lfs);
  1380. if (err) {
  1381. return err;
  1382. }
  1383. }
  1384. return 0;
  1385. }
  1386. int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
  1387. lfs_dir_t cwd;
  1388. int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
  1389. if (err) {
  1390. return err;
  1391. }
  1392. lfs_entry_t entry;
  1393. err = lfs_dir_find(lfs, &cwd, &entry, &path);
  1394. if (err) {
  1395. return err;
  1396. }
  1397. // TODO abstract out info assignment
  1398. memset(info, 0, sizeof(*info));
  1399. info->type = entry.d.type & 0xff;
  1400. if (info->type == LFS_TYPE_REG) {
  1401. info->size = entry.d.u.file.size;
  1402. }
  1403. err = lfs_bd_read(lfs, cwd.pair[0], entry.off + sizeof(entry.d),
  1404. entry.d.len - sizeof(entry.d), info->name);
  1405. if (err) {
  1406. return err;
  1407. }
  1408. return 0;
  1409. }