lfs.c 40 KB

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