Don't try to setup and use X11 shared memory if
[tangerine.git] / compiler / clib / __open.c
bloba9499ce225ea031becdb67165f01a3e0f050d0c0
1 /*
2 Copyright © 1995-2009, 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 <exec/semaphores.h>
22 #include <dos/dos.h>
23 #include <dos/filesystem.h>
24 #include <aros/symbolsets.h>
25 #include <aros/debug.h>
26 #include "__errno.h"
27 #include "__open.h"
28 #include "__upath.h"
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_CREAT) openmode |= FMF_CREATE;
104 if (flags & O_NONBLOCK) openmode |= FMF_NONBLOCK;
105 if (flags & O_APPEND) openmode |= FMF_APPEND;
107 return openmode;
110 int __open(int wanted_fd, const char *pathname, int flags, int mode)
112 BPTR fh = NULL, lock = NULL;
113 fdesc *currdesc = NULL;
114 fcb *cblock = 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 cblock = AllocVec(sizeof(fcb), MEMF_ANY | MEMF_CLEAR);
138 if (!cblock) { D(bug("__open: no memory [1]\n")); goto err; }
139 currdesc = __alloc_fdesc();
140 if (!currdesc) { D(bug("__open: no memory [2]\n")); goto err; }
141 currdesc->fdflags = 0;
142 currdesc->fcb = cblock;
144 wanted_fd = __getfdslot(wanted_fd);
145 if (wanted_fd == -1) { D(bug("__open: no free fd\n")); goto err; }
147 lock = Lock((char *)pathname, SHARED_LOCK);
148 if (!lock)
152 (IoErr() != ERROR_OBJECT_NOT_FOUND) ||
153 /* If the file doesn't exist and the flag O_CREAT is not set return an error */
154 (IoErr() == ERROR_OBJECT_NOT_FOUND && !(flags & O_CREAT))
157 errno = IoErr2errno(IoErr());
158 goto err;
161 else
163 /* If the file exists, but O_EXCL is set, then return an error */
164 if (flags & O_EXCL)
166 errno = EEXIST;
167 goto err;
170 fib = AllocDosObject(DOS_FIB, NULL);
171 if (!fib)
173 errno = IoErr2errno(IoErr());
174 goto err;
177 if (!Examine(lock, fib))
180 The filesystem in which the file resides doesn't support
181 the EXAMINE action. It might be broken or might also not
182 be a filesystem at all. So let's assume the file is not a
183 diretory.
185 fib->fib_DirEntryType = 0;
188 # warning implement softlink handling
190 /* Check if it's a directory or a softlink.
191 Softlinks are not handled yet, though */
192 if (fib->fib_DirEntryType > 0)
194 /* A directory cannot be opened for writing */
195 if (openmode & FMF_WRITE)
197 errno = EISDIR;
198 goto err;
201 fh = lock;
202 FreeDosObject(DOS_FIB, fib);
203 currdesc->fcb->isdir = 1;
205 goto success;
207 FreeDosObject(DOS_FIB, fib);
208 fib = NULL;
211 /* the file exists and it's not a directory or the file doesn't exist */
213 if (lock)
215 UnLock(lock);
216 lock = NULL;
219 if (openmode & (FMF_APPEND | FMF_WRITE))
220 openmode |= FMF_READ; /* force filesystem ACTION_FINDUPDATE */
222 if (!(fh = Open ((char *)pathname, openmode)) )
224 ULONG ioerr = IoErr();
225 D(bug("[clib] Open ioerr=%d\n", ioerr));
226 errno = IoErr2errno(ioerr);
227 goto err;
230 if((flags & O_TRUNC) && (flags & (O_RDWR | O_WRONLY)))
232 if(SetFileSize(fh, 0, OFFSET_BEGINNING) != 0)
234 /* Ignore error if FSA_SET_FILE_SIZE is not implemented */
235 if(IoErr() != ERROR_NOT_IMPLEMENTED)
237 errno = IoErr2errno(IoErr());
238 goto err;
243 success:
244 currdesc->fcb->fh = fh;
245 currdesc->fcb->flags = flags;
246 currdesc->fcb->opencount = 1;
248 __setfdesc(wanted_fd, currdesc);
250 D(bug("__open: exiting fd=%d\n", wanted_fd));
252 return wanted_fd;
254 err:
255 if (fib) FreeDosObject(DOS_FIB, fib);
256 if (cblock) FreeVec(cblock);
257 if (currdesc) __free_fdesc(currdesc);
258 if (fh && fh != lock) Close(fh);
259 if (lock) UnLock(lock);
261 D(bug("__open: exiting with error %d\n", errno ));
263 return -1;
266 fdesc *__alloc_fdesc(void)
268 fdesc * fdesc;
270 fdesc = AllocPooled(__fd_mempool, sizeof(fdesc));
272 D(bug("Allocated fdesc %x from %x pool\n", fdesc, __fd_mempool));
274 return fdesc;
277 void __free_fdesc(fdesc *fdesc)
279 D(bug("Freeing fdesc %x from %x pool\n", fdesc, __fd_mempool));
280 FreePooled(__fd_mempool, fdesc, sizeof(fdesc));
284 struct __reg_fdarray {
285 struct MinNode node;
286 struct Task *task;
287 fdesc **fdarray;
288 int numslots;
291 /* Some local variables for register_init_fdarray */
292 static int __fdinit = 0;
293 static struct SignalSemaphore __fdsem;
294 static struct MinList __fdreglist;
296 int __init_vars(void)
298 InitSemaphore(&__fdsem);
299 NEWLIST(&__fdreglist);
301 return TRUE;
304 int __register_init_fdarray(fdesc **__fdarray, int numslots)
306 /* arosc privdata should not be used inside this function,
307 * this function is called before aroscbase is initialized
309 struct __reg_fdarray *regnode = AllocVec(sizeof(struct __reg_fdarray), MEMF_ANY|MEMF_CLEAR);
311 if (regnode == NULL)
312 return 0;
314 regnode->task = FindTask(NULL);
315 regnode->fdarray = __fdarray;
316 regnode->numslots = numslots;
318 D(bug("Allocated regnode: %p, fdarray: %p, numslots: %d\n",
319 regnode, regnode->fdarray, regnode->numslots
322 ObtainSemaphore(&__fdsem);
323 AddHead((struct List *)&__fdreglist, (struct Node *)regnode);
324 ReleaseSemaphore(&__fdsem);
326 return 1;
330 #warning perhaps this has to be handled in a different way...
331 int __init_stdfiles(void)
333 struct Process *me;
334 fcb *infcb = NULL, *outfcb = NULL, *errfcb = NULL;
335 fdesc *indesc=NULL, *outdesc=NULL, *errdesc=NULL;
336 int res = __getfdslot(2);
340 res == -1 ||
341 !(infcb = AllocVec(sizeof(fcb), MEMF_ANY | MEMF_CLEAR)) ||
342 !(indesc = __alloc_fdesc()) ||
343 !(outfcb = AllocVec(sizeof(fcb), MEMF_ANY | MEMF_CLEAR)) ||
344 !(outdesc = __alloc_fdesc()) ||
345 !(errfcb = AllocVec(sizeof(fcb), MEMF_ANY | MEMF_CLEAR)) ||
346 !(errdesc = __alloc_fdesc())
349 if(infcb)
350 FreeVec(infcb);
351 if(indesc)
352 __free_fdesc(indesc);
353 if(outfcb)
354 FreeVec(outfcb);
355 if(outdesc)
356 __free_fdesc(outdesc);
357 if(errfcb)
358 FreeVec(errfcb);
359 if(errdesc)
360 __free_fdesc(errdesc);
361 SetIoErr(ERROR_NO_FREE_STORE);
362 return 0;
365 indesc->fdflags = 0;
366 outdesc->fdflags = 0;
367 errdesc->fdflags = 0;
369 indesc->fcb = infcb;
370 outdesc->fcb = outfcb;
371 errdesc->fcb = errfcb;
373 me = (struct Process *)FindTask (NULL);
374 indesc->fcb->fh = Input();
375 outdesc->fcb->fh = Output();
376 errdesc->fcb->fh = me->pr_CES ? me->pr_CES : me->pr_COS;
378 indesc->fcb->flags = O_RDONLY;
379 outdesc->fcb->flags = O_WRONLY | O_APPEND;
380 errdesc->fcb->flags = O_WRONLY | O_APPEND;
382 indesc->fcb->opencount = outdesc->fcb->opencount = errdesc->fcb->opencount = 1;
383 indesc->fcb->privflags = outdesc->fcb->privflags = errdesc->fcb->privflags = _FCB_DONTCLOSE_FH;
385 __fd_array[STDIN_FILENO] = indesc;
386 __fd_array[STDOUT_FILENO] = outdesc;
387 __fd_array[STDERR_FILENO] = errdesc;
389 return 1;
392 static int __copy_fdarray(fdesc **__src_fd_array, int numslots)
394 int i;
396 for(i = numslots - 1; i >= 0; i--)
398 if(__src_fd_array[i])
400 if(__getfdslot(i) != i)
401 return 0;
403 if((__fd_array[i] = __alloc_fdesc()) == NULL)
404 return 0;
406 __fd_array[i]->fdflags = 0;
407 __fd_array[i]->fcb = __src_fd_array[i]->fcb;
408 __fd_array[i]->fcb->opencount++;
412 return 1;
415 int __init_fd(void)
417 struct __reg_fdarray *regnodeit, *regnode = NULL;
418 struct Task *self = FindTask(NULL);
420 if (!__fdinit)
422 __init_vars();
423 __fdinit = 1;
426 __fd_mempool = CreatePool(MEMF_PUBLIC, 16*sizeof(fdesc), 16*sizeof(fdesc));
428 ObtainSemaphore(&__fdsem);
429 ForeachNode(&__fdreglist, regnodeit)
431 if (regnodeit->task == self)
433 regnode = regnodeit;
435 D(bug("Found regnode: %p, fdarray: %p, numslots: %d\n",
436 regnode, regnode->fdarray, regnode->numslots
438 Remove((struct Node *)regnode);
439 break;
442 ReleaseSemaphore(&__fdsem);
444 if (regnode == NULL)
445 return __init_stdfiles();
446 else
448 int ok = __copy_fdarray(regnode->fdarray, regnode->numslots);
450 FreeVec(regnode);
452 return ok;
456 void __exit_fd(void)
458 int i = __numslots;
459 while (i)
461 if (__fd_array[--i])
462 close(i);
464 DeletePool(__fd_mempool);
467 #include <stdio.h>
469 void __updatestdio(void)
471 struct Process *me;
473 me = (struct Process *)FindTask(NULL);
475 fflush(stdin);
476 fflush(stdout);
477 fflush(stderr);
479 __fd_array[STDIN_FILENO]->fcb->fh = Input();
480 __fd_array[STDOUT_FILENO]->fcb->fh = Output();
481 __fd_array[STDERR_FILENO]->fcb->fh = me->pr_CES ? me->pr_CES : me->pr_COS;
483 __fd_array[STDIN_FILENO]->fcb->privflags =
484 __fd_array[STDOUT_FILENO]->fcb->privflags =
485 __fd_array[STDERR_FILENO]->fcb->privflags = _FCB_DONTCLOSE_FH;
488 ADD2INIT(__init_fd, 2);
489 ADD2EXIT(__exit_fd, 2);