r27195@plastic: rob | 2007-09-07 07:49:52 +1000
[tangerine.git] / rom / dos / errorreport.c
blob683f2c9c62ba083797a8a23c347a08402580467d
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: English
7 */
9 #include "dos_intern.h"
10 #include <dos/dos.h>
11 #include <dos/dosextens.h>
12 #include <intuition/intuition.h>
13 #include <exec/ports.h>
15 #include <aros/debug.h>
17 /*****************************************************************************
19 NAME */
20 #include <proto/dos.h>
22 AROS_LH4(BOOL, ErrorReport,
24 /* SYNOPSIS */
25 AROS_LHA(LONG , code , D1),
26 AROS_LHA(LONG , type , D2),
27 AROS_LHA(ULONG , arg1 , D3),
28 AROS_LHA(struct MsgPort *, device, D4),
30 /* LOCATION */
31 struct DosLibrary *, DOSBase, 80, Dos)
33 /* FUNCTION
35 INPUTS
37 code -- The error to put up the requester for
38 type -- Type of request
40 REPORT_LOCK -- arg1 is a lock (BPTR).
41 REPORT_FH -- arg1 is a filehandle (BPTR).
42 REPORT_VOLUME -- arg1 is a volumenode (C pointer).
43 REPORT_INSERT -- arg1 is the string for the volumename
45 arg1 -- Argument according to type (see above)
46 device -- Optional handler task address (obsolete!)
48 RESULT
50 NOTES
52 Locks and filehandles are the same in AROS so there is redundancy in
53 the parameters. Furthermore, the 'device' argument is not cared about
54 as AROS don't build filesystems via handlers.
56 EXAMPLE
58 BUGS
60 SEE ALSO
62 INTERNALS
64 *****************************************************************************/
66 AROS_LIBFUNC_INIT
68 struct Process *me = (struct Process *) FindTask(NULL);
69 STRPTR format;
70 BOOL want_volume = FALSE;
71 BOOL want_device = FALSE;
72 STRPTR volname = NULL;
73 STRPTR devname = NULL;
74 struct DeviceList *dl = NULL;
75 struct Device *handler = NULL;
76 struct Unit *unit = NULL;
77 char buf[128];
78 struct DevProc *dvp;
79 struct DosList *dol;
80 APTR args[2];
81 ULONG idcmp = 0;
82 LONG err;
83 LONG res;
85 /* do nothing if errors are disabled */
86 if (me->pr_WindowPtr == (APTR) -1)
87 return DOSTRUE;
89 /* first setup the error format and work out which args we need */
90 switch (code) {
91 /* Volume FOO: is not validated */
92 case ERROR_DISK_NOT_VALIDATED:
93 format = DosGetString(STRING_DISK_NOT_VALIDATED);
94 want_volume = TRUE;
95 break;
97 /* Volume FOO: is write protected */
98 case ERROR_DISK_WRITE_PROTECTED:
99 format = DosGetString(STRING_DISK_WRITE_PROTECTED);
100 want_volume = TRUE;
101 break;
103 /* Please (insert|replace) volume FOO: in ... */
104 case ERROR_DEVICE_NOT_MOUNTED:
105 if (type == REPORT_INSERT) {
106 format = DosGetString(STRING_DEVICE_NOT_MOUNTED_INSERT);
107 want_volume = TRUE;
109 else if (type == REPORT_STREAM) {
110 format = DosGetString(STRING_DEVICE_NOT_MOUNTED_REPLACE_TARGET);
111 want_volume = want_device = TRUE;
113 else {
114 format = DosGetString(STRING_DEVICE_NOT_MOUNTED_REPLACE);
115 want_volume = TRUE;
117 idcmp = IDCMP_DISKINSERTED;
118 break;
120 /* Volume FOO: is full */
121 case ERROR_DISK_FULL:
122 format = DosGetString(STRING_DISK_FULL);
123 want_volume = TRUE;
124 break;
126 /* Not a DOS disk in ...*/
127 case ERROR_NOT_A_DOS_DISK:
128 format = DosGetString(STRING_NOT_A_DOS_DISK);
129 want_device = TRUE;
130 break;
132 /* No disk present in ...*/
133 case ERROR_NO_DISK:
134 format = DosGetString(STRING_NO_DISK);
135 want_device = TRUE;
136 break;
138 /* You MUST replace volume FOO: in ... */
139 case ABORT_BUSY:
140 format = DosGetString(STRING_ABORT_BUSY);
141 want_volume = want_device = TRUE;
142 idcmp = IDCMP_DISKINSERTED;
143 break;
145 /* Volume FOO: has a read/write error */
146 case ABORT_DISK_ERROR:
147 format = DosGetString(STRING_ABORT_DISK_ERROR);
148 want_volume = TRUE;
149 break;
151 /* do nothing with other errors */
152 default:
153 return DOSTRUE;
156 /* now we need to determine the volume name. if they gave it to use
157 * (REPORT_INSERT), we just use it. otherwise, we get it from the device
158 * list (REPORT_VOLUME). if we don't have one, we use the handler/unit
159 * pair to find it */
160 switch (type) {
161 /* a filehandle */
162 case REPORT_STREAM:
163 if (arg1 == NULL)
164 return DOSTRUE;
166 handler = ((struct FileHandle *) BADDR(arg1))->fh_Device;
167 unit = ((struct FileHandle *) BADDR(arg1))->fh_Unit;
168 break;
170 case REPORT_TASK:
171 /* XXX what is this? */
172 return DOSTRUE;
174 /* a lock */
175 case REPORT_LOCK:
176 /* if they provided a lock, just use it */
177 if (arg1 != NULL) {
178 handler = ((struct FileHandle *) BADDR(arg1))->fh_Device;
179 unit = ((struct FileHandle *) BADDR(arg1))->fh_Unit;
182 /* otherwise we use the secondary device, and we look through the
183 * doslist to determine the unit */
184 else {
185 handler = (struct Device *) device;
187 /* find the doslist entry */
188 dol = LockDosList(LDF_READ | LDF_ALL);
189 while (dol != NULL && (dol->dol_Type != DLT_VOLUME ||
190 dol->dol_Ext.dol_AROS.dol_Device != handler))
191 dol = dol->dol_Next;
193 /* found it, steal its unit */
194 if (dol != NULL)
195 unit = dol->dol_Ext.dol_AROS.dol_Unit;
197 UnLockDosList(LDF_READ | LDF_ALL);
199 /* if we didn't find it, there's not much more we can do */
200 if (dol == NULL)
201 return DOSTRUE;
204 break;
206 /* a volume, ie a DeviceList */
207 case REPORT_VOLUME:
208 if (arg1 == NULL)
209 return DOSTRUE;
211 dl = (struct DeviceList *) arg1;
212 break;
214 /* raw volume name */
215 case REPORT_INSERT:
216 if (arg1 == NULL)
217 return DOSTRUE;
219 volname = (STRPTR) arg1;
220 /* rip off any trailing stuff, if its there */
221 if (SplitName(volname, ':', buf, 0, sizeof(buf)-1) == -1)
222 volname = buf;
223 break;
225 /* do nothing with other types */
226 default:
227 return DOSTRUE;
230 /* get the name if we don't already have it */
231 if (volname == NULL) {
233 /* just use the volume pointer if we already have it */
234 if (dl != NULL)
235 volname = dl->dl_Ext.dl_AROS.dol_DevName;
237 /* otherwise we have to get it from the handler */
238 else {
239 /* XXX for packets we'd just call ACTION_CURRENT_DEVICE */
241 struct FileHandle *fh;
242 char *p;
244 /* remember the current error just in case this fails. I don't know if
245 * this is actually necessary but I'm trying to keep side-effects to a
246 * minimum */
247 err = IoErr();
249 /* make a fake lock (filehandle) */
250 if ((fh = AllocDosObject(DOS_FILEHANDLE, 0)) == NULL) {
251 SetIoErr(err);
252 return DOSTRUE;
255 fh->fh_Device = handler;
256 fh->fh_Unit = unit;
258 /* get the handler to give us the name */
259 if (NameFromLock(MKBADDR(fh), buf, 127) != DOSTRUE) {
260 FreeDosObject(fh, DOS_FILEHANDLE);
261 SetIoErr(err);
262 return DOSTRUE;
265 /* cleanup */
266 FreeDosObject(fh, DOS_FILEHANDLE);
267 SetIoErr(err);
269 /* find the volume seperator */
270 for (p = buf; *p != ':' && *p != '\0'; p++);
272 /* not there. can this happen? */
273 if (*p == '\0')
274 return DOSTRUE;
276 /* overwrite it, and we have a volume name */
277 *p = '\0';
279 volname = buf;
283 /* for the device name we need the doslist entry */
284 if (want_device) {
285 /* XXX for packets we just search the doslist for a DLT_DEVICE with
286 * the same task pointer. no need to worry about multiple units */
288 /* remember the current error in case we have to bail out */
289 err = IoErr();
291 /* get the entry for the volume */
292 if ((dvp = GetDeviceProc(volname, NULL)) == NULL) {
293 SetIoErr(err);
294 return DOSTRUE;
297 /* search the list for a device node with the same handler/port as the
298 * volume */
299 dol = LockDosList(LDF_READ | LDF_ALL);
300 while (dol != NULL && (dol->dol_Type != DLT_DEVICE ||
301 dol->dol_Ext.dol_AROS.dol_Device != (struct Device *) dvp->dvp_Port ||
302 dol->dol_Ext.dol_AROS.dol_Unit != dvp->dvp_DevNode->dol_Ext.dol_AROS.dol_Unit))
303 dol = dol->dol_Next;
305 /* found it */
306 if (dol != NULL)
307 devname = dol->dol_Ext.dol_AROS.dol_DevName;
309 /* XXX can this happen? */
310 else
311 devname = "???";
313 UnLockDosList(LDF_READ | LDF_ALL);
315 FreeDeviceProc(dvp);
318 /* have all we need, now to build the arg array */
319 if (want_volume) {
320 args[0] = volname;
321 if (want_device)
322 args[1] = devname;
324 else if (want_device)
325 args[0] = devname;
327 /* display it. idcmp is set further up to catch "disk insert" events if
328 * we're waiting for them to insert something */
330 res = DisplayError(format, idcmp, &args);
332 SetIoErr(code);
334 return res == 0 ? DOSFALSE : DOSTRUE;
336 AROS_LIBFUNC_EXIT
337 } /* ErrorReport */