file.c revision a2734fa74aecefc958622b01467398985041cec1
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence/*
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * Copyright (C) 2000, 2001 Internet Software Consortium.
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews *
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Permission to use, copy, modify, and distribute this software for any
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence * purpose with or without fee is hereby granted, provided that the above
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence * copyright notice and this permission notice appear in all copies.
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence *
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.
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence */
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence
7389e8330d62a059b8923fb8ca6f933caeb559d9Mark Andrews/*
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence * Portions Copyright (c) 1987, 1993
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * The Regents of the University of California. All rights reserved.
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence *
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence * Redistribution and use in source and binary forms, with or without
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence * modification, are permitted provided that the following conditions
6b7257f756eb0530cdf54df9a7fab8d51a5001c3David Lawrence * are met:
6b7257f756eb0530cdf54df9a7fab8d51a5001c3David Lawrence * 1. Redistributions of source code must retain the above copyright
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence * notice, this list of conditions and the following disclaimer.
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence * 2. Redistributions in binary form must reproduce the above copyright
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington * notice, this list of conditions and the following disclaimer in the
ce2be9b7211ab5bacaa10fe74ef35def3a3f6089David Lawrence * documentation and/or other materials provided with the distribution.
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence * 3. All advertising materials mentioning features or use of this software
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence * must display the following acknowledgement:
8f66dad9393ae0724f758c4a51e06ff55c2d1219Brian Wellington * This product includes software developed by the University of
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence * California, Berkeley and its contributors.
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews * 4. Neither the name of the University nor the names of its contributors
f96b41064bcd427d8125a096fd646c1f068d8ed7David Lawrence * may be used to endorse or promote products derived from this software
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington * without specific prior written permission.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence *
f96b41064bcd427d8125a096fd646c1f068d8ed7David Lawrence * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
e19501436a92cd48eba2ff47d90fa49c661ec8d8Brian Wellington * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
669e9657c731176df235832367f61435f7b83ddfAndreas Gustafsson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3db78e0855a8dfc162180880cd70d9c1a03d9301David Lawrence * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington * SUCH DAMAGE.
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington */
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington/* $Id: file.c,v 1.44 2002/05/22 05:57:17 marka Exp $ */
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
b493dfe8bce94b05efc0f161238d32f1234c5670Brian Wellington#include <config.h>
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
b493dfe8bce94b05efc0f161238d32f1234c5670Brian Wellington#include <errno.h>
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence#include <fcntl.h>
3f96cf3e4f96b36cc1ad2ec7edc5b8e285fced8fBrian Wellington#include <limits.h>
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington#include <stdlib.h>
bfafdac0616107ff32389532e7040567cd84b8aaBrian Wellington#include <time.h> /* Required for utimes on some platforms. */
4cd765650776027d05fe7fca248478918e02e63bDavid Lawrence#include <unistd.h> /* Required for mkstemp on NetBSD. */
4cd765650776027d05fe7fca248478918e02e63bDavid Lawrence
80b67b3a4f2d9fc7fdd32a50edc67ff189894da2Danny Mayer
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews#include <sys/stat.h>
87983da955bf63128de85d180359bdc418516c3cDavid Lawrence#include <sys/time.h>
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington#include <isc/dir.h>
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington#include <isc/file.h>
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington#include <isc/random.h>
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews#include <isc/string.h>
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington#include <isc/time.h>
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington#include <isc/util.h>
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington#include "errno2result.h"
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
30a4d5b0c23eb7a73d9635a98250560437a42d59David Lawrence/*
71ca6e64b4d208a090d255eb64c24f945e615ea0Brian Wellington * XXXDCL As the API for accessing file statistics undoubtedly gets expanded,
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence * it might be good to provide a mechanism that allows for the results
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence * of a previous stat() to be used again without having to do another stat,
bfafdac0616107ff32389532e7040567cd84b8aaBrian Wellington * such as perl's mechanism of using "_" in place of a file name to indicate
2ba574f329c14376d26d7c0f22c89d7a978a2625Mark Andrews * that the results of the last stat should be used. But then you get into
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews * annoying MP issues. BTW, Win32 has stat().
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence */
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellingtonstatic isc_result_t
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellingtonfile_stats(const char *file, struct stat *stats) {
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence isc_result_t result = ISC_R_SUCCESS;
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence REQUIRE(file != NULL);
6d6529b5e5ab7223fa2560ebe144bcb82517cef3Mark Andrews REQUIRE(stats != NULL);
6d6529b5e5ab7223fa2560ebe144bcb82517cef3Mark Andrews
94b166ffa58ef0ff263563c0550d0b30eb9f7772David Lawrence if (stat(file, stats) != 0)
f7c21e46c4b5fdae516b91374c24a87671f83ea3Andreas Gustafsson result = isc__errno2result(errno);
94b166ffa58ef0ff263563c0550d0b30eb9f7772David Lawrence
f7c21e46c4b5fdae516b91374c24a87671f83ea3Andreas Gustafsson return (result);
f7c21e46c4b5fdae516b91374c24a87671f83ea3Andreas Gustafsson}
f7c21e46c4b5fdae516b91374c24a87671f83ea3Andreas Gustafsson
f7c21e46c4b5fdae516b91374c24a87671f83ea3Andreas Gustafssonisc_result_t
f7c21e46c4b5fdae516b91374c24a87671f83ea3Andreas Gustafssonisc_file_getmodtime(const char *file, isc_time_t *time) {
5fe21da364d4397c9a413fe689ce82dea36a7b29Mark Andrews isc_result_t result;
5fe21da364d4397c9a413fe689ce82dea36a7b29Mark Andrews struct stat stats;
f29583dca7dc33d6fad6942a6eb4457c694a3974Brian Wellington
f29583dca7dc33d6fad6942a6eb4457c694a3974Brian Wellington REQUIRE(file != NULL);
f29583dca7dc33d6fad6942a6eb4457c694a3974Brian Wellington REQUIRE(time != NULL);
f29583dca7dc33d6fad6942a6eb4457c694a3974Brian Wellington
8b3fb4bded905d65153678f48a006eed5c13b27eAndreas Gustafsson result = file_stats(file, &stats);
f7c21e46c4b5fdae516b91374c24a87671f83ea3Andreas Gustafsson
f7c21e46c4b5fdae516b91374c24a87671f83ea3Andreas Gustafsson if (result == ISC_R_SUCCESS)
9719cb1205c4b30b46a98b4be7475e96befbea2bAndreas Gustafsson /*
f7c21e46c4b5fdae516b91374c24a87671f83ea3Andreas Gustafsson * XXXDCL some operating systems provide nanoseconds, too,
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews * such as BSD/OS via st_mtimespec.
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews */
f7c21e46c4b5fdae516b91374c24a87671f83ea3Andreas Gustafsson isc_time_set(time, stats.st_mtime, 0);
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews
cf300e03de3df3ff422db922520bf07c686c86daMark Andrews return (result);
9e560b59a722d06a62b5aed761e71fec72638a7cBrian Wellington}
dfceef7e68b56f6970dd2e8eea9980ad16bcc653Brian Wellington
9e560b59a722d06a62b5aed761e71fec72638a7cBrian Wellingtonisc_result_t
5455f30a7532738d750252c00e649890c694ee30Brian Wellingtonisc_file_settime(const char *file, isc_time_t *time) {
5455f30a7532738d750252c00e649890c694ee30Brian Wellington struct timeval times[2];
60213f2815a7e6584a2285546d05633fa7b6f5b4Mark Andrews
c30d291128e099a284fa6272b91b2bd64519a209Mark Andrews REQUIRE(file != NULL && time != NULL);
b7ce2258cab8eadbd834de8ca9d0b6f4c71f8c48Brian Wellington
79da8302e8d78f51db5243ba6b2f7de87e667132Mark Andrews /*
94b166ffa58ef0ff263563c0550d0b30eb9f7772David Lawrence * tv_sec is at least a 32 bit quantity on all platforms we're
94b166ffa58ef0ff263563c0550d0b30eb9f7772David Lawrence * dealing with, but it is signed on most (all?) of them,
87983da955bf63128de85d180359bdc418516c3cDavid Lawrence * so we need to make sure the high bit isn't set. This unfortunately
87983da955bf63128de85d180359bdc418516c3cDavid Lawrence * loses when either:
87983da955bf63128de85d180359bdc418516c3cDavid Lawrence * * tv_sec becomes a signed 64 bit integer but long is 32 bits
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence * and isc_time_seconds > LONG_MAX, or
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence * * isc_time_seconds is changed to be > 32 bits but long is 32 bits
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence * and isc_time_seconds has at least 33 significant bits.
20bd7b4bbf2437ef2f9109edca168ab0ce8445b3David Lawrence */
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington times[0].tv_sec = times[1].tv_sec = (long)isc_time_seconds(time);
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington
b493dfe8bce94b05efc0f161238d32f1234c5670Brian Wellington /*
7389e8330d62a059b8923fb8ca6f933caeb559d9Mark Andrews * Here is the real check for the high bit being set.
b493dfe8bce94b05efc0f161238d32f1234c5670Brian Wellington */
7389e8330d62a059b8923fb8ca6f933caeb559d9Mark Andrews if ((times[0].tv_sec &
7389e8330d62a059b8923fb8ca6f933caeb559d9Mark Andrews (1ULL << (sizeof(times[0].tv_sec) * CHAR_BIT - 1))) != 0)
7389e8330d62a059b8923fb8ca6f933caeb559d9Mark Andrews return (ISC_R_RANGE);
7389e8330d62a059b8923fb8ca6f933caeb559d9Mark Andrews
b493dfe8bce94b05efc0f161238d32f1234c5670Brian Wellington /*
b493dfe8bce94b05efc0f161238d32f1234c5670Brian Wellington * isc_time_nanoseconds guarantees a value that divided by 1000 will
b493dfe8bce94b05efc0f161238d32f1234c5670Brian Wellington * fit into the minimum possible size tv_usec field. Unfortunately,
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington * we don't know what that type is so can't cast directly ... but
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington * we can at least cast to signed so the IRIX compiler shuts up.
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington */
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington times[0].tv_usec = times[1].tv_usec =
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington (isc_int32_t)(isc_time_nanoseconds(time) / 1000);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington if (utimes(file, times) < 0)
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington return (isc__errno2result(errno));
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
71ca6e64b4d208a090d255eb64c24f945e615ea0Brian Wellington return (ISC_R_SUCCESS);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington}
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington#undef TEMPLATE
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington#define TEMPLATE "tmp-XXXXXXXXXX" /* 14 characters. */
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellingtonisc_result_t
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellingtonisc_file_mktemplate(const char *path, char *buf, size_t buflen) {
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington return (isc_file_template(path, TEMPLATE, buf, buflen));
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington}
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellingtonisc_result_t
e4cd5a1e5d0358abeee7618b02b4592c055d957fBrian Wellingtonisc_file_template(const char *path, const char *templet, char *buf,
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington size_t buflen) {
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington char *s;
71ca6e64b4d208a090d255eb64c24f945e615ea0Brian Wellington
71ca6e64b4d208a090d255eb64c24f945e615ea0Brian Wellington REQUIRE(path != NULL);
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence REQUIRE(templet != NULL);
e1d05d323526e7e65df13a6d3dfbec30f6ddb500Brian Wellington REQUIRE(buf != NULL);
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence
0a77211c806fa84fd66638b5cccf550c7cd7760dAndreas Gustafsson s = strrchr(templet, '/');
0a77211c806fa84fd66638b5cccf550c7cd7760dAndreas Gustafsson if (s != NULL)
0a77211c806fa84fd66638b5cccf550c7cd7760dAndreas Gustafsson templet = s + 1;
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington s = strrchr(path, '/');
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington if (s != NULL) {
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington if ((s - path + 1 + strlen(templet) + 1) > buflen)
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington return (ISC_R_NOSPACE);
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington strncpy(buf, path, s - path + 1);
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence buf[s - path + 1] = '\0';
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington strcat(buf, templet);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington } else {
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington if ((strlen(templet) + 1) > buflen)
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington return (ISC_R_NOSPACE);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington strcpy(buf, templet);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington }
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington return (ISC_R_SUCCESS);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington}
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellingtonstatic char alphnum[] =
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
e4cd5a1e5d0358abeee7618b02b4592c055d957fBrian Wellington
e4cd5a1e5d0358abeee7618b02b4592c055d957fBrian Wellingtonisc_result_t
e4cd5a1e5d0358abeee7618b02b4592c055d957fBrian Wellingtonisc_file_renameunique(const char *file, char *templet) {
e4cd5a1e5d0358abeee7618b02b4592c055d957fBrian Wellington char *x;
e4cd5a1e5d0358abeee7618b02b4592c055d957fBrian Wellington char *cp;
e4cd5a1e5d0358abeee7618b02b4592c055d957fBrian Wellington isc_uint32_t which;
e4cd5a1e5d0358abeee7618b02b4592c055d957fBrian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington REQUIRE(file != NULL);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington REQUIRE(templet != NULL);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington cp = templet;
fdba3257ced61501d9593224fc9fc83e57db2e87Andreas Gustafsson while (*cp != '\0')
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington cp++;
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington if (cp == templet)
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews return (ISC_R_FAILURE);
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews x = cp--;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews while (*cp == 'X' && cp >= templet) {
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews isc_random_get(&which);
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews *cp = alphnum[which % (sizeof(alphnum) - 1)];
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews x = cp--;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews }
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews while (link(file, templet) == -1) {
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews if (errno != EEXIST)
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews return (isc__errno2result(errno));
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews for (cp = x;;) {
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews char *t;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews if (*cp == '\0')
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews return (ISC_R_FAILURE);
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews t = strchr(alphnum, *cp);
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews if (t == NULL || *++t == '\0')
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews *cp++ = alphnum[0];
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews else {
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews *cp = *t;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews break;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews }
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews }
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews }
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews (void)unlink(file);
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews return (ISC_R_SUCCESS);
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews}
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrewsisc_result_t
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrewsisc_file_openunique(char *templet, FILE **fp) {
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews int fd;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews FILE *f;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews isc_result_t result = ISC_R_SUCCESS;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews char *x;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews char *cp;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews isc_uint32_t which;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews int mode;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews REQUIRE(templet != NULL);
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews REQUIRE(fp != NULL && *fp == NULL);
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews cp = templet;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews while (*cp != '\0')
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews cp++;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews if (cp == templet)
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews return (ISC_R_FAILURE);
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews x = cp--;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews while (*cp == 'X' && cp >= templet) {
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews isc_random_get(&which);
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews *cp = alphnum[which % (sizeof(alphnum) - 1)];
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews x = cp--;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews }
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews while ((fd = open(templet, O_RDWR|O_CREAT|O_EXCL, mode)) == -1) {
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews if (errno != EEXIST)
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews return (isc__errno2result(errno));
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews for (cp = x;;) {
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews char *t;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews if (*cp == '\0')
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews return (ISC_R_FAILURE);
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews t = strchr(alphnum, *cp);
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews if (t == NULL || *++t == '\0')
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews *cp++ = alphnum[0];
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews else {
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews *cp = *t;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews break;
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews }
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews }
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews }
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews f = fdopen(fd, "w+");
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews if (f == NULL) {
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews result = isc__errno2result(errno);
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews (void)remove(templet);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington (void)close(fd);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington } else
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington *fp = f;
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington return (result);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington}
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellingtonisc_result_t
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellingtonisc_file_remove(const char *filename) {
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington int r;
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington REQUIRE(filename != NULL);
71ca6e64b4d208a090d255eb64c24f945e615ea0Brian Wellington
71ca6e64b4d208a090d255eb64c24f945e615ea0Brian Wellington r = unlink(filename);
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington if (r == 0)
420e5e1022ff5ca4697ed5286462eeaf03614e53Brian Wellington return (ISC_R_SUCCESS);
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington else
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington return (isc__errno2result(errno));
420e5e1022ff5ca4697ed5286462eeaf03614e53Brian Wellington}
420e5e1022ff5ca4697ed5286462eeaf03614e53Brian Wellington
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellingtonisc_result_t
420e5e1022ff5ca4697ed5286462eeaf03614e53Brian Wellingtonisc_file_rename(const char *oldname, const char *newname) {
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington int r;
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington REQUIRE(oldname != NULL);
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington REQUIRE(newname != NULL);
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington r = rename(oldname, newname);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington if (r == 0)
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington return (ISC_R_SUCCESS);
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrews else
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington return (isc__errno2result(errno));
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington}
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellingtonisc_boolean_t
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrewsisc_file_exists(const char *pathname) {
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington struct stat stats;
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington REQUIRE(pathname != NULL);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS));
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington}
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellingtonisc_boolean_t
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellingtonisc_file_isabsolute(const char *filename) {
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington REQUIRE(filename != NULL);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington return (ISC_TF(filename[0] == '/'));
35112a392f7baecfdfca9e32c6cf6188ce4f5a1cBrian Wellington}
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellingtonisc_boolean_t
72ddc4cef9c6a6de53aae530dea1ddbb90631131Mark Andrewsisc_file_iscurrentdir(const char *filename) {
71ca6e64b4d208a090d255eb64c24f945e615ea0Brian Wellington REQUIRE(filename != NULL);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington return (ISC_TF(filename[0] == '.' && filename[1] == '\0'));
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington}
71ca6e64b4d208a090d255eb64c24f945e615ea0Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellingtonisc_boolean_t
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellingtonisc_file_ischdiridempotent(const char *filename) {
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington REQUIRE(filename != NULL);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington if (isc_file_isabsolute(filename))
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington return (ISC_TRUE);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington if (isc_file_iscurrentdir(filename))
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington return (ISC_TRUE);
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington return (ISC_FALSE);
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence}
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington
73a691c373488e4f70387a62462cd8ce0d991705David Lawrenceconst char *
73a691c373488e4f70387a62462cd8ce0d991705David Lawrenceisc_file_basename(const char *filename) {
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence char *s;
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington REQUIRE(filename != NULL);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington s = strrchr(filename, '/');
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington if (s == NULL)
71ca6e64b4d208a090d255eb64c24f945e615ea0Brian Wellington return (filename);
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington
1d92d8a2456b23842a649b6104c60a9d6ea25333Brian Wellington return (s + 1);
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington}
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellingtonisc_result_t
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellingtonisc_file_progname(const char *filename, char *buf, size_t buflen) {
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington const char *base;
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington size_t len;
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington
b6b9d8b8434e4eaab74b69cd14fcacf448055ca5Brian Wellington REQUIRE(filename != NULL);
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence REQUIRE(buf != NULL);
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews base = isc_file_basename(filename);
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence len = strlen(base) + 1;
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence if (len > buflen)
7389e8330d62a059b8923fb8ca6f933caeb559d9Mark Andrews return (ISC_R_NOSPACE);
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews memcpy(buf, base, len);
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews return (ISC_R_SUCCESS);
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews}
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews/*
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews * Put the absolute name of the current directory into 'dirname', which is
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews * a buffer of at least 'length' characters. End the string with the
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews * appropriate path separator, such that the final product could be
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews * concatenated with a relative pathname to make a valid pathname string.
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews */
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrewsstatic isc_result_t
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrewsdir_current(char *dirname, size_t length) {
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews char *cwd;
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews isc_result_t result = ISC_R_SUCCESS;
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews
7389e8330d62a059b8923fb8ca6f933caeb559d9Mark Andrews REQUIRE(dirname != NULL);
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence REQUIRE(length > 0);
504f7802d4c9b43db4820f496c4d00e078effa18David Lawrence
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews cwd = getcwd(dirname, length);
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence if (cwd == NULL) {
504f7802d4c9b43db4820f496c4d00e078effa18David Lawrence if (errno == ERANGE)
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence result = ISC_R_NOSPACE;
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews else
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews result = isc__errno2result(errno);
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence } else {
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence if (strlen(dirname) + 1 == length)
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence result = ISC_R_NOSPACE;
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence else if (dirname[1] != '\0')
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence strcat(dirname, "/");
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence }
73a691c373488e4f70387a62462cd8ce0d991705David Lawrence
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews return (result);
0a77211c806fa84fd66638b5cccf550c7cd7760dAndreas Gustafsson}
0a77211c806fa84fd66638b5cccf550c7cd7760dAndreas Gustafsson
73a691c373488e4f70387a62462cd8ce0d991705David Lawrenceisc_result_t
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrewsisc_file_absolutepath(const char *filename, char *path, size_t pathlen) {
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews isc_result_t result;
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews result = dir_current(path, pathlen);
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews if (result != ISC_R_SUCCESS)
0a77211c806fa84fd66638b5cccf550c7cd7760dAndreas Gustafsson return (result);
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews if (strlen(path) + strlen(filename) + 1 > pathlen)
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews return (ISC_R_NOSPACE);
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews strcat(path, filename);
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews return (ISC_R_SUCCESS);
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews}
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrewsisc_result_t
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrewsisc_file_truncate(const char *filename, isc_offset_t size) {
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews isc_result_t result = ISC_R_SUCCESS;
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews if (truncate(filename, size) < 0)
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson result = isc__errno2result(errno);
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews return (result);
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews}
326bcfa0e2a6b924cb829a0bcc3bf9590ce21ad6Mark Andrews