diff --git a/CHANGES b/CHANGES index 44e6cdda41..b0c45a3bdd 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +3598. [cleanup] Improved portability of map file code. [RT #33820] + 3597. [bug] Ensure automatic-resigning heaps are reconstructed when loading zones in map format. [RT #33381] diff --git a/lib/dns/include/dns/rbt.h b/lib/dns/include/dns/rbt.h index 7433d90872..9158be6e2a 100644 --- a/lib/dns/include/dns/rbt.h +++ b/lib/dns/include/dns/rbt.h @@ -153,7 +153,7 @@ typedef isc_result_t (*dns_rbtfindcallback_t)(dns_rbtnode_t *node, typedef isc_result_t (*dns_rbtdatawriter_t)(FILE *file, unsigned char *data, - isc_uint32_t version, + void *arg, isc_uint64_t *crc); typedef isc_result_t (*dns_rbtdatafixer_t)(dns_rbtnode_t *rbtnode, @@ -689,8 +689,8 @@ dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum); * \li ISC_R_QUOTA if 'quantum' nodes have been destroyed. */ -long -dns_rbt_serialize_align(long target); +off_t +dns_rbt_serialize_align(off_t target); /*%< * Align the provided integer to a pointer-size boundary. * This should be used if, during serialization of data to a will-be @@ -700,7 +700,7 @@ dns_rbt_serialize_align(long target); isc_result_t dns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt, dns_rbtdatawriter_t datawriter, - isc_uint32_t serial, long *offset); + void *writer_arg, off_t *offset); /*%< * Write out the RBT structure and its data to a file. * diff --git a/lib/dns/journal.c b/lib/dns/journal.c index 022a3e280f..05878e119e 100644 --- a/lib/dns/journal.c +++ b/lib/dns/journal.c @@ -387,7 +387,8 @@ journal_header_encode(journal_header_t *cooked, journal_rawheader_t *raw) { static isc_result_t journal_seek(dns_journal_t *j, isc_uint32_t offset) { isc_result_t result; - result = isc_stdio_seek(j->fp, (long)offset, SEEK_SET); + + result = isc_stdio_seek(j->fp, (off_t)offset, SEEK_SET); if (result != ISC_R_SUCCESS) { isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR, "%s: seek: %s", j->filename, diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c index bd70f5279f..9ce5acaa52 100644 --- a/lib/dns/rbt.c +++ b/lib/dns/rbt.c @@ -156,7 +156,7 @@ serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left, static isc_result_t serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent, - dns_rbtdatawriter_t datawriter, isc_uint32_t serial, + dns_rbtdatawriter_t datawriter, void *writer_arg, uintptr_t *where, isc_uint64_t *crc); /* * The following functions allow you to get the actual address of a pointer @@ -420,7 +420,7 @@ write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset, { file_header_t header; isc_result_t result; - long location; + off_t location; if (FILE_VERSION[0] == '\0') { memset(FILE_VERSION, 0, sizeof(FILE_VERSION)); @@ -445,9 +445,7 @@ write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset, header.crc = crc; - location = ftell(file); - if (location < 0) - return (ISC_R_FAILURE); + CHECK(isc_stdio_tell(file, &location)); location = dns_rbt_serialize_align(location); CHECK(isc_stdio_seek(file, location, SEEK_SET)); CHECK(isc_stdio_write(&header, 1, sizeof(file_header_t), file, NULL)); @@ -466,7 +464,7 @@ serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left, uintptr_t data, isc_uint64_t *crc) { dns_rbtnode_t temp_node; - long file_position; + off_t file_position; unsigned char *node_data; size_t datasize; isc_result_t result; @@ -476,10 +474,7 @@ serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left, INSIST(node != NULL); - file_position = ftell(file); - if (file_position < 0) - return (ISC_R_FAILURE); - + CHECK(isc_stdio_tell(file, &file_position)); file_position = dns_rbt_serialize_align(file_position); CHECK(isc_stdio_seek(file, file_position, SEEK_SET)); @@ -546,12 +541,11 @@ serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left, static isc_result_t serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent, - dns_rbtdatawriter_t datawriter, isc_uint32_t serial, + dns_rbtdatawriter_t datawriter, void *writer_arg, uintptr_t *where, isc_uint64_t *crc) { uintptr_t left = 0, right = 0, down = 0, data = 0; - long location = 0; - long offset_adjust; + off_t location = 0, offset_adjust; isc_result_t result; if (node == NULL) { @@ -561,14 +555,9 @@ serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent, } /* Reserve space for current node. */ - location = ftell(file); - if (location < 0) - return (ISC_R_FAILURE); + CHECK(isc_stdio_tell(file, &location)); location = dns_rbt_serialize_align(location); CHECK(isc_stdio_seek(file, location, SEEK_SET)); - location = ftell(file); - if (location < 0) - return (ISC_R_FAILURE); offset_adjust = dns_rbt_serialize_align(location + NODE_SIZE(node)); CHECK(isc_stdio_seek(file, offset_adjust, SEEK_SET)); @@ -580,28 +569,21 @@ serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent, * will break the way the crc hash is computed. */ CHECK(serialize_nodes(file, getleft(node, NULL), location, - datawriter, serial, &left, crc)); + datawriter, writer_arg, &left, crc)); CHECK(serialize_nodes(file, getright(node, NULL), location, - datawriter, serial, &right, crc)); + datawriter, writer_arg, &right, crc)); CHECK(serialize_nodes(file, getdown(node, NULL), location, - datawriter, serial, &down, crc)); + datawriter, writer_arg, &down, crc)); if (node->data != NULL) { - long ret; + off_t ret; - ret = ftell(file); - if (ret < 0) - return (ISC_R_FAILURE); + CHECK(isc_stdio_tell(file, &ret)); ret = dns_rbt_serialize_align(ret); - CHECK(isc_stdio_seek(file, ret, SEEK_SET)); - - ret = ftell(file); - if (ret < 0) - return (ISC_R_FAILURE); data = ret; - datawriter(file, node->data, serial, crc); + datawriter(file, node->data, writer_arg, crc); } /* Seek back to reserved space. */ @@ -614,15 +596,15 @@ serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent, CHECK(isc_stdio_seek(file, 0, SEEK_END)); if (where != NULL) - *where = location; + *where = (uintptr_t) location; cleanup: return (result); } -long -dns_rbt_serialize_align(long target) { - long offset = target % 8; +off_t +dns_rbt_serialize_align(off_t target) { + off_t offset = target % 8; if (offset == 0) return (target); @@ -633,10 +615,10 @@ dns_rbt_serialize_align(long target) { isc_result_t dns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt, dns_rbtdatawriter_t datawriter, - isc_uint32_t serial, long *offset) + void *writer_arg, off_t *offset) { isc_result_t result; - long header_position, node_position, end_position; + off_t header_position, node_position, end_position; isc_uint64_t crc; REQUIRE(file != NULL); @@ -645,24 +627,17 @@ dns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt, isc_crc64_init(&crc); - header_position = ftell(file); - if (header_position < 0) - return (ISC_R_FAILURE); + CHECK(isc_stdio_tell(file, &header_position)); /* Write dummy header */ CHECK(dns_rbt_zero_header(file)); /* Serialize nodes */ - node_position = ftell(file); - if (node_position < 0) - return (ISC_R_FAILURE); - + CHECK(isc_stdio_tell(file, &node_position)); CHECK(serialize_nodes(file, rbt->root, 0, datawriter, - serial, NULL, &crc)); - end_position = ftell(file); - if (end_position < 0) - return (ISC_R_FAILURE); + writer_arg, NULL, &crc)); + CHECK(isc_stdio_tell(file, &end_position)); if (node_position == end_position) { CHECK(isc_stdio_seek(file, header_position, SEEK_SET)); *offset = 0; diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index b0a153b482..728b3da96f 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -511,7 +511,7 @@ struct dns_rbtdb { * Base values for the mmap() code. */ void * mmap_location; - isc_uint64_t mmap_size; + size_t mmap_size; /* Locked by tree_lock. */ dns_rbt_t * tree; @@ -1107,7 +1107,8 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) { isc_mem_detach(&rbtdb->hmctx); if (rbtdb->mmap_location != NULL) - isc_file_munmap(rbtdb->mmap_location, (size_t) rbtdb->mmap_size); + isc_file_munmap(rbtdb->mmap_location, + (size_t) rbtdb->mmap_size); isc_mem_putanddetach(&rbtdb->common.mctx, rbtdb, sizeof(*rbtdb)); isc_ondestroy_notify(&ondest, rbtdb); @@ -7093,12 +7094,12 @@ deserialize(void *arg, FILE *f, off_t offset) { header = (rbtdb_file_header_t *)(base + offset); rbtdb->mmap_location = base; - rbtdb->mmap_size = filesize; + rbtdb->mmap_size = (size_t) filesize; rbtdb->origin_node = NULL; if (header->tree != 0) { result = dns_rbt_deserialize_tree(base, filesize, - (size_t) header->tree, + (off_t) header->tree, rbtdb->common.mctx, delete_callback, rbtdb, rbt_datafixer, rbtdb, @@ -7118,7 +7119,7 @@ deserialize(void *arg, FILE *f, off_t offset) { if (header->nsec != 0) { result = dns_rbt_deserialize_tree(base, filesize, - (size_t) header->nsec, + (off_t) header->nsec, rbtdb->common.mctx, delete_callback, rbtdb, rbt_datafixer, rbtdb, @@ -7134,7 +7135,7 @@ deserialize(void *arg, FILE *f, off_t offset) { if (header->nsec3 != 0) { result = dns_rbt_deserialize_tree(base, filesize, - (size_t) header->nsec3, + (off_t) header->nsec3, rbtdb->common.mctx, delete_callback, rbtdb, rbt_datafixer, rbtdb, @@ -7241,18 +7242,24 @@ endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { * by the void *data pointer in the dns_rbtnode */ static isc_result_t -rbt_datawriter(FILE *rbtfile, unsigned char *data, isc_uint32_t serial, +rbt_datawriter(FILE *rbtfile, unsigned char *data, void *arg, isc_uint64_t *crc) { + rbtdb_version_t *version = (rbtdb_version_t *) arg; + rbtdb_serial_t serial; rdatasetheader_t newheader; rdatasetheader_t *header = (rdatasetheader_t *) data, *next; - size_t where, size, cooked; + off_t where, cooked; + size_t size; unsigned char *p; - isc_result_t result; - static const char pad[sizeof(char *)]; + isc_result_t result = ISC_R_SUCCESS; + char pad[sizeof(char *)]; REQUIRE(rbtfile != NULL); REQUIRE(data != NULL); + REQUIRE(version != NULL); + + serial = version->serial; for (; header != NULL; header = next) { next = header->next; @@ -7268,7 +7275,7 @@ rbt_datawriter(FILE *rbtfile, unsigned char *data, isc_uint32_t serial, if (header == NULL) continue; - where = ftell(rbtfile); + CHECK(isc_stdio_tell(rbtfile, &where)); size = dns_rdataslab_size((unsigned char *) header, sizeof(rdatasetheader_t)); @@ -7298,30 +7305,26 @@ rbt_datawriter(FILE *rbtfile, unsigned char *data, isc_uint32_t serial, #endif isc_crc64_update(crc, (unsigned char *) &newheader, sizeof(rdatasetheader_t)); - result = isc_stdio_write(&newheader, - sizeof(rdatasetheader_t), 1, - rbtfile, NULL); - if (result != ISC_R_SUCCESS) - return (result); + CHECK(isc_stdio_write(&newheader, sizeof(rdatasetheader_t), 1, + rbtfile, NULL)); isc_crc64_update(crc, p + sizeof(rdatasetheader_t), size - sizeof(rdatasetheader_t)); - result = isc_stdio_write(p + sizeof(rdatasetheader_t), - size - sizeof(rdatasetheader_t), 1, rbtfile, NULL); - if (result != ISC_R_SUCCESS) - return (result); + CHECK(isc_stdio_write(p + sizeof(rdatasetheader_t), + size - sizeof(rdatasetheader_t), 1, + rbtfile, NULL)); /* * Pad to force alignment. */ - if (cooked != size) { - result = isc_stdio_write(pad, cooked - size, 1, - rbtfile, NULL); - if (result != ISC_R_SUCCESS) - return (result); + if (size != (size_t) cooked) { + memset(pad, 0, sizeof(pad)); + CHECK(isc_stdio_write(pad, cooked - size, 1, + rbtfile, NULL)); } } - return (ISC_R_SUCCESS); + failure: + return (result); } /* @@ -7348,8 +7351,8 @@ rbtdb_zero_header(FILE *rbtfile) { * itself that should be stored here. */ static isc_result_t -rbtdb_write_header(FILE *rbtfile, long tree_location, long nsec_location, - long nsec3_location) +rbtdb_write_header(FILE *rbtfile, off_t tree_location, off_t nsec_location, + off_t nsec3_location) { rbtdb_file_header_t header; isc_result_t result; @@ -7365,9 +7368,9 @@ rbtdb_write_header(FILE *rbtfile, long tree_location, long nsec_location, memcpy(header.version2, FILE_VERSION, sizeof(header.version2)); header.ptrsize = (isc_uint32_t) sizeof(void *); header.bigendian = (1 == htonl(1)) ? 1 : 0; - header.tree = tree_location; - header.nsec = nsec_location; - header.nsec3 = nsec3_location; + header.tree = (isc_uint64_t) tree_location; + header.nsec = (isc_uint64_t) nsec_location; + header.nsec3 = (isc_uint64_t) nsec3_location; result = isc_stdio_write(&header, 1, sizeof(rbtdb_file_header_t), rbtfile, NULL); fflush(rbtfile); @@ -7380,10 +7383,7 @@ serialize(dns_db_t *db, dns_dbversion_t *ver, FILE *rbtfile) { rbtdb_version_t *version = (rbtdb_version_t *) ver; dns_rbtdb_t *rbtdb; isc_result_t result; - long tree_location; - long nsec_location; - long nsec3_location; - long header_location; + off_t tree_location, nsec_location, nsec3_location, header_location; rbtdb = (dns_rbtdb_t *)db; @@ -7405,20 +7405,14 @@ serialize(dns_db_t *db, dns_dbversion_t *ver, FILE *rbtfile) { * NOTE: need to do something better with the return codes, &= will * not work. */ - header_location = ftell(rbtfile); - if (header_location < 0) - return (ISC_R_FAILURE); - + CHECK(isc_stdio_tell(rbtfile, &header_location)); CHECK(rbtdb_zero_header(rbtfile)); CHECK(dns_rbt_serialize_tree(rbtfile, rbtdb->tree, rbt_datawriter, - (isc_uint32_t) version->serial, - &tree_location)); + version, &tree_location)); CHECK(dns_rbt_serialize_tree(rbtfile, rbtdb->nsec, rbt_datawriter, - (isc_uint32_t) version->serial, - &nsec_location)); + version, &nsec_location)); CHECK(dns_rbt_serialize_tree(rbtfile, rbtdb->nsec3, rbt_datawriter, - (isc_uint32_t) version->serial, - &nsec3_location)); + version, &nsec3_location)); CHECK(isc_stdio_seek(rbtfile, header_location, SEEK_SET)); CHECK(rbtdb_write_header(rbtfile, tree_location, nsec_location, diff --git a/lib/dns/tests/rbt_test.c b/lib/dns/tests/rbt_test.c index 01fab10da7..2ab2425c48 100644 --- a/lib/dns/tests/rbt_test.c +++ b/lib/dns/tests/rbt_test.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -106,20 +107,25 @@ delete_data(void *data, void *arg) { } static isc_result_t -write_data(FILE *file, unsigned char *datap, isc_uint32_t serial, - isc_uint64_t *crc) { +write_data(FILE *file, unsigned char *datap, void *arg, isc_uint64_t *crc) { + isc_result_t result; size_t ret = 0; data_holder_t *data = (data_holder_t *)datap; data_holder_t temp; - uintptr_t where = ftell(file); + off_t where; - UNUSED(serial); + UNUSED(arg); + REQUIRE(file != NULL); REQUIRE(crc != NULL); REQUIRE(data != NULL); REQUIRE((data->len == 0 && data->data == NULL) || (data->len != 0 && data->data != NULL)); + result = isc_stdio_tell(file, &where); + if (result != ISC_R_SUCCESS) + return (result); + temp = *data; temp.data = (data->len == 0 ? NULL @@ -332,7 +338,8 @@ ATF_TC_BODY(serialize, tc) { printf("serialization begins.\n"); rbtfile = fopen("./zone.bin", "w+b"); ATF_REQUIRE(rbtfile != NULL); - result = dns_rbt_serialize_tree(rbtfile, rbt, write_data, 0, &offset); + result = dns_rbt_serialize_tree(rbtfile, rbt, write_data, NULL, + &offset); ATF_REQUIRE(result == ISC_R_SUCCESS); dns_rbt_destroy(&rbt); @@ -400,7 +407,8 @@ ATF_TC_BODY(deserialize_corrupt, tc) { add_test_data(mctx, rbt); rbtfile = fopen("./zone.bin", "w+b"); ATF_REQUIRE(rbtfile != NULL); - result = dns_rbt_serialize_tree(rbtfile, rbt, write_data, 0, &offset); + result = dns_rbt_serialize_tree(rbtfile, rbt, write_data, NULL, + &offset); ATF_REQUIRE(result == ISC_R_SUCCESS); dns_rbt_destroy(&rbt); diff --git a/lib/isc/include/isc/stdio.h b/lib/isc/include/isc/stdio.h index 1a7ae642d5..2cade512b6 100644 --- a/lib/isc/include/isc/stdio.h +++ b/lib/isc/include/isc/stdio.h @@ -48,7 +48,11 @@ isc_stdio_close(FILE *f); /*% Seek */ isc_result_t -isc_stdio_seek(FILE *f, long offset, int whence); +isc_stdio_seek(FILE *f, off_t offset, int whence); + +/*% Tell */ +isc_result_t +isc_stdio_tell(FILE *f, off_t *offsetp); /*% Read */ isc_result_t diff --git a/lib/isc/unix/errno2result.c b/lib/isc/unix/errno2result.c index f20aa295ca..2fc1953be4 100644 --- a/lib/isc/unix/errno2result.c +++ b/lib/isc/unix/errno2result.c @@ -58,6 +58,10 @@ isc___errno2result(int posixerrno, const char *file, unsigned int line) { case ENFILE: case EMFILE: return (ISC_R_TOOMANYOPENFILES); +#ifdef EOVERFLOW + case EOVERFLOW: + return (ISC_R_RANGE); +#endif case EPIPE: #ifdef ECONNRESET case ECONNRESET: diff --git a/lib/isc/unix/stdio.c b/lib/isc/unix/stdio.c index 360c8c644a..6adfd70167 100644 --- a/lib/isc/unix/stdio.c +++ b/lib/isc/unix/stdio.c @@ -24,6 +24,7 @@ #include #include +#include #include "errno2result.h" @@ -50,16 +51,30 @@ isc_stdio_close(FILE *f) { } isc_result_t -isc_stdio_seek(FILE *f, long offset, int whence) { +isc_stdio_seek(FILE *f, off_t offset, int whence) { int r; - r = fseek(f, offset, whence); + r = fseeko(f, offset, whence); if (r == 0) return (ISC_R_SUCCESS); else return (isc__errno2result(errno)); } +isc_result_t +isc_stdio_tell(FILE *f, off_t *offsetp) { + off_t r; + + REQUIRE(offsetp != NULL); + + r = ftello(f); + if (r >= 0) { + *offsetp = r; + return (ISC_R_SUCCESS); + } else + return (isc__errno2result(errno)); +} + isc_result_t isc_stdio_read(void *ptr, size_t size, size_t nmemb, FILE *f, size_t *nret) { isc_result_t result = ISC_R_SUCCESS; diff --git a/lib/isc/win32/errno2result.c b/lib/isc/win32/errno2result.c index c3d54d632e..2ff09e542e 100644 --- a/lib/isc/win32/errno2result.c +++ b/lib/isc/win32/errno2result.c @@ -57,6 +57,10 @@ isc__errno2resultx(int posixerrno, const char *file, int line) { return (ISC_R_IOERROR); case ENOMEM: return (ISC_R_NOMEMORY); +#ifdef EOVERFLOW + case EOVERFLOW: + return (ISC_R_RANGE); +#endif case ENFILE: case EMFILE: case WSAEMFILE: diff --git a/lib/isc/win32/libisc.def b/lib/isc/win32/libisc.def index 02dd93d941..7f3cb62e18 100644 --- a/lib/isc/win32/libisc.def +++ b/lib/isc/win32/libisc.def @@ -512,6 +512,7 @@ isc_stdio_open isc_stdio_read isc_stdio_seek isc_stdio_sync +isc_stdio_tell isc_stdio_write isc_stdtime_get isc_string_append diff --git a/lib/isc/win32/stdio.c b/lib/isc/win32/stdio.c index 427a8e1e18..7ff233fee3 100644 --- a/lib/isc/win32/stdio.c +++ b/lib/isc/win32/stdio.c @@ -23,6 +23,7 @@ #include #include +#include #include "errno2result.h" @@ -49,16 +50,30 @@ isc_stdio_close(FILE *f) { } isc_result_t -isc_stdio_seek(FILE *f, long offset, int whence) { +isc_stdio_seek(FILE *f, off_t offset, int whence) { int r; - r = fseek(f, offset, whence); + r = fseeko(f, offset, whence); if (r == 0) return (ISC_R_SUCCESS); else return (isc__errno2result(errno)); } +isc_result_t +isc_stdio_tell(FILE *f, off_t *offsetp) { + off_t r; + + REQUIRE(offsetp != NULL); + + r = ftello(f); + if (r >= 0) { + *offsetp = r; + return (ISC_R_SUCCESS); + } else + return (isc__errno2result(errno)); +} + isc_result_t isc_stdio_read(void *ptr, size_t size, size_t nmemb, FILE *f, size_t *nret) { isc_result_t result = ISC_R_SUCCESS;