grub2: bring back build of aros-side grub2 tools
[AROS.git] / rom / filesys / CDVDFS / src / devsupp.c
blob13c61da2c1c63be32309033c08b67a7d1a9b49f4
1 /* devsupp.c:
3 * Support routines for the device handler.
4 * - debugging
5 * - Mountlist parsing
7 * ----------------------------------------------------------------------
8 * This code is (C) Copyright 1993,1994 by Frank Munkert.
9 * (C) Copyright 2002-2011 The AROS Development Team
10 * All rights reserved.
11 * This software may be freely distributed and redistributed for
12 * non-commercial purposes, provided this notice is included.
13 * ----------------------------------------------------------------------
14 * History:
16 * 18-Dec-11 twilen - SCANINTERVAL=-1: Use media change interrupt.
17 * 11-Aug-10 sonic - Fixed for 64-bit compatibility
18 * 08-Apr-07 sonic - removed redundant "TRACKDISK" option
19 * 31-Mar-07 sonic - merged together 2 versions of Get_Startup(), changed
20 * startup mechanism under AmigaOS/MorphOS
21 * - fixed warnings
22 * - added character set translation support for Joliet
23 * 20-Jul-02 sheutlin - made 2 Versions of Get_Startup() because AROS
24 * doesn't understand startup fields (yet)
25 * - put last part of Get_Startup() into an own function
26 * (OpenCDRom()) and optimized it a little bit
27 * 12-Oct-94 fmu Get_Startup() modified.
28 * 17-May-94 fmu New option MAYBELOWERCASE (=ML).
29 * 09-Apr-94 fmu Larger buffer for startup strings.
30 * 02-Jan-94 fmu New options XPOS and YPOS.
31 * 11-Dec-93 fmu Memory type can now be chosen by the user:
32 * new options CHIP, DMA and ANY.
33 * 11-Dec-93 fmu The assembly code stubs for the debugging process
34 * are no longer necessary; the debugger code is now
35 * called with CreateNewProcTags().
36 * 21-Nov-93 fmu New option SCANINTERVAL.
37 * 14-Nov-93 fmu Added Handle_Control_Packet for 'cdcontrol' program.
38 * 10-Nov-93 fmu New options SHOWVERSION and HFSFIRST.
39 * 23-Oct-93 fmu MacHFS options added.
40 * 15-Oct-93 fmu Adapted to new VOLUME structure.
41 * 07-Jul-02 sheutlin various changes when porting to AROS
42 * - global variables are now in struct Global global
43 * - "Version" is defined somewhere else (struct Resident)
44 * - replaced memcpy by CopyMem
48 * Extract information from Mountlist "Startup" field.
51 #define USE_INLINE_STDARG
53 #include <proto/exec.h>
54 #include <proto/dos.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <stdarg.h>
58 #include <stdio.h>
60 #include <exec/resident.h>
61 #include <exec/types.h>
62 #include <dos/dostags.h>
63 #include <dos/rdargs.h>
65 #include "aros_stuff.h"
66 #include "device.h"
67 #include "devsupp.h"
68 #include "intui.h"
69 #include "params.h"
70 #include "cdcontrol.h"
71 #include "globals.h"
72 #include "debug.h"
74 int OpenCDRom(struct CDVDBase *global) {
76 global->g_cd = Open_CDROM
78 global,
79 global->g_device,
80 global->g_unit,
81 global->g_memory_type,
82 global->g_std_buffers,
83 global->g_file_buffers
85 if (global->g_cd)
87 global->g_disk_inserted =
89 Test_Unit_Ready (global->g_cd) ||
90 Test_Unit_Ready (global->g_cd)
92 return TRUE;
94 if (
95 global->g_retry_mode &&
96 global->g_cdrom_errno != CDROMERR_NO_MEMORY &&
97 global->g_cdrom_errno != CDROMERR_MSGPORT &&
98 global->g_cdrom_errno != CDROMERR_IOREQ
101 return TRUE;
103 switch (global->g_cdrom_errno)
105 case CDROMERR_NO_MEMORY:
106 Display_Error
108 "Out of memory: cannot allocate buffers\n"
109 "(Try changing BufMemType option.)"
111 break;
112 case CDROMERR_MSGPORT:
113 Display_Error ("Cannot open the message port.");
114 break;
115 case CDROMERR_IOREQ:
116 Display_Error ("Cannot open the I/O request structure.");
117 break;
118 case CDROMERR_DEVICE:
119 Display_Error
121 "Cannot open \"%s\" unit %ld",
122 (IPTR)global->g_device, global->g_unit
124 break;
125 case CDROMERR_BLOCKSIZE:
126 Display_Error ("Cannot access CDROM drive: illegal blocksize.");
127 break;
128 default:
129 break;
131 return FALSE;
134 int Get_Startup(struct CDVDBase *global,struct FileSysStartupMsg *fssm) {
135 enum {
136 ARG_RETRY,
137 ARG_LOWERCASE,
138 ARG_MAYBELOWERCASE,
139 ARG_ROCKRIDGE,
140 ARG_JOLIET,
141 ARG_MACTOISO,
142 ARG_CONVERTSPACES,
143 ARG_SHOWVERSION,
144 ARG_HFSFIRST,
145 ARG_FILEBUFFERS,
146 ARG_DATAEXT,
147 ARG_RESOURCEEXT,
148 ARG_SCANINTERVAL,
149 ARG_PLAYCDDA,
150 ARG_XPOS,
151 ARG_YPOS,
152 ARGCOUNT
155 STRPTR Args[ARGCOUNT] = {0};
156 STRPTR Index;
157 UBYTE LocalBuffer[250];
158 struct RDArgs *ArgsPtr;
159 int result = FALSE,len,i;
160 struct DosEnvec *de;
162 if (fssm != (struct FileSysStartupMsg *)-1)
164 len = AROS_BSTR_strlen(fssm->fssm_Device);
165 if (len<sizeof(global->g_device))
167 de = (struct DosEnvec *)BADDR(fssm->fssm_Environ);
168 CopyMem(AROS_BSTR_ADDR(fssm->fssm_Device), global->g_device, len);
169 global->g_device[len] = 0;
170 global->g_unit = fssm->fssm_Unit;
171 global->g_std_buffers = de->de_NumBuffers;
172 global->g_file_buffers = de->de_NumBuffers;
173 global->g_memory_type = de->de_BufMemType;
174 // global->g_memory_type = MEMF_ANY;
176 global->g_retry_mode = FALSE;
177 global->g_map_to_lowercase = FALSE;
178 global->g_maybe_map_to_lowercase = TRUE;
179 global->g_use_rock_ridge = TRUE;
180 global->g_use_joliet = TRUE;
181 global->g_show_version_numbers = FALSE;
182 global->g_hfs_first = FALSE;
183 strcpy(global->g_data_fork_extension, "dfork");
184 strcpy(global->g_resource_fork_extension, "rfork");
185 global->g_convert_hfs_filenames = FALSE;
186 global->g_convert_hfs_spaces = FALSE;
187 global->g_scan_interval = 3;
188 global->g_play_cdda_command[0] = 0;
189 global->g_xpos = NO_ICON_POSITION;
190 global->g_ypos = NO_ICON_POSITION;
192 if (de->de_Control) {
193 /* Get the contents of the control field. */
194 len = AROS_BSTR_strlen(de->de_Control);
195 if (len > sizeof (LocalBuffer) - 1)
196 len = sizeof (LocalBuffer) - 1;
197 CopyMem (AROS_BSTR_ADDR(de->de_Control), LocalBuffer, len);
199 /* Provide null-termination. */
200 LocalBuffer[len] = 0;
202 /* Remove leading quotes. */
203 for (i = 0 ; i < len ; i++) {
204 if (LocalBuffer[i] != ' ') {
205 if (LocalBuffer[i] == '\"')
206 LocalBuffer[i] = ' ';
207 break;
212 /* Remove trailing quotes. */
213 for (i = len - 1 ; i >= 0 ; i--) {
214 if (LocalBuffer[i] != ' '){
215 if (LocalBuffer[i] == '\"')
216 LocalBuffer[i] = ' ';
217 break;
221 /* Replace "+" by spaces, except "++" which is replaced by "+". */
222 Index = LocalBuffer;
223 for (i = 0 ; i < len ; i++) {
224 if (LocalBuffer[i] == '+') {
225 if (i+1 < len && LocalBuffer[i+1] == '+') {
226 *Index++ = '+';
227 i++;
228 } else
229 *Index++ = ' ';
230 } else
231 *Index++ = LocalBuffer[i];
234 /* Provide termination. */
235 *Index++ = '\n';
236 *Index = 0;
237 BUG(dbprintf("Control string: %s", LocalBuffer);)
239 ArgsPtr = (struct RDArgs *)AllocDosObject(DOS_RDARGS, NULL);
240 if (ArgsPtr)
242 /* Don't prompt for input! */
243 ArgsPtr -> RDA_Flags |= RDAF_NOPROMPT;
245 /* Set up for local parsing. */
246 ArgsPtr->RDA_Source.CS_Buffer = LocalBuffer;
247 ArgsPtr->RDA_Source.CS_Length = strlen ((char *) LocalBuffer);
248 ArgsPtr->RDA_Source.CS_CurChr = 0;
250 /* Read the arguments. */
251 if (ReadArgs ((UBYTE *)
252 "RETRY/S,L=LOWERCASE/S,ML=MAYBELOWERCASE/S,"
253 "R=ROCKRIDGE/S,J=JOLIET/S,"
254 "MI=MACTOISO/S,CS=CONVERTSPACES/S,"
255 "SV=SHOWVERSION/S,HF=HFSFIRST/S,"
256 "FB=FILEBUFFERS/K/N,"
257 "DE=DATAEXT/K,RE=RESOURCEEXT/K,"
258 "SI=SCANINTERVAL/K/N,PC=PLAYCDDA/K,"
259 "X=XPOS/K/N,Y=YPOS/K/N,",
260 (IPTR *) Args, ArgsPtr)) {
261 result = TRUE;
263 global->g_retry_mode = (Args[ARG_RETRY] != NULL);
264 global->g_map_to_lowercase = (Args[ARG_LOWERCASE] != NULL);
265 global->g_maybe_map_to_lowercase = (Args[ARG_MAYBELOWERCASE] != NULL);
267 if (global->g_map_to_lowercase && global->g_maybe_map_to_lowercase) {
268 Display_Error ("Options L and ML are mutually exclusive!");
269 result = FALSE;
272 global->g_use_rock_ridge = (Args[ARG_ROCKRIDGE] != NULL);
273 global->g_use_joliet = (Args[ARG_JOLIET] != NULL);
274 global->g_show_version_numbers = (Args[ARG_SHOWVERSION] != NULL);
275 global->g_hfs_first = (Args[ARG_HFSFIRST] != NULL);
277 if (Args[ARG_FILEBUFFERS]) {
278 global->g_file_buffers = *(long *) (Args[ARG_FILEBUFFERS]);
279 if (global->g_file_buffers <= 0) {
280 Display_Error ("Illegal number of file buffers: %ld", global->g_std_buffers);
281 result = FALSE;
285 if (Args[ARG_DATAEXT])
286 strcpy (global->g_data_fork_extension, (char *) Args[ARG_DATAEXT]);
288 if (Args[ARG_RESOURCEEXT])
289 strcpy (global->g_resource_fork_extension, (char *) Args[ARG_RESOURCEEXT]);
291 global->g_convert_hfs_filenames = (Args[ARG_MACTOISO] != NULL);
292 global->g_convert_hfs_spaces = (Args[ARG_CONVERTSPACES] != NULL);
294 if (Args[ARG_SCANINTERVAL]) {
295 global->g_scan_interval = *(long *) (Args[ARG_SCANINTERVAL]);
298 if (Args[ARG_PLAYCDDA]) {
299 len = strlen((char *) (Args[ARG_PLAYCDDA]));
301 if (len >= sizeof (global->g_play_cdda_command)) {
302 Display_Error ("PLAYCDDA command name too long");
303 result = FALSE;
304 } else
305 strcpy (global->g_play_cdda_command, (char *) (Args[ARG_PLAYCDDA]));
308 if (Args[ARG_XPOS])
309 global->g_xpos = *(LONG *) (Args[ARG_XPOS]);
310 if (Args[ARG_YPOS])
311 global->g_ypos = *(LONG *) (Args[ARG_YPOS]);
313 FreeArgs(ArgsPtr);
314 } else {
315 Fault(IoErr (), (UBYTE *) "", LocalBuffer, sizeof (LocalBuffer));
316 Display_Error ("Error while parsing \"Control\" field in Mountlist:\n%s",
317 (IPTR)LocalBuffer + 2);
320 FreeDosObject (DOS_RDARGS, ArgsPtr);
321 } else
322 Display_Error ("Out of memory");
323 } else
324 result = TRUE;
325 BUG(dbprintf(global, "Use RockRidge: %ld\n", global->g_use_rock_ridge);)
326 BUG(dbprintf(global, "Use joliet: %ld\n", global->g_use_joliet);)
327 BUG(dbprintf(global, "Force lowercase: %ld\n", global->g_map_to_lowercase);)
328 BUG(dbprintf(global, "Allow lowercase: %ld\n", global->g_maybe_map_to_lowercase);)
331 if (result)
332 return OpenCDRom(global);
333 else
334 return FALSE;
337 int Handle_Control_Packet (struct CDVDBase *global, ULONG p_type, IPTR p_par1, IPTR p_par2)
339 switch (p_type) {
340 case CDCMD_LOWERCASE:
341 global->g_map_to_lowercase = p_par1;
342 break;
343 case CDCMD_MACTOISO:
344 global->g_convert_hfs_filenames = p_par1;
345 break;
346 case CDCMD_CONVERTSPACES:
347 global->g_convert_hfs_spaces = p_par1;
348 break;
349 case CDCMD_SHOWVERSION:
350 global->g_show_version_numbers = p_par1;
351 break;
352 case CDCMD_HFSFIRST:
353 global->g_hfs_first = p_par1;
354 break;
355 case CDCMD_DATAEXT:
356 strcpy (global->g_data_fork_extension, (char *) p_par1);
357 break;
358 case CDCMD_RESOURCEEXT:
359 strcpy (global->g_resource_fork_extension, (char *) p_par1);
360 break;
361 default:
362 return 999;
364 return 0;
367 char *typetostr (int ty)
369 switch(ty) {
370 case ACTION_DIE: return("DIE");
371 case ACTION_FINDUPDATE: return("OPEN-RW");
372 case ACTION_FINDINPUT: return("OPEN-OLD");
373 case ACTION_FINDOUTPUT: return("OPEN-NEW");
374 case ACTION_READ: return("READ");
375 case ACTION_WRITE: return("WRITE");
376 case ACTION_END: return("CLOSE");
377 case ACTION_SEEK: return("SEEK");
378 case ACTION_EXAMINE_NEXT: return("EXAMINE NEXT");
379 case ACTION_EXAMINE_OBJECT: return("EXAMINE OBJ");
380 case ACTION_INFO: return("INFO");
381 case ACTION_DISK_INFO: return("DISK INFO");
382 case ACTION_PARENT: return("PARENTDIR");
383 case ACTION_DELETE_OBJECT: return("DELETE");
384 case ACTION_CREATE_DIR: return("CREATEDIR");
385 case ACTION_LOCATE_OBJECT: return("LOCK");
386 case ACTION_COPY_DIR: return("DUPLOCK");
387 case ACTION_FREE_LOCK: return("FREELOCK");
388 case ACTION_SET_PROTECT: return("SETPROTECT");
389 case ACTION_SET_COMMENT: return("SETCOMMENT");
390 case ACTION_RENAME_OBJECT: return("RENAME");
391 case ACTION_INHIBIT: return("INHIBIT");
392 case ACTION_RENAME_DISK: return("RENAME DISK");
393 case ACTION_MORE_CACHE: return("MORE CACHE");
394 case ACTION_WAIT_CHAR: return("WAIT FOR CHAR");
395 case ACTION_FLUSH: return("FLUSH");
396 case ACTION_SCREEN_MODE: return("SCREENMODE");
397 case ACTION_IS_FILESYSTEM: return("IS_FILESYSTEM");
398 case ACTION_SAME_LOCK: return("SAME_LOCK");
399 case ACTION_COPY_DIR_FH: return("COPY_DIR_FH");
400 case ACTION_PARENT_FH: return("PARENT_FH");
401 case ACTION_EXAMINE_FH: return("EXAMINE_FH");
402 case ACTION_FH_FROM_LOCK: return("FH_FROM_LOCK");
403 case ACTION_CURRENT_VOLUME: return("CURRENT_VOLUME");
404 case ACTION_READ_LINK: return("READ LINK");
405 case ACTION_MAKE_LINK: return("MAKE LINK");
406 case ACTION_USER: return("USER");
407 default: return("---------UNKNOWN-------");
411 #if !(defined(__AROS__) || defined(__MORPHOS__))
414 * DEBUGGING CODE. You cannot make DOS library calls that access other
415 * devices from within a DOS device driver because they use the same
416 * message port as the driver. If you need to make such calls you must
417 * create a port and construct the DOS messages yourself. I do not
418 * do this. To get debugging info out another PROCESS is created to which
419 * debugging messages can be sent.
421 * You want the priority of the debug process to be larger than the
422 * priority of your DOS handler. This is so if your DOS handler crashes
423 * you have a better idea of where it died from the debugging messages
424 * (remember that the two processes are asyncronous from each other).
428 * BTW, the DOS library used by debugmain() was actually opened by
429 * the device driver. Note: DummyMsg cannot be on debugmain()'s stack
430 * since debugmain() goes away on the final handshake.
433 void SAVEDS debugmain (void)
435 MSG *msg;
436 short len;
437 void *fh;
438 #ifdef LOG_MESSAGES
439 void *out;
440 #endif
441 global->Dbport = CreateMsgPort ();
442 fh = (void *) Open ((UBYTE *) "con:0/0/640/200/debugwindow", 1006);
443 PutMsg(global->Dback, &global->DummyMsg);
444 #ifdef LOG_MESSAGES
445 #ifdef LOG_TO_PAR
446 out = (void *) Open ((UBYTE *) "PAR:", 1006);
447 #else
448 out = (void *) Open ((UBYTE *) "ram:cd.log", 1006);
449 #endif
450 #endif
451 for (;;) {
452 WaitPort(global->Dbport);
453 msg = GetMsg(global->Dbport);
454 len = msg->mn_Length;
455 if (len == 0)
456 break;
457 --len; /* Fix length up */
458 Write((BPTR) fh, msg+1, len);
459 #ifdef LOG_MESSAGES
460 Write((BPTR) out, msg+1, len);
461 #endif
462 FreeMem(msg,sizeof(MSG)+len+1);
464 Close ((BPTR) fh);
465 #ifdef LOG_MESSAGES
466 Close ((BPTR) out);
467 #endif
468 DeleteMsgPort(global->Dbport);
469 PutMsg(global->Dback,&global->DummyMsg); /* Kill handshake */
472 void dbinit (struct CDVDBase *global)
474 TASK *task = FindTask(NULL);
476 if (CreateNewProcTags (
477 NP_Entry, debugmain,
478 NP_Name, "DEV_DB",
479 NP_Priority, task->tc_Node.ln_Pri+1,
480 NP_StackSize, 4096,
481 TAG_DONE)) {
482 WaitPort(global->Dback); /* handshake startup */
483 GetMsg(global->Dback); /* remove dummy msg */
484 dbprintf("Debugger running:" HANDLER_VERSION "%s, %s\n",
485 #define asString(x) #x
486 #if defined(LATTICE)
487 "SAS/C" asString(__VERSION__) "." asString(__REVISION__),
488 #elif defined(__GNUC__)
489 "GNU C " __VERSION__,
490 #else
491 "???",
492 #endif
493 __TIME__);
497 void dbuninit (void)
499 MSG killmsg;
501 if (global->Dbport) {
502 killmsg.mn_Length = 0; /* 0 means die */
503 PutMsg(global->Dbport,&killmsg);
504 WaitPort(global->Dback); /* He's dead jim! */
505 GetMsg(global->Dback);
508 * Since the debug process is running at a greater priority, I
509 * am pretty sure that it is guarenteed to be completely removed
510 * before this task gets control again. Still, it doesn't hurt...
513 Delay(100); /* ensure he's dead */
517 void dbprintf (struct CDVDBase *global, char *format, ...)
519 va_list arg;
520 char buf[256];
521 MSG *msg;
523 va_start (arg, format);
524 if (global->Dbport && !global->DBDisable) {
525 vsprintf (buf, format, arg);
526 msg = AllocMem(sizeof(MSG)+strlen(buf)+1, MEMF_PUBLIC|MEMF_CLEAR);
527 msg->mn_Length = strlen(buf)+1; /* Length NEVER 0 */
528 strcpy((char *) (msg+1), buf);
529 PutMsg(global->Dbport,msg);
531 va_end (arg);
534 /* This hack is intended to suppress linking DOS access functions from libnix.
535 Libnix v1.2 is written badly and vsprintf() uses the same code as vfprintf()
536 whicn in turn relies on fputc(). This causes linker to add whole
537 dos.library-based I/O stuff to the code together with BREAK checking
538 functions. One of bad effects of this is that the handler can't be linked at
539 all due to lack of exit() function (i think even if it would link it is
540 unlikely to work properly) */
541 int __fflush(void)
543 return 1;
546 #endif /* !(__AROS__ || __MORPHOS__) */