1258945Sroberto/*
2280849Scy * Copyright (C) 2004-2007, 2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
3258945Sroberto * Copyright (C) 2000, 2001  Internet Software Consortium.
4258945Sroberto *
5258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any
6258945Sroberto * purpose with or without fee is hereby granted, provided that the above
7258945Sroberto * copyright notice and this permission notice appear in all copies.
8258945Sroberto *
9258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11258945Sroberto * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15258945Sroberto * PERFORMANCE OF THIS SOFTWARE.
16258945Sroberto */
17258945Sroberto
18280849Scy/* $Id$ */
19258945Sroberto
20258945Sroberto#ifndef ISC_FILE_H
21258945Sroberto#define ISC_FILE_H 1
22258945Sroberto
23258945Sroberto/*! \file isc/file.h */
24258945Sroberto
25258945Sroberto#include <stdio.h>
26258945Sroberto
27258945Sroberto#include <isc/lang.h>
28258945Sroberto#include <isc/types.h>
29258945Sroberto
30258945SrobertoISC_LANG_BEGINDECLS
31258945Sroberto
32258945Srobertoisc_result_t
33280849Scyisc_file_settime(const char *file, isc_time_t *itime);
34258945Sroberto
35258945Srobertoisc_result_t
36280849Scyisc_file_getmodtime(const char *file, isc_time_t *itime);
37258945Sroberto/*!<
38258945Sroberto * \brief Get the time of last modification of a file.
39258945Sroberto *
40258945Sroberto * Notes:
41258945Sroberto *\li	The time that is set is relative to the (OS-specific) epoch, as are
42258945Sroberto *	all isc_time_t structures.
43258945Sroberto *
44258945Sroberto * Requires:
45258945Sroberto *\li	file != NULL.
46258945Sroberto *\li	time != NULL.
47258945Sroberto *
48258945Sroberto * Ensures:
49258945Sroberto *\li	If the file could not be accessed, 'time' is unchanged.
50258945Sroberto *
51258945Sroberto * Returns:
52258945Sroberto *\li	#ISC_R_SUCCESS
53258945Sroberto *		Success.
54258945Sroberto *\li	#ISC_R_NOTFOUND
55258945Sroberto *		No such file exists.
56258945Sroberto *\li	#ISC_R_INVALIDFILE
57258945Sroberto *		The path specified was not usable by the operating system.
58258945Sroberto *\li	#ISC_R_NOPERM
59258945Sroberto *		The file's metainformation could not be retrieved because
60258945Sroberto *		permission was denied to some part of the file's path.
61258945Sroberto *\li	#ISC_R_EIO
62258945Sroberto *		Hardware error interacting with the filesystem.
63258945Sroberto *\li	#ISC_R_UNEXPECTED
64258945Sroberto *		Something totally unexpected happened.
65258945Sroberto *
66258945Sroberto */
67258945Sroberto
68258945Srobertoisc_result_t
69258945Srobertoisc_file_mktemplate(const char *path, char *buf, size_t buflen);
70258945Sroberto/*!<
71258945Sroberto * \brief Generate a template string suitable for use with isc_file_openunique().
72258945Sroberto *
73258945Sroberto * Notes:
74258945Sroberto *\li	This function is intended to make creating temporary files
75258945Sroberto *	portable between different operating systems.
76258945Sroberto *
77258945Sroberto *\li	The path is prepended to an implementation-defined string and
78258945Sroberto *	placed into buf.  The string has no path characters in it,
79258945Sroberto *	and its maximum length is 14 characters plus a NUL.  Thus
80258945Sroberto *	buflen should be at least strlen(path) + 15 characters or
81258945Sroberto *	an error will be returned.
82258945Sroberto *
83258945Sroberto * Requires:
84258945Sroberto *\li	buf != NULL.
85258945Sroberto *
86258945Sroberto * Ensures:
87258945Sroberto *\li	If result == #ISC_R_SUCCESS:
88258945Sroberto *		buf contains a string suitable for use as the template argument
89258945Sroberto *		to isc_file_openunique().
90258945Sroberto *
91258945Sroberto *\li	If result != #ISC_R_SUCCESS:
92258945Sroberto *		buf is unchanged.
93258945Sroberto *
94258945Sroberto * Returns:
95258945Sroberto *\li	#ISC_R_SUCCESS 	Success.
96258945Sroberto *\li	#ISC_R_NOSPACE	buflen indicates buf is too small for the catenation
97258945Sroberto *				of the path with the internal template string.
98258945Sroberto */
99258945Sroberto
100258945Sroberto
101258945Srobertoisc_result_t
102258945Srobertoisc_file_openunique(char *templet, FILE **fp);
103280849Scyisc_result_t
104280849Scyisc_file_openuniqueprivate(char *templet, FILE **fp);
105280849Scyisc_result_t
106280849Scyisc_file_openuniquemode(char *templet, int mode, FILE **fp);
107258945Sroberto/*!<
108258945Sroberto * \brief Create and open a file with a unique name based on 'templet'.
109258945Sroberto *
110258945Sroberto * Notes:
111258945Sroberto *\li	'template' is a reserved work in C++.  If you want to complain
112258945Sroberto *	about the spelling of 'templet', first look it up in the
113258945Sroberto *	Merriam-Webster English dictionary. (http://www.m-w.com/)
114258945Sroberto *
115258945Sroberto *\li	This function works by using the template to generate file names.
116258945Sroberto *	The template must be a writable string, as it is modified in place.
117258945Sroberto *	Trailing X characters in the file name (full file name on Unix,
118258945Sroberto *	basename on Win32 -- eg, tmp-XXXXXX vs XXXXXX.tmp, respectively)
119258945Sroberto *	are replaced with ASCII characters until a non-existent filename
120258945Sroberto *	is found.  If the template does not include pathname information,
121258945Sroberto *	the files in the working directory of the program are searched.
122258945Sroberto *
123258945Sroberto *\li	isc_file_mktemplate is a good, portable way to get a template.
124258945Sroberto *
125258945Sroberto * Requires:
126258945Sroberto *\li	'fp' is non-NULL and '*fp' is NULL.
127258945Sroberto *
128258945Sroberto *\li	'template' is non-NULL, and of a form suitable for use by
129258945Sroberto *	the system as described above.
130258945Sroberto *
131258945Sroberto * Ensures:
132258945Sroberto *\li	If result is #ISC_R_SUCCESS:
133258945Sroberto *		*fp points to an stream opening in stdio's "w+" mode.
134258945Sroberto *
135258945Sroberto *\li	If result is not #ISC_R_SUCCESS:
136258945Sroberto *		*fp is NULL.
137258945Sroberto *
138258945Sroberto *		No file is open.  Even if one was created (but unable
139258945Sroberto *		to be reopened as a stdio FILE pointer) then it has been
140258945Sroberto *		removed.
141258945Sroberto *
142258945Sroberto *\li	This function does *not* ensure that the template string has not been
143258945Sroberto *	modified, even if the operation was unsuccessful.
144258945Sroberto *
145258945Sroberto * Returns:
146258945Sroberto *\li	#ISC_R_SUCCESS
147258945Sroberto *		Success.
148258945Sroberto *\li	#ISC_R_EXISTS
149258945Sroberto *		No file with a unique name could be created based on the
150258945Sroberto *		template.
151258945Sroberto *\li	#ISC_R_INVALIDFILE
152258945Sroberto *		The path specified was not usable by the operating system.
153258945Sroberto *\li	#ISC_R_NOPERM
154258945Sroberto *		The file could not be created because permission was denied
155258945Sroberto *		to some part of the file's path.
156258945Sroberto *\li	#ISC_R_IOERROR
157258945Sroberto *		Hardware error interacting with the filesystem.
158258945Sroberto *\li	#ISC_R_UNEXPECTED
159258945Sroberto *		Something totally unexpected happened.
160258945Sroberto */
161258945Sroberto
162258945Srobertoisc_result_t
163258945Srobertoisc_file_remove(const char *filename);
164258945Sroberto/*!<
165258945Sroberto * \brief Remove the file named by 'filename'.
166258945Sroberto */
167258945Sroberto
168258945Srobertoisc_result_t
169258945Srobertoisc_file_rename(const char *oldname, const char *newname);
170258945Sroberto/*!<
171258945Sroberto * \brief Rename the file 'oldname' to 'newname'.
172258945Sroberto */
173258945Sroberto
174258945Srobertoisc_boolean_t
175258945Srobertoisc_file_exists(const char *pathname);
176258945Sroberto/*!<
177258945Sroberto * \brief Return #ISC_TRUE if the calling process can tell that the given file exists.
178258945Sroberto * Will not return true if the calling process has insufficient privileges
179258945Sroberto * to search the entire path.
180258945Sroberto */
181258945Sroberto
182258945Srobertoisc_boolean_t
183258945Srobertoisc_file_isabsolute(const char *filename);
184258945Sroberto/*!<
185258945Sroberto * \brief Return #ISC_TRUE if the given file name is absolute.
186258945Sroberto */
187258945Sroberto
188280849Scyisc_result_t
189280849Scyisc_file_isplainfile(const char *name);
190280849Scy/*!<
191280849Scy * \brief Check that the file is a plain file
192280849Scy *
193280849Scy * Returns:
194280849Scy *\li	#ISC_R_SUCCESS
195280849Scy *		Success. The file is a plain file.
196280849Scy *\li	#ISC_R_INVALIDFILE
197280849Scy *		The path specified was not usable by the operating system.
198280849Scy *\li	#ISC_R_FILENOTFOUND
199280849Scy *		The file does not exist. This return code comes from
200280849Scy *		errno=ENOENT when stat returns -1. This code is mentioned
201280849Scy *		here, because in logconf.c, it is the one rcode that is
202280849Scy *		permitted in addition to ISC_R_SUCCESS. This is done since
203280849Scy *		the next call in logconf.c is to isc_stdio_open(), which
204280849Scy *		will create the file if it can.
205280849Scy *\li	#other ISC_R_* errors translated from errno
206280849Scy *		These occur when stat returns -1 and an errno.
207280849Scy */
208280849Scy
209258945Srobertoisc_boolean_t
210258945Srobertoisc_file_iscurrentdir(const char *filename);
211258945Sroberto/*!<
212258945Sroberto * \brief Return #ISC_TRUE if the given file name is the current directory (".").
213258945Sroberto */
214258945Sroberto
215258945Srobertoisc_boolean_t
216258945Srobertoisc_file_ischdiridempotent(const char *filename);
217258945Sroberto/*%<
218258945Sroberto * Return #ISC_TRUE if calling chdir(filename) multiple times will give
219258945Sroberto * the same result as calling it once.
220258945Sroberto */
221258945Sroberto
222258945Srobertoconst char *
223258945Srobertoisc_file_basename(const char *filename);
224258945Sroberto/*%<
225258945Sroberto * Return the final component of the path in the file name.
226258945Sroberto */
227258945Sroberto
228258945Srobertoisc_result_t
229258945Srobertoisc_file_progname(const char *filename, char *buf, size_t buflen);
230258945Sroberto/*!<
231258945Sroberto * \brief Given an operating system specific file name "filename"
232258945Sroberto * referring to a program, return the canonical program name.
233258945Sroberto *
234258945Sroberto *
235258945Sroberto * Any directory prefix or executable file name extension (if
236258945Sroberto * used on the OS in case) is stripped.  On systems where program
237258945Sroberto * names are case insensitive, the name is canonicalized to all
238258945Sroberto * lower case.  The name is written to 'buf', an array of 'buflen'
239258945Sroberto * chars, and null terminated.
240258945Sroberto *
241258945Sroberto * Returns:
242258945Sroberto *\li	#ISC_R_SUCCESS
243258945Sroberto *\li	#ISC_R_NOSPACE 	The name did not fit in 'buf'.
244258945Sroberto */
245258945Sroberto
246258945Srobertoisc_result_t
247258945Srobertoisc_file_template(const char *path, const char *templet, char *buf,
248258945Sroberto		  size_t buflen);
249258945Sroberto/*%<
250258945Sroberto * Create an OS specific template using 'path' to define the directory
251258945Sroberto * 'templet' to describe the filename and store the result in 'buf'
252258945Sroberto * such that path can be renamed to buf atomically.
253258945Sroberto */
254258945Sroberto
255258945Srobertoisc_result_t
256258945Srobertoisc_file_renameunique(const char *file, char *templet);
257258945Sroberto/*%<
258258945Sroberto * Rename 'file' using 'templet' as a template for the new file name.
259258945Sroberto */
260258945Sroberto
261258945Srobertoisc_result_t
262258945Srobertoisc_file_absolutepath(const char *filename, char *path, size_t pathlen);
263258945Sroberto/*%<
264258945Sroberto * Given a file name, return the fully qualified path to the file.
265258945Sroberto */
266258945Sroberto
267258945Sroberto/*
268258945Sroberto * XXX We should also have a isc_file_writeeopen() function
269258945Sroberto * for safely open a file in a publicly writable directory
270258945Sroberto * (see write_open() in BIND 8's ns_config.c).
271258945Sroberto */
272258945Sroberto
273258945Srobertoisc_result_t
274258945Srobertoisc_file_truncate(const char *filename, isc_offset_t size);
275258945Sroberto/*%<
276258945Sroberto * Truncate/extend the file specified to 'size' bytes.
277258945Sroberto */
278258945Sroberto
279280849Scyisc_result_t
280280849Scyisc_file_safecreate(const char *filename, FILE **fp);
281280849Scy/*%<
282280849Scy * Open 'filename' for writing, truncating if necessary.  Ensure that
283280849Scy * if it existed it was a normal file.  If creating the file, ensure
284280849Scy * that only the owner can read/write it.
285280849Scy */
286280849Scy
287280849Scyisc_result_t
288280849Scyisc_file_splitpath(isc_mem_t *mctx, char *path,
289280849Scy		   char **dirname, char **basename);
290280849Scy/*%<
291280849Scy * Split a path into dirname and basename.  If 'path' contains no slash
292280849Scy * (or, on windows, backslash), then '*dirname' is set to ".".
293280849Scy *
294280849Scy * Allocates memory for '*dirname', which can be freed with isc_mem_free().
295280849Scy *
296280849Scy * Returns:
297280849Scy * - ISC_R_SUCCESS on success
298280849Scy * - ISC_R_INVALIDFILE if 'path' is empty or ends with '/'
299280849Scy * - ISC_R_NOMEMORY if unable to allocate memory
300280849Scy */
301280849Scy
302258945SrobertoISC_LANG_ENDDECLS
303258945Sroberto
304258945Sroberto#endif /* ISC_FILE_H */
305