Index: install.c
===================================================================
RCS file: /home/ncvs/src/release/sysinstall/Attic/install.c,v
retrieving revision 1.268.2.29
diff -u -r1.268.2.29 install.c
--- install.c	2001/10/26 08:26:34	1.268.2.29
+++ install.c	2001/12/08 02:42:03
@@ -66,12 +66,12 @@
 static void	installConfigure(void);
 
 Boolean
-checkLabels(Boolean whinge, Chunk **rdev, Chunk **sdev, Chunk **udev, Chunk **vdev)
+checkLabels(Boolean whinge, Chunk **rdev, Chunk **sdev, Chunk **udev, Chunk **vdev, Chunk **vtdev, Chunk **hdev)
 {
     Device **devs;
     Boolean status;
     Disk *disk;
-    Chunk *c1, *c2, *rootdev, *swapdev, *usrdev, *vardev;
+    Chunk *c1, *c2, *rootdev, *swapdev, *usrdev, *vardev, *vartmpdev, *homedev;
     int i;
 
     /* Don't allow whinging if noWarn is set */
@@ -79,7 +79,19 @@
 	whinge = FALSE;
 
     status = TRUE;
-    *rdev = *sdev = *udev = *vdev = rootdev = swapdev = usrdev = vardev = NULL;
+    if (rdev)
+	*rdev = NULL;
+    if (sdev)
+	*sdev = NULL;
+    if (udev)
+	*udev = NULL;
+    if (vdev)
+	*vdev = NULL;
+    if (vtdev)
+	*vtdev = NULL;
+    if (hdev)
+	*hdev = NULL;
+    rootdev = swapdev = usrdev = vardev = vartmpdev = homedev = NULL;
 
     /* We don't need to worry about root/usr/swap if we're already multiuser */
     if (!RunningAsInit)
@@ -136,6 +148,30 @@
 				if (isDebug())
 				    msgDebug("Found vardev at %s!\n", vardev->name);
 			    }
+			} else if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/var/tmp")) {
+			    if (vartmpdev) {
+				if (whinge)
+				    msgConfirm("WARNING:  You have more than one /var/tmp filesystem.\n"
+					       "Using the first one found.");
+				continue;
+			    }
+			    else {
+				vartmpdev = c2;
+				if (isDebug())
+				    msgDebug("Found vartmpdev at %s!\n", vartmpdev->name);
+			    }
+			} else if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/home")) {
+			    if (homedev) {
+				if (whinge)
+				    msgConfirm("WARNING:  You have more than one /home filesystem.\n"
+					       "Using the first one found.");
+				continue;
+			    }
+			    else {
+				homedev = c2;
+				if (isDebug())
+				    msgDebug("Found homedev at %s!\n", homedev->name);
+			    }
 			}
 		    }
 		}
@@ -166,10 +202,18 @@
     }
 
     /* Copy our values over */
