lfs.c 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559
  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 ((0x7fffffff & dir->d.size) - dir->off < sizeof(entry->d)) {
  457. if (!(dir->d.size >> 31)) {
  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. continue;
  469. }
  470. int err = lfs_bd_read(lfs, dir->pair[0], dir->off,
  471. sizeof(entry->d), &entry->d);
  472. if (err) {
  473. return err;
  474. }
  475. dir->off += entry->d.len;
  476. if ((0xff & entry->d.type) == LFS_TYPE_REG ||
  477. (0xff & entry->d.type) == LFS_TYPE_DIR) {
  478. entry->pair[0] = dir->pair[0];
  479. entry->pair[1] = dir->pair[1];
  480. entry->off = dir->off - entry->d.len;
  481. return 0;
  482. }
  483. }
  484. }
  485. static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
  486. lfs_entry_t *entry, const char **path) {
  487. const char *pathname = *path;
  488. size_t pathlen;
  489. while (true) {
  490. nextname:
  491. // skip slashes
  492. pathname += strspn(pathname, "/");
  493. pathlen = strcspn(pathname, "/");
  494. // skip '.' and root '..'
  495. if ((pathlen == 1 && memcmp(pathname, ".", 1) == 0) ||
  496. (pathlen == 2 && memcmp(pathname, "..", 2) == 0)) {
  497. pathname += pathlen;
  498. goto nextname;
  499. }
  500. // skip if matched by '..' in name
  501. const char *suffix = pathname + pathlen;
  502. size_t sufflen;
  503. int depth = 1;
  504. while (true) {
  505. suffix += strspn(suffix, "/");
  506. sufflen = strcspn(suffix, "/");
  507. if (sufflen == 0) {
  508. break;
  509. }
  510. if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) {
  511. depth -= 1;
  512. if (depth == 0) {
  513. pathname = suffix + sufflen;
  514. goto nextname;
  515. }
  516. } else {
  517. depth += 1;
  518. }
  519. suffix += sufflen;
  520. }
  521. // find path
  522. while (true) {
  523. int err = lfs_dir_next(lfs, dir, entry);
  524. if (err) {
  525. return err;
  526. }
  527. if (entry->d.len - sizeof(entry->d) != pathlen) {
  528. continue;
  529. }
  530. int ret = lfs_bd_cmp(lfs, dir->pair[0],
  531. entry->off + sizeof(entry->d), pathlen, pathname);
  532. if (ret < 0) {
  533. return ret;
  534. }
  535. // Found match
  536. if (ret == true) {
  537. break;
  538. }
  539. }
  540. pathname += pathlen;
  541. pathname += strspn(pathname, "/");
  542. if (pathname[0] == '\0') {
  543. return 0;
  544. }
  545. // continue on if we hit a directory
  546. if (entry->d.type != LFS_TYPE_DIR) {
  547. return LFS_ERROR_NOT_DIR;
  548. }
  549. int err = lfs_dir_fetch(lfs, dir, entry->d.u.dir);
  550. if (err) {
  551. return err;
  552. }
  553. *path = pathname;
  554. }
  555. return 0;
  556. }
  557. /// Top level directory operations ///
  558. int lfs_mkdir(lfs_t *lfs, const char *path) {
  559. // fetch parent directory
  560. lfs_dir_t cwd;
  561. int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
  562. if (err) {
  563. return err;
  564. }
  565. lfs_entry_t entry;
  566. err = lfs_dir_find(lfs, &cwd, &entry, &path);
  567. if (err != LFS_ERROR_NO_ENTRY) {
  568. return err ? err : LFS_ERROR_EXISTS;
  569. }
  570. // Build up new directory
  571. lfs_dir_t dir;
  572. err = lfs_dir_alloc(lfs, &dir);
  573. if (err) {
  574. return err;
  575. }
  576. dir.d.tail[0] = cwd.d.tail[0];
  577. dir.d.tail[1] = cwd.d.tail[1];
  578. err = lfs_dir_commit(lfs, &dir, NULL, NULL);
  579. if (err) {
  580. return err;
  581. }
  582. entry.d.type = LFS_TYPE_DIR;
  583. entry.d.len = sizeof(entry.d) + strlen(path);
  584. entry.d.u.dir[0] = dir.pair[0];
  585. entry.d.u.dir[1] = dir.pair[1];
  586. cwd.d.tail[0] = dir.pair[0];
  587. cwd.d.tail[1] = dir.pair[1];
  588. return lfs_dir_append(lfs, &cwd, &entry, path);
  589. }
  590. int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
  591. dir->pair[0] = lfs->root[0];
  592. dir->pair[1] = lfs->root[1];
  593. int err = lfs_dir_fetch(lfs, dir, dir->pair);
  594. if (err) {
  595. return err;
  596. } else if (strcmp(path, "/") == 0) {
  597. // special offset for '.' and '..'
  598. dir->off = sizeof(dir->d) - 2;
  599. return 0;
  600. }
  601. lfs_entry_t entry;
  602. err = lfs_dir_find(lfs, dir, &entry, &path);
  603. if (err) {
  604. return err;
  605. } else if (entry.d.type != LFS_TYPE_DIR) {
  606. return LFS_ERROR_NOT_DIR;
  607. }
  608. err = lfs_dir_fetch(lfs, dir, entry.d.u.dir);
  609. if (err) {
  610. return err;
  611. }
  612. // special offset for '.' and '..'
  613. dir->off = sizeof(dir->d) - 2;
  614. return 0;
  615. }
  616. int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir) {
  617. // Do nothing, dir is always synchronized
  618. return 0;
  619. }
  620. int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
  621. memset(info, 0, sizeof(*info));
  622. if (dir->off == sizeof(dir->d) - 2) {
  623. info->type = LFS_TYPE_DIR;
  624. strcpy(info->name, ".");
  625. dir->off += 1;
  626. return 1;
  627. } else if (dir->off == sizeof(dir->d) - 1) {
  628. info->type = LFS_TYPE_DIR;
  629. strcpy(info->name, "..");
  630. dir->off += 1;
  631. return 1;
  632. }
  633. lfs_entry_t entry;
  634. int err = lfs_dir_next(lfs, dir, &entry);
  635. if (err) {
  636. return (err == LFS_ERROR_NO_ENTRY) ? 0 : err;
  637. }
  638. info->type = entry.d.type & 0xff;
  639. if (info->type == LFS_TYPE_REG) {
  640. info->size = entry.d.u.file.size;
  641. }
  642. err = lfs_bd_read(lfs, dir->pair[0], entry.off + sizeof(entry.d),
  643. entry.d.len - sizeof(entry.d), info->name);
  644. if (err) {
  645. return err;
  646. }
  647. return 1;
  648. }
  649. /// Index list operations ///
  650. static int lfs_index(lfs_t *lfs, lfs_off_t *off) {
  651. lfs_off_t i = 0;
  652. while (*off >= lfs->cfg->block_size) {
  653. i += 1;
  654. *off -= lfs->cfg->block_size;
  655. *off += 4*lfs_min(lfs_ctz(i)+1, lfs->words-1);
  656. }
  657. return i;
  658. }
  659. static int lfs_index_find(lfs_t *lfs, lfs_block_t head, lfs_size_t size,
  660. lfs_size_t pos, lfs_block_t *block, lfs_off_t *off) {
  661. if (size == 0) {
  662. *block = 0;
  663. *off = 0;
  664. return 0;
  665. }
  666. lfs_off_t current = lfs_index(lfs, &(lfs_off_t){size-1});
  667. lfs_off_t target = lfs_index(lfs, &pos);
  668. while (current > target) {
  669. lfs_size_t skip = lfs_min(
  670. lfs_npw2(current-target+1) - 1,
  671. lfs_min(lfs_ctz(current)+1, lfs->words-1) - 1);
  672. int err = lfs_bd_read(lfs, head, 4*skip, 4, &head);
  673. if (err) {
  674. return err;
  675. }
  676. current -= 1 << skip;
  677. }
  678. *block = head;
  679. *off = pos;
  680. return 0;
  681. }
  682. static int lfs_index_extend(lfs_t *lfs,
  683. lfs_block_t head, lfs_size_t size,
  684. lfs_off_t *block, lfs_block_t *off) {
  685. // go ahead and grab a block
  686. int err = lfs_alloc(lfs, block);
  687. if (err) {
  688. return err;
  689. }
  690. err = lfs_bd_erase(lfs, *block);
  691. if (err) {
  692. return err;
  693. }
  694. if (size == 0) {
  695. *off = 0;
  696. return 0;
  697. }
  698. size -= 1;
  699. lfs_off_t index = lfs_index(lfs, &size);
  700. size += 1;
  701. // just copy out the last block if it is incomplete
  702. if (size != lfs->cfg->block_size) {
  703. for (lfs_off_t i = 0; i < size; i++) {
  704. uint8_t data;
  705. int err = lfs_bd_read(lfs, head, i, 1, &data);
  706. if (err) {
  707. return err;
  708. }
  709. err = lfs_bd_prog(lfs, *block, i, 1, &data);
  710. if (err) {
  711. return err;
  712. }
  713. }
  714. *off = size;
  715. return 0;
  716. }
  717. // append block
  718. index += 1;
  719. lfs_size_t skips = lfs_min(lfs_ctz(index)+1, lfs->words-1);
  720. for (lfs_off_t i = 0; i < skips; i++) {
  721. int err = lfs_bd_prog(lfs, *block, 4*i, 4, &head);
  722. if (err) {
  723. return err;
  724. }
  725. if (i != skips-1) {
  726. err = lfs_bd_read(lfs, head, 4*i, 4, &head);
  727. if (err) {
  728. return err;
  729. }
  730. }
  731. }
  732. *off = 4*skips;
  733. return 0;
  734. }
  735. static int lfs_index_traverse(lfs_t *lfs,
  736. lfs_block_t head, lfs_size_t size,
  737. int (*cb)(void*, lfs_block_t), void *data) {
  738. if (size == 0) {
  739. return 0;
  740. }
  741. lfs_off_t index = lfs_index(lfs, &(lfs_off_t){size-1});
  742. while (true) {
  743. int err = cb(data, head);
  744. if (err) {
  745. return err;
  746. }
  747. if (index == 0) {
  748. return 0;
  749. }
  750. err = lfs_bd_read(lfs, head, 0, 4, &head);
  751. if (err) {
  752. return err;
  753. }
  754. index -= 1;
  755. }
  756. return 0;
  757. }
  758. /// Top level file operations ///
  759. int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
  760. const char *path, int flags) {
  761. file->flags = flags;
  762. // Allocate entry for file if it doesn't exist
  763. // TODO check open files
  764. lfs_dir_t cwd;
  765. int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
  766. if (err) {
  767. return err;
  768. }
  769. err = lfs_dir_find(lfs, &cwd, &file->entry, &path);
  770. if (err && err != LFS_ERROR_NO_ENTRY) {
  771. return err;
  772. }
  773. if (err == LFS_ERROR_NO_ENTRY) {
  774. if (!(flags & LFS_O_CREAT)) {
  775. return LFS_ERROR_NO_ENTRY;
  776. }
  777. // create entry to remember name
  778. file->entry.d.type = LFS_TYPE_REG;
  779. file->entry.d.len = sizeof(file->entry.d) + strlen(path);
  780. file->entry.d.u.file.head = 0;
  781. file->entry.d.u.file.size = 0;
  782. err = lfs_dir_append(lfs, &cwd, &file->entry, path);
  783. if (err) {
  784. return err;
  785. }
  786. } else if (file->entry.d.type == LFS_TYPE_DIR) {
  787. return LFS_ERROR_IS_DIR;
  788. } else if (flags & LFS_O_EXCL) {
  789. return LFS_ERROR_EXISTS;
  790. }
  791. file->wpos = 0;
  792. file->wblock = 0;
  793. file->rpos = 0;
  794. file->rblock = 0;
  795. if (flags & LFS_O_TRUNC) {
  796. file->entry.d.u.file.head = 0;
  797. file->entry.d.u.file.size = 0;
  798. }
  799. if (flags & LFS_O_APPEND) {
  800. file->wpos = file->entry.d.u.file.size;
  801. }
  802. return 0;
  803. }
  804. int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
  805. return lfs_file_sync(lfs, file);
  806. }
  807. int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
  808. if (file->wblock == 0) {
  809. // already in sync, may be rdonly
  810. return 0;
  811. }
  812. // copy over anything after the file
  813. lfs_off_t oldrpos = file->rpos;
  814. lfs_off_t oldwpos = file->wpos;
  815. file->rpos = file->wpos;
  816. file->rblock = 0;
  817. while (file->wpos < file->entry.d.u.file.size) {
  818. uint8_t data;
  819. lfs_ssize_t res = lfs_file_read(lfs, file, &data, 1);
  820. if (res < 0) {
  821. return res;
  822. }
  823. res = lfs_file_write(lfs, file, &data, 1);
  824. if (res < 0) {
  825. return res;
  826. }
  827. }
  828. // actual file updates
  829. file->entry.d.u.file.head = file->wblock;
  830. file->entry.d.u.file.size = file->wpos;
  831. file->rpos = oldrpos;
  832. file->rblock = 0;
  833. file->wpos = oldwpos;
  834. file->wblock = 0;
  835. // update dir entry
  836. lfs_dir_t cwd;
  837. int err = lfs_dir_fetch(lfs, &cwd, file->entry.pair);
  838. if (err) {
  839. return err;
  840. }
  841. return lfs_dir_commit(lfs, &cwd, &file->entry, NULL);
  842. }
  843. lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
  844. const void *buffer, lfs_size_t size) {
  845. const uint8_t *data = buffer;
  846. lfs_size_t nsize = size;
  847. while (nsize > 0) {
  848. // check if we need a new block
  849. if (!file->wblock || file->woff == lfs->cfg->block_size) {
  850. int err = lfs_index_extend(lfs, file->wblock, file->wpos,
  851. &file->wblock, &file->woff);
  852. if (err) {
  853. return err;
  854. }
  855. }
  856. // program as much as we can in current block
  857. lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->woff);
  858. int err = lfs_bd_prog(lfs, file->wblock, file->woff, diff, data);
  859. if (err) {
  860. return err;
  861. }
  862. file->wpos += diff;
  863. file->woff += diff;
  864. data += diff;
  865. nsize -= diff;
  866. if (file->flags & LFS_O_APPEND) {
  867. file->entry.d.u.file.head = file->wblock;
  868. file->entry.d.u.file.size = file->wpos;
  869. }
  870. }
  871. if (file->flags & LFS_O_SYNC) {
  872. int err = lfs_file_sync(lfs, file);
  873. if (err) {
  874. return err;
  875. }
  876. }
  877. return size;
  878. }
  879. lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
  880. void *buffer, lfs_size_t size) {
  881. uint8_t *data = buffer;
  882. size = lfs_min(size, file->entry.d.u.file.size - file->rpos);
  883. lfs_size_t nsize = size;
  884. while (nsize > 0) {
  885. // check if we need a new block
  886. if (!file->rblock || file->roff == lfs->cfg->block_size) {
  887. int err = lfs_index_find(lfs,
  888. file->entry.d.u.file.head, file->entry.d.u.file.size,
  889. file->rpos, &file->rblock, &file->roff);
  890. if (err) {
  891. return err;
  892. }
  893. }
  894. // read as much as we can in current block
  895. lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->roff);
  896. int err = lfs_bd_read(lfs, file->rblock, file->roff, diff, data);
  897. if (err) {
  898. return err;
  899. }
  900. file->rpos += diff;
  901. file->roff += diff;
  902. data += diff;
  903. nsize -= diff;
  904. }
  905. return size;
  906. }
  907. /// Generic filesystem operations ///
  908. static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
  909. lfs->cfg = cfg;
  910. lfs->words = lfs->cfg->block_size / sizeof(uint32_t);
  911. // setup read cache
  912. lfs->rcache.off = -1;
  913. if (lfs->cfg->read_buffer) {
  914. lfs->rcache.buffer = lfs->cfg->read_buffer;
  915. } else {
  916. lfs->rcache.buffer = malloc(lfs->cfg->read_size);
  917. if (!lfs->rcache.buffer) {
  918. return LFS_ERROR_NO_MEM;
  919. }
  920. }
  921. // setup program cache
  922. lfs->pcache.off = -1;
  923. if (lfs->cfg->prog_buffer) {
  924. lfs->pcache.buffer = lfs->cfg->prog_buffer;
  925. } else {
  926. lfs->pcache.buffer = malloc(lfs->cfg->prog_size);
  927. if (!lfs->pcache.buffer) {
  928. return LFS_ERROR_NO_MEM;
  929. }
  930. }
  931. // setup lookahead
  932. if (lfs->cfg->lookahead_buffer) {
  933. lfs->free.lookahead = lfs->cfg->lookahead_buffer;
  934. } else {
  935. lfs->free.lookahead = malloc(lfs->cfg->lookahead/8);
  936. if (!lfs->free.lookahead) {
  937. return LFS_ERROR_NO_MEM;
  938. }
  939. }
  940. return 0;
  941. }
  942. static int lfs_deinit(lfs_t *lfs) {
  943. // Free allocated memory
  944. if (!lfs->cfg->read_buffer) {
  945. free(lfs->rcache.buffer);
  946. }
  947. if (!lfs->cfg->prog_buffer) {
  948. free(lfs->pcache.buffer);
  949. }
  950. return 0;
  951. }
  952. int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
  953. int err = lfs_init(lfs, cfg);
  954. if (err) {
  955. return err;
  956. }
  957. // Create free lookahead
  958. memset(lfs->free.lookahead, 0, lfs->cfg->lookahead/8);
  959. lfs->free.start = 0;
  960. lfs->free.off = 0;
  961. // Create superblock dir
  962. lfs_dir_t superdir;
  963. err = lfs_dir_alloc(lfs, &superdir);
  964. if (err) {
  965. return err;
  966. }
  967. // Write root directory
  968. lfs_dir_t root;
  969. err = lfs_dir_alloc(lfs, &root);
  970. if (err) {
  971. return err;
  972. }
  973. err = lfs_dir_commit(lfs, &root, NULL, NULL);
  974. if (err) {
  975. return err;
  976. }
  977. lfs->root[0] = root.pair[0];
  978. lfs->root[1] = root.pair[1];
  979. // Write superblocks
  980. lfs_superblock_t superblock = {
  981. .off = sizeof(superdir.d),
  982. .d.type = LFS_TYPE_SUPERBLOCK,
  983. .d.len = sizeof(superblock.d),
  984. .d.version = 0x00000001,
  985. .d.magic = {"littlefs"},
  986. .d.block_size = lfs->cfg->block_size,
  987. .d.block_count = lfs->cfg->block_count,
  988. .d.root = {lfs->root[0], lfs->root[1]},
  989. };
  990. superdir.d.tail[0] = root.pair[0];
  991. superdir.d.tail[1] = root.pair[1];
  992. superdir.d.size += sizeof(superdir.d);
  993. for (int i = 0; i < 2; i++) {
  994. // Write both pairs for extra safety, do some finagling to pretend
  995. // the superblock is an entry
  996. int err = lfs_dir_commit(lfs, &superdir,
  997. (const lfs_entry_t*)&superblock,
  998. (const struct lfs_disk_entry*)&superblock.d + 1);
  999. if (err) {
  1000. LFS_ERROR("Failed to write superblock at %d", superdir.pair[0]);
  1001. return err;
  1002. }
  1003. }
  1004. // sanity check that fetch works
  1005. err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1});
  1006. if (err) {
  1007. return err;
  1008. }
  1009. return lfs_deinit(lfs);
  1010. }
  1011. int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
  1012. int err = lfs_init(lfs, cfg);
  1013. if (err) {
  1014. return err;
  1015. }
  1016. // setup free lookahead
  1017. lfs->free.start = -lfs->cfg->lookahead;
  1018. lfs->free.off = lfs->cfg->lookahead;
  1019. // load superblock
  1020. lfs_dir_t dir;
  1021. lfs_superblock_t superblock;
  1022. err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1});
  1023. if (!err) {
  1024. err = lfs_bd_read(lfs, dir.pair[0],
  1025. sizeof(dir.d), sizeof(superblock.d), &superblock.d);
  1026. }
  1027. if (err == LFS_ERROR_CORRUPT ||
  1028. memcmp(superblock.d.magic, "littlefs", 8) != 0) {
  1029. LFS_ERROR("Invalid superblock at %d %d", dir.pair[0], dir.pair[1]);
  1030. return LFS_ERROR_CORRUPT;
  1031. }
  1032. if (superblock.d.version > 0x0000ffff) {
  1033. LFS_ERROR("Invalid version %d.%d\n",
  1034. 0xffff & (superblock.d.version >> 16),
  1035. 0xffff & (superblock.d.version >> 0));
  1036. }
  1037. lfs->root[0] = superblock.d.root[0];
  1038. lfs->root[1] = superblock.d.root[1];
  1039. return err;
  1040. }
  1041. int lfs_unmount(lfs_t *lfs) {
  1042. return lfs_deinit(lfs);
  1043. }
  1044. int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) {
  1045. // iterate over metadata pairs
  1046. lfs_dir_t dir;
  1047. lfs_file_t file;
  1048. lfs_block_t cwd[2] = {0, 1};
  1049. while (true) {
  1050. for (int i = 0; i < 2; i++) {
  1051. int err = cb(data, cwd[i]);
  1052. if (err) {
  1053. return err;
  1054. }
  1055. }
  1056. int err = lfs_dir_fetch(lfs, &dir, cwd);
  1057. if (err) {
  1058. return err;
  1059. }
  1060. // iterate over contents
  1061. while ((0x7fffffff & dir.d.size) >= dir.off + sizeof(file.entry.d)) {
  1062. int err = lfs_bd_read(lfs, dir.pair[0], dir.off,
  1063. sizeof(file.entry.d), &file.entry.d);
  1064. if (err) {
  1065. return err;
  1066. }
  1067. dir.off += file.entry.d.len;
  1068. if ((0xf & file.entry.d.type) == LFS_TYPE_REG) {
  1069. if (file.entry.d.u.file.size < lfs->cfg->block_size) {
  1070. int err = cb(data, file.entry.d.u.file.head);
  1071. if (err) {
  1072. return err;
  1073. }
  1074. } else {
  1075. int err = lfs_index_traverse(lfs,
  1076. file.entry.d.u.file.head,
  1077. file.entry.d.u.file.size,
  1078. cb, data);
  1079. if (err) {
  1080. return err;
  1081. }
  1082. }
  1083. }
  1084. }
  1085. cwd[0] = dir.d.tail[0];
  1086. cwd[1] = dir.d.tail[1];
  1087. if (!cwd[0]) {
  1088. return 0;
  1089. }
  1090. }
  1091. }
  1092. static int lfs_parent(lfs_t *lfs, const lfs_block_t dir[2]) {
  1093. // iterate over all directory directory entries
  1094. lfs_dir_t parent = {
  1095. .d.tail[0] = lfs->root[0],
  1096. .d.tail[1] = lfs->root[1],
  1097. };
  1098. while (parent.d.tail[0]) {
  1099. lfs_entry_t entry;
  1100. int err = lfs_dir_fetch(lfs, &parent, parent.d.tail);
  1101. if (err) {
  1102. return err;
  1103. }
  1104. while (true) {
  1105. int err = lfs_dir_next(lfs, &parent, &entry);
  1106. if (err && err != LFS_ERROR_NO_ENTRY) {
  1107. return err;
  1108. }
  1109. if (err == LFS_ERROR_NO_ENTRY) {
  1110. break;
  1111. }
  1112. if ((0xf & entry.d.type) == LFS_TYPE_DIR &&
  1113. lfs_paircmp(entry.d.u.dir, dir) == 0) {
  1114. return true;
  1115. }
  1116. }
  1117. }
  1118. return false;
  1119. }
  1120. int lfs_deorphan(lfs_t *lfs) {
  1121. // iterate over all directories
  1122. lfs_dir_t pdir;
  1123. lfs_dir_t cdir;
  1124. // skip root
  1125. int err = lfs_dir_fetch(lfs, &pdir, lfs->root);
  1126. if (err) {
  1127. return err;
  1128. }
  1129. while (pdir.d.tail[0]) {
  1130. int err = lfs_dir_fetch(lfs, &cdir, pdir.d.tail);
  1131. if (err) {
  1132. return err;
  1133. }
  1134. // check if we have a parent
  1135. int parent = lfs_parent(lfs, pdir.d.tail);
  1136. if (parent < 0) {
  1137. return parent;
  1138. }
  1139. if (!parent) {
  1140. // we are an orphan
  1141. LFS_INFO("Orphan %d %d", pdir.d.tail[0], pdir.d.tail[1]);
  1142. pdir.d.tail[0] = cdir.d.tail[0];
  1143. pdir.d.tail[1] = cdir.d.tail[1];
  1144. err = lfs_dir_commit(lfs, &pdir, NULL, NULL);
  1145. if (err) {
  1146. return err;
  1147. }
  1148. break;
  1149. }
  1150. memcpy(&pdir, &cdir, sizeof(pdir));
  1151. }
  1152. return 0;
  1153. }
  1154. int lfs_remove(lfs_t *lfs, const char *path) {
  1155. lfs_dir_t cwd;
  1156. int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
  1157. if (err) {
  1158. return err;
  1159. }
  1160. lfs_entry_t entry;
  1161. err = lfs_dir_find(lfs, &cwd, &entry, &path);
  1162. if (err) {
  1163. return err;
  1164. }
  1165. lfs_dir_t dir;
  1166. if (entry.d.type == LFS_TYPE_DIR) {
  1167. // must be empty before removal, checking size
  1168. // without masking top bit checks for any case where
  1169. // dir is not empty
  1170. int err = lfs_dir_fetch(lfs, &dir, entry.d.u.dir);
  1171. if (err) {
  1172. return err;
  1173. } else if (dir.d.size != sizeof(dir.d)) {
  1174. return LFS_ERROR_INVALID;
  1175. }
  1176. }
  1177. // remove the entry
  1178. err = lfs_dir_remove(lfs, &cwd, &entry);
  1179. if (err) {
  1180. return err;
  1181. }
  1182. // if we were a directory, just run a deorphan step, this should
  1183. // collect us, although is expensive
  1184. if (entry.d.type == LFS_TYPE_DIR) {
  1185. int err = lfs_deorphan(lfs);
  1186. if (err) {
  1187. return err;
  1188. }
  1189. }
  1190. return 0;
  1191. }
  1192. int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
  1193. // find old entry
  1194. lfs_dir_t oldcwd;
  1195. int err = lfs_dir_fetch(lfs, &oldcwd, lfs->root);
  1196. if (err) {
  1197. return err;
  1198. }
  1199. lfs_entry_t oldentry;
  1200. err = lfs_dir_find(lfs, &oldcwd, &oldentry, &oldpath);
  1201. if (err) {
  1202. return err;
  1203. }
  1204. // allocate new entry
  1205. lfs_dir_t newcwd;
  1206. err = lfs_dir_fetch(lfs, &newcwd, lfs->root);
  1207. if (err) {
  1208. return err;
  1209. }
  1210. lfs_entry_t preventry;
  1211. err = lfs_dir_find(lfs, &newcwd, &preventry, &newpath);
  1212. if (err && err != LFS_ERROR_NO_ENTRY) {
  1213. return err;
  1214. }
  1215. bool prevexists = (err != LFS_ERROR_NO_ENTRY);
  1216. // must have same type
  1217. if (prevexists && preventry.d.type != oldentry.d.type) {
  1218. return LFS_ERROR_INVALID;
  1219. }
  1220. lfs_dir_t dir;
  1221. if (prevexists && preventry.d.type == LFS_TYPE_DIR) {
  1222. // must be empty before removal, checking size
  1223. // without masking top bit checks for any case where
  1224. // dir is not empty
  1225. int err = lfs_dir_fetch(lfs, &dir, preventry.d.u.dir);
  1226. if (err) {
  1227. return err;
  1228. } else if (dir.d.size != sizeof(dir.d)) {
  1229. return LFS_ERROR_INVALID;
  1230. }
  1231. }
  1232. // move to new location
  1233. lfs_entry_t newentry = preventry;
  1234. newentry.d = oldentry.d;
  1235. newentry.d.len = sizeof(newentry.d) + strlen(newpath);
  1236. if (prevexists) {
  1237. int err = lfs_dir_commit(lfs, &newcwd, &newentry, newpath);
  1238. if (err) {
  1239. return err;
  1240. }
  1241. } else {
  1242. int err = lfs_dir_append(lfs, &newcwd, &newentry, newpath);
  1243. if (err) {
  1244. return err;
  1245. }
  1246. }
  1247. // fetch again in case newcwd == oldcwd
  1248. // TODO handle this better?
  1249. err = lfs_dir_fetch(lfs, &oldcwd, oldcwd.pair);
  1250. if (err) {
  1251. return err;
  1252. }
  1253. err = lfs_dir_find(lfs, &oldcwd, &oldentry, &oldpath);
  1254. if (err) {
  1255. return err;
  1256. }
  1257. // remove from old location
  1258. err = lfs_dir_remove(lfs, &oldcwd, &oldentry);
  1259. if (err) {
  1260. return err;
  1261. }
  1262. // if we were a directory, just run a deorphan step, this should
  1263. // collect us, although is expensive
  1264. if (prevexists && preventry.d.type == LFS_TYPE_DIR) {
  1265. int err = lfs_deorphan(lfs);
  1266. if (err) {
  1267. return err;
  1268. }
  1269. }
  1270. return 0;
  1271. }
  1272. int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
  1273. lfs_dir_t cwd;
  1274. int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
  1275. if (err) {
  1276. return err;
  1277. }
  1278. lfs_entry_t entry;
  1279. err = lfs_dir_find(lfs, &cwd, &entry, &path);
  1280. if (err) {
  1281. return err;
  1282. }
  1283. // TODO abstract out info assignment
  1284. memset(info, 0, sizeof(*info));
  1285. info->type = entry.d.type & 0xff;
  1286. if (info->type == LFS_TYPE_REG) {
  1287. info->size = entry.d.u.file.size;
  1288. }
  1289. err = lfs_bd_read(lfs, cwd.pair[0], entry.off + sizeof(entry.d),
  1290. entry.d.len - sizeof(entry.d), info->name);
  1291. if (err) {
  1292. return err;
  1293. }
  1294. return 0;
  1295. }