summaryrefslogtreecommitdiff
path: root/sbin/disklabel
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2008-01-07 16:51:36 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2008-01-07 16:51:36 +0000
commit13f23c54bbd3d677a1f799c888ebedc1ac476060 (patch)
tree70cee4f1a3ec366d233c7d59bbd759f55f1b0228 /sbin/disklabel
parentd5f9080fce289690c6b83ba4d7b0e747fd84f338 (diff)
Shrink & simplify some more -E code. Remove some chances for user
error. 1) Don't accept a partition offset in used space. 2) Make the default size the space available from the offset to the end of the free chunk the offset is in. 3) Make (m)odify ask the questions in the same order as the (a)dd command. i.e. filesystem type after offset/size. 4) Make it more obvious new partitions default into the largest chunk of free space. 5) Nuke another now pointless function - next_offset(). "Looks reasonable" millert@
Diffstat (limited to 'sbin/disklabel')
-rw-r--r--sbin/disklabel/editor.c156
1 files changed, 47 insertions, 109 deletions
diff --git a/sbin/disklabel/editor.c b/sbin/disklabel/editor.c
index b57dc0fe140..f38f18bac5a 100644
--- a/sbin/disklabel/editor.c
+++ b/sbin/disklabel/editor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: editor.c,v 1.143 2008/01/06 22:28:13 krw Exp $ */
+/* $OpenBSD: editor.c,v 1.144 2008/01/07 16:51:35 krw Exp $ */
/*
* Copyright (c) 1997-2000 Todd C. Miller <Todd.Miller@courtesan.com>
@@ -17,7 +17,7 @@
*/
#ifndef lint
-static char rcsid[] = "$OpenBSD: editor.c,v 1.143 2008/01/06 22:28:13 krw Exp $";
+static char rcsid[] = "$OpenBSD: editor.c,v 1.144 2008/01/07 16:51:35 krw Exp $";
#endif /* not lint */
#include <sys/types.h>
@@ -72,7 +72,6 @@ void editor_name(struct disklabel *, char **, char *);
char *getstring(char *, char *, char *);
u_int64_t getuint(struct disklabel *, int, char *, char *, u_int64_t, u_int64_t, u_int64_t, int);
int has_overlap(struct disklabel *, u_int64_t *, int);
-u_int64_t next_offset(struct disklabel *, u_int64_t *);
int partition_cmp(const void *, const void *);
struct partition **sort_partitions(struct disklabel *, u_int16_t *);
void getdisktype(struct disklabel *, char *, char *);
@@ -87,7 +86,7 @@ int get_bsize(struct disklabel *, int);
int get_fsize(struct disklabel *, int);
int get_fstype(struct disklabel *, int);
int get_mp(struct disklabel *, char **, int);
-int get_offset(struct disklabel *, int);
+int get_offset(struct disklabel *, int, struct diskchunk *);
int get_size(struct disklabel *, int, u_int64_t *, int);
void get_geometry(int, struct disklabel **);
void set_geometry(struct disklabel *, struct disklabel *, struct disklabel *,
@@ -496,8 +495,20 @@ editor_add(struct disklabel *lp, char **mp, u_int64_t *freep, char *p)
/* Set defaults */
memset(pp, 0, sizeof(*pp));
- new_size = *freep;
- new_offset = next_offset(lp, &new_size);
+ chunks = free_chunks(lp);
+
+ /*
+ * Since we know there's free space, there must be at least one
+ * chunk. So find the largest chunk and assume we want to add the
+ * partition in that free space.
+ */
+ new_size = new_offset = 0;
+ for (i = 0; chunks[i].start != 0 || chunks[i].stop != 0; i++) {
+ if (chunks[i].stop - chunks[i].start > new_size) {
+ new_size = chunks[i].stop - chunks[i].start;
+ new_offset = chunks[i].start;
+ }
+ }
DL_SETPSIZE(pp, new_size);
DL_SETPOFFSET(pp, new_offset);
pp->p_fstype = partno == 1 ? FS_SWAP : FS_BSDFFS;
@@ -511,24 +522,11 @@ editor_add(struct disklabel *lp, char **mp, u_int64_t *freep, char *p)
pp->p_cpg = 1;
/* Get offset */
- if (get_offset(lp, partno) != 0) {
+ if (get_offset(lp, partno, chunks) != 0) {
DL_SETPSIZE(pp, 0); /* effective delete */
return;
}
- /* Recompute recommended size based on new offset */
- ui = pp->p_fstype;
- pp->p_fstype = FS_UNUSED;
- chunks = free_chunks(lp);
- for (i = 0; chunks[i].start != 0 || chunks[i].stop != 0; i++) {
- if (DL_GETPOFFSET(pp) >= chunks[i].start &&
- DL_GETPOFFSET(pp) < chunks[i].stop) {
- DL_SETPSIZE(pp, chunks[i].stop - DL_GETPOFFSET(pp));
- break;
- }
- }
- pp->p_fstype = ui;
-
/* Get size */
if (get_size(lp, partno, freep, 1) != 0 || DL_GETPSIZE(pp) == 0) {
DL_SETPSIZE(pp, 0); /* effective delete */
@@ -600,7 +598,8 @@ void
editor_modify(struct disklabel *lp, char **mp, u_int64_t *freep, char *p)
{
struct partition origpart, *pp;
- int partno;
+ struct diskchunk *chunks;
+ int partno, i;
/* Change which partition? */
if (p == NULL) {
@@ -626,27 +625,13 @@ editor_modify(struct disklabel *lp, char **mp, u_int64_t *freep, char *p)
origpart = *pp;
- /* Get filesystem type */
- if (get_fstype(lp, partno) != 0) {
- *pp = origpart; /* undo changes */
- return;
- }
-
- /* Ensure a newly enabled partition fits. */
- if (pp->p_fstype != FS_UNUSED && pp->p_fstype != FS_BOOT &&
- (origpart.p_fstype == FS_UNUSED || origpart.p_fstype == FS_BOOT)) {
- if (DL_GETPSIZE(pp) > *freep) {
- fprintf(stderr,
- "Warning, need %llu sectors but there are only %llu "
- "free. Setting size to %llu.\n", DL_GETPSIZE(pp), *freep,
- *freep);
- DL_SETPSIZE(pp, *freep);
- }
- }
+ pp->p_fstype = FS_UNUSED;
+ chunks = free_chunks(lp);
editor_countfree(lp, freep);
+ pp->p_fstype = origpart.p_fstype;
/* Get offset */
- if (get_offset(lp, partno) != 0) {
+ if (get_offset(lp, partno, chunks) != 0) {
*pp = origpart; /* undo changes */
return;
}
@@ -657,6 +642,12 @@ editor_modify(struct disklabel *lp, char **mp, u_int64_t *freep, char *p)
return;
}
+ /* Get filesystem type */
+ if (get_fstype(lp, partno) != 0) {
+ *pp = origpart; /* undo changes */
+ return;
+ }
+
/* get mount point */
if (get_mp(lp, mp, partno) != 0) {
*pp = origpart; /* undo changes */
@@ -724,70 +715,6 @@ editor_delete(struct disklabel *lp, char **mp, u_int64_t *freep, char *p)
}
/*
- * Find the next reasonable starting offset and returns it.
- * Assumes there is a least one free sector left (returns 0 if not).
- */
-u_int64_t
-next_offset(struct disklabel *lp, u_int64_t *sizep)
-{
- struct partition **spp;
- struct diskchunk *chunks;
- u_int16_t npartitions;
- u_int64_t new_offset, new_size;
- int i, good_offset;
-
- /* Get a sorted list of the partitions */
- if ((spp = sort_partitions(lp, &npartitions)) == NULL)
- return(starting_sector);
-
- new_offset = starting_sector;
- for (i = 0; i < npartitions; i++ ) {
- u_int64_t pstart = DL_GETPOFFSET(spp[i]);
- u_int64_t pend = pstart + DL_GETPSIZE(spp[i]);
- u_int64_t newend = new_offset + *sizep;
-
- /*
- * Is new_offset inside this partition? If so,
- * make it the next sector after the partition ends.
- */
- if (pend < ending_sector &&
- ((new_offset >= pstart && new_offset < pend) ||
- (newend > pstart && newend <= pend)))
- new_offset = pend;
- }
-
- /* Did we find a suitable offset? */
- for (good_offset = 1, i = 0; i < npartitions; i++ ) {
- u_int64_t pstart = DL_GETPOFFSET(spp[i]);
- u_int64_t pend = pstart + DL_GETPSIZE(spp[i]);
- u_int64_t newend = new_offset + *sizep;
-
- if (newend > pstart && newend <= pend) {
- /* Nope */
- good_offset = 0;
- break;
- }
- }
-
- /* Specified size is too big, find something that fits */
- if (!good_offset) {
- chunks = free_chunks(lp);
- new_size = 0;
- for (i = 0; chunks[i].start != 0 || chunks[i].stop != 0; i++) {
- if (chunks[i].stop - chunks[i].start > new_size) {
- new_size = chunks[i].stop - chunks[i].start;
- new_offset = chunks[i].start;
- }
- }
- /* XXX - should do something intelligent if new_size == 0 */
- *sizep = new_size;
- }
-
- (void)free(spp);
- return(new_offset);
-}
-
-/*
* Change the size of an existing partition.
*/
void
@@ -1818,10 +1745,11 @@ mpsave(struct disklabel *lp, char **mp, char *cdev, char *fstabfile)
}
int
-get_offset(struct disklabel *lp, int partno)
+get_offset(struct disklabel *lp, int partno, struct diskchunk *chunks)
{
struct partition *pp = &lp->d_partitions[partno];
- u_int64_t ui;
+ u_int64_t ui, maxsize;
+ int i;
for (;;) {
ui = getuint(lp, partno, "offset",
@@ -1845,11 +1773,21 @@ get_offset(struct disklabel *lp, int partno)
fprintf(stderr, "This architecture requires that "
"partition 'a' start at sector 0.\n");
#endif
- else
- break;
+ else {
+ for (i = 0; chunks[i].start != 0 || chunks[i].stop != 0;
+ i++) {
+ if (ui < chunks[i].start ||
+ ui >= chunks[i].stop)
+ continue;
+ DL_SETPOFFSET(pp, ui);
+ maxsize = chunks[i].stop - DL_GETPOFFSET(pp);
+ if (DL_GETPSIZE(pp) > maxsize)
+ DL_SETPSIZE(pp, maxsize);
+ return (0);
+ }
+ fputs("The offset must be in a free area.\n", stderr);
+ }
}
- DL_SETPOFFSET(pp, ui);
- return(0);
}
int