-    *rdev = rootdev;
-    *sdev = swapdev;
-    *udev = usrdev;
-    *vdev = vardev;
+    if (rdev)
+	*rdev = rootdev;
+    if (sdev)
+	*sdev = swapdev;
+    if (udev)
+	*udev = usrdev;
+    if (vdev)
+	*vdev = vardev;
+    if (vtdev)
+	*vtdev = vartmpdev;
+    if (hdev)
+	*hdev = homedev;
 
     if (!rootdev && whinge) {
 	msgConfirm("No root device found - you must label a partition as /\n"
@@ -868,7 +912,7 @@
 {
     int i;
     Disk *disk;
-    Chunk *c1, *c2, *rootdev, *swapdev, *usrdev, *vardev;
+    Chunk *c1, *c2, *rootdev, *swapdev;
     Device **devs;
     PartInfo *root;
     char dname[80];
@@ -880,7 +924,7 @@
 	return DITEM_SUCCESS;
 
     upgrade = !variable_cmp(SYSTEM_STATE, "upgrade");
-    if (!checkLabels(TRUE, &rootdev, &swapdev, &usrdev, &vardev))
+    if (!checkLabels(TRUE, &rootdev, &swapdev, NULL, NULL, NULL, NULL))
 	return DITEM_FAILURE;
 
     if (rootdev)
Index: label.c
===================================================================
RCS file: /home/ncvs/src/release/sysinstall/Attic/label.c,v
retrieving revision 1.98.2.5
diff -u -r1.98.2.5 label.c
--- label.c	2001/05/09 08:00:30	1.98.2.5
+++ label.c	2001/12/08 07:29:52
@@ -54,29 +54,47 @@
 /* The smallest filesystem we're willing to create */
 #define FS_MIN_SIZE			ONE_MEG
 
-/* The smallest root filesystem we're willing to create */
+/*
+ * Minimum partition sizes
+ */
 #ifdef __alpha__
 #define ROOT_MIN_SIZE			40
 #else
 #define ROOT_MIN_SIZE			30
 #endif
-
-/* The default root filesystem size */
-#ifdef __alpha__
-#define ROOT_DEFAULT_SIZE		110
-#else
-#define ROOT_DEFAULT_SIZE		100
-#endif
-
-/* The smallest swap partition we want to create by default */
 #define SWAP_MIN_SIZE			32
-
-/* The smallest /usr partition we're willing to create by default */
 #define USR_MIN_SIZE			80
-
-/* The smallest /var partition we're willing to create by default */
 #define VAR_MIN_SIZE			20
+#define VARTMP_MIN_SIZE			20
+#define HOME_MIN_SIZE			20
 
+/* 
+ * Swap size limit for auto-partitioning
+ */
+#define SWAP_AUTO_LIMIT_SIZE		4096
+
+/*
+ * Default partition sizes.  If we do not have sufficient disk space
+ * for this configuration we scale things relative to the NOM vs DEFAULT
+ * sizes.  If the disk is larger then /home will get any remaining space.
+ */
+#define ROOT_DEFAULT_SIZE		128
+#define USR_DEFAULT_SIZE		3072
+#define VAR_DEFAULT_SIZE		256
+#define VARTMP_DEFAULT_SIZE		256
+#define HOME_DEFAULT_SIZE		USR_DEFAULT_SIZE
+
+/*
+ * Nominal partition sizes.  These are used to scale the default sizes down
+ * when we have insufficient disk space.  If this isn't sufficient we scale
+ * down using the MIN sizes instead.
+ */
+#define ROOT_NOMINAL_SIZE		128
+#define USR_NOMINAL_SIZE		512
+#define VAR_NOMINAL_SIZE		64
+#define VARTMP_NOMINAL_SIZE		64
+#define HOME_NOMINAL_SIZE		USR_NOMINAL_SIZE
+
 /* The bottom-most row we're allowed to scribble on */
 #define CHUNK_ROW_MAX			16
 
@@ -93,6 +111,7 @@
 
 static int diskLabel(Device *dev);
 static int diskLabelNonInteractive(Device *dev);
+static char *try_auto_label(Device **devs, Device *dev, int perc, int *req);
 
 static int
 labelHook(dialogMenuItem *selected)
@@ -781,110 +800,27 @@
 		msg = "You can only do this in a disk slice (at top of screen)";
 		break;
 	    }
-	    sz = space_free(label_chunk_info[here].c);
-	    if (sz <= FS_MIN_SIZE)
-		msg = "Not enough free space to create a new partition in the slice";
-	    else {
-		struct chunk *tmp;
-		int mib[2];
-		int physmem;
-		size_t size, swsize;
-		char *cp;
-		Chunk *rootdev, *swapdev, *usrdev, *vardev;
-
-		(void)checkLabels(FALSE, &rootdev, &swapdev, &usrdev, &vardev);
-		if (!rootdev) {
-		    cp = variable_get(VAR_ROOT_SIZE);
-		    tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c,
-					    (cp ? atoi(cp) : ROOT_DEFAULT_SIZE) * ONE_MEG, part, FS_BSDFFS,  CHUNK_IS_ROOT);
-		    if (!tmp) {
-			msgConfirm("Unable to create the root partition. Too big?");
-			clear_wins();
+	    /*
+	     * Generate standard partitions automatically.  If we do not
+	     * have sufficient space we attempt to scale-down the size
+	     * of the partitions within certain bounds.
+	     */
+	    {
+		int perc;
+		int req = 0;
+
+		for (perc = 100; perc > 0; perc -= 5) {
+		    req = 0;	/* reset for each loop */
+		    if ((msg = try_auto_label(devs, dev, perc, &req)) == NULL)
 			break;
-		    }
-		    tmp->private_data = new_part("/", TRUE, tmp->size);
-		    tmp->private_free = safe_free;
-		    record_label_chunks(devs, dev);
 		}
-
-		if (!swapdev) {
-		    cp = variable_get(VAR_SWAP_SIZE);
-		    if (cp)
-			swsize = atoi(cp) * ONE_MEG;
-		    else {
-			mib[0] = CTL_HW;
-			mib[1] = HW_PHYSMEM;
-			size = sizeof physmem;
-			sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0);
-			swsize = 16 * ONE_MEG + (physmem * 2 / 512);
-		    }
-		    tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c,
-					    swsize, part, FS_SWAP, 0);
-		    if (!tmp) {
-			msgConfirm("Unable to create the swap partition. Too big?");
+		if (msg) {
+		    if (req) {
+			msgConfirm(msg);
 			clear_wins();
-			break;
-		    }
-		    tmp->private_data = 0;
-		    tmp->private_free = safe_free;
-		    record_label_chunks(devs, dev);
-		}
-
-		if (!vardev) {
-		    cp = variable_get(VAR_VAR_SIZE);
-		    if (cp)
-			sz = atoi(cp) * ONE_MEG;
-		    else
-			sz = variable_get(VAR_NO_USR)
-				?  space_free(label_chunk_info[here].c)
-				:  VAR_MIN_SIZE * ONE_MEG;
-
-		    tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c,
-					    sz, part, FS_BSDFFS, 0);
-		    if (!tmp) {
-			msgConfirm("Less than %dMB free for /var - you will need to\n"
-				   "partition your disk manually with a custom install!",
-				   (cp ? atoi(cp) : VAR_MIN_SIZE));
-			clear_wins();
-			break;
-		    }
-		    tmp->private_data = new_part("/var", TRUE, tmp->size);
-		    tmp->private_free = safe_free;
-		    record_label_chunks(devs, dev);
-		}
-
-		if (!usrdev && !variable_get(VAR_NO_USR)) {
-		    cp = variable_get(VAR_USR_SIZE);
-		    if (cp)
-			sz = atoi(cp) * ONE_MEG;
-		    else
-			sz = space_free(label_chunk_info[here].c);
-		    if (sz) {
-			if (sz < (USR_MIN_SIZE * ONE_MEG)) {
-			    msgConfirm("Less than %dMB free for /usr - you will need to\n"
-				       "partition your disk manually with a custom install!", USR_MIN_SIZE);
-			    clear_wins();
-			    break;
-			}
-
-			tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk,
-						label_chunk_info[here].c,
-						sz, part, FS_BSDFFS, 0);
-			if (!tmp) {
-			    msgConfirm("Unable to create the /usr partition.  Not enough space?\n"
-				       "You will need to partition your disk manually with a custom install!");
-			    clear_wins();
-			    break;
-			}
-			tmp->private_data = new_part("/usr", TRUE, tmp->size);
-			tmp->private_free = safe_free;
-			record_label_chunks(devs, dev);
+			msg = NULL;
 		    }
 		}
-
-		/* At this point, we're reasonably "labelled" */
-		if (variable_cmp(DISK_LABELLED, "written"))
-		    variable_set2(DISK_LABELLED, "yes", 0);
 	    }
 	    break;
 	    
@@ -1172,6 +1108,201 @@
     }
     restorescr(w);
     return DITEM_SUCCESS;
