--- mformat.c.orig 2013-01-08 23:14:21.000000000 +0100 +++ mformat.c 2018-08-11 15:26:57.772597760 +0200 @@ -721,6 +721,7 @@ static void usage(int ret) #ifdef OS_linux static int get_block_geom(int fd, struct device *dev, char *errmsg) { struct hd_geometry geom; + int sec_size; long size; int heads=dev->heads; int sectors=dev->sectors; @@ -738,6 +739,16 @@ static int get_block_geom(int fd, struct return -1; } + if (ioctl(fd, BLKSSZGET, &sec_size) != 0 || sec_size <= 0) { + sprintf(errmsg, "Could not get block size of device (%s)", + strerror(errno)); + return -1; + } + + dev->ssize = 0; + while (dev->ssize < 0x7F && (128 << dev->ssize) < sec_size) + dev->ssize++; + if(!heads) heads = geom.heads; if(!sectors) @@ -763,6 +774,93 @@ static int get_block_geom(int fd, struct } #endif +static int get_lba_geom(Stream_t *Direct, unsigned long tot_sectors, struct device *dev, char *errmsg) { + int sect_per_track; + unsigned long tracks; + + /* if one value is already specified we do not want to overwrite it */ + if (dev->heads || dev->sectors || dev->tracks) { + sprintf(errmsg, "Number of heads or sectors or tracks was already specified"); + return -1; + } + + if (!tot_sectors) { +#ifdef OS_linux + int fd; + int sec_size; + long size; + struct MT_STAT stbuf; + + fd = get_fd(Direct); + if (MT_FSTAT(fd, &stbuf) < 0) { + sprintf(errmsg, "Could not stat file (%s)", strerror(errno)); + return -1; + } + + if (S_ISBLK(stbuf.st_mode)) { + if (ioctl(fd, BLKGETSIZE, &size) != 0) { + sprintf(errmsg, "Could not get size of device (%s)", + strerror(errno)); + return -1; + } + if (ioctl(fd, BLKSSZGET, &sec_size) != 0 || sec_size <= 0) { + sprintf(errmsg, "Could not get block size of device (%s)", + strerror(errno)); + return -1; + } + if (!(dev->ssize & 0x80)) { + dev->ssize = 0; + while (dev->ssize < 0x7F && (128 << dev->ssize) < sec_size) + dev->ssize++; + } + if ((dev->ssize & 0x7f) > 2) + tot_sectors = size >> ((dev->ssize & 0x7f) - 2); + else + tot_sectors = size << (2 - (dev->ssize & 0x7f)); + } else if (S_ISREG(stbuf.st_mode)) { + tot_sectors = stbuf.st_size >> ((dev->ssize & 0x7f) + 7); + } else { + sprintf(errmsg, "Could not get size of device (%s)", + "No method available"); + return -1; + } +#else + mt_size_t size; + GET_DATA(Direct, 0, &size, 0, 0); + if (size == 0) { + sprintf(errmsg, "Could not get size of device (%s)", + "No method available"); + return -1; + } + tot_sectors = size >> ((dev->ssize & 0x7f) + 7); +#endif + } + + dev->sectors = 63; + + if (tot_sectors < 16*63*1024) + dev->heads = 16; + else if (tot_sectors < 32*63*1024) + dev->heads = 32; + else if (tot_sectors < 64*63*1024) + dev->heads = 64; + else if (tot_sectors < 128*63*1024) + dev->heads = 128; + else + dev->heads = 255; + + sect_per_track = dev->heads * dev->sectors; + tracks = (tot_sectors + dev->hidden % sect_per_track) / sect_per_track; + if (tracks > 0xFFFFFFFF) { + sprintf(errmsg, "Device is too big, it has too many tracks"); + return -1; + } + + dev->tracks = tracks; + + return 0; +} + void mformat(int argc, char **argv, int dummy) { int r; /* generic return value */ @@ -1117,19 +1215,21 @@ void mformat(int argc, char **argv, int if (S_ISBLK(stbuf.st_mode) && get_block_geom(fd, &used_dev, errmsg) < 0) - continue; + fprintf(stderr, "%s: %s\n", argv[0], errmsg); } #endif - /* no way to find out geometry */ if ((!used_dev.tracks && !tot_sectors) || !used_dev.heads || !used_dev.sectors){ - sprintf(errmsg, - "Unknown geometry " - "(You must tell the complete geometry " - "of the disk, \neither in /etc/mtools.conf or " - "on the command line) "); - continue; + printf("%s: " + "Complete geometry of the disk was not specified, \n" + "neither in /etc/mtools.conf nor on the command line. \n" + "Using LBA Assist Translation for calculating CHS geometry " + "of the disk.\n", argv[0]); + if (get_lba_geom(Fs.Direct, tot_sectors, &used_dev, errmsg) < 0) + continue; + printf("sector size: %u, sectors: %u, heads: %u, tracks: %u\n", + 128 << (used_dev.ssize & 0x7f), used_dev.sectors, used_dev.heads, used_dev.tracks); } #if 0 @@ -1143,6 +1243,8 @@ void mformat(int argc, char **argv, int Fs.sector_size = 512; if( !(used_dev.use_2m & 0x7f)) { Fs.sector_size = 128 << (used_dev.ssize & 0x7f); + if (Fs.sector_size > 4096) + Fs.sector_size = 4096; } SET_INT(Fs.sector_size, msize);