Skip to content

Commit c5c5e0a

Browse files
committed
Add lfs-tool
1 parent 35ee9f8 commit c5c5e0a

2 files changed

Lines changed: 266 additions & 0 deletions

File tree

tools/lfs-tool/Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
LFS_PATH = ../../lib/littlefs
2+
3+
lfs-tool: main.c
4+
$(CC) $(CFLAGS) -I$(LFS_PATH) -o lfs-tool main.c $(LFS_PATH)/lfs.c $(LFS_PATH)/lfs_util.c
5+
6+
install: lfs-tool
7+
sudo install lfs-tool /usr/local/bin

tools/lfs-tool/main.c

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include <stdint.h>
5+
#include "../../lib/littlefs/lfs.h"
6+
7+
/* ---------------- Configuration ---------------- */
8+
9+
#define BLOCK_SIZE 4096
10+
#define BLOCK_COUNT 844
11+
#define CACHE_SIZE 4096
12+
#define LOOKAHEAD_SIZE 16
13+
14+
#define DEFAULT_OFFSET 0xB4000
15+
16+
static FILE *image;
17+
static uint64_t fs_offset = DEFAULT_OFFSET;
18+
19+
const char *get_lfs_error(int err);
20+
21+
/* ---------------- Block device callbacks ---------------- */
22+
23+
static int block_read(const struct lfs_config *c,
24+
lfs_block_t block,
25+
lfs_off_t off,
26+
void *buffer,
27+
lfs_size_t size)
28+
{
29+
uint64_t addr = fs_offset +
30+
(uint64_t)block * c->block_size + off;
31+
fseek(image, addr, SEEK_SET);
32+
fread(buffer, 1, size, image);
33+
return 0;
34+
}
35+
36+
static int block_prog(const struct lfs_config *c,
37+
lfs_block_t block,
38+
lfs_off_t off,
39+
const void *buffer,
40+
lfs_size_t size)
41+
{
42+
uint64_t addr = fs_offset +
43+
(uint64_t)block * c->block_size + off;
44+
fseek(image, addr, SEEK_SET);
45+
fwrite(buffer, 1, size, image);
46+
fflush(image);
47+
return 0;
48+
}
49+
50+
static int block_erase(const struct lfs_config *c,
51+
lfs_block_t block)
52+
{
53+
uint8_t buf[BLOCK_SIZE];
54+
memset(buf, 0xFF, sizeof(buf));
55+
56+
uint64_t addr = fs_offset +
57+
(uint64_t)block * c->block_size;
58+
fseek(image, addr, SEEK_SET);
59+
fwrite(buf, 1, sizeof(buf), image);
60+
fflush(image);
61+
return 0;
62+
}
63+
64+
static int block_sync(const struct lfs_config *c)
65+
{
66+
fflush(image);
67+
return 0;
68+
}
69+
70+
/* ---------------- Main ---------------- */
71+
72+
int main(int argc, char *argv[])
73+
{
74+
if (argc < 4)
75+
{
76+
printf("Usage:\n");
77+
printf(" %s <image.bin> [--offset bytes] read <path>\n", argv[0]);
78+
printf(" %s <image.bin> [--offset bytes] write <path>\n", argv[0]);
79+
printf(" %s <image.bin> [--offset bytes] ls <path>\n", argv[0]);
80+
printf(" %s <image.bin> [--offset bytes] mkdir <path>\n", argv[0]);
81+
return 1;
82+
}
83+
84+
int argi = 1;
85+
const char *image_path = argv[argi++];
86+
87+
if (argi + 1 < argc && strcmp(argv[argi], "--offset") == 0)
88+
{
89+
fs_offset = strtoull(argv[argi + 1], NULL, 0);
90+
argi += 2;
91+
}
92+
93+
const char *command = argv[argi++];
94+
const char *path = argv[argi];
95+
96+
image = fopen(image_path, "rb+");
97+
if (!image)
98+
{
99+
perror("Failed to open image");
100+
return 1;
101+
}
102+
103+
lfs_t lfs;
104+
struct lfs_config cfg = {
105+
.read = block_read,
106+
.prog = block_prog,
107+
.erase = block_erase,
108+
.sync = block_sync,
109+
110+
.read_size = 16,
111+
.prog_size = 16,
112+
.block_size = BLOCK_SIZE,
113+
.block_count = BLOCK_COUNT,
114+
.cache_size = CACHE_SIZE,
115+
.lookahead_size = LOOKAHEAD_SIZE,
116+
.block_cycles = 500,
117+
};
118+
int res;
119+
120+
if ((res = lfs_mount(&lfs, &cfg)) != 0)
121+
{
122+
fprintf(stderr, "Failed to mount: %s\n", get_lfs_error(res));
123+
fclose(image);
124+
return 1;
125+
}
126+
127+
if (strcmp(command, "read") == 0)
128+
{
129+
lfs_file_t file;
130+
if ((res = lfs_file_open(&lfs, &file, path, LFS_O_RDONLY)) == 0)
131+
{
132+
char buf[256];
133+
int n;
134+
while ((n = lfs_file_read(&lfs, &file, buf, sizeof(buf))) > 0)
135+
{
136+
fwrite(buf, 1, n, stdout);
137+
}
138+
139+
if ((res = lfs_file_close(&lfs, &file)) != 0)
140+
{
141+
fprintf(stderr, "Failed to close file: %s\n", get_lfs_error(res));
142+
}
143+
}
144+
else
145+
{
146+
fprintf(stderr, "Failed to open file: %s\n", get_lfs_error(res));
147+
}
148+
}
149+
else if (strcmp(command, "write") == 0)
150+
{
151+
lfs_file_t file;
152+
if (lfs_file_open(&lfs, &file, path,
153+
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) == 0)
154+
{
155+
char buf[256];
156+
size_t n;
157+
while ((n = fread(buf, 1, sizeof(buf), stdin)) > 0)
158+
{
159+
lfs_file_write(&lfs, &file, buf, n);
160+
}
161+
162+
if ((res = lfs_file_close(&lfs, &file)) != 0)
163+
{
164+
fprintf(stderr, "Failed to close file: %s\n", get_lfs_error(res));
165+
}
166+
else
167+
{
168+
printf("Write successful\n");
169+
}
170+
}
171+
else
172+
{
173+
fprintf(stderr, "Failed to open file: %s\n", get_lfs_error(res));
174+
}
175+
}
176+
else if (strcmp(command, "ls") == 0)
177+
{
178+
lfs_dir_t dir;
179+
struct lfs_info info;
180+
181+
if ((res = lfs_dir_open(&lfs, &dir, path)) == 0)
182+
{
183+
while ((res = lfs_dir_read(&lfs, &dir, &info)) > 0)
184+
{
185+
printf("%s\n", info.name);
186+
}
187+
188+
if (res < 0)
189+
{
190+
fprintf(stderr, "Failed to read directory: %s\n", get_lfs_error(res));
191+
}
192+
193+
if ((res = lfs_dir_close(&lfs, &dir)) != 0)
194+
{
195+
fprintf(stderr, "Failed to close directory: %s\n", get_lfs_error(res));
196+
}
197+
}
198+
else
199+
{
200+
fprintf(stderr, "Failed to open directory: %s\n", get_lfs_error(res));
201+
}
202+
}
203+
else if (strcmp(command, "mkdir") == 0)
204+
{
205+
if ((res = lfs_mkdir(&lfs, path)) != 0)
206+
{
207+
fprintf(stderr, "Failed to create directory: %s\n", get_lfs_error(res));
208+
}
209+
else
210+
{
211+
printf("Directory created successfully\n");
212+
}
213+
}
214+
else
215+
{
216+
fprintf(stderr, "Unknown command: %s\n", command);
217+
}
218+
219+
lfs_unmount(&lfs);
220+
fclose(image);
221+
return 0;
222+
}
223+
224+
const char *get_lfs_error(int err)
225+
{
226+
switch (err)
227+
{
228+
case LFS_ERR_IO:
229+
return "Error during device operation";
230+
case LFS_ERR_CORRUPT:
231+
return "Corrupted";
232+
case LFS_ERR_NOENT:
233+
return "No directory entry";
234+
case LFS_ERR_EXIST:
235+
return "Entry already exists";
236+
case LFS_ERR_NOTDIR:
237+
return "Entry is not a dir";
238+
case LFS_ERR_ISDIR:
239+
return "Entry is a dir";
240+
case LFS_ERR_NOTEMPTY:
241+
return "Dir is not empty";
242+
case LFS_ERR_BADF:
243+
return "Bad file number";
244+
case LFS_ERR_FBIG:
245+
return "File too large";
246+
case LFS_ERR_INVAL:
247+
return "Invalid parameter";
248+
case LFS_ERR_NOSPC:
249+
return "No space left on device";
250+
case LFS_ERR_NOMEM:
251+
return "No more memory available";
252+
case LFS_ERR_NOATTR:
253+
return "No data/attr available";
254+
case LFS_ERR_NAMETOOLONG:
255+
return "File name too long";
256+
}
257+
258+
return "Unknown error";
259+
}

0 commit comments

Comments
 (0)