+}
+
+static __inline int
+requested_part_size(char *varName, int nom, int def, int perc)
+{
+    char *cp;
+    int sz;
+
+    if ((cp = variable_get(VAR_ROOT_SIZE)) != NULL)
+	sz = atoi(cp);
+    else
+	sz = nom + (def - nom) * perc / 100;
+    return(sz * ONE_MEG);
+}
+
+/*
+ * Attempt to auto-label the disk.  'perc' (0-100) scales
+ * the size of the various partitions within appropriate
+ * bounds (NOMINAL through DEFAULT sizes).  The procedure
+ * succeeds of NULL is returned.  A non-null return message
+ * is either a failure-status message (*req == 0), or 
+ * a confirmation requestor (*req == 1).  *req is 0 on
+ * entry to this call.
+ *
+ * We autolabel the following partitions:  /, swap, /var, /var/tmp, /usr,
+ * and /home.  /home receives any extra left over disk space. 
+ */
+static char *
+try_auto_label(Device **devs, Device *dev, int perc, int *req)
+{
+    int sz;
+    struct chunk *root_chunk = NULL;
+    struct chunk *swap_chunk = NULL;
+    struct chunk *usr_chunk = NULL;
+    struct chunk *var_chunk = NULL;
+    struct chunk *vartmp_chunk = NULL;
+    struct chunk *home_chunk = NULL;
+    int mib[2];
+    unsigned int physmem;
+    size_t size;
+    Chunk *rootdev, *swapdev, *usrdev, *vardev;
+    Chunk *vartmpdev, *homedev;
+    char *msg = NULL;
+
+    sz = space_free(label_chunk_info[here].c);
+    if (sz <= FS_MIN_SIZE)
+	return("Not enough free space to create a new partition in the slice");
+
+    (void)checkLabels(FALSE, &rootdev, &swapdev, &usrdev,
+			&vardev, &vartmpdev, &homedev);
+    if (!rootdev) {
+	sz = requested_part_size(VAR_ROOT_SIZE, ROOT_NOMINAL_SIZE, ROOT_DEFAULT_SIZE, perc);
+
+	root_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c,
+				sz, part, FS_BSDFFS,  CHUNK_IS_ROOT);
+	if (!root_chunk) {
+	    *req = 1;
+	    msg = "Unable to create the root partition. Too big?";
+	    goto done;
+	}
+	root_chunk->private_data = new_part("/", TRUE, root_chunk->size);
+	root_chunk->private_free = safe_free;
+	record_label_chunks(devs, dev);
+    }
+    if (!swapdev) {
+	sz = requested_part_size(VAR_SWAP_SIZE, 0, 0, perc);
+	if (sz == 0) {
+	    int nom;
+	    int def;
+
+	    mib[0] = CTL_HW;
+	    mib[1] = HW_PHYSMEM;
+	    size = sizeof physmem;
+	    sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0);
+	    def = 2 * (int)(physmem / 512);
+	    if (def < SWAP_MIN_SIZE * ONE_MEG)
+		def = SWAP_MIN_SIZE * ONE_MEG;
+	    if (def > SWAP_AUTO_LIMIT_SIZE * ONE_MEG)
+		def = SWAP_AUTO_LIMIT_SIZE * ONE_MEG;
+	    nom = (int)(physmem / 512) / 2;
+	    sz = nom + (def - nom) * perc / 100;
+	}
+	swap_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c,
+				sz, part, FS_SWAP, 0);
+	if (!swap_chunk) {
+	    *req = 1;
+	    msg = "Unable to create the swap partition. Too big?";
+	    goto done;
+	}
+	swap_chunk->private_data = 0;
+	swap_chunk->private_free = safe_free;
+	record_label_chunks(devs, dev);
+    }
+    if (!vardev) {
+	sz = requested_part_size(VAR_VAR_SIZE, VAR_NOMINAL_SIZE, VAR_DEFAULT_SIZE, perc);
+
+	var_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c,
+				sz, part, FS_BSDFFS, 0);
+	if (!var_chunk) {
+	    *req = 1;
+	    msg = "Not enough free space for /var - you will need to\n"
+		   "partition your disk manually with a custom install!";
+	    goto done;
+	}
+	var_chunk->private_data = new_part("/var", TRUE, var_chunk->size);
+	var_chunk->private_free = safe_free;
+	record_label_chunks(devs, dev);
+    }
+    if (!vartmpdev && !variable_get(VAR_NO_VARTMP)) {
+	sz = requested_part_size(VAR_VARTMP_SIZE, VARTMP_NOMINAL_SIZE, VARTMP_DEFAULT_SIZE, perc);
+
+	vartmp_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c,
+				sz, part, FS_BSDFFS, 0);
+	if (!vartmp_chunk) {
+	    *req = 1;
+	    msg = "Not enough free space for /var/tmp - you will need to\n"
+		   "partition your disk manually with a custom install!";
+	    goto done;
+	}
+	vartmp_chunk->private_data = new_part("/var/tmp", TRUE, vartmp_chunk->size);
+	vartmp_chunk->private_free = safe_free;
+	record_label_chunks(devs, dev);
+    }
+    if (!usrdev && !variable_get(VAR_NO_USR)) {
+	sz = requested_part_size(VAR_USR_SIZE, USR_NOMINAL_SIZE, USR_DEFAULT_SIZE, perc);
+#if 0
+	    sz = space_free(label_chunk_info[here].c);
+#endif
+	if (sz) {
+	    if (sz < (USR_MIN_SIZE * ONE_MEG)) {
+		*req = 1;
+		msg = "Not enough free space for /usr - you will need to\n"
+		       "partition your disk manually with a custom install!";
+	    }
+
+	    usr_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk,
+				    label_chunk_info[here].c,
+				    sz, part, FS_BSDFFS, 0);
+	    if (!usr_chunk) {
+		msg = "Unable to create the /usr partition.  Not enough space?\n"
+			   "You will need to partition your disk manually with a custom install!";
+		goto done;
+	    }
+	    usr_chunk->private_data = new_part("/usr", TRUE, usr_chunk->size);
+	    usr_chunk->private_free = safe_free;
+	    record_label_chunks(devs, dev);
+	}
+    }
+    if (!homedev && !variable_get(VAR_NO_HOME)) {
+	sz = requested_part_size(VAR_HOME_SIZE, HOME_NOMINAL_SIZE, HOME_DEFAULT_SIZE, perc);
+	if (sz < space_free(label_chunk_info[here].c))
+	    sz = space_free(label_chunk_info[here].c);
+	if (sz) {
+	    if (sz < (HOME_MIN_SIZE * ONE_MEG)) {
+		*req = 1;
+		msg = "Not enough free space for /home - you will need to\n"
+		       "partition your disk manually with a custom install!";
+		goto done;
+	    }
+
+	    home_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk,
+				    label_chunk_info[here].c,
+				    sz, part, FS_BSDFFS, 0);
+	    if (!home_chunk) {
+		msg = "Unable to create the /home partition.  Not enough space?\n"
+			   "You will need to partition your disk manually with a custom install!";
+		goto done;
+	    }
+	    home_chunk->private_data = new_part("/home", TRUE, home_chunk->size);
+	    home_chunk->private_free = safe_free;
+	    record_label_chunks(devs, dev);
+	}
+    }
+
+    /* At this point, we're reasonably "labelled" */
+    if (variable_cmp(DISK_LABELLED, "written"))
+	variable_set2(DISK_LABELLED, "yes", 0);
+
+done:
+    if (msg) {
+	if (root_chunk)
+	    Delete_Chunk(root_chunk->disk, root_chunk);
+	if (swap_chunk)
+	    Delete_Chunk(swap_chunk->disk, swap_chunk);
+	if (var_chunk)
+	    Delete_Chunk(var_chunk->disk, var_chunk);
+	if (vartmp_chunk)
+	    Delete_Chunk(vartmp_chunk->disk, vartmp_chunk);
+	if (usr_chunk)
+	    Delete_Chunk(usr_chunk->disk, usr_chunk);
+	if (home_chunk)
+	    Delete_Chunk(home_chunk->disk, home_chunk);
+	record_label_chunks(devs, dev);
+    }
+    return(msg);
 }
 
 static int
