Annotation of embedaddon/ntp/lib/isc/win32/dir.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2004, 2007-2009 Internet Systems Consortium, Inc. ("ISC")
3: * Copyright (C) 1999-2001 Internet Software Consortium.
4: *
5: * Permission to use, copy, modify, and/or distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10: * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11: * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12: * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13: * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14: * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15: * PERFORMANCE OF THIS SOFTWARE.
16: */
17:
18: /* $Id: dir.c,v 1.16.22.2 2009/01/18 23:47:41 tbox Exp $ */
19:
20: /* Principal Authors: DCL */
21:
22: #include <config.h>
23:
24: #include <string.h>
25: #include <direct.h>
26: #include <process.h>
27: #include <io.h>
28:
29: #include <sys/stat.h>
30:
31: #include <isc/dir.h>
32: #include <isc/magic.h>
33: #include <isc/assertions.h>
34: #include <isc/util.h>
35:
36: #include "errno2result.h"
37:
38: #define ISC_DIR_MAGIC ISC_MAGIC('D', 'I', 'R', '*')
39: #define VALID_DIR(dir) ISC_MAGIC_VALID(dir, ISC_DIR_MAGIC)
40:
41: static isc_result_t
42: start_directory(isc_dir_t *p);
43:
44: void
45: isc_dir_init(isc_dir_t *dir) {
46: REQUIRE(dir != NULL);
47:
48: dir->dirname[0] = '\0';
49:
50: dir->entry.name[0] = '\0';
51: dir->entry.length = 0;
52: memset(&(dir->entry.find_data), 0, sizeof(dir->entry.find_data));
53:
54: dir->entry_filled = ISC_FALSE;
55: dir->search_handle = INVALID_HANDLE_VALUE;
56:
57: dir->magic = ISC_DIR_MAGIC;
58: }
59:
60: /*
61: * Allocate workspace and open directory stream. If either one fails,
62: * NULL will be returned.
63: */
64: isc_result_t
65: isc_dir_open(isc_dir_t *dir, const char *dirname) {
66: char *p;
67: isc_result_t result;
68:
69: REQUIRE(dirname != NULL);
70: REQUIRE(VALID_DIR(dir) && dir->search_handle == INVALID_HANDLE_VALUE);
71:
72: /*
73: * Copy directory name. Need to have enough space for the name,
74: * a possible path separator, the wildcard, and the final NUL.
75: */
76: if (strlen(dirname) + 3 > sizeof(dir->dirname))
77: /* XXXDCL ? */
78: return (ISC_R_NOSPACE);
79: strcpy(dir->dirname, dirname);
80:
81: /*
82: * Append path separator, if needed, and "*".
83: */
84: p = dir->dirname + strlen(dir->dirname);
85: if (dir->dirname < p && *(p - 1) != '\\' && *(p - 1) != ':')
86: *p++ = '\\';
87: *p++ = '*';
88: *p++ = '\0';
89:
90: /*
91: * Open stream.
92: */
93: result = start_directory(dir);
94:
95: return (result);
96: }
97:
98: /*
99: * Return previously retrieved file or get next one. Unix's dirent has
100: * separate open and read functions, but the Win32 and DOS interfaces open
101: * the dir stream and reads the first file in one operation.
102: */
103: isc_result_t
104: isc_dir_read(isc_dir_t *dir) {
105: REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE);
106:
107: if (dir->entry_filled)
108: /*
109: * start_directory() already filled in the first entry.
110: */
111: dir->entry_filled = ISC_FALSE;
112:
113: else {
114: /*
115: * Fetch next file in directory.
116: */
117: if (FindNextFile(dir->search_handle,
118: &dir->entry.find_data) == FALSE)
119: /*
120: * Either the last file has been processed or
121: * an error has occurred. The former is not
122: * really an error, but the latter is.
123: */
124: if (GetLastError() == ERROR_NO_MORE_FILES)
125: return (ISC_R_NOMORE);
126: else
127: return (ISC_R_UNEXPECTED);
128: }
129:
130: /*
131: * Make sure that the space for the name is long enough.
132: */
133: strcpy(dir->entry.name, dir->entry.find_data.cFileName);
134: dir->entry.length = strlen(dir->entry.name);
135:
136: return (ISC_R_SUCCESS);
137: }
138:
139: /*
140: * Close directory stream.
141: */
142: void
143: isc_dir_close(isc_dir_t *dir) {
144: REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE);
145:
146: FindClose(dir->search_handle);
147: dir->search_handle = INVALID_HANDLE_VALUE;
148: }
149:
150: /*
151: * Reposition directory stream at start.
152: */
153: isc_result_t
154: isc_dir_reset(isc_dir_t *dir) {
155: isc_result_t result;
156:
157: REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE);
158: REQUIRE(dir->dirname != NULL);
159:
160: /*
161: * NT cannot reposition the seek pointer to the beginning of the
162: * the directory stream, but rather the directory needs to be
163: * closed and reopened. The latter might fail.
164: */
165:
166: isc_dir_close(dir);
167:
168: result = start_directory(dir);
169:
170: return (result);
171: }
172:
173: /*
174: * Initialize isc_dir_t structure with new directory. The function
175: * returns 0 on failure and nonzero on success.
176: *
177: * Note:
178: * - Be sure to close previous stream before opening new one
179: */
180: static isc_result_t
181: start_directory(isc_dir_t *dir)
182: {
183: REQUIRE(VALID_DIR(dir));
184: REQUIRE(dir->search_handle == INVALID_HANDLE_VALUE);
185:
186: dir->entry_filled = ISC_FALSE;
187:
188: /*
189: * Open stream and retrieve first file.
190: */
191: dir->search_handle = FindFirstFile(dir->dirname,
192: &dir->entry.find_data);
193:
194: if (dir->search_handle == INVALID_HANDLE_VALUE) {
195: /*
196: * Something went wrong but we don't know what. GetLastError()
197: * could give us more information about the error, but the
198: * MSDN documentation is frustratingly thin about what
199: * possible errors could have resulted. (Score one for
200: * the Unix manual pages.) So there is just this lame error
201: * instead of being able to differentiate ISC_R_NOTFOUND
202: * from ISC_R_UNEXPECTED.
203: */
204: return (ISC_R_FAILURE);
205: }
206:
207: /*
208: * Make sure that the space for the name is long enough.
209: */
210: INSIST(sizeof(dir->entry.name) >
211: strlen(dir->entry.find_data.cFileName));
212:
213: /*
214: * Fill in the data for the first entry of the directory.
215: */
216: strcpy(dir->entry.name, dir->entry.find_data.cFileName);
217: dir->entry.length = strlen(dir->entry.name);
218:
219: dir->entry_filled = ISC_TRUE;
220:
221: return (ISC_R_SUCCESS);
222: }
223:
224: isc_result_t
225: isc_dir_chdir(const char *dirname) {
226: /*
227: * Change the current directory to 'dirname'.
228: */
229:
230: REQUIRE(dirname != NULL);
231:
232: if (chdir(dirname) < 0)
233: return (isc__errno2result(errno));
234:
235: return (ISC_R_SUCCESS);
236: }
237:
238: isc_result_t
239: isc_dir_chroot(const char *dirname) {
240: return (ISC_R_NOTIMPLEMENTED);
241: }
242:
243: isc_result_t
244: isc_dir_createunique(char *templet) {
245: isc_result_t result;
246: char *x;
247: char *p;
248: int i;
249: int pid;
250:
251: REQUIRE(templet != NULL);
252:
253: /*
254: * mkdtemp is not portable, so this emulates it.
255: */
256:
257: pid = getpid();
258:
259: /*
260: * Replace trailing Xs with the process-id, zero-filled.
261: */
262: for (x = templet + strlen(templet) - 1; *x == 'X' && x >= templet;
263: x--, pid /= 10)
264: *x = pid % 10 + '0';
265:
266: x++; /* Set x to start of ex-Xs. */
267:
268: do {
269: i = mkdir(templet);
270: i = chmod(templet, 0700);
271:
272: if (i == 0 || errno != EEXIST)
273: break;
274:
275: /*
276: * The BSD algorithm.
277: */
278: p = x;
279: while (*p != '\0') {
280: if (isdigit(*p & 0xff))
281: *p = 'a';
282: else if (*p != 'z')
283: ++*p;
284: else {
285: /*
286: * Reset character and move to next.
287: */
288: *p++ = 'a';
289: continue;
290: }
291:
292: break;
293: }
294:
295: if (*p == '\0') {
296: /*
297: * Tried all combinations. errno should already
298: * be EEXIST, but ensure it is anyway for
299: * isc__errno2result().
300: */
301: errno = EEXIST;
302: break;
303: }
304: } while (1);
305:
306: if (i == -1)
307: result = isc__errno2result(errno);
308: else
309: result = ISC_R_SUCCESS;
310:
311: return (result);
312: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>