2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 File descriptors handling internals.
8 #include "__arosc_privdata.h"
18 #include <proto/exec.h>
19 #include <proto/dos.h>
20 #include <exec/memory.h>
21 #include <exec/semaphores.h>
23 #include <dos/filesystem.h>
24 #include <aros/symbolsets.h>
25 #include <aros/debug.h>
30 int __getfdslots(void)
35 fdesc
*__getfdesc(register int fd
)
37 return ((__numslots
>fd
) && (fd
>=0))?__fd_array
[fd
]:NULL
;
40 void __setfdesc(register int fd
, fdesc
*desc
)
42 /* FIXME: Check if fd is in valid range... */
43 __fd_array
[fd
] = desc
;
46 int __getfirstfd(register int startfd
)
48 /* FIXME: Check if fd is in valid range... */
51 startfd
< __numslots
&& __fd_array
[startfd
];
58 int __getfdslot(int wanted_fd
)
60 if (wanted_fd
>=__numslots
)
64 tmp
= AllocPooled(__fd_mempool
, (wanted_fd
+1)*sizeof(fdesc
*));
70 size_t size
= __numslots
*sizeof(fdesc
*);
71 CopyMem(__fd_array
, tmp
, size
);
72 FreePooled(__fd_mempool
, __fd_array
, size
);
77 bzero(__fd_array
+ __numslots
, (wanted_fd
- __numslots
+ 1) * sizeof(fdesc
*));
78 __numslots
= wanted_fd
+1;
80 else if (wanted_fd
< 0)
85 else if (__fd_array
[wanted_fd
])
93 LONG
__oflags2amode(int flags
)
97 /* filter out invalid modes */
98 switch (flags
& (O_CREAT
|O_TRUNC
|O_EXCL
))
105 if (flags
& O_WRITE
) openmode
|= FMF_WRITE
;
106 if (flags
& O_READ
) openmode
|= FMF_READ
;
107 if (flags
& O_EXEC
) openmode
|= FMF_EXECUTE
;
108 if (flags
& O_CREAT
) openmode
|= FMF_CREATE
;
109 if (flags
& O_NONBLOCK
) openmode
|= FMF_NONBLOCK
;
110 if (flags
& O_APPEND
) openmode
|= FMF_APPEND
;
115 int __open(int wanted_fd
, const char *pathname
, int flags
, int mode
)
117 BPTR fh
= BNULL
, lock
= BNULL
;
118 fdesc
*currdesc
= NULL
;
120 struct FileInfoBlock
*fib
= NULL
;
121 LONG openmode
= __oflags2amode(flags
);
123 if (__doupath
&& pathname
[0] == '\0')
125 /* On *nix "" is not really a valid file name. */
130 pathname
= __path_u2a(pathname
);
131 if (!pathname
) return -1;
133 D(bug("__open: entering, wanted fd = %d, path = %s, flags = %d, mode = %d\n", wanted_fd
, pathname
, flags
, mode
));
138 D(bug( "__open: exiting with error EINVAL\n"));
142 cblock
= AllocVec(sizeof(fcb
), MEMF_ANY
| MEMF_CLEAR
);
143 if (!cblock
) { D(bug("__open: no memory [1]\n")); goto err
; }
144 currdesc
= __alloc_fdesc();
145 if (!currdesc
) { D(bug("__open: no memory [2]\n")); goto err
; }
146 currdesc
->fdflags
= 0;
147 currdesc
->fcb
= cblock
;
149 wanted_fd
= __getfdslot(wanted_fd
);
150 if (wanted_fd
== -1) { D(bug("__open: no free fd\n")); goto err
; }
152 lock
= Lock((char *)pathname
, SHARED_LOCK
);
155 if (IoErr() == ERROR_OBJECT_WRONG_TYPE
)
158 Needed for sfs file system which reports this error number on a
159 Lock aaa/bbb/ccc with bbb being a file instead of a directory.
167 (IoErr() != ERROR_OBJECT_NOT_FOUND
) ||
168 /* If the file doesn't exist and the flag O_CREAT is not set return an error */
169 (IoErr() == ERROR_OBJECT_NOT_FOUND
&& !(flags
& O_CREAT
))
172 errno
= IoErr2errno(IoErr());
178 /* If the file exists, but O_EXCL is set, then return an error */
185 fib
= AllocDosObject(DOS_FIB
, NULL
);
188 errno
= IoErr2errno(IoErr());
192 if (!Examine(lock
, fib
))
195 The filesystem in which the file resides doesn't support
196 the EXAMINE action. It might be broken or might also not
197 be a filesystem at all. So let's assume the file is not a
200 fib
->fib_DirEntryType
= 0;
203 /* FIXME: implement softlink handling */
205 /* Check if it's a directory or a softlink.
206 Softlinks are not handled yet, though */
207 if (fib
->fib_DirEntryType
> 0)
209 /* A directory cannot be opened for writing */
210 if (openmode
& FMF_WRITE
)
217 FreeDosObject(DOS_FIB
, fib
);
218 currdesc
->fcb
->isdir
= 1;
222 FreeDosObject(DOS_FIB
, fib
);
226 /* the file exists and it's not a directory or the file doesn't exist */
234 if (openmode
& (FMF_APPEND
| FMF_WRITE
))
235 openmode
|= FMF_READ
; /* force filesystem ACTION_FINDUPDATE */
237 if (!(fh
= Open ((char *)pathname
, openmode
)) )
239 ULONG ioerr
= IoErr();
240 D(bug("[clib] Open ioerr=%d\n", ioerr
));
241 errno
= IoErr2errno(ioerr
);
245 if((flags
& O_TRUNC
) && (flags
& (O_RDWR
| O_WRONLY
)))
247 if(SetFileSize(fh
, 0, OFFSET_BEGINNING
) != 0)
249 /* Ignore error if FSA_SET_FILE_SIZE is not implemented */
250 if(IoErr() != ERROR_NOT_IMPLEMENTED
)
252 errno
= IoErr2errno(IoErr());
259 currdesc
->fcb
->fh
= fh
;
260 currdesc
->fcb
->flags
= flags
;
261 currdesc
->fcb
->opencount
= 1;
263 __setfdesc(wanted_fd
, currdesc
);
265 D(bug("__open: exiting fd=%d\n", wanted_fd
));
270 if (fib
) FreeDosObject(DOS_FIB
, fib
);
271 if (cblock
) FreeVec(cblock
);
272 if (currdesc
) __free_fdesc(currdesc
);
273 if (fh
&& fh
!= lock
) Close(fh
);
274 if (lock
) UnLock(lock
);
276 D(bug("__open: exiting with error %d\n", errno
));
281 fdesc
*__alloc_fdesc(void)
285 desc
= AllocPooled(__fd_mempool
, sizeof(fdesc
));
287 D(bug("Allocated fdesc %x from %x pool\n", desc
, __fd_mempool
));
292 void __free_fdesc(fdesc
*desc
)
294 D(bug("Freeing fdesc %x from %x pool\n", desc
, __fd_mempool
));
295 FreePooled(__fd_mempool
, desc
, sizeof(fdesc
));
299 struct __reg_fdarray
{
306 /* Some local variables for register_init_fdarray */
307 static int __fdinit
= 0;
308 static struct SignalSemaphore __fdsem
;
309 static struct MinList __fdreglist
;
311 int __init_vars(void)
313 InitSemaphore(&__fdsem
);
314 NEWLIST(&__fdreglist
);
319 int __register_init_fdarray(struct arosc_privdata
*priv
)
321 /* arosc privdata should not be used inside this function,
322 * this function is called before aroscbase is initialized
324 struct __reg_fdarray
*regnode
= AllocVec(sizeof(struct __reg_fdarray
), MEMF_ANY
|MEMF_CLEAR
);
329 regnode
->task
= FindTask(NULL
);
330 regnode
->fdarray
= priv
->acpd_fd_array
;
331 regnode
->numslots
= priv
->acpd_numslots
;
333 D(bug("Allocated regnode: %p, fdarray: %p, numslots: %d\n",
334 regnode
, regnode
->fdarray
, regnode
->numslots
337 ObtainSemaphore(&__fdsem
);
338 AddHead((struct List
*)&__fdreglist
, (struct Node
*)regnode
);
339 ReleaseSemaphore(&__fdsem
);
344 /* FIXME: perhaps this has to be handled in a different way... */
345 int __init_stdfiles(void)
348 fcb
*infcb
= NULL
, *outfcb
= NULL
, *errfcb
= NULL
;
349 fdesc
*indesc
=NULL
, *outdesc
=NULL
, *errdesc
=NULL
;
350 int res
= __getfdslot(2);
355 !(infcb
= AllocVec(sizeof(fcb
), MEMF_ANY
| MEMF_CLEAR
)) ||
356 !(indesc
= __alloc_fdesc()) ||
357 !(outfcb
= AllocVec(sizeof(fcb
), MEMF_ANY
| MEMF_CLEAR
)) ||
358 !(outdesc
= __alloc_fdesc()) ||
359 !(errfcb
= AllocVec(sizeof(fcb
), MEMF_ANY
| MEMF_CLEAR
)) ||
360 !(errdesc
= __alloc_fdesc())
366 __free_fdesc(indesc
);
370 __free_fdesc(outdesc
);
374 __free_fdesc(errdesc
);
375 SetIoErr(ERROR_NO_FREE_STORE
);
380 outdesc
->fdflags
= 0;
381 errdesc
->fdflags
= 0;
384 outdesc
->fcb
= outfcb
;
385 errdesc
->fcb
= errfcb
;
387 me
= (struct Process
*)FindTask (NULL
);
388 indesc
->fcb
->fh
= Input();
389 outdesc
->fcb
->fh
= Output();
390 errdesc
->fcb
->fh
= me
->pr_CES
? me
->pr_CES
: me
->pr_COS
;
392 indesc
->fcb
->flags
= O_RDONLY
;
393 outdesc
->fcb
->flags
= O_WRONLY
| O_APPEND
;
394 errdesc
->fcb
->flags
= O_WRONLY
| O_APPEND
;
396 indesc
->fcb
->opencount
= outdesc
->fcb
->opencount
= errdesc
->fcb
->opencount
= 1;
397 indesc
->fcb
->privflags
= outdesc
->fcb
->privflags
= errdesc
->fcb
->privflags
= _FCB_DONTCLOSE_FH
;
399 __fd_array
[STDIN_FILENO
] = indesc
;
400 __fd_array
[STDOUT_FILENO
] = outdesc
;
401 __fd_array
[STDERR_FILENO
] = errdesc
;
406 static int __copy_fdarray(fdesc
**__src_fd_array
, int numslots
)
410 for(i
= numslots
- 1; i
>= 0; i
--)
412 if(__src_fd_array
[i
])
414 if(__getfdslot(i
) != i
)
417 if((__fd_array
[i
] = __alloc_fdesc()) == NULL
)
420 __fd_array
[i
]->fdflags
= __src_fd_array
[i
]->fdflags
;
421 __fd_array
[i
]->fcb
= __src_fd_array
[i
]->fcb
;
422 __fd_array
[i
]->fcb
->opencount
++;
431 struct __reg_fdarray
*regnodeit
, *regnode
= NULL
;
432 struct Task
*self
= FindTask(NULL
);
440 __fd_mempool
= CreatePool(MEMF_PUBLIC
, 16*sizeof(fdesc
), 16*sizeof(fdesc
));
442 ObtainSemaphore(&__fdsem
);
443 ForeachNode(&__fdreglist
, regnodeit
)
445 if (regnodeit
->task
== self
)
449 D(bug("Found regnode: %p, fdarray: %p, numslots: %d\n",
450 regnode
, regnode
->fdarray
, regnode
->numslots
452 Remove((struct Node
*)regnode
);
456 ReleaseSemaphore(&__fdsem
);
459 return __init_stdfiles();
462 int ok
= __copy_fdarray(regnode
->fdarray
, regnode
->numslots
);
478 DeletePool(__fd_mempool
);
483 void __updatestdio(void)
487 me
= (struct Process
*)FindTask(NULL
);
493 __fd_array
[STDIN_FILENO
]->fcb
->fh
= Input();
494 __fd_array
[STDOUT_FILENO
]->fcb
->fh
= Output();
495 __fd_array
[STDERR_FILENO
]->fcb
->fh
= me
->pr_CES
? me
->pr_CES
: me
->pr_COS
;
497 __fd_array
[STDIN_FILENO
]->fcb
->privflags
=
498 __fd_array
[STDOUT_FILENO
]->fcb
->privflags
=
499 __fd_array
[STDERR_FILENO
]->fcb
->privflags
= _FCB_DONTCLOSE_FH
;
502 ADD2INIT(__init_fd
, 2);
503 ADD2EXIT(__exit_fd
, 2);