summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bind/lib/isc/unix/file.c
diff options
context:
space:
mode:
authorderaadt <deraadt@openbsd.org>2019-12-16 16:16:22 +0000
committerderaadt <deraadt@openbsd.org>2019-12-16 16:16:22 +0000
commit2fc5abb04c862f358e234358caea4444e15db068 (patch)
tree1c77d5b577fef0399be14245b2108ca9c1a8819d /usr.sbin/bind/lib/isc/unix/file.c
parentNeed to include message size in the maximum buffer calculation. (diff)
downloadwireguard-openbsd-2fc5abb04c862f358e234358caea4444e15db068.tar.xz
wireguard-openbsd-2fc5abb04c862f358e234358caea4444e15db068.zip
Update to bind-9.10.5-P3, which appears to have been the last ISC version.
We only use this tree to build dig and nslookup. Our previous version predated edns0 support in those tools, and we want that. This is the worst code I've looked at in years, with layers and layers of spaghetti abstraction clearly unfit for reuse, but then reused anyways, and the old ones remain behind. So this is a 8MB diff. florian, sthen, and otto tried this merge before but failed.
Diffstat (limited to 'usr.sbin/bind/lib/isc/unix/file.c')
-rw-r--r--usr.sbin/bind/lib/isc/unix/file.c339
1 files changed, 303 insertions, 36 deletions
diff --git a/usr.sbin/bind/lib/isc/unix/file.c b/usr.sbin/bind/lib/isc/unix/file.c
index 4fc69cd49f6..75980292713 100644
--- a/usr.sbin/bind/lib/isc/unix/file.c
+++ b/usr.sbin/bind/lib/isc/unix/file.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2011-2016 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@@ -27,11 +27,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
@@ -48,7 +44,7 @@
* SUCH DAMAGE.
*/
-/* $ISC: file.c,v 1.47.18.2 2005/04/29 00:17:07 marka Exp $ */
+/* $Id: file.c,v 1.6 2019/12/16 16:16:27 deraadt Exp $ */
/*! \file */
@@ -65,8 +61,14 @@
#include <sys/stat.h>
#include <sys/time.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
#include <isc/dir.h>
#include <isc/file.h>
+#include <isc/log.h>
+#include <isc/mem.h>
#include <isc/random.h>
#include <isc/string.h>
#include <isc/time.h>
@@ -95,31 +97,88 @@ file_stats(const char *file, struct stat *stats) {
return (result);
}
+static isc_result_t
+fd_stats(int fd, struct stat *stats) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(stats != NULL);
+
+ if (fstat(fd, stats) != 0)
+ result = isc__errno2result(errno);
+
+ return (result);
+}
+
+isc_result_t
+isc_file_getsizefd(int fd, off_t *size) {
+ isc_result_t result;
+ struct stat stats;
+
+ REQUIRE(size != NULL);
+
+ result = fd_stats(fd, &stats);
+
+ if (result == ISC_R_SUCCESS)
+ *size = stats.st_size;
+
+ return (result);
+}
+
+isc_result_t
+isc_file_mode(const char *file, mode_t *modep) {
+ isc_result_t result;
+ struct stat stats;
+
+ REQUIRE(modep != NULL);
+
+ result = file_stats(file, &stats);
+ if (result == ISC_R_SUCCESS)
+ *modep = (stats.st_mode & 07777);
+
+ return (result);
+}
+
isc_result_t
-isc_file_getmodtime(const char *file, isc_time_t *time) {
+isc_file_getmodtime(const char *file, isc_time_t *modtime) {
isc_result_t result;
struct stat stats;
REQUIRE(file != NULL);
- REQUIRE(time != NULL);
+ REQUIRE(modtime != NULL);
result = file_stats(file, &stats);
if (result == ISC_R_SUCCESS)
- /*
- * XXXDCL some operating systems provide nanoseconds, too,
- * such as BSD/OS via st_mtimespec.
- */
- isc_time_set(time, stats.st_mtime, 0);
+#ifdef ISC_PLATFORM_HAVESTATNSEC
+ isc_time_set(modtime, stats.st_mtime, stats.st_mtim.tv_nsec);
+#else
+ isc_time_set(modtime, stats.st_mtime, 0);
+#endif
return (result);
}
isc_result_t
-isc_file_settime(const char *file, isc_time_t *time) {
+isc_file_getsize(const char *file, off_t *size) {
+ isc_result_t result;
+ struct stat stats;
+
+ REQUIRE(file != NULL);
+ REQUIRE(size != NULL);
+
+ result = file_stats(file, &stats);
+
+ if (result == ISC_R_SUCCESS)
+ *size = stats.st_size;
+
+ return (result);
+}
+
+isc_result_t
+isc_file_settime(const char *file, isc_time_t *when) {
struct timeval times[2];
- REQUIRE(file != NULL && time != NULL);
+ REQUIRE(file != NULL && when != NULL);
/*
* tv_sec is at least a 32 bit quantity on all platforms we're
@@ -131,7 +190,7 @@ isc_file_settime(const char *file, isc_time_t *time) {
* * isc_time_seconds is changed to be > 32 bits but long is 32 bits
* and isc_time_seconds has at least 33 significant bits.
*/
- times[0].tv_sec = times[1].tv_sec = (long)isc_time_seconds(time);
+ times[0].tv_sec = times[1].tv_sec = (long)isc_time_seconds(when);
/*
* Here is the real check for the high bit being set.
@@ -147,7 +206,7 @@ isc_file_settime(const char *file, isc_time_t *time) {
* we can at least cast to signed so the IRIX compiler shuts up.
*/
times[0].tv_usec = times[1].tv_usec =
- (isc_int32_t)(isc_time_nanoseconds(time) / 1000);
+ (isc_int32_t)(isc_time_nanoseconds(when) / 1000);
if (utimes(file, times) < 0)
return (isc__errno2result(errno));
@@ -165,8 +224,9 @@ isc_file_mktemplate(const char *path, char *buf, size_t buflen) {
isc_result_t
isc_file_template(const char *path, const char *templet, char *buf,
- size_t buflen) {
- char *s;
+ size_t buflen)
+{
+ const char *s;
REQUIRE(path != NULL);
REQUIRE(templet != NULL);
@@ -182,13 +242,14 @@ isc_file_template(const char *path, const char *templet, char *buf,
if ((s - path + 1 + strlen(templet) + 1) > buflen)
return (ISC_R_NOSPACE);
- strlcpy(buf, path, buflen);
- strlcat(buf, templet, buflen);
+ strncpy(buf, path, s - path + 1);
+ buf[s - path + 1] = '\0';
+ strcat(buf, templet);
} else {
if ((strlen(templet) + 1) > buflen)
return (ISC_R_NOSPACE);
- strlcpy(buf, templet, buflen);
+ strcpy(buf, templet);
}
return (ISC_R_SUCCESS);
@@ -222,7 +283,7 @@ isc_file_renameunique(const char *file, char *templet) {
if (errno != EEXIST)
return (isc__errno2result(errno));
for (cp = x;;) {
- char *t;
+ const char *t;
if (*cp == '\0')
return (ISC_R_FAILURE);
t = strchr(alphnum, *cp);
@@ -234,20 +295,32 @@ isc_file_renameunique(const char *file, char *templet) {
}
}
}
- (void)unlink(file);
+ if (unlink(file) < 0)
+ if (errno != ENOENT)
+ return (isc__errno2result(errno));
return (ISC_R_SUCCESS);
}
-
isc_result_t
isc_file_openunique(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_openuniqueprivate(char *templet, FILE **fp) {
+ int mode = S_IWUSR|S_IRUSR;
+ return (isc_file_openuniquemode(templet, mode, fp));
+}
+
+isc_result_t
+isc_file_openuniquemode(char *templet, int mode, FILE **fp) {
int fd;
FILE *f;
isc_result_t result = ISC_R_SUCCESS;
char *x;
char *cp;
isc_uint32_t which;
- int mode;
REQUIRE(templet != NULL);
REQUIRE(fp != NULL && *fp == NULL);
@@ -265,7 +338,6 @@ isc_file_openunique(char *templet, FILE **fp) {
x = cp--;
}
- mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
while ((fd = open(templet, O_RDWR|O_CREAT|O_EXCL, mode)) == -1) {
if (errno != EEXIST)
@@ -286,7 +358,11 @@ isc_file_openunique(char *templet, FILE **fp) {
f = fdopen(fd, "w+");
if (f == NULL) {
result = isc__errno2result(errno);
- (void)remove(templet);
+ if (remove(templet) < 0) {
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_FILE, ISC_LOG_ERROR,
+ "remove '%s': failed", templet);
+ }
(void)close(fd);
} else
*fp = f;
@@ -295,6 +371,23 @@ isc_file_openunique(char *templet, FILE **fp) {
}
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;
@@ -330,6 +423,59 @@ isc_file_exists(const char *pathname) {
return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS));
}
+isc_result_t
+isc_file_isplainfile(const char *filename) {
+ /*
+ * This function returns success if filename is a plain file.
+ */
+ struct stat filestat;
+ memset(&filestat,0,sizeof(struct stat));
+
+ if ((stat(filename, &filestat)) == -1)
+ return(isc__errno2result(errno));
+
+ if(! S_ISREG(filestat.st_mode))
+ return(ISC_R_INVALIDFILE);
+
+ return(ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_isplainfilefd(int fd) {
+ /*
+ * This function returns success if filename is a plain file.
+ */
+ struct stat filestat;
+ memset(&filestat,0,sizeof(struct stat));
+
+ if ((fstat(fd, &filestat)) == -1)
+ return(isc__errno2result(errno));
+
+ if(! S_ISREG(filestat.st_mode))
+ return(ISC_R_INVALIDFILE);
+
+ return(ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_isdirectory(const char *filename) {
+ /*
+ * This function returns success if filename exists and is a
+ * directory.
+ */
+ struct stat filestat;
+ memset(&filestat,0,sizeof(struct stat));
+
+ if ((stat(filename, &filestat)) == -1)
+ return(isc__errno2result(errno));
+
+ if(! S_ISDIR(filestat.st_mode))
+ return(ISC_R_INVALIDFILE);
+
+ return(ISC_R_SUCCESS);
+}
+
+
isc_boolean_t
isc_file_isabsolute(const char *filename) {
REQUIRE(filename != NULL);
@@ -354,7 +500,7 @@ isc_file_ischdiridempotent(const char *filename) {
const char *
isc_file_basename(const char *filename) {
- char *s;
+ const char *s;
REQUIRE(filename != NULL);
@@ -378,14 +524,14 @@ isc_file_progname(const char *filename, char *buf, size_t buflen) {
if (len > buflen)
return (ISC_R_NOSPACE);
- memcpy(buf, base, len);
+ memmove(buf, base, len);
return (ISC_R_SUCCESS);
}
/*
* Put the absolute name of the current directory into 'dirname', which is
- * a buffer of at least 'length' characters. End the string with the
+ * a buffer of at least 'length' characters. End the string with the
* appropriate path separator, such that the final product could be
* concatenated with a relative pathname to make a valid pathname string.
*/
@@ -408,7 +554,7 @@ dir_current(char *dirname, size_t length) {
if (strlen(dirname) + 1 == length)
result = ISC_R_NOSPACE;
else if (dirname[1] != '\0')
- strlcat(dirname, "/", length);
+ strcat(dirname, "/");
}
return (result);
@@ -422,7 +568,7 @@ isc_file_absolutepath(const char *filename, char *path, size_t pathlen) {
return (result);
if (strlen(path) + strlen(filename) + 1 > pathlen)
return (ISC_R_NOSPACE);
- strlcat(path, filename, pathlen);
+ strcat(path, filename);
return (ISC_R_SUCCESS);
}
@@ -430,7 +576,128 @@ isc_result_t
isc_file_truncate(const char *filename, isc_offset_t size) {
isc_result_t result = ISC_R_SUCCESS;
- if (truncate(filename, size) < 0)
+ if (truncate(filename, size) < 0)
result = isc__errno2result(errno);
return (result);
}
+
+isc_result_t
+isc_file_safecreate(const char *filename, FILE **fp) {
+ isc_result_t result;
+ int flags;
+ struct stat sb;
+ FILE *f;
+ int fd;
+
+ REQUIRE(filename != NULL);
+ REQUIRE(fp != NULL && *fp == NULL);
+
+ result = file_stats(filename, &sb);
+ if (result == ISC_R_SUCCESS) {
+ if ((sb.st_mode & S_IFREG) == 0)
+ return (ISC_R_INVALIDFILE);
+ flags = O_WRONLY | O_TRUNC;
+ } else if (result == ISC_R_FILENOTFOUND) {
+ flags = O_WRONLY | O_CREAT | O_EXCL;
+ } else
+ return (result);
+
+ fd = open(filename, flags, S_IRUSR | S_IWUSR);
+ if (fd == -1)
+ return (isc__errno2result(errno));
+
+ f = fdopen(fd, "w");
+ if (f == NULL) {
+ result = isc__errno2result(errno);
+ close(fd);
+ return (result);
+ }
+
+ *fp = f;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_splitpath(isc_mem_t *mctx, const char *path, char **dirname,
+ char const **bname)
+{
+ char *dir;
+ const char *file, *slash;
+
+ if (path == NULL)
+ return (ISC_R_INVALIDFILE);
+
+ slash = strrchr(path, '/');
+
+ if (slash == path) {
+ file = ++slash;
+ dir = isc_mem_strdup(mctx, "/");
+ } else if (slash != NULL) {
+ file = ++slash;
+ dir = isc_mem_allocate(mctx, slash - path);
+ if (dir != NULL)
+ strlcpy(dir, path, slash - path);
+ } else {
+ file = path;
+ dir = isc_mem_strdup(mctx, ".");
+ }
+
+ if (dir == NULL)
+ return (ISC_R_NOMEMORY);
+
+ if (*file == '\0') {
+ isc_mem_free(mctx, dir);
+ return (ISC_R_INVALIDFILE);
+ }
+
+ *dirname = dir;
+ *bname = file;
+
+ return (ISC_R_SUCCESS);
+}
+
+void *
+isc_file_mmap(void *addr, size_t len, int prot,
+ int flags, int fd, off_t offset)
+{
+#ifdef HAVE_MMAP
+ return (mmap(addr, len, prot, flags, fd, offset));
+#else
+ void *buf;
+ ssize_t ret;
+ off_t end;
+
+ UNUSED(addr);
+ UNUSED(prot);
+ UNUSED(flags);
+
+ end = lseek(fd, 0, SEEK_END);
+ lseek(fd, offset, SEEK_SET);
+ if (end - offset < (off_t) len)
+ len = end - offset;
+
+ buf = malloc(len);
+ if (buf == NULL)
+ return (NULL);
+
+ ret = read(fd, buf, len);
+ if (ret != (ssize_t) len) {
+ free(buf);
+ buf = NULL;
+ }
+
+ return (buf);
+#endif
+}
+
+int
+isc_file_munmap(void *addr, size_t len) {
+#ifdef HAVE_MMAP
+ return (munmap(addr, len));
+#else
+ UNUSED(len);
+
+ free(addr);
+ return (0);
+#endif
+}