1*ccf8c4a2Snia /* $NetBSD: interact.c,v 1.40 2021/11/03 14:25:39 nia Exp $ */
272fbacb3Schristos
372fbacb3Schristos /*
472fbacb3Schristos * Copyright (c) 1997 Christos Zoulas. All rights reserved.
572fbacb3Schristos *
672fbacb3Schristos * Redistribution and use in source and binary forms, with or without
772fbacb3Schristos * modification, are permitted provided that the following conditions
872fbacb3Schristos * are met:
972fbacb3Schristos * 1. Redistributions of source code must retain the above copyright
1072fbacb3Schristos * notice, this list of conditions and the following disclaimer.
1172fbacb3Schristos * 2. Redistributions in binary form must reproduce the above copyright
1272fbacb3Schristos * notice, this list of conditions and the following disclaimer in the
1372fbacb3Schristos * documentation and/or other materials provided with the distribution.
1472fbacb3Schristos *
1572fbacb3Schristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1672fbacb3Schristos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1772fbacb3Schristos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1872fbacb3Schristos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1972fbacb3Schristos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2072fbacb3Schristos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2172fbacb3Schristos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2272fbacb3Schristos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2372fbacb3Schristos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2472fbacb3Schristos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2572fbacb3Schristos */
2672fbacb3Schristos
270636a2feSchristos #if !defined(NO_INTERACT)
280636a2feSchristos
291726c417Sdyoung #if HAVE_NBTOOL_CONFIG_H
301726c417Sdyoung #include "nbtool_config.h"
311726c417Sdyoung #endif
321726c417Sdyoung
335ec7cc78Schristos #include <sys/cdefs.h>
3472fbacb3Schristos #ifndef lint
35*ccf8c4a2Snia __RCSID("$NetBSD: interact.c,v 1.40 2021/11/03 14:25:39 nia Exp $");
3672fbacb3Schristos #endif /* lint */
3772fbacb3Schristos
385f534fcaSmrg #include <sys/param.h>
395f534fcaSmrg #define FSTYPENAMES
405f534fcaSmrg #define DKTYPENAMES
415f534fcaSmrg
425f534fcaSmrg #include <err.h>
4372fbacb3Schristos #include <stdio.h>
4472fbacb3Schristos #include <string.h>
45b7825cc9Schristos #include <stdarg.h>
4672fbacb3Schristos #include <stdlib.h>
47b7825cc9Schristos #include <sys/ioctl.h>
481726c417Sdyoung
491726c417Sdyoung #if HAVE_NBTOOL_CONFIG_H
50af8f0546Smatt #define getmaxpartitions() maxpartitions
511726c417Sdyoung #include <nbinclude/sys/disklabel.h>
521726c417Sdyoung #else
53649ae0edSchristos #include <util.h>
541726c417Sdyoung #include <sys/disklabel.h>
551726c417Sdyoung #endif /* HAVE_NBTOOL_CONFIG_H */
5672fbacb3Schristos
5772fbacb3Schristos #include "extern.h"
5872fbacb3Schristos
5935ccd223Slukem static void cmd_help(struct disklabel *, char *, int);
60b7825cc9Schristos static void cmd_adjust(struct disklabel *, char *, int);
6135ccd223Slukem static void cmd_chain(struct disklabel *, char *, int);
6235ccd223Slukem static void cmd_print(struct disklabel *, char *, int);
6335ccd223Slukem static void cmd_printall(struct disklabel *, char *, int);
6435ccd223Slukem static void cmd_info(struct disklabel *, char *, int);
6535ccd223Slukem static void cmd_part(struct disklabel *, char *, int);
6635ccd223Slukem static void cmd_label(struct disklabel *, char *, int);
6735ccd223Slukem static void cmd_round(struct disklabel *, char *, int);
6835ccd223Slukem static void cmd_name(struct disklabel *, char *, int);
6991af0d68Sjmmv static void cmd_listfstypes(struct disklabel *, char *, int);
7035ccd223Slukem static int runcmd(struct disklabel *, char *, int);
71b7825cc9Schristos static int getinput(char *, const char *, ...) __printflike(2, 3);
7235ccd223Slukem static int alphacmp(const void *, const void *);
73bb95bd59Spooka static void defnum(struct disklabel *, char *, uint32_t);
7435ccd223Slukem static void dumpnames(const char *, const char * const *, size_t);
750bf3480cSdholland static intmax_t getnum(struct disklabel *, char *, intmax_t);
7672fbacb3Schristos
7772fbacb3Schristos static int rounding = 0; /* sector rounding */
78563aff81Schristos static int chaining = 0; /* make partitions contiguous */
7972fbacb3Schristos
8072fbacb3Schristos static struct cmds {
8172fbacb3Schristos const char *name;
8235ccd223Slukem void (*func)(struct disklabel *, char *, int);
8372fbacb3Schristos const char *help;
8472fbacb3Schristos } cmds[] = {
8572fbacb3Schristos { "?", cmd_help, "print this menu" },
86b7825cc9Schristos { "A", cmd_adjust, "adjust the label size to the max disk size" },
87563aff81Schristos { "C", cmd_chain, "make partitions contiguous" },
885f534fcaSmrg { "E", cmd_printall, "print disk label and current partition table"},
895f534fcaSmrg { "I", cmd_info, "change label information" },
9091af0d68Sjmmv { "L", cmd_listfstypes,"list all known file system types" },
91649ae0edSchristos { "N", cmd_name, "name the label" },
92649ae0edSchristos { "P", cmd_print, "print current partition table" },
93649ae0edSchristos { "Q", NULL, "quit" },
94649ae0edSchristos { "R", cmd_round, "rounding (c)ylinders (s)ectors" },
95649ae0edSchristos { "W", cmd_label, "write the current partition table" },
9672fbacb3Schristos { NULL, NULL, NULL }
9772fbacb3Schristos };
9872fbacb3Schristos
9972fbacb3Schristos
10072fbacb3Schristos static void
cmd_help(struct disklabel * lp,char * s,int fd)10135ccd223Slukem cmd_help(struct disklabel *lp, char *s, int fd)
10272fbacb3Schristos {
10372fbacb3Schristos struct cmds *cmd;
104649ae0edSchristos
10572fbacb3Schristos for (cmd = cmds; cmd->name != NULL; cmd++)
10672fbacb3Schristos printf("%s\t%s\n", cmd->name, cmd->help);
107649ae0edSchristos printf("[a-%c]\tdefine named partition\n",
108649ae0edSchristos 'a' + getmaxpartitions() - 1);
10972fbacb3Schristos }
11072fbacb3Schristos
11172fbacb3Schristos
11272fbacb3Schristos static void
cmd_adjust(struct disklabel * lp,char * s,int fd)113b7825cc9Schristos cmd_adjust(struct disklabel *lp, char *s, int fd)
114b7825cc9Schristos {
115b7825cc9Schristos struct disklabel dl;
116b7825cc9Schristos
117772a1045Schristos if (dk_ioctl(fd, DIOCGDEFLABEL, &dl) == -1) {
118b7825cc9Schristos warn("Cannot get default label");
119b7825cc9Schristos return;
120b7825cc9Schristos }
121b7825cc9Schristos
122b7825cc9Schristos if (dl.d_secperunit != lp->d_secperunit) {
123b7825cc9Schristos char line[BUFSIZ];
124b7825cc9Schristos int i = getinput(line, "Adjust disklabel sector from %" PRIu32
125b7825cc9Schristos " to %" PRIu32 " [n]? ", lp->d_secperunit, dl.d_secperunit);
126b7825cc9Schristos if (i <= 0)
127b7825cc9Schristos return;
128b7825cc9Schristos if (line[0] != 'Y' && line[0] != 'y')
129b7825cc9Schristos return;
130b7825cc9Schristos lp->d_secperunit = dl.d_secperunit;
131b7825cc9Schristos return;
132b7825cc9Schristos }
133b7825cc9Schristos
134b7825cc9Schristos printf("Already at %" PRIu32 " sectors\n", dl.d_secperunit);
135b7825cc9Schristos return;
136b7825cc9Schristos }
137b7825cc9Schristos
138b7825cc9Schristos static void
cmd_chain(struct disklabel * lp,char * s,int fd)13935ccd223Slukem cmd_chain(struct disklabel *lp, char *s, int fd)
140563aff81Schristos {
141563aff81Schristos int i;
142563aff81Schristos char line[BUFSIZ];
143563aff81Schristos
144b7825cc9Schristos i = getinput(line, "Automatically adjust partitions [%s]? ",
145b7825cc9Schristos chaining ? "yes" : "no");
146563aff81Schristos if (i <= 0)
147563aff81Schristos return;
148563aff81Schristos
149563aff81Schristos switch (line[0]) {
150563aff81Schristos case 'y':
151563aff81Schristos chaining = 1;
152563aff81Schristos return;
153563aff81Schristos case 'n':
154563aff81Schristos chaining = 0;
155563aff81Schristos return;
156563aff81Schristos default:
157563aff81Schristos printf("Invalid answer\n");
158563aff81Schristos return;
159563aff81Schristos }
160563aff81Schristos }
161563aff81Schristos
16235ccd223Slukem
163563aff81Schristos static void
cmd_printall(struct disklabel * lp,char * s,int fd)16435ccd223Slukem cmd_printall(struct disklabel *lp, char *s, int fd)
1655f534fcaSmrg {
1665f534fcaSmrg
1671c5cb88eSlukem showinfo(stdout, lp, specname);
1681c5cb88eSlukem showpartitions(stdout, lp, Cflag);
1695f534fcaSmrg }
1705f534fcaSmrg
17135ccd223Slukem
1725f534fcaSmrg static void
cmd_print(struct disklabel * lp,char * s,int fd)17335ccd223Slukem cmd_print(struct disklabel *lp, char *s, int fd)
17472fbacb3Schristos {
17535ccd223Slukem
1761c5cb88eSlukem showpartitions(stdout, lp, Cflag);
17772fbacb3Schristos }
17872fbacb3Schristos
17935ccd223Slukem
1805f534fcaSmrg static void
cmd_info(struct disklabel * lp,char * s,int fd)18135ccd223Slukem cmd_info(struct disklabel *lp, char *s, int fd)
1825f534fcaSmrg {
1835f534fcaSmrg char line[BUFSIZ];
1845f534fcaSmrg int v, i;
1855f534fcaSmrg u_int32_t u;
1865f534fcaSmrg
1875f534fcaSmrg printf("# Current values:\n");
1881c5cb88eSlukem showinfo(stdout, lp, specname);
1895f534fcaSmrg
1904c8c8685Slukem /* d_type */
1915f534fcaSmrg for (;;) {
1924c8c8685Slukem i = lp->d_type;
1934c8c8685Slukem if (i < 0 || i >= DKMAXTYPES)
1944c8c8685Slukem i = 0;
195b7825cc9Schristos i = getinput(line, "Disk type [%s]: ", dktypenames[i]);
1964c8c8685Slukem if (i == -1)
1974c8c8685Slukem return;
1984c8c8685Slukem else if (i == 0)
1995f534fcaSmrg break;
2004c8c8685Slukem if (!strcmp(line, "?")) {
2014c8c8685Slukem dumpnames("Supported disk types", dktypenames,
2024c8c8685Slukem DKMAXTYPES);
2034c8c8685Slukem continue;
2044c8c8685Slukem }
2054c8c8685Slukem for (i = 0; i < DKMAXTYPES; i++) {
2064c8c8685Slukem if (!strcasecmp(dktypenames[i], line)) {
2074c8c8685Slukem lp->d_type = i;
2085f534fcaSmrg goto done_typename;
2095f534fcaSmrg }
2104c8c8685Slukem }
2115f534fcaSmrg v = atoi(line);
2125f534fcaSmrg if ((unsigned)v >= DKMAXTYPES) {
2134c8c8685Slukem warnx("Unknown disk type: %s", line);
2145f534fcaSmrg continue;
2155f534fcaSmrg }
2165f534fcaSmrg lp->d_type = v;
2175f534fcaSmrg done_typename:
2185f534fcaSmrg break;
2195f534fcaSmrg }
2205f534fcaSmrg
2214c8c8685Slukem /* d_typename */
222b7825cc9Schristos i = getinput(line, "Disk name [%.*s]: ",
2234c8c8685Slukem (int) sizeof(lp->d_typename), lp->d_typename);
2244c8c8685Slukem if (i == -1)
2254c8c8685Slukem return;
2264c8c8685Slukem else if (i == 1)
2274c8c8685Slukem (void) strncpy(lp->d_typename, line, sizeof(lp->d_typename));
2284c8c8685Slukem
2295f534fcaSmrg /* d_packname */
2305f534fcaSmrg cmd_name(lp, s, fd);
2315f534fcaSmrg
2325f534fcaSmrg /* d_npartitions */
2335f534fcaSmrg for (;;) {
234b7825cc9Schristos i = getinput(line, "Number of partitions [%" PRIu16 "]: ",
235b7825cc9Schristos lp->d_npartitions);
2364c8c8685Slukem if (i == -1)
2374c8c8685Slukem return;
2384c8c8685Slukem else if (i == 0)
2395f534fcaSmrg break;
24063df928bSapb if (sscanf(line, "%" SCNu32, &u) != 1) {
2414c8c8685Slukem printf("Invalid number of partitions `%s'\n", line);
2425f534fcaSmrg continue;
2435f534fcaSmrg }
2445f534fcaSmrg lp->d_npartitions = u;
2455f534fcaSmrg break;
2465f534fcaSmrg }
2475f534fcaSmrg
2485f534fcaSmrg /* d_secsize */
2495f534fcaSmrg for (;;) {
250b7825cc9Schristos i = getinput(line, "Sector size (bytes) [%" PRIu32 "]: ",
251b7825cc9Schristos lp->d_secsize);
2524c8c8685Slukem if (i == -1)
2534c8c8685Slukem return;
2544c8c8685Slukem else if (i == 0)
2555f534fcaSmrg break;
25663df928bSapb if (sscanf(line, "%" SCNu32, &u) != 1) {
2575f534fcaSmrg printf("Invalid sector size `%s'\n", line);
2585f534fcaSmrg continue;
2595f534fcaSmrg }
2605f534fcaSmrg lp->d_secsize = u;
2615f534fcaSmrg break;
2625f534fcaSmrg }
2635f534fcaSmrg
2645f534fcaSmrg /* d_nsectors */
2655f534fcaSmrg for (;;) {
266b7825cc9Schristos i = getinput(line, "Number of sectors per track [%" PRIu32
267b7825cc9Schristos "]: ", lp->d_nsectors);
2684c8c8685Slukem if (i == -1)
2694c8c8685Slukem return;
2704c8c8685Slukem else if (i == 0)
2715f534fcaSmrg break;
27263df928bSapb if (sscanf(line, "%" SCNu32, &u) != 1) {
2734c8c8685Slukem printf("Invalid number of sectors `%s'\n", line);
2745f534fcaSmrg continue;
2755f534fcaSmrg }
2765f534fcaSmrg lp->d_nsectors = u;
2775f534fcaSmrg break;
2785f534fcaSmrg }
2795f534fcaSmrg
2805f534fcaSmrg /* d_ntracks */
2815f534fcaSmrg for (;;) {
282b7825cc9Schristos i = getinput(line, "Number of tracks per cylinder [%" PRIu32
283b7825cc9Schristos "]: ", lp->d_ntracks);
2844c8c8685Slukem if (i == -1)
2854c8c8685Slukem return;
2864c8c8685Slukem else if (i == 0)
2875f534fcaSmrg break;
28863df928bSapb if (sscanf(line, "%" SCNu32, &u) != 1) {
2895f534fcaSmrg printf("Invalid number of tracks `%s'\n", line);
2905f534fcaSmrg continue;
2915f534fcaSmrg }
2925f534fcaSmrg lp->d_ntracks = u;
2935f534fcaSmrg break;
2945f534fcaSmrg }
2955f534fcaSmrg
2965f534fcaSmrg /* d_secpercyl */
2975f534fcaSmrg for (;;) {
298b7825cc9Schristos i = getinput(line, "Number of sectors/cylinder [%" PRIu32 "]: ",
299b7825cc9Schristos lp->d_secpercyl);
3004c8c8685Slukem if (i == -1)
3014c8c8685Slukem return;
3024c8c8685Slukem else if (i == 0)
3035f534fcaSmrg break;
30463df928bSapb if (sscanf(line, "%" SCNu32, &u) != 1) {
3054c8c8685Slukem printf("Invalid number of sector/cylinder `%s'\n",
3064c8c8685Slukem line);
3075f534fcaSmrg continue;
3085f534fcaSmrg }
3095f534fcaSmrg lp->d_secpercyl = u;
3105f534fcaSmrg break;
3115f534fcaSmrg }
3125f534fcaSmrg
3135f534fcaSmrg /* d_ncylinders */
3145f534fcaSmrg for (;;) {
315b7825cc9Schristos i = getinput(line, "Total number of cylinders [%" PRIu32 "]: ",
316b7825cc9Schristos lp->d_ncylinders);
3174c8c8685Slukem if (i == -1)
3184c8c8685Slukem return;
3194c8c8685Slukem else if (i == 0)
3205f534fcaSmrg break;
32163df928bSapb if (sscanf(line, "%" SCNu32, &u) != 1) {
3225f534fcaSmrg printf("Invalid sector size `%s'\n", line);
3235f534fcaSmrg continue;
3245f534fcaSmrg }
3255f534fcaSmrg lp->d_ncylinders = u;
3265f534fcaSmrg break;
3275f534fcaSmrg }
3285f534fcaSmrg
3295f534fcaSmrg /* d_secperunit */
3305f534fcaSmrg for (;;) {
331b7825cc9Schristos i = getinput(line, "Total number of sectors [%" PRIu32 "]: ",
332b7825cc9Schristos lp->d_secperunit);
3334c8c8685Slukem if (i == -1)
3344c8c8685Slukem return;
3354c8c8685Slukem else if (i == 0)
3365f534fcaSmrg break;
33763df928bSapb if (sscanf(line, "%" SCNu32, &u) != 1) {
3384c8c8685Slukem printf("Invalid number of sectors `%s'\n", line);
3395f534fcaSmrg continue;
3405f534fcaSmrg }
3415f534fcaSmrg lp->d_secperunit = u;
3425f534fcaSmrg break;
3435f534fcaSmrg }
3445f534fcaSmrg
3455f534fcaSmrg /* d_rpm */
3465f534fcaSmrg
3475f534fcaSmrg /* d_interleave */
3485f534fcaSmrg for (;;) {
349b7825cc9Schristos i = getinput(line, "Hardware sectors interleave [%" PRIu16
350b7825cc9Schristos "]: ", lp->d_interleave);
3514c8c8685Slukem if (i == -1)
3524c8c8685Slukem return;
3534c8c8685Slukem else if (i == 0)
3545f534fcaSmrg break;
35563df928bSapb if (sscanf(line, "%" SCNu32, &u) != 1) {
3564c8c8685Slukem printf("Invalid sector interleave `%s'\n", line);
3575f534fcaSmrg continue;
3585f534fcaSmrg }
3595f534fcaSmrg lp->d_interleave = u;
3605f534fcaSmrg break;
3615f534fcaSmrg }
3625f534fcaSmrg
3635f534fcaSmrg /* d_trackskew */
3645f534fcaSmrg for (;;) {
365b7825cc9Schristos i = getinput(line, "Sector 0 skew, per track [%" PRIu16 "]: ",
366b7825cc9Schristos lp->d_trackskew);
3674c8c8685Slukem if (i == -1)
3684c8c8685Slukem return;
3694c8c8685Slukem else if (i == 0)
3705f534fcaSmrg break;
37163df928bSapb if (sscanf(line, "%" SCNu32, &u) != 1) {
3724c8c8685Slukem printf("Invalid track sector skew `%s'\n", line);
3735f534fcaSmrg continue;
3745f534fcaSmrg }
3755f534fcaSmrg lp->d_trackskew = u;
3765f534fcaSmrg break;
3775f534fcaSmrg }
3785f534fcaSmrg
3795f534fcaSmrg /* d_cylskew */
3805f534fcaSmrg for (;;) {
381b7825cc9Schristos i = getinput(line, "Sector 0 skew, per cylinder [%" PRIu16
382b7825cc9Schristos "]: ", lp->d_cylskew);
3834c8c8685Slukem if (i == -1)
3844c8c8685Slukem return;
3854c8c8685Slukem else if (i == 0)
3865f534fcaSmrg break;
38763df928bSapb if (sscanf(line, "%" SCNu32, &u) != 1) {
3884c8c8685Slukem printf("Invalid cylinder sector `%s'\n", line);
3895f534fcaSmrg continue;
3905f534fcaSmrg }
3915f534fcaSmrg lp->d_cylskew = u;
3925f534fcaSmrg break;
3935f534fcaSmrg }
3945f534fcaSmrg
3955f534fcaSmrg /* d_headswitch */
3965f534fcaSmrg for (;;) {
397b7825cc9Schristos i = getinput(line, "Head switch time (usec) [%" PRIu32 "]: ",
398b7825cc9Schristos lp->d_headswitch);
3994c8c8685Slukem if (i == -1)
4004c8c8685Slukem return;
4014c8c8685Slukem else if (i == 0)
4025f534fcaSmrg break;
40363df928bSapb if (sscanf(line, "%" SCNu32, &u) != 1) {
4044c8c8685Slukem printf("Invalid head switch time `%s'\n", line);
4055f534fcaSmrg continue;
4065f534fcaSmrg }
4075f534fcaSmrg lp->d_headswitch = u;
4085f534fcaSmrg break;
4095f534fcaSmrg }
4105f534fcaSmrg
4115f534fcaSmrg /* d_trkseek */
4125f534fcaSmrg for (;;) {
413b7825cc9Schristos i = getinput(line, "Track seek time (usec) [%" PRIu32 "]:",
414b7825cc9Schristos lp->d_trkseek);
4154c8c8685Slukem if (i == -1)
4164c8c8685Slukem return;
4174c8c8685Slukem else if (i == 0)
4185f534fcaSmrg break;
41963df928bSapb if (sscanf(line, "%" SCNu32, &u) != 1) {
4204c8c8685Slukem printf("Invalid track seek time `%s'\n", line);
4215f534fcaSmrg continue;
4225f534fcaSmrg }
4235f534fcaSmrg lp->d_trkseek = u;
4245f534fcaSmrg break;
4255f534fcaSmrg }
4265f534fcaSmrg }
42772fbacb3Schristos
42835ccd223Slukem
42972fbacb3Schristos static void
cmd_name(struct disklabel * lp,char * s,int fd)43035ccd223Slukem cmd_name(struct disklabel *lp, char *s, int fd)
43172fbacb3Schristos {
43272fbacb3Schristos char line[BUFSIZ];
4334c8c8685Slukem int i;
43472fbacb3Schristos
435b7825cc9Schristos i = getinput(line, "Label name [%.*s]: ",
4364c8c8685Slukem (int) sizeof(lp->d_packname), lp->d_packname);
43772fbacb3Schristos if (i <= 0)
43872fbacb3Schristos return;
43972fbacb3Schristos (void) strncpy(lp->d_packname, line, sizeof(lp->d_packname));
44072fbacb3Schristos }
44172fbacb3Schristos
44235ccd223Slukem
44372fbacb3Schristos static void
cmd_round(struct disklabel * lp,char * s,int fd)44435ccd223Slukem cmd_round(struct disklabel *lp, char *s, int fd)
44572fbacb3Schristos {
44672fbacb3Schristos int i;
44772fbacb3Schristos char line[BUFSIZ];
44872fbacb3Schristos
449b7825cc9Schristos i = getinput(line, "Rounding [%s]: ", rounding ? "cylinders" :
450b7825cc9Schristos "sectors");
45172fbacb3Schristos if (i <= 0)
45272fbacb3Schristos return;
45372fbacb3Schristos
45472fbacb3Schristos switch (line[0]) {
45572fbacb3Schristos case 'c':
4568dba43fbSchristos case 'C':
45772fbacb3Schristos rounding = 1;
45872fbacb3Schristos return;
45972fbacb3Schristos case 's':
4608dba43fbSchristos case 'S':
46172fbacb3Schristos rounding = 0;
46272fbacb3Schristos return;
46372fbacb3Schristos default:
46472fbacb3Schristos printf("Rounding can be (c)ylinders or (s)ectors\n");
46572fbacb3Schristos return;
46672fbacb3Schristos }
46772fbacb3Schristos }
46872fbacb3Schristos
46935ccd223Slukem
47072fbacb3Schristos static void
cmd_part(struct disklabel * lp,char * s,int fd)47135ccd223Slukem cmd_part(struct disklabel *lp, char *s, int fd)
47272fbacb3Schristos {
47372fbacb3Schristos int i;
4740bf3480cSdholland intmax_t im;
47572fbacb3Schristos char line[BUFSIZ];
47672fbacb3Schristos char def[BUFSIZ];
47735ccd223Slukem int part;
47879569512Schristos struct partition *p, ps;
47972fbacb3Schristos
48035ccd223Slukem part = s[0] - 'a';
48135ccd223Slukem p = &lp->d_partitions[part];
4825a6005a0Schristos if (part >= lp->d_npartitions)
48372fbacb3Schristos lp->d_npartitions = part + 1;
48472fbacb3Schristos
48579569512Schristos (void)memcpy(&ps, p, sizeof(ps));
48679569512Schristos
48772fbacb3Schristos for (;;) {
4884c8c8685Slukem i = p->p_fstype;
4894c8c8685Slukem if (i < 0 || i >= FSMAXTYPES)
4904c8c8685Slukem i = 0;
491b7825cc9Schristos i = getinput(line, "Filesystem type [%s]: ", fstypenames[i]);
4924c8c8685Slukem if (i == -1)
4934c8c8685Slukem return;
4944c8c8685Slukem else if (i == 0)
49572fbacb3Schristos break;
4964c8c8685Slukem if (!strcmp(line, "?")) {
4974c8c8685Slukem dumpnames("Supported file system types",
4984c8c8685Slukem fstypenames, FSMAXTYPES);
49972fbacb3Schristos continue;
50072fbacb3Schristos }
5014c8c8685Slukem for (i = 0; i < FSMAXTYPES; i++)
5024c8c8685Slukem if (!strcasecmp(line, fstypenames[i])) {
50372fbacb3Schristos p->p_fstype = i;
5044c8c8685Slukem goto done_typename;
5054c8c8685Slukem }
5064c8c8685Slukem printf("Invalid file system typename `%s'\n", line);
5074c8c8685Slukem continue;
5084c8c8685Slukem done_typename:
50972fbacb3Schristos break;
51072fbacb3Schristos }
51172fbacb3Schristos for (;;) {
51235ccd223Slukem defnum(lp, def, p->p_offset);
513b7825cc9Schristos i = getinput(line, "Start offset ('x' to start after partition"
514b7825cc9Schristos " 'x') [%s]: ", def);
5154c8c8685Slukem if (i == -1)
5164c8c8685Slukem return;
5174c8c8685Slukem else if (i == 0)
51872fbacb3Schristos break;
519256b6fecSjdc if (line[1] == '\0' &&
520256b6fecSjdc line[0] >= 'a' && line[0] < 'a' + getmaxpartitions()) {
521256b6fecSjdc struct partition *cp = lp->d_partitions;
522256b6fecSjdc
523256b6fecSjdc if ((cp[line[0] - 'a'].p_offset +
524256b6fecSjdc cp[line[0] - 'a'].p_size) >= lp->d_secperunit) {
525256b6fecSjdc printf("Bad offset `%s'\n", line);
526256b6fecSjdc continue;
527256b6fecSjdc } else {
528256b6fecSjdc p->p_offset = cp[line[0] - 'a'].p_offset +
529256b6fecSjdc cp[line[0] - 'a'].p_size;
530256b6fecSjdc }
531256b6fecSjdc } else {
5320bf3480cSdholland if ((im = getnum(lp, line, 0)) == -1 || im < 0) {
53372fbacb3Schristos printf("Bad offset `%s'\n", line);
53472fbacb3Schristos continue;
5350bf3480cSdholland } else if (im > 0xffffffffLL ||
5360bf3480cSdholland (uint32_t)im > lp->d_secperunit) {
53797a9e023Sgrant printf("Offset `%s' out of range\n", line);
53897a9e023Sgrant continue;
53972fbacb3Schristos }
5400bf3480cSdholland p->p_offset = (uint32_t)im;
541256b6fecSjdc }
54272fbacb3Schristos break;
54372fbacb3Schristos }
54472fbacb3Schristos for (;;) {
54535ccd223Slukem defnum(lp, def, p->p_size);
546b7825cc9Schristos i = getinput(line, "Partition size ('$' for all remaining) "
547b7825cc9Schristos "[%s]: ", def);
5484c8c8685Slukem if (i == -1)
5494c8c8685Slukem return;
5504c8c8685Slukem else if (i == 0)
55172fbacb3Schristos break;
5520bf3480cSdholland if ((im = getnum(lp, line, lp->d_secperunit - p->p_offset))
553669feec4Sabs == -1) {
55472fbacb3Schristos printf("Bad size `%s'\n", line);
55572fbacb3Schristos continue;
5560bf3480cSdholland } else if (im > 0xffffffffLL ||
5570bf3480cSdholland (im + p->p_offset) > lp->d_secperunit) {
55897a9e023Sgrant printf("Size `%s' out of range\n", line);
55997a9e023Sgrant continue;
56072fbacb3Schristos }
5610bf3480cSdholland p->p_size = im;
56272fbacb3Schristos break;
56372fbacb3Schristos }
564563aff81Schristos
565256b6fecSjdc if (memcmp(&ps, p, sizeof(ps)))
566256b6fecSjdc showpartition(stdout, lp, part, Cflag);
567563aff81Schristos if (chaining) {
56879569512Schristos int offs = -1;
56979569512Schristos struct partition *cp = lp->d_partitions;
57079569512Schristos for (i = 0; i < lp->d_npartitions; i++) {
57179569512Schristos if (cp[i].p_fstype != FS_UNUSED) {
57207f76885Slukem if (offs != -1 && cp[i].p_offset != (uint32_t)offs) {
57379569512Schristos cp[i].p_offset = offs;
574256b6fecSjdc showpartition(stdout, lp, i, Cflag);
575256b6fecSjdc }
57679569512Schristos offs = cp[i].p_offset + cp[i].p_size;
577563aff81Schristos }
578563aff81Schristos }
579563aff81Schristos }
58072fbacb3Schristos }
58172fbacb3Schristos
58272fbacb3Schristos
58372fbacb3Schristos static void
cmd_label(struct disklabel * lp,char * s,int fd)58435ccd223Slukem cmd_label(struct disklabel *lp, char *s, int fd)
58572fbacb3Schristos {
58672fbacb3Schristos char line[BUFSIZ];
58772fbacb3Schristos int i;
58872fbacb3Schristos
589b7825cc9Schristos i = getinput(line, "Label disk [n]?");
590b755b885Sabs if (i <= 0 || (*line != 'y' && *line != 'Y') )
59172fbacb3Schristos return;
59272fbacb3Schristos
59372fbacb3Schristos if (checklabel(lp) != 0) {
59472fbacb3Schristos printf("Label not written\n");
59572fbacb3Schristos return;
59672fbacb3Schristos }
59772fbacb3Schristos
59865151c95Sdsl if (writelabel(fd, lp) != 0) {
5998daf1590Senami printf("Label not written\n");
60072fbacb3Schristos return;
60172fbacb3Schristos }
60272fbacb3Schristos printf("Label written\n");
60372fbacb3Schristos }
60472fbacb3Schristos
60572fbacb3Schristos
60691af0d68Sjmmv static void
cmd_listfstypes(struct disklabel * lp,char * s,int fd)60791af0d68Sjmmv cmd_listfstypes(struct disklabel *lp, char *s, int fd)
60891af0d68Sjmmv {
60991af0d68Sjmmv
61091af0d68Sjmmv (void)list_fs_types();
61191af0d68Sjmmv }
61291af0d68Sjmmv
61391af0d68Sjmmv
61472fbacb3Schristos static int
runcmd(struct disklabel * lp,char * line,int fd)61535ccd223Slukem runcmd(struct disklabel *lp, char *line, int fd)
61672fbacb3Schristos {
61772fbacb3Schristos struct cmds *cmd;
61872fbacb3Schristos
61972fbacb3Schristos for (cmd = cmds; cmd->name != NULL; cmd++)
62072fbacb3Schristos if (strncmp(line, cmd->name, strlen(cmd->name)) == 0) {
62172fbacb3Schristos if (cmd->func == NULL)
62272fbacb3Schristos return -1;
62372fbacb3Schristos (*cmd->func)(lp, line, fd);
6245ec7cc78Schristos return 0;
62572fbacb3Schristos }
626649ae0edSchristos
627649ae0edSchristos if (line[1] == '\0' &&
628649ae0edSchristos line[0] >= 'a' && line[0] < 'a' + getmaxpartitions()) {
629649ae0edSchristos cmd_part(lp, line, fd);
6305ec7cc78Schristos return 0;
631649ae0edSchristos }
632649ae0edSchristos
63372fbacb3Schristos printf("Unknown command %s\n", line);
6345ec7cc78Schristos return 1;
63572fbacb3Schristos }
63672fbacb3Schristos
63772fbacb3Schristos
63872fbacb3Schristos static int
getinput(char * line,const char * prompt,...)639b7825cc9Schristos getinput(char *line, const char *prompt, ...)
64072fbacb3Schristos {
64135ccd223Slukem
64272fbacb3Schristos for (;;) {
643b7825cc9Schristos va_list ap;
644b7825cc9Schristos va_start(ap, prompt);
645b7825cc9Schristos vprintf(prompt, ap);
646b7825cc9Schristos va_end(ap);
64772fbacb3Schristos
64872fbacb3Schristos if (fgets(line, BUFSIZ, stdin) == NULL)
64972fbacb3Schristos return -1;
650b7825cc9Schristos if (line[0] == '\n' || line[0] == '\0')
65172fbacb3Schristos return 0;
65272fbacb3Schristos else {
65372fbacb3Schristos char *p;
65472fbacb3Schristos
65572fbacb3Schristos if ((p = strrchr(line, '\n')) != NULL)
65672fbacb3Schristos *p = '\0';
65772fbacb3Schristos return 1;
65872fbacb3Schristos }
65972fbacb3Schristos }
66072fbacb3Schristos }
66172fbacb3Schristos
6624c8c8685Slukem static int
alphacmp(const void * a,const void * b)66335ccd223Slukem alphacmp(const void *a, const void *b)
6644c8c8685Slukem {
6654c8c8685Slukem
6662c6eadc9Schristos return (strcasecmp(*(const char * const*)a, *(const char * const*)b));
6674c8c8685Slukem }
6684c8c8685Slukem
6694c8c8685Slukem
6704c8c8685Slukem static void
dumpnames(const char * prompt,const char * const * olist,size_t numentries)67135ccd223Slukem dumpnames(const char *prompt, const char * const *olist, size_t numentries)
6724c8c8685Slukem {
67307f76885Slukem int w;
67407f76885Slukem size_t i, entry, lines;
67507f76885Slukem int columns, width;
6764c8c8685Slukem const char *p;
677*ccf8c4a2Snia const char **list = NULL;
6784c8c8685Slukem
679*ccf8c4a2Snia if (reallocarr(&list, numentries, sizeof(char *)) != 0)
680*ccf8c4a2Snia err(1, "reallocarr");
6814c8c8685Slukem width = 0;
6824c8c8685Slukem printf("%s:\n", prompt);
6834c8c8685Slukem for (i = 0; i < numentries; i++) {
6844c8c8685Slukem list[i] = olist[i];
6854c8c8685Slukem w = strlen(list[i]);
6864c8c8685Slukem if (w > width)
6874c8c8685Slukem width = w;
6884c8c8685Slukem }
6894c8c8685Slukem #if 0
6904c8c8685Slukem for (i = 0; i < numentries; i++)
6914c8c8685Slukem printf("%s%s", i == 0 ? "" : ", ", list[i]);
6924c8c8685Slukem puts("");
6934c8c8685Slukem #endif
69480644903Slukem (void)qsort(list, numentries, sizeof(char *), alphacmp);
6954c8c8685Slukem width++; /* want two spaces between items */
6964c8c8685Slukem width = (width + 8) &~ 7;
6974c8c8685Slukem
6984c8c8685Slukem #define ttywidth 72
6994c8c8685Slukem columns = ttywidth / width;
7004c8c8685Slukem #undef ttywidth
7014c8c8685Slukem if (columns == 0)
7024c8c8685Slukem columns = 1;
7034c8c8685Slukem lines = (numentries + columns - 1) / columns;
70457c63d89Sdsl /* Output sorted by columns */
7054c8c8685Slukem for (i = 0; i < lines; i++) {
7064c8c8685Slukem putc('\t', stdout);
70757c63d89Sdsl entry = i;
70857c63d89Sdsl for (;;) {
70957c63d89Sdsl p = list[entry];
7104c8c8685Slukem fputs(p, stdout);
71157c63d89Sdsl entry += lines;
71257c63d89Sdsl if (entry >= numentries)
7134c8c8685Slukem break;
7144c8c8685Slukem w = strlen(p);
7154c8c8685Slukem while (w < width) {
7164c8c8685Slukem w = (w + 8) & ~7;
7174c8c8685Slukem putc('\t', stdout);
7184c8c8685Slukem }
7194c8c8685Slukem }
72057c63d89Sdsl putc('\n', stdout);
7214c8c8685Slukem }
7224c8c8685Slukem free(list);
7234c8c8685Slukem }
7244c8c8685Slukem
72572fbacb3Schristos
72672fbacb3Schristos static void
defnum(struct disklabel * lp,char * buf,uint32_t size)727bb95bd59Spooka defnum(struct disklabel *lp, char *buf, uint32_t size)
72872fbacb3Schristos {
72935ccd223Slukem
73063df928bSapb (void) snprintf(buf, BUFSIZ, "%.40gc, %" PRIu32 "s, %.40gM",
73172fbacb3Schristos size / (float) lp->d_secpercyl,
73272fbacb3Schristos size, size * (lp->d_secsize / (float) (1024 * 1024)));
73372fbacb3Schristos }
73472fbacb3Schristos
73572fbacb3Schristos
7360bf3480cSdholland static intmax_t
getnum(struct disklabel * lp,char * buf,intmax_t defaultval)7370bf3480cSdholland getnum(struct disklabel *lp, char *buf, intmax_t defaultval)
73872fbacb3Schristos {
73972fbacb3Schristos char *ep;
740669feec4Sabs double d;
7410bf3480cSdholland intmax_t rv;
74272fbacb3Schristos
7430bf3480cSdholland if (defaultval && buf[0] == '$' && buf[1] == 0)
7440bf3480cSdholland return defaultval;
745669feec4Sabs
746669feec4Sabs d = strtod(buf, &ep);
74772fbacb3Schristos if (buf == ep)
74872fbacb3Schristos return -1;
74972fbacb3Schristos
75035ccd223Slukem #define ROUND(a) ((((a) / lp->d_secpercyl) + \
75135ccd223Slukem (((a) % lp->d_secpercyl) ? 1 : 0)) * lp->d_secpercyl)
75272fbacb3Schristos
75372fbacb3Schristos switch (*ep) {
75472fbacb3Schristos case '\0':
75572fbacb3Schristos case 's':
7568dba43fbSchristos case 'S':
7570bf3480cSdholland rv = (intmax_t) d;
75872fbacb3Schristos break;
75972fbacb3Schristos
76072fbacb3Schristos case 'c':
7618dba43fbSchristos case 'C':
7620bf3480cSdholland rv = (intmax_t) (d * lp->d_secpercyl);
76372fbacb3Schristos break;
76472fbacb3Schristos
7658dba43fbSchristos case 'k':
7668dba43fbSchristos case 'K':
7670bf3480cSdholland rv = (intmax_t) (d * 1024 / lp->d_secsize);
7688dba43fbSchristos break;
7698dba43fbSchristos
7704c8c8685Slukem case 'm':
77172fbacb3Schristos case 'M':
7720bf3480cSdholland rv = (intmax_t) (d * 1024 * 1024 / lp->d_secsize);
77372fbacb3Schristos break;
77472fbacb3Schristos
7758dba43fbSchristos case 'g':
7768dba43fbSchristos case 'G':
7770bf3480cSdholland rv = (intmax_t) (d * 1024 * 1024 * 1024 / lp->d_secsize);
7788dba43fbSchristos break;
7798dba43fbSchristos
7808dba43fbSchristos case 't':
7818dba43fbSchristos case 'T':
7820bf3480cSdholland rv = (intmax_t) (d * 1024 * 1024 * 1024 * 1024 / lp->d_secsize);
7838dba43fbSchristos break;
7848dba43fbSchristos
78572fbacb3Schristos default:
78672fbacb3Schristos printf("Unit error %c\n", *ep);
7878dba43fbSchristos printf("Valid units: (S)ectors, (C)ylinders, (K)ilo, (M)ega, "
7888dba43fbSchristos "(G)iga, (T)era");
78972fbacb3Schristos return -1;
79072fbacb3Schristos }
79172fbacb3Schristos
79272fbacb3Schristos if (rounding)
79372fbacb3Schristos return ROUND(rv);
79472fbacb3Schristos else
79572fbacb3Schristos return rv;
79672fbacb3Schristos }
79772fbacb3Schristos
79872fbacb3Schristos
79972fbacb3Schristos void
interact(struct disklabel * lp,int fd)80035ccd223Slukem interact(struct disklabel *lp, int fd)
80172fbacb3Schristos {
80272fbacb3Schristos char line[BUFSIZ];
80372fbacb3Schristos
804b861177eSabs puts("Enter '?' for help");
80572fbacb3Schristos for (;;) {
806b7825cc9Schristos int i = getinput(line, "partition>");
807b7825cc9Schristos if (i == -1)
80872fbacb3Schristos return;
809b7825cc9Schristos if (i == 0)
810b7825cc9Schristos continue;
81135ccd223Slukem if (runcmd(lp, line, fd) == -1)
81272fbacb3Schristos return;
81372fbacb3Schristos }
81472fbacb3Schristos }
8150636a2feSchristos
8160636a2feSchristos #endif /* !NO_INTERACT */
817