Index: sysinstall.h
===================================================================
RCS file: /home/ncvs/src/release/sysinstall/Attic/sysinstall.h,v
retrieving revision 1.186.2.25
diff -u -r1.186.2.25 sysinstall.h
--- sysinstall.h	2001/10/26 09:25:01	1.186.2.25
+++ sysinstall.h	2001/12/08 02:22:31
@@ -150,6 +150,8 @@
 #define VAR_NO_HOLOSHELL		"noHoloShell"
 #define VAR_NO_WARN			"noWarn"
 #define VAR_NO_USR			"noUsr"
+#define VAR_NO_VARTMP			"noVarTmp"
+#define VAR_NO_HOME			"noHome"
 #define VAR_NONINTERACTIVE		"nonInteractive"
 #define VAR_NOVELL			"novell"
 #define VAR_NTPDATE_FLAGS		"ntpdate_flags"
@@ -174,6 +176,8 @@
 #define VAR_UFS_PATH			"ufs"
 #define VAR_USR_SIZE			"usrSize"
 #define VAR_VAR_SIZE			"varSize"
+#define VAR_VARTMP_SIZE			"varTmpSize"
+#define VAR_HOME_SIZE			"homeSize"
 #define VAR_XF86_CONFIG			"_xf86config"
 #define VAR_TERM			"TERM"
 
@@ -572,7 +576,7 @@
 PkgNodePtr	index_search(PkgNodePtr top, char *str, PkgNodePtr *tp);
 
 /* install.c */
-extern Boolean	checkLabels(Boolean whinge, Chunk **rdev, Chunk **sdev, Chunk **udev, Chunk **vdev);
+extern Boolean	checkLabels(Boolean whinge, Chunk **rdev, Chunk **sdev, Chunk **udev, Chunk **vdev, Chunk **vtdev, Chunk **hdev);
 extern int	installCommit(dialogMenuItem *self);
 extern int	installCustomCommit(dialogMenuItem *self);
 extern int	installExpress(dialogMenuItem *self);
