aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/sade/help/partition.hlp27
-rw-r--r--usr.sbin/sade/install.c91
-rw-r--r--usr.sbin/sade/label.c200
-rw-r--r--usr.sbin/sade/sade.h37
-rw-r--r--usr.sbin/sysinstall/help/partition.hlp27
-rw-r--r--usr.sbin/sysinstall/install.c91
-rw-r--r--usr.sbin/sysinstall/label.c200
-rw-r--r--usr.sbin/sysinstall/sysinstall.h37
8 files changed, 572 insertions, 138 deletions
diff --git a/usr.sbin/sade/help/partition.hlp b/usr.sbin/sade/help/partition.hlp
index ef328df0e3c4..19cfb5abc592 100644
--- a/usr.sbin/sade/help/partition.hlp
+++ b/usr.sbin/sade/help/partition.hlp
@@ -126,6 +126,33 @@ with significant activity can temporarily overflow if the soft updates
policy results in free'd blocks not being "garbage collected" as fast
as they're being requested.
+To make use of UFS2, press '2' on a UFS file system to toggle the
+on-disk format revision. UFS2 provides native support for extended
+attributes, larger disk sizes, and forward compatibility with new
+on-disk high performance directory layout and storage extents.
+However, UFS2 is unsupported on versions of FreeBSD prior to 5.0,
+so it is not recommended for environments requiring backward
+compatibility. Also, UFS2 is not currently recommended as a root
+file system format for non-64-bit platforms due to increased size
+of the boot loader; special local configuration is required to boot
+UFS2 as a root file system on i386 and PC98.
+
+To add additional flags to the newfs command line for UFS file
+systems, press 'N'. These options will be specified before the
+device argument of the command line, but after any other options
+placed there by sysinstall, such as the UFS version and soft
+updates flag; as such, arguments provided may override existing
+settings. To completely replace the newfs command used by
+sysinstall, press 'Z' to convert a partition to a Custom
+partition type. Sysinstall will prompt you with the newfs
+command line that it would have used based on existing settings
+prior to the change, but allow you to modify any aspect of the
+command line. Once a partition has been converted to a custom
+partition in the label editor, you will need to restart the
+labeling process or delete and recreate the partition to restore
+it to a non-custom state. Custom partitions are represented by
+the letters "CST" instead of "UFS" or "FAT.
+
When you're done, type `Q' to exit.
No actual changes will be made to the disk until you (C)ommit from the
diff --git a/usr.sbin/sade/install.c b/usr.sbin/sade/install.c
index 9862e5627a79..e1763ec8b424 100644
--- a/usr.sbin/sade/install.c
+++ b/usr.sbin/sade/install.c
@@ -50,6 +50,7 @@
#undef MSDOSFS
#include <sys/stat.h>
#include <sys/sysctl.h>
+#include <limits.h>
#include <unistd.h>
#include <termios.h>
@@ -878,6 +879,44 @@ installFixupXFree(dialogMenuItem *self)
return DITEM_SUCCESS | DITEM_RESTORE;
}
+#define QUEUE_YES 1
+#define QUEUE_NO 0
+static int
+performNewfs(PartInfo *pi, char *dname, int queue)
+{
+ char buffer[LINE_MAX];
+
+ if (pi->do_newfs) {
+ switch(pi->newfs_type) {
+ case NEWFS_UFS:
+ snprintf(buffer, LINE_MAX, "%s %s %s %s %s",
+ NEWFS_UFS_CMD,
+ pi->newfs_data.newfs_ufs.softupdates ? "-U" : "",
+ pi->newfs_data.newfs_ufs.ufs2 ? "-O2" : "-O1",
+ pi->newfs_data.newfs_ufs.user_options,
+ dname);
+ break;
+
+ case NEWFS_MSDOS:
+ snprintf(buffer, LINE_MAX, "%s %s", NEWFS_MSDOS_CMD,
+ dname);
+ break;
+
+ case NEWFS_CUSTOM:
+ snprintf(buffer, LINE_MAX, "%s %s",
+ pi->newfs_data.newfs_custom.command, dname);
+ break;
+ }
+
+ if (queue == QUEUE_YES) {
+ command_shell_add(pi->mountpoint, buffer);
+ return (0);
+ } else
+ return (vsystem(buffer));
+ }
+ return (0);
+}
+
/* Go newfs and/or mount all the filesystems we've been asked to */
int
installFilesystems(dialogMenuItem *self)
@@ -940,12 +979,14 @@ installFilesystems(dialogMenuItem *self)
if (strcmp(root->mountpoint, "/"))
msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", rootdev->name, root->mountpoint);
- if (root->newfs && (!upgrade || !msgNoYes("You are upgrading - are you SURE you want to newfs the root partition?"))) {
+ if (root->do_newfs && (!upgrade ||
+ !msgNoYes("You are upgrading - are you SURE you want to newfs "
+ "the root partition?"))) {
int i;
dialog_clear_norefresh();
msgNotify("Making a new root filesystem on %s", dname);
- i = vsystem("%s %s", root->newfs_cmd, dname);
+ i = performNewfs(root, dname, QUEUE_NO);
if (i) {
msgConfirm("Unable to make new root filesystem on %s!\n"
"Command returned status %d", dname, i);
@@ -964,10 +1005,17 @@ installFilesystems(dialogMenuItem *self)
msgConfirm("Warning: fsck returned status of %d for %s.\n"
"This partition may be unsafe to use.", i, dname);
}
- if (root->soft) {
- i = vsystem("tunefs -n enable %s", dname);
- if (i)
- msgConfirm("Warning: Unable to enable softupdates for root filesystem on %s", dname);
+
+ /*
+ * If soft updates was enabled in the editor but we didn't newfs,
+ * use tunefs to update the soft updates flag on the file system.
+ */
+ if (!root->do_newfs && root->newfs_type == NEWFS_UFS &&
+ root->newfs_data.newfs_ufs.softupdates) {
+ i = vsystem("tunefs -n enable %s", dname);
+ if (i)
+ msgConfirm("Warning: Unable to enable soft updates"
+ " for root file system on %s", dname);
}
/* Switch to block device */
@@ -1021,12 +1069,23 @@ installFilesystems(dialogMenuItem *self)
if (c2 == rootdev)
continue;
- if (tmp->newfs && (!upgrade || !msgNoYes("You are upgrading - are you SURE you want to newfs /dev/%s?", c2->name)))
- command_shell_add(tmp->mountpoint, "%s %s/dev/%s", tmp->newfs_cmd, RunningAsInit ? "/mnt" : "", c2->name);
+ sprintf(dname, "%s/dev/%s",
+ RunningAsInit ? "/mnt" : "", c2->name);
+
+ if (tmp->do_newfs && (!upgrade ||
+ !msgNoYes("You are upgrading - are you SURE you"
+ " want to newfs /dev/%s?", c2->name)))
+ performNewfs(tmp, dname, QUEUE_YES);
else
- command_shell_add(tmp->mountpoint, "fsck_ffs -y %s/dev/%s", RunningAsInit ? "/mnt" : "", c2->name);
+ command_shell_add(tmp->mountpoint,
+ "fsck_ffs -y %s/dev/%s", RunningAsInit ?
+ "/mnt" : "", c2->name);
+#if 0
if (tmp->soft)
- command_shell_add(tmp->mountpoint, "tunefs -n enable %s/dev/%s", RunningAsInit ? "/mnt" : "", c2->name);
+ command_shell_add(tmp->mountpoint,
+ "tunefs -n enable %s/dev/%s", RunningAsInit ?
+ "/mnt" : "", c2->name);
+#endif
command_func_add(tmp->mountpoint, Mount, c2->name);
}
else if (c2->type == part && c2->subtype == FS_SWAP) {
@@ -1047,7 +1106,8 @@ installFilesystems(dialogMenuItem *self)
}
}
}
- else if (c1->type == fat && c1->private_data && (root->newfs || upgrade)) {
+ else if (c1->type == fat && c1->private_data &&
+ (root->do_newfs || upgrade)) {
char name[FILENAME_MAX];
sprintf(name, "%s/%s", RunningAsInit ? "/mnt" : "", ((PartInfo *)c1->private_data)->mountpoint);
@@ -1059,8 +1119,13 @@ installFilesystems(dialogMenuItem *self)
PartInfo *pi = (PartInfo *)c1->private_data;
char *p;
- if (pi->newfs && (!upgrade || !msgNoYes("You are upgrading - are you SURE you want to newfs /dev/%s?", c1->name)))
- command_shell_add(pi->mountpoint, "%s %s/dev/%s", pi->newfs_cmd, RunningAsInit ? "/mnt" : "", c1->name);
+ sprintf(dname, "%s/dev/%s", RunningAsInit ? "/mnt" : "",
+ c1->name);
+
+ if (pi->do_newfs && (!upgrade ||
+ !msgNoYes("You are upgrading - are you SURE you want to "
+ "newfs /dev/%s?", c1->name)))
+ performNewfs(pi, dname, QUEUE_YES);
command_func_add(pi->mountpoint, Mount_msdosfs, c1->name);
diff --git a/usr.sbin/sade/label.c b/usr.sbin/sade/label.c
index 7964545a50d8..860e16a5a3f4 100644
--- a/usr.sbin/sade/label.c
+++ b/usr.sbin/sade/label.c
@@ -322,36 +322,42 @@ record_label_chunks(Device **devs, Device *dev)
static PartInfo *
new_part(char *mpoint, Boolean newfs)
{
- PartInfo *ret;
+ PartInfo *pi;
if (!mpoint)
mpoint = "/change_me";
- ret = (PartInfo *)safe_malloc(sizeof(PartInfo));
- sstrncpy(ret->mountpoint, mpoint, FILENAME_MAX);
- strcpy(ret->newfs_cmd, "newfs ");
- strcat(ret->newfs_cmd, variable_get(VAR_NEWFS_ARGS));
- ret->newfs = newfs;
- ret->soft = strcmp(mpoint, "/") ? 1 : 0;
- return ret;
+ pi = (PartInfo *)safe_malloc(sizeof(PartInfo));
+ sstrncpy(pi->mountpoint, mpoint, FILENAME_MAX);
+
+ pi->do_newfs = newfs;
+
+ pi->newfs_type = NEWFS_UFS;
+ strcpy(pi->newfs_data.newfs_ufs.user_options, "");
+ pi->newfs_data.newfs_ufs.acls = FALSE;
+ pi->newfs_data.newfs_ufs.multilabel = FALSE;
+ pi->newfs_data.newfs_ufs.softupdates = strcmp(mpoint, "/");
+ pi->newfs_data.newfs_ufs.ufs2 = FALSE;
+
+ return pi;
}
#if defined(__ia64__)
static PartInfo *
new_efi_part(char *mpoint, Boolean newfs)
{
- PartInfo *ret;
+ PartInfo *pi;
if (!mpoint)
mpoint = "/efi";
- ret = (PartInfo *)safe_malloc(sizeof(PartInfo));
- sstrncpy(ret->mountpoint, mpoint, FILENAME_MAX);
- /* XXX */
- strcpy(ret->newfs_cmd, "newfs_msdos ");
- ret->newfs = newfs;
- ret->soft = 0;
- return ret;
+ pi = (PartInfo *)safe_malloc(sizeof(PartInfo));
+ sstrncpy(pi->mountpoint, mpoint, FILENAME_MAX);
+
+ pi->do_newfs = newfs;
+ pi->newfs_type = NEWFS_MSDOS;
+
+ return pi;
}
#endif
@@ -404,7 +410,7 @@ get_mountpoint(struct chunk *old)
newfs = TRUE;
if (tmp) {
- newfs = tmp->newfs;
+ newfs = tmp->do_newfs;
safe_free(tmp);
}
val = string_skipwhite(string_prune(val));
@@ -448,13 +454,49 @@ get_partition_type(void)
static void
getNewfsCmd(PartInfo *p)
{
+ char buffer[NEWFS_CMD_ARGS_MAX];
char *val;
- val = msgGetInput(p->newfs_cmd,
- "Please enter the newfs command and options you'd like to use in\n"
- "creating this file system.");
- if (val)
- sstrncpy(p->newfs_cmd, val, NEWFS_CMD_MAX);
+ switch (p->newfs_type) {
+ case NEWFS_UFS:
+ snprintf(buffer, NEWFS_CMD_ARGS_MAX, "%s %s %s %s",
+ NEWFS_UFS_CMD, p->newfs_data.newfs_ufs.softupdates ? "-U" : "",
+ p->newfs_data.newfs_ufs.ufs2 ? "-O2" : "-O1",
+ p->newfs_data.newfs_ufs.user_options);
+ break;
+ case NEWFS_MSDOS:
+ snprintf(buffer, NEWFS_CMD_ARGS_MAX, "%s", NEWFS_MSDOS_CMD);
+ break;
+ case NEWFS_CUSTOM:
+ strcpy(buffer, p->newfs_data.newfs_custom.command);
+ break;
+ }
+
+ val = msgGetInput(buffer,
+ "Please enter the newfs command and options you'd like to use in\n"
+ "creating this file system.");
+ if (val != NULL) {
+ p->newfs_type = NEWFS_CUSTOM;
+ strlcpy(p->newfs_data.newfs_custom.command, val, NEWFS_CMD_ARGS_MAX);
+ }
+}
+
+static void
+getNewfsOptionalArguments(PartInfo *p)
+{
+ char buffer[NEWFS_CMD_ARGS_MAX];
+ char *val;
+
+ /* Must be UFS, per argument checking in I/O routines. */
+
+ strlcpy(buffer, p->newfs_data.newfs_ufs.user_options,
+ NEWFS_CMD_ARGS_MAX);
+ val = msgGetInput(buffer,
+ "Please enter any additional UFS newfs options you'd like to\n"
+ "use in creating this file system.");
+ if (val != NULL)
+ strlcpy(p->newfs_data.newfs_ufs.user_options, val,
+ NEWFS_CMD_ARGS_MAX);
}
#define MAX_MOUNT_NAME 9
@@ -473,7 +515,7 @@ getNewfsCmd(PartInfo *p)
static void
print_label_chunks(void)
{
- int i, j, srow, prow, pcol;
+ int i, j, spaces, srow, prow, pcol;
int sz;
char clrmsg[80];
int ChunkPartStartRow;
@@ -581,7 +623,7 @@ print_label_chunks(void)
}
/* Otherwise it's a DOS, swap or filesystem entry in the Chunk window */
else {
- char onestr[PART_OFF], num[10], *mountpoint, newfs[10];
+ char onestr[PART_OFF], num[10], *mountpoint, newfs[12];
/*
* We copy this into a blank-padded string so that it looks like
@@ -626,18 +668,34 @@ print_label_chunks(void)
label_chunk_info[i].c->type == efi) {
strcat(newfs, " ");
PartInfo *pi = (PartInfo *)label_chunk_info[i].c->private_data;
- strcat(newfs, pi->newfs ? " Y" : " N");
+ strcat(newfs, pi->do_newfs ? " Y" : " N");
}
#endif
}
else if (label_chunk_info[i].c->private_data && label_chunk_info[i].type == PART_FILESYSTEM) {
- strcpy(newfs, "UFS");
- strcat(newfs,
- ((PartInfo *)label_chunk_info[i].c->private_data)->soft ?
- "+S" : " ");
- strcat(newfs,
- ((PartInfo *)label_chunk_info[i].c->private_data)->newfs ?
- " Y" : " N");
+ PartInfo *pi = (PartInfo *)label_chunk_info[i].c->private_data;
+
+ switch (pi->newfs_type) {
+ case NEWFS_UFS:
+ strcpy(newfs, NEWFS_UFS_STRING);
+ if (pi->newfs_data.newfs_ufs.ufs2)
+ strcat(newfs, "2");
+ else
+ strcat(newfs, "1");
+ if (pi->newfs_data.newfs_ufs.softupdates)
+ strcat(newfs, "+S");
+ else
+ strcat(newfs, " ");
+
+ break;
+ case NEWFS_MSDOS:
+ strcpy(newfs, "FAT");
+ break;
+ case NEWFS_CUSTOM:
+ strcpy(newfs, "CUST");
+ break;
+ }
+ strcat(newfs, pi->do_newfs ? " Y" : " N ");
}
else if (label_chunk_info[i].type == PART_SWAP)
strcpy(newfs, "SWAP");
@@ -695,9 +753,9 @@ print_command_summary(void)
mvprintw(17, 0, "The following commands are valid here (upper or lower case):");
mvprintw(18, 0, "C = Create D = Delete M = Mount pt.");
if (!RunningAsInit)
- mvprintw(18, 47, "W = Write");
- mvprintw(19, 0, "N = Newfs Opts Q = Finish S = Toggle SoftUpdates");
- mvprintw(20, 0, "T = Toggle Newfs U = Undo A = Auto Defaults R = Delete+Merge");
+ mvprintw(18, 56, "W = Write");
+ mvprintw(19, 0, "N = Newfs Opts Q = Finish S = Toggle SoftUpdates Z = Custom Newfs");
+ mvprintw(20, 0, "T = Toggle Newfs U = Undo A = Auto Defaults R = Delete+Merge");
mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to select.");
move(0, 0);
}
@@ -799,6 +857,27 @@ diskLabel(Device *dev)
clear_wins();
break;
+ case '2':
+ if (label_chunk_info[here].type == PART_FILESYSTEM) {
+ PartInfo *pi =
+ ((PartInfo *)label_chunk_info[here].c->private_data);
+
+ if ((pi != NULL) &&
+ (pi->newfs_type == NEWFS_UFS)) {
+#ifdef __i386__
+ if (label_chunk_info[here].c->flags & CHUNK_IS_ROOT)
+ msg = MSG_NOT_APPLICABLE;
+ else
+#endif
+ pi->newfs_data.newfs_ufs.ufs2 =
+ !pi->newfs_data.newfs_ufs.ufs2;
+ } else
+ msg = MSG_NOT_APPLICABLE;
+ } else
+ msg = MSG_NOT_APPLICABLE;
+ break;
+ break;
+
case 'A':
if (label_chunk_info[here].type != PART_SLICE) {
msg = "You can only do this in a disk slice (at top of screen)";
@@ -987,7 +1066,7 @@ diskLabel(Device *dev)
p = get_mountpoint(label_chunk_info[here].c);
if (p) {
if (!oldp)
- p->newfs = FALSE;
+ p->do_newfs = FALSE;
if (label_chunk_info[here].type == PART_FAT
&& (!strcmp(p->mountpoint, "/") || !strcmp(p->mountpoint, "/usr")
|| !strcmp(p->mountpoint, "/var"))) {
@@ -1009,8 +1088,9 @@ diskLabel(Device *dev)
case 'N': /* Set newfs options */
if (label_chunk_info[here].c->private_data &&
- ((PartInfo *)label_chunk_info[here].c->private_data)->newfs)
- getNewfsCmd(label_chunk_info[here].c->private_data);
+ ((PartInfo *)label_chunk_info[here].c->private_data)->do_newfs)
+ getNewfsOptionalArguments(
+ label_chunk_info[here].c->private_data);
else
msg = MSG_NOT_APPLICABLE;
clear_wins();
@@ -1019,8 +1099,10 @@ diskLabel(Device *dev)
case 'S': /* Toggle soft updates flag */
if (label_chunk_info[here].type == PART_FILESYSTEM) {
PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data);
- if (pi)
- pi->soft = !pi->soft;
+ if (pi != NULL &&
+ pi->newfs_type == NEWFS_UFS)
+ pi->newfs_data.newfs_ufs.softupdates =
+ !pi->newfs_data.newfs_ufs.softupdates;
else
msg = MSG_NOT_APPLICABLE;
}
@@ -1032,15 +1114,20 @@ diskLabel(Device *dev)
if ((label_chunk_info[here].type == PART_FILESYSTEM) &&
(label_chunk_info[here].c->private_data)) {
PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data);
- if (!pi->newfs)
+ if (!pi->do_newfs)
label_chunk_info[here].c->flags |= CHUNK_NEWFS;
else
label_chunk_info[here].c->flags &= ~CHUNK_NEWFS;
label_chunk_info[here].c->private_data =
- new_part(pi ? pi->mountpoint : NULL, pi ? !pi->newfs : TRUE);
- if (pi && pi->soft)
- ((PartInfo *)label_chunk_info[here].c->private_data)->soft = 1;
+ new_part(pi ? pi->mountpoint : NULL, pi ? !pi->do_newfs
+ : TRUE);
+ if (pi != NULL &&
+ pi->newfs_type == NEWFS_UFS) {
+ PartInfo *pi_new = label_chunk_info[here].c->private_data;
+
+ pi_new->newfs_data.newfs_ufs = pi->newfs_data.newfs_ufs;
+ }
safe_free(pi);
label_chunk_info[here].c->private_free = safe_free;
if (variable_cmp(DISK_LABELLED, "written"))
@@ -1050,14 +1137,16 @@ diskLabel(Device *dev)
else if (label_chunk_info[here].type == PART_FAT &&
label_chunk_info[here].c->type == efi &&
label_chunk_info[here].c->private_data) {
- PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data);
- if (!pi->newfs)
+ PartInfo *pi =
+ ((PartInfo *)label_chunk_info[here].c->private_data);
+
+ if (!pi->do_newfs)
label_chunk_info[here].c->flags |= CHUNK_NEWFS;
else
label_chunk_info[here].c->flags &= ~CHUNK_NEWFS;
label_chunk_info[here].c->private_data =
- new_efi_part(pi->mountpoint, !pi->newfs);
+ new_efi_part(pi->mountpoint, !pi->do_newfs);
safe_free(pi);
label_chunk_info[here].c->private_free = safe_free;
if (variable_cmp(DISK_LABELLED, "written"))
@@ -1113,6 +1202,16 @@ diskLabel(Device *dev)
clear_wins();
break;
+ case 'Z': /* Set newfs command line */
+ if (label_chunk_info[here].c->private_data &&
+ ((PartInfo *)label_chunk_info[here].c->private_data)->do_newfs)
+ getNewfsCmd(label_chunk_info[here].c->private_data);
+ else
+ msg = MSG_NOT_APPLICABLE;
+ clear_wins();
+ break;
+
+
case '|':
if (!msgNoYes("Are you sure you want to go into Wizard mode?\n\n"
"This is an entirely undocumented feature which you are not\n"
@@ -1437,9 +1536,10 @@ diskLabelNonInteractive(Device *dev)
status = DITEM_FAILURE;
break;
} else {
- tmp->private_data = new_part(mpoint, TRUE);
+ PartInfo *pi;
+ pi = tmp->private_data = new_part(mpoint, TRUE);
tmp->private_free = safe_free;
- ((PartInfo *)tmp->private_data)->soft = soft;
+ pi->newfs_data.newfs_ufs.softupdates = soft;
}
}
}
@@ -1459,7 +1559,7 @@ diskLabelNonInteractive(Device *dev)
newfs = toupper(do_newfs[0]) == 'Y' ? TRUE : FALSE;
if (c1->private_data) {
p = c1->private_data;
- p->newfs = newfs;
+ p->do_newfs = newfs;
strcpy(p->mountpoint, mpoint);
}
else {
diff --git a/usr.sbin/sade/sade.h b/usr.sbin/sade/sade.h
index 1a0e20a7b94c..7ed0fab78be8 100644
--- a/usr.sbin/sade/sade.h
+++ b/usr.sbin/sade/sade.h
@@ -308,14 +308,39 @@ typedef enum {
PART_FAT,
} PartType;
-/* The longest newfs command we'll hand to system() */
-#define NEWFS_CMD_MAX 256
+#define NEWFS_UFS_CMD "newfs"
+#define NEWFS_MSDOS_CMD "newfs_msdos"
+
+enum newfs_type { NEWFS_UFS, NEWFS_MSDOS, NEWFS_CUSTOM };
+#define NEWFS_UFS_STRING "UFS"
+#define NEWFS_MSDOS_STRING "FAT"
+#define NEWFS_CUSTOM_STRING "CST"
+
+/* The longest set of custom command line arguments we'll pass. */
+#define NEWFS_CMD_ARGS_MAX 256
typedef struct _part_info {
- Boolean newfs;
- char mountpoint[FILENAME_MAX];
- char newfs_cmd[NEWFS_CMD_MAX];
- int soft;
+ char mountpoint[FILENAME_MAX];
+
+ /* Is invocation of newfs desired? */
+ Boolean do_newfs;
+
+ enum newfs_type newfs_type;
+ union {
+ struct {
+ char user_options[NEWFS_CMD_ARGS_MAX];
+ Boolean acls; /* unused */
+ Boolean multilabel; /* unused */
+ Boolean softupdates;
+ Boolean ufs2;
+ } newfs_ufs;
+ struct {
+ /* unused */
+ } newfs_msdos;
+ struct {
+ char command[NEWFS_CMD_ARGS_MAX];
+ } newfs_custom;
+ } newfs_data;
} PartInfo;
/* An option */
diff --git a/usr.sbin/sysinstall/help/partition.hlp b/usr.sbin/sysinstall/help/partition.hlp
index ef328df0e3c4..19cfb5abc592 100644
--- a/usr.sbin/sysinstall/help/partition.hlp
+++ b/usr.sbin/sysinstall/help/partition.hlp
@@ -126,6 +126,33 @@ with significant activity can temporarily overflow if the soft updates
policy results in free'd blocks not being "garbage collected" as fast
as they're being requested.
+To make use of UFS2, press '2' on a UFS file system to toggle the
+on-disk format revision. UFS2 provides native support for extended
+attributes, larger disk sizes, and forward compatibility with new
+on-disk high performance directory layout and storage extents.
+However, UFS2 is unsupported on versions of FreeBSD prior to 5.0,
+so it is not recommended for environments requiring backward
+compatibility. Also, UFS2 is not currently recommended as a root
+file system format for non-64-bit platforms due to increased size
+of the boot loader; special local configuration is required to boot
+UFS2 as a root file system on i386 and PC98.
+
+To add additional flags to the newfs command line for UFS file
+systems, press 'N'. These options will be specified before the
+device argument of the command line, but after any other options
+placed there by sysinstall, such as the UFS version and soft
+updates flag; as such, arguments provided may override existing
+settings. To completely replace the newfs command used by
+sysinstall, press 'Z' to convert a partition to a Custom
+partition type. Sysinstall will prompt you with the newfs
+command line that it would have used based on existing settings
+prior to the change, but allow you to modify any aspect of the
+command line. Once a partition has been converted to a custom
+partition in the label editor, you will need to restart the
+labeling process or delete and recreate the partition to restore
+it to a non-custom state. Custom partitions are represented by
+the letters "CST" instead of "UFS" or "FAT.
+
When you're done, type `Q' to exit.
No actual changes will be made to the disk until you (C)ommit from the
diff --git a/usr.sbin/sysinstall/install.c b/usr.sbin/sysinstall/install.c
index 9862e5627a79..e1763ec8b424 100644
--- a/usr.sbin/sysinstall/install.c
+++ b/usr.sbin/sysinstall/install.c
@@ -50,6 +50,7 @@
#undef MSDOSFS
#include <sys/stat.h>
#include <sys/sysctl.h>
+#include <limits.h>
#include <unistd.h>
#include <termios.h>
@@ -878,6 +879,44 @@ installFixupXFree(dialogMenuItem *self)
return DITEM_SUCCESS | DITEM_RESTORE;
}
+#define QUEUE_YES 1
+#define QUEUE_NO 0
+static int
+performNewfs(PartInfo *pi, char *dname, int queue)
+{
+ char buffer[LINE_MAX];
+
+ if (pi->do_newfs) {
+ switch(pi->newfs_type) {
+ case NEWFS_UFS:
+ snprintf(buffer, LINE_MAX, "%s %s %s %s %s",
+ NEWFS_UFS_CMD,
+ pi->newfs_data.newfs_ufs.softupdates ? "-U" : "",
+ pi->newfs_data.newfs_ufs.ufs2 ? "-O2" : "-O1",
+ pi->newfs_data.newfs_ufs.user_options,
+ dname);
+ break;
+
+ case NEWFS_MSDOS:
+ snprintf(buffer, LINE_MAX, "%s %s", NEWFS_MSDOS_CMD,
+ dname);
+ break;
+
+ case NEWFS_CUSTOM:
+ snprintf(buffer, LINE_MAX, "%s %s",
+ pi->newfs_data.newfs_custom.command, dname);
+ break;
+ }
+
+ if (queue == QUEUE_YES) {
+ command_shell_add(pi->mountpoint, buffer);
+ return (0);
+ } else
+ return (vsystem(buffer));
+ }
+ return (0);
+}
+
/* Go newfs and/or mount all the filesystems we've been asked to */
int
installFilesystems(dialogMenuItem *self)
@@ -940,12 +979,14 @@ installFilesystems(dialogMenuItem *self)
if (strcmp(root->mountpoint, "/"))
msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", rootdev->name, root->mountpoint);
- if (root->newfs && (!upgrade || !msgNoYes("You are upgrading - are you SURE you want to newfs the root partition?"))) {
+ if (root->do_newfs && (!upgrade ||
+ !msgNoYes("You are upgrading - are you SURE you want to newfs "
+ "the root partition?"))) {
int i;
dialog_clear_norefresh();
msgNotify("Making a new root filesystem on %s", dname);
- i = vsystem("%s %s", root->newfs_cmd, dname);
+ i = performNewfs(root, dname, QUEUE_NO);
if (i) {
msgConfirm("Unable to make new root filesystem on %s!\n"
"Command returned status %d", dname, i);
@@ -964,10 +1005,17 @@ installFilesystems(dialogMenuItem *self)
msgConfirm("Warning: fsck returned status of %d for %s.\n"
"This partition may be unsafe to use.", i, dname);
}
- if (root->soft) {
- i = vsystem("tunefs -n enable %s", dname);
- if (i)
- msgConfirm("Warning: Unable to enable softupdates for root filesystem on %s", dname);
+
+ /*
+ * If soft updates was enabled in the editor but we didn't newfs,
+ * use tunefs to update the soft updates flag on the file system.
+ */
+ if (!root->do_newfs && root->newfs_type == NEWFS_UFS &&
+ root->newfs_data.newfs_ufs.softupdates) {
+ i = vsystem("tunefs -n enable %s", dname);
+ if (i)
+ msgConfirm("Warning: Unable to enable soft updates"
+ " for root file system on %s", dname);
}
/* Switch to block device */
@@ -1021,12 +1069,23 @@ installFilesystems(dialogMenuItem *self)
if (c2 == rootdev)
continue;
- if (tmp->newfs && (!upgrade || !msgNoYes("You are upgrading - are you SURE you want to newfs /dev/%s?", c2->name)))
- command_shell_add(tmp->mountpoint, "%s %s/dev/%s", tmp->newfs_cmd, RunningAsInit ? "/mnt" : "", c2->name);
+ sprintf(dname, "%s/dev/%s",
+ RunningAsInit ? "/mnt" : "", c2->name);
+
+ if (tmp->do_newfs && (!upgrade ||
+ !msgNoYes("You are upgrading - are you SURE you"
+ " want to newfs /dev/%s?", c2->name)))
+ performNewfs(tmp, dname, QUEUE_YES);
else
- command_shell_add(tmp->mountpoint, "fsck_ffs -y %s/dev/%s", RunningAsInit ? "/mnt" : "", c2->name);
+ command_shell_add(tmp->mountpoint,
+ "fsck_ffs -y %s/dev/%s", RunningAsInit ?
+ "/mnt" : "", c2->name);
+#if 0
if (tmp->soft)
- command_shell_add(tmp->mountpoint, "tunefs -n enable %s/dev/%s", RunningAsInit ? "/mnt" : "", c2->name);
+ command_shell_add(tmp->mountpoint,
+ "tunefs -n enable %s/dev/%s", RunningAsInit ?
+ "/mnt" : "", c2->name);
+#endif
command_func_add(tmp->mountpoint, Mount, c2->name);
}
else if (c2->type == part && c2->subtype == FS_SWAP) {
@@ -1047,7 +1106,8 @@ installFilesystems(dialogMenuItem *self)
}
}
}
- else if (c1->type == fat && c1->private_data && (root->newfs || upgrade)) {
+ else if (c1->type == fat && c1->private_data &&
+ (root->do_newfs || upgrade)) {
char name[FILENAME_MAX];
sprintf(name, "%s/%s", RunningAsInit ? "/mnt" : "", ((PartInfo *)c1->private_data)->mountpoint);
@@ -1059,8 +1119,13 @@ installFilesystems(dialogMenuItem *self)
PartInfo *pi = (PartInfo *)c1->private_data;
char *p;
- if (pi->newfs && (!upgrade || !msgNoYes("You are upgrading - are you SURE you want to newfs /dev/%s?", c1->name)))
- command_shell_add(pi->mountpoint, "%s %s/dev/%s", pi->newfs_cmd, RunningAsInit ? "/mnt" : "", c1->name);
+ sprintf(dname, "%s/dev/%s", RunningAsInit ? "/mnt" : "",
+ c1->name);
+
+ if (pi->do_newfs && (!upgrade ||
+ !msgNoYes("You are upgrading - are you SURE you want to "
+ "newfs /dev/%s?", c1->name)))
+ performNewfs(pi, dname, QUEUE_YES);
command_func_add(pi->mountpoint, Mount_msdosfs, c1->name);
diff --git a/usr.sbin/sysinstall/label.c b/usr.sbin/sysinstall/label.c
index 7964545a50d8..860e16a5a3f4 100644
--- a/usr.sbin/sysinstall/label.c
+++ b/usr.sbin/sysinstall/label.c
@@ -322,36 +322,42 @@ record_label_chunks(Device **devs, Device *dev)
static PartInfo *
new_part(char *mpoint, Boolean newfs)
{
- PartInfo *ret;
+ PartInfo *pi;
if (!mpoint)
mpoint = "/change_me";
- ret = (PartInfo *)safe_malloc(sizeof(PartInfo));
- sstrncpy(ret->mountpoint, mpoint, FILENAME_MAX);
- strcpy(ret->newfs_cmd, "newfs ");
- strcat(ret->newfs_cmd, variable_get(VAR_NEWFS_ARGS));
- ret->newfs = newfs;
- ret->soft = strcmp(mpoint, "/") ? 1 : 0;
- return ret;
+ pi = (PartInfo *)safe_malloc(sizeof(PartInfo));
+ sstrncpy(pi->mountpoint, mpoint, FILENAME_MAX);
+
+ pi->do_newfs = newfs;
+
+ pi->newfs_type = NEWFS_UFS;
+ strcpy(pi->newfs_data.newfs_ufs.user_options, "");
+ pi->newfs_data.newfs_ufs.acls = FALSE;
+ pi->newfs_data.newfs_ufs.multilabel = FALSE;
+ pi->newfs_data.newfs_ufs.softupdates = strcmp(mpoint, "/");
+ pi->newfs_data.newfs_ufs.ufs2 = FALSE;
+
+ return pi;
}
#if defined(__ia64__)
static PartInfo *
new_efi_part(char *mpoint, Boolean newfs)
{
- PartInfo *ret;
+ PartInfo *pi;
if (!mpoint)
mpoint = "/efi";
- ret = (PartInfo *)safe_malloc(sizeof(PartInfo));
- sstrncpy(ret->mountpoint, mpoint, FILENAME_MAX);
- /* XXX */
- strcpy(ret->newfs_cmd, "newfs_msdos ");
- ret->newfs = newfs;
- ret->soft = 0;
- return ret;
+ pi = (PartInfo *)safe_malloc(sizeof(PartInfo));
+ sstrncpy(pi->mountpoint, mpoint, FILENAME_MAX);
+
+ pi->do_newfs = newfs;
+ pi->newfs_type = NEWFS_MSDOS;
+
+ return pi;
}
#endif
@@ -404,7 +410,7 @@ get_mountpoint(struct chunk *old)
newfs = TRUE;
if (tmp) {
- newfs = tmp->newfs;
+ newfs = tmp->do_newfs;
safe_free(tmp);
}
val = string_skipwhite(string_prune(val));
@@ -448,13 +454,49 @@ get_partition_type(void)
static void
getNewfsCmd(PartInfo *p)
{
+ char buffer[NEWFS_CMD_ARGS_MAX];
char *val;
- val = msgGetInput(p->newfs_cmd,
- "Please enter the newfs command and options you'd like to use in\n"
- "creating this file system.");
- if (val)
- sstrncpy(p->newfs_cmd, val, NEWFS_CMD_MAX);
+ switch (p->newfs_type) {
+ case NEWFS_UFS:
+ snprintf(buffer, NEWFS_CMD_ARGS_MAX, "%s %s %s %s",
+ NEWFS_UFS_CMD, p->newfs_data.newfs_ufs.softupdates ? "-U" : "",
+ p->newfs_data.newfs_ufs.ufs2 ? "-O2" : "-O1",
+ p->newfs_data.newfs_ufs.user_options);
+ break;
+ case NEWFS_MSDOS:
+ snprintf(buffer, NEWFS_CMD_ARGS_MAX, "%s", NEWFS_MSDOS_CMD);
+ break;
+ case NEWFS_CUSTOM:
+ strcpy(buffer, p->newfs_data.newfs_custom.command);
+ break;
+ }
+
+ val = msgGetInput(buffer,
+ "Please enter the newfs command and options you'd like to use in\n"
+ "creating this file system.");
+ if (val != NULL) {
+ p->newfs_type = NEWFS_CUSTOM;
+ strlcpy(p->newfs_data.newfs_custom.command, val, NEWFS_CMD_ARGS_MAX);
+ }
+}
+
+static void
+getNewfsOptionalArguments(PartInfo *p)
+{
+ char buffer[NEWFS_CMD_ARGS_MAX];
+ char *val;
+
+ /* Must be UFS, per argument checking in I/O routines. */
+
+ strlcpy(buffer, p->newfs_data.newfs_ufs.user_options,
+ NEWFS_CMD_ARGS_MAX);
+ val = msgGetInput(buffer,
+ "Please enter any additional UFS newfs options you'd like to\n"
+ "use in creating this file system.");
+ if (val != NULL)
+ strlcpy(p->newfs_data.newfs_ufs.user_options, val,
+ NEWFS_CMD_ARGS_MAX);
}
#define MAX_MOUNT_NAME 9
@@ -473,7 +515,7 @@ getNewfsCmd(PartInfo *p)
static void
print_label_chunks(void)
{
- int i, j, srow, prow, pcol;
+ int i, j, spaces, srow, prow, pcol;
int sz;
char clrmsg[80];
int ChunkPartStartRow;
@@ -581,7 +623,7 @@ print_label_chunks(void)
}
/* Otherwise it's a DOS, swap or filesystem entry in the Chunk window */
else {
- char onestr[PART_OFF], num[10], *mountpoint, newfs[10];
+ char onestr[PART_OFF], num[10], *mountpoint, newfs[12];
/*
* We copy this into a blank-padded string so that it looks like
@@ -626,18 +668,34 @@ print_label_chunks(void)
label_chunk_info[i].c->type == efi) {
strcat(newfs, " ");
PartInfo *pi = (PartInfo *)label_chunk_info[i].c->private_data;
- strcat(newfs, pi->newfs ? " Y" : " N");
+ strcat(newfs, pi->do_newfs ? " Y" : " N");
}
#endif
}
else if (label_chunk_info[i].c->private_data && label_chunk_info[i].type == PART_FILESYSTEM) {
- strcpy(newfs, "UFS");
- strcat(newfs,
- ((PartInfo *)label_chunk_info[i].c->private_data)->soft ?
- "+S" : " ");
- strcat(newfs,
- ((PartInfo *)label_chunk_info[i].c->private_data)->newfs ?
- " Y" : " N");
+ PartInfo *pi = (PartInfo *)label_chunk_info[i].c->private_data;
+
+ switch (pi->newfs_type) {
+ case NEWFS_UFS:
+ strcpy(newfs, NEWFS_UFS_STRING);
+ if (pi->newfs_data.newfs_ufs.ufs2)
+ strcat(newfs, "2");
+ else
+ strcat(newfs, "1");
+ if (pi->newfs_data.newfs_ufs.softupdates)
+ strcat(newfs, "+S");
+ else
+ strcat(newfs, " ");
+
+ break;
+ case NEWFS_MSDOS:
+ strcpy(newfs, "FAT");
+ break;
+ case NEWFS_CUSTOM:
+ strcpy(newfs, "CUST");
+ break;
+ }
+ strcat(newfs, pi->do_newfs ? " Y" : " N ");
}
else if (label_chunk_info[i].type == PART_SWAP)
strcpy(newfs, "SWAP");
@@ -695,9 +753,9 @@ print_command_summary(void)
mvprintw(17, 0, "The following commands are valid here (upper or lower case):");
mvprintw(18, 0, "C = Create D = Delete M = Mount pt.");
if (!RunningAsInit)
- mvprintw(18, 47, "W = Write");
- mvprintw(19, 0, "N = Newfs Opts Q = Finish S = Toggle SoftUpdates");
- mvprintw(20, 0, "T = Toggle Newfs U = Undo A = Auto Defaults R = Delete+Merge");
+ mvprintw(18, 56, "W = Write");
+ mvprintw(19, 0, "N = Newfs Opts Q = Finish S = Toggle SoftUpdates Z = Custom Newfs");
+ mvprintw(20, 0, "T = Toggle Newfs U = Undo A = Auto Defaults R = Delete+Merge");
mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to select.");
move(0, 0);
}
@@ -799,6 +857,27 @@ diskLabel(Device *dev)
clear_wins();
break;
+ case '2':
+ if (label_chunk_info[here].type == PART_FILESYSTEM) {
+ PartInfo *pi =
+ ((PartInfo *)label_chunk_info[here].c->private_data);
+
+ if ((pi != NULL) &&
+ (pi->newfs_type == NEWFS_UFS)) {
+#ifdef __i386__
+ if (label_chunk_info[here].c->flags & CHUNK_IS_ROOT)
+ msg = MSG_NOT_APPLICABLE;
+ else
+#endif
+ pi->newfs_data.newfs_ufs.ufs2 =
+ !pi->newfs_data.newfs_ufs.ufs2;
+ } else
+ msg = MSG_NOT_APPLICABLE;
+ } else
+ msg = MSG_NOT_APPLICABLE;
+ break;
+ break;
+
case 'A':
if (label_chunk_info[here].type != PART_SLICE) {
msg = "You can only do this in a disk slice (at top of screen)";
@@ -987,7 +1066,7 @@ diskLabel(Device *dev)
p = get_mountpoint(label_chunk_info[here].c);
if (p) {
if (!oldp)
- p->newfs = FALSE;
+ p->do_newfs = FALSE;
if (label_chunk_info[here].type == PART_FAT
&& (!strcmp(p->mountpoint, "/") || !strcmp(p->mountpoint, "/usr")
|| !strcmp(p->mountpoint, "/var"))) {
@@ -1009,8 +1088,9 @@ diskLabel(Device *dev)
case 'N': /* Set newfs options */
if (label_chunk_info[here].c->private_data &&
- ((PartInfo *)label_chunk_info[here].c->private_data)->newfs)
- getNewfsCmd(label_chunk_info[here].c->private_data);
+ ((PartInfo *)label_chunk_info[here].c->private_data)->do_newfs)
+ getNewfsOptionalArguments(
+ label_chunk_info[here].c->private_data);
else
msg = MSG_NOT_APPLICABLE;
clear_wins();
@@ -1019,8 +1099,10 @@ diskLabel(Device *dev)
case 'S': /* Toggle soft updates flag */
if (label_chunk_info[here].type == PART_FILESYSTEM) {
PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data);
- if (pi)
- pi->soft = !pi->soft;
+ if (pi != NULL &&
+ pi->newfs_type == NEWFS_UFS)
+ pi->newfs_data.newfs_ufs.softupdates =
+ !pi->newfs_data.newfs_ufs.softupdates;
else
msg = MSG_NOT_APPLICABLE;
}
@@ -1032,15 +1114,20 @@ diskLabel(Device *dev)
if ((label_chunk_info[here].type == PART_FILESYSTEM) &&
(label_chunk_info[here].c->private_data)) {
PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data);
- if (!pi->newfs)
+ if (!pi->do_newfs)
label_chunk_info[here].c->flags |= CHUNK_NEWFS;
else
label_chunk_info[here].c->flags &= ~CHUNK_NEWFS;
label_chunk_info[here].c->private_data =
- new_part(pi ? pi->mountpoint : NULL, pi ? !pi->newfs : TRUE);
- if (pi && pi->soft)
- ((PartInfo *)label_chunk_info[here].c->private_data)->soft = 1;
+ new_part(pi ? pi->mountpoint : NULL, pi ? !pi->do_newfs
+ : TRUE);
+ if (pi != NULL &&
+ pi->newfs_type == NEWFS_UFS) {
+ PartInfo *pi_new = label_chunk_info[here].c->private_data;
+
+ pi_new->newfs_data.newfs_ufs = pi->newfs_data.newfs_ufs;
+ }
safe_free(pi);
label_chunk_info[here].c->private_free = safe_free;
if (variable_cmp(DISK_LABELLED, "written"))
@@ -1050,14 +1137,16 @@ diskLabel(Device *dev)
else if (label_chunk_info[here].type == PART_FAT &&
label_chunk_info[here].c->type == efi &&
label_chunk_info[here].c->private_data) {
- PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data);
- if (!pi->newfs)
+ PartInfo *pi =
+ ((PartInfo *)label_chunk_info[here].c->private_data);
+
+ if (!pi->do_newfs)
label_chunk_info[here].c->flags |= CHUNK_NEWFS;
else
label_chunk_info[here].c->flags &= ~CHUNK_NEWFS;
label_chunk_info[here].c->private_data =
- new_efi_part(pi->mountpoint, !pi->newfs);
+ new_efi_part(pi->mountpoint, !pi->do_newfs);
safe_free(pi);
label_chunk_info[here].c->private_free = safe_free;
if (variable_cmp(DISK_LABELLED, "written"))
@@ -1113,6 +1202,16 @@ diskLabel(Device *dev)
clear_wins();
break;
+ case 'Z': /* Set newfs command line */
+ if (label_chunk_info[here].c->private_data &&
+ ((PartInfo *)label_chunk_info[here].c->private_data)->do_newfs)
+ getNewfsCmd(label_chunk_info[here].c->private_data);
+ else
+ msg = MSG_NOT_APPLICABLE;
+ clear_wins();
+ break;
+
+
case '|':
if (!msgNoYes("Are you sure you want to go into Wizard mode?\n\n"
"This is an entirely undocumented feature which you are not\n"
@@ -1437,9 +1536,10 @@ diskLabelNonInteractive(Device *dev)
status = DITEM_FAILURE;
break;
} else {
- tmp->private_data = new_part(mpoint, TRUE);
+ PartInfo *pi;
+ pi = tmp->private_data = new_part(mpoint, TRUE);
tmp->private_free = safe_free;
- ((PartInfo *)tmp->private_data)->soft = soft;
+ pi->newfs_data.newfs_ufs.softupdates = soft;
}
}
}
@@ -1459,7 +1559,7 @@ diskLabelNonInteractive(Device *dev)
newfs = toupper(do_newfs[0]) == 'Y' ? TRUE : FALSE;
if (c1->private_data) {
p = c1->private_data;
- p->newfs = newfs;
+ p->do_newfs = newfs;
strcpy(p->mountpoint, mpoint);
}
else {
diff --git a/usr.sbin/sysinstall/sysinstall.h b/usr.sbin/sysinstall/sysinstall.h
index 1a0e20a7b94c..7ed0fab78be8 100644
--- a/usr.sbin/sysinstall/sysinstall.h
+++ b/usr.sbin/sysinstall/sysinstall.h
@@ -308,14 +308,39 @@ typedef enum {
PART_FAT,
} PartType;
-/* The longest newfs command we'll hand to system() */
-#define NEWFS_CMD_MAX 256
+#define NEWFS_UFS_CMD "newfs"
+#define NEWFS_MSDOS_CMD "newfs_msdos"
+
+enum newfs_type { NEWFS_UFS, NEWFS_MSDOS, NEWFS_CUSTOM };
+#define NEWFS_UFS_STRING "UFS"
+#define NEWFS_MSDOS_STRING "FAT"
+#define NEWFS_CUSTOM_STRING "CST"
+
+/* The longest set of custom command line arguments we'll pass. */
+#define NEWFS_CMD_ARGS_MAX 256
typedef struct _part_info {
- Boolean newfs;
- char mountpoint[FILENAME_MAX];
- char newfs_cmd[NEWFS_CMD_MAX];
- int soft;
+ char mountpoint[FILENAME_MAX];
+
+ /* Is invocation of newfs desired? */
+ Boolean do_newfs;
+
+ enum newfs_type newfs_type;
+ union {
+ struct {
+ char user_options[NEWFS_CMD_ARGS_MAX];
+ Boolean acls; /* unused */
+ Boolean multilabel; /* unused */
+ Boolean softupdates;
+ Boolean ufs2;
+ } newfs_ufs;
+ struct {
+ /* unused */
+ } newfs_msdos;
+ struct {
+ char command[NEWFS_CMD_ARGS_MAX];
+ } newfs_custom;
+ } newfs_data;
} PartInfo;
/* An option */