2 Copyright © 1995-2008, The AROS Development Team. All rights reserved.
5 Desc: Open a file with the specified mode.
8 #include <exec/memory.h>
9 #include <exec/lists.h>
10 #include <proto/exec.h>
11 #include <utility/tagitem.h>
12 #include <dos/dosextens.h>
13 #include <dos/filesystem.h>
14 #include <dos/stdio.h>
15 #include <proto/dos.h>
16 #include <proto/utility.h>
17 #include "dos_intern.h"
19 LONG
InternalOpen(CONST_STRPTR name
, LONG accessMode
,
20 struct FileHandle
*handle
, LONG soft_nesting
, struct DosLibrary
*DOSBase
);
22 #define MAX_SOFT_LINK_NESTING 16 /* Maximum level of soft links nesting */
24 /*****************************************************************************
27 #include <proto/dos.h>
32 AROS_LHA(CONST_STRPTR
, name
, D1
),
33 AROS_LHA(LONG
, accessMode
, D2
),
36 struct DosLibrary
*, DOSBase
, 5, Dos
)
39 Opens a file for read and/or write depending on the accessmode given.
42 name - NUL terminated name of the file.
43 accessMode - One of MODE_OLDFILE - open existing file
44 MODE_NEWFILE - delete old, create new file
46 MODE_READWRITE - open new one if it doesn't exist
49 Handle to the file or 0 if the file couldn't be opened.
50 IoErr() gives additional information in that case.
62 *****************************************************************************/
66 struct FileHandle
*ret
;
70 if (name
== NULL
) return NULL
;
72 /* Create filehandle */
73 ret
= (struct FileHandle
*)AllocDosObject(DOS_FILEHANDLE
,NULL
);
77 if(InternalOpen(name
, accessMode
, ret
, MAX_SOFT_LINK_NESTING
, DOSBase
))
84 FreeDosObject(DOS_FILEHANDLE
,ret
);
88 error
= ERROR_NO_FREE_STORE
;
96 /* Try to open name recursively calling itself in case it's a soft link.
97 Store result in handle. Return boolean value indicating result. */
98 LONG
InternalOpen(CONST_STRPTR name
, LONG accessMode
,
99 struct FileHandle
*handle
, LONG soft_nesting
, struct DosLibrary
*DOSBase
)
101 /* Get pointer to I/O request. Use stackspace for now. */
102 struct IOFileSys iofs
;
103 /* Get pointer to process structure */
104 struct Process
*me
= (struct Process
*)FindTask(NULL
);
111 if(soft_nesting
== 0)
113 SetIoErr(ERROR_TOO_MANY_LEVELS
);
117 /* Prepare I/O request. */
118 InitIOFS(&iofs
, FSA_OPEN_FILE
, DOSBase
);
123 iofs
.io_Union
.io_OPEN_FILE
.io_FileMode
= FMF_MODE_OLDFILE
;
124 ast
= con
= me
->pr_CIS
;
128 iofs
.io_Union
.io_OPEN_FILE
.io_FileMode
= FMF_MODE_NEWFILE
;
130 ast
= me
->pr_CES
? me
->pr_CES
: me
->pr_COS
;
134 iofs
.io_Union
.io_OPEN_FILE
.io_FileMode
= FMF_MODE_READWRITE
;
136 ast
= me
->pr_CES
? me
->pr_CES
: me
->pr_COS
;
140 /* See if the user requested append mode */
141 doappend
= accessMode
& FMF_APPEND
;
143 /* The append mode is all taken care by dos.library */
144 accessMode
&= ~FMF_APPEND
;
146 iofs
.io_Union
.io_OPEN_FILE
.io_FileMode
= accessMode
;
147 ast
= con
= me
->pr_CIS
;
151 iofs
.io_Union
.io_OPEN_FILE
.io_Protection
= 0;
153 /* check for an empty filename. this supports this form that was
154 * required pre-2.0, which didn't have OpenFromLock():
156 * old = CurrentDir(lock);
157 * fh = Open("", MODE_OLDFILE);
162 struct FileHandle
*fh
;
164 cur
= me
->pr_CurrentDir
;
166 cur
= DOSBase
->dl_SYSLock
;
171 iofs
.io_Union
.io_OPEN_FILE
.io_Filename
= (STRPTR
) "";
173 iofs
.IOFS
.io_Device
= fh
->fh_Device
;
174 iofs
.IOFS
.io_Unit
= fh
->fh_Unit
;
178 error
= me
->pr_Result2
= iofs
.io_DosError
;
180 error
= ERROR_OBJECT_NOT_FOUND
;
184 else if(!Stricmp(name
, (STRPTR
) "CONSOLE:"))
186 iofs
.IOFS
.io_Device
= ((struct FileHandle
*)BADDR(con
))->fh_Device
;
187 iofs
.IOFS
.io_Unit
= ((struct FileHandle
*)BADDR(con
))->fh_Unit
;
188 iofs
.io_Union
.io_OPEN_FILE
.io_Filename
= (STRPTR
) "";
190 error
= me
->pr_Result2
= iofs
.io_DosError
;
192 else if(!Stricmp(name
, (STRPTR
) "*"))
194 iofs
.IOFS
.io_Device
= ((struct FileHandle
*)BADDR(ast
))->fh_Device
;
195 iofs
.IOFS
.io_Unit
= ((struct FileHandle
*)BADDR(ast
))->fh_Unit
;
196 iofs
.io_Union
.io_OPEN_FILE
.io_Filename
= (STRPTR
) "";
198 error
= me
->pr_Result2
= iofs
.io_DosError
;
202 struct DevProc
*dvp
= NULL
;
204 iofs
.io_Union
.io_OPEN_FILE
.io_Filename
= StripVolume(name
);
207 if ((dvp
= GetDeviceProc(name
, dvp
)) == NULL
) {
212 error
= DoIOFS(&iofs
, dvp
, NULL
, DOSBase
);
213 } while(error
== ERROR_OBJECT_NOT_FOUND
&& accessMode
!= MODE_NEWFILE
);
215 if (error
== ERROR_NO_MORE_ENTRIES
)
216 error
= me
->pr_Result2
= ERROR_OBJECT_NOT_FOUND
;
218 if(error
== ERROR_IS_SOFT_LINK
)
220 ULONG buffer_size
= 256;
227 continue_loop
= FALSE
;
228 if(!(softname
= AllocVec(buffer_size
, MEMF_ANY
)))
230 error2
= ERROR_NO_FREE_STORE
;
234 written
= ReadLink(dvp
->dvp_Port
, dvp
->dvp_Lock
, name
, softname
, buffer_size
);
237 /* An error occured */
240 else if(written
== -2)
242 /* If there's not enough space in the buffer, increase
244 continue_loop
= TRUE
;
247 else if(written
>= 0)
251 olddir
= CurrentDir(dvp
->dvp_Lock
);
252 ret
= InternalOpen(softname
, accessMode
, handle
, soft_nesting
- 1, DOSBase
);
257 error2
= ERROR_UNKNOWN
;
261 while(continue_loop
);
269 handle
->fh_Device
= iofs
.IOFS
.io_Device
;
270 handle
->fh_Unit
= iofs
.IOFS
.io_Unit
;
273 /* See if the handler supports FSA_SEEK */
274 if (Seek(MKBADDR(handle
), 0, OFFSET_END
) != -1)
276 /* if so then set the proper flag in the FileHandle struct */
277 handle
->fh_Flags
|= FHF_APPEND
;
280 if (IsInteractive(MKBADDR(handle
)))
281 SetVBuf(MKBADDR(handle
), NULL
, BUF_LINE
, -1);
285 else if(error
== ERROR_IS_SOFT_LINK
)