Belarusian
[AROS.git] / rom / dos / adddosentry.c
blob3fe2db1032acbb91d8e3e5c978a9e1e2900db2f0
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: english
7 */
8 #include <dos/dosextens.h>
9 #include <proto/exec.h>
10 #include <proto/utility.h>
11 #include "dos_intern.h"
12 #include "../devs/filesys/packet/packet.h"
14 #define DEBUG 0
15 #include <aros/debug.h>
17 /*****************************************************************************
19 NAME */
20 #include <proto/dos.h>
22 AROS_LH1(LONG, AddDosEntry,
24 /* SYNOPSIS */
25 AROS_LHA(struct DosList *, dlist, D1),
27 /* LOCATION */
28 struct DosLibrary *, DOSBase, 113, Dos)
30 /* FUNCTION
31 Adds a given dos list entry to the dos list. Automatically
32 locks the list for writing. There may be not more than one device
33 or assign node of the same name. There are no restrictions on
34 volume nodes.
36 INPUTS
37 dlist - pointer to dos list entry.
39 RESULT
40 != 0 if all went well, 0 otherwise.
42 NOTES
43 Since anybody who wants to use a device or volume node in the
44 dos list has to lock the list, filesystems may be called with
45 the dos list locked. So if you want to add a dos list entry
46 out of a filesystem don't just wait on the lock but serve all
47 incoming requests until the dos list is free instead.
49 EXAMPLE
51 BUGS
53 SEE ALSO
55 INTERNALS
56 Behaviour of this function is slightly different from AmigaOS 3.x
57 and MorphOS. Instead of LDF_WRITE it locks DosList with LDF_READ
58 flag. This is done because in AROS handlers are run with DosList
59 locked with LDF_READ flag and this could cause a lockup if we use
60 LDF_WRITE here.
62 Due to nature of the DosList it is safe to read the list while
63 someone is adding a node, adding operation is atomic to other
64 readers. The only problem here would happen if more than one
65 process attempts to add a DosNode at the same time. In order to
66 avoid this race condition we make this call single-threaded
67 using an LDF_ENTRY lock in LDF_WRITE mode.
69 LDF_ENTRY is NOT touched when a handler is started up in this
70 dos.library implementation. LDF_DELETE is not used at all.
72 *****************************************************************************/
74 AROS_LIBFUNC_INIT
76 LONG success = 1;
77 struct DosList *dl, *scan;
79 if (dlist == NULL) return success;
81 D(bug("[AddDosEntry] Adding '%b' from Task '%s'\n", dlist->dol_Name,
82 FindTask(NULL)->tc_Node.ln_Name));
83 dl = LockDosList(LDF_ALL | LDF_READ);
85 /* If the passed entry has dol_Task defined, then it's a packet-based
86 * handler, and probably doesn't have valid dol_DevName, dol_Device and
87 * dol_Unit fields, which will be needed. So we search through the DOS
88 * list looking for the packet.handler entry for the same process, and
89 * fill in the values from there.
91 * This all falls down if the handler does somehow know these fields and
92 * adds different values. We can't just test for NULL, as the handler may
93 * not have cleared it. I can't think of a single good reason why a
94 * handler would do this, so I'm not worrying about it for now.
96 * It will also break if the handler has set dol_Task to something other
97 * than its original packet.handler task. In that case we won't be able to
98 * match it correctly in the DOS list, and so the three fields will remain
99 * bogus, probably causing crashes shortly after. Again, I'll worry about
100 * it if and when it happens.
102 if (dlist->dol_Task != NULL) {
103 for (scan = dl; scan != NULL; scan = BADDR(scan->dol_Next))
104 if (scan->dol_Task == dlist->dol_Task && scan->dol_Type == DLT_DEVICE) {
105 /* Do patching only if found DeviceNode belongs to packet.handler. Otherwise do not touch anything.
106 This lets filesystems with own IOFS wrappers to set up dol_Task field on their own. This can be
107 used for example to enable utilities to pass packets directly to the filesystem without the need
108 to interact with wrapper. This will be used by SFS - Pavel Fedin <sonic.amiga@gmail.com> */
109 if (!strcmp(scan->dol_Ext.dol_AROS.dol_Device->dd_Library.lib_Node.ln_Name, "packet.handler")) {
110 struct ph_handle *vol_handle;
112 dlist->dol_Ext.dol_AROS.dol_DevName = AROS_BSTR_ADDR(dlist->dol_Name);
113 dlist->dol_Ext.dol_AROS.dol_Device = scan->dol_Ext.dol_AROS.dol_Device;
115 /* A separate handle needs to be allocated for each volume,
116 * because it may need to stay around after its original
117 * DOS device has been destroyed */
118 vol_handle = AllocMem(sizeof(struct ph_handle),
119 MEMF_PUBLIC);
120 if (vol_handle != NULL)
122 CopyMem(scan->dol_Ext.dol_AROS.dol_Unit, vol_handle,
123 sizeof(struct ph_handle));
124 vol_handle->msgport = dlist->dol_Task;
125 vol_handle->volume = dlist;
126 dlist->dol_Ext.dol_AROS.dol_Unit =
127 (struct Unit *)vol_handle;
129 else
130 success = 0;
132 break;
135 /* Software ported from AmigaOS may be unaware of dol_DevName existance.
136 * In this case dol_DevName will be NULL (this assumes that it allocates
137 * the DosNode in a system-friendly manner using AllocDosObject().
139 if (!dlist->dol_Ext.dol_AROS.dol_DevName) {
140 dlist->dol_Ext.dol_AROS.dol_DevName = AROS_BSTR_ADDR(dlist->dol_Name);
141 D(bug("[AddDosEntry] Filling in dol_DevName: %s\n", dlist->dol_Ext.dol_AROS.dol_DevName));
144 LockDosList(LDF_ENTRY|LDF_WRITE);
145 if(dlist->dol_Type != DLT_VOLUME)
147 while(TRUE)
149 dl = BADDR(dl->dol_Next);
151 if(dl == NULL)
152 break;
154 if(dl->dol_Type != DLT_VOLUME &&
155 !Stricmp(dl->dol_Ext.dol_AROS.dol_DevName, dlist->dol_Ext.dol_AROS.dol_DevName))
157 D(bug("[AddDosEntry] Name clash for %08lx->dol_DevName: %s and %08lx->dol_DevName %s\n", dl, dl->dol_Ext.dol_AROS.dol_DevName, dlist, dlist->dol_Ext.dol_AROS.dol_DevName));
158 success = 0;
159 break;
164 if(success)
166 struct DosInfo *dinf = BADDR(DOSBase->dl_Root->rn_Info);
168 dlist->dol_Next = dinf->di_DevInfo;
169 dinf->di_DevInfo = MKBADDR(dlist);
172 UnLockDosList(LDF_ENTRY|LDF_WRITE);
173 UnLockDosList(LDF_ALL | LDF_READ);
175 return success;
177 AROS_LIBFUNC_EXIT
178 } /* AddDosEntry */