Changeset View
Changeset View
Standalone View
Standalone View
head/sbin/newfs_msdos/mkfs_msdos.c
Show First 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | |||||
#include "mkfs_msdos.h" | #include "mkfs_msdos.h" | ||||
#define MAXU16 0xffff /* maximum unsigned 16-bit quantity */ | #define MAXU16 0xffff /* maximum unsigned 16-bit quantity */ | ||||
#define BPN 4 /* bits per nibble */ | #define BPN 4 /* bits per nibble */ | ||||
#define NPB 2 /* nibbles per byte */ | #define NPB 2 /* nibbles per byte */ | ||||
#define DOSMAGIC 0xaa55 /* DOS magic number */ | #define DOSMAGIC 0xaa55 /* DOS magic number */ | ||||
#define MINBPS 512 /* minimum bytes per sector */ | #define MINBPS 512 /* minimum bytes per sector */ | ||||
#define MAXBPS 4096 /* maximum bytes per sector */ | |||||
#define MAXSPC 128 /* maximum sectors per cluster */ | #define MAXSPC 128 /* maximum sectors per cluster */ | ||||
#define MAXNFT 16 /* maximum number of FATs */ | #define MAXNFT 16 /* maximum number of FATs */ | ||||
#define DEFBLK 4096 /* default block size */ | #define DEFBLK 4096 /* default block size */ | ||||
#define DEFBLK16 2048 /* default block size FAT16 */ | #define DEFBLK16 2048 /* default block size FAT16 */ | ||||
#define DEFRDE 512 /* default root directory entries */ | #define DEFRDE 512 /* default root directory entries */ | ||||
#define RESFTE 2 /* reserved FAT entries */ | #define RESFTE 2 /* reserved FAT entries */ | ||||
#define MINCLS12 1U /* minimum FAT12 clusters */ | #define MINCLS12 1U /* minimum FAT12 clusters */ | ||||
#define MINCLS16 0xff5U /* minimum FAT16 clusters */ | #define MINCLS16 0xff5U /* minimum FAT16 clusters */ | ||||
#define MINCLS32 0xfff5U /* minimum FAT32 clusters */ | #define MINCLS32 0xfff5U /* minimum FAT32 clusters */ | ||||
#define MAXCLS12 0xff4U /* maximum FAT12 clusters */ | #define MAXCLS12 0xff4U /* maximum FAT12 clusters */ | ||||
#define MAXCLS16 0xfff4U /* maximum FAT16 clusters */ | #define MAXCLS16 0xfff4U /* maximum FAT16 clusters */ | ||||
#define MAXCLS32 0xffffff4U /* maximum FAT32 clusters */ | #define MAXCLS32 0xffffff4U /* maximum FAT32 clusters */ | ||||
#ifndef CTASSERT | |||||
#define CTASSERT(x) _CTASSERT(x, __LINE__) | |||||
#define _CTASSERT(x, y) __CTASSERT(x, y) | |||||
#define __CTASSERT(x, y) typedef char __assert_ ## y [(x) ? 1 : -1] | |||||
#endif | |||||
/* | |||||
* For better performance, we want to write larger chunks instead of | |||||
* individual sectors (the size can only be 512, 1024, 2048 or 4096 | |||||
* bytes). Assert that MAXPHYS can always hold an integer number of | |||||
* sectors by asserting that both are power of two numbers and the | |||||
* MAXPHYS is greater than MAXBPS. | |||||
*/ | |||||
CTASSERT(powerof2(MAXPHYS)); | |||||
CTASSERT(powerof2(MAXBPS)); | |||||
CTASSERT(MAXPHYS > MAXBPS); | |||||
const static ssize_t chunksize = MAXPHYS; | |||||
#define mincls(fat) ((fat) == 12 ? MINCLS12 : \ | #define mincls(fat) ((fat) == 12 ? MINCLS12 : \ | ||||
(fat) == 16 ? MINCLS16 : \ | (fat) == 16 ? MINCLS16 : \ | ||||
MINCLS32) | MINCLS32) | ||||
#define maxcls(fat) ((fat) == 12 ? MAXCLS12 : \ | #define maxcls(fat) ((fat) == 12 ? MAXCLS12 : \ | ||||
(fat) == 16 ? MAXCLS16 : \ | (fat) == 16 ? MAXCLS16 : \ | ||||
MAXCLS32) | MAXCLS32) | ||||
▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | mkfs_msdos(const char *fname, const char *dtype, const struct msdos_options *op) | ||||
struct bpb bpb; | struct bpb bpb; | ||||
struct tm *tm; | struct tm *tm; | ||||
struct bs *bs; | struct bs *bs; | ||||
struct bsbpb *bsbpb; | struct bsbpb *bsbpb; | ||||
struct bsxbpb *bsxbpb; | struct bsxbpb *bsxbpb; | ||||
struct bsx *bsx; | struct bsx *bsx; | ||||
struct de *de; | struct de *de; | ||||
u_int8_t *img; | u_int8_t *img; | ||||
u_int8_t *physbuf, *physbuf_end; | |||||
const char *bname; | const char *bname; | ||||
ssize_t n; | ssize_t n; | ||||
time_t now; | time_t now; | ||||
u_int fat, bss, rds, cls, dir, lsn, x, x1, x2; | u_int fat, bss, rds, cls, dir, lsn, x, x1, x2; | ||||
u_int extra_res, alignment, saved_x, attempts=0; | u_int extra_res, alignment, saved_x, attempts=0; | ||||
bool set_res, set_spf, set_spc; | bool set_res, set_spf, set_spc; | ||||
int fd, fd1, rv; | int fd, fd1, rv; | ||||
struct msdos_options o = *op; | struct msdos_options o = *op; | ||||
img = NULL; | physbuf = NULL; | ||||
rv = -1; | rv = -1; | ||||
fd = fd1 = -1; | fd = fd1 = -1; | ||||
if (o.block_size && o.sectors_per_cluster) { | if (o.block_size && o.sectors_per_cluster) { | ||||
warnx("Cannot specify both block size and sectors per cluster"); | warnx("Cannot specify both block size and sectors per cluster"); | ||||
goto done; | goto done; | ||||
} | } | ||||
if (o.OEM_string && strlen(o.OEM_string) > 8) { | if (o.OEM_string && strlen(o.OEM_string) > 8) { | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | bpb.bpbSecPerClust = 8; | ||||
else if (bpb.bpbHugeSectors <= (1<<19)) /* 256M -> 8k */ | else if (bpb.bpbHugeSectors <= (1<<19)) /* 256M -> 8k */ | ||||
bpb.bpbSecPerClust = 16; | bpb.bpbSecPerClust = 16; | ||||
else if (bpb.bpbHugeSectors <= (1<<21)) /* 1G -> 16k */ | else if (bpb.bpbHugeSectors <= (1<<21)) /* 1G -> 16k */ | ||||
bpb.bpbSecPerClust = 32; | bpb.bpbSecPerClust = 32; | ||||
else | else | ||||
bpb.bpbSecPerClust = 64; /* otherwise 32k */ | bpb.bpbSecPerClust = 64; /* otherwise 32k */ | ||||
} | } | ||||
} | } | ||||
if (!powerof2(bpb.bpbBytesPerSec)) { | if (bpb.bpbBytesPerSec < MINBPS || | ||||
warnx("bytes/sector (%u) is not a power of 2", bpb.bpbBytesPerSec); | bpb.bpbBytesPerSec > MAXBPS || | ||||
!powerof2(bpb.bpbBytesPerSec)) { | |||||
warnx("Invalid bytes/sector (%u): must be 512, 1024, 2048 or 4096", | |||||
bpb.bpbBytesPerSec); | |||||
goto done; | goto done; | ||||
} | } | ||||
if (bpb.bpbBytesPerSec < MINBPS) { | |||||
warnx("bytes/sector (%u) is too small; minimum is %u", | |||||
bpb.bpbBytesPerSec, MINBPS); | |||||
goto done; | |||||
} | |||||
if (o.volume_label && !oklabel(o.volume_label)) { | if (o.volume_label && !oklabel(o.volume_label)) { | ||||
warnx("%s: bad volume label", o.volume_label); | warnx("%s: bad volume label", o.volume_label); | ||||
goto done; | goto done; | ||||
} | } | ||||
if (!(fat = o.fat_type)) { | if (!(fat = o.fat_type)) { | ||||
if (o.floppy) | if (o.floppy) | ||||
fat = 12; | fat = 12; | ||||
▲ Show 20 Lines • Show All 253 Lines • ▼ Show 20 Lines | if (o.timestamp_set) { | ||||
tv.tv_usec = 0; | tv.tv_usec = 0; | ||||
tm = gmtime(&now); | tm = gmtime(&now); | ||||
} else { | } else { | ||||
gettimeofday(&tv, NULL); | gettimeofday(&tv, NULL); | ||||
now = tv.tv_sec; | now = tv.tv_sec; | ||||
tm = localtime(&now); | tm = localtime(&now); | ||||
} | } | ||||
physbuf = malloc(chunksize); | |||||
if (!(img = malloc(bpb.bpbBytesPerSec))) { | if (physbuf == NULL) { | ||||
warn(NULL); | warn(NULL); | ||||
goto done; | goto done; | ||||
} | } | ||||
physbuf_end = physbuf + chunksize; | |||||
img = physbuf; | |||||
dir = bpb.bpbResSectors + (bpb.bpbFATsecs ? bpb.bpbFATsecs : | dir = bpb.bpbResSectors + (bpb.bpbFATsecs ? bpb.bpbFATsecs : | ||||
bpb.bpbBigFATsecs) * bpb.bpbFATs; | bpb.bpbBigFATsecs) * bpb.bpbFATs; | ||||
memset(&si_sa, 0, sizeof(si_sa)); | memset(&si_sa, 0, sizeof(si_sa)); | ||||
si_sa.sa_handler = infohandler; | si_sa.sa_handler = infohandler; | ||||
#ifdef SIGINFO | #ifdef SIGINFO | ||||
if (sigaction(SIGINFO, &si_sa, NULL) == -1) { | if (sigaction(SIGINFO, &si_sa, NULL) == -1) { | ||||
warn("sigaction SIGINFO"); | warn("sigaction SIGINFO"); | ||||
goto done; | goto done; | ||||
▲ Show 20 Lines • Show All 108 Lines • ▼ Show 20 Lines | x = (u_int)tm->tm_hour << 11 | | ||||
(u_int)tm->tm_min << 5 | | (u_int)tm->tm_min << 5 | | ||||
(u_int)tm->tm_sec >> 1; | (u_int)tm->tm_sec >> 1; | ||||
mk2(de->deMTime, x); | mk2(de->deMTime, x); | ||||
x = (u_int)(tm->tm_year - 80) << 9 | | x = (u_int)(tm->tm_year - 80) << 9 | | ||||
(u_int)(tm->tm_mon + 1) << 5 | | (u_int)(tm->tm_mon + 1) << 5 | | ||||
(u_int)tm->tm_mday; | (u_int)tm->tm_mday; | ||||
mk2(de->deMDate, x); | mk2(de->deMDate, x); | ||||
} | } | ||||
if ((n = write(fd, img, bpb.bpbBytesPerSec)) == -1) { | /* | ||||
warn("%s", fname); | * Issue a write of chunksize once we have collected | ||||
* enough sectors. | |||||
*/ | |||||
img += bpb.bpbBytesPerSec; | |||||
if (img >= physbuf_end) { | |||||
n = write(fd, physbuf, chunksize); | |||||
if (n != chunksize) { | |||||
warnx("%s: can't write sector %u", fname, lsn); | |||||
goto done; | goto done; | ||||
} | } | ||||
if ((unsigned)n != bpb.bpbBytesPerSec) { | img = physbuf; | ||||
} | |||||
} | |||||
/* | |||||
* Write remaining sectors, if the last write didn't end | |||||
* up filling a whole chunk. | |||||
*/ | |||||
if (img != physbuf) { | |||||
ssize_t tailsize = img - physbuf; | |||||
n = write(fd, physbuf, tailsize); | |||||
if (n != tailsize) { | |||||
warnx("%s: can't write sector %u", fname, lsn); | warnx("%s: can't write sector %u", fname, lsn); | ||||
goto done; | goto done; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
rv = 0; | rv = 0; | ||||
done: | done: | ||||
free(img); | free(physbuf); | ||||
if (fd != -1) | if (fd != -1) | ||||
close(fd); | close(fd); | ||||
if (fd1 != -1) | if (fd1 != -1) | ||||
close(fd1); | close(fd1); | ||||
return rv; | return rv; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 260 Lines • Show Last 20 Lines |