xref: /minix3/external/bsd/bind/dist/lib/isc/win32/file.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: file.c,v 1.9 2014/12/10 04:38:01 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004, 2007, 2009, 2011-2013  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 2000-2002  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /* Id */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek #include <config.h>
23*00b67f09SDavid van Moolenbroek 
24*00b67f09SDavid van Moolenbroek #undef rename
25*00b67f09SDavid van Moolenbroek #include <errno.h>
26*00b67f09SDavid van Moolenbroek #include <limits.h>
27*00b67f09SDavid van Moolenbroek #include <stdlib.h>
28*00b67f09SDavid van Moolenbroek #include <io.h>
29*00b67f09SDavid van Moolenbroek #include <process.h>
30*00b67f09SDavid van Moolenbroek 
31*00b67f09SDavid van Moolenbroek #include <sys/stat.h>
32*00b67f09SDavid van Moolenbroek #include <fcntl.h>
33*00b67f09SDavid van Moolenbroek #include <sys/utime.h>
34*00b67f09SDavid van Moolenbroek 
35*00b67f09SDavid van Moolenbroek #include <isc/file.h>
36*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
37*00b67f09SDavid van Moolenbroek #include <isc/result.h>
38*00b67f09SDavid van Moolenbroek #include <isc/time.h>
39*00b67f09SDavid van Moolenbroek #include <isc/util.h>
40*00b67f09SDavid van Moolenbroek #include <isc/stat.h>
41*00b67f09SDavid van Moolenbroek #include <isc/string.h>
42*00b67f09SDavid van Moolenbroek 
43*00b67f09SDavid van Moolenbroek #include "errno2result.h"
44*00b67f09SDavid van Moolenbroek 
45*00b67f09SDavid van Moolenbroek /*
46*00b67f09SDavid van Moolenbroek  * Emulate UNIX mkstemp, which returns an open FD to the new file
47*00b67f09SDavid van Moolenbroek  *
48*00b67f09SDavid van Moolenbroek  */
49*00b67f09SDavid van Moolenbroek static int
gettemp(char * path,isc_boolean_t binary,int * doopen)50*00b67f09SDavid van Moolenbroek gettemp(char *path, isc_boolean_t binary, int *doopen) {
51*00b67f09SDavid van Moolenbroek 	char *start, *trv;
52*00b67f09SDavid van Moolenbroek 	struct stat sbuf;
53*00b67f09SDavid van Moolenbroek 	int pid;
54*00b67f09SDavid van Moolenbroek 	int flags = O_CREAT|O_EXCL|O_RDWR;
55*00b67f09SDavid van Moolenbroek 
56*00b67f09SDavid van Moolenbroek 	if (binary)
57*00b67f09SDavid van Moolenbroek 		flags |= _O_BINARY;
58*00b67f09SDavid van Moolenbroek 
59*00b67f09SDavid van Moolenbroek 	trv = strrchr(path, 'X');
60*00b67f09SDavid van Moolenbroek 	trv++;
61*00b67f09SDavid van Moolenbroek 	pid = getpid();
62*00b67f09SDavid van Moolenbroek 	/* extra X's get set to 0's */
63*00b67f09SDavid van Moolenbroek 	while (*--trv == 'X') {
64*00b67f09SDavid van Moolenbroek 		*trv = (pid % 10) + '0';
65*00b67f09SDavid van Moolenbroek 		pid /= 10;
66*00b67f09SDavid van Moolenbroek 	}
67*00b67f09SDavid van Moolenbroek 	/*
68*00b67f09SDavid van Moolenbroek 	 * check the target directory; if you have six X's and it
69*00b67f09SDavid van Moolenbroek 	 * doesn't exist this runs for a *very* long time.
70*00b67f09SDavid van Moolenbroek 	 */
71*00b67f09SDavid van Moolenbroek 	for (start = trv + 1;; --trv) {
72*00b67f09SDavid van Moolenbroek 		if (trv <= path)
73*00b67f09SDavid van Moolenbroek 			break;
74*00b67f09SDavid van Moolenbroek 		if (*trv == '\\') {
75*00b67f09SDavid van Moolenbroek 			*trv = '\0';
76*00b67f09SDavid van Moolenbroek 			if (stat(path, &sbuf))
77*00b67f09SDavid van Moolenbroek 				return (0);
78*00b67f09SDavid van Moolenbroek 			if (!S_ISDIR(sbuf.st_mode)) {
79*00b67f09SDavid van Moolenbroek 				errno = ENOTDIR;
80*00b67f09SDavid van Moolenbroek 				return (0);
81*00b67f09SDavid van Moolenbroek 			}
82*00b67f09SDavid van Moolenbroek 			*trv = '\\';
83*00b67f09SDavid van Moolenbroek 			break;
84*00b67f09SDavid van Moolenbroek 		}
85*00b67f09SDavid van Moolenbroek 	}
86*00b67f09SDavid van Moolenbroek 
87*00b67f09SDavid van Moolenbroek 	for (;;) {
88*00b67f09SDavid van Moolenbroek 		if (doopen) {
89*00b67f09SDavid van Moolenbroek 			if ((*doopen =
90*00b67f09SDavid van Moolenbroek 			    open(path, flags, _S_IREAD | _S_IWRITE)) >= 0)
91*00b67f09SDavid van Moolenbroek 				return (1);
92*00b67f09SDavid van Moolenbroek 			if (errno != EEXIST)
93*00b67f09SDavid van Moolenbroek 				return (0);
94*00b67f09SDavid van Moolenbroek 		} else if (stat(path, &sbuf))
95*00b67f09SDavid van Moolenbroek 			return (errno == ENOENT ? 1 : 0);
96*00b67f09SDavid van Moolenbroek 
97*00b67f09SDavid van Moolenbroek 		/* tricky little algorithm for backward compatibility */
98*00b67f09SDavid van Moolenbroek 		for (trv = start;;) {
99*00b67f09SDavid van Moolenbroek 			if (!*trv)
100*00b67f09SDavid van Moolenbroek 				return (0);
101*00b67f09SDavid van Moolenbroek 			if (*trv == 'z')
102*00b67f09SDavid van Moolenbroek 				*trv++ = 'a';
103*00b67f09SDavid van Moolenbroek 			else {
104*00b67f09SDavid van Moolenbroek 				if (isdigit(*trv))
105*00b67f09SDavid van Moolenbroek 					*trv = 'a';
106*00b67f09SDavid van Moolenbroek 				else
107*00b67f09SDavid van Moolenbroek 					++*trv;
108*00b67f09SDavid van Moolenbroek 				break;
109*00b67f09SDavid van Moolenbroek 			}
110*00b67f09SDavid van Moolenbroek 		}
111*00b67f09SDavid van Moolenbroek 	}
112*00b67f09SDavid van Moolenbroek 	/*NOTREACHED*/
113*00b67f09SDavid van Moolenbroek }
114*00b67f09SDavid van Moolenbroek 
115*00b67f09SDavid van Moolenbroek static int
mkstemp(char * path,isc_boolean_t binary)116*00b67f09SDavid van Moolenbroek mkstemp(char *path, isc_boolean_t binary) {
117*00b67f09SDavid van Moolenbroek 	int fd;
118*00b67f09SDavid van Moolenbroek 
119*00b67f09SDavid van Moolenbroek 	return (gettemp(path, binary, &fd) ? fd : -1);
120*00b67f09SDavid van Moolenbroek }
121*00b67f09SDavid van Moolenbroek 
122*00b67f09SDavid van Moolenbroek /*
123*00b67f09SDavid van Moolenbroek  * XXXDCL As the API for accessing file statistics undoubtedly gets expanded,
124*00b67f09SDavid van Moolenbroek  * it might be good to provide a mechanism that allows for the results
125*00b67f09SDavid van Moolenbroek  * of a previous stat() to be used again without having to do another stat,
126*00b67f09SDavid van Moolenbroek  * such as perl's mechanism of using "_" in place of a file name to indicate
127*00b67f09SDavid van Moolenbroek  * that the results of the last stat should be used.  But then you get into
128*00b67f09SDavid van Moolenbroek  * annoying MP issues.   BTW, Win32 has stat().
129*00b67f09SDavid van Moolenbroek  */
130*00b67f09SDavid van Moolenbroek static isc_result_t
file_stats(const char * file,struct stat * stats)131*00b67f09SDavid van Moolenbroek file_stats(const char *file, struct stat *stats) {
132*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
133*00b67f09SDavid van Moolenbroek 
134*00b67f09SDavid van Moolenbroek 	REQUIRE(file != NULL);
135*00b67f09SDavid van Moolenbroek 	REQUIRE(stats != NULL);
136*00b67f09SDavid van Moolenbroek 
137*00b67f09SDavid van Moolenbroek 	if (stat(file, stats) != 0)
138*00b67f09SDavid van Moolenbroek 		result = isc__errno2result(errno);
139*00b67f09SDavid van Moolenbroek 
140*00b67f09SDavid van Moolenbroek 	return (result);
141*00b67f09SDavid van Moolenbroek }
142*00b67f09SDavid van Moolenbroek 
143*00b67f09SDavid van Moolenbroek static isc_result_t
fd_stats(int fd,struct stat * stats)144*00b67f09SDavid van Moolenbroek fd_stats(int fd, struct stat *stats) {
145*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
146*00b67f09SDavid van Moolenbroek 
147*00b67f09SDavid van Moolenbroek 	REQUIRE(stats != NULL);
148*00b67f09SDavid van Moolenbroek 
149*00b67f09SDavid van Moolenbroek 	if (fstat(fd, stats) != 0)
150*00b67f09SDavid van Moolenbroek 		result = isc__errno2result(errno);
151*00b67f09SDavid van Moolenbroek 
152*00b67f09SDavid van Moolenbroek 	return (result);
153*00b67f09SDavid van Moolenbroek }
154*00b67f09SDavid van Moolenbroek 
155*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_getsizefd(int fd,off_t * size)156*00b67f09SDavid van Moolenbroek isc_file_getsizefd(int fd, off_t *size) {
157*00b67f09SDavid van Moolenbroek 	isc_result_t result;
158*00b67f09SDavid van Moolenbroek 	struct stat stats;
159*00b67f09SDavid van Moolenbroek 
160*00b67f09SDavid van Moolenbroek 	REQUIRE(size != NULL);
161*00b67f09SDavid van Moolenbroek 
162*00b67f09SDavid van Moolenbroek 	result = fd_stats(fd, &stats);
163*00b67f09SDavid van Moolenbroek 
164*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS)
165*00b67f09SDavid van Moolenbroek 		*size = stats.st_size;
166*00b67f09SDavid van Moolenbroek 	return (result);
167*00b67f09SDavid van Moolenbroek }
168*00b67f09SDavid van Moolenbroek 
169*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_mode(const char * file,mode_t * modep)170*00b67f09SDavid van Moolenbroek isc_file_mode(const char *file, mode_t *modep) {
171*00b67f09SDavid van Moolenbroek 	isc_result_t result;
172*00b67f09SDavid van Moolenbroek 	struct stat stats;
173*00b67f09SDavid van Moolenbroek 
174*00b67f09SDavid van Moolenbroek 	REQUIRE(modep != NULL);
175*00b67f09SDavid van Moolenbroek 
176*00b67f09SDavid van Moolenbroek 	result = file_stats(file, &stats);
177*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS)
178*00b67f09SDavid van Moolenbroek 		*modep = (stats.st_mode & 07777);
179*00b67f09SDavid van Moolenbroek 	return (result);
180*00b67f09SDavid van Moolenbroek }
181*00b67f09SDavid van Moolenbroek 
182*00b67f09SDavid van Moolenbroek /*
183*00b67f09SDavid van Moolenbroek  * isc_file_safemovefile is needed to be defined here to ensure that
184*00b67f09SDavid van Moolenbroek  * any file with the new name is renamed to a backup name and then the
185*00b67f09SDavid van Moolenbroek  * rename is done. If all goes well then the backup can be deleted,
186*00b67f09SDavid van Moolenbroek  * otherwise it gets renamed back.
187*00b67f09SDavid van Moolenbroek  */
188*00b67f09SDavid van Moolenbroek 
189*00b67f09SDavid van Moolenbroek int
isc_file_safemovefile(const char * oldname,const char * newname)190*00b67f09SDavid van Moolenbroek isc_file_safemovefile(const char *oldname, const char *newname) {
191*00b67f09SDavid van Moolenbroek 	BOOL filestatus;
192*00b67f09SDavid van Moolenbroek 	char buf[512];
193*00b67f09SDavid van Moolenbroek 	struct stat sbuf;
194*00b67f09SDavid van Moolenbroek 	BOOL exists = FALSE;
195*00b67f09SDavid van Moolenbroek 	int tmpfd;
196*00b67f09SDavid van Moolenbroek 
197*00b67f09SDavid van Moolenbroek 	/*
198*00b67f09SDavid van Moolenbroek 	 * Make sure we have something to do
199*00b67f09SDavid van Moolenbroek 	 */
200*00b67f09SDavid van Moolenbroek 	if (stat(oldname, &sbuf) != 0) {
201*00b67f09SDavid van Moolenbroek 		errno = ENOENT;
202*00b67f09SDavid van Moolenbroek 		return (-1);
203*00b67f09SDavid van Moolenbroek 	}
204*00b67f09SDavid van Moolenbroek 
205*00b67f09SDavid van Moolenbroek 	/*
206*00b67f09SDavid van Moolenbroek 	 * Rename to a backup the new file if it still exists
207*00b67f09SDavid van Moolenbroek 	 */
208*00b67f09SDavid van Moolenbroek 	if (stat(newname, &sbuf) == 0) {
209*00b67f09SDavid van Moolenbroek 		exists = TRUE;
210*00b67f09SDavid van Moolenbroek 		strcpy(buf, newname);
211*00b67f09SDavid van Moolenbroek 		strcat(buf, ".XXXXX");
212*00b67f09SDavid van Moolenbroek 		tmpfd = mkstemp(buf, ISC_TRUE);
213*00b67f09SDavid van Moolenbroek 		if (tmpfd > 0)
214*00b67f09SDavid van Moolenbroek 			_close(tmpfd);
215*00b67f09SDavid van Moolenbroek 		(void)DeleteFile(buf);
216*00b67f09SDavid van Moolenbroek 		_chmod(newname, _S_IREAD | _S_IWRITE);
217*00b67f09SDavid van Moolenbroek 
218*00b67f09SDavid van Moolenbroek 		filestatus = MoveFile(newname, buf);
219*00b67f09SDavid van Moolenbroek 	}
220*00b67f09SDavid van Moolenbroek 	/* Now rename the file to the new name
221*00b67f09SDavid van Moolenbroek 	 */
222*00b67f09SDavid van Moolenbroek 	_chmod(oldname, _S_IREAD | _S_IWRITE);
223*00b67f09SDavid van Moolenbroek 
224*00b67f09SDavid van Moolenbroek 	filestatus = MoveFile(oldname, newname);
225*00b67f09SDavid van Moolenbroek 	if (filestatus == 0) {
226*00b67f09SDavid van Moolenbroek 		/*
227*00b67f09SDavid van Moolenbroek 		 * Try to rename the backup back to the original name
228*00b67f09SDavid van Moolenbroek 		 * if the backup got created
229*00b67f09SDavid van Moolenbroek 		 */
230*00b67f09SDavid van Moolenbroek 		if (exists == TRUE) {
231*00b67f09SDavid van Moolenbroek 			filestatus = MoveFile(buf, newname);
232*00b67f09SDavid van Moolenbroek 			if (filestatus == 0)
233*00b67f09SDavid van Moolenbroek 				errno = EACCES;
234*00b67f09SDavid van Moolenbroek 		}
235*00b67f09SDavid van Moolenbroek 		return (-1);
236*00b67f09SDavid van Moolenbroek 	}
237*00b67f09SDavid van Moolenbroek 
238*00b67f09SDavid van Moolenbroek 	/*
239*00b67f09SDavid van Moolenbroek 	 * Delete the backup file if it got created
240*00b67f09SDavid van Moolenbroek 	 */
241*00b67f09SDavid van Moolenbroek 	if (exists == TRUE)
242*00b67f09SDavid van Moolenbroek 		(void)DeleteFile(buf);
243*00b67f09SDavid van Moolenbroek 	return (0);
244*00b67f09SDavid van Moolenbroek }
245*00b67f09SDavid van Moolenbroek 
246*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_getmodtime(const char * file,isc_time_t * time)247*00b67f09SDavid van Moolenbroek isc_file_getmodtime(const char *file, isc_time_t *time) {
248*00b67f09SDavid van Moolenbroek 	int fh;
249*00b67f09SDavid van Moolenbroek 
250*00b67f09SDavid van Moolenbroek 	REQUIRE(file != NULL);
251*00b67f09SDavid van Moolenbroek 	REQUIRE(time != NULL);
252*00b67f09SDavid van Moolenbroek 
253*00b67f09SDavid van Moolenbroek 	if ((fh = open(file, _O_RDONLY | _O_BINARY)) < 0)
254*00b67f09SDavid van Moolenbroek 		return (isc__errno2result(errno));
255*00b67f09SDavid van Moolenbroek 
256*00b67f09SDavid van Moolenbroek 	if (!GetFileTime((HANDLE) _get_osfhandle(fh),
257*00b67f09SDavid van Moolenbroek 			 NULL,
258*00b67f09SDavid van Moolenbroek 			 NULL,
259*00b67f09SDavid van Moolenbroek 			 &time->absolute))
260*00b67f09SDavid van Moolenbroek 	{
261*00b67f09SDavid van Moolenbroek 		close(fh);
262*00b67f09SDavid van Moolenbroek 		errno = EINVAL;
263*00b67f09SDavid van Moolenbroek 		return (isc__errno2result(errno));
264*00b67f09SDavid van Moolenbroek 	}
265*00b67f09SDavid van Moolenbroek 	close(fh);
266*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
267*00b67f09SDavid van Moolenbroek }
268*00b67f09SDavid van Moolenbroek 
269*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_getsize(const char * file,off_t * size)270*00b67f09SDavid van Moolenbroek isc_file_getsize(const char *file, off_t *size) {
271*00b67f09SDavid van Moolenbroek 	isc_result_t result;
272*00b67f09SDavid van Moolenbroek 	struct stat stats;
273*00b67f09SDavid van Moolenbroek 
274*00b67f09SDavid van Moolenbroek 	REQUIRE(file != NULL);
275*00b67f09SDavid van Moolenbroek 	REQUIRE(size != NULL);
276*00b67f09SDavid van Moolenbroek 
277*00b67f09SDavid van Moolenbroek 	result = file_stats(file, &stats);
278*00b67f09SDavid van Moolenbroek 
279*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS)
280*00b67f09SDavid van Moolenbroek 		*size = stats.st_size;
281*00b67f09SDavid van Moolenbroek 
282*00b67f09SDavid van Moolenbroek 	return (result);
283*00b67f09SDavid van Moolenbroek }
284*00b67f09SDavid van Moolenbroek 
285*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_settime(const char * file,isc_time_t * time)286*00b67f09SDavid van Moolenbroek isc_file_settime(const char *file, isc_time_t *time) {
287*00b67f09SDavid van Moolenbroek 	int fh;
288*00b67f09SDavid van Moolenbroek 
289*00b67f09SDavid van Moolenbroek 	REQUIRE(file != NULL && time != NULL);
290*00b67f09SDavid van Moolenbroek 
291*00b67f09SDavid van Moolenbroek 	if ((fh = open(file, _O_RDWR | _O_BINARY)) < 0)
292*00b67f09SDavid van Moolenbroek 		return (isc__errno2result(errno));
293*00b67f09SDavid van Moolenbroek 
294*00b67f09SDavid van Moolenbroek 	/*
295*00b67f09SDavid van Moolenbroek 	 * Set the date via the filedate system call and return.  Failing
296*00b67f09SDavid van Moolenbroek 	 * this call implies the new file times are not supported by the
297*00b67f09SDavid van Moolenbroek 	 * underlying file system.
298*00b67f09SDavid van Moolenbroek 	 */
299*00b67f09SDavid van Moolenbroek 	if (!SetFileTime((HANDLE) _get_osfhandle(fh),
300*00b67f09SDavid van Moolenbroek 			 NULL,
301*00b67f09SDavid van Moolenbroek 			 &time->absolute,
302*00b67f09SDavid van Moolenbroek 			 &time->absolute))
303*00b67f09SDavid van Moolenbroek 	{
304*00b67f09SDavid van Moolenbroek 		close(fh);
305*00b67f09SDavid van Moolenbroek 		errno = EINVAL;
306*00b67f09SDavid van Moolenbroek 		return (isc__errno2result(errno));
307*00b67f09SDavid van Moolenbroek 	}
308*00b67f09SDavid van Moolenbroek 
309*00b67f09SDavid van Moolenbroek 	close(fh);
310*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
311*00b67f09SDavid van Moolenbroek 
312*00b67f09SDavid van Moolenbroek }
313*00b67f09SDavid van Moolenbroek 
314*00b67f09SDavid van Moolenbroek #undef TEMPLATE
315*00b67f09SDavid van Moolenbroek #define TEMPLATE "XXXXXXXXXX.tmp" /* 14 characters. */
316*00b67f09SDavid van Moolenbroek 
317*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_mktemplate(const char * path,char * buf,size_t buflen)318*00b67f09SDavid van Moolenbroek isc_file_mktemplate(const char *path, char *buf, size_t buflen) {
319*00b67f09SDavid van Moolenbroek 	return (isc_file_template(path, TEMPLATE, buf, buflen));
320*00b67f09SDavid van Moolenbroek }
321*00b67f09SDavid van Moolenbroek 
322*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_template(const char * path,const char * templet,char * buf,size_t buflen)323*00b67f09SDavid van Moolenbroek isc_file_template(const char *path, const char *templet, char *buf,
324*00b67f09SDavid van Moolenbroek 			size_t buflen) {
325*00b67f09SDavid van Moolenbroek 	char *s;
326*00b67f09SDavid van Moolenbroek 
327*00b67f09SDavid van Moolenbroek 	REQUIRE(path != NULL);
328*00b67f09SDavid van Moolenbroek 	REQUIRE(templet != NULL);
329*00b67f09SDavid van Moolenbroek 	REQUIRE(buf != NULL);
330*00b67f09SDavid van Moolenbroek 
331*00b67f09SDavid van Moolenbroek 	s = strrchr(templet, '\\');
332*00b67f09SDavid van Moolenbroek 	if (s != NULL)
333*00b67f09SDavid van Moolenbroek 		templet = s + 1;
334*00b67f09SDavid van Moolenbroek 
335*00b67f09SDavid van Moolenbroek 	s = strrchr(path, '\\');
336*00b67f09SDavid van Moolenbroek 
337*00b67f09SDavid van Moolenbroek 	if (s != NULL) {
338*00b67f09SDavid van Moolenbroek 	  if ((s - path + 1 + strlen(templet) + 1) > (ssize_t)buflen)
339*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOSPACE);
340*00b67f09SDavid van Moolenbroek 
341*00b67f09SDavid van Moolenbroek 		strncpy(buf, path, s - path + 1);
342*00b67f09SDavid van Moolenbroek 		buf[s - path + 1] = '\0';
343*00b67f09SDavid van Moolenbroek 		strcat(buf, templet);
344*00b67f09SDavid van Moolenbroek 	} else {
345*00b67f09SDavid van Moolenbroek 		if ((strlen(templet) + 1) > buflen)
346*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOSPACE);
347*00b67f09SDavid van Moolenbroek 
348*00b67f09SDavid van Moolenbroek 		strcpy(buf, templet);
349*00b67f09SDavid van Moolenbroek 	}
350*00b67f09SDavid van Moolenbroek 
351*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
352*00b67f09SDavid van Moolenbroek }
353*00b67f09SDavid van Moolenbroek 
354*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_renameunique(const char * file,char * templet)355*00b67f09SDavid van Moolenbroek isc_file_renameunique(const char *file, char *templet) {
356*00b67f09SDavid van Moolenbroek 	int fd;
357*00b67f09SDavid van Moolenbroek 	int res = 0;
358*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
359*00b67f09SDavid van Moolenbroek 
360*00b67f09SDavid van Moolenbroek 	REQUIRE(file != NULL);
361*00b67f09SDavid van Moolenbroek 	REQUIRE(templet != NULL);
362*00b67f09SDavid van Moolenbroek 
363*00b67f09SDavid van Moolenbroek 	fd = mkstemp(templet, ISC_TRUE);
364*00b67f09SDavid van Moolenbroek 	if (fd == -1)
365*00b67f09SDavid van Moolenbroek 		result = isc__errno2result(errno);
366*00b67f09SDavid van Moolenbroek 	else
367*00b67f09SDavid van Moolenbroek 		close(fd);
368*00b67f09SDavid van Moolenbroek 
369*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS) {
370*00b67f09SDavid van Moolenbroek 		res = isc_file_safemovefile(file, templet);
371*00b67f09SDavid van Moolenbroek 		if (res != 0) {
372*00b67f09SDavid van Moolenbroek 			result = isc__errno2result(errno);
373*00b67f09SDavid van Moolenbroek 			(void)unlink(templet);
374*00b67f09SDavid van Moolenbroek 		}
375*00b67f09SDavid van Moolenbroek 	}
376*00b67f09SDavid van Moolenbroek 	return (result);
377*00b67f09SDavid van Moolenbroek }
378*00b67f09SDavid van Moolenbroek 
379*00b67f09SDavid van Moolenbroek static isc_result_t
openuniquemode(char * templet,int mode,isc_boolean_t binary,FILE ** fp)380*00b67f09SDavid van Moolenbroek openuniquemode(char *templet, int mode, isc_boolean_t binary, FILE **fp) {
381*00b67f09SDavid van Moolenbroek 	int fd;
382*00b67f09SDavid van Moolenbroek 	FILE *f;
383*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
384*00b67f09SDavid van Moolenbroek 
385*00b67f09SDavid van Moolenbroek 	REQUIRE(templet != NULL);
386*00b67f09SDavid van Moolenbroek 	REQUIRE(fp != NULL && *fp == NULL);
387*00b67f09SDavid van Moolenbroek 
388*00b67f09SDavid van Moolenbroek 	/*
389*00b67f09SDavid van Moolenbroek 	 * Win32 does not have mkstemp. Using emulation above.
390*00b67f09SDavid van Moolenbroek 	 */
391*00b67f09SDavid van Moolenbroek 	fd = mkstemp(templet, binary);
392*00b67f09SDavid van Moolenbroek 
393*00b67f09SDavid van Moolenbroek 	if (fd == -1)
394*00b67f09SDavid van Moolenbroek 		result = isc__errno2result(errno);
395*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS) {
396*00b67f09SDavid van Moolenbroek #if 1
397*00b67f09SDavid van Moolenbroek 		UNUSED(mode);
398*00b67f09SDavid van Moolenbroek #else
399*00b67f09SDavid van Moolenbroek 		(void)fchmod(fd, mode);
400*00b67f09SDavid van Moolenbroek #endif
401*00b67f09SDavid van Moolenbroek 		f = fdopen(fd, binary ? "wb+" : "w+");
402*00b67f09SDavid van Moolenbroek 		if (f == NULL) {
403*00b67f09SDavid van Moolenbroek 			result = isc__errno2result(errno);
404*00b67f09SDavid van Moolenbroek 			(void)remove(templet);
405*00b67f09SDavid van Moolenbroek 			(void)close(fd);
406*00b67f09SDavid van Moolenbroek 		} else
407*00b67f09SDavid van Moolenbroek 			*fp = f;
408*00b67f09SDavid van Moolenbroek 	}
409*00b67f09SDavid van Moolenbroek 
410*00b67f09SDavid van Moolenbroek 	return (result);
411*00b67f09SDavid van Moolenbroek }
412*00b67f09SDavid van Moolenbroek 
413*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_openuniqueprivate(char * templet,FILE ** fp)414*00b67f09SDavid van Moolenbroek isc_file_openuniqueprivate(char *templet, FILE **fp) {
415*00b67f09SDavid van Moolenbroek 	int mode = _S_IREAD | _S_IWRITE;
416*00b67f09SDavid van Moolenbroek 	return (openuniquemode(templet, mode, ISC_FALSE, fp));
417*00b67f09SDavid van Moolenbroek }
418*00b67f09SDavid van Moolenbroek 
419*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_openunique(char * templet,FILE ** fp)420*00b67f09SDavid van Moolenbroek isc_file_openunique(char *templet, FILE **fp) {
421*00b67f09SDavid van Moolenbroek 	int mode = _S_IREAD | _S_IWRITE;
422*00b67f09SDavid van Moolenbroek 	return (openuniquemode(templet, mode, ISC_FALSE, fp));
423*00b67f09SDavid van Moolenbroek }
424*00b67f09SDavid van Moolenbroek 
425*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_openuniquemode(char * templet,int mode,FILE ** fp)426*00b67f09SDavid van Moolenbroek isc_file_openuniquemode(char *templet, int mode, FILE **fp) {
427*00b67f09SDavid van Moolenbroek 	return (openuniquemode(templet, mode, ISC_FALSE, fp));
428*00b67f09SDavid van Moolenbroek }
429*00b67f09SDavid van Moolenbroek 
430*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_bopenuniqueprivate(char * templet,FILE ** fp)431*00b67f09SDavid van Moolenbroek isc_file_bopenuniqueprivate(char *templet, FILE **fp) {
432*00b67f09SDavid van Moolenbroek 	int mode = _S_IREAD | _S_IWRITE;
433*00b67f09SDavid van Moolenbroek 	return (openuniquemode(templet, mode, ISC_TRUE, fp));
434*00b67f09SDavid van Moolenbroek }
435*00b67f09SDavid van Moolenbroek 
436*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_bopenunique(char * templet,FILE ** fp)437*00b67f09SDavid van Moolenbroek isc_file_bopenunique(char *templet, FILE **fp) {
438*00b67f09SDavid van Moolenbroek 	int mode = _S_IREAD | _S_IWRITE;
439*00b67f09SDavid van Moolenbroek 	return (openuniquemode(templet, mode, ISC_TRUE, fp));
440*00b67f09SDavid van Moolenbroek }
441*00b67f09SDavid van Moolenbroek 
442*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_bopenuniquemode(char * templet,int mode,FILE ** fp)443*00b67f09SDavid van Moolenbroek isc_file_bopenuniquemode(char *templet, int mode, FILE **fp) {
444*00b67f09SDavid van Moolenbroek 	return (openuniquemode(templet, mode, ISC_TRUE, fp));
445*00b67f09SDavid van Moolenbroek }
446*00b67f09SDavid van Moolenbroek 
447*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_remove(const char * filename)448*00b67f09SDavid van Moolenbroek isc_file_remove(const char *filename) {
449*00b67f09SDavid van Moolenbroek 	int r;
450*00b67f09SDavid van Moolenbroek 
451*00b67f09SDavid van Moolenbroek 	REQUIRE(filename != NULL);
452*00b67f09SDavid van Moolenbroek 
453*00b67f09SDavid van Moolenbroek 	r = unlink(filename);
454*00b67f09SDavid van Moolenbroek 	if (r == 0)
455*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
456*00b67f09SDavid van Moolenbroek 	else
457*00b67f09SDavid van Moolenbroek 		return (isc__errno2result(errno));
458*00b67f09SDavid van Moolenbroek }
459*00b67f09SDavid van Moolenbroek 
460*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_rename(const char * oldname,const char * newname)461*00b67f09SDavid van Moolenbroek isc_file_rename(const char *oldname, const char *newname) {
462*00b67f09SDavid van Moolenbroek 	int r;
463*00b67f09SDavid van Moolenbroek 
464*00b67f09SDavid van Moolenbroek 	REQUIRE(oldname != NULL);
465*00b67f09SDavid van Moolenbroek 	REQUIRE(newname != NULL);
466*00b67f09SDavid van Moolenbroek 
467*00b67f09SDavid van Moolenbroek 	r = isc_file_safemovefile(oldname, newname);
468*00b67f09SDavid van Moolenbroek 	if (r == 0)
469*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
470*00b67f09SDavid van Moolenbroek 	else
471*00b67f09SDavid van Moolenbroek 		return (isc__errno2result(errno));
472*00b67f09SDavid van Moolenbroek }
473*00b67f09SDavid van Moolenbroek 
474*00b67f09SDavid van Moolenbroek isc_boolean_t
isc_file_exists(const char * pathname)475*00b67f09SDavid van Moolenbroek isc_file_exists(const char *pathname) {
476*00b67f09SDavid van Moolenbroek 	struct stat stats;
477*00b67f09SDavid van Moolenbroek 
478*00b67f09SDavid van Moolenbroek 	REQUIRE(pathname != NULL);
479*00b67f09SDavid van Moolenbroek 
480*00b67f09SDavid van Moolenbroek 	return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS));
481*00b67f09SDavid van Moolenbroek }
482*00b67f09SDavid van Moolenbroek 
483*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_isplainfile(const char * filename)484*00b67f09SDavid van Moolenbroek isc_file_isplainfile(const char *filename) {
485*00b67f09SDavid van Moolenbroek 	/*
486*00b67f09SDavid van Moolenbroek 	 * This function returns success if filename is a plain file.
487*00b67f09SDavid van Moolenbroek 	 */
488*00b67f09SDavid van Moolenbroek 	struct stat filestat;
489*00b67f09SDavid van Moolenbroek 	memset(&filestat,0,sizeof(struct stat));
490*00b67f09SDavid van Moolenbroek 
491*00b67f09SDavid van Moolenbroek 	if ((stat(filename, &filestat)) == -1)
492*00b67f09SDavid van Moolenbroek 		return(isc__errno2result(errno));
493*00b67f09SDavid van Moolenbroek 
494*00b67f09SDavid van Moolenbroek 	if(! S_ISREG(filestat.st_mode))
495*00b67f09SDavid van Moolenbroek 		return(ISC_R_INVALIDFILE);
496*00b67f09SDavid van Moolenbroek 
497*00b67f09SDavid van Moolenbroek 	return(ISC_R_SUCCESS);
498*00b67f09SDavid van Moolenbroek }
499*00b67f09SDavid van Moolenbroek 
500*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_isplainfilefd(int fd)501*00b67f09SDavid van Moolenbroek isc_file_isplainfilefd(int fd) {
502*00b67f09SDavid van Moolenbroek 	/*
503*00b67f09SDavid van Moolenbroek 	 * This function returns success if filename is a plain file.
504*00b67f09SDavid van Moolenbroek 	 */
505*00b67f09SDavid van Moolenbroek 	struct stat filestat;
506*00b67f09SDavid van Moolenbroek 	memset(&filestat,0,sizeof(struct stat));
507*00b67f09SDavid van Moolenbroek 
508*00b67f09SDavid van Moolenbroek 	if ((fstat(fd, &filestat)) == -1)
509*00b67f09SDavid van Moolenbroek 		return(isc__errno2result(errno));
510*00b67f09SDavid van Moolenbroek 
511*00b67f09SDavid van Moolenbroek 	if(! S_ISREG(filestat.st_mode))
512*00b67f09SDavid van Moolenbroek 		return(ISC_R_INVALIDFILE);
513*00b67f09SDavid van Moolenbroek 
514*00b67f09SDavid van Moolenbroek 	return(ISC_R_SUCCESS);
515*00b67f09SDavid van Moolenbroek }
516*00b67f09SDavid van Moolenbroek 
517*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_isdirectory(const char * filename)518*00b67f09SDavid van Moolenbroek isc_file_isdirectory(const char *filename) {
519*00b67f09SDavid van Moolenbroek 	/*
520*00b67f09SDavid van Moolenbroek 	 * This function returns success if filename is a directory.
521*00b67f09SDavid van Moolenbroek 	 */
522*00b67f09SDavid van Moolenbroek 	struct stat filestat;
523*00b67f09SDavid van Moolenbroek 	memset(&filestat,0,sizeof(struct stat));
524*00b67f09SDavid van Moolenbroek 
525*00b67f09SDavid van Moolenbroek 	if ((stat(filename, &filestat)) == -1)
526*00b67f09SDavid van Moolenbroek 		return(isc__errno2result(errno));
527*00b67f09SDavid van Moolenbroek 
528*00b67f09SDavid van Moolenbroek 	if(! S_ISDIR(filestat.st_mode))
529*00b67f09SDavid van Moolenbroek 		return(ISC_R_INVALIDFILE);
530*00b67f09SDavid van Moolenbroek 
531*00b67f09SDavid van Moolenbroek 	return(ISC_R_SUCCESS);
532*00b67f09SDavid van Moolenbroek }
533*00b67f09SDavid van Moolenbroek 
534*00b67f09SDavid van Moolenbroek 
535*00b67f09SDavid van Moolenbroek isc_boolean_t
isc_file_isabsolute(const char * filename)536*00b67f09SDavid van Moolenbroek isc_file_isabsolute(const char *filename) {
537*00b67f09SDavid van Moolenbroek 	REQUIRE(filename != NULL);
538*00b67f09SDavid van Moolenbroek 	/*
539*00b67f09SDavid van Moolenbroek 	 * Look for c:\path\... style, c:/path/... or \\computer\shar\path...
540*00b67f09SDavid van Moolenbroek 	 * the UNC style file specs
541*00b67f09SDavid van Moolenbroek 	 */
542*00b67f09SDavid van Moolenbroek 	if ((filename[0] == '\\') && (filename[1] == '\\'))
543*00b67f09SDavid van Moolenbroek 		return (ISC_TRUE);
544*00b67f09SDavid van Moolenbroek 	if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '\\')
545*00b67f09SDavid van Moolenbroek 		return (ISC_TRUE);
546*00b67f09SDavid van Moolenbroek 	if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '/')
547*00b67f09SDavid van Moolenbroek 		return (ISC_TRUE);
548*00b67f09SDavid van Moolenbroek 	return (ISC_FALSE);
549*00b67f09SDavid van Moolenbroek }
550*00b67f09SDavid van Moolenbroek 
551*00b67f09SDavid van Moolenbroek isc_boolean_t
isc_file_iscurrentdir(const char * filename)552*00b67f09SDavid van Moolenbroek isc_file_iscurrentdir(const char *filename) {
553*00b67f09SDavid van Moolenbroek 	REQUIRE(filename != NULL);
554*00b67f09SDavid van Moolenbroek 	return (ISC_TF(filename[0] == '.' && filename[1] == '\0'));
555*00b67f09SDavid van Moolenbroek }
556*00b67f09SDavid van Moolenbroek 
557*00b67f09SDavid van Moolenbroek isc_boolean_t
isc_file_ischdiridempotent(const char * filename)558*00b67f09SDavid van Moolenbroek isc_file_ischdiridempotent(const char *filename) {
559*00b67f09SDavid van Moolenbroek 	REQUIRE(filename != NULL);
560*00b67f09SDavid van Moolenbroek 
561*00b67f09SDavid van Moolenbroek 	if (isc_file_isabsolute(filename))
562*00b67f09SDavid van Moolenbroek 		return (ISC_TRUE);
563*00b67f09SDavid van Moolenbroek 	if (filename[0] == '\\')
564*00b67f09SDavid van Moolenbroek 		return (ISC_TRUE);
565*00b67f09SDavid van Moolenbroek 	if (filename[0] == '/')
566*00b67f09SDavid van Moolenbroek 		return (ISC_TRUE);
567*00b67f09SDavid van Moolenbroek 	if (isc_file_iscurrentdir(filename))
568*00b67f09SDavid van Moolenbroek 		return (ISC_TRUE);
569*00b67f09SDavid van Moolenbroek 	return (ISC_FALSE);
570*00b67f09SDavid van Moolenbroek }
571*00b67f09SDavid van Moolenbroek 
572*00b67f09SDavid van Moolenbroek const char *
isc_file_basename(const char * filename)573*00b67f09SDavid van Moolenbroek isc_file_basename(const char *filename) {
574*00b67f09SDavid van Moolenbroek 	char *s;
575*00b67f09SDavid van Moolenbroek 
576*00b67f09SDavid van Moolenbroek 	REQUIRE(filename != NULL);
577*00b67f09SDavid van Moolenbroek 
578*00b67f09SDavid van Moolenbroek 	s = strrchr(filename, '\\');
579*00b67f09SDavid van Moolenbroek 	if (s == NULL)
580*00b67f09SDavid van Moolenbroek 		return (filename);
581*00b67f09SDavid van Moolenbroek 	return (s + 1);
582*00b67f09SDavid van Moolenbroek }
583*00b67f09SDavid van Moolenbroek 
584*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_progname(const char * filename,char * progname,size_t namelen)585*00b67f09SDavid van Moolenbroek isc_file_progname(const char *filename, char *progname, size_t namelen) {
586*00b67f09SDavid van Moolenbroek 	const char *s;
587*00b67f09SDavid van Moolenbroek 	char *p;
588*00b67f09SDavid van Moolenbroek 	size_t len;
589*00b67f09SDavid van Moolenbroek 
590*00b67f09SDavid van Moolenbroek 	REQUIRE(filename != NULL);
591*00b67f09SDavid van Moolenbroek 	REQUIRE(progname != NULL);
592*00b67f09SDavid van Moolenbroek 
593*00b67f09SDavid van Moolenbroek 	/*
594*00b67f09SDavid van Moolenbroek 	 * Strip the path from the name
595*00b67f09SDavid van Moolenbroek 	 */
596*00b67f09SDavid van Moolenbroek 	s = isc_file_basename(filename);
597*00b67f09SDavid van Moolenbroek 	if (s == NULL) {
598*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOSPACE);
599*00b67f09SDavid van Moolenbroek 	}
600*00b67f09SDavid van Moolenbroek 
601*00b67f09SDavid van Moolenbroek 	/*
602*00b67f09SDavid van Moolenbroek 	 * Strip any and all suffixes
603*00b67f09SDavid van Moolenbroek 	 */
604*00b67f09SDavid van Moolenbroek 	p = strchr(s, '.');
605*00b67f09SDavid van Moolenbroek 	if (p == NULL) {
606*00b67f09SDavid van Moolenbroek 		if (namelen <= strlen(s))
607*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOSPACE);
608*00b67f09SDavid van Moolenbroek 
609*00b67f09SDavid van Moolenbroek 		strcpy(progname, s);
610*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
611*00b67f09SDavid van Moolenbroek 	}
612*00b67f09SDavid van Moolenbroek 
613*00b67f09SDavid van Moolenbroek 	/*
614*00b67f09SDavid van Moolenbroek 	 * Copy the result to the buffer
615*00b67f09SDavid van Moolenbroek 	 */
616*00b67f09SDavid van Moolenbroek 	len = p - s;
617*00b67f09SDavid van Moolenbroek 	if (len >= namelen)
618*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOSPACE);
619*00b67f09SDavid van Moolenbroek 
620*00b67f09SDavid van Moolenbroek 	strncpy(progname, s, len);
621*00b67f09SDavid van Moolenbroek 	progname[len] = '\0';
622*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
623*00b67f09SDavid van Moolenbroek }
624*00b67f09SDavid van Moolenbroek 
625*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_absolutepath(const char * filename,char * path,size_t pathlen)626*00b67f09SDavid van Moolenbroek isc_file_absolutepath(const char *filename, char *path, size_t pathlen) {
627*00b67f09SDavid van Moolenbroek 	char *ptrname;
628*00b67f09SDavid van Moolenbroek 	DWORD retval;
629*00b67f09SDavid van Moolenbroek 
630*00b67f09SDavid van Moolenbroek 	REQUIRE(filename != NULL);
631*00b67f09SDavid van Moolenbroek 	REQUIRE(path != NULL);
632*00b67f09SDavid van Moolenbroek 
633*00b67f09SDavid van Moolenbroek 	retval = GetFullPathName(filename, (DWORD) pathlen, path, &ptrname);
634*00b67f09SDavid van Moolenbroek 
635*00b67f09SDavid van Moolenbroek 	/* Something went wrong in getting the path */
636*00b67f09SDavid van Moolenbroek 	if (retval == 0)
637*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOTFOUND);
638*00b67f09SDavid van Moolenbroek 	/* Caller needs to provide a larger buffer to contain the string */
639*00b67f09SDavid van Moolenbroek 	if (retval >= pathlen)
640*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOSPACE);
641*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
642*00b67f09SDavid van Moolenbroek }
643*00b67f09SDavid van Moolenbroek 
644*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_truncate(const char * filename,isc_offset_t size)645*00b67f09SDavid van Moolenbroek isc_file_truncate(const char *filename, isc_offset_t size) {
646*00b67f09SDavid van Moolenbroek 	int fh;
647*00b67f09SDavid van Moolenbroek 
648*00b67f09SDavid van Moolenbroek 	REQUIRE(filename != NULL && size >= 0);
649*00b67f09SDavid van Moolenbroek 
650*00b67f09SDavid van Moolenbroek 	if ((fh = open(filename, _O_RDWR | _O_BINARY)) < 0)
651*00b67f09SDavid van Moolenbroek 		return (isc__errno2result(errno));
652*00b67f09SDavid van Moolenbroek 
653*00b67f09SDavid van Moolenbroek 	if(_chsize(fh, size) != 0) {
654*00b67f09SDavid van Moolenbroek 		close(fh);
655*00b67f09SDavid van Moolenbroek 		return (isc__errno2result(errno));
656*00b67f09SDavid van Moolenbroek 	}
657*00b67f09SDavid van Moolenbroek 	close(fh);
658*00b67f09SDavid van Moolenbroek 
659*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
660*00b67f09SDavid van Moolenbroek }
661*00b67f09SDavid van Moolenbroek 
662*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_safecreate(const char * filename,FILE ** fp)663*00b67f09SDavid van Moolenbroek isc_file_safecreate(const char *filename, FILE **fp) {
664*00b67f09SDavid van Moolenbroek 	isc_result_t result;
665*00b67f09SDavid van Moolenbroek 	int flags;
666*00b67f09SDavid van Moolenbroek 	struct stat sb;
667*00b67f09SDavid van Moolenbroek 	FILE *f;
668*00b67f09SDavid van Moolenbroek 	int fd;
669*00b67f09SDavid van Moolenbroek 
670*00b67f09SDavid van Moolenbroek 	REQUIRE(filename != NULL);
671*00b67f09SDavid van Moolenbroek 	REQUIRE(fp != NULL && *fp == NULL);
672*00b67f09SDavid van Moolenbroek 
673*00b67f09SDavid van Moolenbroek 	result = file_stats(filename, &sb);
674*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS) {
675*00b67f09SDavid van Moolenbroek 		if ((sb.st_mode & S_IFREG) == 0)
676*00b67f09SDavid van Moolenbroek 			return (ISC_R_INVALIDFILE);
677*00b67f09SDavid van Moolenbroek 		flags = O_WRONLY | O_TRUNC;
678*00b67f09SDavid van Moolenbroek 	} else if (result == ISC_R_FILENOTFOUND) {
679*00b67f09SDavid van Moolenbroek 		flags = O_WRONLY | O_CREAT | O_EXCL;
680*00b67f09SDavid van Moolenbroek 	} else
681*00b67f09SDavid van Moolenbroek 		return (result);
682*00b67f09SDavid van Moolenbroek 
683*00b67f09SDavid van Moolenbroek 	fd = open(filename, flags, S_IRUSR | S_IWUSR);
684*00b67f09SDavid van Moolenbroek 	if (fd == -1)
685*00b67f09SDavid van Moolenbroek 		return (isc__errno2result(errno));
686*00b67f09SDavid van Moolenbroek 
687*00b67f09SDavid van Moolenbroek 	f = fdopen(fd, "w");
688*00b67f09SDavid van Moolenbroek 	if (f == NULL) {
689*00b67f09SDavid van Moolenbroek 		result = isc__errno2result(errno);
690*00b67f09SDavid van Moolenbroek 		close(fd);
691*00b67f09SDavid van Moolenbroek 		return (result);
692*00b67f09SDavid van Moolenbroek 	}
693*00b67f09SDavid van Moolenbroek 
694*00b67f09SDavid van Moolenbroek 	*fp = f;
695*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
696*00b67f09SDavid van Moolenbroek }
697*00b67f09SDavid van Moolenbroek 
698*00b67f09SDavid van Moolenbroek isc_result_t
isc_file_splitpath(isc_mem_t * mctx,char * path,char ** dirname,char ** basename)699*00b67f09SDavid van Moolenbroek isc_file_splitpath(isc_mem_t *mctx, char *path, char **dirname, char **basename)
700*00b67f09SDavid van Moolenbroek {
701*00b67f09SDavid van Moolenbroek 	char *dir, *file, *slash;
702*00b67f09SDavid van Moolenbroek 	char *backslash;
703*00b67f09SDavid van Moolenbroek 
704*00b67f09SDavid van Moolenbroek 	slash = strrchr(path, '/');
705*00b67f09SDavid van Moolenbroek 
706*00b67f09SDavid van Moolenbroek 	backslash = strrchr(path, '\\');
707*00b67f09SDavid van Moolenbroek 	if ((slash != NULL && backslash != NULL && backslash > slash) ||
708*00b67f09SDavid van Moolenbroek 	    (slash == NULL && backslash != NULL))
709*00b67f09SDavid van Moolenbroek 		slash = backslash;
710*00b67f09SDavid van Moolenbroek 
711*00b67f09SDavid van Moolenbroek 	if (slash == path) {
712*00b67f09SDavid van Moolenbroek 		file = ++slash;
713*00b67f09SDavid van Moolenbroek 		dir = isc_mem_strdup(mctx, "/");
714*00b67f09SDavid van Moolenbroek 	} else if (slash != NULL) {
715*00b67f09SDavid van Moolenbroek 		file = ++slash;
716*00b67f09SDavid van Moolenbroek 		dir = isc_mem_allocate(mctx, slash - path);
717*00b67f09SDavid van Moolenbroek 		if (dir != NULL)
718*00b67f09SDavid van Moolenbroek 			strlcpy(dir, path, slash - path);
719*00b67f09SDavid van Moolenbroek 	} else {
720*00b67f09SDavid van Moolenbroek 		file = path;
721*00b67f09SDavid van Moolenbroek 		dir = isc_mem_strdup(mctx, ".");
722*00b67f09SDavid van Moolenbroek 	}
723*00b67f09SDavid van Moolenbroek 
724*00b67f09SDavid van Moolenbroek 	if (dir == NULL)
725*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
726*00b67f09SDavid van Moolenbroek 
727*00b67f09SDavid van Moolenbroek 	if (*file == '\0') {
728*00b67f09SDavid van Moolenbroek 		isc_mem_free(mctx, dir);
729*00b67f09SDavid van Moolenbroek 		return (ISC_R_INVALIDFILE);
730*00b67f09SDavid van Moolenbroek 	}
731*00b67f09SDavid van Moolenbroek 
732*00b67f09SDavid van Moolenbroek 	*dirname = dir;
733*00b67f09SDavid van Moolenbroek 	*basename = file;
734*00b67f09SDavid van Moolenbroek 
735*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
736*00b67f09SDavid van Moolenbroek }
737*00b67f09SDavid van Moolenbroek 
738*00b67f09SDavid van Moolenbroek void *
isc_file_mmap(void * addr,size_t len,int prot,int flags,int fd,off_t offset)739*00b67f09SDavid van Moolenbroek isc_file_mmap(void *addr, size_t len, int prot,
740*00b67f09SDavid van Moolenbroek 	      int flags, int fd, off_t offset)
741*00b67f09SDavid van Moolenbroek {
742*00b67f09SDavid van Moolenbroek 	void *buf;
743*00b67f09SDavid van Moolenbroek 	ssize_t ret;
744*00b67f09SDavid van Moolenbroek 	off_t end;
745*00b67f09SDavid van Moolenbroek 
746*00b67f09SDavid van Moolenbroek 	UNUSED(addr);
747*00b67f09SDavid van Moolenbroek 	UNUSED(prot);
748*00b67f09SDavid van Moolenbroek 	UNUSED(flags);
749*00b67f09SDavid van Moolenbroek 
750*00b67f09SDavid van Moolenbroek 	end = lseek(fd, 0, SEEK_END);
751*00b67f09SDavid van Moolenbroek 	lseek(fd, offset, SEEK_SET);
752*00b67f09SDavid van Moolenbroek 	if (end - offset < (off_t) len)
753*00b67f09SDavid van Moolenbroek 		len = end - offset;
754*00b67f09SDavid van Moolenbroek 
755*00b67f09SDavid van Moolenbroek 	buf = malloc(len);
756*00b67f09SDavid van Moolenbroek 	ret = read(fd, buf, (unsigned int) len);
757*00b67f09SDavid van Moolenbroek 	if (ret != (ssize_t) len) {
758*00b67f09SDavid van Moolenbroek 		free(buf);
759*00b67f09SDavid van Moolenbroek 		buf = NULL;
760*00b67f09SDavid van Moolenbroek 	}
761*00b67f09SDavid van Moolenbroek 
762*00b67f09SDavid van Moolenbroek 	return (buf);
763*00b67f09SDavid van Moolenbroek }
764*00b67f09SDavid van Moolenbroek 
765*00b67f09SDavid van Moolenbroek int
isc_file_munmap(void * addr,size_t len)766*00b67f09SDavid van Moolenbroek isc_file_munmap(void *addr, size_t len) {
767*00b67f09SDavid van Moolenbroek 	UNUSED(len);
768*00b67f09SDavid van Moolenbroek 	free(addr);
769*00b67f09SDavid van Moolenbroek 	return (0);
770*00b67f09SDavid van Moolenbroek }
771