Initial import of Scalos. To decrease size I have
[AROS-Contrib.git] / scalos / Prefs / MainPrefs / HiddenDevices.c
blobacc2378c4abb8495a8011c4f92c5f83eeffe06da
1 // HiddenDevices.c
2 // $Date$
3 // $Revision$
6 #include <exec/types.h>
7 #include <scalos/preferences.h>
8 #include <scalos/scalos.h>
9 #include <intuition/intuition.h>
10 #include <devices/inputevent.h>
11 #include <libraries/iffparse.h>
12 #include <libraries/mui.h>
13 #include <libraries/asl.h>
14 #include <libraries/mcpgfx.h>
15 #include <libraries/ttengine.h>
16 #include <graphics/view.h>
17 #include <prefs/prefhdr.h>
18 #include <prefs/font.h>
19 #include <prefs/workbench.h>
20 #include <mui/NListview_mcc.h>
22 #define __USE_SYSBASE
24 #include <proto/dos.h>
25 #include <proto/exec.h>
26 #include <proto/intuition.h>
27 #include <proto/dos.h>
28 #include <proto/iffparse.h>
29 #include <proto/scalos.h>
30 #include <proto/utility.h>
31 #include <proto/wb.h>
32 #define NO_INLINE_STDARG
33 #include <proto/muimaster.h>
35 #include <clib/alib_protos.h>
37 #include <defs.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <stddef.h>
43 #include <ctype.h>
44 #include <limits.h>
46 #include "HiddenDevices.h"
47 #include "ScalosPrefs.h"
49 //-----------------------------------------------------------------
51 struct HiddenDevice
53 struct Node hd_Node;
54 char hd_Name[1]; // variable length
57 struct UnknownPrefsChunk
59 struct Node upc_Node;
60 LONG upc_ID;
61 LONG upc_Type;
62 LONG upc_Size;
63 UBYTE upc_Data[1]; // variable length
66 //-----------------------------------------------------------------
68 static void HandleWBHD(const UBYTE *data, size_t length);
69 static LONG CollectUnknownPrefsChunks(struct List *ChunksList, CONST_STRPTR Filename);
70 static LONG AddUnknownChunk(struct List *ChunksList, struct IFFHandle *iff, const struct ContextNode *cn);
71 static void CleanupUnknownChunks(struct List *ChunksList);
72 static void AddHiddenDeviceFromDosList(struct SCAModule *app, struct DosList *dl, struct InfoData *id, BOOL Hidden);
73 static void BtoCString(BPTR bstring, STRPTR Buffer, size_t Length);
74 static BOOL FindHiddenDevice(CONST_STRPTR Name);
75 static void StripTrailingColon(STRPTR Line);
77 //-----------------------------------------------------------------
79 static struct List HiddenDevicesList;
81 //-----------------------------------------------------------------
83 BOOL HiddenDevicesInit(void)
85 NewList(&HiddenDevicesList);
87 return TRUE;
90 //-----------------------------------------------------------------
92 void HiddenDevicesCleanup(void)
94 struct HiddenDevice *hd;
96 while ((hd = (struct HiddenDevice *) RemHead(&HiddenDevicesList)))
98 free(hd);
102 //-----------------------------------------------------------------
104 // Read workbench.prefs and build list of hidden devices
105 BOOL ReadWorkbenchPrefs(CONST_STRPTR filename)
107 struct IFFHandle *iff;
108 LONG error;
109 BOOL IffOpened = FALSE;
110 static const ULONG pairs[] = {ID_PREF, ID_PREF, ID_WBHD};
112 HiddenDevicesCleanup();
114 d1(KPrintF(__FILE__ "/%s/%ld: filename=<%s>\n", __FUNC__, __LINE__, filename));
116 do {
117 iff = AllocIFF();
118 if (NULL == iff)
119 break;
121 iff->iff_Stream = (ULONG) Open((STRPTR) filename, MODE_OLDFILE);
122 d1(KPrintF(__FILE__ "/%s/%ld: iff_Stream=%08lx\n", __FUNC__, __LINE__, iff->iff_Stream));
123 if (0 == iff->iff_Stream)
124 break;
126 InitIFFasDOS( iff );
128 error = OpenIFF( iff, IFFF_READ );
129 if (RETURN_OK != error)
130 break;
132 IffOpened = TRUE;
134 error = CollectionChunks( iff, (LONG*) pairs, Sizeof(pairs) / 2);
135 if (RETURN_OK != error)
136 break;
138 StopOnExit( iff, ID_PREF, ID_FORM );
140 while(TRUE)
142 if( ( error = ParseIFF( iff, IFFPARSE_SCAN ) ) == IFFERR_EOC )
144 struct CollectionItem *ci;
146 ci = FindCollection( iff, ID_PREF, ID_WBHD);
147 while( ci )
149 HandleWBHD(ci->ci_Data, ci->ci_Size);
150 ci = ci->ci_Next;
154 else
155 break;
157 } while (0);
159 if (iff)
161 if (IffOpened)
162 CloseIFF( iff );
163 if (iff->iff_Stream)
164 Close( (BPTR)iff->iff_Stream );
165 FreeIFF( iff );
168 return TRUE;
171 //-----------------------------------------------------------------
173 static void HandleWBHD(const UBYTE *data, size_t length)
175 d1(KPrintF(__FILE__ "/%s/%ld: data=<%s> length=%lu\n", __FUNC__, __LINE__, data, length));
177 if (!FindHiddenDevice((STRPTR)data)) // make sure we get no cuplicate entries
178 AddHiddenDevice((STRPTR)data);
181 //-----------------------------------------------------------------
183 // save workbench.prefs, including WBHD entries for each hidden device
184 LONG WriteWorkbenchPrefs(CONST_STRPTR Filename)
186 struct IFFHandle *iff = NULL;
187 LONG Result;
188 BOOL IffOpen = FALSE;
189 struct List ChunksList;
191 NewList(&ChunksList);
193 do {
194 static const struct PrefHeader prefHeader = { 0, 0, 0L };
195 struct HiddenDevice *hd;
196 struct UnknownPrefsChunk *upc;
198 d1(KPrintF(__FILE__ "/%s/%ld: Filename=<%s>\n", __FUNC__, __LINE__, Filename));
200 Result = CollectUnknownPrefsChunks(&ChunksList, Filename);
201 d1(KPrintF(__FILE__ "/%s/%ld: Result=%ld\n", __FUNC__, __LINE__, Result));
202 if (RETURN_OK != Result)
203 break;
205 iff = AllocIFF();
206 if (NULL == iff)
208 Result = IoErr();
209 break;
212 InitIFFasDOS(iff);
214 iff->iff_Stream = (IPTR)Open(Filename, MODE_NEWFILE);
215 if (0 == iff->iff_Stream)
217 // ... try to create missing directories here
218 STRPTR FilenameCopy;
220 Result = IoErr();
221 d1(KPrintF(__FILE__ "/%s/%ld: Result=%ld\n", __FUNC__, __LINE__, Result));
223 FilenameCopy = AllocVec(1 + strlen(Filename), MEMF_PUBLIC);
225 if (FilenameCopy)
227 STRPTR lp;
229 strcpy(FilenameCopy, Filename);
231 lp = PathPart(FilenameCopy);
232 if (lp)
234 BPTR dirLock;
236 *lp = '\0';
237 dirLock = CreateDir(FilenameCopy);
239 if (dirLock)
240 UnLock(dirLock);
242 iff->iff_Stream = (IPTR)Open(Filename, MODE_NEWFILE);
243 if (0 == iff->iff_Stream)
244 Result = IoErr();
245 else
246 Result = RETURN_OK;
249 FreeVec(FilenameCopy);
252 d1(KPrintF(__FILE__ "/%s/%ld: Result=%ld\n", __FUNC__, __LINE__, Result));
253 if (RETURN_OK != Result)
254 break;
257 d1(KPrintF(__FILE__ "/%s/%ld: Result=%ld\n", __FUNC__, __LINE__, Result));
259 Result = OpenIFF(iff, IFFF_WRITE);
260 if (RETURN_OK != Result)
261 break;
263 IffOpen = TRUE;
264 d1(KPrintF(__FILE__ "/%s/%ld: Result=%ld\n", __FUNC__, __LINE__, Result));
266 Result = PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN);
267 if (RETURN_OK != Result)
268 break;
270 Result = PushChunk(iff, 0, ID_PRHD, IFFSIZE_UNKNOWN);
271 if (RETURN_OK != Result)
272 break;
274 if (WriteChunkBytes(iff, (APTR) &prefHeader, sizeof(prefHeader)) < 0)
276 Result = IoErr();
277 break;
280 Result = PopChunk(iff); // PRHD
281 if (RETURN_OK != Result)
282 break;
284 d1(KPrintF(__FILE__ "/%s/%ld: Result=%ld\n", __FUNC__, __LINE__, Result));
286 for (hd = (struct HiddenDevice *) HiddenDevicesList.lh_Head;
287 hd != (struct HiddenDevice *) &HiddenDevicesList.lh_Tail;
288 hd = (struct HiddenDevice *) hd->hd_Node.ln_Succ)
290 size_t wbhdLength = 1 + strlen(hd->hd_Name);
292 d1(KPrintF(__FILE__ "/%s/%ld: hd_Name=<%s>\n", __FUNC__, __LINE__, hd->hd_Name));
294 Result = PushChunk(iff, 0, ID_WBHD, IFFSIZE_UNKNOWN);
295 if (RETURN_OK != Result)
296 break;
298 if (wbhdLength != WriteChunkBytes(iff, (APTR) hd->hd_Name, wbhdLength))
300 Result = IoErr();
301 break;
303 if (wbhdLength & 0x01)
305 // write dummy byte to get even chunk length
306 ULONG Dummy = 0;
308 if (1 != WriteChunkBytes(iff, (APTR) &Dummy, 1))
310 Result = IoErr();
311 break;
315 Result = PopChunk(iff); // WBHD
316 if (RETURN_OK != Result)
317 break;
320 d1(KPrintF(__FILE__ "/%s/%ld: Result=%ld\n", __FUNC__, __LINE__, Result));
322 if (RETURN_OK != Result)
323 break;
325 for (upc = (struct UnknownPrefsChunk *) ChunksList.lh_Head;
326 upc != (struct UnknownPrefsChunk *) &ChunksList.lh_Tail;
327 upc = (struct UnknownPrefsChunk *) upc->upc_Node.ln_Succ )
329 d1(KPrintF("%s/%s/%ld: Write Chunk Type=%08lx, ID=%08lx Length=%lu\n", __FILE__, __FUNC__, __LINE__, \
330 upc->upc_Type, upc->upc_ID, upc->upc_Size));
332 Result = PushChunk(iff, 0, upc->upc_ID, IFFSIZE_UNKNOWN);
333 if (RETURN_OK != Result)
334 break;
336 if (upc->upc_Size != WriteChunkBytes(iff, (APTR) upc->upc_Data, upc->upc_Size))
338 Result = IoErr();
339 break;
342 Result = PopChunk(iff); // upc->upc_ID
343 if (RETURN_OK != Result)
344 break;
347 Result = PopChunk(iff); // FORM
348 if (RETURN_OK != Result)
349 break;
351 } while (0);
353 CleanupUnknownChunks(&ChunksList);
355 if (iff)
357 if (IffOpen)
358 CloseIFF(iff);
360 if (iff->iff_Stream)
362 Close((BPTR)iff->iff_Stream);
363 iff->iff_Stream = 0;
366 FreeIFF(iff);
369 d1(KPrintF(__FILE__ "/%s/%ld: Result=%ld\n", __FUNC__, __LINE__, Result));
371 if (RETURN_OK == Result && fCreateIcons)
372 SaveIcon(Filename);
374 return Result;
377 //-----------------------------------------------------------------
379 static LONG CollectUnknownPrefsChunks(struct List *ChunksList, CONST_STRPTR Filename)
381 LONG Result;
382 struct IFFHandle *iff;
383 BOOL iffOpened = FALSE;
385 d1(KPrintF(__FILE__ "/%s/%ld: Filename=<%s>\n", __FUNC__, __LINE__, Filename));
387 do {
388 iff = AllocIFF();
389 if (NULL == iff)
391 Result = IoErr();
392 break;
395 InitIFFasDOS(iff);
397 iff->iff_Stream = (IPTR)Open(Filename, MODE_OLDFILE);
398 if (0 == iff->iff_Stream)
400 Result = IoErr();
401 break;
404 Result = OpenIFF(iff, IFFF_READ);
405 if (RETURN_OK != Result)
406 break;
408 iffOpened = TRUE;
410 while (RETURN_OK == Result)
412 struct ContextNode *cn;
414 Result = ParseIFF(iff, IFFPARSE_RAWSTEP);
415 d1(KPrintF(__FILE__ "/%s/%ld: Result=%ld\n", __FUNC__, __LINE__, Result));
416 if (IFFERR_EOC == Result)
418 Result = RETURN_OK;
419 continue;
421 if (IFFERR_EOF == Result)
423 Result = RETURN_OK;
424 break;
426 if (RETURN_OK != Result)
427 break;
429 cn = CurrentChunk(iff);
430 if (NULL == cn)
431 continue;
433 switch (cn->cn_ID)
435 case ID_FORM:
436 d1(KPrintF(__FILE__ "/%s/%ld: ID_FORM Size=%ld\n", __FUNC__, __LINE__, cn->cn_Size));
437 break;
438 case ID_PREF:
439 d1(KPrintF(__FILE__ "/%s/%ld: ID_PREF Size=%ld\n", __FUNC__, __LINE__, cn->cn_Size));
440 break;
441 case ID_PRHD:
442 d1(KPrintF(__FILE__ "/%s/%ld: ID_PRHD Size=%ld\n", __FUNC__, __LINE__, cn->cn_Size));
443 break;
444 default:
445 d1(KPrintF("%s/%s/%ld: Found Chunk Type=%08lx, ID=%08lx Length=%lu\n", __FILE__, __FUNC__, __LINE__, \
446 cn->cn_Type, cn->cn_ID, cn->cn_Size));
447 Result = AddUnknownChunk(ChunksList, iff, cn);
448 break;
451 } while (0);
453 if (iff)
455 if (iffOpened)
456 CloseIFF(iff);
458 if (iff->iff_Stream)
459 Close((BPTR)iff->iff_Stream);
461 FreeIFF(iff);
464 return Result;
467 //-----------------------------------------------------------------
469 static LONG AddUnknownChunk(struct List *ChunksList, struct IFFHandle *iff, const struct ContextNode *cn)
471 struct UnknownPrefsChunk *upc;
472 LONG Result = RETURN_OK;
474 do {
475 LONG Length;
477 upc = malloc(sizeof(struct UnknownPrefsChunk) + cn->cn_Size);
478 if (NULL == upc)
480 Result = ERROR_NO_FREE_STORE;
481 break;
484 upc->upc_ID = cn->cn_ID;
485 upc->upc_Type = cn->cn_Type;
486 upc->upc_Size = cn->cn_Size;
488 Length = ReadChunkBytes(iff, upc->upc_Data, upc->upc_Size);
489 if (Length != upc->upc_Size)
491 Result = IoErr();
492 break;
495 AddTail(ChunksList, &upc->upc_Node);
496 upc = NULL;
497 } while (0);
499 if (upc)
501 free(upc);
504 d1(KPrintF(__FILE__ "/%s/%ld: Result=%ld\n", __FUNC__, __LINE__, Result));
506 return Result;
509 //-----------------------------------------------------------------
511 static void CleanupUnknownChunks(struct List *ChunksList)
513 struct UnknownPrefsChunk *upc;
515 while ((upc = (struct UnknownPrefsChunk *) RemTail(ChunksList)))
517 free(upc);
521 //-----------------------------------------------------------------
523 // Traverse DosList for all devices, and build list of hideable devices
524 void FillHiddenDevicesList(struct SCAModule *app)
526 ULONG LockDosListFlags = LDF_DEVICES | LDF_READ;
527 struct HiddenDevice *hd;
528 struct DosList *dl;
529 struct InfoData *id;
531 set(app->Obj[NLIST_HIDDENDEVICES], MUIA_NList_Quiet, TRUE);
532 DoMethod(app->Obj[NLIST_HIDDENDEVICES], MUIM_NList_Clear);
533 DoMethod(app->Obj[NLIST_HIDDENDEVICES], MUIM_NList_UseImage,
534 NULL, MUIV_NList_UseImage_All, 0);
536 id = malloc(sizeof(struct InfoData));
537 if (id)
539 dl = LockDosList(LockDosListFlags);
541 while (dl = NextDosEntry(dl, LockDosListFlags))
543 AddHiddenDeviceFromDosList(app, dl, id, FALSE);
546 UnLockDosList(LockDosListFlags);
547 free(id);
550 // Now walk through the list of devices marked as hidden,
551 // and add all entries.
553 dl = LockDosList(LockDosListFlags);
555 for (hd = (struct HiddenDevice *) HiddenDevicesList.lh_Head;
556 hd != (struct HiddenDevice *) &HiddenDevicesList.lh_Tail;
557 hd = (struct HiddenDevice *) hd->hd_Node.ln_Succ)
559 char HiddenDevName[128];
560 struct DosList *dlFound;
562 // Name must not have trailing ":" to use with FindDosEntry()
563 stccpy(HiddenDevName, hd->hd_Name, sizeof(HiddenDevName));
564 StripTrailingColon(HiddenDevName);
565 d1(KPrintF(__FILE__ "/%s/%ld: HiddenDevName=<%s>\n", __FUNC__, __LINE__, HiddenDevName));
567 dlFound = FindDosEntry(dl, HiddenDevName, LockDosListFlags);
568 d1(KPrintF(__FILE__ "/%s/%ld: dl=%08lx\n", __FUNC__, __LINE__, dlFound));
569 if (dlFound)
571 AddHiddenDeviceFromDosList(app, dlFound, id, TRUE);
573 else
575 struct NewHiddenDevice nhd;
577 nhd.nhd_DeviceName = hd->hd_Name;
578 nhd.nhd_VolumeName = "";
579 nhd.nhd_Hidden = TRUE;
581 d1(KPrintF(__FILE__ "/%s/%ld: DevName=<%s> VolName=<%s>\n", \
582 __FUNC__, __LINE__, nhd.nhd_DeviceName, nhd.nhd_VolumeName));
584 DoMethod(app->Obj[NLIST_HIDDENDEVICES],
585 MUIM_NList_InsertSingle,
586 &nhd,
587 MUIV_NList_Insert_Sorted);
591 UnLockDosList(LockDosListFlags);
593 set(app->Obj[NLIST_HIDDENDEVICES], MUIA_NList_Quiet, FALSE);
596 //-----------------------------------------------------------------
598 static void AddHiddenDeviceFromDosList(struct SCAModule *app, struct DosList *dl, struct InfoData *id, BOOL Hidden)
600 char DevName[128];
601 char VolName[128];
602 struct DosList *VolumeNode;
603 BOOL InfoDataValid = FALSE;
605 strcpy(VolName, "");
606 BtoCString(dl->dol_Name, DevName, sizeof(DevName));
608 d1(KPrintF(__FILE__ "/%s/%ld: START DevName=<%s>\n", __FUNC__, __LINE__, DevName));
610 #if defined(__amigaos4__)
611 if (0 != Stricmp(DevName, "ENV"))
612 #endif //!defined(__amigaos4__)
614 d1(KPrintF(__FILE__ "/%s/%ld: \n", __FUNC__, __LINE__));
615 if (dl->dol_Task &&
616 DoPkt(dl->dol_Task, ACTION_DISK_INFO,
617 (IPTR)MKBADDR(id),
618 0, 0, 0, 0))
620 InfoDataValid = TRUE;
622 d1(KPrintF(__FILE__ "/%s/%ld: InfoDataValid=%ld\n", __FUNC__, __LINE__, InfoDataValid));
625 if (!Hidden && !InfoDataValid)
626 return;
628 if (InfoDataValid)
630 switch (id->id_DiskState)
632 case ID_WRITE_PROTECTED:
633 case ID_VALIDATING:
634 case ID_VALIDATED:
635 VolumeNode = BADDR(id->id_VolumeNode);
636 if (VolumeNode)
638 BtoCString(VolumeNode->dol_Name, VolName, sizeof(VolName));
639 StripTrailingColon(VolName);
640 strcat(VolName, ":");
642 break;
643 default:
644 break;
648 StripTrailingColon(DevName);
649 strcat(DevName, ":");
651 // add only visible devices here
652 if (Hidden || !FindHiddenDevice(DevName))
654 struct NewHiddenDevice nhd;
656 nhd.nhd_DeviceName = DevName;
657 nhd.nhd_VolumeName = VolName;
658 nhd.nhd_Hidden = Hidden;
660 d1(KPrintF(__FILE__ "/%s/%ld: DevName=<%s> VolName=<%s>\n", \
661 __FUNC__, __LINE__, nhd.nhd_DeviceName, nhd.nhd_VolumeName));
663 DoMethod(app->Obj[NLIST_HIDDENDEVICES],
664 MUIM_NList_InsertSingle,
665 &nhd,
666 MUIV_NList_Insert_Sorted);
670 //-----------------------------------------------------------------
672 static void BtoCString(BPTR bstring, STRPTR Buffer, size_t Length)
674 #ifdef __AROS__
675 // AROS needs special handling because it uses NULL-terminated
676 // strings on some platforms.
677 size_t Len = AROS_BSTR_strlen(bstring);
678 if (Len >= Length)
679 Len = Length - 1;
680 strncpy(Buffer, AROS_BSTR_ADDR(bstring), Len);
681 Buffer[Len] = '\0';
682 #else
683 CONST_STRPTR Src = BADDR(bstring);
684 size_t bLength;
686 // get BSTRING length (1st octet)
687 bLength = *Src++;
689 while (bLength-- && (Length-- > 1))
690 *Buffer++ = *Src++;
692 *Buffer = '\0';
693 #endif
696 //-----------------------------------------------------------------
698 // Add entry to hidden devices list
699 BOOL AddHiddenDevice(CONST_STRPTR Name)
701 struct HiddenDevice *hd;
702 BOOL Success = FALSE;
704 hd = malloc(sizeof(struct HiddenDevice) + 1 + strlen(Name));
705 if (hd)
707 strcpy(hd->hd_Name, Name);
709 // make sure device name is terminated with exactly one ":"
710 StripTrailingColon(hd->hd_Name);
711 strcat(hd->hd_Name, ":");
713 AddHead(&HiddenDevicesList, &hd->hd_Node);
714 Success = TRUE;
717 d1(KPrintF(__FILE__ "/%s/%ld: Name=<%s> hd=%08lx\n", __FUNC__, __LINE__, Name, hd));
719 return Success;
722 //-----------------------------------------------------------------
724 // Remove entry from hidden devices list
725 BOOL RemoveHiddenDevice(CONST_STRPTR Name)
727 struct HiddenDevice *hd;
728 BOOL Found = FALSE;
730 d1(KPrintF(__FILE__ "/%s/%ld: Name=<%s>", __FUNC__, __LINE__, Name));
732 for (hd = (struct HiddenDevice *) HiddenDevicesList.lh_Head;
733 hd != (struct HiddenDevice *) &HiddenDevicesList.lh_Tail;
734 hd = (struct HiddenDevice *) hd->hd_Node.ln_Succ)
736 if (0 == Stricmp(Name, hd->hd_Name))
738 Found = TRUE;
739 Remove(&hd->hd_Node);
740 free(hd);
741 break;
745 return Found;
748 //-----------------------------------------------------------------
750 // search for entry in hidden devices list
751 static BOOL FindHiddenDevice(CONST_STRPTR Name)
753 const struct HiddenDevice *hd;
754 BOOL Found = FALSE;
756 d1(KPrintF(__FILE__ "/%s/%ld: Name=<%s>", __FUNC__, __LINE__, Name));
758 for (hd = (struct HiddenDevice *) HiddenDevicesList.lh_Head;
759 hd != (struct HiddenDevice *) &HiddenDevicesList.lh_Tail;
760 hd = (struct HiddenDevice *) hd->hd_Node.ln_Succ)
762 if (0 == Stricmp(Name, hd->hd_Name))
764 Found = TRUE;
765 break;
769 return Found;
772 //-----------------------------------------------------------------
774 static void StripTrailingColon(STRPTR Line)
776 size_t Len = strlen(Line);
778 Line += Len - 1;
780 if (':' == *Line)
781 *Line = '\0';
784 //-----------------------------------------------------------------