Annotation of embedaddon/ntp/lib/isc/unix/dir.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2004, 2005, 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.25.332.3 2009/02/16 23:47:15 tbox Exp $ */
19:
20: /*! \file
21: * \author Principal Authors: DCL */
22:
23: #include <config.h>
24:
25: #include <sys/types.h>
26: #include <sys/stat.h>
27:
28: #include <ctype.h>
29: #include <errno.h>
30: #include <unistd.h>
31:
32: #include <isc/dir.h>
33: #include <isc/magic.h>
34: #include <isc/string.h>
35: #include <isc/util.h>
36:
37: #include "errno2result.h"
38:
39: #define ISC_DIR_MAGIC ISC_MAGIC('D', 'I', 'R', '*')
40: #define VALID_DIR(dir) ISC_MAGIC_VALID(dir, ISC_DIR_MAGIC)
41:
42: void
43: isc_dir_init(isc_dir_t *dir) {
44: REQUIRE(dir != NULL);
45:
46: dir->entry.name[0] = '\0';
47: dir->entry.length = 0;
48:
49: dir->handle = NULL;
50:
51: dir->magic = ISC_DIR_MAGIC;
52: }
53:
54: /*!
55: * \brief Allocate workspace and open directory stream. If either one fails,
56: * NULL will be returned.
57: */
58: isc_result_t
59: isc_dir_open(isc_dir_t *dir, const char *dirname) {
60: char *p;
61: isc_result_t result = ISC_R_SUCCESS;
62:
63: REQUIRE(VALID_DIR(dir));
64: REQUIRE(dirname != NULL);
65:
66: /*
67: * Copy directory name. Need to have enough space for the name,
68: * a possible path separator, the wildcard, and the final NUL.
69: */
70: if (strlen(dirname) + 3 > sizeof(dir->dirname))
71: /* XXXDCL ? */
72: return (ISC_R_NOSPACE);
73: strcpy(dir->dirname, dirname);
74:
75: /*
76: * Append path separator, if needed, and "*".
77: */
78: p = dir->dirname + strlen(dir->dirname);
79: if (dir->dirname < p && *(p - 1) != '/')
80: *p++ = '/';
81: *p++ = '*';
82: *p++ = '\0';
83:
84: /*
85: * Open stream.
86: */
87: dir->handle = opendir(dirname);
88:
89: if (dir->handle == NULL)
90: return isc__errno2result(errno);
91:
92: return (result);
93: }
94:
95: /*!
96: * \brief Return previously retrieved file or get next one.
97:
98: * Unix's dirent has
99: * separate open and read functions, but the Win32 and DOS interfaces open
100: * the dir stream and reads the first file in one operation.
101: */
102: isc_result_t
103: isc_dir_read(isc_dir_t *dir) {
104: struct dirent *entry;
105:
106: REQUIRE(VALID_DIR(dir) && dir->handle != NULL);
107:
108: /*
109: * Fetch next file in directory.
110: */
111: entry = readdir(dir->handle);
112:
113: if (entry == NULL)
114: return (ISC_R_NOMORE);
115:
116: /*
117: * Make sure that the space for the name is long enough.
118: */
119: if (sizeof(dir->entry.name) <= strlen(entry->d_name))
120: return (ISC_R_UNEXPECTED);
121:
122: strcpy(dir->entry.name, entry->d_name);
123:
124: /*
125: * Some dirents have d_namlen, but it is not portable.
126: */
127: dir->entry.length = strlen(entry->d_name);
128:
129: return (ISC_R_SUCCESS);
130: }
131:
132: /*!
133: * \brief Close directory stream.
134: */
135: void
136: isc_dir_close(isc_dir_t *dir) {
137: REQUIRE(VALID_DIR(dir) && dir->handle != NULL);
138:
139: (void)closedir(dir->handle);
140: dir->handle = NULL;
141: }
142:
143: /*!
144: * \brief Reposition directory stream at start.
145: */
146: isc_result_t
147: isc_dir_reset(isc_dir_t *dir) {
148: REQUIRE(VALID_DIR(dir) && dir->handle != NULL);
149:
150: rewinddir(dir->handle);
151:
152: return (ISC_R_SUCCESS);
153: }
154:
155: isc_result_t
156: isc_dir_chdir(const char *dirname) {
157: /*!
158: * \brief Change the current directory to 'dirname'.
159: */
160:
161: REQUIRE(dirname != NULL);
162:
163: if (chdir(dirname) < 0)
164: return (isc__errno2result(errno));
165:
166: return (ISC_R_SUCCESS);
167: }
168:
169: isc_result_t
170: isc_dir_chroot(const char *dirname) {
171:
172: REQUIRE(dirname != NULL);
173:
174: #ifdef HAVE_CHROOT
175: if (chroot(dirname) < 0 || chdir("/") < 0)
176: return (isc__errno2result(errno));
177:
178: return (ISC_R_SUCCESS);
179: #else
180: return (ISC_R_NOTIMPLEMENTED);
181: #endif
182: }
183:
184: isc_result_t
185: isc_dir_createunique(char *templet) {
186: isc_result_t result;
187: char *x;
188: char *p;
189: int i;
190: int pid;
191:
192: REQUIRE(templet != NULL);
193:
194: /*!
195: * \brief mkdtemp is not portable, so this emulates it.
196: */
197:
198: pid = getpid();
199:
200: /*
201: * Replace trailing Xs with the process-id, zero-filled.
202: */
203: for (x = templet + strlen(templet) - 1; *x == 'X' && x >= templet;
204: x--, pid /= 10)
205: *x = pid % 10 + '0';
206:
207: x++; /* Set x to start of ex-Xs. */
208:
209: do {
210: i = mkdir(templet, 0700);
211: if (i == 0 || errno != EEXIST)
212: break;
213:
214: /*
215: * The BSD algorithm.
216: */
217: p = x;
218: while (*p != '\0') {
219: if (isdigit(*p & 0xff))
220: *p = 'a';
221: else if (*p != 'z')
222: ++*p;
223: else {
224: /*
225: * Reset character and move to next.
226: */
227: *p++ = 'a';
228: continue;
229: }
230:
231: break;
232: }
233:
234: if (*p == '\0') {
235: /*
236: * Tried all combinations. errno should already
237: * be EEXIST, but ensure it is anyway for
238: * isc__errno2result().
239: */
240: errno = EEXIST;
241: break;
242: }
243: } while (1);
244:
245: if (i == -1)
246: result = isc__errno2result(errno);
247: else
248: result = ISC_R_SUCCESS;
249:
250: return (result);
251: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>