file.c revision ad38e19578815fc064ea0a5f455fa8beffc99e63
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister/*
ddad35552931651426ad70912d29d9ab7d2a8d80Automatic Updater * Copyright (C) 2000 Internet Software Consortium.
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews *
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Permission to use, copy, modify, and distribute this software for any
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater * purpose with or without fee is hereby granted, provided that the above
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * copyright notice and this permission notice appear in all copies.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister *
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉/* $Id: file.c,v 1.14 2001/07/11 04:32:15 mayer Exp $ */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein#include <config.h>
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#undef rename
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <errno.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <limits.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <stdlib.h>
364a82f7c25b62967678027043425201a5e5171aBob Halley#include <io.h>
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉#include <process.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
b3e77535185043f089b346166440402d092030c3David Lawrence#include <sys/stat.h>
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington#include <fcntl.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <sys/utime.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <isc/file.h>
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein#include <isc/result.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <isc/time.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <isc/util.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <isc/stat.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include "errno2result.h"
72166c5cf59db011cce11e98abe377f5aa6f7052Andreas Gustafsson
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister/*
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington * Emulate UNIX mkstemp, which returns an open FD to the new file
1c153afce556ff3c687986fb7c4a0b0a7f5e7cd8Mark Andrews *
08c90261660649ca7d92065f6f13a61ec5a9a86dMark Andrews */
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrewsstatic int
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristergettemp(char *path, int *doopen) {
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson char *start, *trv;
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson struct stat sbuf;
b3e77535185043f089b346166440402d092030c3David Lawrence int pid;
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson trv = strrchr(path, 'X');
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister trv++;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister pid = getpid();
b3e77535185043f089b346166440402d092030c3David Lawrence /* extra X's get set to 0's */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister while (*--trv == 'X') {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *trv = (pid % 10) + '0';
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister pid /= 10;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence }
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson /*
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson * check the target directory; if you have six X's and it
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * doesn't exist this runs for a *very* long time.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister for (start = trv + 1;; --trv) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (trv <= path)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister break;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (*trv == '\\') {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *trv = '\0';
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (stat(path, &sbuf))
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence return (0);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (!S_ISDIR(sbuf.st_mode)) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister errno = ENOTDIR;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister return (0);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister }
b3e77535185043f089b346166440402d092030c3David Lawrence *trv = '\\';
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister break;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister }
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister }
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister for (;;) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (doopen) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if ((*doopen =
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister open(path, O_CREAT|O_EXCL|O_RDWR,
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister _S_IREAD | _S_IWRITE)) >= 0)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister return (1);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (errno != EEXIST)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister return (0);
b3e77535185043f089b346166440402d092030c3David Lawrence } else if (stat(path, &sbuf))
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister return (errno == ENOENT ? 1 : 0);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* tricky little algorithm for backward compatibility */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister for (trv = start;;) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (!*trv)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister return (0);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (*trv == 'z')
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister *trv++ = 'a';
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister else {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (isdigit(*trv))
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister *trv = 'a';
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister else
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister ++*trv;
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson break;
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson }
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister }
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister }
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson /*NOTREACHED*/
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson}
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerint
b3e77535185043f089b346166440402d092030c3David Lawrencemkstemp(char *path) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister int fd;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence return (gettemp(path, &fd) ? fd : -1);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister}
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister/*
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * XXXDCL As the API for accessing file statistics undoubtedly gets expanded,
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * it might be good to provide a mechanism that allows for the results
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * of a previous stat() to be used again without having to do another stat,
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * such as perl's mechanism of using "_" in place of a file name to indicate
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * that the results of the last stat should be used. But then you get into
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson * annoying MP issues. BTW, Win32 has stat().
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic isc_result_t
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencefile_stats(const char *file, struct stat *stats) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_result_t result = ISC_R_SUCCESS;
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence REQUIRE(file != NULL);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister REQUIRE(stats != NULL);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (stat(file, stats) != 0)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister result = isc__errno2result(errno);
b3e77535185043f089b346166440402d092030c3David Lawrence
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister return (result);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister}
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence/*
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews * isc_file_safemovefile is needed to be defined here to ensure that
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews * any file with the new name is renamed to a backup name and then the
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews * rename is done. If all goes well then the backup can be deleted,
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews * otherwise it gets renamed back.
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews */
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrewsint
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrewsisc_file_safemovefile(const char *oldname, const char *newname) {
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews BOOL filestatus;
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews char buf[512];
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews struct stat sbuf;
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews BOOL exists = FALSE;
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews int tmpfd;
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /*
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Make sure we have something to do
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (stat(oldname, &sbuf) != 0) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister errno = ENOENT;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister return (-1);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister }
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence /*
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * Rename to a backup the new file if it still exists
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister */
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (stat(newname, &sbuf) == 0) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister exists = TRUE;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister strcpy(buf, newname);
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews strcat(buf, ".XXXXX");
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews tmpfd = mkstemp(buf);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (tmpfd > 0)
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence _close(tmpfd);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister DeleteFile(buf);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister _chmod(newname, _S_IREAD | _S_IWRITE);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister filestatus = MoveFile(newname, buf);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister }
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* Now rename the file to the new name
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister _chmod(oldname, _S_IREAD | _S_IWRITE);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence filestatus = MoveFile(oldname, newname);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (filestatus == 0) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /*
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * Try to rename the backup back to the original name
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * if the backup got created
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (exists == TRUE) {
b3e77535185043f089b346166440402d092030c3David Lawrence filestatus = MoveFile(buf, newname);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (filestatus == 0) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister errno = EACCES;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister }
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister }
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister return (-1);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister }
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /*
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Delete the backup file if it got created
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister */
b3e77535185043f089b346166440402d092030c3David Lawrence if (exists == TRUE)
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews filestatus = DeleteFile(buf);
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews return (0);
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews}
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrewsisc_result_t
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrewsisc_file_getmodtime(const char *file, isc_time_t *time) {
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews isc_result_t result;
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews struct stat stats;
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews REQUIRE(file != NULL);
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews REQUIRE(time != NULL);
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews result = file_stats(file, &stats);
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews if (result == ISC_R_SUCCESS)
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews /*
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews * XXXDCL some operating systems provide nanoseconds, too,
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews * such as BSD/OS via st_mtimespec.
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews */
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews isc_time_set(time, stats.st_mtime, 0);
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister return (result);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence}
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrenceisc_result_t
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafssonisc_file_settime(const char *file, isc_time_t *time) {
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson struct utimbuf timem;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence REQUIRE(file != NULL && time != NULL);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /*
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews * tv_sec is at least a 32 bit quantity on all platforms we're
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * dealing with, but it is signed on most (all?) of them,
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * so we need to make sure the high bit isn't set. This unfortunately
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * loses when either:
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * * tv_sec becomes a signed 64 bit integer but long is 32 bits
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister * and isc_time_seconds > LONG_MAX, or
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister * * isc_time_seconds is changed to be > 32 bits but long is 32 bits
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * and isc_time_seconds has at least 33 significant bits.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister */
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 timem.actime = timem.modtime = (long)isc_time_seconds(time);
7d4a465de03b26bf9f5ef131d03253b8f6afc169Mark Andrews
7d4a465de03b26bf9f5ef131d03253b8f6afc169Mark Andrews /*
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Here is the real check for the high bit being set.
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson */
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if ((timem.actime &
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister (1UL << (sizeof(timem.actime) * CHAR_BIT - 1))) != 0)
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence return (ISC_R_RANGE);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (utime(file, &timem) < 0)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister return (isc__errno2result(errno));
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister return (ISC_R_SUCCESS);
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson
b3e77535185043f089b346166440402d092030c3David Lawrence}
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#undef TEMPLATE
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#define TEMPLATE "XXXXXXXXXX.tmp" /* 14 characters. */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerisc_result_t
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrenceisc_file_mktemplate(const char *path, char *buf, size_t buflen) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister return (isc_file_template(path, TEMPLATE, buf, buflen));
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister}
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerisc_result_t
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerisc_file_template(const char *path, const char *templet, char *buf,
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson size_t buflen) {
b3e77535185043f089b346166440402d092030c3David Lawrence char *s;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence REQUIRE(path != NULL);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister REQUIRE(templet != NULL);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister REQUIRE(buf != NULL);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister s = strrchr(templet, '\\');
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (s != NULL)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister templet = s + 1;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister s = strrchr(path, '\\');
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (s != NULL) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if ((s - path + 1 + strlen(templet) + 1) > buflen)
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson return (ISC_R_NOSPACE);
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister strncpy(buf, path, s - path + 1);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister buf[s - path + 1] = '\0';
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson strcat(buf, templet);
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson } else {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if ((strlen(templet) + 1) > buflen)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister return (ISC_R_NOSPACE);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister strcpy(buf, templet);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister }
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister return (ISC_R_SUCCESS);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister}
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrenceisc_result_t
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerisc_file_renameunique(const char *file, char *templet) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister int fd = -1;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister int res = 0;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence isc_result_t result = ISC_R_SUCCESS;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister REQUIRE(file != NULL);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister REQUIRE(templet != NULL);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence fd = mkstemp(templet);
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 if (fd == -1)
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 result = isc__errno2result(errno);
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 if (result == ISC_R_SUCCESS) {
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 res = isc_file_safemovefile(file, templet);
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson if (res != 0) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence result = isc__errno2result(errno);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister (void)unlink(templet);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister }
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister }
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (fd != -1)
b3e77535185043f089b346166440402d092030c3David Lawrence close(fd);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister return (result);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence}
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrenceisc_result_t
b3e77535185043f089b346166440402d092030c3David Lawrenceisc_file_openunique(char *templet, FILE **fp) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence int fd;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister FILE *f;
b3e77535185043f089b346166440402d092030c3David Lawrence isc_result_t result = ISC_R_SUCCESS;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister REQUIRE(templet != NULL);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister REQUIRE(fp != NULL && *fp == NULL);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /*
b3e77535185043f089b346166440402d092030c3David Lawrence * Win32 does not have mkstemp. Using emulation above.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister fd = mkstemp(templet);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
b3e77535185043f089b346166440402d092030c3David Lawrence if (fd == -1)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister result = isc__errno2result(errno);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (result == ISC_R_SUCCESS) {
b3e77535185043f089b346166440402d092030c3David Lawrence f = fdopen(fd, "w+");
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (f == NULL) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister result = isc__errno2result(errno);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister (void)remove(templet);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister (void)close(fd);
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister } else
b3e77535185043f089b346166440402d092030c3David Lawrence *fp = f;
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister }
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister return (result);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence}
b3e77535185043f089b346166440402d092030c3David Lawrence
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrenceisc_result_t
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Bristerisc_file_remove(const char *filename) {
b3e77535185043f089b346166440402d092030c3David Lawrence int r;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister REQUIRE(filename != NULL);
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister r = unlink(filename);
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister if (r == 0)
b3e77535185043f089b346166440402d092030c3David Lawrence return (ISC_R_SUCCESS);
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister else
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister return (isc__errno2result(errno));
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence}
b3e77535185043f089b346166440402d092030c3David Lawrence
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Bristerisc_result_t
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Bristerisc_file_rename(const char *oldname, const char *newname) {
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister int r;
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister REQUIRE(oldname != NULL);
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister REQUIRE(newname != NULL);
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister r = isc_file_safemovefile(oldname, newname);
b3e77535185043f089b346166440402d092030c3David Lawrence if (r == 0)
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister return (ISC_R_SUCCESS);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence else
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister return (isc__errno2result(errno));
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence}
b3e77535185043f089b346166440402d092030c3David Lawrence
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrenceisc_boolean_t
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Bristerisc_file_exists(const char *pathname) {
b3e77535185043f089b346166440402d092030c3David Lawrence struct stat stats;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister REQUIRE(pathname != NULL);
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS));
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister}
b3e77535185043f089b346166440402d092030c3David Lawrence
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Bristerisc_boolean_t
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Bristerisc_file_isabsolute(const char *filename) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence REQUIRE(filename != NULL);
b3e77535185043f089b346166440402d092030c3David Lawrence /*
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister * Look for c:\path\... style or \\computer\shar\path...
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister * the UNC style file specs
b3e77535185043f089b346166440402d092030c3David Lawrence */
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister if ((filename[0] == '\\') && (filename[1] == '\\'))
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister return (ISC_TRUE);
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister if (isalpha(filename[0]) != 0 && filename[1] == ':' && filename[2] == '\\')
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington return (ISC_TRUE);
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington return (ISC_FALSE);
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington}
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellingtonisc_boolean_t
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellingtonisc_file_iscurrentdir(const char *filename) {
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington REQUIRE(filename != NULL);
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington return (ISC_TF(filename[0] == '.' && filename[1] == '\0'));
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington}
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellingtonconst char *
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellingtonisc_file_basename(const char *filename) {
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington char *s;
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington REQUIRE(filename != NULL);
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington s = strrchr(filename, '\\');
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington if (s == NULL)
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington return (filename);
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington return (s + 1);
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington}
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellingtonisc_result_t
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellingtonisc_file_progname(const char *filename, char *progname, size_t namelen) {
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington const char *s;
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington char *p;
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews size_t len;
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews REQUIRE(filename != NULL);
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews REQUIRE(progname != NULL);
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews /*
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews * Strip the path from the name
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews */
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews s = isc_file_basename(filename);
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews if (s == NULL) {
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews return (ISC_R_NOSPACE);
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews }
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews /*
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews * Strip any and all suffixes
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews */
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews p = strchr(s, '.');
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews if (p == NULL) {
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews if (namelen <= strlen(s))
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews return (ISC_R_NOSPACE);
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews strcpy(progname, s);
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews return (ISC_R_SUCCESS);
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews }
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews
db30f4bdcb66afb7eb1ab0c6882cc70be9a53d79Mark Andrews /*
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * Copy the result to the buffer
3e42bdfdc901b6b921b02028bd51ca2af8e84adcMark Andrews */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister len = p - s;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (len >= namelen)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister return (ISC_R_NOSPACE);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
b3e77535185043f089b346166440402d092030c3David Lawrence strncpy(progname, s, len);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence progname[len] = '\0';
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister return (ISC_R_SUCCESS);
b3e77535185043f089b346166440402d092030c3David Lawrence}
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence