Some installer cleanup.
[dragonfly.git] / contrib / bsdinstaller-1.1.6 / src / backend / installer / fn_disk.c
1 /*
2  * Copyright (c)2004 The DragonFly Project.  All rights reserved.
3  * 
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 
8  *   Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * 
11  *   Redistributions in binary form must reproduce the above copyright
12  *   notice, this list of conditions and the following disclaimer in
13  *   the documentation and/or other materials provided with the
14  *   distribution.
15  * 
16  *   Neither the name of the DragonFly Project nor the names of its
17  *   contributors may be used to endorse or promote products derived
18  *   from this software without specific prior written permission. 
19  * 
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31  * OF THE POSSIBILITY OF SUCH DAMAGE. 
32  */
33
34 /*
35  * fn_disk.c
36  * Disk functions for installer.
37  * $Id: fn_disk.c,v 1.40 2005/03/13 01:53:58 cpressey Exp $
38  */
39
40 #include <stdlib.h>
41 #include <string.h>
42
43 #ifdef ENABLE_NLS
44 #include <libintl.h>
45 #define _(String) gettext (String)
46 #else
47 #define _(String) (String)
48 #endif
49
50 #include "libaura/mem.h"
51 #include "libaura/fspred.h"
52
53 #include "libdfui/dfui.h"
54 #include "libdfui/system.h"
55
56 #include "libinstaller/commands.h"
57 #include "libinstaller/diskutil.h"
58 #include "libinstaller/functions.h"
59 #include "libinstaller/uiutil.h"
60
61 #include "fn.h"
62 #include "pathnames.h"
63
64 /*** DISK-RELATED FUNCTIONS ***/
65
66 /*
67  * Ask the user which physical disk they want.
68  * Changes ss->selected_disk if successful.
69  */
70 void
71 fn_select_disk(struct i_fn_args *a)
72 {
73         struct dfui_form *f;
74         struct dfui_action *k;
75         struct dfui_response *r;
76         struct disk *d;
77
78         f = dfui_form_create(
79             "select_disk",
80             _("Select Disk"),
81             a->short_desc,
82             "",
83
84             "p", "role",  "menu",
85             "p", "special", "dfinstaller_select_disk",
86
87             NULL
88         );
89
90         for (d = storage_disk_first(a->s); d != NULL; d = disk_next(d)) {
91                 dfui_form_action_add(f, disk_get_device_name(d),
92                     dfui_info_new(disk_get_desc(d), "", ""));
93         }
94
95         k = dfui_form_action_add(f, "cancel",
96             dfui_info_new(a->cancel_desc, "", ""));
97         dfui_action_property_set(k, "accelerator", "ESC");
98
99         if (!dfui_be_present(a->c, f, &r))
100                 abort_backend();
101
102         if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
103                 a->result = 0;
104         } else {
105                 d = disk_find(a->s, dfui_response_get_action_id(r));
106                 if (d == NULL) {
107                         inform(a->c, _("Internal error - response from frontend "
108                             "should be a valid device name."));
109                         a->result = 0;
110                 } else {
111                         storage_set_selected_disk(a->s, d);
112                         a->result = 1;
113                 }
114         }
115
116         dfui_form_free(f);
117         dfui_response_free(r);
118 }
119
120 /*
121  * Ask the user which slice on a the selected disk they want.
122  * Changes ss->selected_slice.
123  */
124 void
125 fn_select_slice(struct i_fn_args *a)
126 {
127         struct dfui_form *f;
128         struct dfui_action *k;
129         struct dfui_response *r;
130         struct slice *s;
131         char string[16];
132
133         f = dfui_form_create(
134             "select_slice",
135             _("Select Primary Partition"),
136             a->short_desc,
137             "",
138
139             "p", "role", "menu",
140             "p", "special", "dfinstaller_select_slice",
141
142             NULL
143         );
144
145         for (s = disk_slice_first(storage_get_selected_disk(a->s));
146              s != NULL; s = slice_next(s)) {
147                 snprintf(string, 16, "%d", slice_get_number(s));
148                 dfui_form_action_add(f, string,
149                     dfui_info_new(slice_get_desc(s), "", ""));
150         }
151
152         k = dfui_form_action_add(f, "cancel",
153             dfui_info_new(a->cancel_desc, "", ""));
154         dfui_action_property_set(k, "accelerator", "ESC");
155
156         if (!dfui_be_present(a->c, f, &r))
157                 abort_backend();
158
159         if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
160                 a->result = 0;
161         } else {
162                 s = slice_find(storage_get_selected_disk(a->s),
163                     atoi(dfui_response_get_action_id(r)));
164                 if (s == NULL) {
165                         inform(a->c, _("Internal error - response from frontend "
166                             "should be a valid slice number."));
167                         a->result = 0;
168                 } else {
169                         storage_set_selected_slice(a->s, s);
170                         a->result = 1;
171                 }
172         }
173
174         dfui_form_free(f);
175         dfui_response_free(r);
176 }
177
178 /*
179  * If ss->selected_disk == NULL, user will be asked for which disk.
180  * Returns 1 if disk was formatted, 0 if it wasn't.
181  * If it was, ss->selected_disk and ss->selected_slice are set to it.
182  */
183 void
184 fn_format_disk(struct i_fn_args *a)
185 {
186         struct commands *cmds;
187         char *selected_disk_string;
188
189         if (storage_get_selected_disk(a->s) == NULL) {
190                 a->short_desc = _("Select a disk to format.");
191                 a->cancel_desc = _("Return to Utilities Menu");
192                 fn_select_disk(a);
193                 if (!a->result || storage_get_selected_disk(a->s) == NULL) {
194                         a->result = 0;
195                         return;
196                 }
197         }
198
199         if (confirm_dangerous_action(a->c,
200             _("WARNING!  ALL data in ALL partitions on the disk\n\n"
201             "%s\n\nwill be IRREVOCABLY ERASED!\n\nAre you ABSOLUTELY "
202             "SURE you wish to take this action?  This is your "
203             "LAST CHANCE to cancel!"), disk_get_desc(storage_get_selected_disk(a->s)))) {
204                 cmds = commands_new();
205                         
206                 /*
207                  * Create the device node if it does not exist.
208                  */
209                 command_add_ensure_dev(a, cmds,
210                     disk_get_device_name(storage_get_selected_disk(a->s)));
211
212                 /*
213                  * Currently you need to pass 'yes' to OpenBSD's fdisk to
214                  * be able to do these.
215                  */
216 #if !defined(__OpenBSD__)
217                 command_add(cmds, "%s%s -I %s",
218                     a->os_root, cmd_name(a, "FDISK"),
219                     disk_get_raw_device_name(storage_get_selected_disk(a->s)));
220                 command_add(cmds, "%s%s | %s%s -B %s",
221                     a->os_root, cmd_name(a, "YES"),
222                     a->os_root, cmd_name(a, "FDISK"),
223                     disk_get_raw_device_name(storage_get_selected_disk(a->s)));
224 #endif
225                 if (!commands_execute(a, cmds)) {
226                         inform(a->c, _("The disk\n\n%s\n\nwas "
227                             "not correctly formatted, and may "
228                             "now be in an inconsistent state. "
229                             "We recommend re-formatting it "
230                             "before attempting to install "
231                             "%s on it."),
232                             disk_get_desc(storage_get_selected_disk(a->s)),
233                             OPERATING_SYSTEM_NAME);
234                         commands_free(cmds);
235                         a->result = 0;
236                         return;
237                 }
238                 commands_free(cmds);
239
240                 /*
241                  * Since one of the disks has now changed, we must
242                  * refresh our view of them and re-select the disk
243                  * since the selected_disk pointer will be invalidated.
244                  */
245                 selected_disk_string = aura_strdup(
246                     disk_get_device_name(storage_get_selected_disk(a->s)));
247                 if (!survey_storage(a)) {
248                         inform(a->c, _("Errors occurred while probing "
249                             "the system for its storage capabilities."));
250                 }
251                 storage_set_selected_disk(a->s, disk_find(a->s, selected_disk_string));
252                 free(selected_disk_string);
253
254                 /*
255                  * Note that we formatted this disk and that we want
256                  * to use the first (and only) slice of it.
257                  */
258                 disk_set_formatted(storage_get_selected_disk(a->s), 1);
259                 storage_set_selected_slice(a->s, disk_slice_first(storage_get_selected_disk(a->s)));
260
261                 if (!format_slice(a)) {
262                         inform(a->c, _("The sole primary partition of "
263                             "the disk\n\n%s\n\nwas "
264                             "not correctly formatted, and may "
265                             "now be in an inconsistent state. "
266                             "We recommend re-formatting the "
267                             "disk before attempting to install "
268                             "%s on it."),
269                             disk_get_desc(storage_get_selected_disk(a->s)),
270                             OPERATING_SYSTEM_NAME);
271                         a->result = 0;
272                         return;
273                 }
274
275                 inform(a->c, _("The disk\n\n%s\n\nwas formatted."),
276                     disk_get_desc(storage_get_selected_disk(a->s)));
277                 a->result = 1;
278         } else {
279                 inform(a->c, _("Action cancelled - no disks were formatted."));
280                 a->result = 0;
281         }
282 }
283
284 /*
285  * Wipes the start of the selected disk.
286  */
287 void
288 fn_wipe_start_of_disk(struct i_fn_args *a)
289 {
290         struct commands *cmds;
291
292         a->short_desc = _("If you are having problems formatting a disk, "
293             "it may be because of junk that has accumulated "
294             "in the boot block and the partition table. "
295             "A cure for this is to wipe out everything on "
296             "the first few sectors of the disk.  However, this "
297             "is a rather drastic action to take, so it is not "
298             "recommended unless you are otherwise "
299             "encountering problems.");
300         a->cancel_desc = _("Return to Utilities Menu");
301         fn_select_disk(a);
302         if (!a->result)
303                 return;
304
305         /* XXX check to make sure no slices on this disk are mounted first? */
306         if (storage_get_selected_disk(a->s) != NULL && confirm_dangerous_action(a->c,
307             _("WARNING!  ALL data in ALL partitions on the disk\n\n"
308             "%s\n\nwill be IRREVOCABLY ERASED!\n\nAre you ABSOLUTELY "
309             "SURE you wish to take this action?  This is your "
310             "LAST CHANCE to cancel!"), disk_get_desc(storage_get_selected_disk(a->s)))) {
311                 cmds = commands_new();
312                 command_add(cmds,
313                     "%s%s if=%sdev/zero of=%sdev/%s bs=32k count=16",
314                     a->os_root, cmd_name(a, "DD"),
315                     a->os_root, a->os_root,
316                     disk_get_raw_device_name(storage_get_selected_disk(a->s)));
317                 if (commands_execute(a, cmds)) {
318                         inform(a->c, _("Start of disk was successfully wiped."));
319                 } else {
320                         inform(a->c, _("Some errors occurred. "
321                             "Start of disk was not successfully wiped."));
322                 }
323                 commands_free(cmds);
324         }
325 }
326
327 /*
328  * Wipes the start of the selected slice.
329  */
330 void
331 fn_wipe_start_of_slice(struct i_fn_args *a)
332 {
333         struct commands *cmds;
334
335         a->short_desc =
336           _("If you are having problems formatting a primary partition, "
337             "it may be because of junk that has accumulated in the "
338             "partition's `disklabel'. A cure for this is to wipe out "
339             "everything on the first few sectors of the primary partition. "
340             "However, this is a rather drastic action to take, so it is not "
341             "recommended unless you are otherwise encountering problems.");
342         a->cancel_desc = _("Return to Utilities Menu");
343         fn_select_slice(a);
344         if (!a->result)
345                 return;
346
347         if (confirm_dangerous_action(a->c,
348             _("WARNING!  ALL data in primary partition #%d,\n\n%s\n\non the "
349             "disk\n\n%s\n\n will be IRREVOCABLY ERASED!\n\nAre you "
350             "ABSOLUTELY SURE you wish to take this action?  This is "
351             "your LAST CHANCE to cancel!"),
352             slice_get_number(storage_get_selected_slice(a->s)),
353             slice_get_desc(storage_get_selected_slice(a->s)),
354             disk_get_desc(storage_get_selected_disk(a->s)))) {
355                 /* XXX check to make sure this slice is not mounted first */
356                 cmds = commands_new();
357                 command_add(cmds, "%s%s if=%sdev/zero of=%sdev/%s bs=32k count=16",
358                     a->os_root, cmd_name(a, "DD"),
359                     a->os_root, a->os_root,
360                     slice_get_raw_device_name(storage_get_selected_slice(a->s)));
361                 if (commands_execute(a, cmds)) {
362                         inform(a->c, _("Start of primary partition was successfully wiped."));
363                 } else {
364                         inform(a->c, _("Some errors occurred. "
365                             "Start of primary partition was not successfully wiped."));
366                 }
367                 commands_free(cmds);
368         }
369 }
370
371 static void
372 ask_to_wipe_boot_sector(struct i_fn_args *a, struct commands *fcmds)
373 {
374         struct commands *cmds;
375         struct command *cmd;
376         char *disk;
377
378         for (cmd = command_get_first(fcmds); cmd != NULL;
379              cmd = command_get_next(cmd)) {
380                 disk = command_get_tag(cmd);
381                 if (disk != NULL &&
382                     command_get_result(cmd) > 0 &&
383                     command_get_result(cmd) < 256) {
384                         switch (dfui_be_present_dialog(a->c,
385                             _("Bootblock Install Failed"),
386                             _("Re-Initialize Bootblock|Cancel"),
387                             _("Warning: bootblocks were not successfully "
388                             "installed on the disk `%s'. This may be "
389                             "because the disk is new and not yet "
390                             "formatted. If this is the case, it might "
391                             "help to re-initialize the boot sector, "
392                             "then try installing the bootblock again. "
393                             "Note that this should not affect the "
394                             "partition table of the disk."),
395                             disk, disk)) {
396                         case 1:
397                                 cmds = commands_new();
398                                 command_add(cmds,
399                                     "%s%s | %s%s -B %sdev/%s",
400                                     a->os_root, cmd_name(a, "YES"),
401                                     a->os_root, cmd_name(a, "FDISK"),
402                                     a->os_root, disk);
403                                 if (commands_execute(a, cmds)) {
404                                         inform(a->c, _("Boot sector successfully initialized."));
405                                 } else {
406                                         inform(a->c, _("Some errors occurred. "
407                                             "Boot sector was not successfully initialized."));
408                                 }
409                                 commands_free(cmds);
410                                 break;
411                         default:
412                                 break;
413                         }
414                 }
415         }
416 }
417
418 void
419 fn_install_bootblocks(struct i_fn_args *a)
420 {
421         struct dfui_form *f;
422         struct dfui_response *r;
423         struct dfui_dataset *ds;
424         struct disk *d;
425         struct commands *cmds;
426         struct command *cmd;
427         char disk[64], boot0cfg[32], packet[32];
428         char msg_buf[1][1024];
429
430         snprintf(msg_buf[0], sizeof(msg_buf[0]),
431             "'Packet Mode' refers to using newer BIOS calls to boot "
432             "from a partition of the disk.  It is generally not "
433             "required unless:\n\n"
434             "- your BIOS does not support legacy mode; or\n"
435             "- your %s primary partition resides on a "
436             "cylinder of the disk beyond cylinder 1024; or\n"
437             "- you just can't get it to boot without it.",
438             OPERATING_SYSTEM_NAME);
439
440         f = dfui_form_create(
441             "install_bootstrap",
442             _("Install Bootblock(s)"),
443             a->short_desc,
444
445             msg_buf[0],
446
447             "p", "special", "dfinstaller_install_bootstrap",
448
449             "f", "disk", _("Disk Drive"),
450             _("The disk on which you wish to install a bootblock"), "",
451             "p", "editable", "false",
452             "f", "boot0cfg", _("Install Bootblock?"),
453             _("Install a bootblock on this disk"), "",
454             "p", "control", "checkbox",
455             "f", "packet", _("Packet Mode?"),
456             _("Select this to use 'packet mode' to boot the disk"), "",
457             "p", "control", "checkbox",
458         
459             "a", "ok", _("Accept and Install Bootblocks"), "", "",
460             "a", "cancel", a->cancel_desc, "", "", 
461             "p", "accelerator", "ESC",
462
463             NULL
464         );
465
466         dfui_form_set_multiple(f, 1);
467
468         for (d = storage_disk_first(a->s); d != NULL; d = disk_next(d)) {
469                 ds = dfui_dataset_new();
470                 /* XXX need to see how this is handled in OpenBSD/NetBSD */
471                 dfui_dataset_celldata_add(ds, "disk", disk_get_raw_device_name(d));
472                 dfui_dataset_celldata_add(ds, "boot0cfg", "Y");
473                 dfui_dataset_celldata_add(ds, "packet", autopacket(d) == 1 ? "Y" : "N");
474                 dfui_form_dataset_add(f, ds);
475         }
476
477         if (!dfui_be_present(a->c, f, &r))
478                 abort_backend();
479
480         a->result = 0;
481         if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
482                 cmds = commands_new();
483
484                 for (ds = dfui_response_dataset_get_first(r); ds != NULL;
485                      ds = dfui_dataset_get_next(ds)) {
486                         strlcpy(disk, dfui_dataset_get_value(ds, "disk"), 64);
487                         strlcpy(boot0cfg, dfui_dataset_get_value(ds, "boot0cfg"), 32);
488                         strlcpy(packet, dfui_dataset_get_value(ds, "packet"), 32);
489
490                         if (strcasecmp(boot0cfg, "Y") == 0) {
491                                 cmd = command_add(cmds, "%s%s -B %s %s",
492                                     a->os_root, cmd_name(a, "BOOT0CFG"),
493                                     strcasecmp(packet, "Y") == 0 ? "-o packet" : "",
494                                     disk);
495                                 command_set_failure_mode(cmd, COMMAND_FAILURE_WARN);
496                                 command_set_tag(cmd, disk);
497                                 cmd = command_add(cmds, "%s%s -v %s",
498                                     a->os_root, cmd_name(a, "BOOT0CFG"),
499                                     disk);
500                                 command_set_failure_mode(cmd, COMMAND_FAILURE_WARN);
501                                 command_set_tag(cmd, disk);
502                         }
503                 }
504
505                 if (!commands_execute(a, cmds)) {
506                         ask_to_wipe_boot_sector(a, cmds);
507                 } else {
508                         inform(a->c, _("Bootblocks were successfully installed!"));
509                         a->result = 1;
510                 }
511                 commands_free(cmds);
512         }
513
514         dfui_form_free(f);
515         dfui_response_free(r);
516 }
517
518 void
519 fn_format_msdos_floppy(struct i_fn_args *a)
520 {
521         struct commands *cmds;
522
523         switch (dfui_be_present_dialog(a->c, _("Format MSDOS Floppy"),
524             _("Format Floppy|Return to Utilities Menu"),
525             _("Please insert the floppy to be formatted "
526             "in unit 0 (``drive A:'')."))) {
527         case 1:
528                 cmds = commands_new();
529                 command_add(cmds, "%s%s -y -f 1440 /dev/fd0",
530                     a->os_root, cmd_name(a, "FDFORMAT"));
531                 command_add(cmds, "%s%s -f 1440 fd0",
532                     a->os_root, cmd_name(a, "NEWFS_MSDOS"));
533                 if (commands_execute(a, cmds))
534                         inform(a->c, _("Floppy successfully formatted!"));
535                 else
536                         inform(a->c, _("Floppy was not successfully formatted."));
537                 break;
538         case 2:
539                 return;
540         default:
541                 abort_backend();
542         }
543 }
544
545 void
546 fn_create_cdboot_floppy(struct i_fn_args *a)
547 {
548         struct commands *cmds;
549         char msg_buf[1][1024];
550
551         snprintf(msg_buf[0], sizeof(msg_buf[0]),
552             "%s cannot be installed from a floppy; "
553             "it must be installed from a booted CD-ROM. "
554             "However, many older systems do not support booting "
555             "from a CD-ROM. For these systems, a boot disk can be "
556             "created. This boot disk contains the Smart Boot "
557             "Manager program, which can boot a CD-ROM even "
558             "on systems with BIOSes which do not support booting "
559             "from the CD-ROM.\n\n"
560             "Smart Boot Manager is not a part of %s; "
561             "the Smart Boot Manager project can be found here:\n\n"
562             "http://btmgr.sourceforge.net/\n\n"
563             "To create a CDBoot floppy, insert a blank floppy "
564             "in unit 0 (``drive A:'') before proceeding."
565             "",
566             OPERATING_SYSTEM_NAME, OPERATING_SYSTEM_NAME);
567
568         switch (dfui_be_present_dialog(a->c, _("Create CDBoot Floppy"),
569             _("Create CDBoot Floppy|Return to Utilities Menu"),
570             msg_buf[0])) {
571         case 1:
572                 cmds = commands_new();
573                 command_add(cmds, "%s%s -c %sboot/cdboot.flp.bz2 | "
574                     "%s%s of=%sdev/fd0 bs=32k",
575                     a->os_root, cmd_name(a, "BUNZIP2"),
576                     a->os_root,
577                     a->os_root, cmd_name(a, "DD"),
578                     a->os_root);
579                 if (commands_execute(a, cmds))
580                         inform(a->c, _("CDBoot floppy successfully created!"));
581                 else
582                         inform(a->c, _("CDBoot floppy was not successfully created."));
583                 break;
584         case 2:
585                 return;
586         default:
587                 abort_backend();
588         }
589 }
590
591 void
592 fn_create_memtest86_floppy(struct i_fn_args *a)
593 {
594         struct commands *cmds;
595
596         switch (dfui_be_present_dialog(a->c, _("Create memtest86 Floppy"),
597             "Create memtest86 Floppy|Return to Utilities Menu",
598             "While this installer allows you to test memory "
599             "on-line, the fact that the installer and operating "
600             "system are already loaded means that the memory "
601             "test has certain limits.  For a more thorough "
602             "memory test, you can create a floppy containing "
603             "the memtest86 program, which boots up independently "
604             "of any operating system, allowing it access to "
605             "almost the entire memory of the computer for testing.\n\n"
606             "memtest86 is not a part of %s; "
607             "the memtest86 project can be found here:\n\n"
608             "http://www.memtest86.com/\n\n"
609             "To create a memtest86 floppy, insert a blank floppy "
610             "in unit 0 (``drive A:'') before proceeding."
611             "", OPERATING_SYSTEM_NAME)) {
612         case 1:
613                 cmds = commands_new();
614                 command_add(cmds, "%s%s -c %sboot/memtest86.flp.bz2 | "
615                     "%s%s of=%sdev/fd0 bs=32k",
616                     a->os_root, cmd_name(a, "BUNZIP2"),
617                     a->os_root,
618                     a->os_root, cmd_name(a, "DD"),
619                     a->os_root);
620                 if (commands_execute(a, cmds))
621                         inform(a->c, _("memtest86 floppy successfully created!"));
622                 else
623                         inform(a->c, _("memtest86 floppy was not successfully created."));
624                 break;
625         case 2:
626                 return;
627         default:
628                 abort_backend();
629         }
630 }
631
632 /**** NON-fn_ FUNCTIONS ***/
633
634 int
635 format_slice(struct i_fn_args *a)
636 {
637         struct commands *cmds;
638         int result;
639         int cyl, hd, sec;
640
641         cmds = commands_new();
642
643         /*
644          * Create the device node if it does not exist.
645          */
646         command_add_ensure_dev(a, cmds,
647             slice_get_device_name(storage_get_selected_slice(a->s)));
648
649         /*
650          * The information in a->s NEEDS to be accurate here!
651          * Presumably we just did a survey_storage() recently.
652          * XXX should we do another one here anyway just to be paranoid?
653          */
654
655         /*
656          * Set the slice's sysid to 165.
657          */
658         disk_get_geometry(storage_get_selected_disk(a->s), &cyl, &hd, &sec);
659         command_add(cmds, "%s%s 'g c%d h%d s%d' >%snew.fdisk",
660             a->os_root, cmd_name(a, "ECHO"),
661             cyl, hd, sec,
662             a->tmp);
663         command_add(cmds, "%s%s 'p %d %d %lu %lu' >>%snew.fdisk",
664             a->os_root, cmd_name(a, "ECHO"),
665             slice_get_number(storage_get_selected_slice(a->s)),
666             165,
667             slice_get_start(storage_get_selected_slice(a->s)),
668             slice_get_size(storage_get_selected_slice(a->s)),
669             a->tmp);
670         if (slice_get_flags(storage_get_selected_slice(a->s)) & 0x80) {
671                 command_add(cmds, "%s%s 'a %d' >>%snew.fdisk",
672                     a->os_root, cmd_name(a, "ECHO"),
673                     slice_get_number(storage_get_selected_slice(a->s)),
674                     a->tmp);
675         }
676
677         command_add(cmds, "%s%s %snew.fdisk",
678             a->os_root, cmd_name(a, "CAT"), a->tmp);
679         temp_file_add(a, "new.fdisk");
680
681         /*
682          * Execute the fdisk script.
683          */
684         command_add(cmds, "%s%s -v -f %snew.fdisk %s",
685             a->os_root, cmd_name(a, "FDISK"), a->tmp,
686             disk_get_raw_device_name(storage_get_selected_disk(a->s)));
687
688         /*
689          * Auto-disklabel the slice.
690          * NB: one cannot use "/dev/adXsY" here -
691          * it must be in the form "adXsY".
692          */
693         command_add(cmds, "%s%s -B -r -w %s auto",
694             a->os_root, cmd_name(a, "DISKLABEL"),
695             slice_get_raw_device_name(storage_get_selected_slice(a->s)));
696
697         /*
698          * If there is an old 'virgin' disklabel hanging around
699          * in the temp dir, get rid of it.  This won't happen
700          * from a real CD, but might happen with '-o' installs.
701          */
702         command_add(cmds, "%s%s -f %sinstall.disklabel.%s",
703             a->os_root, cmd_name(a, "RM"),
704             a->tmp,
705             slice_get_device_name(storage_get_selected_slice(a->s)));
706
707         result = commands_execute(a, cmds);
708
709         commands_free(cmds);
710
711         return(result);
712 }
713
714 int
715 autopacket(struct disk *d) {
716         struct slice *p;
717         long tcap = 0;
718         
719         for (p = disk_slice_first(d); p != NULL; p = slice_next(p)) {
720                 tcap += slice_get_capacity(p);
721                 if (tcap > 8 * 1024)
722                         return(1);
723         }
724         return(0);
725 }