Added setting position while duplicating file handles with FMF_WRITE mode. It's neede...
[cake.git] / compiler / clib / __open.c
blobb480a50a9211caef46b6b206fc6b7a31ab111360
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 File descriptors handling internals.
6 */
8 #include "__arosc_privdata.h"
10 #include <string.h>
11 #include <fcntl.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <errno.h>
16 #define DEBUG 0
18 #include <proto/exec.h>
19 #include <proto/dos.h>
20 #include <exec/memory.h>
21 #include <dos/dos.h>
22 #include <dos/filesystem.h>
23 #include <aros/symbolsets.h>
24 #include <aros/debug.h>
25 #include "__errno.h"
26 #include "__open.h"
27 #include "__upath.h"
29 int c;
31 fdesc *__getfdesc(register int fd)
33 return ((__numslots>fd) && (fd>=0))?__fd_array[fd]:NULL;
36 void __setfdesc(register int fd, fdesc *desc)
38 /* FIXME: Check if fd is in valid range... */
39 __fd_array[fd] = desc;
42 int __getfirstfd(register int startfd)
44 /* FIXME: Check if fd is in valid range... */
45 for (
47 startfd < __numslots && __fd_array[startfd];
48 startfd++
51 return startfd;
54 int __getfdslot(int wanted_fd)
56 if (wanted_fd>=__numslots)
58 void *tmp;
60 tmp = malloc((wanted_fd+1)*sizeof(fdesc *));
62 if (!tmp) return -1;
64 if (__fd_array)
66 CopyMem(__fd_array, tmp, __numslots*sizeof(fdesc *));
67 free(__fd_array);
70 __fd_array = tmp;
72 bzero(__fd_array + __numslots, (wanted_fd - __numslots + 1) * sizeof(fdesc *));
73 __numslots = wanted_fd+1;
75 else if (wanted_fd < 0)
77 errno = EINVAL;
78 return -1;
80 else if (__fd_array[wanted_fd])
82 close(wanted_fd);
85 return wanted_fd;
88 LONG __oflags2amode(int flags)
90 LONG openmode = 0;
92 /* filter out invalid modes */
93 switch (flags & (O_CREAT|O_TRUNC|O_EXCL))
95 case O_EXCL:
96 case O_EXCL|O_TRUNC:
97 return -1;
100 if (flags & O_WRITE) openmode |= FMF_WRITE;
101 if (flags & O_READ) openmode |= FMF_READ;
102 if (flags & O_EXEC) openmode |= FMF_EXECUTE;
103 if (flags & O_TRUNC) openmode |= FMF_CLEAR;
104 if (flags & O_CREAT) openmode |= FMF_CREATE;
105 if (flags & O_NONBLOCK) openmode |= FMF_NONBLOCK;
106 if (flags & O_APPEND) openmode |= FMF_APPEND;
108 return openmode;
111 int __open(int wanted_fd, const char *pathname, int flags, int mode)
113 BPTR fh = NULL, lock = NULL;
114 fdesc *currdesc = NULL;
115 struct FileInfoBlock *fib = NULL;
116 LONG openmode = __oflags2amode(flags);
118 if (__doupath && pathname[0] == '\0')
120 /* On *nix "" is not really a valid file name. */
121 errno = ENOENT;
122 return -1;
125 pathname = __path_u2a(pathname);
126 if (!pathname) return -1;
128 D(bug("__open: entering, wanted fd = %d, path = %s, flags = %d, mode = %d\n", wanted_fd, pathname, flags, mode));
130 if (openmode == -1)
132 errno = EINVAL;
133 D(bug( "__open: exiting with error EINVAL\n"));
134 return -1;
137 currdesc = malloc(sizeof(fdesc));
138 if (!currdesc) { D(bug("__open: no memory [1]\n")); goto err; }
140 wanted_fd = __getfdslot(wanted_fd);
141 if (wanted_fd == -1) { D(bug("__open: no free fd\n")); goto err; }
143 lock = Lock((char *)pathname, SHARED_LOCK);
144 if (!lock)
148 (IoErr() != ERROR_OBJECT_NOT_FOUND) ||
149 /* If the file doesn't exist and the flag O_CREAT is not set return an error */
150 (IoErr() == ERROR_OBJECT_NOT_FOUND && !(flags & O_CREAT))
153 errno = IoErr2errno(IoErr());
154 goto err;
157 else
159 /* If the file exists, but O_EXCL is set, then return an error */
160 if (flags & O_EXCL)
162 errno = EEXIST;
163 goto err;
166 fib = AllocDosObject(DOS_FIB, NULL);
167 if (!fib)
169 errno = IoErr2errno(IoErr());
170 goto err;
173 if (!Examine(lock, fib))
176 The filesystem in which the files resides doesn't support
177 the EXAMINE action. It might be broken or migth also not
178 be a filesystem at all. So let's assume the file is not a
179 diretory.
181 fib->fib_DirEntryType = 0;
184 # warning implement softlink handling
186 /* Check if it's a directory or a softlink.
187 Softlinks are not handled yet, though */
188 if (fib->fib_DirEntryType > 0)
190 /* A directory cannot be opened for writing */
191 if (openmode & FMF_WRITE)
193 errno = EISDIR;
194 goto err;
197 fh = lock;
198 FreeDosObject(DOS_FIB, fib);
200 goto success;
202 FreeDosObject(DOS_FIB, fib);
203 fib = NULL;
206 /* the file exists and it's not a directory or the file doesn't exist */
208 if (lock)
210 UnLock(lock);
211 lock = NULL;
214 if (openmode & (FMF_APPEND | FMF_WRITE))
215 openmode |= FMF_READ; /* force filesystem ACTION_FINDUPDATE */
217 if (!(fh = Open ((char *)pathname, openmode)) )
219 ULONG ioerr = IoErr();
220 D(bug("[clib] Open ioerr=%d\n", ioerr));
221 errno = IoErr2errno(ioerr);
222 goto err;
225 success:
226 currdesc->fh = fh;
227 currdesc->flags = flags;
228 currdesc->opencount = 1;
230 __setfdesc(wanted_fd, currdesc);
232 D(bug("__open: exiting fd=%d\n", wanted_fd));
234 return wanted_fd;
236 err:
237 if (fib) FreeDosObject(DOS_FIB, fib);
238 if (currdesc) free(currdesc);
239 if (fh && fh != lock) Close(fh);
240 if (lock) UnLock(lock);
242 D(bug("__open: exiting with error %d\n", errno ));
244 return -1;
248 #warning perhaps this has to be handled in a different way...
249 int __init_stdfiles(void)
251 struct Process *me;
252 fdesc *indesc=NULL, *outdesc=NULL, *errdesc=NULL;
253 int res = __getfdslot(2);
257 res == -1 ||
258 !(indesc = malloc(sizeof(fdesc))) ||
259 !(outdesc = malloc(sizeof(fdesc))) ||
260 !(errdesc = malloc(sizeof(fdesc)))
263 SetIoErr(ERROR_NO_FREE_STORE);
264 return 0;
267 me = (struct Process *)FindTask (NULL);
268 indesc->fh = __stdfiles[STDIN_FILENO] = Input();
269 outdesc->fh = __stdfiles[STDOUT_FILENO] = Output();
270 errdesc->fh = __stdfiles[STDERR_FILENO] = me->pr_CES ? me->pr_CES : me->pr_COS;
272 indesc->flags = O_RDONLY;
273 outdesc->flags = O_WRONLY | O_APPEND;
274 errdesc->flags = O_WRONLY | O_APPEND;
276 indesc->opencount = outdesc->opencount = errdesc->opencount = 1;
278 __fd_array[STDIN_FILENO] = indesc;
279 __fd_array[STDOUT_FILENO] = outdesc;
280 __fd_array[STDERR_FILENO] = errdesc;
282 return 1;
285 void __exit_stdfiles(void)
287 int i = __numslots;
288 while (i)
290 if (__fd_array[--i])
291 close(i);
295 #include <stdio.h>
297 void __updatestdio(void)
299 struct Process *me;
301 me = (struct Process *)FindTask(NULL);
303 fflush(stdin);
304 fflush(stdout);
305 fflush(stderr);
307 __fd_array[STDIN_FILENO]->fh = __stdfiles[STDIN_FILENO] = Input();
308 __fd_array[STDOUT_FILENO]->fh = __stdfiles[STDOUT_FILENO] = Output();
309 __fd_array[STDERR_FILENO]->fh = __stdfiles[STDERR_FILENO] = me->pr_CES ? me->pr_CES : me->pr_COS;
312 ADD2INIT(__init_stdfiles, 2);
313 ADD2EXIT(__exit_stdfiles, 2);