1 4338ef2e 2024-05-18 benni #include <fuse_opt.h>
2 4338ef2e 2024-05-18 benni #include <libgen.h>
3 4338ef2e 2024-05-18 benni #include <unistd.h>
4 4338ef2e 2024-05-18 benni #include <string.h>
5 4338ef2e 2024-05-18 benni #include <stdlib.h>
6 4338ef2e 2024-05-18 benni #include <stdio.h>
7 4338ef2e 2024-05-18 benni #include <errno.h>
8 4338ef2e 2024-05-18 benni #include <fuse.h>
9 4338ef2e 2024-05-18 benni #include <err.h>
10 4338ef2e 2024-05-18 benni #include "sufs.h"
12 4338ef2e 2024-05-18 benni #define MIN(a, b) ((a) < (b) ? (a) : (b))
13 4338ef2e 2024-05-18 benni #define MAX(a, b) ((a) > (b) ? (a) : (b))
16 4338ef2e 2024-05-18 benni KEY_VERSION,
20 4338ef2e 2024-05-18 benni static const struct fuse_opt opts[] = {
21 4338ef2e 2024-05-18 benni FUSE_OPT_KEY("-V", KEY_VERSION),
22 4338ef2e 2024-05-18 benni FUSE_OPT_KEY("-h", KEY_HELP),
23 4338ef2e 2024-05-18 benni FUSE_OPT_END
25 4338ef2e 2024-05-18 benni static struct sufs_superblock sb;
26 4338ef2e 2024-05-18 benni static char *buffer, *dbuffer;
27 4338ef2e 2024-05-18 benni static int fd;
29 4338ef2e 2024-05-18 benni static void write_inode (uint64_t, const struct sufs_inode *);
30 4338ef2e 2024-05-18 benni static struct sufs_inode read_inode (uint64_t ino);
32 4338ef2e 2024-05-18 benni void read_block (uint64_t b, char *d)
34 4338ef2e 2024-05-18 benni printf ("read_block(%zu);\n", (size_t)b);
35 4338ef2e 2024-05-18 benni if (lseek (fd, b * sb.bsize, SEEK_SET) < 0)
36 4338ef2e 2024-05-18 benni err (1, "read_block(): lseek()");
37 4338ef2e 2024-05-18 benni if (read (fd, d, sb.bsize) != sb.bsize)
38 4338ef2e 2024-05-18 benni err (1, "read_block(): read()");
41 4338ef2e 2024-05-18 benni void write_block (uint64_t b, const char *d)
43 4338ef2e 2024-05-18 benni printf ("write_block(%zu);\n", (size_t)b);
44 4338ef2e 2024-05-18 benni if (lseek (fd, b * sb.bsize, SEEK_SET) < 0)
45 4338ef2e 2024-05-18 benni err (1, "write_block(): lseek()");
46 4338ef2e 2024-05-18 benni if (write (fd, d, sb.bsize) != sb.bsize)
47 4338ef2e 2024-05-18 benni err (1, "write_block(): read()");
50 4338ef2e 2024-05-18 benni static uint64_t alloc_bitmap (uint64_t begin, uint64_t len)
52 4338ef2e 2024-05-18 benni uint8_t *p;
54 4338ef2e 2024-05-18 benni for (uint64_t i = 0; i < len; i += sb.bsize) {
55 4338ef2e 2024-05-18 benni read_block (begin + i, buffer);
56 4338ef2e 2024-05-18 benni for (uint32_t j = 0; j < MIN (len, sb.bsize); ++j) {
57 4338ef2e 2024-05-18 benni p = buffer + j;
58 4338ef2e 2024-05-18 benni if (*p == 0)
61 4338ef2e 2024-05-18 benni for (unsigned k = 0; k < 8; ++k) {
62 4338ef2e 2024-05-18 benni uint8_t mask = 1 << k;
63 4338ef2e 2024-05-18 benni if ((*p & mask) == mask) {
64 4338ef2e 2024-05-18 benni printf ("i=%zu, j=%u, k=%u\n", (size_t)i, j, k);
65 4338ef2e 2024-05-18 benni *p &= ~mask;
66 4338ef2e 2024-05-18 benni write_block (begin + i, buffer);
67 4338ef2e 2024-05-18 benni return (i + j) * 8 + k;
76 4338ef2e 2024-05-18 benni static void free_bitmap (uint64_t begin, uint64_t idx)
78 4338ef2e 2024-05-18 benni uint64_t blkno;
79 4338ef2e 2024-05-18 benni unsigned off, bit;
81 4338ef2e 2024-05-18 benni blkno = begin + idx / (8 * sb.bsize);
82 4338ef2e 2024-05-18 benni off = (idx / 8) % sb.bsize;
83 4338ef2e 2024-05-18 benni bit = idx % 8;
85 4338ef2e 2024-05-18 benni printf ("free_bitmap(%zu, %zu, %zu, %u, %u);\n", (size_t)begin, (size_t)idx, (size_t)blkno, off, bit);
87 4338ef2e 2024-05-18 benni read_block (blkno, buffer);
88 4338ef2e 2024-05-18 benni ((uint8_t *)buffer)[off] |= 1 << bit;
89 4338ef2e 2024-05-18 benni write_block (blkno, buffer);
92 4338ef2e 2024-05-18 benni static uint64_t alloc_inode (void)
94 4338ef2e 2024-05-18 benni uint64_t ino = alloc_bitmap (sb.ibmoff, sb.nino);
96 4338ef2e 2024-05-18 benni printf ("alloc_inode(): %zu\n", (size_t)ino);
98 4338ef2e 2024-05-18 benni return ino;
101 4338ef2e 2024-05-18 benni static void free_dblock (uint64_t blkno)
103 4338ef2e 2024-05-18 benni free_bitmap (sb.dbmoff, blkno - sb.doff);
106 4338ef2e 2024-05-18 benni static void free_inode (uint64_t ino)
108 4338ef2e 2024-05-18 benni struct sufs_inode in;
110 4338ef2e 2024-05-18 benni printf ("free_inode(%zu);\n", (size_t)ino);
112 4338ef2e 2024-05-18 benni in = read_inode (ino);
114 4338ef2e 2024-05-18 benni --in.nlink;
116 4338ef2e 2024-05-18 benni if (in.nlink != 0) {
117 4338ef2e 2024-05-18 benni write_inode (ino, &in);
121 4338ef2e 2024-05-18 benni for (uint64_t i = 0; i < MIN (in.blocks, SUFS_NDIRECT); ++i) {
122 4338ef2e 2024-05-18 benni free_dblock (in.direct[i]);
125 4338ef2e 2024-05-18 benni if (in.blocks >= SUFS_NDIRECT)
126 4338ef2e 2024-05-18 benni errx (1, "free_inode(): TODO: indirect blocks");
128 4338ef2e 2024-05-18 benni free_bitmap (sb.ibmoff, ino);
131 4338ef2e 2024-05-18 benni static uint64_t alloc_dblock (void)
133 4338ef2e 2024-05-18 benni uint64_t b = alloc_bitmap (sb.dbmoff, sb.ndata) + sb.doff;
134 4338ef2e 2024-05-18 benni memset (buffer, 0, sb.bsize);
135 4338ef2e 2024-05-18 benni write_block (b, buffer);
136 4338ef2e 2024-05-18 benni printf ("alloc_dblock(): %zu\n", (size_t)b);
140 4338ef2e 2024-05-18 benni uint64_t resolve_inode_block (const struct sufs_inode *in, uint64_t blkno)
142 4338ef2e 2024-05-18 benni const size_t pbp = sb.bsize / sizeof (uint64_t);
143 4338ef2e 2024-05-18 benni volatile uint64_t *tmp = (volatile uint64_t *)buffer;
144 4338ef2e 2024-05-18 benni uint64_t i;
146 4338ef2e 2024-05-18 benni if (blkno < SUFS_NDIRECT) {
147 4338ef2e 2024-05-18 benni return in->direct[blkno];
148 4338ef2e 2024-05-18 benni } else if (blkno < (SUFS_NDIRECT + pbp)) {
149 4338ef2e 2024-05-18 benni read_block (in->indir[0], buffer);
150 4338ef2e 2024-05-18 benni return tmp[blkno - SUFS_NDIRECT];
151 4338ef2e 2024-05-18 benni } else if (blkno < (SUFS_NDIRECT + pbp * pbp)) {
152 4338ef2e 2024-05-18 benni read_block (in->indir[1], buffer);
153 4338ef2e 2024-05-18 benni i = blkno - SUFS_NDIRECT - pbp;
154 4338ef2e 2024-05-18 benni read_block (tmp[i / pbp], buffer);
155 4338ef2e 2024-05-18 benni return tmp[i % pbp];
156 4338ef2e 2024-05-18 benni } else if (blkno < (SUFS_NDIRECT + pbp * pbp * pbp)) {
157 4338ef2e 2024-05-18 benni read_block (in->indir[2], buffer);
158 4338ef2e 2024-05-18 benni i = blkno - SUFS_NDIRECT - pbp * pbp;
159 4338ef2e 2024-05-18 benni read_block (tmp[i / pbp / pbp], buffer);
160 4338ef2e 2024-05-18 benni read_block (tmp[i / pbp % pbp], buffer);
161 4338ef2e 2024-05-18 benni return tmp[i % pbp];
163 4338ef2e 2024-05-18 benni errx (1, "resolve_inode_block(): inode out of range");
167 4338ef2e 2024-05-18 benni void free_block (uint64_t block)
169 4338ef2e 2024-05-18 benni if (block == 0)
172 4338ef2e 2024-05-18 benni errx (1, "free_block(): TODO");
175 4338ef2e 2024-05-18 benni void map_inode (uint64_t ino, struct sufs_inode *in, uint64_t blkno, uint64_t block)
177 4338ef2e 2024-05-18 benni const size_t pbp = sb.bsize / sizeof (uint64_t);
178 4338ef2e 2024-05-18 benni volatile uint64_t *tmp = (volatile uint64_t *)buffer;
179 4338ef2e 2024-05-18 benni uint64_t i;
181 4338ef2e 2024-05-18 benni printf ("map_inode(%zu, %zu, %zu);\n", (size_t)ino, (size_t)blkno, (size_t)block);
183 4338ef2e 2024-05-18 benni if (blkno < SUFS_NDIRECT) {
184 4338ef2e 2024-05-18 benni free_block (in->direct[blkno]);
185 4338ef2e 2024-05-18 benni in->direct[blkno] = block;
186 4338ef2e 2024-05-18 benni } else if (blkno < (SUFS_NDIRECT + pbp)) {
187 4338ef2e 2024-05-18 benni if (in->indir[0] == 0) {
188 4338ef2e 2024-05-18 benni in->indir[0] = alloc_dblock ();
189 4338ef2e 2024-05-18 benni write_inode (ino, in);
191 4338ef2e 2024-05-18 benni read_block (in->indir[0], buffer);
192 4338ef2e 2024-05-18 benni tmp[blkno - SUFS_NDIRECT] = block;
193 4338ef2e 2024-05-18 benni write_block (in->indir[0], buffer);
194 4338ef2e 2024-05-18 benni } else if (blkno < (SUFS_NDIRECT + pbp * pbp)) {
195 4338ef2e 2024-05-18 benni if (in->indir[1] == 0) {
196 4338ef2e 2024-05-18 benni in->indir[1] = alloc_dblock ();
197 4338ef2e 2024-05-18 benni write_inode (ino, in);
199 4338ef2e 2024-05-18 benni read_block (in->indir[1], buffer);
200 4338ef2e 2024-05-18 benni i = blkno - SUFS_NDIRECT - pbp;
201 4338ef2e 2024-05-18 benni if (tmp[i / pbp] == 0) {
202 4338ef2e 2024-05-18 benni tmp[i / pbp] = alloc_dblock ();
203 4338ef2e 2024-05-18 benni write_block (in->indir[1], buffer);
205 4338ef2e 2024-05-18 benni read_block (tmp[i / pbp], buffer);
206 4338ef2e 2024-05-18 benni tmp[i % pbp] = block;
207 4338ef2e 2024-05-18 benni write_block (tmp[i % pbp], buffer);
208 4338ef2e 2024-05-18 benni } else if (blkno < (SUFS_NDIRECT + pbp * pbp * pbp)) {
209 4338ef2e 2024-05-18 benni if (in->indir[2] == 0) {
210 4338ef2e 2024-05-18 benni in->indir[2] = alloc_dblock ();
211 4338ef2e 2024-05-18 benni write_inode (ino, in);
214 4338ef2e 2024-05-18 benni read_block (in->indir[2], buffer);
215 4338ef2e 2024-05-18 benni i = blkno - SUFS_NDIRECT - pbp * pbp;
216 4338ef2e 2024-05-18 benni if (tmp[i / pbp / pbp] == 0) {
217 4338ef2e 2024-05-18 benni tmp[i / pbp / pbp] = alloc_dblock ();
218 4338ef2e 2024-05-18 benni write_block (in->indir[2], buffer);
221 4338ef2e 2024-05-18 benni read_block (tmp[i / pbp / pbp], buffer);
223 4338ef2e 2024-05-18 benni if (tmp[i / pbp % pbp] == 0) {
224 4338ef2e 2024-05-18 benni tmp[i / pbp % pbp] = alloc_dblock ();
225 4338ef2e 2024-05-18 benni write_block (tmp[i / pbp / pbp], buffer);
227 4338ef2e 2024-05-18 benni read_block (tmp[i / pbp % pbp], buffer);
228 4338ef2e 2024-05-18 benni tmp[i % pbp] = block;
229 4338ef2e 2024-05-18 benni write_block (tmp[i / pbp % pbp], buffer);
231 4338ef2e 2024-05-18 benni errx (1, "resolve_inode_block(): inode out of range");
235 4338ef2e 2024-05-18 benni void read_block_inode (const struct sufs_inode *in, uint64_t blkno, char *buf)
237 4338ef2e 2024-05-18 benni uint64_t b;
239 4338ef2e 2024-05-18 benni b = resolve_inode_block (in, blkno);
240 4338ef2e 2024-05-18 benni if (b != 0) {
241 4338ef2e 2024-05-18 benni read_block (b, buf);
243 4338ef2e 2024-05-18 benni memset (buf, 0, sb.bsize);
247 4338ef2e 2024-05-18 benni void write_block_inode (uint64_t ino, struct sufs_inode *in, uint64_t blkno, const char *buf)
249 4338ef2e 2024-05-18 benni uint64_t b;
251 4338ef2e 2024-05-18 benni b = resolve_inode_block (in, blkno);
252 4338ef2e 2024-05-18 benni if (b == 0) {
253 4338ef2e 2024-05-18 benni b = alloc_dblock ();
254 4338ef2e 2024-05-18 benni map_inode (ino, in, blkno, b);
255 4338ef2e 2024-05-18 benni ++in->blocks;
256 4338ef2e 2024-05-18 benni write_inode (ino, in);
258 4338ef2e 2024-05-18 benni write_block (b, buf);
261 4338ef2e 2024-05-18 benni static struct sufs_inode read_inode (uint64_t ino)
263 4338ef2e 2024-05-18 benni struct sufs_inode in;
264 4338ef2e 2024-05-18 benni printf ("read_inode(%zu);\n", (size_t)ino);
265 4338ef2e 2024-05-18 benni read_block (sufs_iblk (sb, ino), buffer);
266 4338ef2e 2024-05-18 benni memcpy (&in, buffer + sufs_ioff (sb, ino), sizeof (in));
267 4338ef2e 2024-05-18 benni return in;
270 4338ef2e 2024-05-18 benni static void write_inode (uint64_t ino, const struct sufs_inode *in)
272 4338ef2e 2024-05-18 benni printf ("write_inode(%zu);\n", (size_t)ino);
273 4338ef2e 2024-05-18 benni read_block (sufs_iblk (sb, ino), buffer);
274 4338ef2e 2024-05-18 benni memcpy (buffer + sufs_ioff (sb, ino), in, sizeof (*in));
275 4338ef2e 2024-05-18 benni write_block (sufs_iblk (sb, ino), buffer);
278 4338ef2e 2024-05-18 benni static uint64_t searchdir (uint64_t ino, const char *name)
280 4338ef2e 2024-05-18 benni struct sufs_dirent *ent;
281 4338ef2e 2024-05-18 benni struct sufs_inode in;
282 4338ef2e 2024-05-18 benni uint64_t i;
283 4338ef2e 2024-05-18 benni size_t n, len;
285 4338ef2e 2024-05-18 benni printf ("searchdir(%zu, %s);\n", (size_t)ino, name);
287 4338ef2e 2024-05-18 benni len = strlen (name);
289 4338ef2e 2024-05-18 benni in = read_inode (ino);
290 4338ef2e 2024-05-18 benni if ((in.mode & S_IFMT) != S_IFDIR) {
291 4338ef2e 2024-05-18 benni errno = ENOTDIR;
295 4338ef2e 2024-05-18 benni for (i = 0; i < in.blocks; ++i) {
296 4338ef2e 2024-05-18 benni read_block_inode (&in, i, buffer);
298 4338ef2e 2024-05-18 benni for (n = 0; n < sb.bsize; n += ent->size) {
299 4338ef2e 2024-05-18 benni ent = (struct sufs_dirent *)(buffer + n);
301 4338ef2e 2024-05-18 benni if (ent->ino == 0)
304 4338ef2e 2024-05-18 benni if (ent->len != len)
307 4338ef2e 2024-05-18 benni if (memcmp (name, ent->name, len) == 0)
308 4338ef2e 2024-05-18 benni return ent->ino;
312 4338ef2e 2024-05-18 benni errno = ENOENT;
316 4338ef2e 2024-05-18 benni static uint64_t lookup2 (char *path)
318 4338ef2e 2024-05-18 benni uint64_t parent;
319 4338ef2e 2024-05-18 benni char *name, *slash;
320 4338ef2e 2024-05-18 benni size_t len;
322 4338ef2e 2024-05-18 benni // remove trailing slashes
323 4338ef2e 2024-05-18 benni len = strlen (path);
324 4338ef2e 2024-05-18 benni while (len > 0 && path[len - 1] == '/')
326 4338ef2e 2024-05-18 benni path[len] = '\0';
328 4338ef2e 2024-05-18 benni if (len == 0 || strcmp (path, "/") == 0)
329 4338ef2e 2024-05-18 benni return SUFS_INO_ROOT;
331 4338ef2e 2024-05-18 benni // split path at '/'
332 4338ef2e 2024-05-18 benni slash = strrchr (path, '/');
333 4338ef2e 2024-05-18 benni if (slash == NULL)
334 4338ef2e 2024-05-18 benni errx (1, "lookup2(): failed to split path");
335 4338ef2e 2024-05-18 benni *slash = '\0';
336 4338ef2e 2024-05-18 benni name = slash + 1;
338 4338ef2e 2024-05-18 benni // find parent inode
339 4338ef2e 2024-05-18 benni parent = lookup2 (path);
340 4338ef2e 2024-05-18 benni if (parent == 0) {
344 4338ef2e 2024-05-18 benni return searchdir (parent, name);
347 4338ef2e 2024-05-18 benni static uint64_t lookup (const char *path)
349 4338ef2e 2024-05-18 benni uint64_t ino;
350 4338ef2e 2024-05-18 benni char *buf;
352 4338ef2e 2024-05-18 benni printf ("lookup(\"%s\");\n", path);
354 4338ef2e 2024-05-18 benni if (*path != '/') {
355 4338ef2e 2024-05-18 benni errno = EINVAL;
359 4338ef2e 2024-05-18 benni buf = strdup (path);
360 4338ef2e 2024-05-18 benni ino = lookup2 (buf);
362 4338ef2e 2024-05-18 benni free (buf);
363 4338ef2e 2024-05-18 benni return ino;
366 4338ef2e 2024-05-18 benni int sufs_getattr (const char *path, struct stat *st)
368 4338ef2e 2024-05-18 benni struct sufs_inode in;
369 4338ef2e 2024-05-18 benni uint64_t ino;
371 4338ef2e 2024-05-18 benni printf ("getattr(\"%s\");\n", path);
373 4338ef2e 2024-05-18 benni ino = lookup (path);
374 4338ef2e 2024-05-18 benni if (ino == 0)
375 4338ef2e 2024-05-18 benni return -errno;
377 4338ef2e 2024-05-18 benni in = read_inode (ino);
379 4338ef2e 2024-05-18 benni st->st_ino = ino;
380 4338ef2e 2024-05-18 benni st->st_mode = in.mode;
381 4338ef2e 2024-05-18 benni printf ("mode = %o\n", (unsigned)in.mode);
382 4338ef2e 2024-05-18 benni st->st_nlink = in.nlink;
383 4338ef2e 2024-05-18 benni st->st_uid = in.uid;
384 4338ef2e 2024-05-18 benni st->st_gid = in.gid;
385 4338ef2e 2024-05-18 benni st->st_atime = in.atime;
386 4338ef2e 2024-05-18 benni st->st_mtime = in.mtime;
387 4338ef2e 2024-05-18 benni st->st_ctime = in.ctime;
388 4338ef2e 2024-05-18 benni st->st_size = in.size;
389 4338ef2e 2024-05-18 benni st->st_blocks = in.blocks;
390 4338ef2e 2024-05-18 benni st->st_blksize = sb.bsize;
394 4338ef2e 2024-05-18 benni int sufs_open (const char *path, struct fuse_file_info *ffi)
396 4338ef2e 2024-05-18 benni uint64_t ino;
398 4338ef2e 2024-05-18 benni ino = lookup (path);
399 4338ef2e 2024-05-18 benni return ino > 0 ? 0 : -errno;
402 4338ef2e 2024-05-18 benni int sufs_read (const char *path, char *buf, size_t size, off_t off, struct fuse_file_info *ffi)
404 4338ef2e 2024-05-18 benni struct sufs_inode in;
405 4338ef2e 2024-05-18 benni uint64_t ino;
407 4338ef2e 2024-05-18 benni printf ("read(\"%s\", %zu, %zu);\n", path, (size_t)off, size);
409 4338ef2e 2024-05-18 benni ino = lookup (path);
410 4338ef2e 2024-05-18 benni if (ino == 0)
411 4338ef2e 2024-05-18 benni return -errno;
413 4338ef2e 2024-05-18 benni in = read_inode (ino);
415 4338ef2e 2024-05-18 benni if (off > in.size)
418 4338ef2e 2024-05-18 benni if ((off + size) >= sb.bsize)
419 4338ef2e 2024-05-18 benni size = sb.bsize - off;
421 4338ef2e 2024-05-18 benni if ((off + size) >= in.size)
422 4338ef2e 2024-05-18 benni size = in.size - off;
424 4338ef2e 2024-05-18 benni read_block_inode (&in, off / sb.bsize, dbuffer);
425 4338ef2e 2024-05-18 benni memcpy (buf, dbuffer + off % sb.bsize, size);
427 4338ef2e 2024-05-18 benni return size;
430 4338ef2e 2024-05-18 benni int sufs_write (const char *path, const char *buf, size_t size, off_t off, struct fuse_file_info *ffi)
432 4338ef2e 2024-05-18 benni struct sufs_inode in;
433 4338ef2e 2024-05-18 benni uint64_t ino;
435 4338ef2e 2024-05-18 benni printf ("write(\"%s\", %zu, %zu);\n", path, size, (size_t)off);
437 4338ef2e 2024-05-18 benni ino = lookup (path);
438 4338ef2e 2024-05-18 benni if (ino == 0)
439 4338ef2e 2024-05-18 benni return -errno;
441 4338ef2e 2024-05-18 benni in = read_inode (ino);
443 4338ef2e 2024-05-18 benni if ((off + size) >= sb.bsize)
444 4338ef2e 2024-05-18 benni size = sb.bsize - off;
446 4338ef2e 2024-05-18 benni memcpy (dbuffer + off % sb.bsize, buf, size);
447 4338ef2e 2024-05-18 benni write_block_inode (ino, &in, off / sb.bsize, dbuffer);
449 4338ef2e 2024-05-18 benni if (off + size >= in.size)
450 4338ef2e 2024-05-18 benni in.size = off + size;
452 4338ef2e 2024-05-18 benni write_inode (ino, &in);
454 4338ef2e 2024-05-18 benni return size;
457 4338ef2e 2024-05-18 benni int sufs_readdir (const char *path, void *data, fuse_fill_dir_t filler, off_t off, struct fuse_file_info *ffi)
459 4338ef2e 2024-05-18 benni char name[256];
460 4338ef2e 2024-05-18 benni struct sufs_dirent *ent;
461 4338ef2e 2024-05-18 benni struct sufs_inode in;
462 4338ef2e 2024-05-18 benni uint64_t ino;
463 4338ef2e 2024-05-18 benni size_t len;
465 4338ef2e 2024-05-18 benni if (off != 0)
468 4338ef2e 2024-05-18 benni ino = lookup (path);
469 4338ef2e 2024-05-18 benni if (ino == 0)
470 4338ef2e 2024-05-18 benni return -errno;
472 4338ef2e 2024-05-18 benni in = read_inode (ino);
474 4338ef2e 2024-05-18 benni for (uint64_t i = 0; i < in.blocks; ++i) {
475 4338ef2e 2024-05-18 benni read_block_inode (&in, i, buffer);
476 4338ef2e 2024-05-18 benni for (uint32_t j = 0; j < sb.bsize; j += ent->size) {
477 4338ef2e 2024-05-18 benni ent = (struct sufs_dirent *)(buffer + j);
478 4338ef2e 2024-05-18 benni if (ent->size == 0)
480 4338ef2e 2024-05-18 benni len = ent->len;
481 4338ef2e 2024-05-18 benni memcpy (name, ent->name, len);
482 4338ef2e 2024-05-18 benni name[len] = '\0';
483 4338ef2e 2024-05-18 benni filler (data, name, NULL, 0);
491 4338ef2e 2024-05-18 benni int sufs_chown (const char *path, uid_t uid, gid_t gid)
493 4338ef2e 2024-05-18 benni struct sufs_inode in;
494 4338ef2e 2024-05-18 benni uint64_t ino;
496 4338ef2e 2024-05-18 benni printf ("chown(\"%s\", %u, %u);\n", path, (unsigned)uid, (unsigned)gid);
498 4338ef2e 2024-05-18 benni ino = lookup (path);
499 4338ef2e 2024-05-18 benni if (ino == 0)
500 4338ef2e 2024-05-18 benni return -errno;
502 4338ef2e 2024-05-18 benni in = read_inode (ino);
504 4338ef2e 2024-05-18 benni if (uid != -1)
505 4338ef2e 2024-05-18 benni in.uid = uid;
507 4338ef2e 2024-05-18 benni if (gid != -1)
508 4338ef2e 2024-05-18 benni in.gid = gid;
510 4338ef2e 2024-05-18 benni write_inode (ino, &in);
515 4338ef2e 2024-05-18 benni int sufs_chmod (const char *path, mode_t mode)
517 4338ef2e 2024-05-18 benni struct sufs_inode in;
518 4338ef2e 2024-05-18 benni uint64_t ino;
520 4338ef2e 2024-05-18 benni ino = lookup (path);
521 4338ef2e 2024-05-18 benni if (ino == 0)
522 4338ef2e 2024-05-18 benni return -errno;
524 4338ef2e 2024-05-18 benni in = read_inode (ino);
526 4338ef2e 2024-05-18 benni in.mode &= ~07777;
527 4338ef2e 2024-05-18 benni in.mode |= mode & 07777;
529 4338ef2e 2024-05-18 benni write_inode (ino, &in);
535 4338ef2e 2024-05-18 benni static int add_to_dir (uint64_t pino, struct sufs_inode *pin, const char *name, uint64_t ino)
537 4338ef2e 2024-05-18 benni struct sufs_dirent *ent, *new;
538 4338ef2e 2024-05-18 benni uint16_t rem;
539 4338ef2e 2024-05-18 benni uint64_t i, off;
540 4338ef2e 2024-05-18 benni size_t len;
542 4338ef2e 2024-05-18 benni printf ("add_to_dir(\"%s\", %zu);\n", name, (size_t)ino);
544 4338ef2e 2024-05-18 benni len = strlen (name);
545 4338ef2e 2024-05-18 benni if (len > 255) {
546 4338ef2e 2024-05-18 benni errno = -E2BIG;
547 4338ef2e 2024-05-18 benni return -1;
550 4338ef2e 2024-05-18 benni for (i = 0; i < pin->blocks; ++i) {
551 4338ef2e 2024-05-18 benni read_block_inode (pin, i, buffer);
552 4338ef2e 2024-05-18 benni for (uint64_t j = 0; j < sb.bsize; j += ent->size) {
553 4338ef2e 2024-05-18 benni ent = (struct sufs_dirent *)(buffer + j);
554 4338ef2e 2024-05-18 benni if (ent->size == 0)
557 4338ef2e 2024-05-18 benni printf ("ent = { ino: %zu, len: %zu, size: %zu, name: \"%*s\" }\n",
558 4338ef2e 2024-05-18 benni (size_t)ent->ino, (size_t)ent->len, (size_t)ent->size, (int)ent->len, ent->name);
560 4338ef2e 2024-05-18 benni rem = ent->size - ent->len - sizeof (struct sufs_dirent);
562 4338ef2e 2024-05-18 benni printf ("rem = %zu\n", (size_t)rem);
564 4338ef2e 2024-05-18 benni if (rem < (sizeof (struct sufs_dirent) + len + 8))
567 4338ef2e 2024-05-18 benni off = j + sizeof (struct sufs_dirent) + len;
568 4338ef2e 2024-05-18 benni off = (off + 7) & ~7;
569 4338ef2e 2024-05-18 benni printf ("j = %zu, off = %zu\n", (size_t)j, (size_t)off);
571 4338ef2e 2024-05-18 benni new = (struct sufs_dirent *)(buffer + off);
572 4338ef2e 2024-05-18 benni new->ino = ino;
573 4338ef2e 2024-05-18 benni new->size = rem;
574 4338ef2e 2024-05-18 benni new->len = len;
575 4338ef2e 2024-05-18 benni memcpy (new->name, name, len);
576 4338ef2e 2024-05-18 benni ent->size = off - j;
578 4338ef2e 2024-05-18 benni write_block_inode (pino, pin, i, buffer);
583 4338ef2e 2024-05-18 benni errx (1, "add_to_dir(): TODO: allocating new directory blocks");
586 4338ef2e 2024-05-18 benni static int find_parent (const char *path, struct sufs_inode *parent)
588 4338ef2e 2024-05-18 benni uint64_t ino;
589 4338ef2e 2024-05-18 benni char *ppath, *tmp;
591 4338ef2e 2024-05-18 benni tmp = strdup (path);
592 4338ef2e 2024-05-18 benni ppath = dirname (tmp);
593 4338ef2e 2024-05-18 benni ino = lookup (ppath);
594 4338ef2e 2024-05-18 benni free (tmp);
595 4338ef2e 2024-05-18 benni if (ino == 0)
596 4338ef2e 2024-05-18 benni return -1;
598 4338ef2e 2024-05-18 benni *parent = read_inode (ino);
599 4338ef2e 2024-05-18 benni return (parent->mode & S_IFMT) == S_IFDIR ? 0 : -1;
602 4338ef2e 2024-05-18 benni int sufs_mknod (const char *path, mode_t mode, dev_t dev)
604 4338ef2e 2024-05-18 benni struct fuse_context *ctx;
605 4338ef2e 2024-05-18 benni struct sufs_inode pin, in;
606 4338ef2e 2024-05-18 benni uint64_t pino, ino;
607 4338ef2e 2024-05-18 benni char *name, *ppath, *tmp;
609 4338ef2e 2024-05-18 benni printf ("mknod(\"%s\", %o, %u);\n", path, (unsigned)mode, (unsigned)dev);
611 4338ef2e 2024-05-18 benni tmp = strdup (path);
612 4338ef2e 2024-05-18 benni ppath = dirname (tmp);
613 4338ef2e 2024-05-18 benni pino = lookup (ppath);
614 4338ef2e 2024-05-18 benni if (pino == 0)
615 4338ef2e 2024-05-18 benni return -errno;
617 4338ef2e 2024-05-18 benni pin = read_inode (pino);
618 4338ef2e 2024-05-18 benni if ((pin.mode & S_IFMT) != S_IFDIR)
619 4338ef2e 2024-05-18 benni return -ENOTDIR;
621 4338ef2e 2024-05-18 benni ino = alloc_inode ();
623 4338ef2e 2024-05-18 benni ctx = fuse_get_context ();
624 4338ef2e 2024-05-18 benni memset (&in, 0, sizeof (in));
625 4338ef2e 2024-05-18 benni in.mode = mode;
626 4338ef2e 2024-05-18 benni in.nlink = 1;
627 4338ef2e 2024-05-18 benni in.uid = ctx->uid;
628 4338ef2e 2024-05-18 benni in.gid = pin.gid;
629 4338ef2e 2024-05-18 benni in.atime = time (NULL);
630 4338ef2e 2024-05-18 benni in.mtime = time (NULL);
631 4338ef2e 2024-05-18 benni in.ctime = time (NULL);
633 4338ef2e 2024-05-18 benni write_inode (ino, &in);
635 4338ef2e 2024-05-18 benni tmp = strdup (path);
636 4338ef2e 2024-05-18 benni name = basename (tmp);
637 4338ef2e 2024-05-18 benni add_to_dir (pino, &pin, name, ino);
641 4338ef2e 2024-05-18 benni int sufs_create (const char *path, mode_t mode, struct fuse_file_info *ffi)
643 4338ef2e 2024-05-18 benni return sufs_mknod (path, mode, 0);
646 4338ef2e 2024-05-18 benni int sufs_release (const char *path, struct fuse_file_info *ffi)
651 4338ef2e 2024-05-18 benni int sufs_unlink (const char *path)
653 4338ef2e 2024-05-18 benni struct sufs_inode parent, in;
654 4338ef2e 2024-05-18 benni const char *name;
655 4338ef2e 2024-05-18 benni size_t len;
656 4338ef2e 2024-05-18 benni char *tmp;
658 4338ef2e 2024-05-18 benni printf ("unlink(\"%s\");\n", path);
660 4338ef2e 2024-05-18 benni if (find_parent (path, &parent) != 0)
661 4338ef2e 2024-05-18 benni return -errno;
663 4338ef2e 2024-05-18 benni tmp = strdup (path);
664 4338ef2e 2024-05-18 benni name = basename (tmp);
665 4338ef2e 2024-05-18 benni len = strlen (name);
667 4338ef2e 2024-05-18 benni for (uint64_t i = 0; i < parent.blocks; ++i) {
668 4338ef2e 2024-05-18 benni struct sufs_dirent *ent, *prent;
669 4338ef2e 2024-05-18 benni uint64_t blkno, ino;
670 4338ef2e 2024-05-18 benni uint32_t prev;
672 4338ef2e 2024-05-18 benni blkno = resolve_inode_block (&parent, i);
673 4338ef2e 2024-05-18 benni if (blkno == 0)
675 4338ef2e 2024-05-18 benni read_block (blkno, buffer);
677 4338ef2e 2024-05-18 benni for (uint32_t j = 0, prev = -1; j < sb.bsize; prev = j, j += ent->size) {
678 4338ef2e 2024-05-18 benni ent = (struct sufs_dirent *)(buffer + j);
679 4338ef2e 2024-05-18 benni ino = ent->ino;
681 4338ef2e 2024-05-18 benni if (ino == 0 || len != ent->len)
684 4338ef2e 2024-05-18 benni if (memcmp (name, ent->name, len) != 0)
687 4338ef2e 2024-05-18 benni if (prev != -1) {
688 4338ef2e 2024-05-18 benni prent = (struct sufs_dirent *)(buffer + prev);
689 4338ef2e 2024-05-18 benni prent->size += ent->size;
690 4338ef2e 2024-05-18 benni } else if (ent->size == sb.bsize) {
691 4338ef2e 2024-05-18 benni ent->ino = 0;
693 4338ef2e 2024-05-18 benni errx (1, "sufs_unlink(): TODO: removing the first dirent in a block");
696 4338ef2e 2024-05-18 benni write_block (blkno, buffer);
697 4338ef2e 2024-05-18 benni free_inode (ent->ino);
698 4338ef2e 2024-05-18 benni free (tmp);
704 4338ef2e 2024-05-18 benni free (tmp);
705 4338ef2e 2024-05-18 benni return -ENOENT;
708 4338ef2e 2024-05-18 benni int sufs_utime (const char *path, struct utimbuf *t)
710 4338ef2e 2024-05-18 benni struct sufs_inode in;
711 4338ef2e 2024-05-18 benni uint64_t ino;
713 4338ef2e 2024-05-18 benni ino = lookup (path);
714 4338ef2e 2024-05-18 benni if (ino == 0)
715 4338ef2e 2024-05-18 benni return -errno;
717 4338ef2e 2024-05-18 benni in = read_inode (ino);
718 4338ef2e 2024-05-18 benni in.atime = t->actime;
719 4338ef2e 2024-05-18 benni in.mtime = t->modtime;
720 4338ef2e 2024-05-18 benni write_inode (ino, &in);
724 4338ef2e 2024-05-18 benni struct fuse_operations fsops = {
725 4338ef2e 2024-05-18 benni .getattr = sufs_getattr,
726 4338ef2e 2024-05-18 benni .open = sufs_open,
727 4338ef2e 2024-05-18 benni .read = sufs_read,
728 4338ef2e 2024-05-18 benni .write = sufs_write,
729 4338ef2e 2024-05-18 benni .readdir = sufs_readdir,
730 4338ef2e 2024-05-18 benni .chown = sufs_chown,
731 4338ef2e 2024-05-18 benni .chmod = sufs_chmod,
732 4338ef2e 2024-05-18 benni .mknod = sufs_mknod,
733 4338ef2e 2024-05-18 benni .create = sufs_create,
734 4338ef2e 2024-05-18 benni .release = sufs_release,
735 4338ef2e 2024-05-18 benni .unlink = sufs_unlink,
736 4338ef2e 2024-05-18 benni .utime = sufs_utime,
739 4338ef2e 2024-05-18 benni int opt_parse (void *data, const char *arg, int key, struct fuse_args *outargs)
741 4338ef2e 2024-05-18 benni switch (key) {
742 4338ef2e 2024-05-18 benni case KEY_VERSION:
743 4338ef2e 2024-05-18 benni fputs ("fuse_sufs v0\n", stderr);
744 4338ef2e 2024-05-18 benni fuse_opt_add_arg (outargs, "--version");
745 4338ef2e 2024-05-18 benni fuse_main (outargs->argc, outargs->argv, &fsops, NULL);
748 4338ef2e 2024-05-18 benni case KEY_HELP:
749 4338ef2e 2024-05-18 benni fputs ("usage: fuse_sufs file mountpoint\n", stderr);
750 4338ef2e 2024-05-18 benni fuse_opt_add_arg (outargs, "-h");
751 4338ef2e 2024-05-18 benni fuse_main (outargs->argc, outargs->argv, &fsops, NULL);
758 4338ef2e 2024-05-18 benni int main (int argc, char *argv[])
760 4338ef2e 2024-05-18 benni struct fuse_args args = FUSE_ARGS_INIT (argc, argv);
761 4338ef2e 2024-05-18 benni fuse_opt_parse (&args, NULL, opts, opt_parse);
763 4338ef2e 2024-05-18 benni fd = open ("test.img", O_RDWR);
765 4338ef2e 2024-05-18 benni if (fd < 0)
766 4338ef2e 2024-05-18 benni err (1, "open()");
768 4338ef2e 2024-05-18 benni read (fd, &sb, sizeof (sb));
770 4338ef2e 2024-05-18 benni if (sb.magic != SUFS_MAGIC) {
771 4338ef2e 2024-05-18 benni lseek (fd, SUFS_BOOTSIZE, SEEK_SET);
772 4338ef2e 2024-05-18 benni read (fd, &sb, sizeof (sb));
774 4338ef2e 2024-05-18 benni if (sb.magic != SUFS_MAGIC)
775 4338ef2e 2024-05-18 benni errx (1, "invalid magic");
778 4338ef2e 2024-05-18 benni buffer = malloc (sb.bsize);
779 4338ef2e 2024-05-18 benni dbuffer = malloc (sb.bsize);
781 4338ef2e 2024-05-18 benni return fuse_main (argc, argv, &fsops, NULL);