8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence/*
bd911976d51f102751848568ccf56592fd5f6d77Tinderbox User * Copyright (C) 2000-2002, 2004, 2007, 2009, 2011-2017 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence */
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence
28a8f5b0de57d269cf2845c69cb6abe18cbd3b3aMark Andrews/* $Id$ */
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer#include <config.h>
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer#undef rename
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer#include <errno.h>
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer#include <limits.h>
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer#include <stdlib.h>
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer#include <io.h>
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer#include <process.h>
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer#include <sys/stat.h>
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer#include <fcntl.h>
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer#include <sys/utime.h>
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer#include <isc/file.h>
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt#include <isc/mem.h>
ad9645512cc7f07c05005a5b1ad1875aa14e9cd9Evan Hunt#include <isc/print.h>
b05a50c852608a40d1a06d6124bafb9b500c10c1Mukund Sivaraman#include <isc/random.h>
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer#include <isc/result.h>
f5c22df82b202ab3880e5bf346fd6dca68cf86abMark Andrews#include <isc/sha2.h>
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer#include <isc/stat.h>
e30d8c5a4728ca05720ec3fdefa99200e09dca39Evan Hunt#include <isc/string.h>
f5c22df82b202ab3880e5bf346fd6dca68cf86abMark Andrews#include <isc/time.h>
f5c22df82b202ab3880e5bf346fd6dca68cf86abMark Andrews#include <isc/util.h>
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer#include "errno2result.h"
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
b05a50c852608a40d1a06d6124bafb9b500c10c1Mukund Sivaramanstatic const char alphnum[] =
b05a50c852608a40d1a06d6124bafb9b500c10c1Mukund Sivaraman "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
b05a50c852608a40d1a06d6124bafb9b500c10c1Mukund Sivaraman
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer/*
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * Emulate UNIX mkstemp, which returns an open FD to the new file
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer *
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer */
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerstatic int
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsgettemp(char *path, isc_boolean_t binary, int *doopen) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer char *start, *trv;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer struct stat sbuf;
7e9d637131516486630290d36c4c0db544cb700eMark Andrews int flags = O_CREAT|O_EXCL|O_RDWR;
7e9d637131516486630290d36c4c0db544cb700eMark Andrews
7e9d637131516486630290d36c4c0db544cb700eMark Andrews if (binary)
0b9ea3fca6019f741f18376b5b26c0fa0835477fMark Andrews flags |= _O_BINARY;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer trv = strrchr(path, 'X');
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer trv++;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer /* extra X's get set to 0's */
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer while (*--trv == 'X') {
b05a50c852608a40d1a06d6124bafb9b500c10c1Mukund Sivaraman isc_uint32_t which;
b05a50c852608a40d1a06d6124bafb9b500c10c1Mukund Sivaraman
b05a50c852608a40d1a06d6124bafb9b500c10c1Mukund Sivaraman isc_random_get(&which);
b05a50c852608a40d1a06d6124bafb9b500c10c1Mukund Sivaraman *trv = alphnum[which % (sizeof(alphnum) - 1)];
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer }
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer /*
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * check the target directory; if you have six X's and it
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * doesn't exist this runs for a *very* long time.
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer */
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer for (start = trv + 1;; --trv) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (trv <= path)
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer break;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (*trv == '\\') {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer *trv = '\0';
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (stat(path, &sbuf))
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer return (0);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (!S_ISDIR(sbuf.st_mode)) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer errno = ENOTDIR;
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer return (0);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer }
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer *trv = '\\';
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer break;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer }
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer }
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer for (;;) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (doopen) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if ((*doopen =
7e9d637131516486630290d36c4c0db544cb700eMark Andrews open(path, flags, _S_IREAD | _S_IWRITE)) >= 0)
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer return (1);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (errno != EEXIST)
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer return (0);
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson } else if (stat(path, &sbuf))
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer return (errno == ENOENT ? 1 : 0);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer /* tricky little algorithm for backward compatibility */
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer for (trv = start;;) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (!*trv)
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer return (0);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (*trv == 'z')
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer *trv++ = 'a';
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer else {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (isdigit(*trv))
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer *trv = 'a';
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer else
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer ++*trv;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer break;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer }
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer }
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer }
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer /*NOTREACHED*/
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer}
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
39125379e5c9331f3dafd8d4bcb23fd52e30bfa8Andreas Gustafssonstatic int
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsmkstemp(char *path, isc_boolean_t binary) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer int fd;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
7e9d637131516486630290d36c4c0db544cb700eMark Andrews return (gettemp(path, binary, &fd) ? fd : -1);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer}
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer/*
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * XXXDCL As the API for accessing file statistics undoubtedly gets expanded,
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * it might be good to provide a mechanism that allows for the results
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * of a previous stat() to be used again without having to do another stat,
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * such as perl's mechanism of using "_" in place of a file name to indicate
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * that the results of the last stat should be used. But then you get into
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * annoying MP issues. BTW, Win32 has stat().
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer */
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerstatic isc_result_t
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerfile_stats(const char *file, struct stat *stats) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer isc_result_t result = ISC_R_SUCCESS;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer REQUIRE(file != NULL);
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer REQUIRE(stats != NULL);
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (stat(file, stats) != 0)
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer result = isc__errno2result(errno);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer return (result);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer}
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
7829fad4093f2c1985b1efb7cea00287ff015d2bckbstatic isc_result_t
7829fad4093f2c1985b1efb7cea00287ff015d2bckbfd_stats(int fd, struct stat *stats) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb isc_result_t result = ISC_R_SUCCESS;
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb REQUIRE(stats != NULL);
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (fstat(fd, stats) != 0)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb result = isc__errno2result(errno);
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return (result);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckbisc_result_t
7829fad4093f2c1985b1efb7cea00287ff015d2bckbisc_file_getsizefd(int fd, off_t *size) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb isc_result_t result;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb struct stat stats;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb REQUIRE(size != NULL);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb result = fd_stats(fd, &stats);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (result == ISC_R_SUCCESS)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb *size = stats.st_size;
c514f38c801755da4dbe405139d8512873b332b0ckb return (result);
c514f38c801755da4dbe405139d8512873b332b0ckb}
c514f38c801755da4dbe405139d8512873b332b0ckb
c514f38c801755da4dbe405139d8512873b332b0ckbisc_result_t
c514f38c801755da4dbe405139d8512873b332b0ckbisc_file_mode(const char *file, mode_t *modep) {
c514f38c801755da4dbe405139d8512873b332b0ckb isc_result_t result;
c514f38c801755da4dbe405139d8512873b332b0ckb struct stat stats;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
c514f38c801755da4dbe405139d8512873b332b0ckb REQUIRE(modep != NULL);
c514f38c801755da4dbe405139d8512873b332b0ckb
c514f38c801755da4dbe405139d8512873b332b0ckb result = file_stats(file, &stats);
c514f38c801755da4dbe405139d8512873b332b0ckb if (result == ISC_R_SUCCESS)
c514f38c801755da4dbe405139d8512873b332b0ckb *modep = (stats.st_mode & 07777);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return (result);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson/*
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson * isc_file_safemovefile is needed to be defined here to ensure that
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson * any file with the new name is renamed to a backup name and then the
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson * rename is done. If all goes well then the backup can be deleted,
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson * otherwise it gets renamed back.
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer */
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerint
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_safemovefile(const char *oldname, const char *newname) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer BOOL filestatus;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer char buf[512];
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer struct stat sbuf;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer BOOL exists = FALSE;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer int tmpfd;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer /*
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * Make sure we have something to do
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer */
1e71bc82b8e1a95d423d8db1c136080dc034433dAndreas Gustafsson if (stat(oldname, &sbuf) != 0) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer errno = ENOENT;
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer return (-1);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer }
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer /*
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * Rename to a backup the new file if it still exists
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer */
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer if (stat(newname, &sbuf) == 0) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer exists = TRUE;
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt strlcpy(buf, newname, sizeof(buf));
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt strlcat(buf, ".XXXXX", sizeof(buf));
7e9d637131516486630290d36c4c0db544cb700eMark Andrews tmpfd = mkstemp(buf, ISC_TRUE);
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer if (tmpfd > 0)
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer _close(tmpfd);
bbb3705e4cbdacf7cf6da7e448d79d97fdab2411Mark Andrews (void)DeleteFile(buf);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer _chmod(newname, _S_IREAD | _S_IWRITE);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer filestatus = MoveFile(newname, buf);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer }
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer /* Now rename the file to the new name
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer */
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer _chmod(oldname, _S_IREAD | _S_IWRITE);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer filestatus = MoveFile(oldname, newname);
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer if (filestatus == 0) {
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson /*
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson * Try to rename the backup back to the original name
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson * if the backup got created
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer */
1e71bc82b8e1a95d423d8db1c136080dc034433dAndreas Gustafsson if (exists == TRUE) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer filestatus = MoveFile(buf, newname);
1b8eaf41431cc05a5f74446254729987061a9e9bAndreas Gustafsson if (filestatus == 0)
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer errno = EACCES;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer }
1e71bc82b8e1a95d423d8db1c136080dc034433dAndreas Gustafsson return (-1);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer }
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson /*
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson * Delete the backup file if it got created
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer */
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson if (exists == TRUE)
bbb3705e4cbdacf7cf6da7e448d79d97fdab2411Mark Andrews (void)DeleteFile(buf);
1e71bc82b8e1a95d423d8db1c136080dc034433dAndreas Gustafsson return (0);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer}
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_result_t
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_getmodtime(const char *file, isc_time_t *time) {
bdec94477cc9ecac9ff14d3399f47f3d71cd370aAndreas Gustafsson int fh;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer REQUIRE(file != NULL);
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer REQUIRE(time != NULL);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
fdacf913e123db672888ff6b24a89caea6b12a50Danny Mayer if ((fh = open(file, _O_RDONLY | _O_BINARY)) < 0)
bdec94477cc9ecac9ff14d3399f47f3d71cd370aAndreas Gustafsson return (isc__errno2result(errno));
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
bdec94477cc9ecac9ff14d3399f47f3d71cd370aAndreas Gustafsson if (!GetFileTime((HANDLE) _get_osfhandle(fh),
bdec94477cc9ecac9ff14d3399f47f3d71cd370aAndreas Gustafsson NULL,
bdec94477cc9ecac9ff14d3399f47f3d71cd370aAndreas Gustafsson NULL,
bdec94477cc9ecac9ff14d3399f47f3d71cd370aAndreas Gustafsson &time->absolute))
bdec94477cc9ecac9ff14d3399f47f3d71cd370aAndreas Gustafsson {
bdec94477cc9ecac9ff14d3399f47f3d71cd370aAndreas Gustafsson close(fh);
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater errno = EINVAL;
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater return (isc__errno2result(errno));
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater }
bdec94477cc9ecac9ff14d3399f47f3d71cd370aAndreas Gustafsson close(fh);
bdec94477cc9ecac9ff14d3399f47f3d71cd370aAndreas Gustafsson return (ISC_R_SUCCESS);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer}
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
c213258356638f9af1e1c68425df527b856567a2Francis Dupontisc_result_t
c213258356638f9af1e1c68425df527b856567a2Francis Dupontisc_file_getsize(const char *file, off_t *size) {
c213258356638f9af1e1c68425df527b856567a2Francis Dupont isc_result_t result;
c213258356638f9af1e1c68425df527b856567a2Francis Dupont struct stat stats;
c213258356638f9af1e1c68425df527b856567a2Francis Dupont
c213258356638f9af1e1c68425df527b856567a2Francis Dupont REQUIRE(file != NULL);
c213258356638f9af1e1c68425df527b856567a2Francis Dupont REQUIRE(size != NULL);
c213258356638f9af1e1c68425df527b856567a2Francis Dupont
c213258356638f9af1e1c68425df527b856567a2Francis Dupont result = file_stats(file, &stats);
c213258356638f9af1e1c68425df527b856567a2Francis Dupont
c213258356638f9af1e1c68425df527b856567a2Francis Dupont if (result == ISC_R_SUCCESS)
c213258356638f9af1e1c68425df527b856567a2Francis Dupont *size = stats.st_size;
c213258356638f9af1e1c68425df527b856567a2Francis Dupont
c213258356638f9af1e1c68425df527b856567a2Francis Dupont return (result);
c213258356638f9af1e1c68425df527b856567a2Francis Dupont}
c213258356638f9af1e1c68425df527b856567a2Francis Dupont
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_result_t
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_settime(const char *file, isc_time_t *time) {
b602bf9e8b67cb2b1ff9ee8b2a48793bf6c70e16Danny Mayer int fh;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer REQUIRE(file != NULL && time != NULL);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
b602bf9e8b67cb2b1ff9ee8b2a48793bf6c70e16Danny Mayer if ((fh = open(file, _O_RDWR | _O_BINARY)) < 0)
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer return (isc__errno2result(errno));
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater /*
528baec07b1b9a566d47fc638ba5cbbe01475c74Andreas Gustafsson * Set the date via the filedate system call and return. Failing
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater * this call implies the new file times are not supported by the
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater * underlying file system.
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater */
528baec07b1b9a566d47fc638ba5cbbe01475c74Andreas Gustafsson if (!SetFileTime((HANDLE) _get_osfhandle(fh),
528baec07b1b9a566d47fc638ba5cbbe01475c74Andreas Gustafsson NULL,
528baec07b1b9a566d47fc638ba5cbbe01475c74Andreas Gustafsson &time->absolute,
528baec07b1b9a566d47fc638ba5cbbe01475c74Andreas Gustafsson &time->absolute))
528baec07b1b9a566d47fc638ba5cbbe01475c74Andreas Gustafsson {
b602bf9e8b67cb2b1ff9ee8b2a48793bf6c70e16Danny Mayer close(fh);
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater errno = EINVAL;
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater return (isc__errno2result(errno));
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater }
b602bf9e8b67cb2b1ff9ee8b2a48793bf6c70e16Danny Mayer
b602bf9e8b67cb2b1ff9ee8b2a48793bf6c70e16Danny Mayer close(fh);
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater return (ISC_R_SUCCESS);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer}
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence#undef TEMPLATE
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer#define TEMPLATE "XXXXXXXXXX.tmp" /* 14 characters. */
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrenceisc_result_t
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_mktemplate(const char *path, char *buf, size_t buflen) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer return (isc_file_template(path, TEMPLATE, buf, buflen));
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer}
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_result_t
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_template(const char *path, const char *templet, char *buf,
5b1c7ef35bb495820360182b5192689f33f1cc7dMark Andrews size_t buflen)
5b1c7ef35bb495820360182b5192689f33f1cc7dMark Andrews{
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence char *s;
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer REQUIRE(path != NULL);
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer REQUIRE(templet != NULL);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer REQUIRE(buf != NULL);
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer s = strrchr(templet, '\\');
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (s != NULL)
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer templet = s + 1;
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer s = strrchr(path, '\\');
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (s != NULL) {
5a93d3be4e0c652f455066bb764416173a00c951Mark Andrews size_t prefixlen = s - path + 1;
2b5e8ac28170ffc0a46c34db88aacc503c5a6111Mark Andrews if ((prefixlen + strlen(templet) + 1) > buflen)
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer return (ISC_R_NOSPACE);
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence
5a93d3be4e0c652f455066bb764416173a00c951Mark Andrews /* Copy 'prefixlen' bytes and NUL terminate. */
5a93d3be4e0c652f455066bb764416173a00c951Mark Andrews strlcpy(buf, path, ISC_MIN(prefixlen + 1, buflen));
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt strlcat(buf, templet, buflen);
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence } else {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if ((strlen(templet) + 1) > buflen)
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence return (ISC_R_NOSPACE);
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt strlcpy(buf, templet, buflen);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer }
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer return (ISC_R_SUCCESS);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer}
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_result_t
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_renameunique(const char *file, char *templet) {
313b0ea9f258edd8530f4454c69e6ba194280162Tinderbox User int fd;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer int res = 0;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer isc_result_t result = ISC_R_SUCCESS;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer REQUIRE(file != NULL);
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer REQUIRE(templet != NULL);
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer
7e9d637131516486630290d36c4c0db544cb700eMark Andrews fd = mkstemp(templet, ISC_TRUE);
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson if (fd == -1)
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer result = isc__errno2result(errno);
b9c80c8bddbb88384d7baef297a873b5f8715e49Mark Andrews else
b9c80c8bddbb88384d7baef297a873b5f8715e49Mark Andrews close(fd);
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (result == ISC_R_SUCCESS) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer res = isc_file_safemovefile(file, templet);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (res != 0) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer result = isc__errno2result(errno);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer (void)unlink(templet);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer }
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer }
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer return (result);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer}
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsstatic isc_result_t
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsopenuniquemode(char *templet, int mode, isc_boolean_t binary, FILE **fp) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer int fd;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer FILE *f;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer isc_result_t result = ISC_R_SUCCESS;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer REQUIRE(templet != NULL);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer REQUIRE(fp != NULL && *fp == NULL);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer /*
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer * Win32 does not have mkstemp. Using emulation above.
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer */
7e9d637131516486630290d36c4c0db544cb700eMark Andrews fd = mkstemp(templet, binary);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (fd == -1)
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer result = isc__errno2result(errno);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (result == ISC_R_SUCCESS) {
135bcc2e42a94543f11af2a4196b13552ab46d89Automatic Updater#if 1
98455e209089def083d4389b35e6ac195631d6c2Mark Andrews UNUSED(mode);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews#else
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews (void)fchmod(fd, mode);
433e06a25cdd92d665abda3e64c2c65f4a3f9b21Mark Andrews#endif
0b9ea3fca6019f741f18376b5b26c0fa0835477fMark Andrews f = fdopen(fd, binary ? "wb+" : "w+");
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (f == NULL) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer result = isc__errno2result(errno);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer (void)remove(templet);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer (void)close(fd);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer } else
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer *fp = f;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer }
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer return (result);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer}
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsisc_result_t
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsisc_file_openuniqueprivate(char *templet, FILE **fp) {
7e9d637131516486630290d36c4c0db544cb700eMark Andrews int mode = _S_IREAD | _S_IWRITE;
7e9d637131516486630290d36c4c0db544cb700eMark Andrews return (openuniquemode(templet, mode, ISC_FALSE, fp));
7e9d637131516486630290d36c4c0db544cb700eMark Andrews}
7e9d637131516486630290d36c4c0db544cb700eMark Andrews
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsisc_result_t
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsisc_file_openunique(char *templet, FILE **fp) {
7e9d637131516486630290d36c4c0db544cb700eMark Andrews int mode = _S_IREAD | _S_IWRITE;
7e9d637131516486630290d36c4c0db544cb700eMark Andrews return (openuniquemode(templet, mode, ISC_FALSE, fp));
7e9d637131516486630290d36c4c0db544cb700eMark Andrews}
7e9d637131516486630290d36c4c0db544cb700eMark Andrews
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsisc_result_t
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsisc_file_openuniquemode(char *templet, int mode, FILE **fp) {
7e9d637131516486630290d36c4c0db544cb700eMark Andrews return (openuniquemode(templet, mode, ISC_FALSE, fp));
7e9d637131516486630290d36c4c0db544cb700eMark Andrews}
7e9d637131516486630290d36c4c0db544cb700eMark Andrews
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsisc_result_t
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsisc_file_bopenuniqueprivate(char *templet, FILE **fp) {
7e9d637131516486630290d36c4c0db544cb700eMark Andrews int mode = _S_IREAD | _S_IWRITE;
7e9d637131516486630290d36c4c0db544cb700eMark Andrews return (openuniquemode(templet, mode, ISC_TRUE, fp));
7e9d637131516486630290d36c4c0db544cb700eMark Andrews}
7e9d637131516486630290d36c4c0db544cb700eMark Andrews
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsisc_result_t
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsisc_file_bopenunique(char *templet, FILE **fp) {
7e9d637131516486630290d36c4c0db544cb700eMark Andrews int mode = _S_IREAD | _S_IWRITE;
7e9d637131516486630290d36c4c0db544cb700eMark Andrews return (openuniquemode(templet, mode, ISC_TRUE, fp));
7e9d637131516486630290d36c4c0db544cb700eMark Andrews}
7e9d637131516486630290d36c4c0db544cb700eMark Andrews
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsisc_result_t
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsisc_file_bopenuniquemode(char *templet, int mode, FILE **fp) {
7e9d637131516486630290d36c4c0db544cb700eMark Andrews return (openuniquemode(templet, mode, ISC_TRUE, fp));
7e9d637131516486630290d36c4c0db544cb700eMark Andrews}
7e9d637131516486630290d36c4c0db544cb700eMark Andrews
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_result_t
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_remove(const char *filename) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer int r;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer REQUIRE(filename != NULL);
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer r = unlink(filename);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (r == 0)
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer return (ISC_R_SUCCESS);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer else
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer return (isc__errno2result(errno));
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer}
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_result_t
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_rename(const char *oldname, const char *newname) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer int r;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer REQUIRE(oldname != NULL);
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer REQUIRE(newname != NULL);
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer r = isc_file_safemovefile(oldname, newname);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer if (r == 0)
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer return (ISC_R_SUCCESS);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer else
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer return (isc__errno2result(errno));
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer}
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_boolean_t
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_exists(const char *pathname) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer struct stat stats;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer REQUIRE(pathname != NULL);
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS));
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer}
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mannisc_result_t
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mannisc_file_isplainfile(const char *filename) {
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mann /*
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mann * This function returns success if filename is a plain file.
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mann */
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mann struct stat filestat;
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mann memset(&filestat,0,sizeof(struct stat));
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mann
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mann if ((stat(filename, &filestat)) == -1)
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mann return(isc__errno2result(errno));
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mann
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mann if(! S_ISREG(filestat.st_mode))
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mann return(ISC_R_INVALIDFILE);
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mann
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mann return(ISC_R_SUCCESS);
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mann}
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mann
7829fad4093f2c1985b1efb7cea00287ff015d2bckbisc_result_t
7829fad4093f2c1985b1efb7cea00287ff015d2bckbisc_file_isplainfilefd(int fd) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb /*
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * This function returns success if filename is a plain file.
7829fad4093f2c1985b1efb7cea00287ff015d2bckb */
7829fad4093f2c1985b1efb7cea00287ff015d2bckb struct stat filestat;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb memset(&filestat,0,sizeof(struct stat));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if ((fstat(fd, &filestat)) == -1)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return(isc__errno2result(errno));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if(! S_ISREG(filestat.st_mode))
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return(ISC_R_INVALIDFILE);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return(ISC_R_SUCCESS);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Huntisc_result_t
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Huntisc_file_isdirectory(const char *filename) {
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Hunt /*
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Hunt * This function returns success if filename is a directory.
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Hunt */
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Hunt struct stat filestat;
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Hunt memset(&filestat,0,sizeof(struct stat));
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Hunt
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Hunt if ((stat(filename, &filestat)) == -1)
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Hunt return(isc__errno2result(errno));
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Hunt
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Hunt if(! S_ISDIR(filestat.st_mode))
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Hunt return(ISC_R_INVALIDFILE);
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Hunt
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Hunt return(ISC_R_SUCCESS);
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Hunt}
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Hunt
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Hunt
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_boolean_t
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_isabsolute(const char *filename) {
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer REQUIRE(filename != NULL);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer /*
c4958494a98a59ce25e9fecad76a9ab0e36cc59fDanny Mayer * Look for c:\path\... style, c:/path/... or \\computer\shar\path...
ad38e19578815fc064ea0a5f455fa8beffc99e63Danny Mayer * the UNC style file specs
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer */
ad38e19578815fc064ea0a5f455fa8beffc99e63Danny Mayer if ((filename[0] == '\\') && (filename[1] == '\\'))
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer return (ISC_TRUE);
911533025604975b5548d038ca09cff17c7f534eAndreas Gustafsson if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '\\')
5d9777319140d5bf62fbb5a43bc791957538c0adAndreas Gustafsson return (ISC_TRUE);
911533025604975b5548d038ca09cff17c7f534eAndreas Gustafsson if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '/')
c4958494a98a59ce25e9fecad76a9ab0e36cc59fDanny Mayer return (ISC_TRUE);
5d9777319140d5bf62fbb5a43bc791957538c0adAndreas Gustafsson return (ISC_FALSE);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer}
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_boolean_t
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_iscurrentdir(const char *filename) {
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer REQUIRE(filename != NULL);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer return (ISC_TF(filename[0] == '.' && filename[1] == '\0'));
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer}
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
ba35e9924e95c45f8ae536f453b9064740e49841Andreas Gustafssonisc_boolean_t
ba35e9924e95c45f8ae536f453b9064740e49841Andreas Gustafssonisc_file_ischdiridempotent(const char *filename) {
ba35e9924e95c45f8ae536f453b9064740e49841Andreas Gustafsson REQUIRE(filename != NULL);
ba35e9924e95c45f8ae536f453b9064740e49841Andreas Gustafsson
ba35e9924e95c45f8ae536f453b9064740e49841Andreas Gustafsson if (isc_file_isabsolute(filename))
ba35e9924e95c45f8ae536f453b9064740e49841Andreas Gustafsson return (ISC_TRUE);
ba35e9924e95c45f8ae536f453b9064740e49841Andreas Gustafsson if (filename[0] == '\\')
ba35e9924e95c45f8ae536f453b9064740e49841Andreas Gustafsson return (ISC_TRUE);
ba35e9924e95c45f8ae536f453b9064740e49841Andreas Gustafsson if (filename[0] == '/')
ba35e9924e95c45f8ae536f453b9064740e49841Andreas Gustafsson return (ISC_TRUE);
ba35e9924e95c45f8ae536f453b9064740e49841Andreas Gustafsson if (isc_file_iscurrentdir(filename))
ba35e9924e95c45f8ae536f453b9064740e49841Andreas Gustafsson return (ISC_TRUE);
ba35e9924e95c45f8ae536f453b9064740e49841Andreas Gustafsson return (ISC_FALSE);
ba35e9924e95c45f8ae536f453b9064740e49841Andreas Gustafsson}
ba35e9924e95c45f8ae536f453b9064740e49841Andreas Gustafsson
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerconst char *
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_basename(const char *filename) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer char *s;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer REQUIRE(filename != NULL);
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer s = strrchr(filename, '\\');
1e71bc82b8e1a95d423d8db1c136080dc034433dAndreas Gustafsson if (s == NULL)
1e71bc82b8e1a95d423d8db1c136080dc034433dAndreas Gustafsson return (filename);
1e71bc82b8e1a95d423d8db1c136080dc034433dAndreas Gustafsson return (s + 1);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer}
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_result_t
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_progname(const char *filename, char *progname, size_t namelen) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer const char *s;
5b1c7ef35bb495820360182b5192689f33f1cc7dMark Andrews const char *p;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer size_t len;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer REQUIRE(filename != NULL);
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer REQUIRE(progname != NULL);
bb48ac4f813537a060579615a52f9c7963f5e3c4Danny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer /*
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * Strip the path from the name
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer */
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer s = isc_file_basename(filename);
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer if (s == NULL) {
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer return (ISC_R_NOSPACE);
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer }
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer /*
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * Strip any and all suffixes
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer */
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer p = strchr(s, '.');
1e71bc82b8e1a95d423d8db1c136080dc034433dAndreas Gustafsson if (p == NULL) {
1e71bc82b8e1a95d423d8db1c136080dc034433dAndreas Gustafsson if (namelen <= strlen(s))
1e71bc82b8e1a95d423d8db1c136080dc034433dAndreas Gustafsson return (ISC_R_NOSPACE);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
7cd594b8427fe742d44295790ba367e1de22a47dEvan Hunt strlcpy(progname, s, namelen);
1e71bc82b8e1a95d423d8db1c136080dc034433dAndreas Gustafsson return (ISC_R_SUCCESS);
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence }
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater /*
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * Copy the result to the buffer
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer */
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer len = p - s;
1e71bc82b8e1a95d423d8db1c136080dc034433dAndreas Gustafsson if (len >= namelen)
1e71bc82b8e1a95d423d8db1c136080dc034433dAndreas Gustafsson return (ISC_R_NOSPACE);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer
5a93d3be4e0c652f455066bb764416173a00c951Mark Andrews /* Copy up to 'len' bytes and NUL terminate. */
5a93d3be4e0c652f455066bb764416173a00c951Mark Andrews strlcpy(progname, s, ISC_MIN(len + 1, namelen));
1e71bc82b8e1a95d423d8db1c136080dc034433dAndreas Gustafsson return (ISC_R_SUCCESS);
8b7304a34c751e519ede7d00b77f1f962c0a37e4David Lawrence}
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayer
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayerisc_result_t
dee69dd3aafe1339cd62928b858d18fdc0536642Andreas Gustafssonisc_file_absolutepath(const char *filename, char *path, size_t pathlen) {
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayer char *ptrname;
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayer DWORD retval;
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayer
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayer REQUIRE(filename != NULL);
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayer REQUIRE(path != NULL);
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayer
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews retval = GetFullPathName(filename, (DWORD) pathlen, path, &ptrname);
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayer
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayer /* Something went wrong in getting the path */
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayer if (retval == 0)
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayer return (ISC_R_NOTFOUND);
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayer /* Caller needs to provide a larger buffer to contain the string */
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayer if (retval >= pathlen)
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayer return (ISC_R_NOSPACE);
911533025604975b5548d038ca09cff17c7f534eAndreas Gustafsson return (ISC_R_SUCCESS);
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayer}
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayer
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayerisc_result_t
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayerisc_file_truncate(const char *filename, isc_offset_t size) {
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayer int fh;
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayer
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayer REQUIRE(filename != NULL && size >= 0);
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayer
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayer if ((fh = open(filename, _O_RDWR | _O_BINARY)) < 0)
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayer return (isc__errno2result(errno));
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayer
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayer if(_chsize(fh, size) != 0) {
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayer close(fh);
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayer return (isc__errno2result(errno));
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayer }
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayer close(fh);
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayer
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayer return (ISC_R_SUCCESS);
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayer}
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Huntisc_result_t
351b62535d4c4f89883bfdba025999dd32490266Evan Huntisc_file_safecreate(const char *filename, FILE **fp) {
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt isc_result_t result;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt int flags;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt struct stat sb;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt FILE *f;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt int fd;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt REQUIRE(filename != NULL);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt REQUIRE(fp != NULL && *fp == NULL);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt result = file_stats(filename, &sb);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt if (result == ISC_R_SUCCESS) {
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt if ((sb.st_mode & S_IFREG) == 0)
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return (ISC_R_INVALIDFILE);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt flags = O_WRONLY | O_TRUNC;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt } else if (result == ISC_R_FILENOTFOUND) {
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt flags = O_WRONLY | O_CREAT | O_EXCL;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt } else
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return (result);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt fd = open(filename, flags, S_IRUSR | S_IWUSR);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt if (fd == -1)
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return (isc__errno2result(errno));
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt f = fdopen(fd, "w");
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt if (f == NULL) {
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt result = isc__errno2result(errno);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt close(fd);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return (result);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt }
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt *fp = f;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return (ISC_R_SUCCESS);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt}
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt
747abb4993e03b8812514e4476bff67f5248c717Evan Huntisc_result_t
5b1c7ef35bb495820360182b5192689f33f1cc7dMark Andrewsisc_file_splitpath(isc_mem_t *mctx, const char *path, char **dirname,
5b1c7ef35bb495820360182b5192689f33f1cc7dMark Andrews char const ** basename)
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt{
5b1c7ef35bb495820360182b5192689f33f1cc7dMark Andrews char *dir;
5b1c7ef35bb495820360182b5192689f33f1cc7dMark Andrews const char *file, *slash;
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt char *backslash;
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt slash = strrchr(path, '/');
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt backslash = strrchr(path, '\\');
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt if ((slash != NULL && backslash != NULL && backslash > slash) ||
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt (slash == NULL && backslash != NULL))
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt slash = backslash;
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt if (slash == path) {
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt file = ++slash;
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt dir = isc_mem_strdup(mctx, "/");
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt } else if (slash != NULL) {
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt file = ++slash;
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt dir = isc_mem_allocate(mctx, slash - path);
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt if (dir != NULL)
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt strlcpy(dir, path, slash - path);
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt } else {
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt file = path;
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt dir = isc_mem_strdup(mctx, ".");
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt }
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt if (dir == NULL)
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt return (ISC_R_NOMEMORY);
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt if (*file == '\0') {
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt isc_mem_free(mctx, dir);
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt return (ISC_R_INVALIDFILE);
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt }
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt *dirname = dir;
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt *basename = file;
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt return (ISC_R_SUCCESS);
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt}
5506903c9215faf42586307c2288942fd804c579Evan Hunt
5506903c9215faf42586307c2288942fd804c579Evan Huntvoid *
5506903c9215faf42586307c2288942fd804c579Evan Huntisc_file_mmap(void *addr, size_t len, int prot,
5506903c9215faf42586307c2288942fd804c579Evan Hunt int flags, int fd, off_t offset)
5506903c9215faf42586307c2288942fd804c579Evan Hunt{
5506903c9215faf42586307c2288942fd804c579Evan Hunt void *buf;
5506903c9215faf42586307c2288942fd804c579Evan Hunt ssize_t ret;
5506903c9215faf42586307c2288942fd804c579Evan Hunt off_t end;
3b398443f0dca316ba7a6e057ba2d1b8ab4ddf70Tinderbox User
5506903c9215faf42586307c2288942fd804c579Evan Hunt UNUSED(addr);
5506903c9215faf42586307c2288942fd804c579Evan Hunt UNUSED(prot);
5506903c9215faf42586307c2288942fd804c579Evan Hunt UNUSED(flags);
5506903c9215faf42586307c2288942fd804c579Evan Hunt
5506903c9215faf42586307c2288942fd804c579Evan Hunt end = lseek(fd, 0, SEEK_END);
5506903c9215faf42586307c2288942fd804c579Evan Hunt lseek(fd, offset, SEEK_SET);
5506903c9215faf42586307c2288942fd804c579Evan Hunt if (end - offset < (off_t) len)
5506903c9215faf42586307c2288942fd804c579Evan Hunt len = end - offset;
5506903c9215faf42586307c2288942fd804c579Evan Hunt
5506903c9215faf42586307c2288942fd804c579Evan Hunt buf = malloc(len);
4dd41c7d5976ff6889e4fbf306036f4256af409aMark Andrews if (buf == NULL)
4dd41c7d5976ff6889e4fbf306036f4256af409aMark Andrews return (NULL);
4dd41c7d5976ff6889e4fbf306036f4256af409aMark Andrews
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews ret = read(fd, buf, (unsigned int) len);
5506903c9215faf42586307c2288942fd804c579Evan Hunt if (ret != (ssize_t) len) {
5506903c9215faf42586307c2288942fd804c579Evan Hunt free(buf);
5506903c9215faf42586307c2288942fd804c579Evan Hunt buf = NULL;
5506903c9215faf42586307c2288942fd804c579Evan Hunt }
5506903c9215faf42586307c2288942fd804c579Evan Hunt
5506903c9215faf42586307c2288942fd804c579Evan Hunt return (buf);
5506903c9215faf42586307c2288942fd804c579Evan Hunt}
5506903c9215faf42586307c2288942fd804c579Evan Hunt
5506903c9215faf42586307c2288942fd804c579Evan Huntint
5506903c9215faf42586307c2288942fd804c579Evan Huntisc_file_munmap(void *addr, size_t len) {
5506903c9215faf42586307c2288942fd804c579Evan Hunt UNUSED(len);
5506903c9215faf42586307c2288942fd804c579Evan Hunt free(addr);
5506903c9215faf42586307c2288942fd804c579Evan Hunt return (0);
5506903c9215faf42586307c2288942fd804c579Evan Hunt}
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt#define DISALLOW "\\/:ABCDEFGHIJKLMNOPQRSTUVWXYZ"
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt#ifndef PATH_MAX
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt#define PATH_MAX 1024
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt#endif
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Huntisc_result_t
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Huntisc_file_sanitize(const char *dir, const char *base, const char *ext,
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt char *path, size_t length)
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt{
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt char buf[PATH_MAX], hash[PATH_MAX];
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt size_t l = 0;
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt REQUIRE(base != NULL);
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt REQUIRE(path != NULL);
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt l = strlen(base) + 1;
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt /*
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt * allow room for a full sha256 hash (64 chars
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt * plus null terminator)
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt */
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt if (l < 65)
6d0a639bd0e8f18a9bfef15697564be853944716Tinderbox User l = 65;
6d0a639bd0e8f18a9bfef15697564be853944716Tinderbox User
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt if (dir != NULL)
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt l += strlen(dir) + 1;
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt if (ext != NULL)
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt l += strlen(ext) + 1;
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt if (l > length || l > PATH_MAX)
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt return (ISC_R_NOSPACE);
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt /* Check whether the full-length SHA256 hash filename exists */
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt isc_sha256_data((const void *) base, strlen(base), hash);
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt snprintf(buf, sizeof(buf), "%s%s%s%s%s",
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt dir != NULL ? dir : "", dir != NULL ? "/" : "",
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt hash, ext != NULL ? "." : "", ext != NULL ? ext : "");
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt if (isc_file_exists(buf)) {
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt strlcpy(path, buf, length);
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt return (ISC_R_SUCCESS);
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt }
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt /* Check for a truncated SHA256 hash filename */
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt hash[16] = '\0';
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt snprintf(buf, sizeof(buf), "%s%s%s%s%s",
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt dir != NULL ? dir : "", dir != NULL ? "/" : "",
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt hash, ext != NULL ? "." : "", ext != NULL ? ext : "");
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt if (isc_file_exists(buf)) {
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt strlcpy(path, buf, length);
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt return (ISC_R_SUCCESS);
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt }
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt /*
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt * If neither hash filename already exists, then we'll use
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt * the original base name if it has no disallowed characters,
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt * or the truncated hash name if it does.
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt */
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt if (strpbrk(base, DISALLOW) != NULL) {
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt strlcpy(path, buf, length);
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt return (ISC_R_SUCCESS);
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt }
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt snprintf(buf, sizeof(buf), "%s%s%s%s%s",
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt dir != NULL ? dir : "", dir != NULL ? "/" : "",
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt base, ext != NULL ? "." : "", ext != NULL ? ext : "");
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt strlcpy(path, buf, length);
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt return (ISC_R_SUCCESS);
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt}
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews/*
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews * Based on http://blog.aaronballman.com/2011/08/how-to-check-access-rights/
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews */
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrewsisc_boolean_t
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrewsisc_file_isdirwritable(const char *path) {
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews DWORD length = 0;
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews HANDLE hToken = NULL;
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews PSECURITY_DESCRIPTOR security = NULL;
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews isc_boolean_t answer = ISC_FALSE;
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews if (isc_file_isdirectory(path) != ISC_R_SUCCESS) {
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews return (answer);
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews }
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews /*
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews * Figure out buffer size. GetFileSecurity() should not succeed.
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews */
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews if (GetFileSecurity(path, OWNER_SECURITY_INFORMATION |
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews GROUP_SECURITY_INFORMATION |
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews DACL_SECURITY_INFORMATION,
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews NULL, 0, &length))
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews {
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews return (answer);
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews }
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews return (answer);
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews }
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews security = malloc(length);
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews if (security == NULL) {
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews return (answer);
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews }
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews /*
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews * GetFileSecurity() should succeed.
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews */
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews if (!GetFileSecurity(path, OWNER_SECURITY_INFORMATION |
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews GROUP_SECURITY_INFORMATION |
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews DACL_SECURITY_INFORMATION,
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews security, length, &length))
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews {
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews return (answer);
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews }
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews if (OpenProcessToken(GetCurrentProcess(), TOKEN_IMPERSONATE |
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews TOKEN_QUERY | TOKEN_DUPLICATE |
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews STANDARD_RIGHTS_READ, &hToken))
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews {
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews HANDLE hImpersonatedToken = NULL;
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews if (DuplicateToken(hToken, SecurityImpersonation,
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews &hImpersonatedToken))
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews {
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews GENERIC_MAPPING mapping;
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews PRIVILEGE_SET privileges = { 0 };
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews DWORD grantedAccess = 0;
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews DWORD privilegesLength = sizeof(privileges);
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews BOOL result = FALSE;
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews DWORD genericAccessRights = GENERIC_WRITE;
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews mapping.GenericRead = FILE_GENERIC_READ;
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews mapping.GenericWrite = FILE_GENERIC_WRITE;
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews mapping.GenericExecute = FILE_GENERIC_EXECUTE;
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews mapping.GenericAll = FILE_ALL_ACCESS;
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews MapGenericMask(&genericAccessRights, &mapping);
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews if (AccessCheck(security, hImpersonatedToken,
9159c4c80c574867349a04d639fd303f410ed332Tinderbox User genericAccessRights, &mapping,
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews &privileges, &privilegesLength,
9159c4c80c574867349a04d639fd303f410ed332Tinderbox User &grantedAccess, &result))
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews {
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews answer = ISC_TF(result);
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews }
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews CloseHandle(hImpersonatedToken);
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews }
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews CloseHandle(hToken);
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews }
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews free(security);
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews return (answer);
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews}