1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18: #include <config.h>
19:
20:
21: #include <unistd.h>
22:
23: #include <errno.h>
24: #include <fcntl.h>
25: #include <stdarg.h>
26: #include <stdlib.h>
27: #include <string.h>
28: #include <sys/types.h>
29: #include <sys/stat.h>
30: #include <dirent.h>
31:
32: #include "canonicalize.h"
33: #include "dirfd.h"
34:
35:
36:
37:
38:
39:
40: typedef struct
41: {
42: char *name;
43: int saved_errno;
44:
45: } dir_info_t;
46: static dir_info_t *dirs;
47: static size_t dirs_allocated;
48:
49:
50: static void
51: ensure_dirs_slot (size_t fd)
52: {
53: if (fd >= dirs_allocated)
54: {
55: size_t new_allocated;
56: dir_info_t *new_dirs;
57: size_t i;
58:
59: new_allocated = 2 * dirs_allocated + 1;
60: if (new_allocated <= fd)
61: new_allocated = fd + 1;
62: new_dirs =
63: (dirs != NULL
64: ? (dir_info_t *) realloc (dirs, new_allocated * sizeof (dir_info_t))
65: : (dir_info_t *) malloc (new_allocated * sizeof (dir_info_t)));
66: if (new_dirs != NULL)
67: {
68: for (i = dirs_allocated; i < new_allocated; i++)
69: {
70: new_dirs[i].name = NULL;
71: new_dirs[i].saved_errno = ENOTDIR;
72: }
73: dirs = new_dirs;
74: dirs_allocated = new_allocated;
75: }
76: }
77: }
78:
79:
80:
81: int
82: close (int fd)
83: #undef close
84: {
85: int retval = close (fd);
86:
87: if (retval >= 0 && fd >= 0 && fd < dirs_allocated)
88: {
89: if (dirs[fd].name != NULL)
90: free (dirs[fd].name);
91: dirs[fd].name = NULL;
92: dirs[fd].saved_errno = ENOTDIR;
93: }
94: return retval;
95: }
96:
97: int
98: open (const char *filename, int flags, ...)
99: #undef open
100: {
101: mode_t mode;
102: int fd;
103: struct stat statbuf;
104:
105: mode = 0;
106: if (flags & O_CREAT)
107: {
108: va_list arg;
109: va_start (arg, flags);
110:
111:
112:
113:
114: mode = (sizeof (mode_t) < sizeof (int)
115: ? va_arg (arg, int)
116: : va_arg (arg, mode_t));
117:
118: va_end (arg);
119: }
120: fd = open (filename, flags, mode);
121: if (fd >= 0)
122: {
123: ensure_dirs_slot (fd);
124: if (fd < dirs_allocated
125: && fstat (fd, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode))
126: {
127: dirs[fd].name = canonicalize_file_name (filename);
128: if (dirs[fd].name == NULL)
129: dirs[fd].saved_errno = errno;
130: }
131: }
132: return fd;
133: }
134:
135:
136:
137:
138: int
139: closedir (DIR *dp)
140: #undef closedir
141: {
142: int fd = dirfd (dp);
143: int retval = closedir (dp);
144:
145: if (retval >= 0 && fd >= 0 && fd < dirs_allocated)
146: {
147: if (dirs[fd].name != NULL)
148: free (dirs[fd].name);
149: dirs[fd].name = NULL;
150: dirs[fd].saved_errno = ENOTDIR;
151: }
152: return retval;
153: }
154:
155: DIR *
156: opendir (const char *filename)
157: #undef opendir
158: {
159: DIR *dp;
160:
161: dp = opendir (filename);
162: if (dp != NULL)
163: {
164: int fd = dirfd (dp);
165: if (fd >= 0)
166: {
167: ensure_dirs_slot (fd);
168: if (fd < dirs_allocated)
169: {
170: dirs[fd].name = canonicalize_file_name (filename);
171: if (dirs[fd].name == NULL)
172: dirs[fd].saved_errno = errno;
173: }
174: }
175: }
176: return dp;
177: }
178:
179:
180:
181: int
182: dup (int oldfd)
183: #undef dup
184: {
185: int newfd = dup (oldfd);
186:
187: if (oldfd >= 0 && newfd >= 0)
188: {
189: ensure_dirs_slot (newfd);
190: if (newfd < dirs_allocated)
191: {
192: if (oldfd < dirs_allocated)
193: {
194: if (dirs[oldfd].name != NULL)
195: {
196: dirs[newfd].name = strdup (dirs[oldfd].name);
197: if (dirs[newfd].name == NULL)
198: dirs[newfd].saved_errno = ENOMEM;
199: }
200: else
201: {
202: dirs[newfd].name = NULL;
203: dirs[newfd].saved_errno = dirs[oldfd].saved_errno;
204: }
205: }
206: else
207: {
208: dirs[newfd].name = NULL;
209: dirs[newfd].saved_errno = ENOMEM;
210: }
211: }
212: }
213: return newfd;
214: }
215:
216: int
217: dup2 (int oldfd, int newfd)
218: #undef dup2
219: {
220: int retval = dup2 (oldfd, newfd);
221:
222: if (retval >= 0 && oldfd >= 0 && newfd >= 0 && newfd != oldfd)
223: {
224: ensure_dirs_slot (newfd);
225: if (newfd < dirs_allocated)
226: {
227: if (oldfd < dirs_allocated)
228: {
229: if (dirs[oldfd].name != NULL)
230: {
231: dirs[newfd].name = strdup (dirs[oldfd].name);
232: if (dirs[newfd].name == NULL)
233: dirs[newfd].saved_errno = ENOMEM;
234: }
235: else
236: {
237: dirs[newfd].name = NULL;
238: dirs[newfd].saved_errno = dirs[oldfd].saved_errno;
239: }
240: }
241: else
242: {
243: dirs[newfd].name = NULL;
244: dirs[newfd].saved_errno = ENOMEM;
245: }
246: }
247: }
248: return retval;
249: }
250:
251:
252:
253: int
254: fchdir (int fd)
255: {
256: if (fd >= 0)
257: {
258: if (fd < dirs_allocated)
259: {
260: if (dirs[fd].name != NULL)
261: return chdir (dirs[fd].name);
262: else
263: {
264: errno = dirs[fd].saved_errno;
265: return -1;
266: }
267: }
268: else
269: {
270: errno = ENOMEM;
271: return -1;
272: }
273: }
274: else
275: {
276: errno = EBADF;
277: return -1;
278: }
279: }