Skip to content

Commit 617dd87

Browse files
committed
Added deletion to custom attributes
This follows from enabling tag deletion, however does require some consideration with the APIs. Now we can remove custom attributes, as well as determine if an attribute exists or not.
1 parent c67a41a commit 617dd87

File tree

5 files changed

+63
-22
lines changed

5 files changed

+63
-22
lines changed

lfs.c

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ static inline lfs_size_t lfs_tag_size(uint32_t tag) {
401401
}
402402

403403
static inline lfs_size_t lfs_tag_dsize(uint32_t tag) {
404-
return sizeof(tag) + lfs_tag_size(tag) + lfs_tag_isdelete(tag);
404+
return sizeof(tag) + lfs_tag_size(tag + lfs_tag_isdelete(tag));
405405
}
406406

407407
// operations on set of globals
@@ -472,15 +472,15 @@ struct lfs_diskoff {
472472
};
473473

474474
static int32_t lfs_commit_get(lfs_t *lfs,
475-
lfs_block_t block, lfs_off_t off, uint32_t tag, bool stopatcommit,
475+
lfs_block_t block, lfs_off_t off, uint32_t tag, bool compacting,
476476
uint32_t getmask, uint32_t gettag, int32_t getdiff, void *buffer) {
477477
gettag += getdiff;
478478

479479
// iterate over dir block backwards (for faster lookups)
480480
while (off >= sizeof(uint32_t) + lfs_tag_dsize(tag)) {
481481
off -= lfs_tag_dsize(tag);
482482

483-
if (lfs_tag_subtype(tag) == LFS_TYPE_CRC && stopatcommit) {
483+
if (lfs_tag_subtype(tag) == LFS_TYPE_CRC && compacting) {
484484
break;
485485
} else if (lfs_tag_subtype(tag) == LFS_TYPE_DELETE) {
486486
// something was deleted, need to move around it
@@ -489,8 +489,11 @@ static int32_t lfs_commit_get(lfs_t *lfs,
489489
}
490490
}
491491

492-
if (!lfs_tag_isdelete(tag) &&
493-
(tag & getmask) == ((gettag - getdiff) & getmask)) {
492+
if ((tag & getmask) == ((gettag - getdiff) & getmask)) {
493+
if (lfs_tag_isdelete(tag) && !compacting) {
494+
return LFS_ERR_NOENT;
495+
}
496+
494497
if (buffer) {
495498
lfs_size_t diff = lfs_min(
496499
lfs_tag_size(gettag), lfs_tag_size(tag));
@@ -2912,19 +2915,18 @@ lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
29122915
res = lfs_dir_get(lfs, &cwd, 0x7ffff000,
29132916
LFS_MKTAG(0x100 | type, id, lfs_min(size, lfs->attr_max)),
29142917
buffer);
2915-
if (res < 0 && res != LFS_ERR_NOENT) {
2918+
if (res < 0) {
2919+
if (res == LFS_ERR_NOENT) {
2920+
return LFS_ERR_NOATTR;
2921+
}
29162922
return res;
29172923
}
29182924

2919-
return (res == LFS_ERR_NOENT) ? 0 : lfs_tag_size(res);
2925+
return lfs_tag_size(res);
29202926
}
29212927

2922-
int lfs_setattr(lfs_t *lfs, const char *path,
2928+
static int lfs_commitattr(lfs_t *lfs, const char *path,
29232929
uint8_t type, const void *buffer, lfs_size_t size) {
2924-
if (size > lfs->attr_max) {
2925-
return LFS_ERR_NOSPC;
2926-
}
2927-
29282930
lfs_mdir_t cwd;
29292931
int32_t res = lfs_dir_lookup(lfs, &cwd, &path);
29302932
if (res < 0) {
@@ -2946,6 +2948,19 @@ int lfs_setattr(lfs_t *lfs, const char *path,
29462948
NULL));
29472949
}
29482950

2951+
int lfs_setattr(lfs_t *lfs, const char *path,
2952+
uint8_t type, const void *buffer, lfs_size_t size) {
2953+
if (size > lfs->attr_max) {
2954+
return LFS_ERR_NOSPC;
2955+
}
2956+
2957+
return lfs_commitattr(lfs, path, type, buffer, size);
2958+
}
2959+
2960+
int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type) {
2961+
return lfs_commitattr(lfs, path, type, NULL, 0xfff);
2962+
}
2963+
29492964

29502965
/// Filesystem operations ///
29512966
static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {

lfs.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ enum lfs_error {
8282
LFS_ERR_INVAL = -22, // Invalid parameter
8383
LFS_ERR_NOSPC = -28, // No space left on device
8484
LFS_ERR_NOMEM = -12, // No more memory available
85+
LFS_ERR_NOATTR = -61, // No data/attr available
8586
LFS_ERR_NAMETOOLONG = -36, // File name too long
8687
};
8788

@@ -456,7 +457,8 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
456457
// Custom attributes are uniquely identified by an 8-bit type and limited
457458
// to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller than
458459
// the buffer, it will be padded with zeros. If the stored attribute is larger,
459-
// then it will be silently truncated.
460+
// then it will be silently truncated. If no attribute is found, the error
461+
// LFS_ERR_NOATTR is returned and the buffer is filled with zeros.
460462
//
461463
// Returns the size of the attribute, or a negative error code on failure.
462464
// Note, the returned size is the size of the attribute on disk, irrespective
@@ -469,13 +471,19 @@ lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
469471
//
470472
// Custom attributes are uniquely identified by an 8-bit type and limited
471473
// to LFS_ATTR_MAX bytes. If an attribute is not found, it will be
472-
// implicitly created, and setting the size of an attribute to zero deletes
473-
// the attribute.
474+
// implicitly created.
474475
//
475476
// Returns a negative error code on failure.
476477
int lfs_setattr(lfs_t *lfs, const char *path,
477478
uint8_t type, const void *buffer, lfs_size_t size);
478479

480+
// Removes a custom attribute
481+
//
482+
// If an attribute is not found, nothing happens.
483+
//
484+
// Returns a negative error code on failure.
485+
int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type);
486+
479487

480488
/// File operations ///
481489

tests/corrupt.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ def corrupt(block):
1919
break
2020

2121
tag ^= ntag
22-
file.seek(tag & 0xfff, os.SEEK_CUR)
22+
size = (tag & 0xfff) if (tag & 0xfff) != 0xfff else 0
23+
file.seek(size, os.SEEK_CUR)
2324

2425
# lob off last 3 bytes
25-
file.seek(-((tag & 0xfff) + 3), os.SEEK_CUR)
26+
file.seek(-(size + 3), os.SEEK_CUR)
2627
file.truncate()
2728

2829
def main(args):

tests/debug.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,21 @@ def main(*blocks):
8181
size = (tag & 0x00000fff) >> 0
8282
iscrc = (type & 0x1f0) == 0x0f0
8383

84-
data = file.read(size)
84+
data = file.read(size if size != 0xfff else 0)
8585
if iscrc:
8686
crc = binascii.crc32(data[:4], crc)
8787
else:
8888
crc = binascii.crc32(data, crc)
8989

90-
print '%04x: %08x %-14s %3s %3d %-23s %-8s' % (
90+
print '%04x: %08x %-14s %3s %3s %-23s %-8s' % (
9191
off, tag,
9292
typeof(type) + (' bad!' if iscrc and ~crc else ''),
93-
id if id != 0x3ff else '.', size,
93+
id if id != 0x3ff else '.',
94+
size if size != 0xfff else 'x',
9495
' '.join('%02x' % ord(c) for c in data[:8]),
9596
''.join(c if c >= ' ' and c <= '~' else '.' for c in data[:8]))
9697

97-
off += tag & 0xfff
98+
off += size if size != 0xfff else 0
9899
if iscrc:
99100
crc = 0
100101
tag ^= (type & 1) << 31

tests/test_attrs.sh

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ tests/test.py << TEST
3737
memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0;
3838
memcmp(buffer+10, "ccccc", 5) => 0;
3939
40+
lfs_removeattr(&lfs, "hello", 'B') => 0;
41+
lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
42+
lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => LFS_ERR_NOATTR;
43+
lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5;
44+
memcmp(buffer, "aaaa", 4) => 0;
45+
memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0;
46+
memcmp(buffer+10, "ccccc", 5) => 0;
47+
4048
lfs_setattr(&lfs, "hello", 'B', "dddddd", 6) => 0;
4149
lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
4250
lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 6;
@@ -98,6 +106,14 @@ tests/test.py << TEST
98106
memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0;
99107
memcmp(buffer+10, "ccccc", 5) => 0;
100108
109+
lfs_removeattr(&lfs, "/", 'B') => 0;
110+
lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4;
111+
lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => LFS_ERR_NOATTR;
112+
lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5;
113+
memcmp(buffer, "aaaa", 4) => 0;
114+
memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0;
115+
memcmp(buffer+10, "ccccc", 5) => 0;
116+
101117
lfs_setattr(&lfs, "/", 'B', "dddddd", 6) => 0;
102118
lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4;
103119
lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 6;
@@ -241,7 +257,7 @@ tests/test.py << TEST
241257
242258
lfs_getattr(&lfs, "hello/hello", 'B', buffer, 9) => 9;
243259
lfs_getattr(&lfs, "hello/hello", 'C', buffer+9, 9) => 5;
244-
lfs_getattr(&lfs, "hello/hello", 'D', buffer+18, 9) => 0;
260+
lfs_getattr(&lfs, "hello/hello", 'D', buffer+18, 9) => LFS_ERR_NOATTR;
245261
memcmp(buffer, "fffffffff", 9) => 0;
246262
memcmp(buffer+9, "ccccc\0\0\0\0", 9) => 0;
247263
memcmp(buffer+18, "\0\0\0\0\0\0\0\0\0", 9) => 0;

0 commit comments

Comments
 (0)