From: Mark Andrews Date: Wed, 12 Sep 2012 01:44:24 +0000 (+1000) Subject: 3373. [bug] win32: open raw files in binary mode. [RT #30944] X-Git-Tag: v9.10.0a1~901 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7e9d637131516486630290d36c4c0db544cb700e;p=thirdparty%2Fbind9.git 3373. [bug] win32: open raw files in binary mode. [RT #30944] --- diff --git a/CHANGES b/CHANGES index f187f7db6de..83e0ca75189 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +3373. [bug] win32: open raw files in binary mode. [RT #30944] + 3372. [bug] Silence spurious "deleted from unreachable cache" messages. [RT #30501] diff --git a/lib/dns/master.c b/lib/dns/master.c index 26eb6c6e2b9..46867dcc5b8 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -2215,19 +2215,21 @@ load_raw(dns_loadctx_t *lctx) { unsigned int loop_cnt = 0; dns_rdatacallbacks_t *callbacks; unsigned char namebuf[DNS_NAME_MAXWIRE]; - isc_region_t r; - dns_name_t name; + dns_fixedname_t fixed; + dns_name_t *name; rdatalist_head_t head, dummy; dns_rdatalist_t rdatalist; isc_mem_t *mctx = lctx->mctx; dns_rdata_t *rdata = NULL; unsigned int rdata_size = 0; int target_size = TSIZ; - isc_buffer_t target; + isc_buffer_t target, buf; unsigned char *target_mem = NULL; + dns_decompress_t dctx; REQUIRE(DNS_LCTX_VALID(lctx)); callbacks = lctx->callbacks; + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE); if (lctx->first) { result = load_header(lctx); @@ -2250,6 +2252,9 @@ load_raw(dns_loadctx_t *lctx) { } isc_buffer_init(&target, target_mem, target_size); + dns_fixedname_init(&fixed); + name = dns_fixedname_name(&fixed); + /* * In the following loop, we regard any error fatal regardless of * whether "MANYERRORS" is set in the context option. This is because @@ -2261,7 +2266,7 @@ load_raw(dns_loadctx_t *lctx) { for (loop_cnt = 0; (lctx->loop_cnt == 0 || loop_cnt < lctx->loop_cnt); loop_cnt++) { - unsigned int i, rdcount, consumed_name; + unsigned int i, rdcount; isc_uint16_t namelen; isc_uint32_t totallen; size_t minlen, readlen; @@ -2351,12 +2356,11 @@ load_raw(dns_loadctx_t *lctx) { lctx->f); if (result != ISC_R_SUCCESS) goto cleanup; + isc_buffer_setactive(&target, (unsigned int)namelen); - isc_buffer_activeregion(&target, &r); - dns_name_init(&name, NULL); - dns_name_fromregion(&name, &r); - isc_buffer_forward(&target, (unsigned int)namelen); - consumed_name = isc_buffer_consumedlength(&target); + result = dns_name_fromwire(name, &target, &dctx, 0, NULL); + if (result != ISC_R_SUCCESS) + goto cleanup; /* Rdata contents. */ if (rdcount > rdata_size) { @@ -2387,7 +2391,7 @@ load_raw(dns_loadctx_t *lctx) { /* Partial Commit. */ ISC_LIST_APPEND(head, &rdatalist, link); - result = commit(callbacks, lctx, &head, &name, + result = commit(callbacks, lctx, &head, name, NULL, 0); for (j = 0; j < i; j++) { ISC_LIST_UNLINK(rdatalist.rdata, @@ -2399,8 +2403,6 @@ load_raw(dns_loadctx_t *lctx) { /* Rewind the buffer and continue */ isc_buffer_clear(&target); - isc_buffer_add(&target, consumed_name); - isc_buffer_forward(&target, consumed_name); rdcount -= i; @@ -2420,11 +2422,20 @@ load_raw(dns_loadctx_t *lctx) { if (result != ISC_R_SUCCESS) goto cleanup; isc_buffer_setactive(&target, (unsigned int)rdlen); - isc_buffer_activeregion(&target, &r); - isc_buffer_forward(&target, (unsigned int)rdlen); - dns_rdata_fromregion(&rdata[i], rdatalist.rdclass, - rdatalist.type, &r); - + /* + * It is safe to have the source active region and + * the target available region be the same if + * decompression is disabled (see dctx above) and we + * are not downcasing names (options == 0). + */ + isc_buffer_init(&buf, isc_buffer_current(&target), + (unsigned int)rdlen); + result = dns_rdata_fromwire(&rdata[i], + rdatalist.rdclass, + rdatalist.type, &target, + &dctx, 0, &buf); + if (result != ISC_R_SUCCESS) + goto cleanup; ISC_LIST_APPEND(rdatalist.rdata, &rdata[i], link); } @@ -2441,7 +2452,7 @@ load_raw(dns_loadctx_t *lctx) { ISC_LIST_APPEND(head, &rdatalist, link); /* Commit this RRset. rdatalist will be unlinked. */ - result = commit(callbacks, lctx, &head, &name, NULL, 0); + result = commit(callbacks, lctx, &head, name, NULL, 0); for (i = 0; i < rdcount; i++) { ISC_LIST_UNLINK(rdatalist.rdata, &rdata[i], link); diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c index 90360aaef65..42ba1f5fa40 100644 --- a/lib/dns/masterdump.c +++ b/lib/dns/masterdump.c @@ -1665,7 +1665,8 @@ dns_master_dumptostream3(isc_mem_t *mctx, dns_db_t *db, } static isc_result_t -opentmp(isc_mem_t *mctx, const char *file, char **tempp, FILE **fp) { +opentmp(isc_mem_t *mctx, dns_masterformat_t format, const char *file, + char **tempp, FILE **fp) { FILE *f = NULL; isc_result_t result; char *tempname = NULL; @@ -1680,7 +1681,10 @@ opentmp(isc_mem_t *mctx, const char *file, char **tempp, FILE **fp) { if (result != ISC_R_SUCCESS) goto cleanup; - result = isc_file_openunique(tempname, &f); + if (format == dns_masterformat_text) + result = isc_file_openunique(tempname, &f); + else + result = isc_file_bopenunique(tempname, &f); if (result != ISC_R_SUCCESS) { isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR, @@ -1735,7 +1739,7 @@ dns_master_dumpinc3(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, if (file == NULL) return (ISC_R_NOMEMORY); - result = opentmp(mctx, filename, &tempname, &f); + result = opentmp(mctx, format, filename, &tempname, &f); if (result != ISC_R_SUCCESS) goto cleanup; @@ -1799,7 +1803,7 @@ dns_master_dump3(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, char *tempname; dns_dumpctx_t *dctx = NULL; - result = opentmp(mctx, filename, &tempname, &f); + result = opentmp(mctx, format, filename, &tempname, &f); if (result != ISC_R_SUCCESS) return (result); diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index 683130ac833..b6e715eff0b 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -445,6 +445,8 @@ dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass, REQUIRE(DNS_RDATA_INITIALIZED(rdata)); REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); } + REQUIRE(source != NULL); + REQUIRE(target != NULL); if (type == 0) return (DNS_R_FORMERR); @@ -545,13 +547,11 @@ rdata_validate(isc_buffer_t *src, isc_buffer_t *dest, dns_rdataclass_t rdclass, dns_rdatatype_t type) { dns_decompress_t dctx; - dns_rdata_t rdata = DNS_RDATA_INIT; isc_result_t result; dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE); isc_buffer_setactive(src, isc_buffer_usedlength(src)); - result = dns_rdata_fromwire(&rdata, rdclass, type, src, - &dctx, 0, dest); + result = dns_rdata_fromwire(NULL, rdclass, type, src, &dctx, 0, dest); dns_decompress_invalidate(&dctx); return (result); @@ -1182,7 +1182,8 @@ txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) { if (n > tregion.length) return (ISC_R_NOSPACE); - memcpy(tregion.base, sregion.base, n); + if (tregion.base != sregion.base) + memcpy(tregion.base, sregion.base, n); isc_buffer_forward(source, n); isc_buffer_add(target, n); return (ISC_R_SUCCESS); @@ -1331,7 +1332,8 @@ multitxt_fromwire(isc_buffer_t *source, isc_buffer_t *target) { if (n > tregion.length) return (ISC_R_NOSPACE); - memcpy(tregion.base, sregion.base, n); + if (tregion.base != sregion.base) + memcpy(tregion.base, sregion.base, n); isc_buffer_forward(source, n); isc_buffer_add(target, n); isc_buffer_activeregion(source, &sregion); @@ -1507,7 +1509,8 @@ mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) { isc_buffer_availableregion(target, &tr); if (length > tr.length) return (ISC_R_NOSPACE); - memcpy(tr.base, base, length); + if (tr.base != base) + memcpy(tr.base, base, length); isc_buffer_add(target, length); return (ISC_R_SUCCESS); } diff --git a/lib/isc/include/isc/file.h b/lib/isc/include/isc/file.h index 11c037d27b7..e87837a5f9e 100644 --- a/lib/isc/include/isc/file.h +++ b/lib/isc/include/isc/file.h @@ -101,15 +101,22 @@ isc_file_mktemplate(const char *path, char *buf, size_t buflen); * of the path with the internal template string. */ - isc_result_t isc_file_openunique(char *templet, FILE **fp); isc_result_t isc_file_openuniqueprivate(char *templet, FILE **fp); isc_result_t isc_file_openuniquemode(char *templet, int mode, FILE **fp); +isc_result_t +isc_file_bopenunique(char *templet, FILE **fp); +isc_result_t +isc_file_bopenuniqueprivate(char *templet, FILE **fp); +isc_result_t +isc_file_bopenuniquemode(char *templet, int mode, FILE **fp); /*!< * \brief Create and open a file with a unique name based on 'templet'. + * isc_file_bopen*() open the file in binary mode in Windows. + * isc_file_open*() open the file in text mode in Windows. * * Notes: *\li 'template' is a reserved work in C++. If you want to complain diff --git a/lib/isc/unix/file.c b/lib/isc/unix/file.c index 31fd49ddcbe..8c2b86972b7 100644 --- a/lib/isc/unix/file.c +++ b/lib/isc/unix/file.c @@ -373,6 +373,23 @@ isc_file_openuniquemode(char *templet, int mode, FILE **fp) { return (result); } +isc_result_t +isc_file_bopenunique(char *templet, FILE **fp) { + int mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; + return (isc_file_openuniquemode(templet, mode, fp)); +} + +isc_result_t +isc_file_bopenuniqueprivate(char *templet, FILE **fp) { + int mode = S_IWUSR|S_IRUSR; + return (isc_file_openuniquemode(templet, mode, fp)); +} + +isc_result_t +isc_file_bopenuniquemode(char *templet, int mode, FILE **fp) { + return (isc_file_openuniquemode(templet, mode, fp)); +} + isc_result_t isc_file_remove(const char *filename) { int r; diff --git a/lib/isc/win32/file.c b/lib/isc/win32/file.c index 9bc8d49090e..9d6f1e77e2b 100644 --- a/lib/isc/win32/file.c +++ b/lib/isc/win32/file.c @@ -45,10 +45,14 @@ * */ static int -gettemp(char *path, int *doopen) { +gettemp(char *path, isc_boolean_t binary, int *doopen) { char *start, *trv; struct stat sbuf; int pid; + int flags = O_CREAT|O_EXCL|O_RDWR; + + if (binary) + flags |= O_BINARY; trv = strrchr(path, 'X'); trv++; @@ -81,8 +85,7 @@ gettemp(char *path, int *doopen) { for (;;) { if (doopen) { if ((*doopen = - open(path, O_CREAT|O_EXCL|O_RDWR, - _S_IREAD | _S_IWRITE)) >= 0) + open(path, flags, _S_IREAD | _S_IWRITE)) >= 0) return (1); if (errno != EEXIST) return (0); @@ -108,10 +111,10 @@ gettemp(char *path, int *doopen) { } static int -mkstemp(char *path) { +mkstemp(char *path, isc_boolean_t binary) { int fd; - return (gettemp(path, &fd) ? fd : -1); + return (gettemp(path, binary, &fd) ? fd : -1); } /* @@ -204,7 +207,7 @@ isc_file_safemovefile(const char *oldname, const char *newname) { exists = TRUE; strcpy(buf, newname); strcat(buf, ".XXXXX"); - tmpfd = mkstemp(buf); + tmpfd = mkstemp(buf, ISC_TRUE); if (tmpfd > 0) _close(tmpfd); DeleteFile(buf); @@ -339,7 +342,7 @@ isc_file_renameunique(const char *file, char *templet) { REQUIRE(file != NULL); REQUIRE(templet != NULL); - fd = mkstemp(templet); + fd = mkstemp(templet, ISC_TRUE); if (fd == -1) result = isc__errno2result(errno); else @@ -355,20 +358,8 @@ isc_file_renameunique(const char *file, char *templet) { return (result); } -isc_result_t -isc_file_openuniqueprivate(char *templet, FILE **fp) { - int mode = _S_IREAD | _S_IWRITE; - return (isc_file_openuniquemode(templet, mode, fp)); -} - -isc_result_t -isc_file_openunique(char *templet, FILE **fp) { - int mode = _S_IREAD | _S_IWRITE; - return (isc_file_openuniquemode(templet, mode, fp)); -} - -isc_result_t -isc_file_openuniquemode(char *templet, int mode, FILE **fp) { +static isc_result_t +openuniquemode(char *templet, int mode, isc_boolean_t binary, FILE **fp) { int fd; FILE *f; isc_result_t result = ISC_R_SUCCESS; @@ -379,7 +370,7 @@ isc_file_openuniquemode(char *templet, int mode, FILE **fp) { /* * Win32 does not have mkstemp. Using emulation above. */ - fd = mkstemp(templet); + fd = mkstemp(templet, binary); if (fd == -1) result = isc__errno2result(errno); @@ -389,7 +380,7 @@ isc_file_openuniquemode(char *templet, int mode, FILE **fp) { #else (void)fchmod(fd, mode); #endif - f = fdopen(fd, "w+"); + f = fdopen(fd, binary ? "wb+", "w+"); if (f == NULL) { result = isc__errno2result(errno); (void)remove(templet); @@ -401,6 +392,40 @@ isc_file_openuniquemode(char *templet, int mode, FILE **fp) { return (result); } +isc_result_t +isc_file_openuniqueprivate(char *templet, FILE **fp) { + int mode = _S_IREAD | _S_IWRITE; + return (openuniquemode(templet, mode, ISC_FALSE, fp)); +} + +isc_result_t +isc_file_openunique(char *templet, FILE **fp) { + int mode = _S_IREAD | _S_IWRITE; + return (openuniquemode(templet, mode, ISC_FALSE, fp)); +} + +isc_result_t +isc_file_openuniquemode(char *templet, int mode, FILE **fp) { + return (openuniquemode(templet, mode, ISC_FALSE, fp)); +} + +isc_result_t +isc_file_bopenuniqueprivate(char *templet, FILE **fp) { + int mode = _S_IREAD | _S_IWRITE; + return (openuniquemode(templet, mode, ISC_TRUE, fp)); +} + +isc_result_t +isc_file_bopenunique(char *templet, FILE **fp) { + int mode = _S_IREAD | _S_IWRITE; + return (openuniquemode(templet, mode, ISC_TRUE, fp)); +} + +isc_result_t +isc_file_bopenuniquemode(char *templet, int mode, FILE **fp) { + return (openuniquemode(templet, mode, ISC_TRUE, fp)); +} + isc_result_t isc_file_remove(const char *filename) { int r; diff --git a/lib/isc/win32/libisc.def b/lib/isc/win32/libisc.def index eee911e8ea0..a6ac6186d1a 100644 --- a/lib/isc/win32/libisc.def +++ b/lib/isc/win32/libisc.def @@ -220,6 +220,9 @@ isc_event_allocate isc_event_free isc_file_absolutepath isc_file_basename +isc_file_bopenunique +isc_file_bopenuniquemode +isc_file_bopenuniqueprivate isc_file_exists isc_file_getmodtime isc_file_getsize