jcs
/subtext
/amendments
/134
bile: Bug fixes, store highest ids when deleting
The previous fix was bogus, back it out.
The "o = &bile->map[n - 1]" line seems to have been erroneously copied
and pasted (many times) from another loop where I was going
backwards :(
Implement storage of highest ids seen when deleting, so that
bile_next_id hands out 1 higher than that id. This way we won't
re-use ids of deleted things like users, posts, etc.
jcs made amendment 134 over 2 years ago
--- bile.c Thu Jun 9 16:12:42 2022
+++ bile.c Sat Jun 11 19:59:05 2022
@@ -23,6 +23,7 @@ static short _bile_error = 0;
static short _bile_open_ignore_primary_map = 0;
+void bile_find_highest_ids(struct bile *bile);
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,
@@ -124,7 +125,7 @@ struct bile *
bile_open(const Str255 filename, short vrefnum)
{
struct bile *bile = NULL;
- struct bile_object map_obj;
+ struct bile_object map_obj, *o;
char magic[BILE_MAGIC_LEN + 1];
size_t file_size, map_size, size;
short fh, old_map_tried = 0;
@@ -291,7 +292,7 @@ bile_count_by_type(struct bile *bile, const OSType typ
_bile_error = bile->last_error = 0;
for (n = 0; n < bile->nobjects; n++) {
- o = &bile->map[n - 1];
+ o = &bile->map[n];
if (o->type == type)
count++;
}
@@ -309,7 +310,7 @@ bile_sorted_ids_by_type(struct bile *bile, const OSTyp
bile_check_sanity(bile);
for (n = 0; n < bile->nobjects; n++) {
- o = &bile->map[n - 1];
+ o = &bile->map[n];
if (o->type != type)
continue;
@@ -344,7 +345,7 @@ bile_get_nth_of_type(struct bile *bile, const size_t i
_bile_error = bile->last_error = 0;
for (n = 0; n < bile->nobjects; n++) {
- o = &bile->map[n - 1];
+ o = &bile->map[n];
if (o->type != type)
continue;
@@ -364,17 +365,24 @@ bile_next_id(struct bile *bile, const OSType type)
{
struct bile_object *o;
size_t n, id = 1;
+ unsigned long highest;
bile_check_sanity(bile);
_bile_error = bile->last_error = 0;
for (n = 0; n < bile->nobjects; n++) {
- o = &bile->map[n - 1];
+ o = &bile->map[n];
if (o->type == type && o->id >= id)
id = o->id + 1;
}
+ if (bile_read(bile, BILE_TYPE_HIGHESTID, type, &highest,
+ sizeof(unsigned long)) == sizeof(unsigned long)) {
+ if (highest > id)
+ id = highest + 1;
+ }
+
return id;
}
@@ -383,8 +391,9 @@ bile_delete(struct bile *bile, const OSType type, cons
{
static char zero[128] = { 0 };
struct bile_object *o;
- size_t pos, size, wsize;
-
+ size_t pos, size, wsize, n;
+ unsigned long highest;
+
bile_check_sanity(bile);
_bile_error = bile->last_error = 0;
@@ -413,10 +422,31 @@ bile_delete(struct bile *bile, const OSType type, cons
if (_bile_error)
return -1;
}
+
+ /*
+ * If this is the highest id of this type, store it so it won't get
+ * handed out again from bile_next_id
+ */
+ highest = id;
+ for (n = 0; n < bile->nobjects; n++) {
+ o = &bile->map[n];
+ if (o->type == type && o->id > highest) {
+ highest = o->id;
+ break;
+ }
+ }
- bile_write_map(bile);
- if (_bile_error)
- return -1;
+ if (highest == id) {
+ /* store the type as the id, and the highest id as the data */
+ bile_write(bile, BILE_TYPE_HIGHESTID, type, &highest,
+ sizeof(unsigned long));
+
+ /* bile_write wrote a new map for us */
+ } else {
+ bile_write_map(bile);
+ if (_bile_error)
+ return -1;
+ }
return 0;
}
@@ -710,19 +740,23 @@ short
bile_verify(struct bile *bile)
{
struct bile_object o;
- size_t n, size;
+ size_t n, size, pos;
char data;
bile_check_sanity(bile);
_bile_error = bile->last_error = 0;
- for (n = 0; n < bile->nobjects; n++) {
+ for (n = 0, pos = 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;
+
+ if (bile->map[n].pos <= pos)
+ return -1;
+ pos = bile->map[n].pos + bile->map[n].size;
}
return 0;
@@ -763,14 +797,13 @@ bile_alloc(struct bile *bile, const OSType type, const
_bile_error = bile->last_error = 0;
- /* find a last_pos we can use */
+ /* find a gap big enough to hold our object + its size */
for (n = 0; n < bile->nobjects; n++) {
- if (n > 0 &&
- bile->map[n].pos - last_pos >= (size + BILE_OBJECT_SIZE))
+ if (bile->map[n].pos - last_pos >= (size + BILE_OBJECT_SIZE))
break;
last_pos = bile->map[n].pos + BILE_OBJECT_SIZE + bile->map[n].size;
}
-
+
/*
* The map is always sorted, so walk the map to find out where to
* wedge a copy of this new object, then return a pointer to it in
--- bile.h Wed Jun 8 11:26:04 2022
+++ bile.h Sat Jun 11 20:00:38 2022
@@ -48,11 +48,12 @@
* [ map id - long ]
* [ map contents ]
*/
-#define BILE_MAGIC "BILE2"
-#define BILE_MAGIC_LEN 5
-#define BILE_TYPE_MAP '_BLM'
-#define BILE_TYPE_MAPPTR '_BL>'
-#define BILE_TYPE_PURGE '_BLP'
+#define BILE_MAGIC "BILE2"
+#define BILE_MAGIC_LEN 5
+#define BILE_TYPE_MAP '_BLM'
+#define BILE_TYPE_MAPPTR '_BL>'
+#define BILE_TYPE_PURGE '_BLP'
+#define BILE_TYPE_HIGHESTID '_BLH'
struct bile_object {
unsigned long pos;
@@ -75,6 +76,11 @@ struct bile_object {
#define BILE_ERR_NEED_UPGRADE_1 -4000
#define BILE_ERR_BOGUS_OBJECT -4001
+
+struct bile_highest_id {
+ OSType type;
+ unsigned long highest_id;
+};
struct bile {
struct bile_object map_ptr;