file.c revision 754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764
1633838b8255282d10af15c5c84cee5a51466712Bob Halley/*
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * Copyright (C) 2000-2002 Internet Software Consortium.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
1633838b8255282d10af15c5c84cee5a51466712Bob Halley * Permission to use, copy, modify, and/or distribute this software for any
1633838b8255282d10af15c5c84cee5a51466712Bob Halley * purpose with or without fee is hereby granted, provided that the above
1633838b8255282d10af15c5c84cee5a51466712Bob Halley * copyright notice and this permission notice appear in all copies.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * PERFORMANCE OF THIS SOFTWARE.
1633838b8255282d10af15c5c84cee5a51466712Bob Halley */
94e25967cda41b886e33ec254b917d21df21a187Bob Halley
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/* $Id: file.c,v 1.33 2009/06/11 23:47:55 tbox Exp $ */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein#include <config.h>
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence
d25afd60ee2286cb171c4960a790f3d7041b6f85Bob Halley#undef rename
d25afd60ee2286cb171c4960a790f3d7041b6f85Bob Halley#include <errno.h>
94e25967cda41b886e33ec254b917d21df21a187Bob Halley#include <limits.h>
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence#include <stdlib.h>
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews#include <io.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <process.h>
94e25967cda41b886e33ec254b917d21df21a187Bob Halley
6e3a8256eed85f6704861d269ccfb35bdaeed5ffDavid Lawrence#include <sys/stat.h>
6e3a8256eed85f6704861d269ccfb35bdaeed5ffDavid Lawrence#include <fcntl.h>
df0f58959ed82a2a43ca8d816ce9592541df9f2fMark Andrews#include <sys/utime.h>
33f87146a856eb6c3dfd55a8ee9c173c94f82150Andreas Gustafsson
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews#include <isc/file.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/result.h>
94e25967cda41b886e33ec254b917d21df21a187Bob Halley#include <isc/time.h>
364a82f7c25b62967678027043425201a5e5171aBob Halley#include <isc/util.h>
94e25967cda41b886e33ec254b917d21df21a187Bob Halley#include <isc/stat.h>
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein#include "errno2result.h"
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence/*
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * Emulate UNIX mkstemp, which returns an open FD to the new file
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence */
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrencestatic int
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrencegettemp(char *path, int *doopen) {
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence char *start, *trv;
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence struct stat sbuf;
df0f58959ed82a2a43ca8d816ce9592541df9f2fMark Andrews int pid;
df0f58959ed82a2a43ca8d816ce9592541df9f2fMark Andrews
df0f58959ed82a2a43ca8d816ce9592541df9f2fMark Andrews trv = strrchr(path, 'X');
df0f58959ed82a2a43ca8d816ce9592541df9f2fMark Andrews trv++;
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein pid = getpid();
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley /* extra X's get set to 0's */
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley while (*--trv == 'X') {
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley *trv = (pid % 10) + '0';
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley pid /= 10;
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley }
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley /*
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews * check the target directory; if you have six X's and it
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews * doesn't exist this runs for a *very* long time.
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews */
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews for (start = trv + 1;; --trv) {
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews if (trv <= path)
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews break;
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews if (*trv == '\\') {
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews *trv = '\0';
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews if (stat(path, &sbuf))
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews return (0);
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews if (!S_ISDIR(sbuf.st_mode)) {
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews errno = ENOTDIR;
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews return (0);
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews }
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews *trv = '\\';
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews break;
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews }
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews }
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews for (;;) {
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews if (doopen) {
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews if ((*doopen =
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson open(path, O_CREAT|O_EXCL|O_RDWR,
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews _S_IREAD | _S_IWRITE)) >= 0)
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews return (1);
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews if (errno != EEXIST)
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley return (0);
3740b569ae76295b941d57a724a43beb75b533baBob Halley } else if (stat(path, &sbuf))
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence return (errno == ENOENT ? 1 : 0);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley /* tricky little algorithm for backward compatibility */
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence for (trv = start;;) {
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley if (!*trv)
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley return (0);
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley if (*trv == 'z')
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley *trv++ = 'a';
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley else {
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley if (isdigit(*trv))
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafsson *trv = 'a';
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley else
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence ++*trv;
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley break;
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley }
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley }
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley }
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley /*NOTREACHED*/
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley}
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halleystatic int
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halleymkstemp(char *path) {
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley int fd;
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley return (gettemp(path, &fd) ? fd : -1);
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley}
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley/*
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrence * XXXDCL As the API for accessing file statistics undoubtedly gets expanded,
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrence * it might be good to provide a mechanism that allows for the results
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrence * of a previous stat() to be used again without having to do another stat,
232fd751edcb5dd2b1fd2666e039efe83d2e2b55Michael Sawyer * such as perl's mechanism of using "_" in place of a file name to indicate
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrence * that the results of the last stat should be used. But then you get into
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrence * annoying MP issues. BTW, Win32 has stat().
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrence */
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrencestatic isc_result_t
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrencefile_stats(const char *file, struct stat *stats) {
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley isc_result_t result = ISC_R_SUCCESS;
3740b569ae76295b941d57a724a43beb75b533baBob Halley
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley REQUIRE(file != NULL);
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley REQUIRE(stats != NULL);
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley if (stat(file, stats) != 0)
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley result = isc__errno2result(errno);
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley return (result);
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafsson}
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence/*
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley * isc_file_safemovefile is needed to be defined here to ensure that
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley * any file with the new name is renamed to a backup name and then the
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley * rename is done. If all goes well then the backup can be deleted,
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley * otherwise it gets renamed back.
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley */
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halleyint
df0f58959ed82a2a43ca8d816ce9592541df9f2fMark Andrewsisc_file_safemovefile(const char *oldname, const char *newname) {
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley BOOL filestatus;
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley char buf[512];
94e25967cda41b886e33ec254b917d21df21a187Bob Halley struct stat sbuf;
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews BOOL exists = FALSE;
94e25967cda41b886e33ec254b917d21df21a187Bob Halley int tmpfd;
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence /*
94e25967cda41b886e33ec254b917d21df21a187Bob Halley * Make sure we have something to do
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews */
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews if (stat(oldname, &sbuf) != 0) {
94e25967cda41b886e33ec254b917d21df21a187Bob Halley errno = ENOENT;
94e25967cda41b886e33ec254b917d21df21a187Bob Halley return (-1);
94e25967cda41b886e33ec254b917d21df21a187Bob Halley }
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence /*
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * Rename to a backup the new file if it still exists
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence */
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence if (stat(newname, &sbuf) == 0) {
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence exists = TRUE;
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence strcpy(buf, newname);
df0f58959ed82a2a43ca8d816ce9592541df9f2fMark Andrews strcat(buf, ".XXXXX");
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews tmpfd = mkstemp(buf);
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews if (tmpfd > 0)
df0f58959ed82a2a43ca8d816ce9592541df9f2fMark Andrews _close(tmpfd);
df0f58959ed82a2a43ca8d816ce9592541df9f2fMark Andrews DeleteFile(buf);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence _chmod(newname, _S_IREAD | _S_IWRITE);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
df0f58959ed82a2a43ca8d816ce9592541df9f2fMark Andrews filestatus = MoveFile(newname, buf);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence }
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence /* Now rename the file to the new name
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence */
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence _chmod(oldname, _S_IREAD | _S_IWRITE);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
5eb91bd90e3ad3426e5e3213031556a737cf3809Mark Andrews filestatus = MoveFile(oldname, newname);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence if (filestatus == 0) {
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence /*
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley * Try to rename the backup back to the original name
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * if the backup got created
94e25967cda41b886e33ec254b917d21df21a187Bob Halley */
94e25967cda41b886e33ec254b917d21df21a187Bob Halley if (exists == TRUE) {
94e25967cda41b886e33ec254b917d21df21a187Bob Halley filestatus = MoveFile(buf, newname);
94e25967cda41b886e33ec254b917d21df21a187Bob Halley if (filestatus == 0)
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley errno = EACCES;
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafsson }
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley return (-1);
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews }
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley /*
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley * Delete the backup file if it got created
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence */
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence if (exists == TRUE)
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley filestatus = DeleteFile(buf);
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews return (0);
4b87939256ede703385e9cab92d3c58d03c31098Mark Andrews}
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halleyisc_result_t
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halleyisc_file_getmodtime(const char *file, isc_time_t *time) {
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence int fh;
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence REQUIRE(file != NULL);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence REQUIRE(time != NULL);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence if ((fh = open(file, _O_RDONLY | _O_BINARY)) < 0)
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence return (isc__errno2result(errno));
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews if (!GetFileTime((HANDLE) _get_osfhandle(fh),
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews NULL,
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews NULL,
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews &time->absolute))
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence {
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence close(fh);
70ec7dd74103fa9e92a6d56a0e3b0fc30e17af0dMark Andrews errno = EINVAL;
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence return (isc__errno2result(errno));
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence }
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence close(fh);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence return (ISC_R_SUCCESS);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence}
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrenceisc_result_t
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrenceisc_file_settime(const char *file, isc_time_t *time) {
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence int fh;
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence REQUIRE(file != NULL && time != NULL);
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence if ((fh = open(file, _O_RDWR | _O_BINARY)) < 0)
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence return (isc__errno2result(errno));
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence /*
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley * Set the date via the filedate system call and return. Failing
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley * this call implies the new file times are not supported by the
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley * underlying file system.
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley */
afdb3abb9b06ed4070ac9021f1f4427b4cb3a286Bob Halley if (!SetFileTime((HANDLE) _get_osfhandle(fh),
94e25967cda41b886e33ec254b917d21df21a187Bob Halley NULL,
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafsson &time->absolute,
bf6d2e39124ab3d51c253f7acad9a4abef059be6Bob Halley &time->absolute))
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence {
94e25967cda41b886e33ec254b917d21df21a187Bob Halley close(fh);
bf6d2e39124ab3d51c253f7acad9a4abef059be6Bob Halley errno = EINVAL;
94e25967cda41b886e33ec254b917d21df21a187Bob Halley return (isc__errno2result(errno));
bf6d2e39124ab3d51c253f7acad9a4abef059be6Bob Halley }
94e25967cda41b886e33ec254b917d21df21a187Bob Halley
bf6d2e39124ab3d51c253f7acad9a4abef059be6Bob Halley close(fh);
94e25967cda41b886e33ec254b917d21df21a187Bob Halley return (ISC_R_SUCCESS);
bf6d2e39124ab3d51c253f7acad9a4abef059be6Bob Halley
94e25967cda41b886e33ec254b917d21df21a187Bob Halley}
94e25967cda41b886e33ec254b917d21df21a187Bob Halley
94e25967cda41b886e33ec254b917d21df21a187Bob Halley#undef TEMPLATE
94e25967cda41b886e33ec254b917d21df21a187Bob Halley#define TEMPLATE "XXXXXXXXXX.tmp" /* 14 characters. */
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafssonisc_result_t
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafssonisc_file_mktemplate(const char *path, char *buf, size_t buflen) {
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley return (isc_file_template(path, TEMPLATE, buf, buflen));
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence}
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrenceisc_result_t
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrenceisc_file_template(const char *path, const char *templet, char *buf,
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence size_t buflen) {
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence char *s;
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence REQUIRE(path != NULL);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence REQUIRE(templet != NULL);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence REQUIRE(buf != NULL);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
94e25967cda41b886e33ec254b917d21df21a187Bob Halley s = strrchr(templet, '\\');
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley if (s != NULL)
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley templet = s + 1;
c89ac488df58cf6a37918cd00236eedf015830f8Andreas Gustafsson
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley s = strrchr(path, '\\');
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
94e25967cda41b886e33ec254b917d21df21a187Bob Halley if (s != NULL) {
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence if ((s - path + 1 + strlen(templet) + 1) > buflen)
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence return (ISC_R_NOSPACE);
94e25967cda41b886e33ec254b917d21df21a187Bob Halley
94e25967cda41b886e33ec254b917d21df21a187Bob Halley strncpy(buf, path, s - path + 1);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence buf[s - path + 1] = '\0';
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafsson strcat(buf, templet);
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafsson } else {
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafsson if ((strlen(templet) + 1) > buflen)
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley return (ISC_R_NOSPACE);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence strcpy(buf, templet);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence }
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence return (ISC_R_SUCCESS);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence}
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halleyisc_result_t
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halleyisc_file_renameunique(const char *file, char *templet) {
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley int fd = -1;
94e25967cda41b886e33ec254b917d21df21a187Bob Halley int res = 0;
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence isc_result_t result = ISC_R_SUCCESS;
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley
4bed2e84a34b37259b85e5c092d51c122ef58c3cBob Halley REQUIRE(file != NULL);
94e25967cda41b886e33ec254b917d21df21a187Bob Halley REQUIRE(templet != NULL);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence fd = mkstemp(templet);
94e25967cda41b886e33ec254b917d21df21a187Bob Halley if (fd == -1)
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrence result = isc__errno2result(errno);
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrence else
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafsson close(fd);
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrence
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrence if (result == ISC_R_SUCCESS) {
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrence res = isc_file_safemovefile(file, templet);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence if (res != 0) {
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrence result = isc__errno2result(errno);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence (void)unlink(templet);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence }
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrence }
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrence return (result);
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrence}
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrence
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrenceisc_result_t
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrenceisc_file_openunique(char *templet, FILE **fp) {
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrence int fd;
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrence FILE *f;
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrence isc_result_t result = ISC_R_SUCCESS;
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrence REQUIRE(templet != NULL);
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrence REQUIRE(fp != NULL && *fp == NULL);
4ad9b25e6ddf948ffb3b8198c5540d251f26c52eDavid Lawrence
114d0d1642b5ede0ab154532159fe38c30762d82David Lawrence /*
114d0d1642b5ede0ab154532159fe38c30762d82David Lawrence * Win32 does not have mkstemp. Using emulation above.
ae5df22719a9e2c252ea1fcccd2cadb44c8bd8d4Mark Andrews */
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrence fd = mkstemp(templet);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrence if (fd == -1)
114d0d1642b5ede0ab154532159fe38c30762d82David Lawrence result = isc__errno2result(errno);
114d0d1642b5ede0ab154532159fe38c30762d82David Lawrence if (result == ISC_R_SUCCESS) {
114d0d1642b5ede0ab154532159fe38c30762d82David Lawrence f = fdopen(fd, "w+");
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence if (f == NULL) {
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafsson result = isc__errno2result(errno);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence (void)remove(templet);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence (void)close(fd);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence } else
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence *fp = f;
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence }
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence return (result);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence}
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrenceisc_result_t
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrenceisc_file_remove(const char *filename) {
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence int r;
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence REQUIRE(filename != NULL);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence r = unlink(filename);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence if (r == 0)
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence return (ISC_R_SUCCESS);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence else
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence return (isc__errno2result(errno));
826c281a05cb89c9c28621937dc83fa676a5b207David Lawrence}
826c281a05cb89c9c28621937dc83fa676a5b207David Lawrence
826c281a05cb89c9c28621937dc83fa676a5b207David Lawrenceisc_result_t
826c281a05cb89c9c28621937dc83fa676a5b207David Lawrenceisc_file_rename(const char *oldname, const char *newname) {
826c281a05cb89c9c28621937dc83fa676a5b207David Lawrence int r;
826c281a05cb89c9c28621937dc83fa676a5b207David Lawrence
826c281a05cb89c9c28621937dc83fa676a5b207David Lawrence REQUIRE(oldname != NULL);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence REQUIRE(newname != NULL);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence r = isc_file_safemovefile(oldname, newname);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence if (r == 0)
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence return (ISC_R_SUCCESS);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence else
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence return (isc__errno2result(errno));
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence}
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence
826c281a05cb89c9c28621937dc83fa676a5b207David Lawrenceisc_boolean_t
5eb91bd90e3ad3426e5e3213031556a737cf3809Mark Andrewsisc_file_exists(const char *pathname) {
604a596b5f97f09f6a4de67fe2f076d3c939df33David Lawrence struct stat stats;
826c281a05cb89c9c28621937dc83fa676a5b207David Lawrence
604a596b5f97f09f6a4de67fe2f076d3c939df33David Lawrence REQUIRE(pathname != NULL);
604a596b5f97f09f6a4de67fe2f076d3c939df33David Lawrence
604a596b5f97f09f6a4de67fe2f076d3c939df33David Lawrence return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS));
604a596b5f97f09f6a4de67fe2f076d3c939df33David Lawrence}
604a596b5f97f09f6a4de67fe2f076d3c939df33David Lawrence
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrenceisc_boolean_t
604a596b5f97f09f6a4de67fe2f076d3c939df33David Lawrenceisc_file_isabsolute(const char *filename) {
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence REQUIRE(filename != NULL);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence /*
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * Look for c:\path\... style, c:/path/... or \\computer\shar\path...
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * the UNC style file specs
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence */
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence if ((filename[0] == '\\') && (filename[1] == '\\'))
114d0d1642b5ede0ab154532159fe38c30762d82David Lawrence return (ISC_TRUE);
26f327f1f53afdb8256affa1c197ed138bf3cb2fAndreas Gustafsson if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '\\')
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrence return (ISC_TRUE);
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrence if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '/')
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence return (ISC_TRUE);
114d0d1642b5ede0ab154532159fe38c30762d82David Lawrence return (ISC_FALSE);
114d0d1642b5ede0ab154532159fe38c30762d82David Lawrence}
114d0d1642b5ede0ab154532159fe38c30762d82David Lawrence
c8563aaf86c04f0e2284bcc8e444a0651c157ea0Andreas Gustafssonisc_boolean_t
c8563aaf86c04f0e2284bcc8e444a0651c157ea0Andreas Gustafssonisc_file_iscurrentdir(const char *filename) {
c8563aaf86c04f0e2284bcc8e444a0651c157ea0Andreas Gustafsson REQUIRE(filename != NULL);
c8563aaf86c04f0e2284bcc8e444a0651c157ea0Andreas Gustafsson return (ISC_TF(filename[0] == '.' && filename[1] == '\0'));
c8563aaf86c04f0e2284bcc8e444a0651c157ea0Andreas Gustafsson}
c8563aaf86c04f0e2284bcc8e444a0651c157ea0Andreas Gustafsson
6184f9fc1e65ef131ea308a1a92882595bb1aeeaAndreas Gustafssonisc_boolean_t
6184f9fc1e65ef131ea308a1a92882595bb1aeeaAndreas Gustafssonisc_file_ischdiridempotent(const char *filename) {
c8563aaf86c04f0e2284bcc8e444a0651c157ea0Andreas Gustafsson REQUIRE(filename != NULL);
c36f45e354c0d5b6ab9f821bfe315d0ce9d95a29Mark Andrews
ff6e834f7d48d4b116627ecf8cafa0fbacc25bd4Andreas Gustafsson if (isc_file_isabsolute(filename))
ff6e834f7d48d4b116627ecf8cafa0fbacc25bd4Andreas Gustafsson return (ISC_TRUE);
ff6e834f7d48d4b116627ecf8cafa0fbacc25bd4Andreas Gustafsson if (filename[0] == '\\')
ff6e834f7d48d4b116627ecf8cafa0fbacc25bd4Andreas Gustafsson return (ISC_TRUE);
ff6e834f7d48d4b116627ecf8cafa0fbacc25bd4Andreas Gustafsson if (filename[0] == '/')
13f20ab1fad3f7620a1eb31937ff0d1021e5590bDanny Mayer return (ISC_TRUE);
c8563aaf86c04f0e2284bcc8e444a0651c157ea0Andreas Gustafsson if (isc_file_iscurrentdir(filename))
return (ISC_TRUE);
return (ISC_FALSE);
}
const char *
isc_file_basename(const char *filename) {
char *s;
REQUIRE(filename != NULL);
s = strrchr(filename, '\\');
if (s == NULL)
return (filename);
return (s + 1);
}
isc_result_t
isc_file_progname(const char *filename, char *progname, size_t namelen) {
const char *s;
char *p;
size_t len;
REQUIRE(filename != NULL);
REQUIRE(progname != NULL);
/*
* Strip the path from the name
*/
s = isc_file_basename(filename);
if (s == NULL) {
return (ISC_R_NOSPACE);
}
/*
* Strip any and all suffixes
*/
p = strchr(s, '.');
if (p == NULL) {
if (namelen <= strlen(s))
return (ISC_R_NOSPACE);
strcpy(progname, s);
return (ISC_R_SUCCESS);
}
/*
* Copy the result to the buffer
*/
len = p - s;
if (len >= namelen)
return (ISC_R_NOSPACE);
strncpy(progname, s, len);
progname[len] = '\0';
return (ISC_R_SUCCESS);
}
isc_result_t
isc_file_absolutepath(const char *filename, char *path, size_t pathlen) {
char *ptrname;
DWORD retval;
REQUIRE(filename != NULL);
REQUIRE(path != NULL);
retval = GetFullPathName(filename, pathlen, path, &ptrname);
/* Something went wrong in getting the path */
if (retval == 0)
return (ISC_R_NOTFOUND);
/* Caller needs to provide a larger buffer to contain the string */
if (retval >= pathlen)
return (ISC_R_NOSPACE);
return (ISC_R_SUCCESS);
}
isc_result_t
isc_file_truncate(const char *filename, isc_offset_t size) {
int fh;
REQUIRE(filename != NULL && size >= 0);
if ((fh = open(filename, _O_RDWR | _O_BINARY)) < 0)
return (isc__errno2result(errno));
if(_chsize(fh, size) != 0) {
close(fh);
return (isc__errno2result(errno));
}
close(fh);
return (ISC_R_SUCCESS);
}
isc_result_t
isc_file_safecreate(const char *filename, FILE **fp) {
isc_result_t result;
int flags;
struct stat sb;
FILE *f;
int fd;
REQUIRE(filename != NULL);
REQUIRE(fp != NULL && *fp == NULL);
result = file_stats(filename, &sb);
if (result == ISC_R_SUCCESS) {
if ((sb.st_mode & S_IFREG) == 0)
return (ISC_R_INVALIDFILE);
flags = O_WRONLY | O_TRUNC;
} else if (result == ISC_R_FILENOTFOUND) {
flags = O_WRONLY | O_CREAT | O_EXCL;
} else
return (result);
fd = open(filename, flags, S_IRUSR | S_IWUSR);
if (fd == -1)
return (isc__errno2result(errno));
f = fdopen(fd, "w");
if (f == NULL) {
result = isc__errno2result(errno);
close(fd);
return (result);
}
*fp = f;
return (ISC_R_SUCCESS);
}