Build fix.
[AROS.git] / rom / dos / open.c
blob43624316851a827482747885f6ba44c79e028b4e
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Open a file with the specified mode.
6 Lang: english
7 */
9 #include <aros/debug.h>
10 #include <exec/memory.h>
11 #include <exec/lists.h>
12 #include <proto/exec.h>
13 #include <utility/tagitem.h>
14 #include <dos/dosextens.h>
15 #include <dos/filesystem.h>
16 #include <dos/stdio.h>
17 #include <proto/dos.h>
18 #include <proto/utility.h>
20 #include "dos_intern.h"
22 static LONG InternalOpen(CONST_STRPTR name, LONG accessMode,
23 struct FileHandle *handle, LONG soft_nesting, struct DosLibrary *DOSBase);
25 #define MAX_SOFT_LINK_NESTING 16 /* Maximum level of soft links nesting */
27 /*****************************************************************************
29 NAME */
30 #include <proto/dos.h>
32 AROS_LH2(BPTR, Open,
34 /* SYNOPSIS */
35 AROS_LHA(CONST_STRPTR, name, D1),
36 AROS_LHA(LONG, accessMode, D2),
38 /* LOCATION */
39 struct DosLibrary *, DOSBase, 5, Dos)
41 /* FUNCTION
42 Opens a file for read and/or write depending on the accessmode given.
44 INPUTS
45 name - NUL terminated name of the file.
46 accessMode - One of MODE_OLDFILE - open existing file
47 MODE_NEWFILE - delete old, create new file
48 exclusive lock
49 MODE_READWRITE - open new one if it doesn't exist
51 RESULT
52 Handle to the file or 0 if the file couldn't be opened.
53 IoErr() gives additional information in that case.
55 NOTES
57 EXAMPLE
59 BUGS
61 SEE ALSO
63 INTERNALS
65 *****************************************************************************/
67 AROS_LIBFUNC_INIT
69 struct FileHandle *ret;
70 LONG error;
72 /* Sanity check */
73 if (name == NULL) return BNULL;
75 /* Create filehandle */
76 ret = (struct FileHandle *)AllocDosObject(DOS_FILEHANDLE,NULL);
78 if(ret != NULL)
80 LONG ok = InternalOpen(name, accessMode, ret, MAX_SOFT_LINK_NESTING, DOSBase);
81 D(bug("[Open] = %d Error = %d\n", ok, IoErr()));
82 if (ok)
84 return MKBADDR(ret);
86 else
88 error = IoErr();
89 FreeDosObject(DOS_FILEHANDLE,ret);
92 else
93 error = ERROR_NO_FREE_STORE;
95 SetIoErr(error);
96 return BNULL;
98 AROS_LIBFUNC_EXIT
99 } /* Open */
101 /* Try to open name recursively calling itself in case it's a soft link.
102 Store result in handle. Return boolean value indicating result. */
103 static LONG InternalOpen(CONST_STRPTR name, LONG accessMode,
104 struct FileHandle *handle, LONG soft_nesting, struct DosLibrary *DOSBase)
106 /* Get pointer to process structure */
107 struct Process *me = (struct Process *)FindTask(NULL);
108 LONG ret = DOSFALSE;
109 LONG error = 0;
110 BPTR con, ast;
112 D(bug("[Open] Process: 0x%p \"%s\", Window: 0x%p, Name: \"%s\" FH: 0x%p\n", me, me->pr_Task.tc_Node.ln_Name, me->pr_WindowPtr, name, handle));
114 if(soft_nesting == 0)
116 SetIoErr(ERROR_TOO_MANY_LEVELS);
117 return DOSFALSE;
120 switch(accessMode)
122 case MODE_NEWFILE:
123 case MODE_READWRITE:
124 con = me->pr_COS;
125 ast = me->pr_CES ? me->pr_CES : me->pr_COS;
126 break;
128 case MODE_OLDFILE:
129 ast = con = me->pr_CIS;
130 break;
132 default:
133 if (accessMode & (FMF_CREATE|FMF_CLEAR))
135 con = me->pr_COS;
136 ast = me->pr_CES ? me->pr_CES : me->pr_COS;
138 else
139 ast = con = me->pr_CIS;
140 break;
143 if (!Stricmp(name, "CONSOLE:"))
144 error = fs_Open(handle, REF_CONSOLE, con, accessMode, name, DOSBase);
145 else if (!Stricmp(name, "*"))
146 error = fs_Open(handle, REF_CONSOLE, ast, accessMode, name, DOSBase);
147 #ifdef AROS_DOS_PACKETS
148 /* Special case for NIL:, unsupported by IOFS */
149 else if (!Stricmp(name, "NIL:"))
151 SetIoErr(0);
153 handle->fh_Type = BNULL;
154 /* NIL: is considered interactive */
155 handle->fh_Port = (struct MsgPort*)DOSTRUE;
156 return DOSTRUE;
158 #endif
159 else
161 BPTR cur = BNULL;
162 struct DevProc *dvp = NULL;
163 STRPTR filename = strchr(name, ':');
165 if (!filename)
167 /* No ':', pathname relative to current dir */
168 cur = me->pr_CurrentDir;
170 if (!cur)
171 cur = DOSBase->dl_SYSLock;
173 if (cur)
174 error = fs_Open(handle, REF_LOCK, cur, accessMode, name, DOSBase);
175 else
177 * This can be reached if we attempt to load disk-based library or
178 * device before dl_SYSLock is assigned. This can happen, for example,
179 * when attempting to mount a handler at boottime which is missing
180 * from the kickstart.
182 error = ERROR_OBJECT_NOT_FOUND;
184 else
186 filename++;
189 if ((dvp = GetDeviceProc(name, dvp)) == NULL)
191 error = IoErr();
192 break;
195 error = fs_Open(handle, REF_DEVICE, MKBADDR(dvp), accessMode, filename, DOSBase);
196 } while(error == ERROR_OBJECT_NOT_FOUND && accessMode != MODE_NEWFILE);
198 if (error == ERROR_NO_MORE_ENTRIES)
199 error = ERROR_OBJECT_NOT_FOUND;
202 if (error == ERROR_IS_SOFT_LINK)
204 STRPTR softname = ResolveSoftlink(cur, dvp, name, DOSBase);
206 if (softname)
208 /* All OK */
209 BPTR olddir = BNULL;
211 if (dvp)
213 olddir = me->pr_CurrentDir;
214 error = RootDir(dvp, DOSBase);
216 else
217 error = 0;
219 if (!error)
221 ret = InternalOpen(softname, accessMode, handle, soft_nesting - 1, DOSBase);
222 error = ret ? 0 : IoErr();
224 if (olddir)
225 UnLock(CurrentDir(olddir));
228 FreeVec(softname);
230 else
231 error = IoErr();
234 FreeDeviceProc(dvp);
237 if (!error)
239 if (IsInteractive(MKBADDR(handle)))
240 SetVBuf(MKBADDR(handle), NULL, BUF_LINE, -1);
242 return DOSTRUE;
244 else
246 SetIoErr(error);
247 return DOSFALSE;