@@ -310,7 +310,7 @@ static int lfs_pair_commit(lfs_t *lfs, lfs_block_t pair[2],
310
310
311
311
/// Directory operations ///
312
312
313
- static int lfs_dir_create (lfs_t * lfs , lfs_dir_t * dir , lfs_block_t parent [2 ]) {
313
+ static int lfs_dir_alloc (lfs_t * lfs , lfs_dir_t * dir , lfs_block_t parent [2 ]) {
314
314
// Allocate pair of dir blocks
315
315
for (int i = 0 ; i < 2 ; i ++ ) {
316
316
int err = lfs_alloc (lfs , & dir -> pair [i ]);
@@ -328,7 +328,7 @@ static int lfs_dir_create(lfs_t *lfs, lfs_dir_t *dir, lfs_block_t parent[2]) {
328
328
dir -> d .rev += 1 ;
329
329
330
330
// Calculate total size
331
- dir -> d .size = sizeof (dir -> d ) + 2 * sizeof ( struct lfs_disk_entry ) + 3 ;
331
+ dir -> d .size = sizeof (dir -> d );
332
332
dir -> off = sizeof (dir -> d );
333
333
334
334
// Other defaults
@@ -337,27 +337,35 @@ static int lfs_dir_create(lfs_t *lfs, lfs_dir_t *dir, lfs_block_t parent[2]) {
337
337
dir -> d .free = lfs -> free ;
338
338
339
339
// Write out to memory
340
- return lfs_pair_commit (lfs , dir -> pair ,
341
- 5 , (struct lfs_commit_region []){
342
- {0 , sizeof (dir -> d ), & dir -> d },
343
- {sizeof (dir -> d ), sizeof (struct lfs_disk_entry ),
344
- & (struct lfs_disk_entry ){
345
- .type = LFS_TYPE_DIR ,
346
- .len = sizeof (struct lfs_disk_entry )+1 ,
347
- .u .dir [0 ] = dir -> pair [0 ],
348
- .u .dir [1 ] = dir -> pair [1 ],
349
- }},
350
- {sizeof (dir -> d )+ sizeof (struct lfs_disk_entry ), 1 , "." },
351
- {sizeof (dir -> d )+ sizeof (struct lfs_disk_entry )+1 ,
352
- sizeof (struct lfs_disk_entry ),
353
- & (struct lfs_disk_entry ){
354
- .type = LFS_TYPE_DIR ,
355
- .len = sizeof (struct lfs_disk_entry )+2 ,
356
- .u .dir [0 ] = parent ? parent [0 ] : dir -> pair [0 ],
357
- .u .dir [1 ] = parent ? parent [1 ] : dir -> pair [1 ],
358
- }},
359
- {sizeof (dir -> d )+ 2 * sizeof (struct lfs_disk_entry )+1 , 2 , ".." },
360
- });
340
+ if (!parent ) {
341
+ return lfs_pair_commit (lfs , dir -> pair ,
342
+ 1 , (struct lfs_commit_region []){
343
+ {0 , sizeof (dir -> d ), & dir -> d }
344
+ });
345
+ } else {
346
+ dir -> d .size += 2 * sizeof (struct lfs_disk_entry ) + 3 ;
347
+ return lfs_pair_commit (lfs , dir -> pair ,
348
+ 5 , (struct lfs_commit_region []){
349
+ {0 , sizeof (dir -> d ), & dir -> d },
350
+ {sizeof (dir -> d ), sizeof (struct lfs_disk_entry ),
351
+ & (struct lfs_disk_entry ){
352
+ .type = LFS_TYPE_DIR ,
353
+ .len = sizeof (struct lfs_disk_entry )+1 ,
354
+ .u .dir [0 ] = dir -> pair [0 ],
355
+ .u .dir [1 ] = dir -> pair [1 ],
356
+ }},
357
+ {sizeof (dir -> d )+ sizeof (struct lfs_disk_entry ), 1 , "." },
358
+ {sizeof (dir -> d )+ sizeof (struct lfs_disk_entry )+1 ,
359
+ sizeof (struct lfs_disk_entry ),
360
+ & (struct lfs_disk_entry ){
361
+ .type = LFS_TYPE_DIR ,
362
+ .len = sizeof (struct lfs_disk_entry )+2 ,
363
+ .u .dir [0 ] = parent [0 ] ? parent [0 ] : dir -> pair [0 ],
364
+ .u .dir [1 ] = parent [1 ] ? parent [1 ] : dir -> pair [1 ],
365
+ }},
366
+ {sizeof (dir -> d )+ 2 * sizeof (struct lfs_disk_entry )+1 , 2 , ".." },
367
+ });
368
+ }
361
369
}
362
370
363
371
static int lfs_dir_fetch (lfs_t * lfs , lfs_dir_t * dir , lfs_block_t pair [2 ]) {
@@ -373,13 +381,20 @@ static int lfs_dir_fetch(lfs_t *lfs, lfs_dir_t *dir, lfs_block_t pair[2]) {
373
381
374
382
static int lfs_dir_next (lfs_t * lfs , lfs_dir_t * dir , lfs_entry_t * entry ) {
375
383
while (true) {
376
- // TODO iterate down list
377
- entry -> dir [0 ] = dir -> pair [0 ];
378
- entry -> dir [1 ] = dir -> pair [1 ];
379
- entry -> off = dir -> off ;
380
-
381
384
if (dir -> d .size - dir -> off < sizeof (entry -> d )) {
382
- return LFS_ERROR_NO_ENTRY ;
385
+ if (!dir -> d .tail [0 ]) {
386
+ entry -> dir [0 ] = dir -> pair [0 ];
387
+ entry -> dir [1 ] = dir -> pair [1 ];
388
+ entry -> off = dir -> off ;
389
+ return LFS_ERROR_NO_ENTRY ;
390
+ }
391
+
392
+ int err = lfs_dir_fetch (lfs , dir , dir -> d .tail );
393
+ if (err ) {
394
+ return err ;
395
+ }
396
+
397
+ dir -> off = sizeof (dir -> d );
383
398
}
384
399
385
400
int err = lfs_bd_read (lfs , dir -> pair [0 ], dir -> off ,
@@ -389,51 +404,92 @@ static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
389
404
}
390
405
391
406
dir -> off += entry -> d .len ;
392
-
393
- // Skip any unknown entries
394
- if ((entry -> d .type & 0xf ) == 1 || (entry -> d .type & 0xf ) == 2 ) {
407
+ if (entry -> d .type == LFS_TYPE_REG || entry -> d .type == LFS_TYPE_DIR ) {
408
+ entry -> dir [0 ] = dir -> pair [0 ];
409
+ entry -> dir [1 ] = dir -> pair [1 ];
410
+ entry -> off = dir -> off - entry -> d .len ;
395
411
return 0 ;
396
412
}
397
413
}
398
414
}
399
415
400
416
static int lfs_dir_find (lfs_t * lfs , lfs_dir_t * dir ,
401
- const char * path , lfs_entry_t * entry ) {
402
- // TODO follow directories
403
- lfs_size_t pathlen = strcspn (path , "/" );
417
+ const char * * path , lfs_entry_t * entry ) {
404
418
while (true) {
405
- int err = lfs_dir_next (lfs , dir , entry );
406
- if (err ) {
407
- return err ;
419
+ const char * pathname = * path ;
420
+ lfs_size_t pathlen = strcspn (pathname , "/" );
421
+ while (true) {
422
+ int err = lfs_dir_next (lfs , dir , entry );
423
+ if (err ) {
424
+ return err ;
425
+ }
426
+
427
+ if (entry -> d .len - sizeof (entry -> d ) != pathlen ) {
428
+ continue ;
429
+ }
430
+
431
+ int ret = lfs_bd_cmp (lfs , entry -> dir [0 ],
432
+ entry -> off + sizeof (entry -> d ), pathlen , pathname );
433
+ if (ret < 0 ) {
434
+ return ret ;
435
+ }
436
+
437
+ // Found match
438
+ if (ret == true) {
439
+ break ;
440
+ }
408
441
}
409
442
410
- if (entry -> d .len - sizeof (entry -> d ) != pathlen ) {
411
- continue ;
443
+ pathname += pathlen ;
444
+ pathname += strspn (pathname , "/" );
445
+ if (pathname [0 ] == '\0' ) {
446
+ return 0 ;
412
447
}
413
448
414
- int ret = lfs_bd_cmp (lfs , entry -> dir [0 ],
415
- entry -> off + sizeof (entry -> d ), pathlen , path );
416
- if (ret < 0 ) {
417
- return ret ;
449
+ if (entry -> d .type != LFS_TYPE_DIR ) {
450
+ return LFS_ERROR_NOT_DIR ;
418
451
}
419
452
420
- // Found match
421
- if (ret == true ) {
422
- return 0 ;
453
+ int err = lfs_dir_fetch ( lfs , dir , entry -> d . u . dir );
454
+ if (err ) {
455
+ return err ;
423
456
}
457
+
458
+ * path = pathname ;
424
459
}
460
+
461
+ return 0 ;
425
462
}
426
463
427
464
static int lfs_dir_append (lfs_t * lfs , lfs_dir_t * dir ,
428
- const char * path , lfs_entry_t * entry ) {
465
+ const char * * path , lfs_entry_t * entry ) {
429
466
int err = lfs_dir_find (lfs , dir , path , entry );
430
467
if (err != LFS_ERROR_NO_ENTRY ) {
431
468
return err ? err : LFS_ERROR_EXISTS ;
432
469
}
433
470
434
471
// Check if we fit
435
- if (dir -> d .size + strlen (path ) > lfs -> block_size - 4 ) {
436
- return -1 ; // TODO make fit
472
+ if (dir -> d .size + sizeof (entry -> d ) + strlen (* path ) > lfs -> block_size - 4 ) {
473
+ lfs_dir_t olddir ;
474
+ memcpy (& olddir , dir , sizeof (olddir ));
475
+
476
+ int err = lfs_dir_alloc (lfs , dir , 0 );
477
+ if (err ) {
478
+ return err ;
479
+ }
480
+
481
+ entry -> dir [0 ] = dir -> pair [0 ];
482
+ entry -> dir [1 ] = dir -> pair [1 ];
483
+ entry -> off = dir -> off ;
484
+
485
+ olddir .d .rev += 1 ;
486
+ olddir .d .tail [0 ] = dir -> pair [0 ];
487
+ olddir .d .tail [1 ] = dir -> pair [1 ];
488
+ olddir .d .free = lfs -> free ;
489
+ return lfs_pair_commit (lfs , olddir .pair ,
490
+ 1 , (struct lfs_commit_region []){
491
+ {0 , sizeof (olddir .d ), & olddir .d }
492
+ });
437
493
}
438
494
439
495
return 0 ;
@@ -448,14 +504,14 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
448
504
}
449
505
450
506
lfs_entry_t entry ;
451
- err = lfs_dir_append (lfs , & cwd , path , & entry );
507
+ err = lfs_dir_append (lfs , & cwd , & path , & entry );
452
508
if (err ) {
453
509
return err ;
454
510
}
455
511
456
512
// Build up new directory
457
513
lfs_dir_t dir ;
458
- err = lfs_dir_create (lfs , & dir , cwd .pair );
514
+ err = lfs_dir_alloc (lfs , & dir , cwd .pair );
459
515
if (err ) {
460
516
return err ;
461
517
}
@@ -494,7 +550,7 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
494
550
}
495
551
496
552
lfs_entry_t entry ;
497
- err = lfs_dir_find (lfs , dir , path , & entry );
553
+ err = lfs_dir_find (lfs , dir , & path , & entry );
498
554
if (err ) {
499
555
return err ;
500
556
} else if (entry .d .type != LFS_TYPE_DIR ) {
@@ -546,12 +602,12 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
546
602
}
547
603
548
604
if (flags & LFS_O_CREAT ) {
549
- err = lfs_dir_append (lfs , & cwd , path , & file -> entry );
605
+ err = lfs_dir_append (lfs , & cwd , & path , & file -> entry );
550
606
if (err && err != LFS_ERROR_EXISTS ) {
551
607
return err ;
552
608
}
553
609
} else {
554
- err = lfs_dir_find (lfs , & cwd , path , & file -> entry );
610
+ err = lfs_dir_find (lfs , & cwd , & path , & file -> entry );
555
611
if (err ) {
556
612
return err ;
557
613
}
@@ -789,11 +845,11 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *config) {
789
845
790
846
// Create free list
791
847
lfs -> free .begin = 2 ;
792
- lfs -> free .end = lfs -> block_count ;
848
+ lfs -> free .end = lfs -> block_count - 1 ;
793
849
794
850
// Write root directory
795
851
lfs_dir_t root ;
796
- err = lfs_dir_create (lfs , & root , 0 );
852
+ err = lfs_dir_alloc (lfs , & root , ( lfs_block_t [ 2 ]){ 0 , 0 } );
797
853
if (err ) {
798
854
return err ;
799
855
}
0 commit comments