- Don't access list nodes after their memory has been freed.
[AROS.git] / workbench / tools / HDToolBox / partitiontables.c
blobb7f8af94b158d88126f5ebf9bfd7b81b91d0e80f
1 /*
2 Copyright © 1995-2008, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <proto/dos.h>
7 #include <proto/exec.h>
8 #include <proto/expansion.h>
9 #include <proto/gadtools.h>
10 #include <proto/intuition.h>
11 #include <proto/partition.h>
13 #include <devices/bootblock.h>
14 #include <devices/scsidisk.h>
15 #include <devices/trackdisk.h>
16 #include <dos/dosextens.h>
17 #include <exec/memory.h>
18 #include <libraries/expansion.h>
19 #include <libraries/partition.h>
21 #include <stdio.h>
22 #include <string.h>
24 #include "partitiontables.h"
25 #include "gui.h"
26 #include "hdtoolbox_support.h"
27 #include "platform.h"
29 #include "debug.h"
31 extern struct GUIGadgets gadgets;
33 void getPartitionInfo(struct PartitionTable *table, struct PartitionHandle *ph)
35 D(bug("[HDToolBox] getPartitionInfo()\n"));
37 table->tattrlist = QueryPartitionTableAttrs(ph);
38 table->pattrlist = QueryPartitionAttrs(ph);
39 GetPartitionTableAttrsA
41 ph,
42 PTT_TYPE, &table->type,
43 PTT_RESERVED, &table->reserved,
44 PTT_MAX_PARTITIONS, &table->max_partitions,
45 TAG_DONE
47 D(bug("[HDToolBox] getPartitionInfo:type=%ld\n", table->type));
50 struct PartitionTable *newPartitionTable(struct PartitionHandle *ph)
52 struct PartitionTable *table;
54 D(bug("[HDToolBox] newPartitionTable()\n"));
56 table = AllocMem(sizeof(struct PartitionTable), MEMF_PUBLIC | MEMF_CLEAR);
57 if (table)
58 getPartitionInfo(table, ph);
59 return table;
62 BOOL findPartitionTable(struct HDTBPartition *partition)
64 D(bug("[HDToolBox] findPartitionTable()\n"));
66 if (OpenPartitionTable(partition->ph) == 0)
68 partition->table = newPartitionTable(partition->ph);
69 if (partition->table != NULL)
70 return TRUE;
71 ClosePartitionTable(partition->ph);
73 return FALSE;
76 void freePartitionTable(struct HDTBPartition *partition)
78 D(bug("[HDToolBox] freePartitionTable()\n"));
80 ClosePartitionTable(partition->ph);
81 FreeMem(partition->table, sizeof(struct PartitionTable));
84 BOOL makePartitionTable(struct HDTBPartition *table, ULONG type)
86 D(bug("[HDToolBox] makePartitionTable()\n"));
88 if (table->table)
90 /* if there is already a partition table then free it */
91 freePartitionList(&table->listnode.list);
92 DestroyPartitionTable(table->ph);
94 else
96 table->table = AllocMem(sizeof(struct PartitionTable), MEMF_PUBLIC | MEMF_CLEAR);
98 if (table->table)
100 if (CreatePartitionTable(table->ph, type) == 0)
102 getPartitionInfo(table->table, table->ph);
103 return TRUE;
106 return FALSE;
109 /**************************************************************************/
111 #if 0
112 ULONG getOffset(struct PartitionHandle *ph)
114 struct DosEnvec de;
115 ULONG offset = 0;
117 D(bug("[HDToolBox] getOffset()\n"));
119 while (ph->root)
121 GetPartitionAttrsA(ph, PT_DOSENVEC, de, TAG_DONE);
122 offset += de.de_LowCyl;
123 ph = ph->root;
125 return offset;
129 Output: 0 - no mount (no partition change)
130 1 - mount that device
131 2 - reboot not really neccessary
132 (FS not so important things changed like de_Mask)
133 3 - reboot neccessary
134 (FS important things changed like de_LowCyl)
136 WORD checkMount(struct HDTBPartition *table, STRPTR name, struct DosEnvec *de)
138 WORD retval = 1;
139 struct DosList *dl;
140 struct DeviceNode *entry;
141 ULONG i;
143 D(bug("[HDToolBox] checkMount('%s')\n", name));
145 dl = LockDosList(LDF_READ | LDF_DEVICES);
146 if (dl)
148 entry = (struct DeviceNode *)FindDosEntry(dl, name, LDF_DEVICES);
149 if (entry)
151 struct FileSysStartupMsg *fssm;
152 struct DosEnvec *d_de;
153 STRPTR devname;
155 fssm = (struct FileSysStartupMsg *)BADDR(entry->dn_Startup);
156 devname = AROS_BSTR_ADDR(fssm->fssm_Device);
157 if (
158 (fssm->fssm_Unit != table->hd->unit) ||
159 (strcmp(devname, table->hd->devname))
162 retval = 3; /* better do a reboot */
164 else
166 d_de = (struct DosEnvec *)BADDR(fssm->fssm_Environ);
167 i = getOffset(table->ph);
168 if (
169 (d_de->de_SizeBlock != de->de_SizeBlock) ||
170 (d_de->de_Reserved != de->de_Reserved) ||
171 (d_de->de_PreAlloc != de->de_PreAlloc) ||
172 (d_de->de_LowCyl != (de->de_LowCyl+i)) ||
173 (d_de->de_HighCyl != (de->de_HighCyl+i)) ||
174 (d_de->de_DosType != de->de_DosType) ||
177 /* at least one has de_BootBocks */
178 (d_de->de_TableSize>=DE_BOOTBLOCKS) ||
179 (de->de_TableSize>=DE_BOOTBLOCKS)
180 ) &&
182 /* if one has no de_BootBlock assume de_BootBlock change */
183 (d_de->de_TableSize<DE_BOOTBLOCKS) ||
184 (de->de_TableSize<DE_BOOTBLOCKS)
186 ) ||
188 /* both have de_BootBlocks */
189 (d_de->de_TableSize>=DE_BOOTBLOCKS) &&
190 (de->de_TableSize>=DE_BOOTBLOCKS) &&
191 (d_de->de_BootBlocks != de->de_BootBlocks)
195 retval = 3;
197 else if
199 (d_de->de_NumBuffers != de->de_NumBuffers) ||
200 (d_de->de_BufMemType != de->de_BufMemType) ||
201 (d_de->de_MaxTransfer != de->de_MaxTransfer) ||
202 (d_de->de_Mask != de->de_Mask) ||
203 (d_de->de_BootPri != de->de_BootPri)
206 retval = 2;
208 else
209 retval = 0;
212 UnLockDosList(LDF_READ | LDF_DEVICES);
214 return retval;
217 void mount(struct HDTBPartition *table, struct PartitionHandle *ph, STRPTR name, struct DosEnvec *de)
219 struct ExpansionBase *ExpansionBase;
220 struct DeviceNode *dn;
221 struct DosEnvec *nde;
222 IPTR *params;
223 ULONG i;
225 D(bug("[HDToolBox] mount('%s')\n", name));
227 #error "TODO: pass DOS device name in params[0] and set handler name manually"
228 #warning "TODO: get filesystem"
229 if ((de->de_DosType & 0xFFFFFF00) == BBNAME_DOS)
231 ExpansionBase = (struct ExpansionBase *)OpenLibrary("expansion.library",41);
232 if (ExpansionBase)
234 params = (IPTR *)AllocVec(sizeof(struct DosEnvec)+sizeof(IPTR)*4, MEMF_PUBLIC | MEMF_CLEAR);
235 if (params)
237 nde = (struct DosEnvec *)&params[4];
238 CopyMem(de, nde, sizeof(struct DosEnvec));
239 params[0] = (IPTR)"afs.handler";
240 params[1] = (IPTR)table->hd->devname;
241 params[2] = (IPTR)table->hd->unit;
242 params[3] = 0;
243 i = getOffset(ph->root);
244 nde->de_LowCyl += i;
245 nde->de_HighCyl += i;
246 dn = MakeDosNode(params);
247 if (dn)
249 dn->dn_Name = MKBADDR(AllocVec(AROS_BSTR_MEMSIZE4LEN(strlen(name)), MEMF_PUBLIC));
250 dn->dn_Ext.dn_AROS.dn_DevName = AROS_BSTR_ADDR(dn->dn_Name);
252 i = 0;
255 AROS_BSTR_putchar(dn->dn_Name, i, name[i]);
256 } while (name[i++]);
257 AROS_BSTR_setstrlen(dn->dn_Name, i-1);
258 AddDosNode(nde->de_BootPri, ADNF_STARTPROC, dn);
260 else
261 FreeVec(params);
263 CloseLibrary((struct Library *)ExpansionBase);
266 else
267 kprintf("ignored %s: unknown FS (0x%lx)\n", name, de->de_DosType);
270 void mountPartitions(struct List *ptlist)
272 struct EasyStruct es =
274 sizeof(struct EasyStruct), 0,
275 "HDToolBox",
277 "Yes|No"
279 struct PartitionTableNode *table;
280 struct PartitionHandle *ph;
281 WORD cm;
282 WORD reboot = 0;
284 D(bug("[HDToolBox] mountPartitions()\n"));
286 table = (struct PartitionTableNode *)ptlist->lh_Head;
287 while (table->ln.ln_Succ)
289 if (table->type != PHPTT_UNKNOWN)
291 ph = (struct PartitionHandle *)table->ph->table->list.lh_Head;
292 while (ph->ln.ln_Succ)
294 if (existsAttr(table->pattrlist, PTA_AUTOMOUNT))
296 LONG flag;
298 GetPartitionAttrsA(ph, PT_AUTOMOUNT, &flag, TAG_DONE);
299 if (flag)
301 if (existsAttr(table->pattrlist, PTA_NAME))
303 UBYTE name[32];
304 struct DosEnvec de;
306 GetPartitionAttrsA(ph, PT_NAME, name, PT_DOSENVEC, &de, TAG_DONE);
307 cm = checkMount(table, name, &de);
308 if (cm == 1)
309 mount(table, ph, name, &de);
310 else if (cm == 2)
311 kprintf("may reboot\n");
312 else if (cm == 3)
313 kprintf("have to reboot\n");
314 else
315 kprintf("mount %s not needed\n", name);
316 if (reboot<cm)
317 reboot = cm;
319 else
320 kprintf("Partition with no name is automountable\n");
323 ph = (struct PartitionHandle *)ph->ln.ln_Succ;
326 table = (struct PartitionTableNode *)table->ln.ln_Succ;
328 if (reboot > 1)
330 if (reboot == 2)
332 es.es_TextFormat =
333 "A reboot is not necessary because the changes do not\n"
334 "affect the work of any running filesystem.\n"
335 "Do you want to reboot anyway?";
337 else
339 es.es_TextFormat =
340 "A reboot is required because the changes affect\n"
341 "the work of at least one running filesystem.\n"
342 "Do you want to reboot now?";
344 if (EasyRequestArgs(0, &es, 0, 0))
345 ColdReboot();
348 #endif