file.c revision 2c34cafc1c7c5176c3f34dc80ba889c54fdec681
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer/*
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer * Copyright (C) 2000 Internet Software Consortium.
6fe42ff85ced80bd2ccc49b429d36831b5f2a5b9Tinderbox User *
bf8267aa453e5d2a735ed732a043b77a0b355b20Mark Andrews * Permission to use, copy, modify, and distribute this software for any
bf8267aa453e5d2a735ed732a043b77a0b355b20Mark Andrews * purpose with or without fee is hereby granted, provided that the above
bf8267aa453e5d2a735ed732a043b77a0b355b20Mark Andrews * copyright notice and this permission notice appear in all copies.
bf8267aa453e5d2a735ed732a043b77a0b355b20Mark Andrews *
bf8267aa453e5d2a735ed732a043b77a0b355b20Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
bf8267aa453e5d2a735ed732a043b77a0b355b20Mark Andrews * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
bf8267aa453e5d2a735ed732a043b77a0b355b20Mark Andrews * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
bf8267aa453e5d2a735ed732a043b77a0b355b20Mark Andrews * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
bf8267aa453e5d2a735ed732a043b77a0b355b20Mark Andrews * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
bf8267aa453e5d2a735ed732a043b77a0b355b20Mark Andrews * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
bf8267aa453e5d2a735ed732a043b77a0b355b20Mark Andrews * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
bf8267aa453e5d2a735ed732a043b77a0b355b20Mark Andrews * SOFTWARE.
bf8267aa453e5d2a735ed732a043b77a0b355b20Mark Andrews */
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews
1d32b1df372d6be6bac6450739b9e5ea23819995Evan Hunt#include <errno.h>
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer#include <stdio.h>
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer#include <stdlib.h>
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer#include <string.h>
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer#include <unistd.h>
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer
8aee18709f238406719768b8a6b843a15c5075f8Mark Andrews#include <sys/stat.h>
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Hunt#include <isc/assertions.h>
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Hunt#include <isc/file.h>
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Hunt#include <isc/result.h>
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Hunt#include <isc/time.h>
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Hunt
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Hunt/*
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Hunt * XXXDCL As the API for accessing file statistics undoubtedly gets expanded,
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Hunt * it might be good to provide a mechanism that allows for the results
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Hunt * of a previous stat() to be used again without having to do another stat.
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Hunt * Such as perl's mechanism of using "_" in place of a file name to indicate
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Hunt * that the results of the last stat should be used. But then you get into
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Hunt * annoying MP issues. BTW, Win32 has stat().
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Hunt */
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Huntstatic isc_result_t
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Huntfile_stats(const char *file, struct stat *stats) {
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Hunt isc_result_t result = ISC_R_SUCCESS;
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Hunt
30a60d2aff0ec1810262a8b8efc532e28b32bd57Evan Hunt if (stat(file, stats) != 0) {
222d38735f97f771054e223b03f84c5858252332Evan Hunt switch (errno) {
c634c94d673f1bab17e7f65d332f989b683e712cDavid Lawrence case ENOTDIR:
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer case ENOENT:
222d38735f97f771054e223b03f84c5858252332Evan Hunt result = ISC_R_NOTFOUND;
222d38735f97f771054e223b03f84c5858252332Evan Hunt break;
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer case ELOOP:
222d38735f97f771054e223b03f84c5858252332Evan Hunt case EINVAL:
c634c94d673f1bab17e7f65d332f989b683e712cDavid Lawrence case ENAMETOOLONG:
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer result = ISC_R_INVALIDFILE;
222d38735f97f771054e223b03f84c5858252332Evan Hunt break;
222d38735f97f771054e223b03f84c5858252332Evan Hunt case EACCES:
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer result = ISC_R_NOPERM;
222d38735f97f771054e223b03f84c5858252332Evan Hunt break;
c634c94d673f1bab17e7f65d332f989b683e712cDavid Lawrence case EIO:
222d38735f97f771054e223b03f84c5858252332Evan Hunt result = ISC_R_IOERROR;
222d38735f97f771054e223b03f84c5858252332Evan Hunt break;
222d38735f97f771054e223b03f84c5858252332Evan Hunt case EFAULT:
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer default:
222d38735f97f771054e223b03f84c5858252332Evan Hunt result = ISC_R_UNEXPECTED;
c634c94d673f1bab17e7f65d332f989b683e712cDavid Lawrence break;
fdebae839745f79a7550aeb49d15a930523ec483David Lawrence }
222d38735f97f771054e223b03f84c5858252332Evan Hunt }
28002bd7cb4baa0eab9f47e1e51069c5ea7ea5d4Andreas Gustafsson
28002bd7cb4baa0eab9f47e1e51069c5ea7ea5d4Andreas Gustafsson return (result);
1d32b1df372d6be6bac6450739b9e5ea23819995Evan Hunt}
1d32b1df372d6be6bac6450739b9e5ea23819995Evan Hunt
28002bd7cb4baa0eab9f47e1e51069c5ea7ea5d4Andreas Gustafssonisc_result_t
28002bd7cb4baa0eab9f47e1e51069c5ea7ea5d4Andreas Gustafssonisc_file_getmodtime(const char *file, isc_time_t *time) {
222d38735f97f771054e223b03f84c5858252332Evan Hunt isc_result_t result;
222d38735f97f771054e223b03f84c5858252332Evan Hunt struct stat stats;
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt REQUIRE(file != NULL && time != NULL);
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer
222d38735f97f771054e223b03f84c5858252332Evan Hunt result = file_stats(file, &stats);
c634c94d673f1bab17e7f65d332f989b683e712cDavid Lawrence
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer if (result == ISC_R_SUCCESS)
222d38735f97f771054e223b03f84c5858252332Evan Hunt /*
222d38735f97f771054e223b03f84c5858252332Evan Hunt * XXXDCL some operating systems provide nanoseconds, too,
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer * such as BSD/OS via st_mtimespec.
222d38735f97f771054e223b03f84c5858252332Evan Hunt */
c634c94d673f1bab17e7f65d332f989b683e712cDavid Lawrence isc_time_set(time, stats.st_mtime, 0);
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer
222d38735f97f771054e223b03f84c5858252332Evan Hunt return (result);
222d38735f97f771054e223b03f84c5858252332Evan Hunt}
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer
222d38735f97f771054e223b03f84c5858252332Evan Hunt#undef TEMPLATE
c634c94d673f1bab17e7f65d332f989b683e712cDavid Lawrence#define TEMPLATE "tmp-XXXXXXXXXX" /* 14 characters. */
222d38735f97f771054e223b03f84c5858252332Evan Hunt
222d38735f97f771054e223b03f84c5858252332Evan Huntisc_result_t
222d38735f97f771054e223b03f84c5858252332Evan Huntisc_file_mktemplate(const char *path, char *buf, size_t buflen) {
c3c6770e537ea916265c78d0294ad108233e17c1Michael Sawyer char *s;
222d38735f97f771054e223b03f84c5858252332Evan Hunt
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt REQUIRE(buf != NULL);
222d38735f97f771054e223b03f84c5858252332Evan Hunt
222d38735f97f771054e223b03f84c5858252332Evan Hunt s = strrchr(path, '/');
222d38735f97f771054e223b03f84c5858252332Evan Hunt
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt if (s != NULL) {
222d38735f97f771054e223b03f84c5858252332Evan Hunt if ((s - path + 1 + sizeof(TEMPLATE)) > buflen)
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt return (ISC_R_NOSPACE);
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt
222d38735f97f771054e223b03f84c5858252332Evan Hunt strncpy(buf, path, s - path + 1);
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt buf[s - path + 1] = '\0';
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt strcat(buf, TEMPLATE);
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt } else {
222d38735f97f771054e223b03f84c5858252332Evan Hunt if (sizeof(TEMPLATE) > buflen)
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt return (ISC_R_NOSPACE);
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt strcpy(buf, TEMPLATE);
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt }
222d38735f97f771054e223b03f84c5858252332Evan Hunt
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt return (ISC_R_SUCCESS);
222d38735f97f771054e223b03f84c5858252332Evan Hunt}
222d38735f97f771054e223b03f84c5858252332Evan Hunt
222d38735f97f771054e223b03f84c5858252332Evan Huntisc_result_t
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Huntisc_file_openunique(char *template, FILE **fp) {
222d38735f97f771054e223b03f84c5858252332Evan Hunt int fd;
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt FILE *f;
222d38735f97f771054e223b03f84c5858252332Evan Hunt isc_result_t result = ISC_R_SUCCESS;
222d38735f97f771054e223b03f84c5858252332Evan Hunt
9069215eac23e32f4ef1c8e44ad7ff2865cfcdacEvan Hunt REQUIRE(template != NULL);
222d38735f97f771054e223b03f84c5858252332Evan Hunt REQUIRE(fp != NULL && *fp == NULL);
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt /*
222d38735f97f771054e223b03f84c5858252332Evan Hunt * Win32 does not have mkstemp.
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt */
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt fd = mkstemp(template);
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt
222d38735f97f771054e223b03f84c5858252332Evan Hunt if (fd == -1)
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt switch (errno) {
222d38735f97f771054e223b03f84c5858252332Evan Hunt case ENOTDIR:
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt case ELOOP:
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt case EINVAL:
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt case ENAMETOOLONG:
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt result = ISC_R_INVALIDFILE;
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt break;
222d38735f97f771054e223b03f84c5858252332Evan Hunt case EACCES:
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt result = ISC_R_NOPERM;
222d38735f97f771054e223b03f84c5858252332Evan Hunt break;
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt case EEXIST:
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt result = ISC_R_EXISTS;
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt break;
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt case EIO:
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt result = ISC_R_IOERROR;
222d38735f97f771054e223b03f84c5858252332Evan Hunt break;
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt default:
222d38735f97f771054e223b03f84c5858252332Evan Hunt result = ISC_R_UNEXPECTED;
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt }
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt if (result == ISC_R_SUCCESS) {
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt f = fdopen(fd, "w+");
222d38735f97f771054e223b03f84c5858252332Evan Hunt if (f == NULL) {
222d38735f97f771054e223b03f84c5858252332Evan Hunt if (errno == ENOMEM)
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt result = ISC_R_NOMEMORY;
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt else
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt result = ISC_R_UNEXPECTED;
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt
222d38735f97f771054e223b03f84c5858252332Evan Hunt (void)remove(template);
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt (void)close(fd);
222d38735f97f771054e223b03f84c5858252332Evan Hunt
222d38735f97f771054e223b03f84c5858252332Evan Hunt } else
222d38735f97f771054e223b03f84c5858252332Evan Hunt *fp = f;
222d38735f97f771054e223b03f84c5858252332Evan Hunt }
222d38735f97f771054e223b03f84c5858252332Evan Hunt
222d38735f97f771054e223b03f84c5858252332Evan Hunt return (result);
b5b934a0bb46aded1552a17473652b5a7f4a3274Evan Hunt}
47e70d820ed07895a25e5b3520adf953114ac01eEvan Hunt