Index: newfs_msdos.c =================================================================== --- newfs_msdos.c (revision 186493) +++ newfs_msdos.c (working copy) @@ -56,6 +56,7 @@ #define DOSMAGIC 0xaa55 /* DOS magic number */ #define MINBPS 512 /* minimum bytes per sector */ +#define MAXBPS 4096 /* maximum bytes per sector */ #define MAXSPC 128 /* maximum sectors per cluster */ #define MAXNFT 16 /* maximum number of FATs */ #define DEFBLK 4096 /* default block size */ @@ -69,6 +70,16 @@ #define MAXCLS16 0xfff5 /* maximum FAT16 clusters */ #define MAXCLS32 0xffffff5 /* maximum FAT32 clusters */ +/* + * The size of our in-memory I/O buffer. This is the size of the writes we + * do to the device (except perhaps a few odd sectors at the end). + * + * This must be a multiple of the sector size. Larger is generally faster, + * but some old devices have bugs if you ask them to do more than 128KB + * per I/O. + */ +#define IO_BUFFER_SIZE (128*1024) + #define mincls(fat) ((fat) == 12 ? MINCLS12 : \ (fat) == 16 ? MINCLS16 : \ MINCLS32) @@ -249,7 +260,8 @@ struct bsxbpb *bsxbpb; struct bsx *bsx; struct de *de; - u_int8_t *img; + u_int8_t *io_buffer; /* The buffer for sectors being constructed/written */ + u_int8_t *img; /* Current sector within io_buffer */ const char *fname, *dtype, *bname; ssize_t n; time_t now; @@ -421,7 +433,10 @@ errx(1, "bytes/sector (%u) is not a power of 2", bpb.bps); if (bpb.bps < MINBPS) errx(1, "bytes/sector (%u) is too small; minimum is %u", - bpb.bps, MINBPS); + bpb.bps, MINBPS); + if (bpb.bps > MAXBPS) + errx(1, "bytes/sector (%u) is too large; maximum is %u", + bpb.bps, MAXBPS); if (!(fat = opt_F)) { if (opt_f) fat = 12; @@ -596,8 +611,9 @@ gettimeofday(&tv, NULL); now = tv.tv_sec; tm = localtime(&now); - if (!(img = malloc(bpb.bps))) + if (!(io_buffer = malloc(IO_BUFFER_SIZE))) err(1, NULL); + img = io_buffer; dir = bpb.res + (bpb.spf ? bpb.spf : bpb.bspf) * bpb.nft; for (lsn = 0; lsn < dir + (fat == 32 ? bpb.spc : rds); lsn++) { x = lsn; @@ -697,9 +713,21 @@ (u_int)tm->tm_mday; mk2(de->date, x); } - if ((n = write(fd, img, bpb.bps)) == -1) - err(1, "%s", fname); - if ((unsigned)n != bpb.bps) + img += bpb.bps; + if (img >= (io_buffer + IO_BUFFER_SIZE)) { + /* We filled the I/O buffer, so write it out now */ + if ((n = write(fd, io_buffer, IO_BUFFER_SIZE)) == -1) + err(1, "%s", fname); + if (n != IO_BUFFER_SIZE) + errx(1, "%s: can't write sector %u", fname, lsn); + img = io_buffer; + } + } + if (img != io_buffer) { + /* The I/O buffer was partially full; write it out before exit */ + if ((n = write(fd, io_buffer, img-io_buffer)) == -1) + err(1, "%s", fname); + if (n < 0 || n != (img-io_buffer)) errx(1, "%s: can't write sector %u", fname, lsn); } }