diff options
Diffstat (limited to 'usr.sbin/bind/lib/isc/unix/file.c')
| -rw-r--r-- | usr.sbin/bind/lib/isc/unix/file.c | 339 |
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 +} |
