From 276b1de4c64e0c29aa73cdbd5c127bdf2313e30c Mon Sep 17 00:00:00 2001 From: joerg Date: Tue, 30 Jan 1996 02:35:08 +0000 Subject: Attempt to figure out the size of the device/file we are about to format. A bit tricky, but i believe this to work for 98 % of the cases. --- usr.sbin/mkdosfs/mkdosfs.1 | 11 +++++- usr.sbin/mkdosfs/mkdosfs.c | 92 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 90 insertions(+), 13 deletions(-) diff --git a/usr.sbin/mkdosfs/mkdosfs.1 b/usr.sbin/mkdosfs/mkdosfs.1 index e6b06ac..e08e755 100644 --- a/usr.sbin/mkdosfs/mkdosfs.1 +++ b/usr.sbin/mkdosfs/mkdosfs.1 @@ -1,5 +1,5 @@ .\" -.\" Copyright (c) 1995 Joerg Wunsch +.\" Copyright (c) 1995, 1996 Joerg Wunsch .\" .\" All rights reserved. .\" @@ -25,7 +25,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $Id$ +.\" $Id: mkdosfs.1,v 1.1.1.1 1995/11/05 16:02:04 joerg Exp $ .\" .Dd November 5, 1995 .Os @@ -60,6 +60,13 @@ Use defaults for a typical file system with .Ar capacity kilobytes. Currently, the values 360, 720, 1200, and 1440 are recognized. +.Pp +If this option is not specified, +.Nm +attempts to determine the size of the +.Ar device . +This is not reliably possible in all cases, but is believed to work +for the more common situations. .It Fl L Ar vollabel Use .Ar vollabel diff --git a/usr.sbin/mkdosfs/mkdosfs.c b/usr.sbin/mkdosfs/mkdosfs.c index 2e88d16..23a6dfe 100644 --- a/usr.sbin/mkdosfs/mkdosfs.c +++ b/usr.sbin/mkdosfs/mkdosfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995 Joerg Wunsch + * Copyright (c) 1995, 1996 Joerg Wunsch * * All rights reserved. * @@ -29,16 +29,18 @@ /* * Create an MS-DOS (FAT) file system. * - * $Id$ + * $Id: mkdosfs.c,v 1.1.1.1 1995/11/05 16:02:04 joerg Exp $ */ #include +#include #include #include #include #include #include #include +#include #include #include "bootcode.h" @@ -71,23 +73,24 @@ struct descrip static struct descrip table[] = { + /* NB: must be sorted, starting with the largest format! */ /* * kilobytes * sec cls res fat rot tot med fsz spt hds hid * tot phs ebt label fsysid */ - { 720, - 512, 2, 1, 2, 112, 1440, 0xf9, 3, 9, 2, 0, - 0, 0, 0, "4.4BSD ", "FAT12 "}, {1440, 512, 1, 1, 2, 224, 2880, 0xf0, 9, 18, 2, 0, 0, 0, 0, "4.4BSD ", "FAT12 "}, - { 360, - 512, 2, 1, 2, 112, 720, 0xfd, 2, 9, 2, 0, - 0, 0, 0, "4.4BSD ", "FAT12 "}, {1200, 512, 1, 1, 2, 224, 2400, 0xf9, 7, 15, 2, 0, 0, 0, 0, "4.4BSD ", "FAT12 "}, + { 720, + 512, 2, 1, 2, 112, 1440, 0xf9, 3, 9, 2, 0, + 0, 0, 0, "4.4BSD ", "FAT12 "}, + { 360, + 512, 2, 1, 2, 112, 720, 0xfd, 2, 9, 2, 0, + 0, 0, 0, "4.4BSD ", "FAT12 "}, }; void @@ -97,6 +100,64 @@ usage(void) errx(2, "[-f kbytes] [-L label] device"); } +unsigned +findformat(int fd) +{ + struct stat sb; + + /* + * This is a bit tricky. If the argument is a regular file, we can + * lseek() to its end and get the size reported. If it's a device + * however, lseeking doesn't report us any useful number. Instead, + * we try to seek just to the end of the device and try reading a + * block there. In the case where we've hit exactly the device + * boundary, we get a zero read, and thus have found the size. + * Since our knowledge of distinct formats is limited anyway, this + * is not a big deal at all. + */ + + if(fstat(fd, &sb) == -1) + err(1, "Huh? Cannot fstat()"); /* Cannot happen */ + if(S_ISREG(sb.st_mode)) + { + off_t o; + if(lseek(fd, (off_t)0, SEEK_END) == -1 || + (o = lseek(fd, (off_t)0, SEEK_CUR)) == -1) + /* Hmm, hmm. Hard luck. */ + return 0; + return (int)(o / 1024); + } + else if(S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) + { + char b[512]; + int i, rv; + struct descrip *dp; + + for(i = 0, dp = table; + i < sizeof table / sizeof(struct descrip); + i++, dp++) + { + if(lseek(fd, (off_t)(dp->kilobytes * 1024), SEEK_SET) == 1) + /* Uh-oh, lseek() is not supposed to fail. */ + return 0; + if((rv = read(fd, b, 512)) == 0) + break; + /* XXX The ENOSPC is for the bogus fd(4) driver return value. */ + if(rv == -1 && errno != EINVAL && errno != ENOSPC) + return 0; + /* else: continue */ + } + if(i == sizeof table / sizeof(struct descrip)) + return 0; + (void)lseek(fd, (off_t)0, SEEK_SET); + return dp->kilobytes; + } + else + /* Outta luck. */ + return 0; +} + + void setup_boot_sector_from_template(union bootsector *bs, struct descrip *dp) { @@ -166,14 +227,23 @@ main(int argc, char **argv) if(argc != 1) usage(); + if((fd = open(argv[0], O_RDWR|O_EXCL, 0)) == -1) + err(1, "open(%s)", argv[0]); + + if(format == 0) + { + /* + * No format specified, try to figure it out. + */ + if((format = findformat(fd)) == 0) + errx(1, "cannot determine size, must use -f format"); + } + for(i = 0, dp = table; i < sizeof table / sizeof(struct descrip); i++, dp++) if(dp->kilobytes == format) break; if(i == sizeof table / sizeof(struct descrip)) errx(1, "cannot find format description for %d KB", format); - - if((fd = open(argv[0], O_RDWR|O_EXCL, 0)) == -1) - err(1, "open(%s)", argv[0]); /* prepare and write the boot sector */ setup_boot_sector_from_template(&bs, dp); -- cgit v1.1