Added support for entry insertion

Currently unused, the insertion of new file entries in arbitrary
locations in a metadata-pair is very easy to add into the existing
metadata logging.

The only tricky things:
1. Name tags must strictly precede any tags related to a file. We can
   pull this off during a compact, but must make two passes. One for the
   name tag, one for the file. Though a benefit of this is that now our
   scans during moves can exit early upon finding the name tag.

1. We need to handle name tags appearing out of order. This makes name
   tags symmetric to deletes, although it doesn't seem like we can
   leverage this fact very well. Note this also means we need to make
   the superblock tag a type of name tag.
This commit is contained in:
Christopher Haster
2018-09-09 09:01:06 -05:00
parent 6db5202bdc
commit 6046d85e6e
3 changed files with 148 additions and 125 deletions

203
lfs.c
View File

@@ -463,20 +463,25 @@ struct lfs_diskoff {
lfs_off_t off; lfs_off_t off;
}; };
static int32_t lfs_commit_get(lfs_t *lfs, lfs_block_t block, lfs_off_t off, static int32_t lfs_commit_get(lfs_t *lfs,
uint32_t tag, uint32_t getmask, uint32_t gettag, int32_t getdiff, lfs_block_t block, lfs_off_t off, uint32_t tag, bool stopatcommit,
void *buffer, bool stopatcommit) { uint32_t getmask, uint32_t gettag, int32_t getdiff, void *buffer) {
gettag += getdiff;
// iterate over dir block backwards (for faster lookups) // iterate over dir block backwards (for faster lookups)
while (off >= 2*sizeof(tag)+lfs_tag_size(tag)) { while (off >= 2*sizeof(uint32_t)+lfs_tag_size(tag)) {
off -= sizeof(tag)+lfs_tag_size(tag); off -= sizeof(tag)+lfs_tag_size(tag);
if (lfs_tag_subtype(tag) == LFS_TYPE_CRC && stopatcommit) { if (lfs_tag_subtype(tag) == LFS_TYPE_CRC && stopatcommit) {
break; break;
} else if (lfs_tag_type(tag) == LFS_TYPE_DELETE) { } else if (lfs_tag_subtype(tag) == LFS_TYPE_DELETE) {
if (lfs_tag_id(tag) <= lfs_tag_id(gettag + getdiff)) { // something was deleted, need to move around it
getdiff += LFS_MKTAG(0, 1, 0); if (lfs_tag_id(tag) <= lfs_tag_id(gettag - getdiff)) {
getdiff -= LFS_MKTAG(0, 1, 0);
} }
} else if ((tag & getmask) == ((gettag + getdiff) & getmask)) { }
if ((tag & getmask) == ((gettag - getdiff) & getmask)) {
if (buffer) { if (buffer) {
lfs_size_t diff = lfs_min( lfs_size_t diff = lfs_min(
lfs_tag_size(gettag), lfs_tag_size(tag)); lfs_tag_size(gettag), lfs_tag_size(tag));
@@ -491,7 +496,16 @@ static int32_t lfs_commit_get(lfs_t *lfs, lfs_block_t block, lfs_off_t off,
lfs_tag_size(gettag) - diff); lfs_tag_size(gettag) - diff);
} }
return tag - getdiff; return tag + getdiff;
}
if (lfs_tag_subtype(tag) == LFS_TYPE_NAME) {
// found where something was created
if (lfs_tag_id(tag) == lfs_tag_id(gettag - getdiff)) {
break;
} else if (lfs_tag_id(tag) < lfs_tag_id(gettag - getdiff)) {
getdiff += LFS_MKTAG(0, 1, 0);
}
} }
uint32_t ntag; uint32_t ntag;
@@ -529,19 +543,20 @@ static int lfs_commit_prog(lfs_t *lfs, struct lfs_commit *commit,
static int lfs_commit_attrs(lfs_t *lfs, struct lfs_commit *commit, static int lfs_commit_attrs(lfs_t *lfs, struct lfs_commit *commit,
uint16_t id, const struct lfs_attr *attrs); uint16_t id, const struct lfs_attr *attrs);
static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit, static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit, int pass,
uint32_t frommask, uint32_t fromtag, uint32_t tomask, uint32_t totag, uint32_t frommask, uint32_t fromtag, int32_t fromdiff,
const lfs_mdir_t *dir, const lfs_mattr_t *attrs); const lfs_mdir_t *dir, const lfs_mattr_t *attrs);
static int lfs_commit_attr(lfs_t *lfs, struct lfs_commit *commit, static int lfs_commit_attr(lfs_t *lfs, struct lfs_commit *commit,
uint32_t tag, const void *buffer) { uint32_t tag, const void *buffer) {
if (lfs_tag_subtype(tag) == LFS_FROM_MOVE) { if (lfs_tag_type(tag) == LFS_FROM_MOVE) {
// special case for moves // special case for moves
return lfs_commit_move(lfs, commit, return lfs_commit_move(lfs, commit, 1,
0x003ff000, LFS_MKTAG(0, lfs_tag_size(tag), 0), 0x003ff000, LFS_MKTAG(0, lfs_tag_size(tag), 0),
0x003ff000, LFS_MKTAG(0, lfs_tag_id(tag), 0), LFS_MKTAG(0, lfs_tag_id(tag), 0) -
LFS_MKTAG(0, lfs_tag_size(tag), 0),
buffer, NULL); buffer, NULL);
} else if (lfs_tag_subtype(tag) == LFS_FROM_ATTRS) { } else if (lfs_tag_type(tag) == LFS_FROM_ATTRS) {
// special case for custom attributes // special case for custom attributes
return lfs_commit_attrs(lfs, commit, return lfs_commit_attrs(lfs, commit,
lfs_tag_id(tag), buffer); lfs_tag_id(tag), buffer);
@@ -603,13 +618,15 @@ static int lfs_commit_attrs(lfs_t *lfs, struct lfs_commit *commit,
return 0; return 0;
} }
static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit, static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit, int pass,
uint32_t frommask, uint32_t fromtag, uint32_t tomask, uint32_t totag, uint32_t frommask, uint32_t fromtag, int32_t fromdiff,
const lfs_mdir_t *dir, const lfs_mattr_t *attrs) { const lfs_mdir_t *dir, const lfs_mattr_t *attrs) {
fromtag += fromdiff;
// iterate through list and commits, only committing unique entries // iterate through list and commits, only committing unique entries
lfs_off_t off = dir->off; lfs_off_t off = dir->off;
uint32_t ntag = dir->etag; uint32_t ntag = dir->etag;
while (attrs || off > sizeof(uint32_t)) { while (attrs || off >= 2*sizeof(uint32_t)+lfs_tag_size(ntag)) {
struct lfs_diskoff disk; struct lfs_diskoff disk;
uint32_t tag; uint32_t tag;
const void *buffer; const void *buffer;
@@ -618,7 +635,6 @@ static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit,
buffer = attrs->buffer; buffer = attrs->buffer;
attrs = attrs->next; attrs = attrs->next;
} else { } else {
LFS_ASSERT(off > sizeof(ntag)+lfs_tag_size(ntag));
off -= sizeof(ntag)+lfs_tag_size(ntag); off -= sizeof(ntag)+lfs_tag_size(ntag);
tag = ntag; tag = ntag;
@@ -637,31 +653,48 @@ static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit,
tag |= 0x80000000; tag |= 0x80000000;
} }
if (lfs_tag_type(tag) == LFS_TYPE_DELETE && if (lfs_tag_subtype(tag) == LFS_TYPE_DELETE &&
lfs_tag_id(tag) <= lfs_tag_id(fromtag)) { lfs_tag_id(tag) <= lfs_tag_id(fromtag - fromdiff)) {
// something was deleted, we need to move around it // something was deleted, we need to move around it
fromtag += LFS_MKTAG(0, 1, 0); fromdiff -= LFS_MKTAG(0, 1, 0);
} else if ((tag & frommask) == (fromtag & frommask)) { }
if ((tag & frommask) == ((fromtag - fromdiff) & frommask)) {
bool duplicate;
if (pass == 0) {
duplicate = (lfs_tag_subtype(tag) != LFS_TYPE_NAME);
} else {
// check if type has already been committed // check if type has already been committed
int32_t res = lfs_commit_get(lfs, commit->block, int32_t res = lfs_commit_get(lfs,
commit->off, commit->ptag, commit->block, commit->off, commit->ptag, true,
lfs_tag_isuser(tag) ? 0x7ffff000 : 0x7c3ff000, lfs_tag_isuser(tag) ? 0x7ffff000 : 0x7c3ff000,
(tag & ~tomask) | totag, tag + fromdiff, 0, NULL);
0, NULL, true);
if (res < 0 && res != LFS_ERR_NOENT) { if (res < 0 && res != LFS_ERR_NOENT) {
return res; return res;
} }
if (res == LFS_ERR_NOENT) { duplicate = (res != LFS_ERR_NOENT);
}
if (!duplicate) {
// update id and commit, as we are currently unique // update id and commit, as we are currently unique
int err = lfs_commit_attr(lfs, commit, int err = lfs_commit_attr(lfs, commit,
(tag & ~tomask) | totag, tag + fromdiff,
buffer); buffer);
if (err) { if (err) {
return err; return err;
} }
} }
} }
if (lfs_tag_subtype(tag) == LFS_TYPE_NAME) {
// found where something was created
if (lfs_tag_id(tag) == lfs_tag_id(fromtag - fromdiff)) {
break;
} else if (lfs_tag_id(tag) < lfs_tag_id(fromtag - fromdiff)) {
fromdiff += LFS_MKTAG(0, 1, 0);
}
}
} }
return 0; return 0;
@@ -914,13 +947,25 @@ static int32_t lfs_dir_fetchmatch(lfs_t *lfs,
crc = lfs_crc(crc, &dat, 1); crc = lfs_crc(crc, &dat, 1);
} }
// keep track of id count
if (lfs_tag_id(tag) < 0x3ff && lfs_tag_id(tag) >= tempcount) {
tempcount = lfs_tag_id(tag)+1;
}
// check for special tags // check for special tags
if (lfs_tag_subtype(tag) == LFS_TYPE_TAIL) { if (lfs_tag_subtype(tag) == LFS_TYPE_NAME) {
tempcount += 1;
if (lfs_tag_isvalid(tempfoundtag) &&
lfs_tag_id(tag) <= lfs_tag_id(tempfoundtag)) {
tempfoundtag += LFS_MKTAG(0, 1, 0);
}
} else if (lfs_tag_subtype(tag) == LFS_TYPE_DELETE) {
LFS_ASSERT(tempcount > 0);
tempcount -= 1;
if (lfs_tag_id(tag) == lfs_tag_id(tempfoundtag)) {
tempfoundtag = LFS_ERR_NOENT;
} else if (lfs_tag_isvalid(tempfoundtag) &&
lfs_tag_id(tag) < lfs_tag_id(tempfoundtag)) {
tempfoundtag -= LFS_MKTAG(0, 1, 0);
}
} else if (lfs_tag_subtype(tag) == LFS_TYPE_TAIL) {
tempsplit = (lfs_tag_type(tag) & 1); tempsplit = (lfs_tag_type(tag) & 1);
err = lfs_bd_read(lfs, err = lfs_bd_read(lfs,
&lfs->pcache, &lfs->rcache, lfs->cfg->block_size, &lfs->pcache, &lfs->rcache, lfs->cfg->block_size,
@@ -945,17 +990,9 @@ static int32_t lfs_dir_fetchmatch(lfs_t *lfs,
break; break;
} }
} }
} else if (lfs_tag_subtype(tag) == LFS_TYPE_DELETE) {
LFS_ASSERT(tempcount > 0);
tempcount -= 1;
if (lfs_tag_id(tag) == lfs_tag_id(tempfoundtag)) {
tempfoundtag = LFS_ERR_NOENT;
} else if (lfs_tag_isvalid(tempfoundtag) &&
lfs_tag_id(tag) < lfs_tag_id(tempfoundtag)) {
tempfoundtag -= LFS_MKTAG(0, 1, 0);
} }
} else if ((tag & findmask) == (findtag & findmask)) {
if ((tag & findmask) == (findtag & findmask)) {
// found a match? // found a match?
if (lfs_tag_type(findtag) == LFS_TYPE_DIRSTRUCT) { if (lfs_tag_type(findtag) == LFS_TYPE_DIRSTRUCT) {
lfs_block_t child[2]; lfs_block_t child[2];
@@ -1062,11 +1099,13 @@ static int32_t lfs_dir_get(lfs_t *lfs, lfs_mdir_t *dir,
if (lfs_pair_cmp(dir->pair, lfs->globals.g.movepair) == 0 && if (lfs_pair_cmp(dir->pair, lfs->globals.g.movepair) == 0 &&
lfs_tag_id(gettag) <= lfs->globals.g.moveid) { lfs_tag_id(gettag) <= lfs->globals.g.moveid) {
// synthetic moves // synthetic moves
getdiff = LFS_MKTAG(0, 1, 0); gettag += LFS_MKTAG(0, 1, 0);
getdiff -= LFS_MKTAG(0, 1, 0);
} }
return lfs_commit_get(lfs, dir->pair[0], dir->off, dir->etag, return lfs_commit_get(lfs,
getmask, gettag, getdiff, buffer, false); dir->pair[0], dir->off, dir->etag, false,
getmask, gettag, getdiff, buffer);
} }
static int lfs_dir_compact(lfs_t *lfs, static int lfs_dir_compact(lfs_t *lfs,
@@ -1159,9 +1198,10 @@ commit:
// commit with a move // commit with a move
for (uint16_t id = begin; id < end || commit.off < commit.ack; id++) { for (uint16_t id = begin; id < end || commit.off < commit.ack; id++) {
err = lfs_commit_move(lfs, &commit, for (int pass = 0; pass < 2; pass++) {
err = lfs_commit_move(lfs, &commit, pass,
0x003ff000, LFS_MKTAG(0, id, 0), 0x003ff000, LFS_MKTAG(0, id, 0),
0x003ff000, LFS_MKTAG(0, id - begin, 0), -LFS_MKTAG(0, begin, 0),
source, attrs); source, attrs);
if (err && !(splitted && err == LFS_ERR_NOSPC)) { if (err && !(splitted && err == LFS_ERR_NOSPC)) {
if (err == LFS_ERR_NOSPC) { if (err == LFS_ERR_NOSPC) {
@@ -1171,6 +1211,7 @@ commit:
} }
return err; return err;
} }
}
ackid = id; ackid = id;
} }
@@ -1191,20 +1232,6 @@ commit:
} }
} }
if (lfs_pair_cmp(dir->pair, (const lfs_block_t[2]){0, 1}) == 0) {
// move over (duplicate) superblock if we are root
err = lfs_commit_move(lfs, &commit,
0x7c000000, LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, 0),
0x7ffff000, LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, 0),
source, attrs);
if (err) {
if (err == LFS_ERR_CORRUPT) {
goto relocate;
}
return err;
}
}
if (!relocated) { if (!relocated) {
// commit any globals, unless we're relocating, // commit any globals, unless we're relocating,
// in which case our parent will steal our globals // in which case our parent will steal our globals
@@ -1350,12 +1377,11 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
// calculate new directory size // calculate new directory size
uint32_t deletetag = 0xffffffff; uint32_t deletetag = 0xffffffff;
int attrcount = 0;
for (const lfs_mattr_t *a = attrs; a; a = a->next) { for (const lfs_mattr_t *a = attrs; a; a = a->next) {
if (lfs_tag_id(a->tag) < 0x3ff && lfs_tag_id(a->tag) >= dir->count) { if (lfs_tag_subtype(a->tag) == LFS_TYPE_NAME) {
dir->count = lfs_tag_id(a->tag)+1; dir->count += 1;
} } else if (lfs_tag_subtype(a->tag) == LFS_TYPE_DELETE) {
if (lfs_tag_type(a->tag) == LFS_TYPE_DELETE) {
LFS_ASSERT(dir->count > 0); LFS_ASSERT(dir->count > 0);
dir->count -= 1; dir->count -= 1;
deletetag = a->tag; deletetag = a->tag;
@@ -1381,6 +1407,8 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
} }
} }
} }
attrcount += 1;
} }
while (true) { while (true) {
@@ -1400,8 +1428,13 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
.ack = 0, .ack = 0,
}; };
for (const lfs_mattr_t *a = attrs; a; a = a->next) { // iterate over commits backwards, this lets us "append" commits cheaply
if (lfs_tag_type(a->tag) != LFS_TYPE_DELETE) { for (int i = 0; i < attrcount; i++) {
const lfs_mattr_t *a = attrs;
for (int j = 0; j < attrcount-i-1; j++) {
a = a->next;
}
lfs_pair_tole32(dir->tail); lfs_pair_tole32(dir->tail);
int err = lfs_commit_attr(lfs, &commit, a->tag, a->buffer); int err = lfs_commit_attr(lfs, &commit, a->tag, a->buffer);
lfs_pair_fromle32(dir->tail); lfs_pair_fromle32(dir->tail);
@@ -1412,18 +1445,6 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
return err; return err;
} }
} }
}
if (lfs_tag_isvalid(deletetag)) {
// special case for deletes, since order matters
int err = lfs_commit_attr(lfs, &commit, deletetag, NULL);
if (err) {
if (err == LFS_ERR_NOSPC || err == LFS_ERR_CORRUPT) {
goto compact;
}
return err;
}
}
int err = lfs_commit_globals(lfs, &commit, &dir->locals); int err = lfs_commit_globals(lfs, &commit, &dir->locals);
if (err) { if (err) {
@@ -1654,9 +1675,9 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
cwd.tail[1] = dir.pair[1]; cwd.tail[1] = dir.pair[1];
lfs_pair_tole32(dir.pair); lfs_pair_tole32(dir.pair);
err = lfs_dir_commit(lfs, &cwd, err = lfs_dir_commit(lfs, &cwd,
LFS_MKATTR(LFS_TYPE_DIR, id, path, nlen,
LFS_MKATTR(LFS_TYPE_DIRSTRUCT, id, dir.pair, sizeof(dir.pair),
LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x3ff, cwd.tail, sizeof(cwd.tail), LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x3ff, cwd.tail, sizeof(cwd.tail),
LFS_MKATTR(LFS_TYPE_DIRSTRUCT, id, dir.pair, sizeof(dir.pair),
LFS_MKATTR(LFS_TYPE_DIR, id, path, nlen,
NULL)))); NULL))));
lfs_pair_fromle32(dir.pair); lfs_pair_fromle32(dir.pair);
if (err) { if (err) {
@@ -2059,8 +2080,8 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
// get next slot and create entry to remember name // get next slot and create entry to remember name
file->id = file->m.count; file->id = file->m.count;
err = lfs_dir_commit(lfs, &file->m, err = lfs_dir_commit(lfs, &file->m,
LFS_MKATTR(LFS_TYPE_REG, file->id, path, nlen,
LFS_MKATTR(LFS_TYPE_INLINESTRUCT, file->id, NULL, 0, LFS_MKATTR(LFS_TYPE_INLINESTRUCT, file->id, NULL, 0,
LFS_MKATTR(LFS_TYPE_REG, file->id, path, nlen,
NULL))); NULL)));
if (err) { if (err) {
err = LFS_ERR_NAMETOOLONG; err = LFS_ERR_NAMETOOLONG;
@@ -2343,8 +2364,8 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
// commit file data and attributes // commit file data and attributes
err = lfs_dir_commit(lfs, &file->m, err = lfs_dir_commit(lfs, &file->m,
LFS_MKATTR(type, file->id, buffer, size,
LFS_MKATTR(LFS_FROM_ATTRS, file->id, file->cfg->attrs, 0, LFS_MKATTR(LFS_FROM_ATTRS, file->id, file->cfg->attrs, 0,
LFS_MKATTR(type, file->id, buffer, size,
NULL))); NULL)));
if (err) { if (err) {
if (err == LFS_ERR_NOSPC && (file->flags & LFS_F_INLINE)) { if (err == LFS_ERR_NOSPC && (file->flags & LFS_F_INLINE)) {
@@ -2811,9 +2832,11 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
// move over all attributes // move over all attributes
err = lfs_dir_commit(lfs, &newcwd, err = lfs_dir_commit(lfs, &newcwd,
LFS_MKATTR(lfs_tag_type(oldtag), newid, newpath, strlen(newpath),
LFS_MKATTR(LFS_FROM_MOVE, newid, &oldcwd, lfs_tag_id(oldtag), LFS_MKATTR(LFS_FROM_MOVE, newid, &oldcwd, lfs_tag_id(oldtag),
NULL))); LFS_MKATTR(lfs_tag_type(oldtag), newid, newpath, strlen(newpath),
(prevtag != LFS_ERR_NOENT)
? LFS_MKATTR(LFS_TYPE_DELETE, newid, NULL, 0, NULL)
: NULL)));
if (err) { if (err) {
return err; return err;
} }
@@ -3085,7 +3108,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
goto cleanup; goto cleanup;
} }
int32_t res = lfs_dir_get(lfs, &root, 0x7c000000, int32_t res = lfs_dir_get(lfs, &root, 0x7f800000,
LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, sizeof(superblock)), LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, sizeof(superblock)),
&superblock); &superblock);
if (res < 0) { if (res < 0) {

26
lfs.h
View File

@@ -88,21 +88,21 @@ enum lfs_error {
// File types // File types
enum lfs_type { enum lfs_type {
// file types // file types
LFS_TYPE_REG = 0x001, LFS_TYPE_REG = 0x002,
LFS_TYPE_DIR = 0x002, LFS_TYPE_DIR = 0x003,
// internally used types // internally used types
LFS_TYPE_USER = 0x100, LFS_TYPE_USER = 0x100,
LFS_TYPE_SUPERBLOCK = 0x011, LFS_TYPE_SUPERBLOCK = 0x001,
LFS_TYPE_ROOT = 0x010, LFS_TYPE_ROOT = 0x000,
LFS_TYPE_NAME = 0x000, LFS_TYPE_NAME = 0x000,
LFS_TYPE_DELETE = 0x030, LFS_TYPE_DELETE = 0x020,
LFS_TYPE_STRUCT = 0x040, LFS_TYPE_STRUCT = 0x040,
LFS_TYPE_GLOBALS = 0x080, LFS_TYPE_GLOBALS = 0x0e0,
LFS_TYPE_TAIL = 0x0c0, LFS_TYPE_TAIL = 0x080,
LFS_TYPE_SOFTTAIL = 0x0c0, LFS_TYPE_SOFTTAIL = 0x080,
LFS_TYPE_HARDTAIL = 0x0c1, LFS_TYPE_HARDTAIL = 0x081,
LFS_TYPE_CRC = 0x0f0, LFS_TYPE_CRC = 0x0a0,
LFS_TYPE_DIRSTRUCT = 0x040, LFS_TYPE_DIRSTRUCT = 0x040,
LFS_TYPE_INLINESTRUCT = 0x041, LFS_TYPE_INLINESTRUCT = 0x041,
@@ -111,9 +111,9 @@ enum lfs_type {
// internal chip sources // internal chip sources
LFS_FROM_REGION = 0x000, LFS_FROM_REGION = 0x000,
LFS_FROM_DISK = 0x200, LFS_FROM_DISK = 0x200,
LFS_FROM_MOVE = 0x050, LFS_FROM_MOVE = 0x0c1,
LFS_FROM_ATTRS = 0x060, LFS_FROM_ATTRS = 0x0c2,
LFS_FROM_SUPERBLOCK = 0x070, LFS_FROM_SUPERBLOCK = 0x0c3,
}; };
// File open flags // File open flags

View File

@@ -4,15 +4,15 @@ import struct
import binascii import binascii
TYPES = { TYPES = {
(0x1ff, 0x001): 'reg', (0x1ff, 0x002): 'reg',
(0x1ff, 0x002): 'dir', (0x1ff, 0x003): 'dir',
(0x1ff, 0x011): 'superblock', (0x1ff, 0x001): 'superblock',
(0x1ff, 0x010): 'root', (0x1ff, 0x000): 'root',
(0x1ff, 0x030): 'delete', (0x1ff, 0x020): 'delete',
(0x1f0, 0x080): 'globals', (0x1f0, 0x0e0): 'globals',
(0x1ff, 0x0c0): 'tail soft', (0x1ff, 0x080): 'tail soft',
(0x1ff, 0x0c1): 'tail hard', (0x1ff, 0x081): 'tail hard',
(0x1f0, 0x0f0): 'crc', (0x1f0, 0x0a0): 'crc',
(0x1ff, 0x040): 'struct dir', (0x1ff, 0x040): 'struct dir',
(0x1ff, 0x041): 'struct inline', (0x1ff, 0x041): 'struct inline',
(0x1ff, 0x042): 'struct ctz', (0x1ff, 0x042): 'struct ctz',