file.c revision b05a50c852608a40d1a06d6124bafb9b500c10c1
7e4d75a5daeaaf8a7f559f9bd7fbf540184e235cMark Andrews/*
7e4d75a5daeaaf8a7f559f9bd7fbf540184e235cMark Andrews * Copyright (C) 2004, 2007, 2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Copyright (C) 2000-2002 Internet Software Consortium.
7e4d75a5daeaaf8a7f559f9bd7fbf540184e235cMark Andrews *
7e4d75a5daeaaf8a7f559f9bd7fbf540184e235cMark Andrews * Permission to use, copy, modify, and/or distribute this software for any
7e4d75a5daeaaf8a7f559f9bd7fbf540184e235cMark Andrews * purpose with or without fee is hereby granted, provided that the above
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * copyright notice and this permission notice appear in all copies.
15a44745412679c30a6d022733925af70a38b715David Lawrence *
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
15a44745412679c30a6d022733925af70a38b715David Lawrence * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15a44745412679c30a6d022733925af70a38b715David Lawrence * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15a44745412679c30a6d022733925af70a38b715David Lawrence * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15a44745412679c30a6d022733925af70a38b715David Lawrence * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15a44745412679c30a6d022733925af70a38b715David Lawrence * PERFORMANCE OF THIS SOFTWARE.
7e4d75a5daeaaf8a7f559f9bd7fbf540184e235cMark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
fa5a42fbad42f4e033376d5d4624e29d018d97b7Brian Wellington/* $Id$ */
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence
6b7257f756eb0530cdf54df9a7fab8d51a5001c3David Lawrence#include <config.h>
6b7257f756eb0530cdf54df9a7fab8d51a5001c3David Lawrence
37d266d288410d1ead241c02a8a1dbcb0160be46Michael Graff#undef rename
37d266d288410d1ead241c02a8a1dbcb0160be46Michael Graff#include <errno.h>
37d266d288410d1ead241c02a8a1dbcb0160be46Michael Graff#include <limits.h>
37d266d288410d1ead241c02a8a1dbcb0160be46Michael Graff#include <stdlib.h>
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#include <io.h>
8c8360e5c3e4b27641633c22d0fcfd3f1f3af2b5Michael Graff#include <process.h>
8c8360e5c3e4b27641633c22d0fcfd3f1f3af2b5Michael Graff
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#include <sys/stat.h>
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#include <fcntl.h>
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#include <sys/utime.h>
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
37d266d288410d1ead241c02a8a1dbcb0160be46Michael Graff#include <isc/file.h>
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley#include <isc/mem.h>
37d266d288410d1ead241c02a8a1dbcb0160be46Michael Graff#include <isc/print.h>
37d266d288410d1ead241c02a8a1dbcb0160be46Michael Graff#include <isc/random.h>
37d266d288410d1ead241c02a8a1dbcb0160be46Michael Graff#include <isc/result.h>
37d266d288410d1ead241c02a8a1dbcb0160be46Michael Graff#include <isc/sha2.h>
d0783e645b149fcea7e7f22cd43f87b5d188b055Mark Andrews#include <isc/stat.h>
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#include <isc/string.h>
d0783e645b149fcea7e7f22cd43f87b5d188b055Mark Andrews#include <isc/time.h>
d0783e645b149fcea7e7f22cd43f87b5d188b055Mark Andrews#include <isc/util.h>
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
d0783e645b149fcea7e7f22cd43f87b5d188b055Mark Andrews#include "errno2result.h"
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrencestatic const char alphnum[] =
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley/*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Emulate UNIX mkstemp, which returns an open FD to the new file
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence */
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrencestatic int
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsgettemp(char *path, isc_boolean_t binary, int *doopen) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews char *start, *trv;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct stat sbuf;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int flags = O_CREAT|O_EXCL|O_RDWR;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (binary)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews flags |= _O_BINARY;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews trv = strrchr(path, 'X');
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews trv++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /* extra X's get set to 0's */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews while (*--trv == 'X') {
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence isc_uint32_t which;
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews isc_random_get(&which);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *trv = alphnum[which % (sizeof(alphnum) - 1)];
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * check the target directory; if you have six X's and it
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * doesn't exist this runs for a *very* long time.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence for (start = trv + 1;; --trv) {
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence if (trv <= path)
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence break;
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence if (*trv == '\\') {
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence *trv = '\0';
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence if (stat(path, &sbuf))
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence return (0);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence if (!S_ISDIR(sbuf.st_mode)) {
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence errno = ENOTDIR;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (0);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *trv = '\\';
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews for (;;) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (doopen) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if ((*doopen =
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews open(path, flags, _S_IREAD | _S_IWRITE)) >= 0)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (1);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (errno != EEXIST)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (0);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews } else if (stat(path, &sbuf))
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (errno == ENOENT ? 1 : 0);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /* tricky little algorithm for backward compatibility */
af9cfbc64363b61aa5903dd916e9fbc152084d4cMark Andrews for (trv = start;;) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (!*trv)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (0);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (*trv == 'z')
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *trv++ = 'a';
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews else {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (isdigit(*trv))
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *trv = 'a';
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews else
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews ++*trv;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence }
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence }
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*NOTREACHED*/
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsstatic int
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsmkstemp(char *path, isc_boolean_t binary) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int fd;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley return (gettemp(path, binary, &fd) ? fd : -1);
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence/*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * XXXDCL As the API for accessing file statistics undoubtedly gets expanded,
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * it might be good to provide a mechanism that allows for the results
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * of a previous stat() to be used again without having to do another stat,
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * such as perl's mechanism of using "_" in place of a file name to indicate
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * that the results of the last stat should be used. But then you get into
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * annoying MP issues. BTW, Win32 has stat().
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsstatic isc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsfile_stats(const char *file, struct stat *stats) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews isc_result_t result = ISC_R_SUCCESS;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(file != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(stats != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence if (stat(file, stats) != 0)
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence result = isc__errno2result(errno);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (result);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencestatic isc_result_t
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencefd_stats(int fd, struct stat *stats) {
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence isc_result_t result = ISC_R_SUCCESS;
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(stats != NULL);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence if (fstat(fd, stats) != 0)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews result = isc__errno2result(errno);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (result);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_getsizefd(int fd, off_t *size) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews isc_result_t result;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct stat stats;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
efe2f579ba6fbec4229129015780f2d925085b04Michael Graff REQUIRE(size != NULL);
6add3af8397580475ab9fa10ac8c1269465cff87Mark Andrews
6add3af8397580475ab9fa10ac8c1269465cff87Mark Andrews result = fd_stats(fd, &stats);
6add3af8397580475ab9fa10ac8c1269465cff87Mark Andrews
6add3af8397580475ab9fa10ac8c1269465cff87Mark Andrews if (result == ISC_R_SUCCESS)
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington *size = stats.st_size;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (result);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_mode(const char *file, mode_t *modep) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews isc_result_t result;
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews struct stat stats;
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews REQUIRE(modep != NULL);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews result = file_stats(file, &stats);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (result == ISC_R_SUCCESS)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *modep = (stats.st_mode & 07777);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (result);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews/*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * isc_file_safemovefile is needed to be defined here to ensure that
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * any file with the new name is renamed to a backup name and then the
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * rename is done. If all goes well then the backup can be deleted,
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * otherwise it gets renamed back.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrewsint
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrewsisc_file_safemovefile(const char *oldname, const char *newname) {
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews BOOL filestatus;
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews char buf[512];
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews struct stat sbuf;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews BOOL exists = FALSE;
171d0db7f93bf796f870713d6208b21893401cfcBrian Wellington int tmpfd;
171d0db7f93bf796f870713d6208b21893401cfcBrian Wellington
171d0db7f93bf796f870713d6208b21893401cfcBrian Wellington /*
171d0db7f93bf796f870713d6208b21893401cfcBrian Wellington * Make sure we have something to do
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews */
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (stat(oldname, &sbuf) != 0) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews errno = ENOENT;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (-1);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Rename to a backup the new file if it still exists
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
af9cfbc64363b61aa5903dd916e9fbc152084d4cMark Andrews if (stat(newname, &sbuf) == 0) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews exists = TRUE;
af9cfbc64363b61aa5903dd916e9fbc152084d4cMark Andrews strcpy(buf, newname);
03084608809afbaf570093a14d2dc4ad507336a0Brian Wellington strcat(buf, ".XXXXX");
03084608809afbaf570093a14d2dc4ad507336a0Brian Wellington tmpfd = mkstemp(buf, ISC_TRUE);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews if (tmpfd > 0)
03084608809afbaf570093a14d2dc4ad507336a0Brian Wellington _close(tmpfd);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (void)DeleteFile(buf);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews _chmod(newname, _S_IREAD | _S_IWRITE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews filestatus = MoveFile(newname, buf);
af9cfbc64363b61aa5903dd916e9fbc152084d4cMark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /* Now rename the file to the new name
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews _chmod(oldname, _S_IREAD | _S_IWRITE);
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence filestatus = MoveFile(oldname, newname);
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence if (filestatus == 0) {
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence /*
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence * Try to rename the backup back to the original name
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * if the backup got created
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence if (exists == TRUE) {
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence filestatus = MoveFile(buf, newname);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (filestatus == 0)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews errno = EACCES;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (-1);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Delete the backup file if it got created
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (exists == TRUE)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (void)DeleteFile(buf);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (0);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_getmodtime(const char *file, isc_time_t *time) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int fh;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(file != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(time != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if ((fh = open(file, _O_RDONLY | _O_BINARY)) < 0)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (isc__errno2result(errno));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence if (!GetFileTime((HANDLE) _get_osfhandle(fh),
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence NULL,
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence NULL,
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence &time->absolute))
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence {
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence close(fh);
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence errno = EINVAL;
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence return (isc__errno2result(errno));
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence }
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence close(fh);
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence return (ISC_R_SUCCESS);
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrenceisc_result_t
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrenceisc_file_getsize(const char *file, off_t *size) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews isc_result_t result;
ea023072092112a831ca7c2943387ccbb422a3f2Mark Andrews struct stat stats;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(file != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(size != NULL);
efe2f579ba6fbec4229129015780f2d925085b04Michael Graff
03084608809afbaf570093a14d2dc4ad507336a0Brian Wellington result = file_stats(file, &stats);
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington if (result == ISC_R_SUCCESS)
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews *size = stats.st_size;
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington return (result);
03084608809afbaf570093a14d2dc4ad507336a0Brian Wellington}
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews
171d0db7f93bf796f870713d6208b21893401cfcBrian Wellingtonisc_result_t
171d0db7f93bf796f870713d6208b21893401cfcBrian Wellingtonisc_file_settime(const char *file, isc_time_t *time) {
171d0db7f93bf796f870713d6208b21893401cfcBrian Wellington int fh;
171d0db7f93bf796f870713d6208b21893401cfcBrian Wellington
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(file != NULL && time != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if ((fh = open(file, _O_RDWR | _O_BINARY)) < 0)
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews return (isc__errno2result(errno));
03084608809afbaf570093a14d2dc4ad507336a0Brian Wellington
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews /*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Set the date via the filedate system call and return. Failing
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * this call implies the new file times are not supported by the
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * underlying file system.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence if (!SetFileTime((HANDLE) _get_osfhandle(fh),
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence NULL,
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews &time->absolute,
af9cfbc64363b61aa5903dd916e9fbc152084d4cMark Andrews &time->absolute))
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews close(fh);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews errno = EINVAL;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (isc__errno2result(errno));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews close(fh);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_SUCCESS);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#undef TEMPLATE
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence#define TEMPLATE "XXXXXXXXXX.tmp" /* 14 characters. */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_mktemplate(const char *path, char *buf, size_t buflen) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (isc_file_template(path, TEMPLATE, buf, buflen));
efe2f579ba6fbec4229129015780f2d925085b04Michael Graff}
03084608809afbaf570093a14d2dc4ad507336a0Brian Wellington
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellingtonisc_result_t
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellingtonisc_file_template(const char *path, const char *templet, char *buf,
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews size_t buflen) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews char *s;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(path != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(templet != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(buf != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews s = strrchr(templet, '\\');
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews if (s != NULL)
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews templet = s + 1;
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews s = strrchr(path, '\\');
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (s != NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if ((s - path + 1 + strlen(templet) + 1) > (ssize_t)buflen)
af9cfbc64363b61aa5903dd916e9fbc152084d4cMark Andrews return (ISC_R_NOSPACE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews strncpy(buf, path, s - path + 1);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews buf[s - path + 1] = '\0';
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews strcat(buf, templet);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews } else {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if ((strlen(templet) + 1) > buflen)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_NOSPACE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews strcpy(buf, templet);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_SUCCESS);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_renameunique(const char *file, char *templet) {
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews int fd;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int res = 0;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews isc_result_t result = ISC_R_SUCCESS;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(file != NULL);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews REQUIRE(templet != NULL);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews fd = mkstemp(templet, ISC_TRUE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (fd == -1)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews result = isc__errno2result(errno);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews else
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews close(fd);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (result == ISC_R_SUCCESS) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews res = isc_file_safemovefile(file, templet);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (res != 0) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews result = isc__errno2result(errno);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (void)unlink(templet);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (result);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsstatic isc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsopenuniquemode(char *templet, int mode, isc_boolean_t binary, FILE **fp) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int fd;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews FILE *f;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews isc_result_t result = ISC_R_SUCCESS;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(templet != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(fp != NULL && *fp == NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Win32 does not have mkstemp. Using emulation above.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews fd = mkstemp(templet, binary);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence if (fd == -1)
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence result = isc__errno2result(errno);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence if (result == ISC_R_SUCCESS) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#if 1
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews UNUSED(mode);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence#else
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence (void)fchmod(fd, mode);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence#endif
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews f = fdopen(fd, binary ? "wb+" : "w+");
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (f == NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews result = isc__errno2result(errno);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (void)remove(templet);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (void)close(fd);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews } else
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *fp = f;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (result);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_openuniqueprivate(char *templet, FILE **fp) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int mode = _S_IREAD | _S_IWRITE;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (openuniquemode(templet, mode, ISC_FALSE, fp));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_openunique(char *templet, FILE **fp) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int mode = _S_IREAD | _S_IWRITE;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (openuniquemode(templet, mode, ISC_FALSE, fp));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_openuniquemode(char *templet, int mode, FILE **fp) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence return (openuniquemode(templet, mode, ISC_FALSE, fp));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_bopenuniqueprivate(char *templet, FILE **fp) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int mode = _S_IREAD | _S_IWRITE;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (openuniquemode(templet, mode, ISC_TRUE, fp));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_bopenunique(char *templet, FILE **fp) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int mode = _S_IREAD | _S_IWRITE;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (openuniquemode(templet, mode, ISC_TRUE, fp));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_bopenuniquemode(char *templet, int mode, FILE **fp) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (openuniquemode(templet, mode, ISC_TRUE, fp));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrenceisc_result_t
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrenceisc_file_remove(const char *filename) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int r;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(filename != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews r = unlink(filename);
fa5a42fbad42f4e033376d5d4624e29d018d97b7Brian Wellington if (r == 0)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_SUCCESS);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews else
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews return (isc__errno2result(errno));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_rename(const char *oldname, const char *newname) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int r;
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(oldname != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(newname != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews r = isc_file_safemovefile(oldname, newname);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (r == 0)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_SUCCESS);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews else
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (isc__errno2result(errno));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
fa5a42fbad42f4e033376d5d4624e29d018d97b7Brian Wellingtonisc_boolean_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_exists(const char *pathname) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct stat stats;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(pathname != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS));
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_isplainfile(const char *filename) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * This function returns success if filename is a plain file.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct stat filestat;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews memset(&filestat,0,sizeof(struct stat));
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if ((stat(filename, &filestat)) == -1)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return(isc__errno2result(errno));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if(! S_ISREG(filestat.st_mode))
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return(ISC_R_INVALIDFILE);
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence return(ISC_R_SUCCESS);
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence}
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_isplainfilefd(int fd) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * This function returns success if filename is a plain file.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct stat filestat;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews memset(&filestat,0,sizeof(struct stat));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if ((fstat(fd, &filestat)) == -1)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return(isc__errno2result(errno));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if(! S_ISREG(filestat.st_mode))
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews return(ISC_R_INVALIDFILE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return(ISC_R_SUCCESS);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_isdirectory(const char *filename) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * This function returns success if filename is a directory.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct stat filestat;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews memset(&filestat,0,sizeof(struct stat));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence if ((stat(filename, &filestat)) == -1)
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence return(isc__errno2result(errno));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if(! S_ISDIR(filestat.st_mode))
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return(ISC_R_INVALIDFILE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return(ISC_R_SUCCESS);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_boolean_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_isabsolute(const char *filename) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(filename != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Look for c:\path\... style, c:/path/... or \\computer\shar\path...
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * the UNC style file specs
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if ((filename[0] == '\\') && (filename[1] == '\\'))
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_TRUE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '\\')
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_TRUE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '/')
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_TRUE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_FALSE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_boolean_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_iscurrentdir(const char *filename) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(filename != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_TF(filename[0] == '.' && filename[1] == '\0'));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_boolean_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_ischdiridempotent(const char *filename) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(filename != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (isc_file_isabsolute(filename))
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_TRUE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (filename[0] == '\\')
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_TRUE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (filename[0] == '/')
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_TRUE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (isc_file_iscurrentdir(filename))
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_TRUE);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews return (ISC_FALSE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsconst char *
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrewsisc_file_basename(const char *filename) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews char *s;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(filename != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence s = strrchr(filename, '\\');
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence if (s == NULL)
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence return (filename);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (s + 1);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrewsisc_file_progname(const char *filename, char *progname, size_t namelen) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews const char *s;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews char *p;
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence size_t len;
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence REQUIRE(filename != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(progname != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Strip the path from the name
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews s = isc_file_basename(filename);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (s == NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_NOSPACE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Strip any and all suffixes
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews p = strchr(s, '.');
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (p == NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (namelen <= strlen(s))
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_NOSPACE);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews strcpy(progname, s);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_SUCCESS);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence }
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Copy the result to the buffer
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews len = p - s;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (len >= namelen)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_NOSPACE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews strncpy(progname, s, len);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews progname[len] = '\0';
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_SUCCESS);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_absolutepath(const char *filename, char *path, size_t pathlen) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews char *ptrname;
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews DWORD retval;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(filename != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(path != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence retval = GetFullPathName(filename, (DWORD) pathlen, path, &ptrname);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /* Something went wrong in getting the path */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (retval == 0)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_NOTFOUND);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /* Caller needs to provide a larger buffer to contain the string */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (retval >= pathlen)
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews return (ISC_R_NOSPACE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_SUCCESS);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_truncate(const char *filename, isc_offset_t size) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int fh;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence REQUIRE(filename != NULL && size >= 0);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence if ((fh = open(filename, _O_RDWR | _O_BINARY)) < 0)
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews return (isc__errno2result(errno));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if(_chsize(fh, size) != 0) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews close(fh);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (isc__errno2result(errno));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence close(fh);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence return (ISC_R_SUCCESS);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_file_safecreate(const char *filename, FILE **fp) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews isc_result_t result;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int flags;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct stat sb;
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews FILE *f;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int fd;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews REQUIRE(filename != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(fp != NULL && *fp == NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews result = file_stats(filename, &sb);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (result == ISC_R_SUCCESS) {
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews if ((sb.st_mode & S_IFREG) == 0)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_INVALIDFILE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews flags = O_WRONLY | O_TRUNC;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews } else if (result == ISC_R_FILENOTFOUND) {
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews flags = O_WRONLY | O_CREAT | O_EXCL;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews } else
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (result);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews fd = open(filename, flags, S_IRUSR | S_IWUSR);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (fd == -1)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (isc__errno2result(errno));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews f = fdopen(fd, "w");
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (f == NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews result = isc__errno2result(errno);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews close(fd);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (result);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *fp = f;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_SUCCESS);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsisc_result_t
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrenceisc_file_splitpath(isc_mem_t *mctx, char *path, char **dirname, char **basename)
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence{
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence char *dir, *file, *slash;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews char *backslash;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews slash = strrchr(path, '/');
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews backslash = strrchr(path, '\\');
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if ((slash != NULL && backslash != NULL && backslash > slash) ||
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews (slash == NULL && backslash != NULL))
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews slash = backslash;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (slash == path) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews file = ++slash;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews dir = isc_mem_strdup(mctx, "/");
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence } else if (slash != NULL) {
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence file = ++slash;
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence dir = isc_mem_allocate(mctx, slash - path);
88ed7381f16a72409061875ddeda598f477e5ef6Michael Graff if (dir != NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews strlcpy(dir, path, slash - path);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews } else {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews file = path;
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence dir = isc_mem_strdup(mctx, ".");
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence }
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (dir == NULL)
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington return (ISC_R_NOMEMORY);
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (*file == '\0') {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews isc_mem_free(mctx, dir);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_INVALIDFILE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *dirname = dir;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *basename = file;
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence return (ISC_R_SUCCESS);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
c4cc75482fd6846163cafa79e98abb11bcfaf3d3Mark Andrewsvoid *
c4cc75482fd6846163cafa79e98abb11bcfaf3d3Mark Andrewsisc_file_mmap(void *addr, size_t len, int prot,
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int flags, int fd, off_t offset)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews{
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews void *buf;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews ssize_t ret;
c4cc75482fd6846163cafa79e98abb11bcfaf3d3Mark Andrews off_t end;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews UNUSED(addr);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews UNUSED(prot);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews UNUSED(flags);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews end = lseek(fd, 0, SEEK_END);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews lseek(fd, offset, SEEK_SET);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (end - offset < (off_t) len)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews len = end - offset;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews buf = malloc(len);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews ret = read(fd, buf, (unsigned int) len);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (ret != (ssize_t) len) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews free(buf);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews buf = NULL;
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington }
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (buf);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsint
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrenceisc_file_munmap(void *addr, size_t len) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews UNUSED(len);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews free(addr);
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff return (0);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#define DISALLOW "\\/:ABCDEFGHIJKLMNOPQRSTUVWXYZ"
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#ifndef PATH_MAX
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#define PATH_MAX 1024
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#endif
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrenceisc_result_t
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrenceisc_file_sanitize(const char *dir, const char *base, const char *ext,
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews char *path, size_t length)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews{
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews char buf[PATH_MAX], hash[PATH_MAX];
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews size_t l = 0;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews REQUIRE(base != NULL);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews REQUIRE(path != NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews l = strlen(base) + 1;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * allow room for a full sha256 hash (64 chars
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * plus null terminator)
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence if (l < 65)
88ed7381f16a72409061875ddeda598f477e5ef6Michael Graff l = 65;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (dir != NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews l += strlen(dir) + 1;
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence if (ext != NULL)
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence l += strlen(ext) + 1;
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (l > length || l > PATH_MAX)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_NOSPACE);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /* Check whether the full-length SHA256 hash filename exists */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews isc_sha256_data((const void *) base, strlen(base), hash);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews snprintf(buf, sizeof(buf), "%s%s%s%s%s",
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews dir != NULL ? dir : "", dir != NULL ? "/" : "",
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews hash, ext != NULL ? "." : "", ext != NULL ? ext : "");
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence if (isc_file_exists(buf)) {
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence strlcpy(path, buf, length);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence return (ISC_R_SUCCESS);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff /* Check for a truncated SHA256 hash filename */
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff hash[16] = '\0';
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews snprintf(buf, sizeof(buf), "%s%s%s%s%s",
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews dir != NULL ? dir : "", dir != NULL ? "/" : "",
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews hash, ext != NULL ? "." : "", ext != NULL ? ext : "");
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff if (isc_file_exists(buf)) {
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff strlcpy(path, buf, length);
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff return (ISC_R_SUCCESS);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * If neither hash filename already exists, then we'll use
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * the original base name if it has no disallowed characters,
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * or the truncated hash name if it does.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (strpbrk(base, DISALLOW) != NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews strlcpy(path, buf, length);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_SUCCESS);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews snprintf(buf, sizeof(buf), "%s%s%s%s%s",
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews dir != NULL ? dir : "", dir != NULL ? "/" : "",
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews base, ext != NULL ? "." : "", ext != NULL ? ext : "");
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews strlcpy(path, buf, length);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (ISC_R_SUCCESS);
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington}
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington