AmendHub

Download:

jcs

/

subtext

/

amendments

/

58

bile: Sync with upstream


jcs made amendment 58 over 2 years ago
--- bile.c Tue Jan 18 16:50:07 2022 +++ bile.c Fri Jan 21 17:59:46 2022 @@ -19,12 +19,16 @@ #include "util.h" /* for errors not specific to a bile */ -static short _bile_error; +static short _bile_error = 0; +static short _bile_open_ignore_primary_map = 0; + struct bile_object * bile_alloc(struct bile *bile, const OSType type, const unsigned long id, const size_t size); struct bile_object * bile_object_in_map(struct bile *bile, const OSType type, const unsigned long id); +short bile_read_map(struct bile *bile, + struct bile_object *map_ptr); short bile_write_map(struct bile *bile); void bile_sort_by_pos(struct bile *bile); size_t bile_xwriteat(struct bile *bile, const size_t pos, @@ -47,7 +51,7 @@ bile_create(const Str255 filename, short vrefnum, cons { struct bile *bile = NULL; size_t len; - char *magic; + char *tmp; short fh; _bile_error = 0; @@ -69,9 +73,9 @@ bile_create(const Str255 filename, short vrefnum, cons /* write magic */ len = BILE_MAGIC_LEN; - magic = xstrdup(BILE_MAGIC); - _bile_error = FSWrite(bile->frefnum, &len, magic); - free(magic); + tmp = xstrdup(BILE_MAGIC); + _bile_error = FSWrite(bile->frefnum, &len, tmp); + free(tmp); if (_bile_error) goto create_bail; @@ -81,6 +85,20 @@ bile_create(const Str255 filename, short vrefnum, cons if (_bile_error) goto create_bail; + len = sizeof(bile->old_map_ptr); + _bile_error = FSWrite(bile->frefnum, &len, &bile->old_map_ptr); + if (_bile_error) + goto create_bail; + + /* padding */ + len = BILE_HEADER_LEN - BILE_MAGIC_LEN - BILE_OBJECT_SIZE - + BILE_OBJECT_SIZE; + tmp = xmalloczero(len); + _bile_error = FSWrite(bile->frefnum, &len, tmp); + if (_bile_error) + goto create_bail; + free(tmp); + GetFPos(fh, &bile->file_size); if (bile->file_size != BILE_HEADER_LEN) @@ -101,9 +119,9 @@ bile_open(const Str255 filename, short vrefnum) { struct bile *bile = NULL; struct bile_object map_obj; - size_t file_size, map_size, size; - short fh; char magic[BILE_MAGIC_LEN + 1]; + size_t file_size, map_size, size; + short fh, old_map_tried = 0; _bile_error = 0; @@ -118,6 +136,12 @@ bile_open(const Str255 filename, short vrefnum) GetFPos(fh, &file_size); SetFPos(fh, fsFromStart, 0); + bile = xmalloczero(sizeof(struct bile)); + bile->vrefnum = vrefnum; + bile->frefnum = fh; + memcpy(bile->filename, filename, sizeof(bile->filename)); + bile->file_size = file_size; + /* verify magic */ size = BILE_MAGIC_LEN; _bile_error = FSRead(fh, &size, &magic); @@ -125,55 +149,36 @@ bile_open(const Str255 filename, short vrefnum) goto open_bail; if (strncmp(magic, BILE_MAGIC, BILE_MAGIC_LEN) != 0) { - _bile_error = -1; + if (strncmp(magic, BILE1_MAGIC, BILE1_MAGIC_LEN) == 0) + _bile_error = BILE_ERR_NEED_UPGRADE_1; + else + _bile_error = -1; goto open_bail; } - - bile = xmalloczero(sizeof(struct bile)); - bile->vrefnum = vrefnum; - bile->frefnum = fh; - memcpy(bile->filename, filename, sizeof(bile->filename)); - bile->file_size = file_size; - + /* load map pointer */ size = sizeof(bile->map_ptr); _bile_error = FSRead(bile->frefnum, &size, &bile->map_ptr); if (_bile_error) goto open_bail; + + /* old map pointer */ + size = sizeof(bile->old_map_ptr); + _bile_error = FSRead(bile->frefnum, &size, &bile->old_map_ptr); + if (_bile_error) + goto open_bail; - if (bile->map_ptr.pos + bile->map_ptr.size > file_size) - panic("bile_open: map points to %lu + %lu, but file is only %lu", - bile->map_ptr.pos, bile->map_ptr.size, file_size); - if (bile->map_ptr.size % BILE_OBJECT_SIZE != 0) - panic("bile_open: map pointer size is not a multiple of object " - "size (%lu): %lu", BILE_OBJECT_SIZE, bile->map_ptr.size); + if (_bile_open_ignore_primary_map) { + if (!bile->old_map_ptr.size) + goto open_bail; + bile->map_ptr = bile->old_map_ptr; + } if (bile->map_ptr.size) { - /* read and verify map object header map_ptr points to */ - _bile_error = SetFPos(bile->frefnum, fsFromStart, - bile->map_ptr.pos); - if (_bile_error) + if (bile_read_map(bile, &bile->map_ptr) != 0) { + warn("bile_open: Failed reading map"); goto open_bail; - - size = sizeof(struct bile_object); - _bile_error = FSRead(bile->frefnum, &size, &map_obj); - if (_bile_error) - goto open_bail; - - if (map_obj.pos != bile->map_ptr.pos) - panic("bile_open: map pointer points to %lu but object there " - "has position %lu", bile->map_ptr.pos, map_obj.pos); - if (map_obj.size != bile->map_ptr.size) - panic("bile_open: map is supposed to have size %lu but object " - "pointed to has size %lu", bile->map_ptr.size, map_obj.size); - - /* read entire map */ - size = map_obj.size; - bile->map = xmalloczero(size); - _bile_error = FSRead(bile->frefnum, &size, bile->map); - if (_bile_error) - goto open_bail; - bile->nobjects = map_obj.size / BILE_OBJECT_SIZE; + } } return bile; @@ -185,6 +190,52 @@ open_bail: return NULL; } +struct bile * +bile_open_recover_map(const Str255 filename, short vrefnum) +{ + struct bile *bile; + + _bile_open_ignore_primary_map = 1; + bile = bile_open(filename, vrefnum); + _bile_open_ignore_primary_map = 0; + + if (bile) { + bile->map_ptr = bile->old_map_ptr; + bile_write_map(bile); + } + + return bile; +} + +short +bile_autoflush(struct bile *bile, short val) +{ + bile->autoflush = val; +} + +short +bile_flush(struct bile *bile, short and_vol) +{ + IOParam pb; + short ret; + + memset(&pb, 0, sizeof(pb)); + pb.ioRefNum = bile->frefnum; + ret = PBFlushFile(&pb, false); + if (ret != noErr) + return ret; + + if (and_vol) { + memset(&pb, 0, sizeof(pb)); + /* XXX: this flushes default volume, maybe flush specific volume */ + ret = PBFlushVol(&pb, false); + if (ret != noErr) + return ret; + } + + return 0; +} + void bile_close(struct bile *bile) { @@ -345,30 +396,51 @@ bile_read_object(struct bile *bile, const struct bile_ _bile_error = bile->last_error = 0; - if (o->pos + BILE_OBJECT_SIZE + o->size > bile->file_size) - panic("bile_read_object: object %ld pos %ld size %ld > file size %ld", - o->id, o->pos, o->size, bile->file_size); + if (o->pos + BILE_OBJECT_SIZE + o->size > bile->file_size) { + warn("bile_read_object: object %s:%ld pos %ld size %ld > " + "file size %ld", OSTypeToString(o->type), o->id, o->pos, + o->size, bile->file_size); + _bile_error = bile->last_error = BILE_ERR_BOGUS_OBJECT; + return 0; + } - _bile_error = SetFPos(bile->frefnum, fsFromStart, o->pos); - if (_bile_error) - panic("bile_read_object: object %lu points to bogus position %lu", - o->id, o->pos); - + _bile_error = bile->last_error = SetFPos(bile->frefnum, fsFromStart, + o->pos); + if (_bile_error) { + warn("bile_read_object: object %s:%lu points to bogus position " + "%lu", OSTypeToString(o->type), o->id, o->pos); + _bile_error = bile->last_error = BILE_ERR_BOGUS_OBJECT; + return 0; + } + rsize = BILE_OBJECT_SIZE; - _bile_error = bile->last_error = FSRead(bile->frefnum, &rsize, &verify); + _bile_error = bile->last_error = FSRead(bile->frefnum, &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: object %ld pos %ld wrong size %ld, " - "expected %ld", o->id, o->pos, verify.size, o->size); - + if (verify.id != o->id) { + warn("bile_read_object: object %s:%ld pos %ld wrong id %ld, " + "expected %ld", OSTypeToString(o->type), o->id, o->pos, + verify.id, o->id); + _bile_error = bile->last_error = BILE_ERR_BOGUS_OBJECT; + return 0; + } + if (verify.type != o->type) { + warn("bile_read_object: object %s:%ld pos %ld wrong type %ld, " + "expected %ld", OSTypeToString(o->type), o->id, o->pos, + verify.type, o->type); + _bile_error = bile->last_error = BILE_ERR_BOGUS_OBJECT; + return 0; + } + if (verify.size != o->size) { + warn("bile_read_object: object %s:%ld pos %ld wrong size %ld, " + "expected %ld", OSTypeToString(o->type), o->id, o->pos, + verify.size, o->size); + _bile_error = bile->last_error = BILE_ERR_BOGUS_OBJECT; + return 0; + } + wantlen = len; if (wantlen > o->size) wantlen = o->size; @@ -378,9 +450,13 @@ bile_read_object(struct bile *bile, const struct bile_ if (_bile_error) return 0; - if (rsize != wantlen) - panic("bile_read: needed to read %ld, read %ld", wantlen, rsize); - + if (rsize != wantlen) { + warn("bile_read: %s:%lu: needed to read %ld, read %ld", + OSTypeToString(o->type), o->id, wantlen, rsize); + _bile_error = bile->last_error = BILE_ERR_BOGUS_OBJECT; + return 0; + } + return rsize; } @@ -460,8 +536,8 @@ bile_write(struct bile *bile, const OSType type, const new_obj = bile_alloc(bile, type, id, len); - bile_xwriteat(bile, new_obj->pos, new_obj, BILE_OBJECT_SIZE); - if (bile->last_error) + wrote = bile_xwriteat(bile, new_obj->pos, new_obj, BILE_OBJECT_SIZE); + if (wrote != BILE_OBJECT_SIZE || bile->last_error) return 0; wrote = bile_xwriteat(bile, new_obj->pos + BILE_OBJECT_SIZE, data, len); if (wrote != len || bile->last_error) @@ -477,21 +553,27 @@ bile_write(struct bile *bile, const OSType type, const return wrote; } - -void -bile_fsck(struct bile *bile) +short +bile_verify(struct bile *bile) { struct bile_object o; - size_t n; + size_t n, size; char data; if (bile == NULL) - panic("bile_fsck: bogus bile"); + panic("bile_verify: bogus bile"); _bile_error = bile->last_error = 0; - for (n = 0; n < bile->nobjects; n++) - bile_read_object(bile, &bile->map[n], &data, 1); + for (n = 0; n < bile->nobjects; n++) { + size = bile_read_object(bile, &bile->map[n], &data, 1); + if (bile_error(bile)) + return bile_error(bile); + else if (size == 0) + return -1; + } + + return 0; } /* Private API */ @@ -561,9 +643,63 @@ bile_alloc(struct bile *bile, const OSType type, const } short +bile_read_map(struct bile *bile, struct bile_object *map_ptr) +{ + size_t size; + struct bile_object map_obj, *map; + + if (map_ptr->pos + map_ptr->size > bile->file_size) { + warn("bile_read_map: map points to %lu + %lu, but file is only %lu", + map_ptr->pos, map_ptr->size, bile->file_size); + return -1; + } + + if (map_ptr->size % BILE_OBJECT_SIZE != 0) { + warn("bile_read_map: map pointer size is not a multiple of object " + "size (%lu): %lu", BILE_OBJECT_SIZE, map_ptr->size); + return -1; + } + + /* read and verify map object header map_ptr points to */ + _bile_error = SetFPos(bile->frefnum, fsFromStart, map_ptr->pos); + if (_bile_error) + return -1; + + size = sizeof(struct bile_object); + _bile_error = FSRead(bile->frefnum, &size, &map_obj); + if (_bile_error) + return -1; + + if (map_obj.pos != map_ptr->pos) { + warn("bile_read_map: map pointer points to %lu but object " + "there has position %lu", map_ptr->pos, map_obj.pos); + return -1; + } + + if (map_obj.size != map_ptr->size) { + warn("bile_read_map: map is supposed to have size %lu but " + "object pointed to has size %lu", map_ptr->size, map_obj.size); + return -1; + } + + /* read entire map */ + size = map_obj.size; + map = xmalloczero(size); + _bile_error = FSRead(bile->frefnum, &size, map); + if (_bile_error) { + free(map); + return -1; + } + + bile->map = map; + bile->nobjects = map_obj.size / BILE_OBJECT_SIZE; + + return 0; +} + +short bile_write_map(struct bile *bile) { - IOParam pb; struct bile_object *obj, *new_map_obj, *new_map, *new_map_obj_in_new_map = NULL; size_t new_map_size, new_nobjects, new_map_id; @@ -623,14 +759,20 @@ bile_write_map(struct bile *bile) SetFPos(bile->frefnum, fsFromLEOF, 0); GetFPos(bile->frefnum, &bile->file_size); - memset(&pb, 0, sizeof(pb)); - pb.ioRefNum = bile->frefnum; - PBFlushFile(&pb, false); - + if (bile->autoflush) { + if ((ret = bile_flush(bile, false)) != noErr) { + warn("bile_write_map: flush failed: %d", ret); + return -1; + } + } + /* successfully wrote new map, switch over */ free(bile->map); bile->nobjects = new_nobjects; bile->map = new_map; + bile->old_map_ptr.pos = bile->map_ptr.pos; + bile->old_map_ptr.size = bile->map_ptr.size; + bile->old_map_ptr.id = bile->map_ptr.id; bile->map_ptr.pos = new_map_obj->pos; bile->map_ptr.size = new_map_obj->size; bile->map_ptr.id = new_map_obj->id; @@ -640,9 +782,18 @@ bile_write_map(struct bile *bile) sizeof(bile->map_ptr)); if (bile->last_error) return -1; + bile_xwriteat(bile, BILE_MAGIC_LEN + sizeof(bile->map_ptr), + &bile->old_map_ptr, sizeof(bile->old_map_ptr)); + if (bile->last_error) + return -1; - PBFlushFile(&pb, false); - + if (bile->autoflush) { + if ((ret = bile_flush(bile, false)) != noErr) { + warn("bile_write_map: final flush failed: %d", ret); + return -1; + } + } + return 0; } --- bile.h Mon Jan 10 21:07:52 2022 +++ bile.h Fri Jan 21 17:58:40 2022 @@ -28,6 +28,12 @@ * [ pointer size - long ] * [ pointer type (_BL>) - long ] * [ pointer id - long ] + * [ previous map pointer object ] + * [ pointer position - long ] + * [ pointer size - long ] + * [ pointer type (_BL>) - long ] + * [ pointer id - long ] + * [ padding for future use ] * [ object[0] start (map points to this as its position) ] * [ object[0] position - long ] * [ object[0] size - long ] @@ -42,7 +48,7 @@ * [ map id - long ] * [ map contents ] */ -#define BILE_MAGIC "BILE1" +#define BILE_MAGIC "BILE2" #define BILE_MAGIC_LEN 5 #define BILE_TYPE_MAP '_BLM' #define BILE_TYPE_MAPPTR '_BL>' @@ -54,16 +60,28 @@ struct bile_object { OSType type; unsigned long id; }; -#define BILE_OBJECT_SIZE (sizeof(struct bile_object)) -#define BILE_HEADER_LEN (BILE_MAGIC_LEN + BILE_OBJECT_SIZE) +#define BILE_OBJECT_SIZE (sizeof(struct bile_object)) +#define BILE_HEADER_LEN 256 +#ifndef BILE1_MAGIC +#define BILE1_MAGIC "BILE1" +#endif +#ifndef BILE1_MAGIC_LEN +#define BILE1_MAGIC_LEN 5 +#endif + +#define BILE_ERR_NEED_UPGRADE_1 -4000 +#define BILE_ERR_BOGUS_OBJECT -4001 + struct bile { struct bile_object map_ptr; + struct bile_object old_map_ptr; short vrefnum, frefnum, last_error; Str255 filename; size_t file_size; struct bile_object *map; /* array of bile_objects */ size_t nobjects; + short autoflush; }; short bile_error(struct bile *bile); @@ -71,6 +89,10 @@ short bile_error(struct bile *bile); struct bile * bile_create(const Str255 filename, short vrefnum, const OSType creator, const OSType type); struct bile * bile_open(const Str255 filename, short vrefnum); +struct bile * bile_open_recover_map(const Str255 filename, + short vrefnum); +short bile_flush(struct bile *bile, short and_vol); +short bile_autoflush(struct bile *bile, short val); void bile_close(struct bile *bile); struct bile_object * bile_find(struct bile *bile, const OSType type, @@ -94,6 +116,6 @@ size_t bile_read_alloc(struct bile *bile, size_t bile_write(struct bile *bile, OSType type, const unsigned long id, const void *data, const size_t len); -void bile_fsck(struct bile *bile); +short bile_verify(struct bile *bile); #endif