1 /* $NetBSD: label.c,v 1.53 2009/02/22 11:21:56 ad Exp $ */
4 * Copyright 1997 Jonathan Stone
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed for the NetBSD Project by
19 * 4. The name of Jonathan Stone may not be used to endorse
20 * or promote products derived from this software without specific prior
23 * THIS SOFTWARE IS PROVIDED BY JONATHAN STONE ``AS IS''
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33 * THE POSSIBILITY OF SUCH DAMAGE.
37 #include <sys/cdefs.h>
38 #if defined(LIBC_SCCS) && !defined(lint)
39 __RCSID("$NetBSD: label.c,v 1.53 2009/02/22 11:21:56 ad Exp $");
42 #include <sys/types.h>
50 #include <sys/param.h>
51 #include <ufs/ffs/fs.h>
55 #include "menu_defs.h"
57 struct ptn_menu_info
{
59 #define PIF_SHOW_UNUSED 1
65 static int boringpart(partinfo
*, int, int, int);
66 static uint32_t getpartoff(uint32_t);
67 static uint32_t getpartsize(uint32_t, uint32_t);
69 static int checklabel(partinfo
*, int, int, int, int *, int *);
70 static int atofsb(const char *, uint32_t *, uint32_t *);
74 * Return 1 if partition i in lp should be ignored when checking
75 * for overlapping partitions.
78 boringpart(partinfo
*lp
, int i
, int rawpart
, int bsdpart
)
81 if (i
== rawpart
|| i
== bsdpart
||
82 lp
[i
].pi_fstype
== FS_UNUSED
|| lp
[i
].pi_size
== 0)
90 * Check a sysinst label structure for overlapping partitions.
91 * Returns 0 if no overlapping partition found, nonzero otherwise.
92 * Sets reference arguments ovly1 and ovly2 to the indices of
93 * overlapping partitions if any are found.
96 checklabel(partinfo
*lp
, int nparts
, int rawpart
, int bsdpart
,
97 int *ovly1
, int *ovly2
)
105 for (i
= 0; i
< nparts
- 1; i
++ ) {
106 partinfo
*ip
= &lp
[i
];
107 uint32_t istart
, istop
;
109 /* skip unused or reserved partitions */
110 if (boringpart(lp
, i
, rawpart
, bsdpart
))
114 * check succeeding partitions for overlap.
115 * O(n^2), but n is small (currently <= 16).
117 istart
= ip
->pi_offset
;
118 istop
= istart
+ ip
->pi_size
;
120 for (j
= i
+1; j
< nparts
; j
++) {
121 partinfo
*jp
= &lp
[j
];
122 uint32_t jstart
, jstop
;
124 /* skip unused or reserved partitions */
125 if (boringpart(lp
, j
, rawpart
, bsdpart
))
128 jstart
= jp
->pi_offset
;
129 jstop
= jstart
+ jp
->pi_size
;
132 if ((istart
<= jstart
&& jstart
< istop
) ||
133 (jstart
<= istart
&& istart
< jstop
)) {
145 check_one_root(partinfo
*lp
, int nparts
)
150 for (part
= 0; part
< nparts
; lp
++, part
++) {
155 if (!(lp
->pi_flags
& PIF_MOUNT
))
157 if (strcmp(lp
->pi_mount
, "/") != 0)
163 /* Save partition number, a few things need to know it */
170 edit_fs_start(menudesc
*m
, void *arg
)
175 start
= getpartoff(p
->pi_offset
);
176 if (p
->pi_size
!= 0) {
177 /* Try to keep end in the same place */
178 end
= p
->pi_offset
+ p
->pi_size
;
182 p
->pi_size
= end
- start
;
184 p
->pi_offset
= start
;
189 edit_fs_size(menudesc
*m
, void *arg
)
194 size
= getpartsize(p
->pi_offset
, p
->pi_size
);
196 size
= dlsize
- p
->pi_offset
;
202 set_ptype(partinfo
*p
, int fstype
, int flag
)
204 p
->pi_flags
= (p
->pi_flags
& ~PIF_FFSv2
) | flag
;
206 if (p
->pi_fstype
== fstype
)
209 p
->pi_fstype
= fstype
;
210 if (fstype
== FS_BSDFFS
|| fstype
== FS_BSDLFS
) {
212 /* match newfs defaults for fragments size (2k if >= 1024MB) */
213 p
->pi_fsize
= p
->pi_size
> 1024*1024*1024 / 512 ? 2048 : 1024;
215 /* zero - fields not used */
222 set_bsize(partinfo
*p
, int size
)
236 p
->pi_fsize
= size
/ frags
;
240 set_fsize(partinfo
*p
, int fsize
)
242 int bsz
= p
->pi_fsize
* p
->pi_frag
;
243 int frags
= bsz
/ fsize
;
255 edit_fs_isize(menudesc
*m
, void *arg
)
260 snprintf(answer
, sizeof answer
, "%u", p
->pi_isize
);
261 msg_prompt_win(MSG_fs_isize
, -1, 18, 0, 0,
262 answer
, answer
, sizeof answer
);
263 p
->pi_isize
= atol(answer
);
269 edit_fs_preserve(menudesc
*m
, void *arg
)
273 p
->pi_flags
^= PIF_NEWFS
;
278 edit_fs_mount(menudesc
*m
, void *arg
)
282 p
->pi_flags
^= PIF_MOUNT
;
287 edit_fs_mountpt(menudesc
*m
, void *arg
)
291 msg_prompt_win(MSG_mountpoint
, -1, 18, 0, 0,
292 p
->pi_mount
, p
->pi_mount
, sizeof p
->pi_mount
);
294 if (p
->pi_mount
[0] == ' ' || strcmp(p
->pi_mount
, "none") == 0) {
299 if (p
->pi_mount
[0] != '/') {
300 memmove(p
->pi_mount
+ 1, p
->pi_mount
,
301 sizeof p
->pi_mount
- 1);
302 p
->pi_mount
[sizeof p
->pi_mount
- 1] = 0;
303 p
->pi_mount
[0] = '/';
310 edit_restore(menudesc
*m
, void *arg
)
314 p
->pi_flags
|= PIF_RESET
;
319 set_fstype(menudesc
*m
, void *arg
)
323 if (m
->cursel
== FS_UNUSED
)
324 memset(p
, 0, sizeof *p
);
326 p
->pi_fstype
= m
->cursel
;
331 get_fstype(menudesc
*m
, void *arg
)
335 m
->cursel
= p
->pi_fstype
;
338 static void set_ptn_header(menudesc
*m
, void *arg
);
339 static void set_ptn_label(menudesc
*m
, int opt
, void *arg
);
340 int all_fstype_menu
= -1;
343 edit_ptn(menudesc
*menu
, void *arg
)
345 static menu_ent fs_fields
[] = {
346 #define PTN_MENU_FSKIND 0
347 {NULL
, MENU_selfskind
, OPT_SUB
, NULL
},
348 #define PTN_MENU_START 1
349 {NULL
, OPT_NOMENU
, 0, edit_fs_start
},
350 #define PTN_MENU_SIZE 2
351 {NULL
, OPT_NOMENU
, 0, edit_fs_size
},
352 #define PTN_MENU_END 3
353 {NULL
, OPT_NOMENU
, OPT_IGNORE
, NULL
}, /* displays 'end' */
354 #define PTN_MENU_NEWFS 4
355 {NULL
, OPT_NOMENU
, 0, edit_fs_preserve
},
356 #define PTN_MENU_ISIZE 5
357 {NULL
, OPT_NOMENU
, 0, edit_fs_isize
},
358 #define PTN_MENU_BSIZE 6
359 {NULL
, MENU_selbsize
, OPT_SUB
, NULL
},
360 #define PTN_MENU_FSIZE 7
361 {NULL
, MENU_selfsize
, OPT_SUB
, NULL
},
362 #define PTN_MENU_MOUNT 8
363 {NULL
, OPT_NOMENU
, 0, edit_fs_mount
},
364 #define PTN_MENU_MOUNTOPT 9
365 {NULL
, MENU_mountoptions
, OPT_SUB
, NULL
},
366 #define PTN_MENU_MOUNTPT 10
367 {NULL
, OPT_NOMENU
, 0, edit_fs_mountpt
},
368 {MSG_askunits
, MENU_sizechoice
, OPT_SUB
, NULL
},
369 {MSG_restore
, OPT_NOMENU
, 0, edit_restore
},
371 static int fspart_menu
= -1;
372 static menu_ent all_fstypes
[FSMAXTYPES
];
376 if (fspart_menu
== -1) {
377 fspart_menu
= new_menu(NULL
, fs_fields
, nelem(fs_fields
),
379 MC_NOBOX
| MC_NOCLEAR
| MC_SCROLL
,
380 set_ptn_header
, set_ptn_label
, NULL
,
381 NULL
, MSG_partition_sizes_ok
);
384 if (all_fstype_menu
== -1) {
385 for (i
= 0; i
< nelem(all_fstypes
); i
++) {
386 all_fstypes
[i
].opt_name
= fstypenames
[i
];
387 all_fstypes
[i
].opt_menu
= OPT_NOMENU
;
388 all_fstypes
[i
].opt_flags
= 0;
389 all_fstypes
[i
].opt_action
= set_fstype
;
391 all_fstype_menu
= new_menu(MSG_Select_the_type
,
392 all_fstypes
, nelem(all_fstypes
),
393 30, 6, 10, 0, MC_SUBMENU
| MC_SCROLL
,
394 get_fstype
, NULL
, NULL
, NULL
, MSG_unchanged
);
397 p
= bsdlabel
+ menu
->cursel
;
398 p
->pi_flags
&= ~PIF_RESET
;
401 process_menu(fspart_menu
, p
);
402 if (!(p
->pi_flags
& PIF_RESET
))
411 set_ptn_header(menudesc
*m
, void *arg
)
418 msg_table_add(MSG_edfspart
, 'a' + (p
- bsdlabel
));
420 /* Determine which of the properties can be changed */
421 for (i
= PTN_MENU_START
; i
<= PTN_MENU_MOUNTPT
; i
++) {
422 /* Default to disabled... */
423 m
->opts
[i
].opt_flags
|= OPT_IGNORE
;
425 if (i
== PTN_MENU_END
)
426 /* The 'end address' is calculated from the size */
428 if (t
== FS_UNUSED
|| (t
== FS_SWAP
&& i
> PTN_MENU_END
)) {
429 /* Nothing after 'size' can be set for swap/unused */
430 p
->pi_flags
&= ~(PIF_NEWFS
| PIF_MOUNT
);
434 if (i
== PTN_MENU_NEWFS
&& t
!= FS_BSDFFS
&& t
!= FS_BSDLFS
435 && t
!= FS_APPLEUFS
) {
436 /* Can only newfs UFS and LFS filesystems */
437 p
->pi_flags
&= ~PIF_NEWFS
;
440 if (i
>= PTN_MENU_ISIZE
&& i
<= PTN_MENU_FSIZE
) {
441 /* Parameters for newfs... */
442 if (!(p
->pi_flags
& PIF_NEWFS
))
443 /* Not if we aren't going to run newfs */
445 if (t
== FS_APPLEUFS
&& i
!= PTN_MENU_ISIZE
)
446 /* Can only set # inodes for appleufs */
448 if (t
== FS_BSDLFS
&& i
!= PTN_MENU_BSIZE
)
449 /* LFS doesn't have fragments */
452 /* Ok: we want this one */
453 m
->opts
[i
].opt_flags
&= ~OPT_IGNORE
;
458 disp_sector_count(menudesc
*m
, msg fmt
, uint s
)
460 uint ms
= MEG
/ sectorsize
;
462 wprintw(m
->mw
, msg_string(fmt
),
463 s
/ ms
, s
/ dlcylsize
, s
% dlcylsize
? '*' : ' ', s
);
467 set_ptn_label(menudesc
*m
, int opt
, void *arg
)
472 if (m
->opts
[opt
].opt_flags
& OPT_IGNORE
473 && (opt
!= PTN_MENU_END
|| p
->pi_fstype
== FS_UNUSED
)) {
474 wprintw(m
->mw
, " -");
479 case PTN_MENU_FSKIND
:
480 if (p
->pi_fstype
== FS_BSDFFS
)
481 if (p
->pi_flags
& PIF_FFSv2
)
486 c
= fstypenames
[p
->pi_fstype
];
487 wprintw(m
->mw
, msg_string(MSG_fstype_fmt
), c
);
490 disp_sector_count(m
, MSG_start_fmt
, p
->pi_offset
);
493 disp_sector_count(m
, MSG_size_fmt
, p
->pi_size
);
496 disp_sector_count(m
, MSG_end_fmt
, p
->pi_offset
+ p
->pi_size
);
499 wprintw(m
->mw
, msg_string(MSG_newfs_fmt
),
500 msg_string(p
->pi_flags
& PIF_NEWFS
? MSG_Yes
: MSG_No
));
503 wprintw(m
->mw
, msg_string(p
->pi_isize
> 0 ?
504 MSG_isize_fmt
: MSG_isize_fmt_dflt
), p
->pi_isize
);
507 wprintw(m
->mw
, msg_string(MSG_bsize_fmt
),
508 p
->pi_fsize
* p
->pi_frag
);
511 wprintw(m
->mw
, msg_string(MSG_fsize_fmt
), p
->pi_fsize
);
514 wprintw(m
->mw
, msg_string(MSG_mount_fmt
),
515 msg_string(p
->pi_flags
& PIF_MOUNT
? MSG_Yes
: MSG_No
));
517 case PTN_MENU_MOUNTOPT
:
518 wprintw(m
->mw
, msg_string(MSG_mount_options_fmt
));
519 if (p
->pi_flags
& PIF_ASYNC
)
520 wprintw(m
->mw
, "async ");
521 if (p
->pi_flags
& PIF_NOATIME
)
522 wprintw(m
->mw
, "noatime ");
523 if (p
->pi_flags
& PIF_NODEV
)
524 wprintw(m
->mw
, "nodev ");
525 if (p
->pi_flags
& PIF_NODEVMTIME
)
526 wprintw(m
->mw
, "nodevmtime ");
527 if (p
->pi_flags
& PIF_NOEXEC
)
528 wprintw(m
->mw
, "noexec ");
529 if (p
->pi_flags
& PIF_NOSUID
)
530 wprintw(m
->mw
, "nosuid ");
531 if (p
->pi_flags
& PIF_LOG
)
532 wprintw(m
->mw
, "log ");
534 case PTN_MENU_MOUNTPT
:
535 wprintw(m
->mw
, msg_string(MSG_mountpt_fmt
), p
->pi_mount
);
541 show_all_unused(menudesc
*m
, void *arg
)
543 struct ptn_menu_info
*pi
= arg
;
545 pi
->flags
|= PIF_SHOW_UNUSED
;
550 set_label_texts(menudesc
*menu
, void *arg
)
552 struct ptn_menu_info
*pi
= arg
;
554 int ptn
, show_unused_ptn
;
555 int rawptn
= getrawpartition();
556 int maxpart
= getmaxpartitions();
558 msg_display(MSG_fspart
);
559 msg_table_add(MSG_fspart_header
, multname
, multname
, multname
);
561 for (show_unused_ptn
= 0, ptn
= 0; ptn
< maxpart
; ptn
++) {
562 m
= &menu
->opts
[ptn
];
563 m
->opt_menu
= OPT_NOMENU
;
565 m
->opt_action
= edit_ptn
;
571 m
->opt_flags
= OPT_IGNORE
;
574 if (bsdlabel
[ptn
].pi_fstype
== FS_UNUSED
)
577 show_unused_ptn
= ptn
+ 2;
580 if (!(pi
->flags
& PIF_SHOW_UNUSED
) && ptn
> show_unused_ptn
) {
581 ptn
= show_unused_ptn
;
582 m
= &menu
->opts
[ptn
];
583 m
->opt_name
= MSG_show_all_unused_partitions
;
584 m
->opt_action
= show_all_unused
;
588 m
= &menu
->opts
[ptn
];
589 m
->opt_menu
= MENU_sizechoice
;
590 m
->opt_flags
= OPT_SUB
;
591 m
->opt_action
= NULL
;
592 m
->opt_name
= MSG_askunits
;
594 menu
->numopts
= ptn
+ 1;
599 * If there are overlapping active partitions,
600 * Ask the user if they want to edit the partition or give up.
603 edit_and_check_label(partinfo
*lp
, int nparts
, int rawpart
, int bsdpart
)
605 static struct menu_ent
*menu
;
606 static int menu_no
= -1;
607 static struct ptn_menu_info pi
;
608 int maxpart
= getmaxpartitions();
611 menu
= malloc((maxpart
+ 1) * sizeof *menu
);
617 menu_no
= new_menu(NULL
, menu
, maxpart
+ 1,
618 0, -1, maxpart
+ 2, 74,
619 MC_ALWAYS_SCROLL
| MC_NOBOX
| MC_DFLTEXIT
,
620 set_label_texts
, fmt_fspart
, NULL
, NULL
,
621 MSG_partition_sizes_ok
);
628 current_cylsize
= dlcylsize
;
633 /* first give the user the option to edit the label... */
634 process_menu(menu_no
, &pi
);
636 /* User thinks the label is OK. */
637 /* check we have a single root fs */
638 if (check_one_root(lp
, nparts
) == 0)
639 msg_display(MSG_must_be_one_root
);
641 /* Check for overlaps */
642 if (checklabel(lp
, nparts
, rawpart
, bsdpart
, &i
, &j
))
643 /* partitions overlap */
644 msg_display(MSG_partitions_overlap
,'a'+i
,'a'+j
);
649 msg_display_add(MSG_edit_partitions_again
);
650 process_menu(MENU_yesno
, NULL
);
659 * Read a label from disk into a sysinst label structure.
662 incorelabel(const char *dkname
, partinfo
*lp
)
664 struct disklabel lab
;
666 struct partition
*pp
;
670 if (get_real_geom(dkname
, &lab
) == 0)
674 maxpart
= getmaxpartitions();
675 if (maxpart
> MAXPARTITIONS
)
676 maxpart
= MAXPARTITIONS
;
677 if (maxpart
> lab
.d_npartitions
)
678 maxpart
= lab
.d_npartitions
;
681 * Historically sysinst writes the name to d_typename rather
682 * than d_diskname. Who knows why, but pull the value back here.
684 if (lab
.d_typename
[0] != 0 && strcmp(lab
.d_typename
, "unknown") != 0)
685 strlcpy(bsddiskname
, lab
.d_typename
, sizeof bsddiskname
);
687 fd
= opendisk(dkname
, O_RDONLY
, buf
, sizeof buf
, 0);
688 pp
= &lab
.d_partitions
[0];
689 for (i
= 0; i
< maxpart
; lp
++, pp
++, i
++) {
690 lp
->pi_partition
= *pp
;
691 if (lp
->pi_fstype
>= FSMAXTYPES
)
692 lp
->pi_fstype
= FS_OTHER
;
693 strlcpy(lp
->pi_mount
, get_last_mounted(fd
, pp
->p_offset
, lp
),
694 sizeof lp
->pi_mount
);
703 * Try to get 'last mounted on' (or equiv) from fs superblock.
706 get_last_mounted(int fd
, int partstart
, partinfo
*lp
)
708 static char sblk
[SBLOCKSIZE
]; /* is this enough? */
709 #define SB ((struct fs *)sblk)
710 static const int sblocks
[] = SBLOCKSEARCH
;
713 const char *mnt
= NULL
;
719 /* Check UFS1/2 (and hence LFS) superblock */
720 for (sbp
= sblocks
; mnt
== NULL
&& *sbp
!= -1; sbp
++) {
721 if (pread(fd
, sblk
, sizeof sblk
,
722 partstart
* (off_t
)512 + *sbp
) != sizeof sblk
)
724 /* Maybe we should validate the checksum??? */
725 switch (((struct fs
*)sblk
)->fs_magic
) {
727 case FS_UFS1_MAGIC_SWAPPED
:
728 if (!(SB
->fs_old_flags
& FS_FLAGS_UPDATED
)) {
729 if (*sbp
== SBLOCK_UFS1
)
730 mnt
= (const char *)SB
->fs_fsmnt
;
732 /* Check we have the main superblock */
733 if (SB
->fs_sblockloc
== *sbp
)
734 mnt
= (const char *)SB
->fs_fsmnt
;
738 case FS_UFS2_MAGIC_SWAPPED
:
739 /* Check we have the main superblock */
740 if (SB
->fs_sblockloc
== *sbp
) {
741 mnt
= (const char *)SB
->fs_fsmnt
;
743 lp
->pi_flags
|= PIF_FFSv2
;
748 #if 0 /* Requires fs/ext2fs/ext2fs.h which collides badly... */
749 if ((struct ext2fs
*)sblk
)->e2fs_magic
== E2FS_MAGIC
) {
750 mnt
= ((struct ext2fs
*)sblk
)->e2fs_fsmnt
;
757 /* If start of partition check for other fs types */
758 if (sblk
[0x42] == 0x29 && memcmp(sblk
+ 0x52, "FAT", 3) == 0) {
759 /* Probably a FAT filesystem, report volume name */
760 cp
= strchr(sblk
+ 0x47, ' ');
761 if (cp
== NULL
|| cp
- (sblk
+ 0x47) > 11)
762 cp
= sblk
+ 0x47 + 11;
771 /* If sysinst mounted this last then strip prefix */
772 len
= strlen(targetroot_mnt
);
773 if (memcmp(mnt
, targetroot_mnt
, len
) == 0) {
783 /* Ask for a partition offset, check bounds and do the needed roundups */
785 getpartoff(uint32_t defpartstart
)
787 char defsize
[20], isize
[20], maxpartc
;
789 uint32_t localsizemult
;
791 const char *errmsg
= "\n";
793 maxpartc
= 'a' + getmaxpartitions() - 1;
795 snprintf(defsize
, sizeof defsize
, "%d", defpartstart
/sizemult
);
796 msg_prompt_win(MSG_label_offset
, -1, 13, 70, 9,
797 (defpartstart
> 0) ? defsize
: NULL
, isize
, sizeof isize
,
798 errmsg
, maxpartc
, maxpartc
, multname
);
799 if (strcmp(defsize
, isize
) == 0)
800 /* Don't do rounding if default accepted */
802 if (isize
[1] == '\0' && isize
[0] >= 'a' &&
803 isize
[0] <= maxpartc
) {
804 partn
= isize
[0] - 'a';
805 i
= bsdlabel
[partn
].pi_size
+ bsdlabel
[partn
].pi_offset
;
807 } else if (atoi(isize
) == -1) {
811 if (atofsb(isize
, &i
, &localsizemult
)) {
812 errmsg
= msg_string(MSG_invalid_sector_number
);
816 /* round to cylinder size if localsizemult != 1 */
817 i
= NUMSEC(i
/localsizemult
, localsizemult
, dlcylsize
);
818 /* Adjust to start of slice if needed */
819 if ((i
< ptstart
&& (ptstart
- i
) < localsizemult
) ||
820 (i
> ptstart
&& (i
- ptstart
) < localsizemult
)) {
825 errmsg
= msg_string(MSG_startoutsidedisk
);
831 /* Ask for a partition size, check bounds and do the needed roundups */
833 getpartsize(uint32_t partstart
, uint32_t defpartsize
)
835 char dsize
[20], isize
[20], maxpartc
;
836 const char *errmsg
= "\n";
837 uint32_t i
, partend
, localsizemult
;
838 uint32_t fsptend
= ptstart
+ ptsize
;
841 maxpartc
= 'a' + getmaxpartitions() - 1;
843 snprintf(dsize
, sizeof dsize
, "%d", defpartsize
/sizemult
);
844 msg_prompt_win(MSG_label_size
, -1, 12, 70, 9,
845 (defpartsize
!= 0) ? dsize
: 0, isize
, sizeof isize
,
846 errmsg
, maxpartc
, multname
);
847 if (strcmp(isize
, dsize
) == 0)
849 if (isize
[1] == '\0' && isize
[0] >= 'a' &&
850 isize
[0] <= maxpartc
) {
851 partn
= isize
[0] - 'a';
852 i
= bsdlabel
[partn
].pi_offset
- partstart
;
854 } else if (atoi(isize
) == -1) {
855 i
= fsptend
- partstart
;
858 if (atofsb(isize
, &i
, &localsizemult
)) {
859 errmsg
= msg_string(MSG_invalid_sector_number
);
864 * partend is aligned to a cylinder if localsizemult
867 partend
= NUMSEC((partstart
+ i
) / localsizemult
,
868 localsizemult
, dlcylsize
);
869 /* Align to end-of-disk or end-of-slice if close enough */
870 if (partend
> (dlsize
- localsizemult
)
871 && partend
< (dlsize
+ localsizemult
))
873 if (partend
> (fsptend
- localsizemult
)
874 && partend
< (fsptend
+ localsizemult
))
877 if (partend
> dlsize
) {
879 msg_prompt_win(MSG_endoutsidedisk
, -1, 13, 70, 6,
881 (partend
- partstart
) / sizemult
, multname
);
883 return (partend
- partstart
);
889 * convert a string to a number of sectors, with a possible unit
890 * 150M = 150 Megabytes
891 * 2000c = 2000 cylinders
892 * 150256s = 150256 sectors
893 * Without units, use the default (sizemult)
894 * returns the number of sectors, and the unit used (for roundups).
898 atofsb(const char *str
, uint32_t *p_val
, uint32_t *localsizemult
)
903 *localsizemult
= sizemult
;
904 if (str
[0] == '\0') {
908 for (i
= 0; str
[i
] != '\0'; i
++) {
909 if (str
[i
] >= '0' && str
[i
] <= '9') {
910 val
= val
* 10 + str
[i
] - '0';
913 if (str
[i
+ 1] != '\0') {
914 /* A non-digit caracter, not at the end */
917 if (str
[i
] == 'G' || str
[i
] == 'g') {
919 *localsizemult
= MEG
/ sectorsize
;
922 if (str
[i
] == 'M' || str
[i
] == 'm') {
923 *localsizemult
= MEG
/ sectorsize
;
927 *localsizemult
= dlcylsize
;
934 /* not a known unit */
937 *p_val
= val
* (*localsizemult
);