Subject: PATCH: disklabel & fdisk regular files
To: None <tech-userlevel@netbsd.org, dyoung@netbsd.org>
From: David Young <dyoung@pobox.com>
List: tech-userlevel
Date: 02/17/2004 01:46:38
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.
Please leave me on the To: line; I do not subscribe to tech-userlevel.
Dave
Index: sbin/disklabel/disklabel.c
===================================================================
RCS file: /cvsroot/src/sbin/disklabel/disklabel.c,v
retrieving revision 1.126
diff -u -r1.126 disklabel.c
--- sbin/disklabel/disklabel.c 18 Jan 2004 22:34:22 -0000 1.126
+++ sbin/disklabel/disklabel.c 17 Feb 2004 07:20:52 -0000
@@ -122,6 +122,7 @@
UNSPEC, EDIT, READ, RESTORE, SETWRITABLE, WRITE, WRITEBOOT, INTERACT
} op = UNSPEC;
+static int is_file;
static int rflag;
static int tflag;
int Cflag;
@@ -171,6 +172,7 @@
main(int argc, char *argv[])
{
struct disklabel *lp;
+ struct stat st;
FILE *t;
int ch, f, writable, error;
@@ -271,6 +273,9 @@
usage();
dkname = argv[0];
+ if (stat(dkname, &st) == -1)
+ err(EXIT_FAILURE, "stat");
+ is_file = ((st.st_mode & S_IFMT) == S_IFREG);
f = opendisk(dkname, op == READ ? O_RDONLY : O_RDWR, np, MAXPATHLEN, 0);
specname = np;
np += strlen(specname) + 1;
@@ -472,7 +477,7 @@
lp->d_checksum = 0;
lp->d_checksum = dkcksum(lp);
- if (rflag || Iflag)
+ if (is_file || rflag || Iflag)
{
#ifdef USE_MBR
struct partition *pp = &lp->d_partitions[2];
@@ -523,7 +528,7 @@
* disable after writing.
*/
writable = 1;
- if (ioctl(f, DIOCWLABEL, &writable) < 0)
+ if (!is_file && ioctl(f, DIOCWLABEL, &writable) < 0)
perror("ioctl DIOCWLABEL");
#ifdef __alpha__
@@ -555,13 +560,13 @@
#endif /* NUMBOOT > 0 */
writable = 0;
- if (ioctl(f, DIOCWLABEL, &writable) < 0)
+ if (!is_file && 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 (!is_file && ioctl(f, DIOCWDINFO, lp) < 0) {
l_perror("ioctl DIOCWDINFO");
return (1);
}
@@ -870,7 +875,7 @@
{
struct disklabel *lp;
- if (rflag || Iflag) {
+ if (is_file || rflag || Iflag) {
const char *msg;
off_t sectoffset;
Index: sbin/fdisk/fdisk.8
===================================================================
RCS file: /cvsroot/src/sbin/fdisk/fdisk.8,v
retrieving revision 1.43
diff -u -r1.43 fdisk.8
--- sbin/fdisk/fdisk.8 6 Oct 2003 12:02:52 -0000 1.43
+++ sbin/fdisk/fdisk.8 17 Feb 2004 07:20:52 -0000
@@ -13,6 +13,12 @@
.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
Index: sbin/fdisk/fdisk.c
===================================================================
RCS file: /cvsroot/src/sbin/fdisk/fdisk.c,v
retrieving revision 1.74
diff -u -r1.74 fdisk.c
--- sbin/fdisk/fdisk.c 5 Jan 2004 23:23:32 -0000 1.74
+++ sbin/fdisk/fdisk.c 17 Feb 2004 07:20:55 -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,7 +115,7 @@
#define DEFAULT_ACTIVE (~(daddr_t)0)
-#define OPTIONS "0123BSafiluvs:b:c:E:r:w:"
+#define OPTIONS "0123BSafiluvs: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:"
@@ -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 is_file = 0;
struct mbr_sector bootcode[8192 / sizeof (struct mbr_sector)];
int bootsize; /* actual size of bootcode */
@@ -445,13 +448,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();
@@ -470,8 +482,15 @@
usage();
}
- if (argc > 0)
+ if (argc > 0) {
disk = argv[0];
+ if (stat(disk, &sb) == -1)
+ err(EXIT_FAILURE, "stat(%s,)", disk);
+ if ((sb.st_mode & S_IFMT) == S_IFREG)
+ is_file = 1;
+ else if ((sb.st_mode & S_IFMT) != S_IFCHR)
+ errx(EXIT_FAILURE, "bad filetype for %s", disk);
+ }
if (open_disk(B_flag || a_flag || i_flag || u_flag) < 0)
exit(1);
@@ -563,6 +582,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"
@@ -572,7 +592,7 @@
"\t-v verbose output, -v -v more verbose still\n"
"\t-B update bootselect options\n"
"\t-S output as shell defines\n",
- getprogname(), indent, "", indent, "");
+ getprogname(), indent, "", indent, "", indent, "");
exit(1);
}
@@ -2216,8 +2236,15 @@
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 (ioctl(fd, DIOCGDEFLABEL, &disklabel) == -1) {
warn("DIOCGDEFLABEL");
if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
warn("DIOCGDINFO");
@@ -2279,7 +2306,7 @@
* sector 0. (e.g. empty disk)
*/
flag = 1;
- if (wfd == fd && ioctl(wfd, DIOCWLABEL, &flag) < 0)
+ if (wfd == fd && is_file == 0 && ioctl(wfd, DIOCWLABEL, &flag) < 0)
warn("DIOCWLABEL");
if (write_disk(0, &mboot) == -1) {
warn("Can't write fdisk partition table");
@@ -2301,7 +2328,7 @@
rval = 0;
protect_label:
flag = 0;
- if (wfd == fd && ioctl(wfd, DIOCWLABEL, &flag) < 0)
+ if (wfd == fd && is_file == 0 && ioctl(wfd, DIOCWLABEL, &flag) < 0)
warn("DIOCWLABEL");
return rval;
}
--
David Young OJC Technologies
dyoung@ojctech.com Urbana, IL * (217) 278-3933