Hi, > > Minor knits I just noticed ((more for the sake of being clean): > > > > - meaningful errors when missing an argument in -s > > - check for 'id' validity before converting via strtoll(3) > Ok, thank you! the attached patch includes your proposed fixes. Regards, Julian
--- sbin/fdisk/fdisk.8 +++ sbin/fdisk/fdisk.8 @@ -308,10 +308,19 @@ .Ar size , and optionally .Ar bootmenu . This flag requires the use of a partition selection flag .Pq Fl 0 , 1 , 2 , 3 , No or Fl E Ar number . +.Pp +You can modify the values of +.Ar start +and +.Ar size +by +.Em mb , gb , cyl , % , +then specifying the number being counted either in megabytes, gigabytes, +cylinders or percentage of the whole disk size. .It Fl T Ar disktype Use the disklabel .Ar disktype instead of the disklabel on .Ar device .
--- sbin/fdisk/fdisk.c
+++ sbin/fdisk/fdisk.c
@@ -271,10 +271,12 @@
static void get_ptn_alignmemt(void);
#if defined(USE_DISKLIST)
static void get_diskname(const char *, char *, size_t);
#endif
static int change_part(int, int, int, daddr_t, daddr_t, char *);
+static void parse_partstr(char *, int *, daddr_t *, daddr_t *, char **);
+static int64_t parse_smodifier(const char *, int);
static void print_geometry(void);
static int first_active(void);
static void change_active(int);
static void change_bios_geometry(void);
static void dos(int, unsigned char *, unsigned char *, unsigned char *);
@@ -329,18 +331,19 @@
{
struct stat sb;
int ch;
size_t len;
char *cp;
+ static char *partstr;
int n;
#ifdef BOOTSEL
daddr_t default_ptn; /* start sector of default ptn */
char *cbootmenu = 0;
#endif
int csysid; /* For the s_flag. */
- unsigned int cstart, csize;
+ daddr_t cstart, csize;
a_flag = u_flag = sh_flag = f_flag = s_flag = b_flag = 0;
i_flag = B_flag = 0;
v_flag = 0;
E_flag = 0;
csysid = cstart = csize = 0;
@@ -398,22 +401,13 @@
case 'v': /* Be verbose */
v_flag++;
break;
case 's': /* Partition details */
s_flag = 1;
- if (sscanf(optarg, "%d/%u/%u%n", &csysid, &cstart,
- &csize, &n) == 3) {
- if (optarg[n] == 0)
- break;
-#ifdef BOOTSEL
- if (optarg[n] == '/') {
- cbootmenu = optarg + n + 1;
- break;
- }
-#endif
- }
- errx(1, "Bad argument to the -s flag.");
+ partstr = strdup(optarg);
+ if (!partstr)
+ err(1, "Could not allocate string.");
break;
case 'b': /* BIOS geometry */
b_flag = 1;
if (sscanf(optarg, "%d/%d/%d%n", &b_cyl, &b_head,
&b_sec, &n) != 3 || optarg[n] != 0)
@@ -528,13 +522,21 @@
/* Do the update stuff! */
if (u_flag) {
if (!f_flag && !b_flag)
change_bios_geometry();
- if (s_flag)
+ if (s_flag) {
+ parse_partstr(partstr, &csysid, &cstart, &csize,
&cbootmenu);
+#ifndef BOOTSEL
+ if (strlen(cbootmenu))
+ errx(1, "Bad argument to the -s flag: Too many
slashes.");
+#endif
+ free(partstr);
+
change_part(E_flag, partition, csysid, cstart, csize,
cbootmenu);
+ }
else {
int part = partition, chg_ext = E_flag, prompt = 1;
do {
if (prompt) {
printf("\n");
@@ -1953,10 +1955,99 @@
ext.ptn[p].mbr_parts[0].mbrp_type = 0;
}
}
}
return 0;
+}
+
+static int64_t
+parse_smodifier(const char *sizestr, int flags)
+{
+ char *cp;
+ int64_t acc;
+ int valid;
+
+ if (!isdigit((unsigned char)*sizestr))
+ return -1;
+
+ acc = strtoll(sizestr, &cp, 10);
+ valid = 0;
+ if (!strcasecmp(cp, "gb")) {
+ acc *= 1024;
+ valid = 1;
+ }
+ if (valid || !strcmp(cp, "%")) {
+ if (acc < 0 || acc > 100)
+ return -1;
+ acc = disksectors / 100 * acc;
+ }
+ if (valid || !strcasecmp(cp, "mb")) {
+ acc *= SEC_IN_1M;
+ /* round to whole number of cylinders */
+ acc += ptn_alignment / 2;
+ acc /= ptn_alignment;
+ valid = 1;
+ }
+ if (valid || !strcasecmp(cp, "cyl")) {
+ acc *= ptn_alignment;
+ /* adjustments for cylinder boundary */
+ if (acc == 0 && flags & DEC_RND_0)
+ acc += ptn_0_offset;
+ if (flags & DEC_RND)
+ acc += ptn_0_offset;
+ if (flags & DEC_RND_DOWN)
+ acc -= ptn_0_offset;
+ if (flags & DEC_RND_DOWN_2)
+ acc -= ptn_0_offset;
+ }
+
+ return acc;
+}
+
+static void
+parse_partstr(char *partstr, int *csysid, daddr_t *cstart,
+ daddr_t *csize, char **cbootmenu)
+{
+ int64_t tval;
+ char *tmpstr;
+
+ /* Get sysid. */
+ tmpstr = strtok(partstr, "/");
+ if (tmpstr == NULL)
+ errx(1, "Bad argument to the -s flag.");
+ *csysid = strtoll(tmpstr, NULL, 10);
+ if (strspn(tmpstr, "1234567890") != strlen(tmpstr))
+ errx(1, "Bad id argument to the -s flag.");
+
+ /* Get start. */
+ tmpstr = strtok(NULL, "/");
+ if (tmpstr == NULL)
+ errx(1, "Bad argument to the -s flag.");
+ tval = parse_smodifier(tmpstr, DEC_RND);
+ if (tval < 0)
+ errx(1, "Bad start argument to the -s flag.");
+ *cstart = tval;
+
+ /* Get start. */
+ tmpstr = strtok(NULL, "/");
+ if (tmpstr == NULL)
+ errx(1, "Bad argument to the -s flag.");
+ tval = parse_smodifier(tmpstr, DEC_RND_DOWN);
+ if (tval < 0)
+ errx(1, "Bad size argument to the -s flag.");
+ *csize = tval;
+
+#ifdef BOOTSEL
+ /* Get bootmenu. */
+ tmpstr = strtok(NULL, "/");
+ if (tmpstr != NULL)
+ *cbootmenu = strdup(tmpstr);
+ else
+ *cbootmenu = NULL;
+#endif
+
+ return;
}
static int
change_part(int extended, int part, int sysid, daddr_t start, daddr_t size,
char *bootmenu)
Attachment:
signature.asc
Description: PGP signature