Hint added.
[AROS.git] / workbench / c / Automount.c
blob8fe18ef70915f9de2c9327997d6da8c4e2e44b97
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /******************************************************************************
9 NAME
11 AutoMount
13 SYNOPSIS
15 (N/A)
17 LOCATION
21 FUNCTION
23 INPUTS
25 RESULT
27 NOTES
29 Command is called in Startup-Sequence.
31 EXAMPLE
33 BUGS
35 SEE ALSO
37 INTERNALS
39 HISTORY
41 ******************************************************************************/
43 #include <aros/debug.h>
44 #include <dos/dos.h>
45 #include <dos/rdargs.h>
46 #include <exec/lists.h>
47 #include <exec/memory.h>
48 #include <libraries/expansion.h>
49 #include <libraries/expansionbase.h>
50 #include <proto/alib.h>
51 #include <proto/arossupport.h>
52 #include <proto/dos.h>
53 #include <proto/exec.h>
54 #include <proto/expansion.h>
56 #include <stdlib.h>
57 #include <string.h>
59 struct HandlerNode
61 struct MinNode n;
62 ULONG id;
63 ULONG mask;
64 char handler[1];
67 struct MinList handlerlist;
68 APTR pool;
70 LONG parsePrefs(char *buffer, LONG size)
72 struct CSource csrc = {buffer, size, 0};
73 char ident[256];
74 LONG res;
75 WORD line = 1;
77 D(bug("[Automount] parsePrefs()\n"));
79 while (csrc.CS_CurChr < csrc.CS_Length)
81 struct HandlerNode *tn;
82 int i;
83 char *p;
84 ULONG id = 0;
85 ULONG mask = 0xFFFFFFFF;
87 DB2(bug("[parsePrefs] Cur %d, Length %d\n", csrc.CS_CurChr, csrc.CS_Length));
89 res = ReadItem(ident, 256, &csrc);
90 switch (res)
92 case ITEM_ERROR:
93 return IoErr();
95 case ITEM_UNQUOTED:
96 if (ident[0] == '#')
98 /* Skip over to the end of line */
99 while ((csrc.CS_CurChr < csrc.CS_Length) && (buffer[csrc.CS_CurChr] != '\n'))
100 csrc.CS_CurChr++;
102 goto next_line;
104 /* Fall through */
105 case ITEM_QUOTED:
106 p = ident;
107 for (i = 0; i < 4; i++)
109 UBYTE c;
111 if (!*p)
113 Printf("LINE %ld: Mailformed filesystem ID\n", line);
114 return -1;
117 c = *p++;
118 switch (c)
120 case '\\':
121 c = strtoul(p, &p, 16);
122 break;
124 case '?':
125 mask &= ~(0xFF000000 >> (i << 3));
126 c = 0;
129 id <<= 8;
130 id |= c;
132 break;
134 default:
135 Printf("LINE %ld: Missing filesystem ID\n", line);
136 return -1;
139 res = ReadItem(ident, 256, &csrc);
140 if (res == ITEM_ERROR)
141 return IoErr();
143 if (res != ITEM_EQUAL)
145 Printf("LINE %ld: Unexpected item after filesystem ID\n", line);
146 return -1;
149 res = ReadItem(ident, 256, &csrc);
150 if (res == ITEM_ERROR)
151 return IoErr();
153 if ((res != ITEM_QUOTED) && (res != ITEM_UNQUOTED))
155 Printf("LINE %ld: Missing handler name\n", line);
156 return -1;
159 res = strlen(ident);
160 tn = AllocPooled(pool, sizeof(struct HandlerNode) + res);
161 if (tn == NULL)
162 return ERROR_NO_FREE_STORE;
164 tn->id = id;
165 tn->mask = mask;
166 CopyMem(ident, tn->handler, res + 1);
168 AddTail((struct List *)&handlerlist, (struct Node *)tn);
170 next_line:
172 * Intentional ReadItem() bug workaround.
173 * Ungets '\n' every time, causing an infinite loop without this adjustment.
175 if ((csrc.CS_CurChr < csrc.CS_Length) && (buffer[csrc.CS_CurChr] == '\n'))
177 line++;
178 csrc.CS_CurChr++;
182 return 0;
185 static LONG LoadPrefs(STRPTR filename)
187 struct FileInfoBlock fib;
188 char *buffer;
189 LONG retval = 0;
190 LONG size;
191 BPTR fh;
193 D(bug("[Automount] LoadPrefs('%s')\n", filename));
195 fh = Open(filename, MODE_OLDFILE);
196 if (fh)
198 if (ExamineFH(fh, &fib))
200 if (fib.fib_Size>0)
202 buffer = AllocMem(fib.fib_Size, MEMF_PUBLIC | MEMF_CLEAR);
203 if (buffer)
205 size = Read(fh, buffer, fib.fib_Size);
206 if (size == fib.fib_Size)
207 retval = parsePrefs(buffer, size);
208 else
209 retval = IoErr();
211 FreeMem(buffer, fib.fib_Size);
213 else
214 retval = ERROR_NO_FREE_STORE;
217 else
218 retval = IoErr();
220 Close(fh);
223 return retval;
226 static struct HandlerNode *FindHandler(ULONG id)
228 struct HandlerNode *n;
230 ForeachNode(&handlerlist, n)
232 if (n->id == (id & n->mask))
233 return n;
236 return NULL;
239 static BOOL IsMounted(struct DeviceNode *dn)
241 BOOL ret = FALSE;
242 struct DosList *dl = LockDosList(LDF_DEVICES|LDF_READ);
244 while ((dl = NextDosEntry(dl, LDF_DEVICES)))
246 if (dl == (struct DosList *)dn)
248 ret = TRUE;
249 break;
253 UnLockDosList(LDF_DEVICES|LDF_READ);
254 return ret;
257 int __nocommandline = 1;
259 int main(void)
261 LONG res;
263 pool = CreatePool(1024, 1024, MEMF_ANY);
264 if (!pool)
266 PrintFault(ERROR_NO_FREE_STORE, "Automount");
267 return RETURN_FAIL;
270 NewList((struct List *)&handlerlist);
271 res = LoadPrefs("L:automount-config");
273 if (res == 0)
275 struct BootNode *n;
277 ForeachNode(&((struct ExpansionBase *)ExpansionBase)->MountList, n)
279 struct DeviceNode *dn = n->bn_DeviceNode;
281 D(bug("[Automount] Checking BootNode %b...\n", dn->dn_Name));
283 if ((!dn->dn_Task) && (!dn->dn_SegList) && (!dn->dn_Handler) && dn->dn_Startup)
285 struct FileSysStartupMsg *fssm = BADDR(dn->dn_Startup);
287 D(bug("[Automount] Not mounted\n"));
289 if (fssm->fssm_Environ)
291 struct DosEnvec *de = BADDR(fssm->fssm_Environ);
293 if (de)
295 struct HandlerNode *hn = FindHandler(de->de_DosType);
297 if (hn)
299 Printf("Mounting %b with %s\n", dn->dn_Name, hn->handler);
301 dn->dn_Handler = CreateBSTR(hn->handler);
302 if (!dn->dn_Handler)
304 res = ERROR_NO_FREE_STORE;
305 break;
308 if (!IsMounted(dn))
310 D(bug("[Automount] Adding DOS entry...\n"));
311 AddDosEntry((struct DosList *)dn);
314 if (n->bn_Flags & ADNF_STARTPROC)
316 char *buf;
318 D(bug("[Automount] Starting up...\n"));
320 res = AROS_BSTR_strlen(dn->dn_Name);
321 buf = AllocMem(res + 2, MEMF_ANY);
322 if (!buf)
324 res = ERROR_NO_FREE_STORE;
325 break;
328 CopyMem(AROS_BSTR_ADDR(dn->dn_Name), buf, res);
329 buf[res++] = ':';
330 buf[res++] = 0;
332 DeviceProc(buf);
333 FreeMem(buf, res);
341 else if (res != -1)
342 PrintFault(res, "Automount");
344 DeletePool(pool);
345 return RETURN_OK;