On Saturday 26 July 2014 17:38:06 Fung wrote:
> http://www.openbsd.org/faq/faq4.html#Morefdisk
> 
> uh-oh! What's our offset? Simple -- the offset of the previous partition
> plus the size of the partition, in this case, 63+10490382 = 10490445.
> 
> offset: [0] 10490445
> size: [0] *
> fdisk:*1>
> 
> in this situation, default offset = 0  , may this fuction change to auto
> caculate the default to 10490445 ? just like
> offset: [10490445]

Yes, it can. Bitrig already does it, so find the patch below. I had it in my 
tree for some time and already tested it on amd64.

Best regards,
Markus


Index: cmd.c
===================================================================
RCS file: /cvs/src/sbin/fdisk/cmd.c,v
retrieving revision 1.71
diff -u -p -u -r1.71 cmd.c
--- cmd.c       31 Mar 2014 23:04:03 -0000      1.71
+++ cmd.c       26 Jul 2014 17:49:05 -0000
@@ -141,7 +141,7 @@ Xedit(char *args, struct disk *disk, str
     int offset)
 {
        const char *errstr;
-       int pn, num, ret;
+       int pn, num, ret, new;
        struct prt *pp;
 
        pn = strtonum(args, 0, 3, &errstr);
@@ -151,6 +151,8 @@ Xedit(char *args, struct disk *disk, str
        }
        pp = &mbr->part[pn];
 
+       new = (pp->id == DOSPTYP_UNUSED);
+
        /* Edit partition type */
        ret = Xsetpid(args, disk, mbr, tt, offset);
 
@@ -165,6 +167,10 @@ Xedit(char *args, struct disk *disk, str
                printf("Partition %d is disabled.\n", pn);
                return (ret);
        }
+
+       /* Use remaining free space for new partitions */
+       if (new)
+               MBR_fillremaining(mbr, disk, pn);
 
        /* Change table entry */
        if (ask_yn("Do you wish to edit in CHS mode?")) {
Index: mbr.c
===================================================================
RCS file: /cvs/src/sbin/fdisk/mbr.c,v
retrieving revision 1.40
diff -u -p -u -r1.40 mbr.c
--- mbr.c       21 May 2014 15:55:19 -0000      1.40
+++ mbr.c       26 Jul 2014 17:49:05 -0000
@@ -57,54 +57,16 @@ MBR_init(struct disk *disk, struct mbr *
        mbr->part[2].flag = 0;
 
        mbr->part[3].flag = DOSACTIVE;
-       mbr->signature = DOSMBR_SIGNATURE;
-
-       /* Use whole disk. Reserve first track, or first cyl, if possible. */
        mbr->part[3].id = DOSPTYP_OPENBSD;
-       if (disk->heads > 1)
-               mbr->part[3].shead = 1;
-       else
-               mbr->part[3].shead = 0;
-       if (disk->heads < 2 && disk->cylinders > 1)
-               mbr->part[3].scyl = 1;
-       else
-               mbr->part[3].scyl = 0;
-       mbr->part[3].ssect = 1;
-
-       /* Go right to the end */
-       mbr->part[3].ecyl = disk->cylinders - 1;
-       mbr->part[3].ehead = disk->heads - 1;
-       mbr->part[3].esect = disk->sectors;
-
-       /* Fix up start/length fields */
-       PRT_fix_BN(disk, &mbr->part[3], 3);
+       mbr->signature = DOSMBR_SIGNATURE;
 
 #if defined(__powerpc__) || defined(__mips__)
        /* Now fix up for the MS-DOS boot partition on PowerPC. */
        mbr->part[0].flag = DOSACTIVE;  /* Boot from dos part */
        mbr->part[3].flag = 0;
-       mbr->part[3].ns += mbr->part[3].bs;
-       mbr->part[3].bs = mbr->part[0].bs + mbr->part[0].ns;
-       mbr->part[3].ns -= mbr->part[3].bs;
-       PRT_fix_CHS(disk, &mbr->part[3]);
-       if ((mbr->part[3].shead != 1) || (mbr->part[3].ssect != 1)) {
-               /* align the partition on a cylinder boundary */
-               mbr->part[3].shead = 0;
-               mbr->part[3].ssect = 1;
-               mbr->part[3].scyl += 1;
-       }
-       /* Fix up start/length fields */
-       PRT_fix_BN(disk, &mbr->part[3], 3);
 #endif
 
-       /* Start OpenBSD MBR partition on a power of 2 block number. */
-       i = 1;
-       while (i < DL_SECTOBLK(&dl, mbr->part[3].bs))
-               i *= 2;
-       adj = DL_BLKTOSEC(&dl, i) - mbr->part[3].bs;
-       mbr->part[3].bs += adj;
-       mbr->part[3].ns -= adj; 
-       PRT_fix_CHS(disk, &mbr->part[3]);
+       MBR_fillremaining(mbr, disk, 3);
 }
 
 void
@@ -257,4 +219,68 @@ MBR_pcopy(struct disk *disk, struct mbr 
 
        for (i = 0; i < NDOSPART; i++)
                PRT_parse(disk, &dos_parts[i], 0, 0, &mbr->part[i]);
+}
+
+void
+MBR_fillremaining(struct mbr *mbr, struct disk *disk, int pn)
+{
+       struct prt *part, *p;
+       u_int64_t adj;
+       daddr_t i;
+
+       part = &mbr->part[pn];
+
+       /* Use whole disk. Reserve first track, or first cyl, if possible. */
+       if (disk->heads > 1)
+               part->shead = 1;
+       else
+               part->shead = 0;
+       if (disk->heads < 2 && disk->cylinders > 1)
+               part->scyl = 1;
+       else
+               part->scyl = 0;
+       part->ssect = 1;
+
+       /* Go right to the end */
+       part->ecyl = disk->cylinders - 1;
+       part->ehead = disk->heads - 1;
+       part->esect = disk->sectors;
+
+       /* Fix up start/length fields */
+       PRT_fix_BN(disk, part, pn);
+
+#if defined(__powerpc__) || defined(__mips__)
+       if ((part->shead != 1) || (part->ssect != 1)) {
+               /* align the partition on a cylinder boundary */
+               part->shead = 0;
+               part->ssect = 1;
+               part->scyl += 1;
+       }
+       /* Fix up start/length fields */
+       PRT_fix_BN(disk, part, pn);
+#endif
+
+       /* Start OpenBSD MBR partition on a power of 2 block number. */
+       i = 1;
+       while (i < DL_SECTOBLK(&dl, part->bs))
+               i *= 2;
+       adj = DL_BLKTOSEC(&dl, i) - part->bs;
+       part->bs += adj;
+       part->ns -= adj;
+       PRT_fix_CHS(disk, part);
+
+       /* Shrink to remaining free space */
+       for (i = 0; i < NDOSPART; i++) {
+               p = &mbr->part[i];
+               if (i != pn && PRT_overlap(part, p)) {
+                       if (p->bs > part->bs) {
+                               part->ns = p->bs - part->bs;
+                       } else {
+                               part->ns += part->bs;
+                               part->bs = p->bs + p->ns;
+                               part->ns -= part->bs;
+                       }
+               }
+       }
+       PRT_fix_CHS(disk, part);
 }
Index: mbr.h
===================================================================
RCS file: /cvs/src/sbin/fdisk/mbr.h,v
retrieving revision 1.17
diff -u -p -u -r1.17 mbr.h
--- mbr.h       23 Mar 2014 13:56:24 -0000      1.17
+++ mbr.h       26 Jul 2014 17:49:05 -0000
@@ -44,5 +44,6 @@ void MBR_init(struct disk *, struct mbr 
 int MBR_read(int, off_t, struct dos_mbr *);
 int MBR_write(int, off_t, struct dos_mbr *);
 void MBR_pcopy(struct disk *, struct mbr *);
+void MBR_fillremaining(struct mbr *, struct disk *, int);
 
 #endif /* _MBR_H */
Index: part.c
===================================================================
RCS file: /cvs/src/sbin/fdisk/part.c,v
retrieving revision 1.66
diff -u -p -u -r1.66 part.c
--- part.c      5 May 2014 17:18:08 -0000       1.66
+++ part.c      26 Jul 2014 17:49:05 -0000
@@ -303,6 +303,12 @@ PRT_print(int num, struct prt *partn, ch
        }
 }
 
+int
+PRT_overlap(struct prt *p1, struct prt *p2)
+{
+       return (p1->bs + p1->ns > p2->bs && p2->bs + p2->ns > p1->bs);
+}
+
 void
 PRT_fix_BN(struct disk *disk, struct prt *part, int pn)
 {
Index: part.h
===================================================================
RCS file: /cvs/src/sbin/fdisk/part.h,v
retrieving revision 1.16
diff -u -p -u -r1.16 part.h
--- part.h      25 Mar 2014 12:59:03 -0000      1.16
+++ part.h      26 Jul 2014 17:49:05 -0000
@@ -43,6 +43,7 @@ void PRT_parse(struct disk *, struct dos
     struct prt *);
 void PRT_make(struct prt *, off_t, off_t, struct dos_partition *);
 void PRT_print(int, struct prt *, char *);
+int PRT_overlap(struct prt *, struct prt *);
 
 /* This does CHS -> bs/ns */
 void PRT_fix_BN(struct disk *, struct prt *, int);

Reply via email to