bd911976d51f102751848568ccf56592fd5f6d77Tinderbox User * Copyright (C) 2000-2002, 2004, 2007, 2009, 2011-2017 Internet Systems Consortium, Inc. ("ISC")
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
b05a50c852608a40d1a06d6124bafb9b500c10c1Mukund Sivaraman "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * Emulate UNIX mkstemp, which returns an open FD to the new file
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsgettemp(char *path, isc_boolean_t binary, int *doopen) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer /* extra X's get set to 0's */
b05a50c852608a40d1a06d6124bafb9b500c10c1Mukund Sivaraman *trv = alphnum[which % (sizeof(alphnum) - 1)];
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * check the target directory; if you have six X's and it
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * doesn't exist this runs for a *very* long time.
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer /* tricky little algorithm for backward compatibility */
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer /*NOTREACHED*/
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * XXXDCL As the API for accessing file statistics undoubtedly gets expanded,
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * it might be good to provide a mechanism that allows for the results
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * of a previous stat() to be used again without having to do another stat,
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * such as perl's mechanism of using "_" in place of a file name to indicate
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * that the results of the last stat should be used. But then you get into
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * annoying MP issues. BTW, Win32 has stat().
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerfile_stats(const char *file, struct stat *stats) {
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson * isc_file_safemovefile is needed to be defined here to ensure that
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson * any file with the new name is renamed to a backup name and then the
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson * rename is done. If all goes well then the backup can be deleted,
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson * otherwise it gets renamed back.
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_safemovefile(const char *oldname, const char *newname) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * Make sure we have something to do
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer return (-1);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * Rename to a backup the new file if it still exists
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer /* Now rename the file to the new name
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson * Try to rename the backup back to the original name
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson * if the backup got created
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson * Delete the backup file if it got created
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_getmodtime(const char *file, isc_time_t *time) {
fdacf913e123db672888ff6b24a89caea6b12a50Danny Mayer if ((fh = open(file, _O_RDONLY | _O_BINARY)) < 0)
bdec94477cc9ecac9ff14d3399f47f3d71cd370aAndreas Gustafsson if (!GetFileTime((HANDLE) _get_osfhandle(fh),
c213258356638f9af1e1c68425df527b856567a2Francis Dupontisc_file_getsize(const char *file, off_t *size) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_settime(const char *file, isc_time_t *time) {
528baec07b1b9a566d47fc638ba5cbbe01475c74Andreas Gustafsson * Set the date via the filedate system call and return. Failing
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater * this call implies the new file times are not supported by the
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater * underlying file system.
528baec07b1b9a566d47fc638ba5cbbe01475c74Andreas Gustafsson if (!SetFileTime((HANDLE) _get_osfhandle(fh),
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer#define TEMPLATE "XXXXXXXXXX.tmp" /* 14 characters. */
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_mktemplate(const char *path, char *buf, size_t buflen) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer return (isc_file_template(path, TEMPLATE, buf, buflen));
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_template(const char *path, const char *templet, char *buf,
2b5e8ac28170ffc0a46c34db88aacc503c5a6111Mark Andrews if ((prefixlen + strlen(templet) + 1) > buflen)
5a93d3be4e0c652f455066bb764416173a00c951Mark Andrews /* Copy 'prefixlen' bytes and NUL terminate. */
5a93d3be4e0c652f455066bb764416173a00c951Mark Andrews strlcpy(buf, path, ISC_MIN(prefixlen + 1, buflen));
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_renameunique(const char *file, char *templet) {
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsopenuniquemode(char *templet, int mode, isc_boolean_t binary, FILE **fp) {
68c2ccc953059f389cefc0f8a5ce0f83be7458c9Danny Mayer * Win32 does not have mkstemp. Using emulation above.
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsisc_file_openuniqueprivate(char *templet, FILE **fp) {
7e9d637131516486630290d36c4c0db544cb700eMark Andrews return (openuniquemode(templet, mode, ISC_FALSE, fp));
7e9d637131516486630290d36c4c0db544cb700eMark Andrews return (openuniquemode(templet, mode, ISC_FALSE, fp));
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsisc_file_openuniquemode(char *templet, int mode, FILE **fp) {
7e9d637131516486630290d36c4c0db544cb700eMark Andrews return (openuniquemode(templet, mode, ISC_FALSE, fp));
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsisc_file_bopenuniqueprivate(char *templet, FILE **fp) {
7e9d637131516486630290d36c4c0db544cb700eMark Andrews return (openuniquemode(templet, mode, ISC_TRUE, fp));
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsisc_file_bopenunique(char *templet, FILE **fp) {
7e9d637131516486630290d36c4c0db544cb700eMark Andrews return (openuniquemode(templet, mode, ISC_TRUE, fp));
7e9d637131516486630290d36c4c0db544cb700eMark Andrewsisc_file_bopenuniquemode(char *templet, int mode, FILE **fp) {
7e9d637131516486630290d36c4c0db544cb700eMark Andrews return (openuniquemode(templet, mode, ISC_TRUE, fp));
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_rename(const char *oldname, const char *newname) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS));
32babe43eb479d2ae8736f9985a84d1b9d95a33aScott Mann * This function returns success if filename is a plain file.
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * This function returns success if filename is a plain file.
05284949f73d496092c6f21f1ef9d788075fa2dbEvan Hunt * This function returns success if filename is a directory.
c4958494a98a59ce25e9fecad76a9ab0e36cc59fDanny Mayer * Look for c:\path\... style, c:/path/... or \\computer\shar\path...
ad38e19578815fc064ea0a5f455fa8beffc99e63Danny Mayer * the UNC style file specs
ad38e19578815fc064ea0a5f455fa8beffc99e63Danny Mayer if ((filename[0] == '\\') && (filename[1] == '\\'))
911533025604975b5548d038ca09cff17c7f534eAndreas Gustafsson if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '\\')
911533025604975b5548d038ca09cff17c7f534eAndreas Gustafsson if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '/')
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer return (ISC_TF(filename[0] == '.' && filename[1] == '\0'));
ba35e9924e95c45f8ae536f453b9064740e49841Andreas Gustafssonisc_file_ischdiridempotent(const char *filename) {
1e71bc82b8e1a95d423d8db1c136080dc034433dAndreas Gustafsson return (s + 1);
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayerisc_file_progname(const char *filename, char *progname, size_t namelen) {
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer const char *s;
5b1c7ef35bb495820360182b5192689f33f1cc7dMark Andrews const char *p;
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * Strip the path from the name
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * Strip any and all suffixes
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * Copy the result to the buffer
5a93d3be4e0c652f455066bb764416173a00c951Mark Andrews /* Copy up to 'len' bytes and NUL terminate. */
5a93d3be4e0c652f455066bb764416173a00c951Mark Andrews strlcpy(progname, s, ISC_MIN(len + 1, namelen));
dee69dd3aafe1339cd62928b858d18fdc0536642Andreas Gustafssonisc_file_absolutepath(const char *filename, char *path, size_t pathlen) {
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews retval = GetFullPathName(filename, (DWORD) pathlen, path, &ptrname);
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayer /* Something went wrong in getting the path */
3bd4083e486d200d4f5992ac9da2dc7131c7b9aeDanny Mayer /* Caller needs to provide a larger buffer to contain the string */
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayerisc_file_truncate(const char *filename, isc_offset_t size) {
7c7b389ae01b7953982ed8827cfd6010fce6e575Danny Mayer if ((fh = open(filename, _O_RDWR | _O_BINARY)) < 0)
351b62535d4c4f89883bfdba025999dd32490266Evan Huntisc_file_safecreate(const char *filename, FILE **fp) {
5b1c7ef35bb495820360182b5192689f33f1cc7dMark Andrewsisc_file_splitpath(isc_mem_t *mctx, const char *path, char **dirname,
5b1c7ef35bb495820360182b5192689f33f1cc7dMark Andrews char const ** basename)
747abb4993e03b8812514e4476bff67f5248c717Evan Hunt if ((slash != NULL && backslash != NULL && backslash > slash) ||
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Huntisc_file_sanitize(const char *dir, const char *base, const char *ext,
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt * allow room for a full sha256 hash (64 chars
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt * plus null terminator)
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt /* Check whether the full-length SHA256 hash filename exists */
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt isc_sha256_data((const void *) base, strlen(base), hash);
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt hash, ext != NULL ? "." : "", ext != NULL ? ext : "");
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt /* Check for a truncated SHA256 hash filename */
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt hash, ext != NULL ? "." : "", ext != NULL ? ext : "");
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt * If neither hash filename already exists, then we'll use
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt * the original base name if it has no disallowed characters,
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt * or the truncated hash name if it does.
ce96d4326c872c8165b5e3a81ac5b49950c782c6Evan Hunt base, ext != NULL ? "." : "", ext != NULL ? ext : "");
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews * Based on http://blog.aaronballman.com/2011/08/how-to-check-access-rights/
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews if (isc_file_isdirectory(path) != ISC_R_SUCCESS) {
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews * Figure out buffer size. GetFileSecurity() should not succeed.
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews if (GetFileSecurity(path, OWNER_SECURITY_INFORMATION |
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews * GetFileSecurity() should succeed.
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews if (!GetFileSecurity(path, OWNER_SECURITY_INFORMATION |
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews if (OpenProcessToken(GetCurrentProcess(), TOKEN_IMPERSONATE |
24231e53a5c3079431f84dcddfee1e761fec7329Mark Andrews if (DuplicateToken(hToken, SecurityImpersonation,