AmendHub

Download:

jcs

/

subtext

/

amendments

/

47

bile: A more Unix-like API, with bile_error like errno


jcs made amendment 47 over 2 years ago
--- bile.c Tue Jan 4 16:30:53 2022 +++ bile.c Wed Jan 5 20:45:19 2022 @@ -18,30 +18,38 @@ #include "bile.h" #include "util.h" -void bile_write_map(struct bile *bile); +static short _bile_error; + +short bile_write_map(struct bile *bile); void bile_sort_by_pos(struct bile *bile); -void bile_free(struct bile *bile, unsigned long id); -size_t bile_xwriteat(struct bile *bile, size_t pos, size_t len, void *data); +size_t bile_xwriteat(struct bile *bile, const size_t pos, const size_t len, + const void *data); +short +bile_error(void) +{ + return _bile_error; +} + struct bile * -bile_create(Str255 filename, OSType creator, OSType type) +bile_create(const Str255 filename, const OSType creator, const OSType type) { - struct bile *bile; + struct bile *bile = NULL; size_t len; char *magic; - short error, fh; + short fh; + _bile_error = 0; + /* create file */ - error = Create(filename, 0, creator, type); - if (error) - panic("bile_create: failed to create %s: %d", PtoCstr(filename), - error); + _bile_error = Create(filename, 0, creator, type); + if (_bile_error) + return NULL; - error = FSOpen(filename, 0, &fh); - if (error) - panic("bile_create: failed to open %s: %d", PtoCstr(filename), - error); - + _bile_error = FSOpen(filename, 0, &fh); + if (_bile_error) + return NULL; + bile = xmalloczero(sizeof(struct bile)); bile->vrefid = fh; memcpy(bile->filename, filename, sizeof(bile->filename)); @@ -49,21 +57,21 @@ bile_create(Str255 filename, OSType creator, OSType ty /* write magic */ len = BILE_MAGIC_LEN; magic = xstrdup(BILE_MAGIC); - error = FSWrite(bile->vrefid, &len, magic); + _bile_error = FSWrite(bile->vrefid, &len, magic); free(magic); - if (error) - goto write_error; + if (_bile_error) + goto create_bail; /* write empty map */ len = sizeof(long); - error = FSWrite(bile->vrefid, &len, &bile->map_pos); - if (error) - goto write_error; + _bile_error = FSWrite(bile->vrefid, &len, &bile->map_pos); + if (_bile_error) + goto create_bail; len = sizeof(long); - error = FSWrite(bile->vrefid, &len, &bile->map_size); - if (error) - goto write_error; + _bile_error = FSWrite(bile->vrefid, &len, &bile->map_size); + if (_bile_error) + goto create_bail; GetFPos(fh, &bile->file_size); @@ -73,41 +81,44 @@ bile_create(Str255 filename, OSType creator, OSType ty return bile; -write_error: - panic("bile_create: failed to write to %s: %d", PtoCstr(filename), - error); +create_bail: + FSClose(bile->vrefid); + if (bile != NULL) + free(bile); + return NULL; } struct bile * -bile_open(Str255 filename) +bile_open(const Str255 filename) { - struct bile *bile; + struct bile *bile = NULL; size_t file_size, map_size, size; - short error, fh; + short fh; char magic[BILE_MAGIC_LEN + 1]; + _bile_error = 0; + /* open file */ - error = FSOpen(filename, 0, &fh); - if (error) - panic("bile_open: failed to open %s: %d", PtoCstr(filename), - error); + _bile_error = FSOpen(filename, 0, &fh); + if (_bile_error) + return NULL; - error = SetFPos(fh, fsFromLEOF, 0); - if (error) - panic("bile_open: SetFPos: %d", error); + _bile_error = SetFPos(fh, fsFromLEOF, 0); + if (_bile_error) + goto open_bail; GetFPos(fh, &file_size); - SetFPos(fh, fsFromStart, 0); /* verify magic */ size = BILE_MAGIC_LEN; - error = FSRead(fh, &size, &magic); - if (error) - panic("bile_open: failed reading from %s: %d", PtoCstr(filename), - error); + _bile_error = FSRead(fh, &size, &magic); + if (_bile_error) + goto open_bail; - if (strncmp(magic, BILE_MAGIC, BILE_MAGIC_LEN) != 0) - panic("bile_open: bad magic in %s", PtoCstr(filename)); + if (strncmp(magic, BILE_MAGIC, BILE_MAGIC_LEN) != 0) { + _bile_error = -1; + goto open_bail; + } bile = xmalloczero(sizeof(struct bile)); bile->vrefid = fh; @@ -116,55 +127,68 @@ bile_open(Str255 filename) /* load map */ size = sizeof(long); - error = FSRead(fh, &size, &bile->map_pos); - if (error) - goto read_error; + _bile_error = FSRead(bile->vrefid, &size, &bile->map_pos); + if (_bile_error) + goto open_bail; size = sizeof(long); - error = FSRead(fh, &size, &bile->map_size); - if (error) - goto read_error; + _bile_error = FSRead(bile->vrefid, &size, &bile->map_size); + if (_bile_error) + goto open_bail; if (bile->map_pos + bile->map_size > file_size) panic("bile_open: map points to %lu + %lu, but file is only %lu", bile->map_pos, bile->map_size, file_size); if (bile->map_size) { - error = SetFPos(bile->vrefid, fsFromStart, bile->map_pos + + _bile_error = SetFPos(bile->vrefid, fsFromStart, bile->map_pos + BILE_OBJECT_SIZE); - if (error) - goto read_error; + if (_bile_error) + goto open_bail; /* read size */ size = bile->map_size; bile->map = xmalloczero(bile->map_size); - error = FSRead(fh, &size, bile->map); - if (error) - goto read_error; + _bile_error = FSRead(bile->vrefid, &size, bile->map); + if (_bile_error) + goto open_bail; bile->nobjects = bile->map_size / BILE_OBJECT_SIZE; } return bile; -read_error: - panic("bile_open: failed reading from %s: %d", PtoCstr(filename), - error); +open_bail: + FSClose(bile->vrefid); + if (bile != NULL) + free(bile); + return NULL; } void bile_close(struct bile *bile) { + if (bile == NULL) + panic("bile_close: bogus bile"); + + _bile_error = 0; + FSClose(bile->vrefid); - free(bile->map); + if (bile->map != NULL) + free(bile->map); } /* XXX: these become invalid once we re-sort, should we return a copy? */ struct bile_object * -bile_find(struct bile *bile, OSType type, unsigned long id) +bile_find(struct bile *bile, const OSType type, const unsigned long id) { struct bile_object *o; unsigned long n; + if (bile == NULL) + panic("bile_find: bogus bile"); + + _bile_error = 0; + /* look backwards, optimizing for newer data */ for (n = bile->nobjects; n > 0; n--) { o = &bile->map[n - 1]; @@ -176,11 +200,36 @@ bile_find(struct bile *bile, OSType type, unsigned lon } size_t -bile_next_id(struct bile *bile, OSType type) +bile_count_by_type(struct bile *bile, const OSType type) { struct bile_object *o; + size_t n, count = 0; + + if (bile == NULL) + panic("bile_count_by_type: bogus bile"); + + _bile_error = 0; + + for (n = 0; n < bile->nobjects; n++) { + o = &bile->map[n - 1]; + if (o->type == type) + count++; + } + + return count; +} + +size_t +bile_next_id(struct bile *bile, const OSType type) +{ + struct bile_object *o; size_t n, id = 1; + + if (bile == NULL) + panic("bile_next_id: bogus bile"); + _bile_error = 0; + for (n = 0; n < bile->nobjects; n++) { o = &bile->map[n - 1]; if (o->type == type && o->id >= id) @@ -191,12 +240,18 @@ bile_next_id(struct bile *bile, OSType type) } struct bile_object * -bile_alloc(struct bile *bile, OSType type, unsigned long id, size_t size) +bile_alloc(struct bile *bile, const OSType type, const unsigned long id, + const size_t size) { struct bile_object *new, *o; size_t last_pos = BILE_HEADER_LEN; short n; + + if (bile == NULL) + panic("bile_alloc: bogus bile"); + _bile_error = 0; + bile->map = xreallocarray(bile->map, bile->nobjects + 1, BILE_OBJECT_SIZE); @@ -231,7 +286,12 @@ bile_sort_by_pos(struct bile *bile) { short i, j; struct bile_object o; + + if (bile == NULL) + panic("bile_sort_by_pos: bogus bile"); + _bile_error = 0; + for (i = 0; i < bile->nobjects; i++) { for (j = 0; j < bile->nobjects - i - 1; j++) { if (bile->map[j].pos > bile->map[j + 1].pos) { @@ -243,128 +303,204 @@ bile_sort_by_pos(struct bile *bile) } } -void -bile_delete(struct bile *bile, OSType type, unsigned long id) +short +bile_delete(struct bile *bile, const OSType type, const unsigned long id) { struct bile_object *o; size_t pos, size, wsize; - short error; char *zero; + + if (bile == NULL) + panic("bile_delete: bogus bile"); + _bile_error = 0; + o = bile_find(bile, type, id); - if (o == NULL) - return; + if (o == NULL) { + _bile_error = -1; + return -1; + } o->type = BILE_PURGE_TYPE; pos = o->pos; size = o->size + BILE_OBJECT_SIZE; bile_write_map(bile); + if (_bile_error) + return -1; - error = SetFPos(bile->vrefid, fsFromStart, pos); - if (error) - goto write_error; + _bile_error = SetFPos(bile->vrefid, fsFromStart, pos); + if (_bile_error) + return -1; zero = xmalloczero(128); while (size > 0) { wsize = MIN(128, size); size -= wsize; - error = FSWrite(bile->vrefid, &wsize, zero); - if (error) - goto write_error; + _bile_error = FSWrite(bile->vrefid, &wsize, zero); + if (_bile_error) + return -1; } - return; - -write_error: - panic("bile_delete: failed writing to %s: %d", PtoCstr(bile->filename), - error); + return 0; } size_t -bile_read(struct bile *bile, OSType type, unsigned long id, char **data) +bile_read_object(struct bile *bile, const struct bile_object *o, + char *data, const size_t len) { - struct bile_object *o, verify; - size_t rsize; - short error; - - o = bile_find(bile, type, id); + struct bile_object verify; + size_t rsize, wantlen, ret; + + if (bile == NULL) + panic("bile_read_object: bogus bile"); if (o == NULL) - return -1; - - if (*data == NULL) - *data = xmalloc(o->size); - + panic("bile_read_object: NULL object passed"); + if (data == NULL) + panic("bile_read_object: NULL data pointer passed"); + if (len == 0) + panic("bile_read_object: zero len"); + + _bile_error = 0; + if (o->pos + BILE_OBJECT_SIZE + o->size > bile->file_size) - panic("bile_read: object %ld pos %ld size %ld > file size %ld", - id, o->pos, o->size, bile->file_size); - - error = SetFPos(bile->vrefid, fsFromStart, o->pos + BILE_OBJECT_SIZE); - if (error) - goto read_error; + panic("bile_read_object: object %ld pos %ld size %ld > file size %ld", + o->id, o->pos, o->size, bile->file_size); + + _bile_error = SetFPos(bile->vrefid, fsFromStart, o->pos); + if (_bile_error) + panic("bile_read_object: object %lu points to bogus position %lu", + o->id, o->pos); rsize = BILE_OBJECT_SIZE; - error = FSRead(bile->vrefid, &rsize, &verify); - if (error) - goto read_error; - if (verify.id != id) - panic("bile_read: object %ld pos %ld wrong id %ld, expected %ld", - id, o->pos, verify.id, id); - if (verify.type != type) - panic("bile_read: object %ld pos %ld wrong type %ld, expected %ld", - id, o->pos, verify.type, type); + _bile_error = FSRead(bile->vrefid, &rsize, &verify); + if (_bile_error) + return 0; + + if (verify.id != o->id) + panic("bile_read_object: object %ld pos %ld wrong id %ld, expected %ld", + o->id, o->pos, verify.id, o->id); + if (verify.type != o->type) + panic("bile_read_object: object %ld pos %ld wrong type %ld, expected %ld", + o->id, o->pos, verify.type, o->type); if (verify.size != o->size) - panic("bile_read: object %ld pos %ld wrong size %ld, expected %ld", - id, o->pos, verify.size, o->size); + panic("bile_read_object: object %ld pos %ld wrong size %ld, expected %ld", + o->id, o->pos, verify.size, o->size); - rsize = o->size; - error = FSRead(bile->vrefid, &rsize, *data); - if (error) - goto read_error; - if (rsize != o->size) - panic("bile_open: needed to read %ld, read %ld", o->size, rsize); + wantlen = len; + if (wantlen > o->size) + wantlen = o->size; + + rsize = wantlen; + _bile_error = FSRead(bile->vrefid, &rsize, data); + if (_bile_error) + return 0; + + if (rsize != wantlen) + panic("bile_read: needed to read %ld, read %ld", wantlen, rsize); - return o->size; + return rsize; +} + +size_t +bile_read(struct bile *bile, const OSType type, const unsigned long id, + char *data, const size_t len) +{ + struct bile_object *o; + + if (bile == NULL) + panic("bile_read: bogus bile"); + if (data == NULL) + panic("bile_read: NULL data pointer passed"); -read_error: - panic("bile_open: failed reading from %s: %d", PtoCstr(bile->filename), - error); + _bile_error = 0; + + o = bile_find(bile, type, id); + if (o == NULL) { + _bile_error = -1; + return 0; + } + + return bile_read_object(bile, o, data, len); } size_t -bile_write(struct bile *bile, OSType type, unsigned long id, char *data, - size_t size) +bile_read_alloc(struct bile *bile, const OSType type, + const unsigned long id, char **data) { + struct bile_object *o; + + if (bile == NULL) + panic("bile_read: bogus bile"); + if (data == NULL) + panic("bile_read: NULL data pointer passed"); + + _bile_error = 0; + + o = bile_find(bile, type, id); + if (o == NULL) { + _bile_error = -1; + return 0; + } + + *data = xmalloczero(o->size); + return bile_read_object(bile, o, *data, o->size); +} + +size_t +bile_write(struct bile *bile, const OSType type, const unsigned long id, + const void *data, const size_t len) +{ struct bile_object *old, *new_obj; - size_t ret; + size_t wrote; short error; - + + if (bile == NULL) + panic("bile_write: bogus bile"); + if (len == 0) + panic("bile_write: zero len passed"); + if (data == NULL) + panic("bile_write: NULL data pointer passed"); + + _bile_error = 0; + old = bile_find(bile, type, id); if (old) old->type = BILE_PURGE_TYPE; - new_obj = bile_alloc(bile, type, id, size); + new_obj = bile_alloc(bile, type, id, len); bile_xwriteat(bile, new_obj->pos, BILE_OBJECT_SIZE, new_obj); - bile_xwriteat(bile, new_obj->pos + BILE_OBJECT_SIZE, size, data); + if (_bile_error) + return 0; + wrote = bile_xwriteat(bile, new_obj->pos + BILE_OBJECT_SIZE, len, + data); + if (wrote == 0 || _bile_error) + return 0; SetFPos(bile->vrefid, fsFromLEOF, 0); GetFPos(bile->vrefid, &bile->file_size); bile_write_map(bile); - - return ret; + if (_bile_error) + return 0; + + return wrote; } -void +short bile_write_map(struct bile *bile) { struct bile_object *obj, *new_map_obj, *new_map; size_t new_map_size, new_nobjects; - size_t pos, n; - short error; + size_t n; + + if (bile == NULL) + panic("bile_write_map: bogus bile"); + _bile_error = 0; + /* allocate a new map slightly larger than we need */ new_nobjects = bile->nobjects; if (!bile->map_pos) @@ -390,9 +526,13 @@ bile_write_map(struct bile *bile) new_map_obj->size = new_map_size; bile->nobjects = new_nobjects; - pos = bile_xwriteat(bile, new_map_obj->pos, BILE_OBJECT_SIZE, - &new_map_obj); - pos = bile_xwriteat(bile, pos, new_map_size, new_map); + bile_xwriteat(bile, new_map_obj->pos, BILE_OBJECT_SIZE, &new_map_obj); + if (_bile_error) + return -1; + bile_xwriteat(bile, new_map_obj->pos + BILE_OBJECT_SIZE, new_map_size, + new_map); + if (_bile_error) + return -1; SetFPos(bile->vrefid, fsFromLEOF, 0); GetFPos(bile->vrefid, &bile->file_size); @@ -404,44 +544,54 @@ bile_write_map(struct bile *bile) bile->map_size = new_map_obj->size; /* write new header to point at new map object */ - pos = bile_xwriteat(bile, BILE_MAGIC_LEN, sizeof(long), - &bile->map_pos); - pos = bile_xwriteat(bile, pos, sizeof(long), &bile->map_size); + bile_xwriteat(bile, BILE_MAGIC_LEN, sizeof(long), &bile->map_pos); + if (_bile_error) + return -1; + bile_xwriteat(bile, BILE_MAGIC_LEN + sizeof(long), sizeof(long), + &bile->map_size); + if (_bile_error) + return -1; /* TODO: flush? */ + + return 0; } size_t -bile_xwriteat(struct bile *bile, size_t pos, size_t len, void *data) +bile_xwriteat(struct bile *bile, const size_t pos, const size_t len, + const void *data) { short error; size_t wsize; long asize; + if (bile == NULL) + panic("bile_xwriteat: bogus bile"); + + _bile_error = 0; + if (pos == bile->file_size) { - error = SetFPos(bile->vrefid, fsFromLEOF, 0); + _bile_error = SetFPos(bile->vrefid, fsFromLEOF, 0); } else if (pos > bile->file_size) { /* may as well allocate to cover len too */ asize = pos + len - bile->file_size; - error = Allocate(bile->vrefid, &asize); - if (error) - panic("bile_xwriteat: failed Allocate of %lu in %s: %d", - pos + len - bile->file_size, PtoCstr(bile->filename), error); - error = SetFPos(bile->vrefid, fsFromLEOF, 0); + _bile_error = Allocate(bile->vrefid, &asize); + if (_bile_error) + return 0; + _bile_error = SetFPos(bile->vrefid, fsFromLEOF, 0); } else - error = SetFPos(bile->vrefid, fsFromStart, pos); - if (error) - panic("bile_xwriteat: failed SetFPos to %lu in %s: %d", - pos, PtoCstr(bile->filename), error); + _bile_error = SetFPos(bile->vrefid, fsFromStart, pos); + + if (_bile_error) + return 0; wsize = len; - error = FSWrite(bile->vrefid, &wsize, data); - if (error) - panic("bile_xwriteat: failed writing %lu at %lu to %s: %d", - len, pos, PtoCstr(bile->filename), error); + _bile_error = FSWrite(bile->vrefid, &wsize, data); + if (_bile_error) + return 0; if (wsize != len) panic("bile_xwriteat: short write of %lu at %lu to %s: %lu", len, pos, PtoCstr(bile->filename), wsize); - return pos + len; + return wsize; } --- bile.h Tue Jan 4 16:21:13 2022 +++ bile.h Wed Jan 5 20:41:23 2022 @@ -14,6 +14,9 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifndef __BILE_H__ +#define __BILE_H__ + #include "util.h" /* @@ -61,16 +64,25 @@ struct bile { size_t nobjects; }; -struct bile * bile_create(Str255 filename, OSType creator, OSType type); -struct bile * bile_open(Str255 filename); +short bile_error(void); +struct bile * bile_create(const Str255 filename, const OSType creator, + const OSType type); +struct bile * bile_open(const Str255 filename); void bile_close(struct bile *bile); -struct bile_object * bile_find(struct bile *bile, OSType type, - unsigned long id); -size_t bile_next_id(struct bile *bile, OSType type); -struct bile_object * bile_alloc(struct bile *bile, OSType type, - unsigned long id, size_t size); -void bile_delete(struct bile *bile, OSType type, unsigned long id); -size_t bile_read(struct bile *bile, OSType type, unsigned long id, - char **data); -size_t bile_write(struct bile *bile, OSType type, unsigned long id, - char *data, size_t size); +struct bile_object * bile_find(struct bile *bile, const OSType type, + const unsigned long id); +size_t bile_count_by_type(struct bile *bile, const OSType type); +size_t bile_next_id(struct bile *bile, const OSType type); +struct bile_object * bile_alloc(struct bile *bile, const OSType type, + const unsigned long id, const size_t size); +short bile_delete(struct bile *bile, OSType type, const unsigned long id); +size_t bile_read_object(struct bile *bile, const struct bile_object *o, + char *data, const size_t len); +size_t bile_read(struct bile *bile, const OSType type, + const unsigned long id, char *data, const size_t len); +size_t bile_read_alloc(struct bile *bile, const OSType type, + const unsigned long id, char **data); +size_t bile_write(struct bile *bile, OSType type, const unsigned long id, + const void *data, const size_t len); + +#endif