diff --git a/sbin/bsdlabel/bsdlabel.8 b/sbin/bsdlabel/bsdlabel.8 index bf14e0f23b04..1cc33abe7aff 100644 --- a/sbin/bsdlabel/bsdlabel.8 +++ b/sbin/bsdlabel/bsdlabel.8 @@ -161,6 +161,21 @@ If the disk does not already have a label, the flag must be used. In either case, the kernel's in-core label is replaced. .Pp +For a virgin disk that is not known to +.Xr disktab 5 , +.Ar disktype +can be specified as +.Dq auto . +In this case, the driver is requested to produce a virgin label for the +disk. This might or might not be successful, depending on whether the +driver for the disk is able to get the required data without reading +anything from the disk at all. It will likely succeed for all SCSI +disks, most IDE disks, and vnode devices. Writing a label to the +disk is the only supported operation, and the +.Ar disk +itself must be provided as the canonical name, i.e. not as a full +path name. +.Pp An existing disk label may be edited by using the .Fl e flag. @@ -286,6 +301,12 @@ Read the on-disk label for sd0, edit it and reinstall in-core as well as on-disk. Existing bootstrap code is unaffected. .Pp +.Dl disklabel -r -w sd0 auto +.Pp +Try to auto-detect the required information from sd0, and write a new +label to the disk. Use another disklabel -e command to edit the +partitioning and file system information. +.Pp .Dl disklabel -R sd0 mylabel .Pp Restore the on-disk and in-core label for sd0 from information in diff --git a/sbin/bsdlabel/bsdlabel.c b/sbin/bsdlabel/bsdlabel.c index d3337c1941a5..cf93fc4373ff 100644 --- a/sbin/bsdlabel/bsdlabel.c +++ b/sbin/bsdlabel/bsdlabel.c @@ -110,6 +110,7 @@ void Warning (char *, ...); void Perror __P((char *)); void usage __P((void)); extern u_short dkcksum __P((struct disklabel *)); +struct disklabel * getvirginlabel __P((void)); #define DEFEDITOR _PATH_VI #define streq(a,b) (strcmp(a,b) == 0) @@ -336,7 +337,10 @@ makelabel(type, name, lp) register struct disklabel *lp; { register struct disklabel *dp; - char *strcpy(); + + if (strcmp(type, "auto") == 0) + dp = getvirginlabel(); + else dp = getdiskbyname(type); if (dp == NULL) { fprintf(stderr, "%s: unknown disk type\n", type); @@ -1279,6 +1283,48 @@ checklabel(lp) return (errors); } +/* + * When operating on a "virgin" disk, try getting an initial label + * from the associated device driver. This might work for all device + * drivers that are able to fetch some initial device parameters + * without even having access to a (BSD) disklabel, like SCSI disks, + * most IDE drives, or vn devices. + * + * The device name must be given in its "canonical" form. + */ +struct disklabel * +getvirginlabel(void) +{ + static struct disklabel lab; + char namebuf[BBSIZE]; + int f; + + if (dkname[0] == '/') { + fprintf(stderr, + "\"auto\" requires the usage of a canonical disk name.\n"); + return 0; + } + (void)snprintf(namebuf, BBSIZE, "%sr%s", _PATH_DEV, dkname); + if ((f = open(namebuf, O_RDONLY, 0)) == -1) { + Perror("open()"); + return 0; + } + if (ioctl(f, DIOCGDINFO, &lab) < 0) { + Perror("ioctl DIOCGDINFO"); + close(f); + return 0; + } + close(f); + /* insert reasonable defaults where necessary */ + if (lab.d_npartitions < 8) lab.d_npartitions = 8; + if (lab.d_bbsize == 0) lab.d_bbsize = BBSIZE; + if (lab.d_sbsize == 0) lab.d_sbsize = SBSIZE; + if (lab.d_rpm == 0) lab.d_rpm = 3600; + if (lab.d_interleave == 0) lab.d_interleave = 1; + return &lab; +} + + /* * If we are installing a boot program that doesn't fit in d_bbsize * we need to mark those partitions that the boot overflows into. diff --git a/sbin/disklabel/disklabel.8 b/sbin/disklabel/disklabel.8 index bf14e0f23b04..1cc33abe7aff 100644 --- a/sbin/disklabel/disklabel.8 +++ b/sbin/disklabel/disklabel.8 @@ -161,6 +161,21 @@ If the disk does not already have a label, the flag must be used. In either case, the kernel's in-core label is replaced. .Pp +For a virgin disk that is not known to +.Xr disktab 5 , +.Ar disktype +can be specified as +.Dq auto . +In this case, the driver is requested to produce a virgin label for the +disk. This might or might not be successful, depending on whether the +driver for the disk is able to get the required data without reading +anything from the disk at all. It will likely succeed for all SCSI +disks, most IDE disks, and vnode devices. Writing a label to the +disk is the only supported operation, and the +.Ar disk +itself must be provided as the canonical name, i.e. not as a full +path name. +.Pp An existing disk label may be edited by using the .Fl e flag. @@ -286,6 +301,12 @@ Read the on-disk label for sd0, edit it and reinstall in-core as well as on-disk. Existing bootstrap code is unaffected. .Pp +.Dl disklabel -r -w sd0 auto +.Pp +Try to auto-detect the required information from sd0, and write a new +label to the disk. Use another disklabel -e command to edit the +partitioning and file system information. +.Pp .Dl disklabel -R sd0 mylabel .Pp Restore the on-disk and in-core label for sd0 from information in diff --git a/sbin/disklabel/disklabel.c b/sbin/disklabel/disklabel.c index d3337c1941a5..cf93fc4373ff 100644 --- a/sbin/disklabel/disklabel.c +++ b/sbin/disklabel/disklabel.c @@ -110,6 +110,7 @@ void Warning (char *, ...); void Perror __P((char *)); void usage __P((void)); extern u_short dkcksum __P((struct disklabel *)); +struct disklabel * getvirginlabel __P((void)); #define DEFEDITOR _PATH_VI #define streq(a,b) (strcmp(a,b) == 0) @@ -336,7 +337,10 @@ makelabel(type, name, lp) register struct disklabel *lp; { register struct disklabel *dp; - char *strcpy(); + + if (strcmp(type, "auto") == 0) + dp = getvirginlabel(); + else dp = getdiskbyname(type); if (dp == NULL) { fprintf(stderr, "%s: unknown disk type\n", type); @@ -1279,6 +1283,48 @@ checklabel(lp) return (errors); } +/* + * When operating on a "virgin" disk, try getting an initial label + * from the associated device driver. This might work for all device + * drivers that are able to fetch some initial device parameters + * without even having access to a (BSD) disklabel, like SCSI disks, + * most IDE drives, or vn devices. + * + * The device name must be given in its "canonical" form. + */ +struct disklabel * +getvirginlabel(void) +{ + static struct disklabel lab; + char namebuf[BBSIZE]; + int f; + + if (dkname[0] == '/') { + fprintf(stderr, + "\"auto\" requires the usage of a canonical disk name.\n"); + return 0; + } + (void)snprintf(namebuf, BBSIZE, "%sr%s", _PATH_DEV, dkname); + if ((f = open(namebuf, O_RDONLY, 0)) == -1) { + Perror("open()"); + return 0; + } + if (ioctl(f, DIOCGDINFO, &lab) < 0) { + Perror("ioctl DIOCGDINFO"); + close(f); + return 0; + } + close(f); + /* insert reasonable defaults where necessary */ + if (lab.d_npartitions < 8) lab.d_npartitions = 8; + if (lab.d_bbsize == 0) lab.d_bbsize = BBSIZE; + if (lab.d_sbsize == 0) lab.d_sbsize = SBSIZE; + if (lab.d_rpm == 0) lab.d_rpm = 3600; + if (lab.d_interleave == 0) lab.d_interleave = 1; + return &lab; +} + + /* * If we are installing a boot program that doesn't fit in d_bbsize * we need to mark those partitions that the boot overflows into.