diff --git a/include/file.h b/include/file.h index b3b89593..c0eee6c1 100644 --- a/include/file.h +++ b/include/file.h @@ -77,6 +77,11 @@ struct empfile { * visible to caller of ef_write() and are written to the file. */ void (*prewrite)(int id, void *old, void *elt); + /* + * Called after table size changed, with file type as argument. + * Return -1 and set errno to make the operation fail. + */ + int (*onresize)(int type); }; struct emptypedstr { diff --git a/src/lib/common/file.c b/src/lib/common/file.c index 692ed187..4c63be71 100644 --- a/src/lib/common/file.c +++ b/src/lib/common/file.c @@ -156,6 +156,8 @@ ef_open(int type, int how, int nelt) } } + if (ep->onresize && ep->onresize(type) < 0) + return 0; return 1; } @@ -250,6 +252,8 @@ ef_close(int type) ep->fd = -1; } ep->baseid = ep->cids = ep->fids = 0; + if (ep->onresize && ep->onresize(type) < 0) + retval = 0; return retval; } @@ -487,25 +491,27 @@ ef_write(int type, int id, void *from) ep = &empfile[type]; if (CANT_HAPPEN((ep->flags & (EFF_MEM | EFF_PRIVATE)) == EFF_PRIVATE)) return 0; + if (CANT_HAPPEN((ep->flags & EFF_MEM) ? id >= ep->fids : id > ep->fids)) + return 0; /* not implemented */ + new_seqno(ep, from); + if (id >= ep->fids) { + /* write beyond end of file extends it, take note */ + ep->fids = id + 1; + if (ep->onresize && ep->onresize(type) < 0) + return 0; + } if (id >= ep->baseid && id < ep->baseid + ep->cids) cachep = ep->cache + (id - ep->baseid) * ep->size; else cachep = NULL; if (ep->prewrite) ep->prewrite(id, cachep, from); - if (CANT_HAPPEN((ep->flags & EFF_MEM) ? id >= ep->fids : id > ep->fids)) - return 0; /* not implemented */ - new_seqno(ep, from); if (ep->fd >= 0) { if (do_write(ep, from, id, 1) < 0) return 0; } if (cachep && cachep != from) /* update the cache if necessary */ memcpy(cachep, from, ep->size); - if (id >= ep->fids) { - /* write beyond end of file extends it, take note */ - ep->fids = id + 1; - } return 1; } @@ -634,6 +640,8 @@ ef_extend(int type, int count) } } ep->fids = id + count; + if (ep->onresize && ep->onresize(type) < 0) + return 0; return 1; } @@ -723,6 +731,8 @@ ef_truncate(int type, int count) ep->cids = count - ep->baseid; } + if (ep->onresize && ep->onresize(type) < 0) + return 0; return 1; } diff --git a/src/lib/common/filetable.c b/src/lib/common/filetable.c index 4894369c..2b92ab5c 100644 --- a/src/lib/common/filetable.c +++ b/src/lib/common/filetable.c @@ -62,21 +62,21 @@ /* Initializers for members flags... */ /* Unmapped cache */ #define UNMAPPED_CACHE(type, flags) \ - sizeof(type), (flags), NULL, 0, 0, 0, 0, -1, NULL, NULL, NULL + sizeof(type), (flags), NULL, 0, 0, 0, 0, -1, NULL, NULL, NULL, NULL /* * Mapped cache, array with known size. * Members cids, fids are not set. */ #define ARRAY_CACHE(array, flags) \ sizeof(*(array)), (flags), (char *)(array), \ - SZ((array)), 0, 0, 0, -1, NULL, NULL, NULL + SZ((array)), 0, 0, 0, -1, NULL, NULL, NULL, NULL /* * Mapped cache, array with unknown size. * Members csize, cids, fids are not set. */ #define PTR_CACHE(ptr, flags) \ sizeof(*(ptr)), (flags), (char *)(ptr), \ - 0, 0, 0, 0, -1, NULL, NULL, NULL + 0, 0, 0, 0, -1, NULL, NULL, NULL, NULL /* * Array-backed table. * The array's last element is the sentinel. @@ -84,7 +84,7 @@ #define ARRAY_TABLE(array, flags) \ sizeof(*(array)), (flags), (char *)(array), \ SZ((array)), 0, SZ((array)) - 1, SZ((array)) - 1, -1, \ - NULL, NULL, NULL + NULL, NULL, NULL, NULL /* Common configuration table flags */ #define EFF_CFG (EFF_PRIVATE | EFF_MEM | EFF_STATIC | EFF_SENTINEL) @@ -145,9 +145,9 @@ struct empfile empfile[] = { {EF_LOAN, "loan", "loan", loan_ca, UNMAPPED_CACHE(struct lonstr, EFF_TYPED)}, {EF_MAP, "map", "map", NULL, - 0, 0, NULL, 0, 0, 0, 0, -1, NULL, NULL, NULL}, + 0, 0, NULL, 0, 0, 0, 0, -1, NULL, NULL, NULL, NULL}, {EF_BMAP, "bmap", "bmap", NULL, - 0, 0, NULL, 0, 0, 0, 0, -1, NULL, NULL, NULL}, + 0, 0, NULL, 0, 0, 0, 0, -1, NULL, NULL, NULL, NULL}, {EF_COMM, "commodity", "commodity", commodity_ca, UNMAPPED_CACHE(struct comstr, EFF_TYPED | EFF_OWNER)}, {EF_LOST, "lost", "lostitems", lost_ca, @@ -197,7 +197,7 @@ struct empfile empfile[] = { ARRAY_TABLE(empfile, EFF_CFG)}, {EF_VERSION, "version", NULL, NULL, sizeof(PACKAGE_STRING), EFF_STATIC, version, 1, 0, 1, 1, -1, - NULL, NULL, NULL}, + NULL, NULL, NULL, NULL}, {EF_META, "meta", NULL, mdchr_ca, PTR_CACHE(mdchr_ca, EFF_CFG)}, @@ -237,7 +237,7 @@ struct empfile empfile[] = { /* Sentinel */ {EF_BAD, NULL, NULL, NULL, - 0, 0, NULL, 0, 0, 0, 0, -1, NULL, NULL, NULL}, + 0, 0, NULL, 0, 0, 0, 0, -1, NULL, NULL, NULL, NULL}, }; static void