fdformat.c revision a388614e98609b492a4937e6bf8bfdf340c6ba27
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* fdformat program - formats floppy disks, and then adds a label to them
*
* ****Warning, Warning, Warning, Warning*****
* This program runs suid root. This change was made to
* allow it to umount a file system if it's mounted.
*/
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <memory.h>
#include <errno.h>
#include <locale.h>
#include <libintl.h>
#include <volmgt.h>
#include <sys/isa_defs.h>
/* DEFINES */
#if defined(_BIG_ENDIAN)
#define getbyte(A, N) (((unsigned char *)(&(A)))[N])
#elif defined(_LITTLE_ENDIAN)
#else
#endif
#define getlobyte(A) (A & 0xFF)
#define min(a, b) ((a) < (b) ? (a) : (b))
/* FORMAT PATTERNS */
#define PATTERN_1 0x55;
#define PATTERN_2 0xaa;
#define PATTERN_3 0xff;
#define PATTERN_4 0x00;
/* UNINITIALIZED DATA */
/* EXTERN */
extern char *optarg;
extern int optind;
/* for verify buffers */
static char *myname;
static int b_flag = 0; /* install a volume label to the diskette */
static int d_flag = 0; /* format the diskette in dos format */
static int D_flag = 0; /* double (aka low) density flag */
static int e_flag = 0; /* "eject" diskette when done (if supported) */
static int E_flag = 0; /* extended density */
static int f_flag = 0; /* "force" (no confirmation before start) */
static int H_flag = 0; /* high density */
static int m_flag = 0; /* medium density */
static int n_flag = 0; /* format the diskette in NEC-DOS format */
static int q_flag = 0; /* quiet format flag */
static int U_flag = 0; /* automatically unmount if it's mounted */
static int x_flag = 0; /* skip the format, only install SunOS label */
/* or DOS file system */
static int z_flag = 0; /* debugging only, setting partial formatting */
struct bios_param_blk {
char b_mediadescriptor; /* media descriptor byte */
};
/*
* ON-private functions from libvolmgt
*/
char *_media_oldaliases(char *name);
int _dev_mounted(char *path);
int _dev_unmount(char *path);
/*
* local functions
*/
static void usage(char *);
static int verify(int, int, int);
static void write_SunOS_label(int, char *, struct vtoc *);
static int valid_DOS_boot(char *, uchar_t **);
static void write_DOS_label(int, uchar_t *, int, char *, char *,
struct bios_param_blk *, int);
static void write_NEC_DOS_label(int, char *);
static int check_mount();
static void format_diskette(int, char *, struct vtoc *,
struct bios_param_blk *, int *);
static void restore_default_chars(int fd,
struct fd_char save_fdchar,
struct dk_allmap save_allmap);
int
{
int altsize = 0;
int fd;
int i;
char *altbootname = NULL;
char *vollabel = "";
struct bios_param_blk bpb;
int rdirsec;
char *nullstring = "";
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
switch (i) {
case 'B':
d_flag++;
/* check for valid boot file now */
if (!altsize) {
"%s: invalid boot loader\n"), myname);
exit(1);
}
break;
case 'b':
b_flag++;
break;
case 'd':
/* format a MS-DOS diskette */
d_flag++;
break;
case 'D':
case 'L':
case 'l':
/* format a Double density 720KB (or 360KB) disk */
D_flag++;
break;
case 'e':
/* eject diskette when done */
e_flag++;
break;
case 'E':
/* format an 2.88MB Extended density disk */
E_flag++;
break;
case 'f':
/* don't ask for confirmation */
f_flag++;
break;
case 'H':
case 'h':
/* format a High density 1.2MB or 1.44MB disk */
H_flag++;
break;
#if 0
case 'i':
/* interleave factor */
if (interleave <= 0) {
"%s: invalid interleave\n"), myname);
exit(1);
}
break;
#endif
case 'M':
case 'm':
/* format a 3.5" HD disk to 1.2MB */
m_flag++;
break;
case 'x':
/* skip format, just write label */
x_flag++;
break;
case 'q':
/* quiet format */
q_flag++;
break;
case 't':
/* Type of DOS formatting: NEC or MS */
n_flag++;
}
d_flag++;
}
break;
case 'U':
/* umount filesystem if mounted */
U_flag++;
break;
case 'v':
case 'V':
/* verify the diskette after format */
v_flag++;
break;
case 'Z':
/* for debug only, format cyl 0 only */
if (!fd_debug) {
/* NOTREACHED */
}
z_flag++;
break;
default:
usage(" ");
/* NOTREACHED */
}
}
/* NOTREACHED */
}
}
/* NOTREACHED */
}
/* NOTREACHED */
}
/* NOTREACHED */
}
/* NOTREACHED */
}
/* NOTREACHED */
}
/* NOTREACHED */
}
/* NOTREACHED */
}
dev_name = "floppy";
gettext("No such volume (or no media in specified device): %s\n"),
dev_name);
exit(1);
}
}
/*
* This check is required because program runs suid root.
*/
exit(1);
}
/* store callers euid */
/*
* See if the given device name is mounted. If this check isn't done
* before the open, the open will fail. The failed open will not
* indicate that the device is mounted, only that it's busy
*/
if (_dev_mounted(real_name)) {
if (U_flag) {
if (!_dev_unmount(real_name)) {
gettext("%s: umount of %s failed\n"),
exit(1);
}
} else {
gettext("%s: %s is mounted (use -U flag)\n"),
exit(1);
}
}
/* Set to user access permissions to open file */
gettext("%s: \"%s\" is write protected\n"),
exit(1);
}
/* XXX ought to check for "drive not installed", etc. */
exit(1);
}
/* restore effective id */
exit(3);
}
/* See if there are any mounted partitions. */
if (check_mount() != 0) {
exit(3);
}
/*
* The fd_vtoc, bpb, and rdirsec structures will be
* partially filled in by format_diskette().
* This was done so that write_DOS_label(),
* write_SunOS_label(), and write_NEC_DOS_label() could be
* device independent. If a new device needs to be added to
* fdformat, a new format function like format_diskette should
* be added. This function should fill in fd_vtoc, bpb, and
* rdirsec with device dependent information.
*/
if (d_flag)
else if (n_flag)
else
if (e_flag)
/* eject media if possible */
exit(3);
}
return (0);
}
/*
* Inputs: file descriptor for the device and the device name.
* Oututs: the fd_vtoc will be partially filled in with the
* device specific information such as partition
* information and ascillabel. bpb and rdirsec will
* also be partially filled in with device specific information
*/
void
{
int cyl_size;
int i;
int size_of_part, size_of_dev;
int drive_size;
char *nullstring = "";
/* FDRAW ioctl command structures for seeking and formatting */
FDRAW_SEEK, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0
};
0x4D, 0, 2, 0, 0x54, (char)0xA5, 0, 0, 0, 0,
6,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, /* nbytes */
0 /* addr */
};
/*
* restore drive to default geometry and characteristics
* (probably not implemented on sparc)
*/
/* get the default partititon maps */
exit(3);
}
/* Save the original default partition maps */
/* find out the characteristics of the default diskette */
exit(3);
}
/* Save the original characteristics of the default diskette */
/*
* The user may only format the entire diskette.
* formatting partion a or b is not allowed
*/
* DEV_BSIZE;
if (size_of_part != size_of_dev) {
/*CSTYLED*/
gettext("%s: The entire diskette must be formatted. Invalid device name.\n"),
myname);
exit(3);
}
/* find out the geometry of the drive */
exit(3);
}
#ifdef sparc
#endif
drive_size = 5;
else
drive_size = 3;
/*
* set proper density flag in case we're formating to default
* characteristics because no density switch was input
*/
switch (fdchar.fdc_transfer_rate) {
case 1000:
E_flag++;
break;
case 500:
default:
/*
* default to HD even though High density and
*/
H_flag++;
break;
#ifndef sparc
case 250:
D_flag++;
break;
#endif
}
}
if (H_flag) {
transfer_rate = 500;
num_cyl = 80;
sec_size = 512;
if (drive_size == 5) {
"5.25\" floppy cyl 80 alt 0 hd 2 sec 15");
spt = 15;
capacity = "1.2 MB";
} else {
"3.5\" floppy cyl 80 alt 0 hd 2 sec 18");
spt = 18;
capacity = "1.44 MB";
}
gap = 0x54;
} else if (D_flag) {
transfer_rate = 250;
if (drive_size == 5) {
"5.25\" floppy cyl 40 alt 0 hd 2 sec 9");
/*
* formatting a 360KB DD diskette in
* a 1.2MB drive is not a good idea
*/
transfer_rate = 300;
}
num_cyl = 40;
gap = 0x50;
capacity = "360 KB";
} else {
"3.5\" floppy cyl 80 alt 0 hd 2 sec 9");
num_cyl = 80;
gap = 0x54;
capacity = "720 KB";
}
sec_size = 512;
spt = 9;
} else if (m_flag) {
#ifdef sparc
transfer_rate = 500;
#else
/*
* density diskette spun at 300 rpm instead of 360 rpm
*/
transfer_rate = 417;
#endif
"3.5\" floppy cyl 77 alt 0 hd 2 sec 8");
num_cyl = 77;
sec_size = 1024;
spt = 8;
gap = 0x74;
capacity = "1.2 MB";
} else if (E_flag) {
"3.5\" floppy cyl 80 alt 0 hd 2 sec 36");
transfer_rate = 1000;
num_cyl = 80;
sec_size = 512;
spt = 36;
gap = 0x54;
capacity = "2.88 MB";
}
/*
* Medium density diskettes have 1024 byte blocks. The dk_map
* structure in dklabel.h assumes the blocks size is DEVBSIZE (512)
* bytes. The dkl_nblk field is in terms of DEVBSIZE byte blocks
* while the spt variable is in terms of the true block size on
* the diskette.
*/
}
/* initialize the vtoc structure */
/* initialize the bios parameter blockstructure */
} else if (H_flag) {
if (drive_size == 5) {
*rdirsec = 224;
} else {
*rdirsec = 224;
}
} else if (drive_size == 5) {
*rdirsec = 112;
} else if (drive_size == 3) {
*rdirsec = 112;
}
#ifndef sparc
gettext("%s: drive not capable of requested density, "),
myname);
exit(3);
}
#endif
/*
* -- CAUTION --
* The SPARC fd driver is using a non-zero value in
* fdc_medium to indicate the 360 rpm, 77 track,
*
* The x86 fd driver uses fdc_medium as the diameter
* indicator, either 3 or 5. It should not be modified.
*/
#ifdef sparc
#endif
"%s: FDIOSCHAR (density selection) failed, "),
myname);
/* restore the default characteristics */
exit(3);
}
gettext("%s: DKIOCSAPART failed, "),
myname);
/* restore the default characteristics */
exit(3);
}
}
/* restore the default characteristics */
exit(3);
}
}
gettext("%s: can't malloc verify buffer, "),
myname);
/* restore the default characteristics */
exit(4);
}
if (x_flag)
goto skipformat;
if (interleave != 1) {
"Formatting %s, %d cylinders, %d sectors per trk, interleave=%d in %s\n"),
} else {
}
}
if (!f_flag) {
(void) printf(
gettext("Press return to start formatting floppy."));
while (getchar() != '\n')
;
}
/*
* for those systems that support this ioctl, they will
* return whether or not a diskette is in the drive.
*/
if (chgd & FDGC_CURRENT) {
gettext("%s: no diskette in drive %s\n"),
/* restore the default characteristics */
exit(4);
}
if (chgd & FDGC_CURWPROT) {
gettext("%s: \"%s\" is write protected\n"),
/* restore the default characteristics */
exit(1);
}
}
gettext("%s: can't malloc format header buffer, "),
myname);
/* restore the default characteristics */
exit(3);
}
/*
* do the format, a track at a time
*/
/*
* This is not the optimal ioctl to format the floppy.
* The device driver should do do the work,
* instead of this program mucking with a lot
* of low-level, device-dependent code.
*/
gettext("%s: seek to cyl %d failed\n"),
/* restore the default characteristics */
exit(3);
}
/*
* Assume that the fd driver has issued a SENSE_INT
* command to complete the seek operation.
*/
for (i = 1; i <= spt; i++) {
*p++ = cyl;
*p++ = hd;
*p++ = i; /* sector # */
}
/*
* ASSUME the fd driver is going to set drive-select
* bits in the second command byte
*/
"%s: format of cyl %d head %d failed\n"),
/* restore the default characteristics */
exit(3);
}
/*CSTYLED*/
"%s: diskette is write protected\n"),
myname);
/*
* restore the default
* characteristics
*/
exit(3);
}
"%s: format of cyl %d head %d failed\n"),
/* restore the default characteristics */
exit(3);
}
}
/*
* do a quick verify
*/
if (!v_flag) {
gettext("%s: bad seek to format verify, "),
myname);
/* restore the default characteristics */
exit(3);
}
/* write some progress msg */
/* when each cylinder is done. */
if (!q_flag)
(void) printf(".");
} else {
if (!q_flag)
"%s: can't read format data, "), myname);
/* restore the default characteristics */
exit(3);
}
} else
if (!q_flag)
(void) printf(".");
if (!q_flag)
}
if (!q_flag)
(void) printf("\n");
if (v_flag) {
/*
* do a write & read verify of the entire diskette
*/
int val;
/* restore the default characteristics */
}
/* write some progress msg as */
/* each cylinder is done. */
if (!q_flag)
}
if (!q_flag)
(void) printf("\n");
}
myname);
/* restore the default characteristics */
exit(3);
}
}
/*
* Restore the default characteristics of the floppy diskette.
* Fdformat changes the characteristics in the process of formatting.
* If fdformat fails while in the process of doing the format, fdformat
* should clean up after itself and reset the driver back to the original
* state.
*/
static void
restore_default_chars(int fd,
struct fd_char save_fdchar,
struct dk_allmap save_allmap)
{
/*
* When this function is called, fdformat is failing anyways,
* so the errors are not processed.
*/
/*
* Before looking at the diskette's characteristics, format_diskette()
* sets the x86 floppy driver to the default characteristics.
* restore drive to default geometry and
* characteristics. This ioctl isn't implemented on
* sparc.
*/
}
/*
* See if any partitions on the device are mounted. Return 1 if a partition is
* mounted. Return 0 otherwise.
*/
static int
{
int mfd;
struct dk_cinfo dkinfo_tmp;
struct mnttab mnt_record;
char raw_device[MAXPATHLEN];
int found = 0;
exit(3);
}
continue;
}
/*
* Attempt to open the device. If it fails, skip it.
*/
continue;
}
/*
* Must be a character device
*/
continue;
}
/*
* Attempt to read the configuration info on the disk.
*/
continue;
}
/*
* Finished with the opened device
*/
/*
* If it's not the disk we're interested in, it doesn't apply.
*/
continue;
}
/*
* It's a mount on the disk we're checking. If we are
* checking whole disk, then we found trouble. We can
* quit searching.
*/
if (U_flag) {
gettext("%s: umount of %s failed\n"),
found = 1;
}
} else {
gettext("%s: %s is mounted (use -U flag)\n"),
found = 1;
}
}
return (found);
}
static void
{
char *real_name, *alias_name;
}
if (str[0] != ' ')
/*CSTYLED*/
"\n usage: %s [-dDeEfHlLmMqUvx] [-b label] [-B file] [-t dostype] [devname]\n"),
myname);
/*CSTYLED*/
" -b label install \"label\" on media\n"));
" -B file install special boot loader on MS-DOS media\n"));
/*CSTYLED*/
" -d format MS-DOS media\n"));
/*CSTYLED*/
" -D format 720KB (3.5\") or 360KB (5.25\") Double-density diskette\n"));
" -e eject the media when done\n"));
/*CSTYLED*/
/*CSTYLED*/
" -E format 2.88MB (3.5\") Extended-density diskette\n"));
" -f \"force\" - don't wait for confirmation\n"));
/*CSTYLED*/
" -H format 1.44MB (3.5\") or 1.2MB (5.25\") High-density diskette\n"));
/*CSTYLED*/
" -l format 720KB (3.5\") or 360KB (5.25\") Double-density diskette\n"));
/*CSTYLED*/
" -L format 720KB (3.5\") or 360KB (5.25\") Double-density diskette\n"));
" -m format 1.2MB (3.5\") Medium-density diskette\n"));
" -M format 1.2MB (3.5\") Medium-density diskette\n"));
" -q quiet\n"));
/*CSTYLED*/
" -t dos format MS-DOS media (same as -d)\n"));
" -t nec format NEC-DOS media (with -M only)\n"));
/*CSTYLED*/
" -U unmount media if it's mounted\n"));
" -v verify each block of the media\n"));
" -x skip the format, only install SunOS or DOS label\n"));
" devname defaults to '%s'\n"),
exit(1);
}
static int
{
char *nullstring = "";
if (!q_flag)
return (4);
}
if (!q_flag)
if (blk == 0)
gettext("%s: check diskette density, "),
myname);
else
gettext("%s: can't write verify data, "),
myname);
return (4);
}
if (!q_flag)
gettext("%s: bad seek to read verify, "),
myname);
return (4);
}
if (!q_flag)
return (4);
}
if (!q_flag)
myname);
return (4);
}
return (0);
}
/*
* write a SunOS label
* NOTE: this function assumes fd_vtoc has been filled in with the
* device specific information such as partition information
* and the asciilabel
*/
static void
{
char *nullstring = "";
/*
* The label structure is set up for DEV_BSIZE (512 byte) blocks,
* even though a medium density diskette has 1024 byte blocks
* See dklabel.h for more details.
*/
/* let the fd driver finish constructing the label and writing it */
exit(3);
}
}
/*
* MS-DOS Disk layout:
*
* ---------------------
* | Boot sector |
* |-------------------|
* | Reserved area |
* |-------------------|
* | FAT #1 |
* |-------------------|
* | FAT #2 |
* |-------------------|
* | Root directory |
* |-------------------|
* | |
* | File area |
* |___________________|
*/
/*
* The following is a copy of MS-DOS 3.3 boot block.
* It consists of the BIOS parameter block, and a disk
* bootstrap program.
*
* The BIOS parameter block contains the right values
* for the 3.5" high-density 1.44MB floppy format.
*
*/
0xeb, 0x34, 0x90, /* 8086 short jump + displacement + NOP */
'M', 'S', 'D', 'O', 'S', '3', '.', '3', /* OEM name & version */
0, 2, 1, 1, 0, /* Start of BIOS parameter block */
2, 224, 0, 0x40, 0xb, 0xf0, 9, 0,
18, 0, 2, 0, 0, 0, /* End of BIOS parameter block */
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12,
0x0, 0x0, 0x0, 0x0,
0x1, 0x0, 0xfa, 0x33, /* 0x34, start of the bootstrap. */
0xc0, 0x8e, 0xd0, 0xbc, 0x0, 0x7c, 0x16, 0x7,
0xbb, 0x78, 0x0, 0x36, 0xc5, 0x37, 0x1e, 0x56,
0x16, 0x53, 0xbf, 0x2b, 0x7c, 0xb9, 0xb, 0x0,
0xfc, 0xac, 0x26, 0x80, 0x3d, 0x0, 0x74, 0x3,
0x26, 0x8a, 0x5, 0xaa, 0x8a, 0xc4, 0xe2, 0xf1,
0x6, 0x1f, 0x89, 0x47, 0x2, 0xc7, 0x7, 0x2b,
0x7c, 0xfb, 0xcd, 0x13, 0x72, 0x67, 0xa0, 0x10,
0x7c, 0x98, 0xf7, 0x26, 0x16, 0x7c, 0x3, 0x6,
0x1c, 0x7c, 0x3, 0x6, 0xe, 0x7c, 0xa3, 0x3f,
0x7c, 0xa3, 0x37, 0x7c, 0xb8, 0x20, 0x0, 0xf7,
0x26, 0x11, 0x7c, 0x8b, 0x1e, 0xb, 0x7c, 0x3,
0xc3, 0x48, 0xf7, 0xf3, 0x1, 0x6, 0x37, 0x7c,
0xbb, 0x0, 0x5, 0xa1, 0x3f, 0x7c, 0xe8, 0x9f,
0x0, 0xb8, 0x1, 0x2, 0xe8, 0xb3, 0x0, 0x72,
0x19, 0x8b, 0xfb, 0xb9, 0xb, 0x0, 0xbe, 0xd6,
0x7d, 0xf3, 0xa6, 0x75, 0xd, 0x8d, 0x7f, 0x20,
0xbe, 0xe1, 0x7d, 0xb9, 0xb, 0x0, 0xf3, 0xa6,
0x74, 0x18, 0xbe, 0x77, 0x7d, 0xe8, 0x6a, 0x0,
0x32, 0xe4, 0xcd, 0x16, 0x5e, 0x1f, 0x8f, 0x4,
0x8f, 0x44, 0x2, 0xcd, 0x19, 0xbe, 0xc0, 0x7d,
0xeb, 0xeb, 0xa1, 0x1c, 0x5, 0x33, 0xd2, 0xf7,
0x36, 0xb, 0x7c, 0xfe, 0xc0, 0xa2, 0x3c, 0x7c,
0xa1, 0x37, 0x7c, 0xa3, 0x3d, 0x7c, 0xbb, 0x0,
0x7, 0xa1, 0x37, 0x7c, 0xe8, 0x49, 0x0, 0xa1,
0x18, 0x7c, 0x2a, 0x6, 0x3b, 0x7c, 0x40, 0x38,
0x6, 0x3c, 0x7c, 0x73, 0x3, 0xa0, 0x3c, 0x7c,
0x50, 0xe8, 0x4e, 0x0, 0x58, 0x72, 0xc6, 0x28,
0x6, 0x3c, 0x7c, 0x74, 0xc, 0x1, 0x6, 0x37,
0x7c, 0xf7, 0x26, 0xb, 0x7c, 0x3, 0xd8, 0xeb,
0xd0, 0x8a, 0x2e, 0x15, 0x7c, 0x8a, 0x16, 0xfd,
0x7d, 0x8b, 0x1e, 0x3d, 0x7c, 0xea, 0x0, 0x0,
0x70, 0x0, 0xac, 0xa, 0xc0, 0x74, 0x22, 0xb4,
0xe, 0xbb, 0x7, 0x0, 0xcd, 0x10, 0xeb, 0xf2,
0x33, 0xd2, 0xf7, 0x36, 0x18, 0x7c, 0xfe, 0xc2,
0x88, 0x16, 0x3b, 0x7c, 0x33, 0xd2, 0xf7, 0x36,
0x1a, 0x7c, 0x88, 0x16, 0x2a, 0x7c, 0xa3, 0x39,
0x7c, 0xc3, 0xb4, 0x2, 0x8b, 0x16, 0x39, 0x7c,
0xb1, 0x6, 0xd2, 0xe6, 0xa, 0x36, 0x3b, 0x7c,
0x8b, 0xca, 0x86, 0xe9, 0x8a, 0x16, 0xfd, 0x7d,
0x8a, 0x36, 0x2a, 0x7c, 0xcd, 0x13, 0xc3, '\r',
'\n', 'N', 'o', 'n', '-', 'S', 'y', 's',
't', 'e', 'm', ' ', 'd', 'i', 's', 'k',
' ', 'o', 'r', ' ', 'd', 'i', 's', 'k',
' ', 'e', 'r', 'r', 'o', 'r', '\r', '\n',
'R', 'e', 'p', 'l', 'a', 'c', 'e', ' ',
'a', 'n', 'd', ' ', 's', 't', 'r', 'i',
'k', 'e', ' ', 'a', 'n', 'y', ' ', 'k',
'e', 'y', ' ', 'w', 'h', 'e', 'n', ' ',
'r', 'e', 'a', 'd', 'y', '\r', '\n', '\0',
'\r', '\n', 'D', 'i', 's', 'k', ' ', 'B',
'o', 'o', 't', ' ', 'f', 'a', 'i', 'l',
'u', 'r', 'e', '\r', '\n', '\0', 'I', 'O',
' ', ' ', ' ', ' ', ' ', ' ', 'S', 'Y',
'S', 'M', 'S', 'D', 'O', 'S', ' ', ' ',
' ', 'S', 'Y', 'S', '\0', 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0x55, 0xaa
};
static int
{
int bfd;
int boot_size = 0;
int err;
char *nullstring = "";
return (0);
}
return (0);
}
myname);
return (0);
}
/* switch to user to access the boot file */
return (0);
}
/* restore effective id */
return (0);
}
if (!((*bootloader == 0xE9 ||
boot_size = 0;
}
*bootloadp = bootloader;
return (boot_size);
}
static void
{
int i, j;
int bootclen;
char *nullstring = "";
/* use default boot loader routine */
bootlen = 512;
} else
(void) printf
(gettext("%s: using \"%s\" for MS-DOS boot loader\n"),
if (bootlen % 512 > 0)
/* MS-DOS 5.0 supports only 1 reserved sector :-( */
bpb->b_hiddensec[0] = 0;
sizeof (struct bios_param_blk));
exit(3);
}
bootloadr += 512;
bootlen -= 512;
#define BAD_CLUSTER 0xFF7
/*
* pre-allocate any clusters used by boot loader if
* loader will occupy more than 1 sector
*/
if (!(i & 01)) {
} else {
fatptr++;
}
gettext("%s: write of MS-DOS File Allocation Table failed, "),
myname);
exit(3);
}
if (b_flag) {
/* the label can be no more than 11 characters */
for (i = 0; i < j; i++) {
}
for (; i < 11; i++) {
fat_rdir[i] = ' ';
}
/* get the time & day into DOS format */
gettext("%s: write of MS-DOS FAT failed, "),
myname);
exit(3);
}
i = 1;
} else {
i = 0;
}
for (; i < (int)rdirsec; ++i) {
gettext("%s: write of MS-DOS root directory failed, "),
myname);
exit(3);
}
}
/*
* Write the rest of the boot loader if it's longer than one sector.
* The clusters used are marked Bad in the FAT.
* No directory entry exists for this file (so that it cannot be
* deleted).
*/
exit(3);
}
}
static void
{
struct bios_param_blk *bpb;
char fat_rdir[1024];
int i, j, m = 1;
char *nullstring = "";
0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x1, 0x1, 0x0,
0x2, 0xc0, 0x0, 0xd0, 0x4, 0xfe, 0x2, 0x0,
0x8, 0x0, 0x2, 0x0, 0x0, 0x0
};
0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5
};
"%s: write of NEC-DOS boot sector failed, "),
myname);
exit(3);
}
if ((i % (int)fatsec) == 0) {
fat_rdir[3] = 0;
fat_rdir[4] = 0;
fat_rdir[5] = 0;
} else {
fat_rdir[0] = 0;
fat_rdir[1] = 0;
fat_rdir[2] = 0;
fat_rdir[3] = 0;
fat_rdir[4] = 0;
fat_rdir[5] = 0;
}
/*CSTYLED*/
exit(3);
}
}
#ifndef sparc
/* LINTED */
#else
#endif
if (b_flag) {
/* the label can be no more than 11 characters */
for (i = 0; i < j; i++) {
}
for (; i < 11; i++) {
fat_rdir[i] = ' ';
}
/* get the time & day into DOS format */
/*CSTYLED*/
exit(3);
}
i = 1;
} else {
i = 0;
while (m < 1024) {
m = m + 32;
}
}
for (; i < (int)rdirsec; ++i) {
/*CSTYLED*/
exit(3);
}
}
}