Subject: Re: PATCH: disklabel & fdisk regular files
To: None <tech-userlevel@NetBSD.org>
From: David Young <dyoung@pobox.com>
List: tech-userlevel
Date: 03/02/2004 02:11:46
--kXdP64Ggrk/fb43R
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Tue, Feb 17, 2004 at 07:39:06PM +1100, Luke Mewburn wrote:
> On Tue, Feb 17, 2004 at 01:46:38AM -0600, David Young wrote:
> | It's useful sometimes for a privilegeless user to disklabel or fdisk
> | a file containing a disk image---a file was made by makefs, say. Here
> | are patches that make it possible. The disklabel patch is pretty simple:
> | detect that the target is a file and avoid certain steps. Because fdisk
> | needs a disklabel to get started, my patch lets you give it a disktab
> | and disktype with -t and -T options.
>
> I'd prefer that disklabel(8) took a specific option to use a regular
> file to enable this behaviour; other disk related tools use '-F' for this.
Done. Patches attached.
> As for fdisk; is there a way we can implement '-F' to enable the
> "don't bother disklabeling" stuff, rather than the -t/-T stuff ?
There is a way. I can provide -F by "faking up" the disk geometry.
Patches attached.
I had used -t/-T because it was expedient, but I would like for it
to stick around. It lets one avoid "faking up" C/H/S for the file,
if one knows the geometry of the device where one will dd(1) the disk
image later.
Dave
--
David Young OJC Technologies
dyoung@ojctech.com Urbana, IL * (217) 278-3933
--kXdP64Ggrk/fb43R
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="privless-fdisk-n-disklabel.patch"
Index: fdisk/fdisk.8
===================================================================
RCS file: /cvsroot/src/sbin/fdisk/fdisk.8,v
retrieving revision 1.43
diff -u -r1.43 fdisk.8
--- fdisk/fdisk.8 6 Oct 2003 12:02:52 -0000 1.43
+++ fdisk/fdisk.8 2 Mar 2004 08:10:44 -0000
@@ -8,11 +8,17 @@
.Nd MS-DOS partition maintenance program
.Sh SYNOPSIS
.Nm
-.Op Fl afiuvBS
+.Op Fl afiuvBFS
.Bk -words
.Op Fl 0 | 1 | 2 | 3
.Ek
.Bk -words
+.Op Fl t Ar disktab
+.Ek
+.Bk -words
+.Op Fl T Ar disktype
+.Ek
+.Bk -words
.Op Fl E Ar number
.Ek
.Bk -words
@@ -182,6 +188,19 @@
are specified then the details of the specified partition will be changed.
Any other partitions which overlap the requested part of the disk will be
silently deleted.
+.It Fl F
+Indicate that
+.Ar device
+is a regular file. Unless the geometry of
+.Ar device
+is told to
+.Nm fdisk
+by
+.Fl T Ar disktype ,
+.Nm fdisk
+will count the 512-byte sectors in
+.Ar device
+and produce a fake geometry.
.It Fl i
Explicitly request initialisation of the master boot code
(similar to what
@@ -221,6 +240,18 @@
.Pa /bin/sh
commands for setting variables to the partition information.
This could be used by installation scripts.
+.It Fl t Ar disktab
+Read
+.Ar disktype
+from the named
+.Xr disktab 5
+file instead of from
+.Pa /etc/disktab.
+.It Fl T Ar disktype
+Use the disklabel
+.Ar disktype
+instead of the disklabel on
+.Ar device .
.It Fl u
Display the partitions and interactively ask which one you want to edit.
.Nm
@@ -445,6 +476,7 @@
.El
.Sh SEE ALSO
.Xr disklabel 8 ,
+.Xr disktab 5 ,
.Xr mbr 8 ,
.Xr mbrlabel 8
.Sh BUGS
Index: fdisk/fdisk.c
===================================================================
RCS file: /cvsroot/src/sbin/fdisk/fdisk.c,v
retrieving revision 1.74
diff -u -r1.74 fdisk.c
--- fdisk/fdisk.c 5 Jan 2004 23:23:32 -0000 1.74
+++ fdisk/fdisk.c 2 Mar 2004 08:10:44 -0000
@@ -47,6 +47,7 @@
#include <sys/sysctl.h>
#include <ctype.h>
+#include <disktab.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
@@ -114,10 +115,10 @@
#define DEFAULT_ACTIVE (~(daddr_t)0)
-#define OPTIONS "0123BSafiluvs:b:c:E:r:w:"
+#define OPTIONS "0123BFSafiluvs:b:c:E:r:w:t:T:"
#else
#define change_part(e, p, id, st, sz, bm) change__part(e, p, id, st, sz)
-#define OPTIONS "0123Safiluvs:b:c:E:r:w:"
+#define OPTIONS "0123FSafiluvs:b:c:E:r:w:"
#endif
uint dos_cylinders;
@@ -140,6 +141,7 @@
int fd = -1, wfd = -1, *rfd = &fd;
char *disk_file;
+char *disk_type = NULL;
int a_flag; /* set active partition */
int i_flag; /* init bootcode */
@@ -152,6 +154,7 @@
int B_flag; /* Edit/install bootselect code */
int E_flag; /* extended partition number */
int b_cyl, b_head, b_sec; /* b_flag values. */
+int F_flag = 0;
struct mbr_sector bootcode[8192 / sizeof (struct mbr_sector)];
int bootsize; /* actual size of bootcode */
@@ -382,6 +385,9 @@
B_flag = 1;
break;
#endif
+ case 'F': /* device argument is really a file */
+ F_flag = 1;
+ break;
case 'S': /* Output as shell variables */
sh_flag = 1;
break;
@@ -445,13 +451,22 @@
case 'w': /* write data to disk_file */
disk_file = optarg;
break;
-
+ case 't':
+ if (setdisktab(optarg) == -1)
+ errx(EXIT_FAILURE, "bad disktab");
+ break;
+ case 'T':
+ disk_type = optarg;
+ break;
default:
usage();
}
argc -= optind;
argv += optind;
+ if (disk_type != NULL && getdiskbyname(disk_type) == NULL)
+ errx(EXIT_FAILURE, "bad disktype");
+
if (sh_flag && (a_flag || i_flag || u_flag || f_flag || s_flag))
usage();
@@ -563,6 +578,7 @@
"[-b cylinders/heads/sectors] \\\n"
"%*s[-0123 | -E num "
"[-s id/start/size[/bootmenu]]] \\\n"
+ "%*s[-t disktab] [-T disktype] \\\n"
"%*s[-c bootcode] [-r|-w file] [device]\n"
"\t-a change active partition\n"
"\t-f force - not interactive\n"
@@ -571,8 +587,9 @@
"\t-u update partition data\n"
"\t-v verbose output, -v -v more verbose still\n"
"\t-B update bootselect options\n"
+ "\t-F treat device as a regular file\n"
"\t-S output as shell defines\n",
- getprogname(), indent, "", indent, "");
+ getprogname(), indent, "", indent, "", indent, "");
exit(1);
}
@@ -2213,36 +2230,63 @@
return (write(wfd, buf, 512));
}
+static void
+guess_geometry(daddr_t _sectors)
+{
+ /* guess - has to better than the above */
+ dos_sectors = MAXSECTOR;
+ dos_heads = MAXHEAD - 1; /* some BIOS might use 256 */
+ dos_cylinders = _sectors / (MAXSECTOR * (MAXHEAD - 1));
+ if (dos_cylinders > MAXCYL - 1)
+ dos_cylinders = MAXCYL - 1;
+}
+
int
get_params(void)
{
+ if (disk_type != NULL) {
+ struct disklabel *tmplabel;
- if (ioctl(fd, DIOCGDEFLABEL, &disklabel) == -1) {
+ if ((tmplabel = getdiskbyname(disk_type)) == NULL) {
+ warn("bad disktype");
+ return (-1);
+ }
+ disklabel = *tmplabel;
+ } else if (F_flag) {
+ struct stat st;
+ if (fstat(fd, &st) == -1) {
+ warn("fstat");
+ return (-1);
+ }
+ if (st.st_size % 512 != 0) {
+ warnx("%s size (%lld) is not divisible "
+ "by sector size (%d)", disk, (long long)st.st_size,
+ 512);
+ }
+ disklabel.d_secperunit = st.st_size / 512;
+ guess_geometry(disklabel.d_secperunit);
+ disklabel.d_ncylinders = dos_cylinders;
+ disklabel.d_ntracks = dos_heads;
+ disklabel.d_nsectors = dos_sectors;
+ } else if (ioctl(fd, DIOCGDEFLABEL, &disklabel) == -1) {
warn("DIOCGDEFLABEL");
if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
warn("DIOCGDINFO");
return (-1);
}
}
-
+ disksectors = disklabel.d_secperunit;
cylinders = disklabel.d_ncylinders;
heads = disklabel.d_ntracks;
sectors = disklabel.d_nsectors;
- disksectors = disklabel.d_secperunit;
/* pick up some defaults for the BIOS sizes */
if (sectors <= MAXSECTOR) {
dos_cylinders = cylinders;
dos_heads = heads;
dos_sectors = sectors;
- } else {
- /* guess - has to better than the above */
- dos_sectors = MAXSECTOR;
- dos_heads = MAXHEAD - 1; /* some BIOS might use 256 */
- dos_cylinders = disksectors / (MAXSECTOR * (MAXHEAD - 1));
- if (dos_cylinders > MAXCYL - 1)
- dos_cylinders = MAXCYL - 1;
- }
+ } else
+ guess_geometry(disksectors);
dos_disksectors = disksectors;
return (0);
@@ -2279,7 +2323,7 @@
* sector 0. (e.g. empty disk)
*/
flag = 1;
- if (wfd == fd && ioctl(wfd, DIOCWLABEL, &flag) < 0)
+ if (wfd == fd && F_flag == 0 && ioctl(wfd, DIOCWLABEL, &flag) < 0)
warn("DIOCWLABEL");
if (write_disk(0, &mboot) == -1) {
warn("Can't write fdisk partition table");
@@ -2301,7 +2345,7 @@
rval = 0;
protect_label:
flag = 0;
- if (wfd == fd && ioctl(wfd, DIOCWLABEL, &flag) < 0)
+ if (wfd == fd && F_flag == 0 && ioctl(wfd, DIOCWLABEL, &flag) < 0)
warn("DIOCWLABEL");
return rval;
}
Index: disklabel/disklabel.8
===================================================================
RCS file: /cvsroot/src/sbin/disklabel/disklabel.8,v
retrieving revision 1.49
diff -u -r1.49 disklabel.8
--- disklabel/disklabel.8 10 Nov 2003 09:22:09 -0000 1.49
+++ disklabel/disklabel.8 2 Mar 2004 08:10:45 -0000
@@ -42,10 +42,12 @@
.Nm
.Op Fl rt
.Op Fl C
+.Op Fl F
.Ar disk
.Nm
.Fl w
.Op Fl r
+.Op Fl F
.Op Fl f Ar disktab
.Ar disk Ar disktype
.Oo Ar packid Oc
@@ -54,15 +56,18 @@
.Op Fl r
.Op Fl I
.Op Fl C
+.Op Fl F
.Ar disk
.Nm
.Fl i
.Op Fl I
.Op Fl r
+.Op Fl F
.Ar disk
.Nm
.Fl R
.Op Fl r
+.Op Fl F
.Ar disk Ar protofile
.Nm
.Op Fl NW
@@ -70,6 +75,7 @@
.sp
.Nm
.Fl B
+.Op Fl F
.Op Fl f Ar disktab
.Oo
.Fl b Ar boot1
@@ -80,6 +86,7 @@
.Nm
.Fl w
.Fl B
+.Op Fl F
.Op Fl f Ar disktab
.Oo
.Fl b Ar boot1
@@ -90,6 +97,7 @@
.Nm
.Fl R
.Fl B
+.Op Fl F
.Op Fl f Ar disktab
.Oo
.Fl b Ar boot1
@@ -122,6 +130,15 @@
flag are described with the affected commands.
.Pp
The
+.Fl F
+option indicates that
+.Nm
+should treat
+.Ar disk
+as if it is a regular file, instead of as if it is a block device,
+for the purposes of reading and writing a disklabel.
+.Pp
+The
.Fl I
option is similar to the
.Fl r
Index: disklabel/disklabel.c
===================================================================
RCS file: /cvsroot/src/sbin/disklabel/disklabel.c,v
retrieving revision 1.127
diff -u -r1.127 disklabel.c
--- disklabel/disklabel.c 29 Feb 2004 21:31:14 -0000 1.127
+++ disklabel/disklabel.c 2 Mar 2004 08:10:45 -0000
@@ -122,16 +122,19 @@
UNSPEC, EDIT, READ, RESTORE, SETWRITABLE, WRITE, WRITEBOOT, INTERACT
} op = UNSPEC;
+static int Fflag;
static int rflag;
static int tflag;
int Cflag;
static int Iflag;
+#define COMMON_OPTIONS "BCFINRWb:ef:irs:tw"
+
#ifdef DEBUG
static int debug;
-#define OPTIONS "BCINRWb:def:irs:tw"
+#define OPTIONS COMMON_OPTIONS "d"
#else /* ! DEBUG */
-#define OPTIONS "BCINRWb:ef:irs:tw"
+#define OPTIONS COMMON_OPTIONS
#endif /* ! DEBUG */
#ifdef USE_MBR
@@ -194,6 +197,9 @@
case 'C':
++Cflag;
break;
+ case 'F':
+ ++Fflag;
+ break;
case 'I':
++Iflag;
break;
@@ -473,7 +479,7 @@
lp->d_checksum = 0;
lp->d_checksum = dkcksum(lp);
- if (rflag || Iflag)
+ if (Fflag || rflag || Iflag)
{
#ifdef USE_MBR
struct partition *pp = &lp->d_partitions[2];
@@ -524,7 +530,7 @@
* disable after writing.
*/
writable = 1;
- if (ioctl(f, DIOCWLABEL, &writable) < 0)
+ if (!Fflag && ioctl(f, DIOCWLABEL, &writable) < 0)
perror("ioctl DIOCWLABEL");
#ifdef __alpha__
@@ -556,13 +562,13 @@
#endif /* NUMBOOT > 0 */
writable = 0;
- if (ioctl(f, DIOCWLABEL, &writable) < 0)
+ if (!Fflag && ioctl(f, DIOCWLABEL, &writable) < 0)
perror("ioctl DIOCWLABEL");
/*
* Now issue a DIOCWDINFO. This will let the kernel convert the
* disklabel to some machdep format if needed.
*/
- if (ioctl(f, DIOCWDINFO, lp) < 0) {
+ if (!Fflag && ioctl(f, DIOCWDINFO, lp) < 0) {
l_perror("ioctl DIOCWDINFO");
return (1);
}
@@ -871,7 +877,7 @@
{
struct disklabel *lp;
- if (rflag || Iflag) {
+ if (Fflag || rflag || Iflag) {
const char *msg;
off_t sectoffset;
@@ -1827,20 +1833,20 @@
const char *name;
const char *expn;
} usages[] = {
- { "[-rt] [-C] disk",
+ { "[-rt] [-C] [-F] disk",
"(to read label)" },
- { "-w [-r] [-f disktab] disk type [ packid ]",
+ { "-w [-r] [-F] [-f disktab] disk type [ packid ]",
#if NUMBOOT > 0
"(to write label with existing boot program)"
#else
"(to write label)"
#endif
},
- { "-e [-r] [-I] [-C] disk",
+ { "-e [-r] [-I] [-C] [-F] disk",
"(to edit label)" },
- { "-i [-I] [-r] disk",
+ { "-i [-I] [-r] [-F] disk",
"(to create a label interactively)" },
- { "-R [-r] disk protofile",
+ { "-R [-r] [-F] disk protofile",
#if NUMBOOT > 0
"(to restore label with existing boot program)"
#else
@@ -1851,16 +1857,16 @@
# if NUMBOOT > 1
{ "-B [-f disktab] [ -b xxboot [ -s bootxx ] ] disk [ type ]",
"(to install boot program with existing label)" },
- { "-w -B [-f disktab] [ -b xxboot [ -s bootxx ] ] disk type [ packid ]",
+ { "-w -B [-F] [-f disktab] [ -b xxboot [ -s bootxx ] ] disk type [ packid ]",
"(to write label and boot program)" },
- { "-R -B [-f disktab] [ -b xxboot [ -s bootxx ] ] disk protofile [ type ]",
+ { "-R -B [-F] [-f disktab] [ -b xxboot [ -s bootxx ] ] disk protofile [ type ]",
"(to restore label and boot program)" },
# else
- { "-B [-f disktab] [ -b bootprog ] disk [ type ]",
+ { "-B [-F] [-f disktab] [ -b bootprog ] disk [ type ]",
"(to install boot program with existing on-disk label)" },
- { "-w -B [-f disktab] [ -b bootprog ] disk type [ packid ]",
+ { "-w -B [-F] [-f disktab] [ -b bootprog ] disk type [ packid ]",
"(to write label and install boot program)" },
- { "-R -B [-f disktab] [ -b bootprog ] disk protofile [ type ]",
+ { "-R -B [-F] [-f disktab] [ -b bootprog ] disk protofile [ type ]",
"(to restore label and install boot program)" },
# endif
#endif
--kXdP64Ggrk/fb43R--