10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53925Sartem * Common Development and Distribution License (the "License").
63925Sartem * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*9889SLarry.Liu@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23452Sjkennedy * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <ctype.h>
280Sstevel@tonic-gate #include <unistd.h>
290Sstevel@tonic-gate #include <stdio.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <string.h>
320Sstevel@tonic-gate #include <errno.h>
330Sstevel@tonic-gate #include <fcntl.h>
340Sstevel@tonic-gate #include <libintl.h>
350Sstevel@tonic-gate #include <locale.h>
360Sstevel@tonic-gate #include <sys/fdio.h>
370Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
380Sstevel@tonic-gate #include <sys/dkio.h>
390Sstevel@tonic-gate #include <sys/sysmacros.h>
400Sstevel@tonic-gate #include "mkfs_pcfs.h"
410Sstevel@tonic-gate #include <sys/fs/pc_fs.h>
420Sstevel@tonic-gate #include <sys/fs/pc_dir.h>
430Sstevel@tonic-gate #include <sys/fs/pc_label.h>
440Sstevel@tonic-gate #include <macros.h>
450Sstevel@tonic-gate
460Sstevel@tonic-gate /*
470Sstevel@tonic-gate * mkfs (for pcfs)
480Sstevel@tonic-gate *
490Sstevel@tonic-gate * Install a boot block, FAT, and (if desired) the first resident
500Sstevel@tonic-gate * of the new fs.
510Sstevel@tonic-gate *
520Sstevel@tonic-gate * XXX -- floppy opens need O_NDELAY?
530Sstevel@tonic-gate */
540Sstevel@tonic-gate #define DEFAULT_LABEL "NONAME"
550Sstevel@tonic-gate
560Sstevel@tonic-gate static char *BootBlkFn = NULL;
570Sstevel@tonic-gate static char *DiskName = NULL;
580Sstevel@tonic-gate static char *FirstFn = NULL;
590Sstevel@tonic-gate static char *Label = NULL;
600Sstevel@tonic-gate static char Firstfileattr = 0x20;
610Sstevel@tonic-gate static int Outputtofile = 0;
620Sstevel@tonic-gate static int SunBPBfields = 0;
630Sstevel@tonic-gate static int GetFsParams = 0;
640Sstevel@tonic-gate static int Fatentsize = 0;
650Sstevel@tonic-gate static int Imagesize = 3;
660Sstevel@tonic-gate static int Notreally = 0;
670Sstevel@tonic-gate static int Verbose = 0;
680Sstevel@tonic-gate static int MakeFAT32 = 0;
690Sstevel@tonic-gate
700Sstevel@tonic-gate /*
710Sstevel@tonic-gate * If there is an FDISK entry for the device where we're about to
720Sstevel@tonic-gate * make the file system, we ought to make a file system that has the
730Sstevel@tonic-gate * same size FAT as the FDISK table claims. We track the size FDISK
740Sstevel@tonic-gate * thinks in this variable.
750Sstevel@tonic-gate */
760Sstevel@tonic-gate static int FdiskFATsize = 0;
770Sstevel@tonic-gate
780Sstevel@tonic-gate static int GetSize = 1; /* Unless we're given as arg, must look it up */
790Sstevel@tonic-gate static ulong_t TotSize; /* Total size of FS in # of sectors */
800Sstevel@tonic-gate static int GetSPC = 1; /* Unless we're given as arg, must calculate */
810Sstevel@tonic-gate static ulong_t SecPerClust; /* # of sectors per cluster */
820Sstevel@tonic-gate static int GetOffset = 1; /* Unless we're given as arg, must look it up */
830Sstevel@tonic-gate static ulong_t RelOffset; /* Relative start sector (hidden sectors) */
840Sstevel@tonic-gate static int GetSPT = 1; /* Unless we're given as arg, must look it up */
850Sstevel@tonic-gate static ushort_t SecPerTrk; /* # of sectors per track */
860Sstevel@tonic-gate static int GetTPC = 1; /* Unless we're given as arg, must look it up */
870Sstevel@tonic-gate static ushort_t TrkPerCyl; /* # of tracks per cylinder */
880Sstevel@tonic-gate static int GetResrvd = 1; /* Unless we're given as arg, must calculate */
89452Sjkennedy static int Resrvd; /* Number of reserved sectors */
900Sstevel@tonic-gate static int GetBPF = 1; /* Unless we're given as arg, must calculate */
910Sstevel@tonic-gate static int BitsPerFAT; /* Total size of FS in # of sectors */
920Sstevel@tonic-gate
930Sstevel@tonic-gate static ulong_t TotalClusters; /* Computed total number of clusters */
940Sstevel@tonic-gate
950Sstevel@tonic-gate /*
960Sstevel@tonic-gate * Unless we are told otherwise, we should use fdisk table for non-diskettes.
970Sstevel@tonic-gate */
980Sstevel@tonic-gate static int DontUseFdisk = 0;
990Sstevel@tonic-gate
1000Sstevel@tonic-gate /*
1010Sstevel@tonic-gate * Function prototypes
1020Sstevel@tonic-gate */
1030Sstevel@tonic-gate #ifndef i386
1040Sstevel@tonic-gate static void swap_pack_grabsebpb(bpb_t *wbpb, struct _boot_sector *bsp);
1050Sstevel@tonic-gate static void swap_pack_bpb32cpy(struct _boot_sector32 *bsp, bpb_t *wbpb);
1060Sstevel@tonic-gate static void swap_pack_sebpbcpy(struct _boot_sector *bsp, bpb_t *wbpb);
1070Sstevel@tonic-gate static void swap_pack_grabbpb(bpb_t *wbpb, struct _boot_sector *bsp);
1080Sstevel@tonic-gate static void swap_pack_bpbcpy(struct _boot_sector *bsp, bpb_t *wbpb);
1090Sstevel@tonic-gate #endif
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate static uchar_t *build_rootdir(bpb_t *wbpb, char *ffn, int fffd,
1120Sstevel@tonic-gate ulong_t ffsize, pc_cluster32_t ffstart, ulong_t *rdirsize);
1135121Sfrankho static uchar_t *build_fat(bpb_t *wbpb, struct fat_od_fsi *fsinfop,
1140Sstevel@tonic-gate ulong_t bootblksize, ulong_t *fatsize, char *ffn, int *fffd,
1150Sstevel@tonic-gate ulong_t *ffsize, pc_cluster32_t *ffstartclust);
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate static char *stat_actual_disk(char *diskname, struct stat *info, char **suffix);
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate static void compare_existing_with_computed(int fd, char *suffix,
1200Sstevel@tonic-gate bpb_t *wbpb, int *prtsize, int *prtspc, int *prtbpf, int *prtnsect,
1210Sstevel@tonic-gate int *prtntrk, int *prtfdisk, int *prthidden, int *prtrsrvd,
1220Sstevel@tonic-gate int *dashos);
1230Sstevel@tonic-gate static void print_reproducing_command(int fd, char *actualdisk, char *suffix,
1240Sstevel@tonic-gate bpb_t *wbpb);
1250Sstevel@tonic-gate static void compute_file_area_size(bpb_t *wbpb);
1260Sstevel@tonic-gate static void write_fat32_bootstuff(int fd, boot_sector_t *bsp,
1275121Sfrankho struct fat_od_fsi *fsinfop, off64_t seekto);
1280Sstevel@tonic-gate static void sanity_check_options(int argc, int optind);
1290Sstevel@tonic-gate static void compute_cluster_size(bpb_t *wbpb);
1300Sstevel@tonic-gate static void find_fixed_details(int fd, bpb_t *wbpb);
1310Sstevel@tonic-gate static void dirent_fname_fill(struct pcdir *dep, char *fn);
1320Sstevel@tonic-gate static void floppy_bpb_fillin(bpb_t *wbpb,
1330Sstevel@tonic-gate int diam, int hds, int spt);
1340Sstevel@tonic-gate static void read_existing_bpb(int fd, bpb_t *wbpb);
1350Sstevel@tonic-gate static void warn_funky_fatsize(void);
1360Sstevel@tonic-gate static void warn_funky_floppy(void);
1370Sstevel@tonic-gate static void dirent_time_fill(struct pcdir *dep);
1380Sstevel@tonic-gate static void parse_suboptions(char *optsstr);
1390Sstevel@tonic-gate static void header_for_dump(void);
1400Sstevel@tonic-gate static void write_bootsects(int fd, boot_sector_t *bsp, bpb_t *wbpb,
1415121Sfrankho struct fat_od_fsi *fsinfop, off64_t seekto);
1420Sstevel@tonic-gate static void fill_bpb_sizes(bpb_t *wbpb, struct ipart part[],
1430Sstevel@tonic-gate int partno, off64_t offset);
1440Sstevel@tonic-gate static void set_fat_string(bpb_t *wbpb, int fatsize);
1450Sstevel@tonic-gate static void partn_lecture(char *dn);
1460Sstevel@tonic-gate static void store_16_bits(uchar_t **bp, uint32_t v);
1470Sstevel@tonic-gate static void store_32_bits(uchar_t **bp, uint32_t v);
1480Sstevel@tonic-gate static void lookup_floppy(struct fd_char *fdchar, bpb_t *wbpb);
1490Sstevel@tonic-gate static void label_volume(char *lbl, bpb_t *wbpb);
1500Sstevel@tonic-gate static void mark_cluster(uchar_t *fatp, pc_cluster32_t clustnum,
1510Sstevel@tonic-gate uint32_t value);
1520Sstevel@tonic-gate static void missing_arg(char *option);
1530Sstevel@tonic-gate static void dashm_bail(int fd);
1540Sstevel@tonic-gate static void dump_bytes(uchar_t *, int);
1550Sstevel@tonic-gate static void write_rest(bpb_t *wbpb, char *efn,
1560Sstevel@tonic-gate int dfd, int sfd, int remaining);
1570Sstevel@tonic-gate static void write_fat(int fd, off64_t seekto, char *fn, char *lbl,
1580Sstevel@tonic-gate char *ffn, bpb_t *wbpb);
1590Sstevel@tonic-gate static void bad_arg(char *option);
1600Sstevel@tonic-gate static void usage(void);
1610Sstevel@tonic-gate
1620Sstevel@tonic-gate static int prepare_image_file(char *fn, bpb_t *wbpb);
1630Sstevel@tonic-gate static int verify_bootblkfile(char *fn, boot_sector_t *bs,
1640Sstevel@tonic-gate ulong_t *blkfilesize);
1650Sstevel@tonic-gate static int open_and_examine(char *dn, bpb_t *wbpb);
1660Sstevel@tonic-gate static int verify_firstfile(char *fn, ulong_t *filesize);
1670Sstevel@tonic-gate static int lookup_FAT_size(uchar_t partid);
1680Sstevel@tonic-gate static int powerofx_le_y(int x, int y, int value);
1690Sstevel@tonic-gate static int open_and_seek(char *dn, bpb_t *wbpb, off64_t *seekto);
1700Sstevel@tonic-gate static int warn_mismatch(char *desc, char *src, int expect, int assigned);
1710Sstevel@tonic-gate static int copy_bootblk(char *fn, boot_sector_t *bootsect,
1720Sstevel@tonic-gate ulong_t *bootblksize);
1730Sstevel@tonic-gate static int parse_drvnum(char *pn);
1740Sstevel@tonic-gate static int seek_nofdisk(int fd, bpb_t *wbpb, off64_t *seekto);
1750Sstevel@tonic-gate static int ask_nicely(char *special);
1760Sstevel@tonic-gate static int seek_partn(int fd, char *pn, bpb_t *wbpb, off64_t *seekto);
1770Sstevel@tonic-gate static int yes(void);
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate /*
1800Sstevel@tonic-gate * usage
1810Sstevel@tonic-gate *
1820Sstevel@tonic-gate * Display usage message and exit.
1830Sstevel@tonic-gate */
1840Sstevel@tonic-gate static
1850Sstevel@tonic-gate void
usage(void)1860Sstevel@tonic-gate usage(void)
1870Sstevel@tonic-gate {
1880Sstevel@tonic-gate (void) fprintf(stderr,
1890Sstevel@tonic-gate gettext("pcfs usage: mkfs [-F FSType] [-V] [-m] "
1905121Sfrankho "[-o specific_options] special\n"));
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate (void) fprintf(stderr,
1930Sstevel@tonic-gate gettext(" -V: print this command line and return\n"
1945121Sfrankho " -m: dump command line used to create a FAT on this media\n"
1955121Sfrankho "\t(other options are ignored if this option is chosen).\n"
1965121Sfrankho " -o: pcfs_specific_options:\n"
1975121Sfrankho "\t'pcfs_specific_options' is a comma separated list\n"
1985121Sfrankho "\tincluding one or more of the following options:\n"
1995121Sfrankho "\t N,v,r,h,s,b=label,B=filename,i=filename,\n"
2005121Sfrankho "\t spc=n,fat=n,nsect=n,ntrack=n,nofdisk,size=n,\n"
2015121Sfrankho "\t reserve=n,hidden=n\n\n"));
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate (void) fprintf(stderr,
2040Sstevel@tonic-gate gettext("'Special' should specify a raw diskette "
2055121Sfrankho "or raw fixed disk device. \"Fixed\"\n"
2065121Sfrankho "disks (which include high-capacity removable "
2075121Sfrankho "media such as Zip disks)\n"
2085121Sfrankho "may be further qualified with a logical "
2095121Sfrankho "drive specifier.\n"
2105121Sfrankho "Examples are: /dev/rdiskette and "
2115121Sfrankho "/dev/rdsk/c0t0d0p0:c\n"));
2120Sstevel@tonic-gate exit(1);
2130Sstevel@tonic-gate }
2140Sstevel@tonic-gate
2150Sstevel@tonic-gate static
2160Sstevel@tonic-gate int
yes(void)2170Sstevel@tonic-gate yes(void)
2180Sstevel@tonic-gate {
2190Sstevel@tonic-gate char *affirmative = gettext("yY");
2200Sstevel@tonic-gate char *a = affirmative;
2210Sstevel@tonic-gate int b;
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate b = getchar();
2240Sstevel@tonic-gate while (b == '\n' && b != '\0' && b != EOF)
2250Sstevel@tonic-gate b = getchar();
2260Sstevel@tonic-gate while (*a) {
2270Sstevel@tonic-gate if (b == (int)*a)
2280Sstevel@tonic-gate break;
2290Sstevel@tonic-gate a++;
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate return (*a);
2320Sstevel@tonic-gate }
2330Sstevel@tonic-gate
2340Sstevel@tonic-gate /*
2350Sstevel@tonic-gate * powerofx_le_y
2360Sstevel@tonic-gate * args of x,y, and value to be checked
2370Sstevel@tonic-gate * returns 1 if x**n == value and n >= 0 and value <= y
2380Sstevel@tonic-gate * returns 0 otherwise
2390Sstevel@tonic-gate */
2400Sstevel@tonic-gate static
2410Sstevel@tonic-gate int
powerofx_le_y(int x,int y,int value)2420Sstevel@tonic-gate powerofx_le_y(int x, int y, int value)
2430Sstevel@tonic-gate {
2440Sstevel@tonic-gate int ispower = 0;
2450Sstevel@tonic-gate int pow = 1;
2460Sstevel@tonic-gate
2470Sstevel@tonic-gate if (value < 1 || value > y)
2480Sstevel@tonic-gate return (ispower);
2490Sstevel@tonic-gate
2500Sstevel@tonic-gate do {
2510Sstevel@tonic-gate if (pow == value) {
2520Sstevel@tonic-gate ispower = 1;
2530Sstevel@tonic-gate break;
2540Sstevel@tonic-gate }
2550Sstevel@tonic-gate pow *= x;
2560Sstevel@tonic-gate } while (pow <= y);
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate return (ispower);
2590Sstevel@tonic-gate }
2600Sstevel@tonic-gate
2610Sstevel@tonic-gate static
2620Sstevel@tonic-gate int
ask_nicely(char * special)2630Sstevel@tonic-gate ask_nicely(char *special)
2640Sstevel@tonic-gate {
2650Sstevel@tonic-gate /*
2660Sstevel@tonic-gate * 4228473 - No way to non-interactively make a pcfs filesystem
2670Sstevel@tonic-gate *
2680Sstevel@tonic-gate * If we don't have an input TTY, or we aren't really doing
2690Sstevel@tonic-gate * anything, then don't ask questions. Assume a yes answer
2700Sstevel@tonic-gate * to any questions we would ask.
2710Sstevel@tonic-gate */
2720Sstevel@tonic-gate if (Notreally || !isatty(fileno(stdin)))
2730Sstevel@tonic-gate return (1);
2740Sstevel@tonic-gate
2750Sstevel@tonic-gate (void) printf(
2760Sstevel@tonic-gate gettext("Construct a new FAT file system on %s: (y/n)? "), special);
2770Sstevel@tonic-gate (void) fflush(stdout);
2780Sstevel@tonic-gate return (yes());
2790Sstevel@tonic-gate }
2800Sstevel@tonic-gate
2810Sstevel@tonic-gate /*
2820Sstevel@tonic-gate * store_16_bits
2830Sstevel@tonic-gate * Save the lower 16 bits of a 32 bit value (v) into the provided
2840Sstevel@tonic-gate * buffer (pointed at by *bp), and increment the buffer pointer
2850Sstevel@tonic-gate * as well. This way the routine can be called multiple times in
2860Sstevel@tonic-gate * succession to fill buffers. The value is stored in little-endian
2870Sstevel@tonic-gate * order.
2880Sstevel@tonic-gate */
2890Sstevel@tonic-gate static
2900Sstevel@tonic-gate void
store_16_bits(uchar_t ** bp,uint32_t v)2910Sstevel@tonic-gate store_16_bits(uchar_t **bp, uint32_t v)
2920Sstevel@tonic-gate {
2930Sstevel@tonic-gate uchar_t *l = *bp;
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate *l++ = v & 0xff;
2960Sstevel@tonic-gate *l = (v >> 8) & 0xff;
2970Sstevel@tonic-gate *bp += 2;
2980Sstevel@tonic-gate }
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate /*
3010Sstevel@tonic-gate * store_32_bits
3020Sstevel@tonic-gate * Save the 32 bit value (v) into the provided buffer (pointed
3030Sstevel@tonic-gate * at by *bp), and increment the buffer pointer as well. This way
3040Sstevel@tonic-gate * the routine can be called multiple times in succession to fill
3050Sstevel@tonic-gate * buffers. The value is stored in little-endian order.
3060Sstevel@tonic-gate */
3070Sstevel@tonic-gate static
3080Sstevel@tonic-gate void
store_32_bits(uchar_t ** bp,uint32_t v)3090Sstevel@tonic-gate store_32_bits(uchar_t **bp, uint32_t v)
3100Sstevel@tonic-gate {
3110Sstevel@tonic-gate uchar_t *l = *bp;
3120Sstevel@tonic-gate int b;
3130Sstevel@tonic-gate
3140Sstevel@tonic-gate for (b = 0; b < 4; b++) {
3150Sstevel@tonic-gate *l++ = v & 0xff;
3160Sstevel@tonic-gate v = v >> 8;
3170Sstevel@tonic-gate }
3180Sstevel@tonic-gate *bp += 4;
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate
3210Sstevel@tonic-gate /*
3220Sstevel@tonic-gate * dump_bytes -- display bytes as hex numbers.
3230Sstevel@tonic-gate * b is the pointer to the byte buffer
3240Sstevel@tonic-gate * n is the number of bytes in the buffer
3250Sstevel@tonic-gate */
3260Sstevel@tonic-gate /* Note: BPL = bytes to display per line */
3270Sstevel@tonic-gate #define BPL 16
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate static
3300Sstevel@tonic-gate void
dump_bytes(uchar_t * b,int n)3310Sstevel@tonic-gate dump_bytes(uchar_t *b, int n)
3320Sstevel@tonic-gate {
3330Sstevel@tonic-gate int cd = n;
3340Sstevel@tonic-gate int cu = 0;
3350Sstevel@tonic-gate int o = 0;
3360Sstevel@tonic-gate int bl;
3370Sstevel@tonic-gate int ac;
3380Sstevel@tonic-gate
3390Sstevel@tonic-gate /* Display offset, 16 bytes per line, and printable ascii version */
3400Sstevel@tonic-gate while (cd > 0) {
3410Sstevel@tonic-gate ac = 0;
3420Sstevel@tonic-gate (void) printf("\n%06x: ", o);
3430Sstevel@tonic-gate for (bl = 0; bl < BPL; bl++) {
3440Sstevel@tonic-gate if (cu+bl < n) {
3450Sstevel@tonic-gate (void) printf("%02x ", (b[cu+bl] & 0xff));
3460Sstevel@tonic-gate ac++;
3470Sstevel@tonic-gate }
3480Sstevel@tonic-gate else
3490Sstevel@tonic-gate (void) printf(" ");
3500Sstevel@tonic-gate }
3510Sstevel@tonic-gate for (bl = 0; bl < BPL; bl++) {
3520Sstevel@tonic-gate if ((cu+bl < n) &&
3535121Sfrankho ((b[cu+bl] >= ' ') && (b[cu+bl] <= '~')))
3545121Sfrankho (void) printf("%c", b[cu+bl]);
3550Sstevel@tonic-gate else
3560Sstevel@tonic-gate (void) printf(".");
3570Sstevel@tonic-gate }
3580Sstevel@tonic-gate cu += ac; o += ac; cd -= ac;
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate (void) printf("\n\n");
3610Sstevel@tonic-gate }
3620Sstevel@tonic-gate
3630Sstevel@tonic-gate /*
3640Sstevel@tonic-gate * header_for_dump -- display simple header over what will be output.
3650Sstevel@tonic-gate */
3660Sstevel@tonic-gate static
3670Sstevel@tonic-gate void
header_for_dump(void)3680Sstevel@tonic-gate header_for_dump(void)
3690Sstevel@tonic-gate {
3700Sstevel@tonic-gate int bl;
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate (void) printf("\n ");
3730Sstevel@tonic-gate for (bl = 0; bl < BPL; bl++)
3740Sstevel@tonic-gate (void) printf("%02x ", bl);
3750Sstevel@tonic-gate (void) printf("\n ");
3760Sstevel@tonic-gate bl = 3*BPL;
3770Sstevel@tonic-gate while (bl-- > 0)
3780Sstevel@tonic-gate (void) printf("-");
3790Sstevel@tonic-gate }
3800Sstevel@tonic-gate
3810Sstevel@tonic-gate /*
3820Sstevel@tonic-gate * parse_drvnum
3830Sstevel@tonic-gate * Convert a partition name into a drive number.
3840Sstevel@tonic-gate */
3850Sstevel@tonic-gate static
3860Sstevel@tonic-gate int
parse_drvnum(char * pn)3870Sstevel@tonic-gate parse_drvnum(char *pn)
3880Sstevel@tonic-gate {
3890Sstevel@tonic-gate int drvnum;
3900Sstevel@tonic-gate
3910Sstevel@tonic-gate /*
3920Sstevel@tonic-gate * Determine logical drive to seek after.
3930Sstevel@tonic-gate */
3940Sstevel@tonic-gate if (strlen(pn) == 1 && *pn >= 'c' && *pn <= 'z') {
3950Sstevel@tonic-gate drvnum = *pn - 'c' + 1;
3960Sstevel@tonic-gate } else if (*pn >= '0' && *pn <= '9') {
3970Sstevel@tonic-gate char *d;
3980Sstevel@tonic-gate int v, m, c;
3990Sstevel@tonic-gate
4000Sstevel@tonic-gate v = 0;
4010Sstevel@tonic-gate d = pn;
4020Sstevel@tonic-gate while (*d && *d >= '0' && *d <= '9') {
4030Sstevel@tonic-gate c = strlen(d);
4040Sstevel@tonic-gate m = 1;
4050Sstevel@tonic-gate while (--c)
4060Sstevel@tonic-gate m *= 10;
4070Sstevel@tonic-gate v += m * (*d - '0');
4080Sstevel@tonic-gate d++;
4090Sstevel@tonic-gate }
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate if (*d || v > 24) {
4120Sstevel@tonic-gate (void) fprintf(stderr,
4130Sstevel@tonic-gate gettext("%s: bogus logical drive specification.\n"),
4140Sstevel@tonic-gate pn);
4150Sstevel@tonic-gate return (-1);
4160Sstevel@tonic-gate }
4170Sstevel@tonic-gate drvnum = v;
4180Sstevel@tonic-gate } else if (strcmp(pn, "boot") == 0) {
4190Sstevel@tonic-gate drvnum = 99;
4200Sstevel@tonic-gate } else {
4210Sstevel@tonic-gate (void) fprintf(stderr,
4220Sstevel@tonic-gate gettext("%s: bogus logical drive specification.\n"), pn);
4230Sstevel@tonic-gate return (-1);
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate return (drvnum);
4270Sstevel@tonic-gate }
4280Sstevel@tonic-gate
4290Sstevel@tonic-gate /*
4300Sstevel@tonic-gate * Define some special logical drives we use.
4310Sstevel@tonic-gate */
4320Sstevel@tonic-gate #define BOOT_PARTITION_DRIVE 99
4330Sstevel@tonic-gate #define PRIMARY_DOS_DRIVE 1
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate /*
4360Sstevel@tonic-gate * isDosDrive()
4370Sstevel@tonic-gate * Boolean function. Give it the systid field for an fdisk partition
4380Sstevel@tonic-gate * and it decides if that's a systid that describes a DOS drive. We
4390Sstevel@tonic-gate * use systid values defined in sys/dktp/fdisk.h.
4400Sstevel@tonic-gate */
4410Sstevel@tonic-gate static int
isDosDrive(uchar_t checkMe)4420Sstevel@tonic-gate isDosDrive(uchar_t checkMe)
4430Sstevel@tonic-gate {
4440Sstevel@tonic-gate return ((checkMe == DOSOS12) || (checkMe == DOSOS16) ||
4450Sstevel@tonic-gate (checkMe == DOSHUGE) || (checkMe == FDISK_WINDOWS) ||
4460Sstevel@tonic-gate (checkMe == FDISK_EXT_WIN) || (checkMe == FDISK_FAT95) ||
4470Sstevel@tonic-gate (checkMe == DIAGPART));
4480Sstevel@tonic-gate }
4490Sstevel@tonic-gate
4500Sstevel@tonic-gate /*
4510Sstevel@tonic-gate * isDosExtended()
4520Sstevel@tonic-gate * Boolean function. Give it the systid field for an fdisk partition
4530Sstevel@tonic-gate * and it decides if that's a systid that describes an extended DOS
4540Sstevel@tonic-gate * partition.
4550Sstevel@tonic-gate */
4560Sstevel@tonic-gate static int
isDosExtended(uchar_t checkMe)4570Sstevel@tonic-gate isDosExtended(uchar_t checkMe)
4580Sstevel@tonic-gate {
4590Sstevel@tonic-gate return ((checkMe == EXTDOS) || (checkMe == FDISK_EXTLBA));
4600Sstevel@tonic-gate }
4610Sstevel@tonic-gate
4620Sstevel@tonic-gate /*
4630Sstevel@tonic-gate * isBootPart()
4640Sstevel@tonic-gate * Boolean function. Give it the systid field for an fdisk partition
4650Sstevel@tonic-gate * and it decides if that's a systid that describes a Solaris boot
4660Sstevel@tonic-gate * partition.
4670Sstevel@tonic-gate */
4680Sstevel@tonic-gate static int
isBootPart(uchar_t checkMe)4690Sstevel@tonic-gate isBootPart(uchar_t checkMe)
4700Sstevel@tonic-gate {
4710Sstevel@tonic-gate return (checkMe == X86BOOT);
4720Sstevel@tonic-gate }
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate static
4750Sstevel@tonic-gate int
warn_mismatch(char * desc,char * src,int expect,int assigned)4760Sstevel@tonic-gate warn_mismatch(char *desc, char *src, int expect, int assigned)
4770Sstevel@tonic-gate {
4780Sstevel@tonic-gate if (expect == assigned)
4790Sstevel@tonic-gate return (assigned);
4800Sstevel@tonic-gate
4810Sstevel@tonic-gate /*
4820Sstevel@tonic-gate * 4228473 - No way to non-interactively make a pcfs filesystem
4830Sstevel@tonic-gate *
4840Sstevel@tonic-gate * If we don't have an input TTY, or we aren't really doing
4850Sstevel@tonic-gate * anything, then don't ask questions. Assume a yes answer
4860Sstevel@tonic-gate * to any questions we would ask.
4870Sstevel@tonic-gate */
4880Sstevel@tonic-gate if (Notreally || !isatty(fileno(stdin))) {
4890Sstevel@tonic-gate (void) printf(gettext("WARNING: User supplied %s is %d,"
4905121Sfrankho "\nbut value obtained from the %s is %d.\n"
4915121Sfrankho "Using user supplied value.\n"),
4925121Sfrankho desc, assigned, src, expect);
4930Sstevel@tonic-gate return (assigned);
4940Sstevel@tonic-gate }
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate (void) printf(gettext("User supplied %s is %d."
4975121Sfrankho "\nThe value obtained from the %s is %d.\n"),
4985121Sfrankho desc, assigned, src, expect);
4990Sstevel@tonic-gate
5000Sstevel@tonic-gate (void) printf(
5010Sstevel@tonic-gate gettext("Continue with value given on command line (y/n)? "));
5020Sstevel@tonic-gate (void) fflush(stdout);
5030Sstevel@tonic-gate if (yes())
5040Sstevel@tonic-gate return (assigned);
5050Sstevel@tonic-gate else
5060Sstevel@tonic-gate exit(2);
5070Sstevel@tonic-gate /*NOTREACHED*/
5080Sstevel@tonic-gate }
5090Sstevel@tonic-gate
5100Sstevel@tonic-gate static
5110Sstevel@tonic-gate void
fill_fat32_bpb(bpb_t * wbpb)5120Sstevel@tonic-gate fill_fat32_bpb(bpb_t *wbpb)
5130Sstevel@tonic-gate {
5140Sstevel@tonic-gate /*
5150Sstevel@tonic-gate * ExtFlags means (according to MSDN BPB (FAT32) document)
5160Sstevel@tonic-gate *
5170Sstevel@tonic-gate * Bit 8 indicates info written to the active FAT is written
5180Sstevel@tonic-gate * to all copies of the FAT. (I think they mean bit 7, with
5190Sstevel@tonic-gate * numbering starting at 0)
5200Sstevel@tonic-gate *
5210Sstevel@tonic-gate * Lowest 4 bits of field are the 0 based FAT number of the
5220Sstevel@tonic-gate * Active FAT. (only meaningful if bit 8 is set)
5230Sstevel@tonic-gate *
5240Sstevel@tonic-gate * Field contains combination of these values:
5250Sstevel@tonic-gate *
5260Sstevel@tonic-gate * VALUE DESCRIPTION
5270Sstevel@tonic-gate * BGBPB_F_ActiveFATMsk Mask for low four bits
5280Sstevel@tonic-gate * (0x000F)
5290Sstevel@tonic-gate * BGBPB_F_NoFATMirror If set FAT mirroring disabled.
5300Sstevel@tonic-gate * (0x0080) If clear, FAT mirroring enabled.
5310Sstevel@tonic-gate *
5320Sstevel@tonic-gate * We set the value based on what I've seen on all the FAT32 drives
5330Sstevel@tonic-gate * I've seen created by Windows.
5340Sstevel@tonic-gate *
5350Sstevel@tonic-gate */
5360Sstevel@tonic-gate wbpb->bpb32.ext_flags = 0x0;
5370Sstevel@tonic-gate /*
5380Sstevel@tonic-gate * No real explanation of the fs_vers file in the BPB doc. The
5390Sstevel@tonic-gate * high byte is supposed to be the major version and the low the
5400Sstevel@tonic-gate * minor version. Again I set according to what I've seen on Windows.
5410Sstevel@tonic-gate */
5420Sstevel@tonic-gate wbpb->bpb32.fs_vers_lo = '\0';
5430Sstevel@tonic-gate wbpb->bpb32.fs_vers_hi = '\0';
5440Sstevel@tonic-gate /*
5450Sstevel@tonic-gate * The convention appears to be to place the fs info sector
5460Sstevel@tonic-gate * immediately after the boot sector, and that the backup boot
5470Sstevel@tonic-gate * sector should be at sector 6. (based on what I see with
5480Sstevel@tonic-gate * Windows)
5490Sstevel@tonic-gate */
5500Sstevel@tonic-gate wbpb->bpb32.fsinfosec = 1;
5510Sstevel@tonic-gate wbpb->bpb32.backupboot = 6;
5520Sstevel@tonic-gate }
5530Sstevel@tonic-gate
5540Sstevel@tonic-gate static
5550Sstevel@tonic-gate void
fill_bpb_sizes(bpb_t * wbpb,struct ipart part[],int partno,off64_t offset)5560Sstevel@tonic-gate fill_bpb_sizes(bpb_t *wbpb, struct ipart part[], int partno, off64_t offset)
5570Sstevel@tonic-gate {
5580Sstevel@tonic-gate ulong_t usesize;
5590Sstevel@tonic-gate
5600Sstevel@tonic-gate if (GetFsParams || GetSize) {
5610Sstevel@tonic-gate usesize = ltohi(part[partno].numsect);
5620Sstevel@tonic-gate if (Verbose) {
5635121Sfrankho (void) printf(
5645121Sfrankho gettext("Partition size (from FDISK table) "
5650Sstevel@tonic-gate "= %d sectors.\n"), usesize);
5660Sstevel@tonic-gate }
5670Sstevel@tonic-gate } else {
5680Sstevel@tonic-gate usesize = warn_mismatch(
5690Sstevel@tonic-gate gettext("length of partition (in sectors)"),
5700Sstevel@tonic-gate gettext("FDISK table"),
5710Sstevel@tonic-gate ltohi(part[partno].numsect), TotSize);
5720Sstevel@tonic-gate }
5730Sstevel@tonic-gate
5740Sstevel@tonic-gate if (GetFsParams) {
5750Sstevel@tonic-gate TotSize = usesize;
5760Sstevel@tonic-gate } else {
5770Sstevel@tonic-gate if (usesize > 0xffff)
5780Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = 0;
5790Sstevel@tonic-gate else
5800Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = usesize;
5810Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = usesize;
5820Sstevel@tonic-gate }
5830Sstevel@tonic-gate
5840Sstevel@tonic-gate wbpb->bpb.hidden_sectors = offset;
5850Sstevel@tonic-gate
5860Sstevel@tonic-gate if (GetFsParams) {
5870Sstevel@tonic-gate RelOffset = offset;
5880Sstevel@tonic-gate } else {
5890Sstevel@tonic-gate wbpb->sunbpb.bs_offset_high = offset >> 16;
5900Sstevel@tonic-gate wbpb->sunbpb.bs_offset_low = offset & 0xFFFF;
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate }
5930Sstevel@tonic-gate
5940Sstevel@tonic-gate /*
5950Sstevel@tonic-gate * lookup_FAT_size
5960Sstevel@tonic-gate *
5970Sstevel@tonic-gate * Given the FDISK partition file system identifier, return the
5980Sstevel@tonic-gate * expected FAT size for the partition.
5990Sstevel@tonic-gate */
6000Sstevel@tonic-gate static
6010Sstevel@tonic-gate int
lookup_FAT_size(uchar_t partid)6020Sstevel@tonic-gate lookup_FAT_size(uchar_t partid)
6030Sstevel@tonic-gate {
6040Sstevel@tonic-gate int rval;
6050Sstevel@tonic-gate
6060Sstevel@tonic-gate switch (partid) {
6070Sstevel@tonic-gate case DOSOS12:
6080Sstevel@tonic-gate rval = 12;
6090Sstevel@tonic-gate break;
6100Sstevel@tonic-gate case DOSOS16:
6110Sstevel@tonic-gate case DOSHUGE:
6120Sstevel@tonic-gate case FDISK_FAT95:
6130Sstevel@tonic-gate case X86BOOT:
6140Sstevel@tonic-gate rval = 16;
6150Sstevel@tonic-gate break;
6160Sstevel@tonic-gate case FDISK_WINDOWS:
6170Sstevel@tonic-gate case FDISK_EXT_WIN:
6180Sstevel@tonic-gate rval = 32;
6190Sstevel@tonic-gate break;
6200Sstevel@tonic-gate case EXTDOS:
6210Sstevel@tonic-gate case FDISK_EXTLBA:
6220Sstevel@tonic-gate default:
6230Sstevel@tonic-gate rval = -1;
6240Sstevel@tonic-gate break;
6250Sstevel@tonic-gate }
6260Sstevel@tonic-gate
6270Sstevel@tonic-gate return (rval);
6280Sstevel@tonic-gate }
6290Sstevel@tonic-gate
6300Sstevel@tonic-gate /*
6310Sstevel@tonic-gate * seek_partn
6320Sstevel@tonic-gate *
6330Sstevel@tonic-gate * Seek to the beginning of the partition where we need to install
6340Sstevel@tonic-gate * the new FAT. Zero return for any error, but print error
6350Sstevel@tonic-gate * messages here.
6360Sstevel@tonic-gate */
6370Sstevel@tonic-gate static
6380Sstevel@tonic-gate int
seek_partn(int fd,char * pn,bpb_t * wbpb,off64_t * seekto)6390Sstevel@tonic-gate seek_partn(int fd, char *pn, bpb_t *wbpb, off64_t *seekto)
6400Sstevel@tonic-gate {
6410Sstevel@tonic-gate struct ipart part[FD_NUMPART];
6420Sstevel@tonic-gate struct mboot extmboot;
6430Sstevel@tonic-gate struct mboot mb;
6447563SPrasad.Singamsetty@Sun.COM diskaddr_t xstartsect;
6450Sstevel@tonic-gate off64_t nextseek = 0;
6460Sstevel@tonic-gate off64_t lastseek = 0;
6470Sstevel@tonic-gate int logicalDriveCount = 0;
6480Sstevel@tonic-gate int extendedPart = -1;
6490Sstevel@tonic-gate int primaryPart = -1;
6500Sstevel@tonic-gate int bootPart = -1;
6517563SPrasad.Singamsetty@Sun.COM uint32_t xnumsect = 0;
6520Sstevel@tonic-gate int drvnum;
6530Sstevel@tonic-gate int driveIndex;
6540Sstevel@tonic-gate int i;
6550Sstevel@tonic-gate /*
6560Sstevel@tonic-gate * Count of drives in the current extended partition's
6570Sstevel@tonic-gate * FDISK table, and indexes of the drives themselves.
6580Sstevel@tonic-gate */
6590Sstevel@tonic-gate int extndDrives[FD_NUMPART];
6600Sstevel@tonic-gate int numDrives = 0;
6610Sstevel@tonic-gate /*
6620Sstevel@tonic-gate * Count of drives (beyond primary) in master boot record's
6630Sstevel@tonic-gate * FDISK table, and indexes of the drives themselves.
6640Sstevel@tonic-gate */
6650Sstevel@tonic-gate int extraDrives[FD_NUMPART];
6660Sstevel@tonic-gate int numExtraDrives = 0;
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate if ((drvnum = parse_drvnum(pn)) < 0)
6690Sstevel@tonic-gate return (PART_NOT_FOUND);
6700Sstevel@tonic-gate
6710Sstevel@tonic-gate if (read(fd, &mb, sizeof (mb)) != sizeof (mb)) {
6720Sstevel@tonic-gate (void) fprintf(stderr,
6730Sstevel@tonic-gate gettext("Couldn't read a Master Boot Record?!\n"));
6740Sstevel@tonic-gate return (PART_NOT_FOUND);
6750Sstevel@tonic-gate }
6760Sstevel@tonic-gate
6770Sstevel@tonic-gate if (ltohs(mb.signature) != BOOTSECSIG) {
6780Sstevel@tonic-gate (void) fprintf(stderr,
6790Sstevel@tonic-gate gettext("Bad Sig on master boot record!\n"));
6800Sstevel@tonic-gate return (PART_NOT_FOUND);
6810Sstevel@tonic-gate }
6820Sstevel@tonic-gate
6830Sstevel@tonic-gate *seekto = 0;
6840Sstevel@tonic-gate
6850Sstevel@tonic-gate /*
6860Sstevel@tonic-gate * Copy partition table into memory
6870Sstevel@tonic-gate */
6880Sstevel@tonic-gate (void) memcpy(part, mb.parts, sizeof (part));
6890Sstevel@tonic-gate
6900Sstevel@tonic-gate /*
6910Sstevel@tonic-gate * Get a summary of what is in the Master FDISK table.
6920Sstevel@tonic-gate * Normally we expect to find one partition marked as a DOS drive.
6930Sstevel@tonic-gate * This partition is the one Windows calls the primary dos partition.
6940Sstevel@tonic-gate * If the machine has any logical drives then we also expect
6950Sstevel@tonic-gate * to find a partition marked as an extended DOS partition.
6960Sstevel@tonic-gate *
6970Sstevel@tonic-gate * Sometimes we'll find multiple partitions marked as DOS drives.
6980Sstevel@tonic-gate * The Solaris fdisk program allows these partitions
6990Sstevel@tonic-gate * to be created, but Windows fdisk no longer does. We still need
7000Sstevel@tonic-gate * to support these, though, since Windows does. We also need to fix
7010Sstevel@tonic-gate * our fdisk to behave like the Windows version.
7020Sstevel@tonic-gate *
7030Sstevel@tonic-gate * It turns out that some off-the-shelf media have *only* an
7040Sstevel@tonic-gate * Extended partition, so we need to deal with that case as
7050Sstevel@tonic-gate * well.
7060Sstevel@tonic-gate *
7070Sstevel@tonic-gate * Only a single (the first) Extended or Boot Partition will
7080Sstevel@tonic-gate * be recognized. Any others will be ignored.
7090Sstevel@tonic-gate */
7100Sstevel@tonic-gate for (i = 0; i < FD_NUMPART; i++) {
7110Sstevel@tonic-gate if (isDosDrive(part[i].systid)) {
7120Sstevel@tonic-gate if (primaryPart < 0) {
7130Sstevel@tonic-gate logicalDriveCount++;
7140Sstevel@tonic-gate primaryPart = i;
7150Sstevel@tonic-gate } else {
7160Sstevel@tonic-gate extraDrives[numExtraDrives++] = i;
7170Sstevel@tonic-gate }
7180Sstevel@tonic-gate continue;
7190Sstevel@tonic-gate }
7200Sstevel@tonic-gate if ((extendedPart < 0) && isDosExtended(part[i].systid)) {
7210Sstevel@tonic-gate extendedPart = i;
7220Sstevel@tonic-gate continue;
7230Sstevel@tonic-gate }
7240Sstevel@tonic-gate if ((bootPart < 0) && isBootPart(part[i].systid)) {
7250Sstevel@tonic-gate bootPart = i;
7260Sstevel@tonic-gate continue;
7270Sstevel@tonic-gate }
7280Sstevel@tonic-gate }
7290Sstevel@tonic-gate
7300Sstevel@tonic-gate if (drvnum == BOOT_PARTITION_DRIVE) {
7310Sstevel@tonic-gate if (bootPart < 0) {
7320Sstevel@tonic-gate (void) fprintf(stderr,
7330Sstevel@tonic-gate gettext("No boot partition found on drive\n"));
7340Sstevel@tonic-gate return (PART_NOT_FOUND);
7350Sstevel@tonic-gate }
7360Sstevel@tonic-gate if ((*seekto = ltohi(part[bootPart].relsect)) == 0) {
7370Sstevel@tonic-gate (void) fprintf(stderr, gettext("Bogus FDISK entry? "
7380Sstevel@tonic-gate "A boot partition starting\nat sector 0 would "
7390Sstevel@tonic-gate "collide with the FDISK table!\n"));
7400Sstevel@tonic-gate return (PART_NOT_FOUND);
7410Sstevel@tonic-gate }
7420Sstevel@tonic-gate
7430Sstevel@tonic-gate fill_bpb_sizes(wbpb, part, bootPart, *seekto);
7440Sstevel@tonic-gate *seekto *= BPSEC;
7450Sstevel@tonic-gate FdiskFATsize = lookup_FAT_size(part[bootPart].systid);
7460Sstevel@tonic-gate if (Verbose)
7470Sstevel@tonic-gate (void) printf(gettext("Boot partition's offset: "
7480Sstevel@tonic-gate "Sector %x.\n"), *seekto/BPSEC);
7490Sstevel@tonic-gate if (lseek64(fd, *seekto, SEEK_SET) < 0) {
7500Sstevel@tonic-gate (void) fprintf(stderr, gettext("Partition %s: "), pn);
7510Sstevel@tonic-gate perror("");
7520Sstevel@tonic-gate return (PART_NOT_FOUND);
7530Sstevel@tonic-gate }
7540Sstevel@tonic-gate return (PART_FOUND);
7550Sstevel@tonic-gate }
7560Sstevel@tonic-gate
7570Sstevel@tonic-gate if (drvnum == PRIMARY_DOS_DRIVE && primaryPart >= 0) {
7580Sstevel@tonic-gate if ((*seekto = ltohi(part[primaryPart].relsect)) == 0) {
7590Sstevel@tonic-gate (void) fprintf(stderr, gettext("Bogus FDISK entry? "
7600Sstevel@tonic-gate "A partition starting\nat sector 0 would "
7610Sstevel@tonic-gate "collide with the FDISK table!\n"));
7620Sstevel@tonic-gate return (PART_NOT_FOUND);
7630Sstevel@tonic-gate }
7640Sstevel@tonic-gate
7650Sstevel@tonic-gate fill_bpb_sizes(wbpb, part, primaryPart, *seekto);
7660Sstevel@tonic-gate *seekto *= BPSEC;
7670Sstevel@tonic-gate FdiskFATsize = lookup_FAT_size(part[primaryPart].systid);
7680Sstevel@tonic-gate if (Verbose)
7690Sstevel@tonic-gate (void) printf(gettext("Partition's offset: "
7700Sstevel@tonic-gate "Sector %x.\n"), *seekto/BPSEC);
7710Sstevel@tonic-gate if (lseek64(fd, *seekto, SEEK_SET) < 0) {
7720Sstevel@tonic-gate (void) fprintf(stderr, gettext("Partition %s: "), pn);
7730Sstevel@tonic-gate perror("");
7740Sstevel@tonic-gate return (PART_NOT_FOUND);
7750Sstevel@tonic-gate }
7760Sstevel@tonic-gate return (PART_FOUND);
7770Sstevel@tonic-gate }
7780Sstevel@tonic-gate
7790Sstevel@tonic-gate /*
7800Sstevel@tonic-gate * We are not looking for the C: drive (or there was no primary
7810Sstevel@tonic-gate * drive found), so we had better have an extended partition or
7820Sstevel@tonic-gate * extra drives in the Master FDISK table.
7830Sstevel@tonic-gate */
7840Sstevel@tonic-gate if ((extendedPart < 0) && (numExtraDrives == 0)) {
7850Sstevel@tonic-gate (void) fprintf(stderr,
7860Sstevel@tonic-gate gettext("No such logical drive "
7870Sstevel@tonic-gate "(missing extended partition entry)\n"));
7880Sstevel@tonic-gate return (PART_NOT_FOUND);
7890Sstevel@tonic-gate }
7900Sstevel@tonic-gate
7910Sstevel@tonic-gate if (extendedPart >= 0) {
7920Sstevel@tonic-gate nextseek = xstartsect = ltohi(part[extendedPart].relsect);
7930Sstevel@tonic-gate xnumsect = ltohi(part[extendedPart].numsect);
7940Sstevel@tonic-gate do {
7950Sstevel@tonic-gate /*
7960Sstevel@tonic-gate * If the seek would not cause us to change
7970Sstevel@tonic-gate * position on the drive, then we're out of
7980Sstevel@tonic-gate * extended partitions to examine.
7990Sstevel@tonic-gate */
8000Sstevel@tonic-gate if (nextseek == lastseek)
8010Sstevel@tonic-gate break;
8020Sstevel@tonic-gate logicalDriveCount += numDrives;
8030Sstevel@tonic-gate /*
8040Sstevel@tonic-gate * Seek the next extended partition, and find
8050Sstevel@tonic-gate * logical drives within it.
8060Sstevel@tonic-gate */
8070Sstevel@tonic-gate if (lseek64(fd, nextseek * BPSEC, SEEK_SET) < 0 ||
8080Sstevel@tonic-gate read(fd, &extmboot, sizeof (extmboot)) !=
8095121Sfrankho sizeof (extmboot)) {
8100Sstevel@tonic-gate perror(gettext("Unable to read extended "
8115121Sfrankho "partition record"));
8120Sstevel@tonic-gate return (PART_NOT_FOUND);
8130Sstevel@tonic-gate }
8140Sstevel@tonic-gate (void) memcpy(part, extmboot.parts, sizeof (part));
8150Sstevel@tonic-gate lastseek = nextseek;
8160Sstevel@tonic-gate if (ltohs(extmboot.signature) != MBB_MAGIC) {
8170Sstevel@tonic-gate (void) fprintf(stderr,
8180Sstevel@tonic-gate gettext("Bad signature on "
8190Sstevel@tonic-gate "extended partition\n"));
8200Sstevel@tonic-gate return (PART_NOT_FOUND);
8210Sstevel@tonic-gate }
8220Sstevel@tonic-gate /*
8230Sstevel@tonic-gate * Count up drives, and track where the next
8240Sstevel@tonic-gate * extended partition is in case we need it. We
8250Sstevel@tonic-gate * are expecting only one extended partition. If
8260Sstevel@tonic-gate * there is more than one we'll only go to the
8270Sstevel@tonic-gate * first one we see, but warn about ignoring.
8280Sstevel@tonic-gate */
8290Sstevel@tonic-gate numDrives = 0;
8300Sstevel@tonic-gate for (i = 0; i < FD_NUMPART; i++) {
8310Sstevel@tonic-gate if (isDosDrive(part[i].systid)) {
8320Sstevel@tonic-gate extndDrives[numDrives++] = i;
8330Sstevel@tonic-gate continue;
8340Sstevel@tonic-gate } else if (isDosExtended(part[i].systid)) {
8350Sstevel@tonic-gate if (nextseek != lastseek) {
8360Sstevel@tonic-gate /*
8370Sstevel@tonic-gate * Already found an extended
8380Sstevel@tonic-gate * partition in this table.
8390Sstevel@tonic-gate */
8400Sstevel@tonic-gate (void) fprintf(stderr,
8410Sstevel@tonic-gate gettext("WARNING: "
8420Sstevel@tonic-gate "Ignoring unexpected "
8430Sstevel@tonic-gate "additional extended "
8440Sstevel@tonic-gate "partition"));
8450Sstevel@tonic-gate continue;
8460Sstevel@tonic-gate }
8470Sstevel@tonic-gate nextseek = xstartsect +
8480Sstevel@tonic-gate ltohi(part[i].relsect);
8490Sstevel@tonic-gate continue;
8500Sstevel@tonic-gate }
8510Sstevel@tonic-gate }
8520Sstevel@tonic-gate } while (drvnum > logicalDriveCount + numDrives);
8530Sstevel@tonic-gate
8540Sstevel@tonic-gate if (drvnum <= logicalDriveCount + numDrives) {
8550Sstevel@tonic-gate /*
8560Sstevel@tonic-gate * The number of logical drives we've found thus
8570Sstevel@tonic-gate * far is enough to get us to the one we were
8580Sstevel@tonic-gate * searching for.
8590Sstevel@tonic-gate */
8600Sstevel@tonic-gate driveIndex = logicalDriveCount + numDrives - drvnum;
8610Sstevel@tonic-gate *seekto =
8620Sstevel@tonic-gate ltohi(part[extndDrives[driveIndex]].relsect) +
8630Sstevel@tonic-gate lastseek;
8640Sstevel@tonic-gate if (*seekto == lastseek) {
8650Sstevel@tonic-gate (void) fprintf(stderr,
8660Sstevel@tonic-gate gettext("Bogus FDISK entry? A logical "
8670Sstevel@tonic-gate "drive starting at\nsector 0x%llx would "
8680Sstevel@tonic-gate "collide with the\nFDISK information in "
8690Sstevel@tonic-gate "that sector.\n"), *seekto);
8700Sstevel@tonic-gate return (PART_NOT_FOUND);
8710Sstevel@tonic-gate } else if (*seekto <= xstartsect ||
8720Sstevel@tonic-gate *seekto >= (xstartsect + xnumsect)) {
8730Sstevel@tonic-gate (void) fprintf(stderr,
8740Sstevel@tonic-gate gettext("Bogus FDISK entry? "
8750Sstevel@tonic-gate "Logical drive start sector (0x%llx)\n"
8760Sstevel@tonic-gate "not within extended partition! "
8770Sstevel@tonic-gate "(Expected in range 0x%x - 0x%x)\n"),
8780Sstevel@tonic-gate *seekto, xstartsect + 1,
8790Sstevel@tonic-gate xstartsect + xnumsect - 1);
8800Sstevel@tonic-gate return (PART_NOT_FOUND);
8810Sstevel@tonic-gate }
8820Sstevel@tonic-gate fill_bpb_sizes(wbpb, part, extndDrives[driveIndex],
8830Sstevel@tonic-gate *seekto);
8840Sstevel@tonic-gate *seekto *= BPSEC;
8850Sstevel@tonic-gate FdiskFATsize = lookup_FAT_size(
8860Sstevel@tonic-gate part[extndDrives[driveIndex]].systid);
8870Sstevel@tonic-gate if (Verbose)
8880Sstevel@tonic-gate (void) printf(gettext("Partition's offset: "
8890Sstevel@tonic-gate "Sector 0x%x.\n"), *seekto/BPSEC);
8900Sstevel@tonic-gate if (lseek64(fd, *seekto, SEEK_SET) < 0) {
8910Sstevel@tonic-gate (void) fprintf(stderr,
8920Sstevel@tonic-gate gettext("Partition %s: "), pn);
8930Sstevel@tonic-gate perror("");
8940Sstevel@tonic-gate return (PART_NOT_FOUND);
8950Sstevel@tonic-gate }
8960Sstevel@tonic-gate return (PART_FOUND);
8970Sstevel@tonic-gate } else {
8980Sstevel@tonic-gate /*
8990Sstevel@tonic-gate * We ran out of extended dos partition
9000Sstevel@tonic-gate * drives. The only hope now is to go
9010Sstevel@tonic-gate * back to extra drives defined in the master
9020Sstevel@tonic-gate * fdisk table. But we overwrote that table
9030Sstevel@tonic-gate * already, so we must load it in again.
9040Sstevel@tonic-gate */
9050Sstevel@tonic-gate logicalDriveCount += numDrives;
9060Sstevel@tonic-gate (void) memcpy(part, mb.parts, sizeof (part));
9070Sstevel@tonic-gate }
9080Sstevel@tonic-gate }
9090Sstevel@tonic-gate /*
9100Sstevel@tonic-gate * Still haven't found the drive, is it an extra
9110Sstevel@tonic-gate * drive defined in the main FDISK table?
9120Sstevel@tonic-gate */
9130Sstevel@tonic-gate if (drvnum <= logicalDriveCount + numExtraDrives) {
9140Sstevel@tonic-gate driveIndex = logicalDriveCount + numExtraDrives - drvnum;
9150Sstevel@tonic-gate *seekto = ltohi(part[extraDrives[driveIndex]].relsect);
9160Sstevel@tonic-gate if (*seekto == 0) {
9170Sstevel@tonic-gate (void) fprintf(stderr, gettext("Bogus FDISK entry? "
9180Sstevel@tonic-gate "A partition starting\nat sector 0 would "
9190Sstevel@tonic-gate "collide with the FDISK table!\n"));
9200Sstevel@tonic-gate return (PART_NOT_FOUND);
9210Sstevel@tonic-gate }
9220Sstevel@tonic-gate
9230Sstevel@tonic-gate fill_bpb_sizes(wbpb, part, extraDrives[driveIndex], *seekto);
9240Sstevel@tonic-gate *seekto *= BPSEC;
9250Sstevel@tonic-gate FdiskFATsize =
9265121Sfrankho lookup_FAT_size(part[extraDrives[driveIndex]].systid);
9270Sstevel@tonic-gate if (Verbose)
9280Sstevel@tonic-gate (void) printf(gettext("Partition's offset: "
9290Sstevel@tonic-gate "Sector %x.\n"), *seekto/BPSEC);
9300Sstevel@tonic-gate if (lseek64(fd, *seekto, SEEK_SET) < 0) {
9310Sstevel@tonic-gate (void) fprintf(stderr,
9320Sstevel@tonic-gate gettext("Partition %s: "), pn);
9330Sstevel@tonic-gate perror("");
9340Sstevel@tonic-gate return (PART_NOT_FOUND);
9350Sstevel@tonic-gate }
9360Sstevel@tonic-gate return (PART_FOUND);
9370Sstevel@tonic-gate }
9380Sstevel@tonic-gate (void) fprintf(stderr, gettext("No such logical drive\n"));
9390Sstevel@tonic-gate return (PART_NOT_FOUND);
9400Sstevel@tonic-gate }
9410Sstevel@tonic-gate
9420Sstevel@tonic-gate /*
9430Sstevel@tonic-gate * seek_nofdisk
9440Sstevel@tonic-gate *
9450Sstevel@tonic-gate * User is asking us to trust them that they know best.
9460Sstevel@tonic-gate * We basically won't do much seeking here, the only seeking we'll do
9470Sstevel@tonic-gate * is if the 'hidden' parameter was given.
9480Sstevel@tonic-gate */
9490Sstevel@tonic-gate static
9500Sstevel@tonic-gate int
seek_nofdisk(int fd,bpb_t * wbpb,off64_t * seekto)9510Sstevel@tonic-gate seek_nofdisk(int fd, bpb_t *wbpb, off64_t *seekto)
9520Sstevel@tonic-gate {
9530Sstevel@tonic-gate if (TotSize > 0xffff)
9540Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = 0;
9550Sstevel@tonic-gate else
9560Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = (short)TotSize;
9570Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = TotSize;
9580Sstevel@tonic-gate
9590Sstevel@tonic-gate *seekto = RelOffset * BPSEC;
9600Sstevel@tonic-gate wbpb->bpb.hidden_sectors = RelOffset;
9610Sstevel@tonic-gate wbpb->sunbpb.bs_offset_high = RelOffset >> 16;
9620Sstevel@tonic-gate wbpb->sunbpb.bs_offset_low = RelOffset & 0xFFFF;
9630Sstevel@tonic-gate
9640Sstevel@tonic-gate if (Verbose)
9650Sstevel@tonic-gate (void) printf(gettext("Requested offset: Sector %x.\n"),
9660Sstevel@tonic-gate *seekto/BPSEC);
9670Sstevel@tonic-gate
9680Sstevel@tonic-gate if (lseek64(fd, *seekto, SEEK_SET) < 0) {
9690Sstevel@tonic-gate (void) fprintf(stderr,
9700Sstevel@tonic-gate gettext("User specified start sector %d"), RelOffset);
9710Sstevel@tonic-gate perror("");
9720Sstevel@tonic-gate return (PART_NOT_FOUND);
9730Sstevel@tonic-gate }
9740Sstevel@tonic-gate return (PART_FOUND);
9750Sstevel@tonic-gate }
9760Sstevel@tonic-gate
9770Sstevel@tonic-gate /*
9780Sstevel@tonic-gate * set_fat_string
9790Sstevel@tonic-gate *
9800Sstevel@tonic-gate * Fill in the type string of the FAT
9810Sstevel@tonic-gate */
9820Sstevel@tonic-gate static
9830Sstevel@tonic-gate void
set_fat_string(bpb_t * wbpb,int fatsize)9840Sstevel@tonic-gate set_fat_string(bpb_t *wbpb, int fatsize)
9850Sstevel@tonic-gate {
9860Sstevel@tonic-gate if (fatsize == 12) {
9870Sstevel@tonic-gate (void) strncpy((char *)wbpb->ebpb.type, FAT12_TYPE_STRING,
9885121Sfrankho strlen(FAT12_TYPE_STRING));
9890Sstevel@tonic-gate } else if (fatsize == 16) {
9900Sstevel@tonic-gate (void) strncpy((char *)wbpb->ebpb.type, FAT16_TYPE_STRING,
9915121Sfrankho strlen(FAT16_TYPE_STRING));
9920Sstevel@tonic-gate } else {
9930Sstevel@tonic-gate (void) strncpy((char *)wbpb->ebpb.type, FAT32_TYPE_STRING,
9945121Sfrankho strlen(FAT32_TYPE_STRING));
9950Sstevel@tonic-gate }
9960Sstevel@tonic-gate }
9970Sstevel@tonic-gate
9980Sstevel@tonic-gate /*
9990Sstevel@tonic-gate * prepare_image_file
10000Sstevel@tonic-gate *
10010Sstevel@tonic-gate * Open the file that will hold the image (as opposed to the image
10020Sstevel@tonic-gate * being written to the boot sector of an actual disk).
10030Sstevel@tonic-gate */
10040Sstevel@tonic-gate static
10050Sstevel@tonic-gate int
prepare_image_file(char * fn,bpb_t * wbpb)10060Sstevel@tonic-gate prepare_image_file(char *fn, bpb_t *wbpb)
10070Sstevel@tonic-gate {
10080Sstevel@tonic-gate int fd;
10090Sstevel@tonic-gate char zerobyte = '\0';
10100Sstevel@tonic-gate
10110Sstevel@tonic-gate if ((fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0666)) < 0) {
10120Sstevel@tonic-gate perror(fn);
10130Sstevel@tonic-gate exit(2);
10140Sstevel@tonic-gate }
10150Sstevel@tonic-gate
10160Sstevel@tonic-gate if (Imagesize == 5) {
10170Sstevel@tonic-gate /* Disk image of a 1.2M floppy */
10180Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = 2 * 80 * 15;
10190Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = 2 * 80 * 15;
10200Sstevel@tonic-gate wbpb->bpb.sectors_per_track = 15;
10210Sstevel@tonic-gate wbpb->bpb.heads = 2;
10220Sstevel@tonic-gate wbpb->bpb.media = 0xF9;
10230Sstevel@tonic-gate wbpb->bpb.num_root_entries = 224;
10240Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1;
10250Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 7;
10260Sstevel@tonic-gate } else {
10270Sstevel@tonic-gate /* Disk image of a 1.44M floppy */
10280Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = 2 * 80 * 18;
10290Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = 2 * 80 * 18;
10300Sstevel@tonic-gate wbpb->bpb.sectors_per_track = 18;
10310Sstevel@tonic-gate wbpb->bpb.heads = 2;
10320Sstevel@tonic-gate wbpb->bpb.media = 0xF0;
10330Sstevel@tonic-gate wbpb->bpb.num_root_entries = 224;
10340Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1;
10350Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 9;
10360Sstevel@tonic-gate }
10370Sstevel@tonic-gate
10380Sstevel@tonic-gate /*
10390Sstevel@tonic-gate * Make a holey file, with length the exact
10400Sstevel@tonic-gate * size of the floppy image.
10410Sstevel@tonic-gate */
10420Sstevel@tonic-gate if (lseek(fd, (wbpb->bpb.sectors_in_volume * BPSEC)-1, SEEK_SET) < 0) {
10430Sstevel@tonic-gate (void) close(fd);
10440Sstevel@tonic-gate perror(fn);
10450Sstevel@tonic-gate exit(2);
10460Sstevel@tonic-gate }
10470Sstevel@tonic-gate
10480Sstevel@tonic-gate if (write(fd, &zerobyte, 1) != 1) {
10490Sstevel@tonic-gate (void) close(fd);
10500Sstevel@tonic-gate perror(fn);
10510Sstevel@tonic-gate exit(2);
10520Sstevel@tonic-gate }
10530Sstevel@tonic-gate
10540Sstevel@tonic-gate if (lseek(fd, 0, SEEK_SET) < 0) {
10550Sstevel@tonic-gate (void) close(fd);
10560Sstevel@tonic-gate perror(fn);
10570Sstevel@tonic-gate exit(2);
10580Sstevel@tonic-gate }
10590Sstevel@tonic-gate
10600Sstevel@tonic-gate Fatentsize = 12; /* Size of fat entry in bits */
10610Sstevel@tonic-gate set_fat_string(wbpb, Fatentsize);
10620Sstevel@tonic-gate
10630Sstevel@tonic-gate wbpb->ebpb.phys_drive_num = 0;
10640Sstevel@tonic-gate
10650Sstevel@tonic-gate wbpb->sunbpb.bs_offset_high = 0;
10660Sstevel@tonic-gate wbpb->sunbpb.bs_offset_low = 0;
10670Sstevel@tonic-gate
10680Sstevel@tonic-gate return (fd);
10690Sstevel@tonic-gate }
10700Sstevel@tonic-gate
10710Sstevel@tonic-gate /*
10720Sstevel@tonic-gate * partn_lecture
10730Sstevel@tonic-gate *
10740Sstevel@tonic-gate * Give a brief sermon on dev_name user should pass to
10750Sstevel@tonic-gate * the program from the command line.
10760Sstevel@tonic-gate *
10770Sstevel@tonic-gate */
10780Sstevel@tonic-gate static
10790Sstevel@tonic-gate void
partn_lecture(char * dn)10800Sstevel@tonic-gate partn_lecture(char *dn)
10810Sstevel@tonic-gate {
10820Sstevel@tonic-gate (void) fprintf(stderr,
10835121Sfrankho gettext("\nDevice %s was assumed to be a diskette.\n"
10845121Sfrankho "A diskette specific operation failed on this device.\n"
10855121Sfrankho "If the device is a hard disk, provide the name of "
10865121Sfrankho "the full physical disk,\n"
10875121Sfrankho "and qualify that name with a logical drive specifier.\n\n"
10885121Sfrankho "Hint: the device is usually something similar to\n\n"
10895121Sfrankho "/dev/rdsk/c0d0p0 or /dev/rdsk/c0t0d0p0 (x86)\n"
10905121Sfrankho "/dev/rdsk/c0t5d0s2 (sparc)\n\n"
10915121Sfrankho "The drive specifier is appended to the device name."
10925121Sfrankho " For example:\n\n"
10935121Sfrankho "/dev/rdsk/c0t5d0s2:c or /dev/rdsk/c0d0p0:boot\n\n"), dn);
10940Sstevel@tonic-gate }
10950Sstevel@tonic-gate
10960Sstevel@tonic-gate static
10970Sstevel@tonic-gate void
warn_funky_floppy(void)10980Sstevel@tonic-gate warn_funky_floppy(void)
10990Sstevel@tonic-gate {
11000Sstevel@tonic-gate (void) fprintf(stderr,
11010Sstevel@tonic-gate gettext("Use the 'nofdisk' option to create file systems\n"
11025121Sfrankho "on non-standard floppies.\n\n"));
11030Sstevel@tonic-gate exit(4);
11040Sstevel@tonic-gate }
11050Sstevel@tonic-gate
11060Sstevel@tonic-gate static
11070Sstevel@tonic-gate void
warn_funky_fatsize(void)11080Sstevel@tonic-gate warn_funky_fatsize(void)
11090Sstevel@tonic-gate {
11100Sstevel@tonic-gate (void) fprintf(stderr,
11110Sstevel@tonic-gate gettext("Non-standard FAT size requested for floppy.\n"
11125121Sfrankho "The 'nofdisk' option must be used to\n"
11135121Sfrankho "override the 12 bit floppy default.\n\n"));
11140Sstevel@tonic-gate exit(4);
11150Sstevel@tonic-gate }
11160Sstevel@tonic-gate
11170Sstevel@tonic-gate static
11180Sstevel@tonic-gate void
floppy_bpb_fillin(bpb_t * wbpb,int diam,int hds,int spt)11190Sstevel@tonic-gate floppy_bpb_fillin(bpb_t *wbpb, int diam, int hds, int spt)
11200Sstevel@tonic-gate {
11210Sstevel@tonic-gate switch (diam) {
11220Sstevel@tonic-gate case 3:
11230Sstevel@tonic-gate switch (hds) {
11240Sstevel@tonic-gate case 2:
11250Sstevel@tonic-gate switch (spt) {
11260Sstevel@tonic-gate case 9:
11270Sstevel@tonic-gate wbpb->bpb.media = 0xF9;
11280Sstevel@tonic-gate wbpb->bpb.num_root_entries = 112;
11290Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 2;
11300Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 3;
11310Sstevel@tonic-gate break;
11320Sstevel@tonic-gate case 18:
11330Sstevel@tonic-gate wbpb->bpb.media = 0xF0;
11340Sstevel@tonic-gate wbpb->bpb.num_root_entries = 224;
11350Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1;
11360Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 9;
11370Sstevel@tonic-gate break;
11380Sstevel@tonic-gate case 36:
11390Sstevel@tonic-gate wbpb->bpb.media = 0xF0;
11400Sstevel@tonic-gate wbpb->bpb.num_root_entries = 240;
11410Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 2;
11420Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 9;
11430Sstevel@tonic-gate break;
11440Sstevel@tonic-gate default:
11450Sstevel@tonic-gate (void) fprintf(stderr,
11460Sstevel@tonic-gate gettext("Unknown diskette parameters! "
11475121Sfrankho "3.5'' diskette with %d heads "
11485121Sfrankho "and %d sectors/track.\n"), hds, spt);
11490Sstevel@tonic-gate warn_funky_floppy();
11500Sstevel@tonic-gate }
11510Sstevel@tonic-gate break;
11520Sstevel@tonic-gate case 1:
11530Sstevel@tonic-gate default:
11540Sstevel@tonic-gate (void) fprintf(stderr,
11550Sstevel@tonic-gate gettext("Unknown diskette parameters! "
11565121Sfrankho "3.5'' diskette with %d heads "), hds);
11570Sstevel@tonic-gate warn_funky_floppy();
11580Sstevel@tonic-gate }
11590Sstevel@tonic-gate break;
11600Sstevel@tonic-gate case 5:
11610Sstevel@tonic-gate switch (hds) {
11620Sstevel@tonic-gate case 2:
11630Sstevel@tonic-gate switch (spt) {
11640Sstevel@tonic-gate case 15:
11650Sstevel@tonic-gate wbpb->bpb.media = 0xF9;
11660Sstevel@tonic-gate wbpb->bpb.num_root_entries = 224;
11670Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1;
11680Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 7;
11690Sstevel@tonic-gate break;
11700Sstevel@tonic-gate case 9:
11710Sstevel@tonic-gate wbpb->bpb.media = 0xFD;
11720Sstevel@tonic-gate wbpb->bpb.num_root_entries = 112;
11730Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 2;
11740Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 2;
11750Sstevel@tonic-gate break;
11760Sstevel@tonic-gate case 8:
11770Sstevel@tonic-gate wbpb->bpb.media = 0xFF;
11780Sstevel@tonic-gate wbpb->bpb.num_root_entries = 112;
11790Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1;
11800Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 2;
11810Sstevel@tonic-gate break;
11820Sstevel@tonic-gate default:
11830Sstevel@tonic-gate (void) fprintf(stderr,
11840Sstevel@tonic-gate gettext("Unknown diskette parameters! "
11855121Sfrankho "5.25'' diskette with %d heads "
11865121Sfrankho "and %d sectors/track.\n"), hds, spt);
11870Sstevel@tonic-gate warn_funky_floppy();
11880Sstevel@tonic-gate }
11890Sstevel@tonic-gate break;
11900Sstevel@tonic-gate case 1:
11910Sstevel@tonic-gate switch (spt) {
11920Sstevel@tonic-gate case 9:
11930Sstevel@tonic-gate wbpb->bpb.media = 0xFC;
11940Sstevel@tonic-gate wbpb->bpb.num_root_entries = 64;
11950Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1;
11960Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 2;
11970Sstevel@tonic-gate break;
11980Sstevel@tonic-gate case 8:
11990Sstevel@tonic-gate wbpb->bpb.media = 0xFE;
12000Sstevel@tonic-gate wbpb->bpb.num_root_entries = 64;
12010Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1;
12020Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 1;
12030Sstevel@tonic-gate break;
12040Sstevel@tonic-gate default:
12050Sstevel@tonic-gate (void) fprintf(stderr,
12060Sstevel@tonic-gate gettext("Unknown diskette parameters! "
12075121Sfrankho "5.25'' diskette with %d heads "
12085121Sfrankho "and %d sectors/track.\n"), hds, spt);
12090Sstevel@tonic-gate warn_funky_floppy();
12100Sstevel@tonic-gate }
12110Sstevel@tonic-gate break;
12120Sstevel@tonic-gate default:
12130Sstevel@tonic-gate (void) fprintf(stderr,
12140Sstevel@tonic-gate gettext("Unknown diskette parameters! "
12155121Sfrankho "5.25'' diskette with %d heads."), hds);
12160Sstevel@tonic-gate warn_funky_floppy();
12170Sstevel@tonic-gate }
12180Sstevel@tonic-gate break;
12190Sstevel@tonic-gate default:
12200Sstevel@tonic-gate (void) fprintf(stderr,
12210Sstevel@tonic-gate gettext("\nUnknown diskette type. Only know about "
12225121Sfrankho "5.25'' and 3.5'' diskettes.\n"));
12230Sstevel@tonic-gate warn_funky_floppy();
12240Sstevel@tonic-gate }
12250Sstevel@tonic-gate }
12260Sstevel@tonic-gate
12270Sstevel@tonic-gate /*
12280Sstevel@tonic-gate * lookup_floppy
12290Sstevel@tonic-gate *
12300Sstevel@tonic-gate * Look up a media descriptor byte and other crucial BPB values
12310Sstevel@tonic-gate * based on floppy characteristics.
12320Sstevel@tonic-gate */
12330Sstevel@tonic-gate static
12340Sstevel@tonic-gate void
lookup_floppy(struct fd_char * fdchar,bpb_t * wbpb)12350Sstevel@tonic-gate lookup_floppy(struct fd_char *fdchar, bpb_t *wbpb)
12360Sstevel@tonic-gate {
12370Sstevel@tonic-gate ulong_t tsize;
12380Sstevel@tonic-gate ulong_t cyls, spt, hds, diam;
12390Sstevel@tonic-gate
12400Sstevel@tonic-gate cyls = fdchar->fdc_ncyl;
12410Sstevel@tonic-gate diam = fdchar->fdc_medium;
12420Sstevel@tonic-gate spt = fdchar->fdc_secptrack;
12430Sstevel@tonic-gate hds = fdchar->fdc_nhead;
12440Sstevel@tonic-gate
12450Sstevel@tonic-gate tsize = cyls * hds * spt;
12460Sstevel@tonic-gate
12470Sstevel@tonic-gate if (GetFsParams)
12480Sstevel@tonic-gate TotSize = tsize;
12490Sstevel@tonic-gate
12500Sstevel@tonic-gate if (GetSize) {
12510Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = tsize;
12520Sstevel@tonic-gate } else {
12530Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume =
12545121Sfrankho warn_mismatch(
12555121Sfrankho gettext("length of partition (in sectors)"),
12565121Sfrankho gettext("FDIOGCHAR call"), tsize, TotSize);
12570Sstevel@tonic-gate }
12580Sstevel@tonic-gate wbpb->bpb.sectors_in_volume =
12595121Sfrankho (short)wbpb->bpb.sectors_in_logical_volume;
12600Sstevel@tonic-gate
12610Sstevel@tonic-gate if (GetSPT) {
12620Sstevel@tonic-gate wbpb->bpb.sectors_per_track = spt;
12630Sstevel@tonic-gate } else {
12640Sstevel@tonic-gate wbpb->bpb.sectors_per_track =
12655121Sfrankho warn_mismatch(
12665121Sfrankho gettext("sectors per track"),
12675121Sfrankho gettext("FDIOGCHAR call"), spt, SecPerTrk);
12680Sstevel@tonic-gate spt = wbpb->bpb.sectors_per_track;
12690Sstevel@tonic-gate }
12700Sstevel@tonic-gate
12710Sstevel@tonic-gate if (GetTPC) {
12720Sstevel@tonic-gate wbpb->bpb.heads = hds;
12730Sstevel@tonic-gate } else {
12740Sstevel@tonic-gate wbpb->bpb.heads =
12755121Sfrankho warn_mismatch(
12765121Sfrankho gettext("number of heads"),
12775121Sfrankho gettext("FDIOGCHAR call"), hds, TrkPerCyl);
12780Sstevel@tonic-gate hds = wbpb->bpb.heads;
12790Sstevel@tonic-gate }
12800Sstevel@tonic-gate
12810Sstevel@tonic-gate Fatentsize = 12; /* Size of fat entry in bits */
12820Sstevel@tonic-gate if (!GetBPF && BitsPerFAT != Fatentsize) {
12830Sstevel@tonic-gate warn_funky_fatsize();
12840Sstevel@tonic-gate }
12850Sstevel@tonic-gate set_fat_string(wbpb, Fatentsize);
12860Sstevel@tonic-gate
12870Sstevel@tonic-gate wbpb->ebpb.phys_drive_num = 0;
12880Sstevel@tonic-gate
12890Sstevel@tonic-gate wbpb->bpb.hidden_sectors = 0;
12900Sstevel@tonic-gate wbpb->sunbpb.bs_offset_high = 0;
12910Sstevel@tonic-gate wbpb->sunbpb.bs_offset_low = 0;
12920Sstevel@tonic-gate
12930Sstevel@tonic-gate floppy_bpb_fillin(wbpb, diam, hds, spt);
12940Sstevel@tonic-gate }
12950Sstevel@tonic-gate
12960Sstevel@tonic-gate /*
12970Sstevel@tonic-gate * compute_cluster_size
12980Sstevel@tonic-gate *
12990Sstevel@tonic-gate * Compute an acceptable sectors/cluster value.
13000Sstevel@tonic-gate *
13011161Swyllys * Based on values from the Hardware White Paper
13021161Swyllys * from Microsoft.
13031161Swyllys * "Microsoft Extensible Firmware Initiative
13041161Swyllys * FAT32 File System Specification
13051161Swyllys * FAT: General Overview of On-Disk Format"
13060Sstevel@tonic-gate *
13071161Swyllys * Version 1.03, December 6, 2000
13081161Swyllys *
13090Sstevel@tonic-gate */
13100Sstevel@tonic-gate static
13110Sstevel@tonic-gate void
compute_cluster_size(bpb_t * wbpb)13120Sstevel@tonic-gate compute_cluster_size(bpb_t *wbpb)
13130Sstevel@tonic-gate {
1314608Swyllys ulong_t volsize;
1315608Swyllys ulong_t spc;
1316607Swyllys ulong_t rds, tmpval1, tmpval2;
1317607Swyllys ulong_t fatsz;
13181161Swyllys int newfat = 16;
13191161Swyllys
13201161Swyllys #define FAT12_MAX_CLUSTERS 0x0FF4
13211161Swyllys #define FAT16_MAX_CLUSTERS 0xFFF4
13221161Swyllys #define FAT32_MAX_CLUSTERS 0x0FFFFFF0
13231161Swyllys #define FAT32_SUGGESTED_NCLUST 0x400000
13241161Swyllys
13251161Swyllys /* compute volume size in sectors. */
13260Sstevel@tonic-gate volsize = wbpb->bpb.sectors_in_volume ? wbpb->bpb.sectors_in_volume :
13275121Sfrankho wbpb->bpb.sectors_in_logical_volume;
13280Sstevel@tonic-gate volsize -= wbpb->bpb.resv_sectors;
13290Sstevel@tonic-gate
13300Sstevel@tonic-gate if (GetSPC) {
13311161Swyllys /*
13321161Swyllys * User indicated what sort of FAT to create,
13331161Swyllys * make sure it is valid with the given size
13341161Swyllys * and compute an SPC value.
13351161Swyllys */
13361161Swyllys if (!MakeFAT32) { /* FAT16 */
13371161Swyllys /* volsize is in sectors */
13381161Swyllys if (volsize < FAT12_MAX_CLUSTERS) {
13391161Swyllys (void) fprintf(stderr,
13405121Sfrankho gettext("Requested size is too "
13415121Sfrankho "small for FAT16.\n"));
13421161Swyllys exit(4);
13431161Swyllys }
13441161Swyllys /* SPC must be a power of 2 */
13451161Swyllys for (spc = 1; spc <= 64; spc = spc * 2) {
13461161Swyllys if (volsize < spc * FAT16_MAX_CLUSTERS)
13471161Swyllys break;
13480Sstevel@tonic-gate }
13491161Swyllys if (volsize > (spc * FAT16_MAX_CLUSTERS)) {
13501161Swyllys (void) fprintf(stderr,
13515121Sfrankho gettext("Requested size is too "
13525121Sfrankho "large for FAT16.\n"));
13531161Swyllys exit(4);
13541161Swyllys }
13551161Swyllys } else { /* FAT32 */
13561161Swyllys /* volsize is in sectors */
13571161Swyllys if (volsize < FAT16_MAX_CLUSTERS) {
13581161Swyllys (void) fprintf(stderr,
13595121Sfrankho gettext("Requested size is too "
13605121Sfrankho "small for FAT32.\n"));
13611161Swyllys exit(4);
13621161Swyllys }
13631161Swyllys /* SPC must be a power of 2 */
13641161Swyllys for (spc = 1; spc <= 64; spc = spc * 2) {
13651161Swyllys if (volsize < (spc * FAT32_SUGGESTED_NCLUST))
13661161Swyllys break;
13671161Swyllys }
13681161Swyllys if (volsize > (spc * FAT32_MAX_CLUSTERS)) {
13691161Swyllys (void) fprintf(stderr,
13705121Sfrankho gettext("Requested size is too "
13715121Sfrankho "large for FAT32.\n"));
13720Sstevel@tonic-gate exit(4);
13730Sstevel@tonic-gate }
13740Sstevel@tonic-gate }
13750Sstevel@tonic-gate } else {
13761161Swyllys /*
13771161Swyllys * User gave the SPC as an explicit option,
13781161Swyllys * make sure it will work with the requested
13791161Swyllys * volume size.
13801161Swyllys */
13811161Swyllys int nclust;
13821161Swyllys
13830Sstevel@tonic-gate spc = SecPerClust;
13841161Swyllys nclust = volsize / spc;
13851161Swyllys
13861161Swyllys if (nclust <= FAT16_MAX_CLUSTERS && MakeFAT32) {
13875121Sfrankho (void) fprintf(stderr, gettext("Requested size is too "
13885121Sfrankho "small for FAT32.\n"));
13891161Swyllys exit(4);
13901161Swyllys }
13911161Swyllys if (!MakeFAT32) {
13921161Swyllys /* Determine if FAT12 or FAT16 */
13931161Swyllys if (nclust < FAT12_MAX_CLUSTERS)
13941161Swyllys newfat = 12;
13951161Swyllys else if (nclust < FAT16_MAX_CLUSTERS)
13961161Swyllys newfat = 16;
13971161Swyllys else {
13981161Swyllys (void) fprintf(stderr,
13995121Sfrankho gettext("Requested size is too "
14005121Sfrankho "small for FAT32.\n"));
14011161Swyllys exit(4);
14021161Swyllys }
14031161Swyllys }
14040Sstevel@tonic-gate }
14050Sstevel@tonic-gate
1406607Swyllys /*
1407607Swyllys * RootDirSectors = ((BPB_RootEntCnt * 32) +
1408607Swyllys * (BPB_BytsPerSec 1)) / BPB_BytsPerSec;
1409607Swyllys */
1410607Swyllys rds = ((wbpb->bpb.num_root_entries * 32) +
14115121Sfrankho (wbpb->bpb.bytes_sector - 1)) / wbpb->bpb.bytes_sector;
1412607Swyllys
14130Sstevel@tonic-gate if (GetBPF) {
14140Sstevel@tonic-gate if (MakeFAT32)
14150Sstevel@tonic-gate Fatentsize = 32;
14160Sstevel@tonic-gate else
14171161Swyllys Fatentsize = newfat;
14180Sstevel@tonic-gate } else {
14190Sstevel@tonic-gate Fatentsize = BitsPerFAT;
1420607Swyllys
1421607Swyllys if (Fatentsize == 12 &&
14225121Sfrankho (volsize - rds) >= DOS_F12MAXC * spc) {
14230Sstevel@tonic-gate /*
14241161Swyllys * If we don't have an input TTY, or we aren't
14251161Swyllys * really doing anything, then don't ask
14261161Swyllys * questions. Assume a yes answer to any
14271161Swyllys * questions we would ask.
14280Sstevel@tonic-gate */
14290Sstevel@tonic-gate if (Notreally || !isatty(fileno(stdin))) {
14305121Sfrankho (void) printf(
14310Sstevel@tonic-gate gettext("Volume too large for 12 bit FAT,"
14325121Sfrankho " increasing to 16 bit FAT size.\n"));
14335121Sfrankho (void) fflush(stdout);
14345121Sfrankho Fatentsize = 16;
14350Sstevel@tonic-gate } else {
14365121Sfrankho (void) printf(
14370Sstevel@tonic-gate gettext("Volume too large for a 12 bit FAT.\n"
14385121Sfrankho "Increase to 16 bit FAT "
14395121Sfrankho "and continue (y/n)? "));
14405121Sfrankho (void) fflush(stdout);
14415121Sfrankho if (yes())
14425121Sfrankho Fatentsize = 16;
14435121Sfrankho else
14445121Sfrankho exit(5);
14450Sstevel@tonic-gate }
14460Sstevel@tonic-gate }
14470Sstevel@tonic-gate }
14480Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = spc;
14490Sstevel@tonic-gate
14500Sstevel@tonic-gate if (!GetFsParams && FdiskFATsize < 0) {
14510Sstevel@tonic-gate (void) printf(
14520Sstevel@tonic-gate gettext("Cannot verify chosen/computed FAT "
14535121Sfrankho "entry size (%d bits) with FDISK table.\n"
14545121Sfrankho "FDISK table has an unknown file system "
14555121Sfrankho "type for this device. Giving up...\n"),
14565121Sfrankho Fatentsize, Fatentsize);
14570Sstevel@tonic-gate exit(6);
14580Sstevel@tonic-gate } else if (!GetFsParams && FdiskFATsize && FdiskFATsize != Fatentsize) {
14590Sstevel@tonic-gate (void) printf(
14600Sstevel@tonic-gate gettext("Chosen/computed FAT entry size (%d bits) "
14615121Sfrankho "does not match FDISK table (%d bits).\n"),
14625121Sfrankho Fatentsize, FdiskFATsize);
14630Sstevel@tonic-gate (void) printf(
14640Sstevel@tonic-gate gettext("Use -o fat=%d to build a FAT "
14655121Sfrankho "that matches the FDISK entry.\n"), FdiskFATsize);
14660Sstevel@tonic-gate exit(6);
14670Sstevel@tonic-gate }
14680Sstevel@tonic-gate set_fat_string(wbpb, Fatentsize);
1469607Swyllys /*
1470607Swyllys * Compure the FAT sizes according to algorithm from Microsoft:
1471607Swyllys *
1472607Swyllys * RootDirSectors = ((BPB_RootEntCnt * 32) +
1473607Swyllys * (BPB_BytsPerSec 1)) / BPB_BytsPerSec;
1474607Swyllys * TmpVal1 = DskSize - (BPB_ResvdSecCnt + RootDirSectors);
1475607Swyllys * TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs;
1476607Swyllys * If (FATType == FAT32)
1477607Swyllys * TmpVal2 = TmpVal2 / 2;
1478607Swyllys * FATSz = (TMPVal1 + (TmpVal2 1)) / TmpVal2;
1479607Swyllys * If (FATType == FAT32) {
1480607Swyllys * BPB_FATSz16 = 0;
1481607Swyllys * BPB_FATSz32 = FATSz;
1482607Swyllys * } else {
1483607Swyllys * BPB_FATSz16 = LOWORD(FATSz);
1484607Swyllys * // there is no BPB_FATSz32 in a FAT16 BPB
1485607Swyllys * }
1486607Swyllys */
1487607Swyllys tmpval1 = volsize - (wbpb->bpb.resv_sectors + rds);
1488607Swyllys
14895121Sfrankho tmpval2 = (256 * wbpb->bpb.sectors_per_cluster) + wbpb->bpb.num_fats;
1490607Swyllys
1491607Swyllys if (Fatentsize == 32)
1492607Swyllys tmpval2 = tmpval2 / 2;
1493607Swyllys
1494607Swyllys fatsz = (tmpval1 + (tmpval2 - 1)) / tmpval2;
14950Sstevel@tonic-gate
14960Sstevel@tonic-gate /* Compute a sector/fat figure */
14970Sstevel@tonic-gate switch (Fatentsize) {
14980Sstevel@tonic-gate case 32:
14990Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 0;
1500607Swyllys wbpb->bpb32.big_sectors_per_fat = fatsz;
1501607Swyllys if (Verbose)
15025121Sfrankho (void) printf("compute_cluster_size: Sectors per "
15035121Sfrankho "FAT32 = %d\n", wbpb->bpb32.big_sectors_per_fat);
15040Sstevel@tonic-gate break;
15050Sstevel@tonic-gate case 12:
15060Sstevel@tonic-gate default: /* 16 bit FAT */
1507607Swyllys wbpb->bpb.sectors_per_fat = (ushort_t)(fatsz & 0x0000FFFF);
1508607Swyllys if (Verbose)
15095121Sfrankho (void) printf("compute_cluster_size: Sectors per "
15105121Sfrankho "FAT16 = %d\n", wbpb->bpb.sectors_per_fat);
15110Sstevel@tonic-gate break;
15120Sstevel@tonic-gate }
15130Sstevel@tonic-gate }
15140Sstevel@tonic-gate
15150Sstevel@tonic-gate static
15160Sstevel@tonic-gate void
find_fixed_details(int fd,bpb_t * wbpb)15170Sstevel@tonic-gate find_fixed_details(int fd, bpb_t *wbpb)
15180Sstevel@tonic-gate {
15190Sstevel@tonic-gate struct dk_geom dginfo;
15200Sstevel@tonic-gate
15210Sstevel@tonic-gate /*
15220Sstevel@tonic-gate * Look up the last remaining bits of info we need
15230Sstevel@tonic-gate * that is specific to the hard drive using a disk ioctl.
15240Sstevel@tonic-gate */
15250Sstevel@tonic-gate if (GetSPT || GetTPC) {
15265121Sfrankho if (ioctl(fd, DKIOCG_VIRTGEOM, &dginfo) == -1 &&
15275121Sfrankho ioctl(fd, DKIOCG_PHYGEOM, &dginfo) == -1 &&
15285121Sfrankho ioctl(fd, DKIOCGGEOM, &dginfo) == -1) {
15295121Sfrankho (void) close(fd);
15305121Sfrankho perror(
15315121Sfrankho gettext("Drive geometry lookup (need "
15325121Sfrankho "tracks/cylinder and/or sectors/track"));
15335121Sfrankho exit(2);
15340Sstevel@tonic-gate }
15350Sstevel@tonic-gate }
15360Sstevel@tonic-gate
15370Sstevel@tonic-gate wbpb->bpb.heads = (GetTPC ? dginfo.dkg_nhead : TrkPerCyl);
15380Sstevel@tonic-gate wbpb->bpb.sectors_per_track = (GetSPT ? dginfo.dkg_nsect : SecPerTrk);
15390Sstevel@tonic-gate
15400Sstevel@tonic-gate if (Verbose) {
15410Sstevel@tonic-gate if (GetTPC) {
15425121Sfrankho (void) printf(
15435121Sfrankho gettext("DKIOCG determined number of heads = %d\n"),
15445121Sfrankho dginfo.dkg_nhead);
15450Sstevel@tonic-gate }
15460Sstevel@tonic-gate if (GetSPT) {
15475121Sfrankho (void) printf(
15485121Sfrankho gettext("DKIOCG determined sectors per track"
15495121Sfrankho " = %d\n"), dginfo.dkg_nsect);
15500Sstevel@tonic-gate }
15510Sstevel@tonic-gate }
15520Sstevel@tonic-gate
15530Sstevel@tonic-gate /*
15540Sstevel@tonic-gate * XXX - MAY need an additional flag (or flags) to set media
15550Sstevel@tonic-gate * and physical drive number fields. That in the case of weird
15560Sstevel@tonic-gate * floppies that have to go through 'nofdisk' route for formatting.
15570Sstevel@tonic-gate */
15580Sstevel@tonic-gate wbpb->bpb.media = 0xF8;
15590Sstevel@tonic-gate if (MakeFAT32)
15600Sstevel@tonic-gate wbpb->bpb.num_root_entries = 0;
15610Sstevel@tonic-gate else
15620Sstevel@tonic-gate wbpb->bpb.num_root_entries = 512;
15630Sstevel@tonic-gate wbpb->ebpb.phys_drive_num = 0x80;
15640Sstevel@tonic-gate compute_cluster_size(wbpb);
15650Sstevel@tonic-gate }
15660Sstevel@tonic-gate
15670Sstevel@tonic-gate static
15680Sstevel@tonic-gate char *
stat_actual_disk(char * diskname,struct stat * info,char ** suffix)15690Sstevel@tonic-gate stat_actual_disk(char *diskname, struct stat *info, char **suffix)
15700Sstevel@tonic-gate {
15710Sstevel@tonic-gate char *actualdisk;
15720Sstevel@tonic-gate
15730Sstevel@tonic-gate if (stat(diskname, info)) {
15740Sstevel@tonic-gate /*
15750Sstevel@tonic-gate * Device named on command line doesn't exist. That
15760Sstevel@tonic-gate * probably means there is a partition-specifying
15770Sstevel@tonic-gate * suffix attached to the actual disk name.
15780Sstevel@tonic-gate */
15790Sstevel@tonic-gate actualdisk = strtok(strdup(diskname), ":");
15800Sstevel@tonic-gate if (*suffix = strchr(diskname, ':'))
15810Sstevel@tonic-gate (*suffix)++;
15820Sstevel@tonic-gate
15830Sstevel@tonic-gate if (stat(actualdisk, info)) {
15840Sstevel@tonic-gate perror(actualdisk);
15850Sstevel@tonic-gate exit(2);
15860Sstevel@tonic-gate }
15870Sstevel@tonic-gate } else {
15880Sstevel@tonic-gate actualdisk = strdup(diskname);
15890Sstevel@tonic-gate }
15900Sstevel@tonic-gate
15910Sstevel@tonic-gate return (actualdisk);
15920Sstevel@tonic-gate }
15930Sstevel@tonic-gate
15940Sstevel@tonic-gate static
15950Sstevel@tonic-gate void
compute_file_area_size(bpb_t * wbpb)15960Sstevel@tonic-gate compute_file_area_size(bpb_t *wbpb)
15970Sstevel@tonic-gate {
1598607Swyllys int FATSz;
1599607Swyllys int TotSec;
1600607Swyllys int DataSec;
16015121Sfrankho int RootDirSectors =
16025121Sfrankho ((wbpb->bpb.num_root_entries * 32) + (wbpb->bpb.bytes_sector - 1)) /
16035121Sfrankho wbpb->bpb.bytes_sector;
16040Sstevel@tonic-gate
16050Sstevel@tonic-gate if (wbpb->bpb.sectors_per_fat) {
16060Sstevel@tonic-gate /*
16070Sstevel@tonic-gate * Good old FAT12 or FAT16
16080Sstevel@tonic-gate */
1609607Swyllys FATSz = wbpb->bpb.sectors_per_fat;
1610607Swyllys TotSec = wbpb->bpb.sectors_in_volume;
16110Sstevel@tonic-gate } else {
16120Sstevel@tonic-gate /*
16130Sstevel@tonic-gate * FAT32
16140Sstevel@tonic-gate */
1615607Swyllys FATSz = wbpb->bpb32.big_sectors_per_fat;
1616607Swyllys TotSec = wbpb->bpb.sectors_in_logical_volume;
16170Sstevel@tonic-gate }
16180Sstevel@tonic-gate
16195121Sfrankho DataSec = TotSec -
16205121Sfrankho (wbpb->bpb.resv_sectors + (wbpb->bpb.num_fats * FATSz) +
16215121Sfrankho RootDirSectors);
1622607Swyllys
1623607Swyllys
16240Sstevel@tonic-gate /*
16250Sstevel@tonic-gate * Now change sectors to clusters
16260Sstevel@tonic-gate */
1627607Swyllys TotalClusters = DataSec / wbpb->bpb.sectors_per_cluster;
16280Sstevel@tonic-gate
16290Sstevel@tonic-gate if (Verbose)
16300Sstevel@tonic-gate (void) printf(gettext("Disk has a file area of %d "
16310Sstevel@tonic-gate "allocation units,\neach with %d sectors = %d "
16320Sstevel@tonic-gate "bytes.\n"), TotalClusters, wbpb->bpb.sectors_per_cluster,
16330Sstevel@tonic-gate TotalClusters * wbpb->bpb.sectors_per_cluster * BPSEC);
16340Sstevel@tonic-gate }
16350Sstevel@tonic-gate
16360Sstevel@tonic-gate #ifndef i386
16370Sstevel@tonic-gate /*
16380Sstevel@tonic-gate * swap_pack_{bpb,bpb32,sebpb}cpy
16390Sstevel@tonic-gate *
16400Sstevel@tonic-gate * If not on an x86 we assume the structures making up the bpb
16410Sstevel@tonic-gate * were not packed and that longs and shorts need to be byte swapped
16420Sstevel@tonic-gate * (we've kept everything in host order up until now). A new architecture
16430Sstevel@tonic-gate * might not need to swap or might not need to pack, in which case
16440Sstevel@tonic-gate * new routines will have to be written. Of course if an architecture
16450Sstevel@tonic-gate * supports both packing and little-endian host order, it can follow the
16460Sstevel@tonic-gate * same path as the x86 code.
16470Sstevel@tonic-gate */
16480Sstevel@tonic-gate static
16490Sstevel@tonic-gate void
swap_pack_bpbcpy(struct _boot_sector * bsp,bpb_t * wbpb)16500Sstevel@tonic-gate swap_pack_bpbcpy(struct _boot_sector *bsp, bpb_t *wbpb)
16510Sstevel@tonic-gate {
16520Sstevel@tonic-gate uchar_t *fillp;
16530Sstevel@tonic-gate
16540Sstevel@tonic-gate fillp = (uchar_t *)&(bsp->bs_filler[ORIG_BPB_START_INDEX]);
16550Sstevel@tonic-gate
16560Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.bytes_sector);
16570Sstevel@tonic-gate *fillp++ = wbpb->bpb.sectors_per_cluster;
16580Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.resv_sectors);
16590Sstevel@tonic-gate *fillp++ = wbpb->bpb.num_fats;
16600Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.num_root_entries);
16610Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_in_volume);
16620Sstevel@tonic-gate *fillp++ = wbpb->bpb.media;
16630Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_per_fat);
16640Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_per_track);
16650Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.heads);
16660Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb.hidden_sectors);
16670Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb.sectors_in_logical_volume);
16680Sstevel@tonic-gate
16690Sstevel@tonic-gate *fillp++ = wbpb->ebpb.phys_drive_num;
16700Sstevel@tonic-gate *fillp++ = wbpb->ebpb.reserved;
16710Sstevel@tonic-gate *fillp++ = wbpb->ebpb.ext_signature;
16720Sstevel@tonic-gate store_32_bits(&fillp, wbpb->ebpb.volume_id);
16730Sstevel@tonic-gate (void) strncpy((char *)fillp, (char *)wbpb->ebpb.volume_label, 11);
16740Sstevel@tonic-gate fillp += 11;
16750Sstevel@tonic-gate (void) strncpy((char *)fillp, (char *)wbpb->ebpb.type, 8);
16760Sstevel@tonic-gate }
16770Sstevel@tonic-gate
16780Sstevel@tonic-gate static
16790Sstevel@tonic-gate void
swap_pack_bpb32cpy(struct _boot_sector32 * bsp,bpb_t * wbpb)16800Sstevel@tonic-gate swap_pack_bpb32cpy(struct _boot_sector32 *bsp, bpb_t *wbpb)
16810Sstevel@tonic-gate {
16820Sstevel@tonic-gate uchar_t *fillp;
16830Sstevel@tonic-gate int r;
16840Sstevel@tonic-gate
16850Sstevel@tonic-gate fillp = (uchar_t *)&(bsp->bs_filler[ORIG_BPB_START_INDEX]);
16860Sstevel@tonic-gate
16870Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.bytes_sector);
16880Sstevel@tonic-gate *fillp++ = wbpb->bpb.sectors_per_cluster;
16890Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.resv_sectors);
16900Sstevel@tonic-gate *fillp++ = wbpb->bpb.num_fats;
16910Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.num_root_entries);
16920Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_in_volume);
16930Sstevel@tonic-gate *fillp++ = wbpb->bpb.media;
16940Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_per_fat);
16950Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_per_track);
16960Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.heads);
16970Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb.hidden_sectors);
16980Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb.sectors_in_logical_volume);
16990Sstevel@tonic-gate
17000Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb32.big_sectors_per_fat);
17010Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb32.ext_flags);
17020Sstevel@tonic-gate *fillp++ = wbpb->bpb32.fs_vers_lo;
17030Sstevel@tonic-gate *fillp++ = wbpb->bpb32.fs_vers_hi;
17040Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb32.root_dir_clust);
17050Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb32.fsinfosec);
17060Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb32.backupboot);
17070Sstevel@tonic-gate for (r = 0; r < 6; r++)
17080Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb32.reserved[r]);
17090Sstevel@tonic-gate
17100Sstevel@tonic-gate *fillp++ = wbpb->ebpb.phys_drive_num;
17110Sstevel@tonic-gate *fillp++ = wbpb->ebpb.reserved;
17120Sstevel@tonic-gate *fillp++ = wbpb->ebpb.ext_signature;
17130Sstevel@tonic-gate store_32_bits(&fillp, wbpb->ebpb.volume_id);
17140Sstevel@tonic-gate (void) strncpy((char *)fillp, (char *)wbpb->ebpb.volume_label, 11);
17150Sstevel@tonic-gate fillp += 11;
17160Sstevel@tonic-gate (void) strncpy((char *)fillp, (char *)wbpb->ebpb.type, 8);
17170Sstevel@tonic-gate }
17180Sstevel@tonic-gate
17190Sstevel@tonic-gate static
17200Sstevel@tonic-gate void
swap_pack_sebpbcpy(struct _boot_sector * bsp,bpb_t * wbpb)17210Sstevel@tonic-gate swap_pack_sebpbcpy(struct _boot_sector *bsp, bpb_t *wbpb)
17220Sstevel@tonic-gate {
17230Sstevel@tonic-gate uchar_t *fillp;
17240Sstevel@tonic-gate
17250Sstevel@tonic-gate fillp = bsp->bs_sun_bpb;
17260Sstevel@tonic-gate store_16_bits(&fillp, wbpb->sunbpb.bs_offset_high);
17270Sstevel@tonic-gate store_16_bits(&fillp, wbpb->sunbpb.bs_offset_low);
17280Sstevel@tonic-gate }
17290Sstevel@tonic-gate
17300Sstevel@tonic-gate static
17310Sstevel@tonic-gate void
swap_pack_grabbpb(bpb_t * wbpb,struct _boot_sector * bsp)17320Sstevel@tonic-gate swap_pack_grabbpb(bpb_t *wbpb, struct _boot_sector *bsp)
17330Sstevel@tonic-gate {
17340Sstevel@tonic-gate uchar_t *grabp;
17350Sstevel@tonic-gate
17360Sstevel@tonic-gate grabp = (uchar_t *)&(bsp->bs_filler[ORIG_BPB_START_INDEX]);
17370Sstevel@tonic-gate
17380Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.bytes_sector))[1] = *grabp++;
17390Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.bytes_sector))[0] = *grabp++;
17400Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = *grabp++;
17410Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.resv_sectors))[1] = *grabp++;
17420Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.resv_sectors))[0] = *grabp++;
17430Sstevel@tonic-gate wbpb->bpb.num_fats = *grabp++;
17440Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.num_root_entries))[1] = *grabp++;
17450Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.num_root_entries))[0] = *grabp++;
17460Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_volume))[1] = *grabp++;
17470Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_volume))[0] = *grabp++;
17480Sstevel@tonic-gate wbpb->bpb.media = *grabp++;
17490Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_per_fat))[1] = *grabp++;
17500Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_per_fat))[0] = *grabp++;
17510Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_per_track))[1] = *grabp++;
17520Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_per_track))[0] = *grabp++;
17530Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.heads))[1] = *grabp++;
17540Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.heads))[0] = *grabp++;
17550Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.hidden_sectors))[3] = *grabp++;
17560Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.hidden_sectors))[2] = *grabp++;
17570Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.hidden_sectors))[1] = *grabp++;
17580Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.hidden_sectors))[0] = *grabp++;
17590Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[3] = *grabp++;
17600Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[2] = *grabp++;
17610Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[1] = *grabp++;
17620Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[0] = *grabp++;
17630Sstevel@tonic-gate wbpb->ebpb.phys_drive_num = *grabp++;
17640Sstevel@tonic-gate wbpb->ebpb.reserved = *grabp++;
17650Sstevel@tonic-gate wbpb->ebpb.ext_signature = *grabp++;
17660Sstevel@tonic-gate ((uchar_t *)&(wbpb->ebpb.volume_id))[3] = *grabp++;
17670Sstevel@tonic-gate ((uchar_t *)&(wbpb->ebpb.volume_id))[2] = *grabp++;
17680Sstevel@tonic-gate ((uchar_t *)&(wbpb->ebpb.volume_id))[1] = *grabp++;
17690Sstevel@tonic-gate ((uchar_t *)&(wbpb->ebpb.volume_id))[0] = *grabp++;
17700Sstevel@tonic-gate
17710Sstevel@tonic-gate (void) strncpy((char *)wbpb->ebpb.volume_label, (char *)grabp, 11);
17720Sstevel@tonic-gate grabp += 11;
17730Sstevel@tonic-gate (void) strncpy((char *)wbpb->ebpb.type, (char *)grabp, 8);
17740Sstevel@tonic-gate }
17750Sstevel@tonic-gate
17760Sstevel@tonic-gate static
17770Sstevel@tonic-gate void
swap_pack_grabsebpb(bpb_t * wbpb,struct _boot_sector * bsp)17780Sstevel@tonic-gate swap_pack_grabsebpb(bpb_t *wbpb, struct _boot_sector *bsp)
17790Sstevel@tonic-gate {
17800Sstevel@tonic-gate uchar_t *grabp;
17810Sstevel@tonic-gate
17820Sstevel@tonic-gate grabp = bsp->bs_sun_bpb;
17830Sstevel@tonic-gate ((uchar_t *)&(wbpb->sunbpb.bs_offset_high))[1] = *grabp++;
17840Sstevel@tonic-gate ((uchar_t *)&(wbpb->sunbpb.bs_offset_high))[0] = *grabp++;
17850Sstevel@tonic-gate ((uchar_t *)&(wbpb->sunbpb.bs_offset_low))[1] = *grabp++;
17860Sstevel@tonic-gate ((uchar_t *)&(wbpb->sunbpb.bs_offset_low))[0] = *grabp++;
17870Sstevel@tonic-gate }
17880Sstevel@tonic-gate
17890Sstevel@tonic-gate static
17900Sstevel@tonic-gate void
swap_pack_grab32bpb(bpb_t * wbpb,struct _boot_sector * bsp)17910Sstevel@tonic-gate swap_pack_grab32bpb(bpb_t *wbpb, struct _boot_sector *bsp)
17920Sstevel@tonic-gate {
17930Sstevel@tonic-gate uchar_t *grabp;
17940Sstevel@tonic-gate
17950Sstevel@tonic-gate grabp = (uchar_t *)&(bsp->bs_filler[BPB_32_START_INDEX]);
17960Sstevel@tonic-gate
17970Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[3] = *grabp++;
17980Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[2] = *grabp++;
17990Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[1] = *grabp++;
18000Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[0] = *grabp++;
18010Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.ext_flags))[1] = *grabp++;
18020Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.ext_flags))[0] = *grabp++;
18030Sstevel@tonic-gate wbpb->bpb32.fs_vers_lo = *grabp++;
18040Sstevel@tonic-gate wbpb->bpb32.fs_vers_hi = *grabp++;
18050Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.root_dir_clust))[3] = *grabp++;
18060Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.root_dir_clust))[2] = *grabp++;
18070Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.root_dir_clust))[1] = *grabp++;
18080Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.root_dir_clust))[0] = *grabp++;
18090Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.fsinfosec))[1] = *grabp++;
18100Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.fsinfosec))[0] = *grabp++;
18110Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.backupboot))[1] = *grabp++;
18120Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.backupboot))[0] = *grabp++;
18130Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[0]))[1] = *grabp++;
18140Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[0]))[0] = *grabp++;
18150Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[1]))[1] = *grabp++;
18160Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[1]))[0] = *grabp++;
18170Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[2]))[1] = *grabp++;
18180Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[2]))[0] = *grabp++;
18190Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[3]))[1] = *grabp++;
18200Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[3]))[0] = *grabp++;
18210Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[4]))[1] = *grabp++;
18220Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[4]))[0] = *grabp++;
18230Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[5]))[1] = *grabp++;
18240Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[5]))[0] = *grabp++;
18250Sstevel@tonic-gate }
18260Sstevel@tonic-gate #endif /* ! i386 */
18270Sstevel@tonic-gate
18280Sstevel@tonic-gate static
18290Sstevel@tonic-gate void
dashm_bail(int fd)18300Sstevel@tonic-gate dashm_bail(int fd)
18310Sstevel@tonic-gate {
18320Sstevel@tonic-gate (void) fprintf(stderr,
18335121Sfrankho gettext("This media does not appear to be "
18345121Sfrankho "formatted with a FAT file system.\n"));
18350Sstevel@tonic-gate (void) close(fd);
18360Sstevel@tonic-gate exit(6);
18370Sstevel@tonic-gate }
18380Sstevel@tonic-gate
18390Sstevel@tonic-gate /*
18400Sstevel@tonic-gate * read_existing_bpb
18410Sstevel@tonic-gate *
18420Sstevel@tonic-gate * Grab the first sector, which we think is a bios parameter block.
18430Sstevel@tonic-gate * If it looks bad, bail. Otherwise fill in the parameter struct
18440Sstevel@tonic-gate * fields that matter.
18450Sstevel@tonic-gate */
18460Sstevel@tonic-gate static
18470Sstevel@tonic-gate void
read_existing_bpb(int fd,bpb_t * wbpb)18480Sstevel@tonic-gate read_existing_bpb(int fd, bpb_t *wbpb)
18490Sstevel@tonic-gate {
18500Sstevel@tonic-gate boot_sector_t ubpb;
18510Sstevel@tonic-gate
18520Sstevel@tonic-gate if (read(fd, ubpb.buf, BPSEC) < BPSEC) {
18530Sstevel@tonic-gate perror(gettext("Read BIOS parameter block "
18545121Sfrankho "from previously formatted media"));
18550Sstevel@tonic-gate (void) close(fd);
18560Sstevel@tonic-gate exit(6);
18570Sstevel@tonic-gate }
18580Sstevel@tonic-gate
18590Sstevel@tonic-gate if (ltohs(ubpb.mb.signature) != BOOTSECSIG) {
18600Sstevel@tonic-gate dashm_bail(fd);
18610Sstevel@tonic-gate }
18620Sstevel@tonic-gate
18630Sstevel@tonic-gate #ifdef i386
18640Sstevel@tonic-gate (void) memcpy(&(wbpb->bpb), &(ubpb.bs.bs_front.bs_bpb),
18655121Sfrankho sizeof (wbpb->bpb));
18660Sstevel@tonic-gate (void) memcpy(&(wbpb->ebpb), &(ubpb.bs.bs_ebpb), sizeof (wbpb->ebpb));
18670Sstevel@tonic-gate #else
18680Sstevel@tonic-gate swap_pack_grabbpb(wbpb, &(ubpb.bs));
18690Sstevel@tonic-gate #endif
18700Sstevel@tonic-gate if (SunBPBfields) {
18710Sstevel@tonic-gate #ifdef i386
18720Sstevel@tonic-gate (void) memcpy(&(wbpb->sunbpb), &(ubpb.bs.bs_sebpb),
18735121Sfrankho sizeof (wbpb->sunbpb));
18740Sstevel@tonic-gate #else
18750Sstevel@tonic-gate swap_pack_grabsebpb(wbpb, &(ubpb.bs));
18760Sstevel@tonic-gate #endif
18770Sstevel@tonic-gate }
18780Sstevel@tonic-gate if (wbpb->bpb.bytes_sector != BPSEC) {
18790Sstevel@tonic-gate (void) fprintf(stderr,
18800Sstevel@tonic-gate gettext("Bogus bytes per sector value.\n"));
18810Sstevel@tonic-gate if (!powerofx_le_y(2, BPSEC * 8, wbpb->bpb.bytes_sector)) {
18820Sstevel@tonic-gate (void) fprintf(stderr,
18830Sstevel@tonic-gate gettext("The device name may be missing a "
18845121Sfrankho "logical drive specifier.\n"));
18850Sstevel@tonic-gate (void) close(fd);
18860Sstevel@tonic-gate exit(6);
18870Sstevel@tonic-gate } else {
18880Sstevel@tonic-gate (void) fprintf(stderr,
18890Sstevel@tonic-gate gettext("Do not know how to build FATs with a\n"
18905121Sfrankho "non-standard sector size. Standard "
18915121Sfrankho "size is %d bytes,\nyour sector size "
18925121Sfrankho "is %d bytes.\n"), BPSEC,
18935121Sfrankho wbpb->bpb.bytes_sector);
18940Sstevel@tonic-gate (void) close(fd);
18950Sstevel@tonic-gate exit(6);
18960Sstevel@tonic-gate }
18970Sstevel@tonic-gate }
18980Sstevel@tonic-gate if (!(powerofx_le_y(2, 128, wbpb->bpb.sectors_per_cluster))) {
18990Sstevel@tonic-gate (void) fprintf(stderr,
19000Sstevel@tonic-gate gettext("Bogus sectors per cluster value.\n"));
19010Sstevel@tonic-gate (void) fprintf(stderr,
19020Sstevel@tonic-gate gettext("The device name may be missing a "
19035121Sfrankho "logical drive specifier.\n"));
19040Sstevel@tonic-gate (void) close(fd);
19050Sstevel@tonic-gate exit(6);
19060Sstevel@tonic-gate }
19070Sstevel@tonic-gate
19080Sstevel@tonic-gate if (wbpb->bpb.sectors_per_fat == 0) {
19090Sstevel@tonic-gate #ifdef i386
19100Sstevel@tonic-gate (void) memcpy(&(wbpb->bpb32), &(ubpb.bs32.bs_bpb32),
19115121Sfrankho sizeof (wbpb->bpb32));
19120Sstevel@tonic-gate #else
19130Sstevel@tonic-gate swap_pack_grab32bpb(wbpb, &(ubpb.bs));
19140Sstevel@tonic-gate #endif
19150Sstevel@tonic-gate compute_file_area_size(wbpb);
19160Sstevel@tonic-gate if ((wbpb->bpb32.big_sectors_per_fat * BPSEC / 4) >=
19170Sstevel@tonic-gate TotalClusters) {
19180Sstevel@tonic-gate MakeFAT32 = 1;
19190Sstevel@tonic-gate } else {
19200Sstevel@tonic-gate dashm_bail(fd);
19210Sstevel@tonic-gate }
19220Sstevel@tonic-gate } else {
19230Sstevel@tonic-gate compute_file_area_size(wbpb);
19240Sstevel@tonic-gate }
19250Sstevel@tonic-gate }
19260Sstevel@tonic-gate
19270Sstevel@tonic-gate /*
19280Sstevel@tonic-gate * compare_existing_with_computed
19290Sstevel@tonic-gate *
19300Sstevel@tonic-gate * We use this function when we the user specifies the -m option.
19310Sstevel@tonic-gate * We compute and look up things like we would if they had asked
19320Sstevel@tonic-gate * us to make the fs, and compare that to what's already layed down
19330Sstevel@tonic-gate * in the existing fs. If there's a difference we can tell them what
19340Sstevel@tonic-gate * options to specify in order to reproduce their existing layout.
19350Sstevel@tonic-gate * Note that they still may not get an exact duplicate, because we
19360Sstevel@tonic-gate * don't, for example, preserve their existing boot code. We think
19370Sstevel@tonic-gate * we've got all the fields that matter covered, though.
19380Sstevel@tonic-gate *
19390Sstevel@tonic-gate * XXX - We're basically ignoring sbpb at this point. I'm unsure
19400Sstevel@tonic-gate * if we'll ever care about those fields, in terms of the -m option.
19410Sstevel@tonic-gate */
19420Sstevel@tonic-gate static
19430Sstevel@tonic-gate void
compare_existing_with_computed(int fd,char * suffix,bpb_t * wbpb,int * prtsize,int * prtspc,int * prtbpf,int * prtnsect,int * prtntrk,int * prtfdisk,int * prthidden,int * prtrsrvd,int * dashos)19440Sstevel@tonic-gate compare_existing_with_computed(int fd, char *suffix,
19450Sstevel@tonic-gate bpb_t *wbpb, int *prtsize, int *prtspc, int *prtbpf, int *prtnsect,
19460Sstevel@tonic-gate int *prtntrk, int *prtfdisk, int *prthidden, int *prtrsrvd, int *dashos)
19470Sstevel@tonic-gate {
19480Sstevel@tonic-gate struct dk_geom dginfo;
19490Sstevel@tonic-gate struct fd_char fdchar;
19500Sstevel@tonic-gate bpb_t compare;
19510Sstevel@tonic-gate int fd_ioctl_worked = 0;
19520Sstevel@tonic-gate int fatents;
19530Sstevel@tonic-gate
19540Sstevel@tonic-gate /*
19550Sstevel@tonic-gate * For all non-floppy cases we expect to find a 16-bit FAT
19560Sstevel@tonic-gate */
19570Sstevel@tonic-gate int expectfatsize = 16;
19580Sstevel@tonic-gate
19590Sstevel@tonic-gate compare = *wbpb;
19600Sstevel@tonic-gate
19610Sstevel@tonic-gate if (!suffix) {
19620Sstevel@tonic-gate if (ioctl(fd, FDIOGCHAR, &fdchar) != -1) {
19630Sstevel@tonic-gate expectfatsize = 12;
19640Sstevel@tonic-gate fd_ioctl_worked++;
19650Sstevel@tonic-gate }
19660Sstevel@tonic-gate }
19670Sstevel@tonic-gate
19680Sstevel@tonic-gate if (fd_ioctl_worked) {
19690Sstevel@tonic-gate #ifdef sparc
19700Sstevel@tonic-gate fdchar.fdc_medium = 3;
19710Sstevel@tonic-gate #endif
19720Sstevel@tonic-gate GetSize = GetSPT = GetSPC = GetTPC = GetBPF = 1;
19730Sstevel@tonic-gate lookup_floppy(&fdchar, &compare);
19740Sstevel@tonic-gate if (compare.bpb.heads != wbpb->bpb.heads) {
19750Sstevel@tonic-gate (*prtntrk)++;
19760Sstevel@tonic-gate (*dashos)++;
19770Sstevel@tonic-gate }
19780Sstevel@tonic-gate if (compare.bpb.sectors_per_track !=
19790Sstevel@tonic-gate wbpb->bpb.sectors_per_track) {
19800Sstevel@tonic-gate (*prtnsect)++;
19810Sstevel@tonic-gate (*dashos)++;
19820Sstevel@tonic-gate }
19830Sstevel@tonic-gate } else {
19840Sstevel@tonic-gate int dk_ioctl_worked = 1;
19850Sstevel@tonic-gate
19860Sstevel@tonic-gate if (!suffix) {
19870Sstevel@tonic-gate (*prtfdisk)++;
19880Sstevel@tonic-gate (*prtsize)++;
19890Sstevel@tonic-gate *dashos += 2;
19900Sstevel@tonic-gate }
19915121Sfrankho if (ioctl(fd, DKIOCG_VIRTGEOM, &dginfo) == -1 &&
19925121Sfrankho ioctl(fd, DKIOCG_PHYGEOM, &dginfo) == -1 &&
19935121Sfrankho ioctl(fd, DKIOCGGEOM, &dginfo) == -1) {
19945121Sfrankho *prtnsect = *prtntrk = 1;
19955121Sfrankho *dashos += 2;
19965121Sfrankho dk_ioctl_worked = 0;
19970Sstevel@tonic-gate }
19980Sstevel@tonic-gate if (dk_ioctl_worked) {
19990Sstevel@tonic-gate if (dginfo.dkg_nhead != wbpb->bpb.heads) {
20000Sstevel@tonic-gate (*prtntrk)++;
20010Sstevel@tonic-gate (*dashos)++;
20020Sstevel@tonic-gate }
20030Sstevel@tonic-gate if (dginfo.dkg_nsect !=
20040Sstevel@tonic-gate wbpb->bpb.sectors_per_track) {
20050Sstevel@tonic-gate (*prtnsect)++;
20060Sstevel@tonic-gate (*dashos)++;
20070Sstevel@tonic-gate }
20080Sstevel@tonic-gate }
20090Sstevel@tonic-gate GetBPF = GetSPC = 1;
20100Sstevel@tonic-gate compute_cluster_size(&compare);
20110Sstevel@tonic-gate }
20120Sstevel@tonic-gate
20130Sstevel@tonic-gate if (!*prtfdisk && TotSize != wbpb->bpb.sectors_in_volume &&
20145121Sfrankho TotSize != wbpb->bpb.sectors_in_logical_volume) {
20150Sstevel@tonic-gate (*dashos)++;
20160Sstevel@tonic-gate (*prtsize)++;
20170Sstevel@tonic-gate }
20180Sstevel@tonic-gate
20190Sstevel@tonic-gate if (compare.bpb.sectors_per_cluster != wbpb->bpb.sectors_per_cluster) {
20200Sstevel@tonic-gate (*dashos)++;
20210Sstevel@tonic-gate (*prtspc)++;
20220Sstevel@tonic-gate }
20230Sstevel@tonic-gate
20240Sstevel@tonic-gate if (compare.bpb.hidden_sectors != wbpb->bpb.hidden_sectors) {
20250Sstevel@tonic-gate (*dashos)++;
20260Sstevel@tonic-gate (*prthidden)++;
20270Sstevel@tonic-gate }
20280Sstevel@tonic-gate
20290Sstevel@tonic-gate if (compare.bpb.resv_sectors != wbpb->bpb.resv_sectors) {
20300Sstevel@tonic-gate (*dashos)++;
20310Sstevel@tonic-gate (*prtrsrvd)++;
20320Sstevel@tonic-gate }
20330Sstevel@tonic-gate
20340Sstevel@tonic-gate /*
20350Sstevel@tonic-gate * Compute approximate Fatentsize. It's approximate because the
20360Sstevel@tonic-gate * size of the FAT may not be exactly a multiple of the number of
20370Sstevel@tonic-gate * clusters. It should be close, though.
20380Sstevel@tonic-gate */
20390Sstevel@tonic-gate if (MakeFAT32) {
20400Sstevel@tonic-gate Fatentsize = 32;
20410Sstevel@tonic-gate (*dashos)++;
20420Sstevel@tonic-gate (*prtbpf)++;
20430Sstevel@tonic-gate } else {
20440Sstevel@tonic-gate fatents = wbpb->bpb.sectors_per_fat * BPSEC * 2 / 3;
20450Sstevel@tonic-gate if (fatents >= TotalClusters && wbpb->ebpb.type[4] == '2')
20460Sstevel@tonic-gate Fatentsize = 12;
20470Sstevel@tonic-gate else
20480Sstevel@tonic-gate Fatentsize = 16;
20490Sstevel@tonic-gate if (Fatentsize != expectfatsize) {
20500Sstevel@tonic-gate (*dashos)++;
20510Sstevel@tonic-gate (*prtbpf)++;
20520Sstevel@tonic-gate }
20530Sstevel@tonic-gate }
20540Sstevel@tonic-gate }
20550Sstevel@tonic-gate
20560Sstevel@tonic-gate static
20570Sstevel@tonic-gate void
print_reproducing_command(int fd,char * actualdisk,char * suffix,bpb_t * wbpb)20580Sstevel@tonic-gate print_reproducing_command(int fd, char *actualdisk, char *suffix, bpb_t *wbpb)
20590Sstevel@tonic-gate {
20600Sstevel@tonic-gate int needcomma = 0;
20610Sstevel@tonic-gate int prthidden = 0;
20620Sstevel@tonic-gate int prtrsrvd = 0;
20630Sstevel@tonic-gate int prtfdisk = 0;
20640Sstevel@tonic-gate int prtnsect = 0;
20650Sstevel@tonic-gate int prtntrk = 0;
20660Sstevel@tonic-gate int prtsize = 0;
20670Sstevel@tonic-gate int prtbpf = 0;
20680Sstevel@tonic-gate int prtspc = 0;
20690Sstevel@tonic-gate int dashos = 0;
20700Sstevel@tonic-gate int ll, i;
20710Sstevel@tonic-gate
20720Sstevel@tonic-gate compare_existing_with_computed(fd, suffix, wbpb,
20730Sstevel@tonic-gate &prtsize, &prtspc, &prtbpf, &prtnsect, &prtntrk,
20740Sstevel@tonic-gate &prtfdisk, &prthidden, &prtrsrvd, &dashos);
20750Sstevel@tonic-gate
20760Sstevel@tonic-gate /*
20770Sstevel@tonic-gate * Print out the command line they can use to reproduce the
20780Sstevel@tonic-gate * file system.
20790Sstevel@tonic-gate */
20800Sstevel@tonic-gate (void) printf("mkfs -F pcfs");
20810Sstevel@tonic-gate
20820Sstevel@tonic-gate ll = min(11, (int)strlen((char *)wbpb->ebpb.volume_label));
20830Sstevel@tonic-gate /*
20840Sstevel@tonic-gate * First, eliminate trailing spaces. Now compare the name against
20850Sstevel@tonic-gate * our default label. If there's a match we don't need to print
20860Sstevel@tonic-gate * any label info.
20870Sstevel@tonic-gate */
20880Sstevel@tonic-gate i = ll;
20895121Sfrankho while (wbpb->ebpb.volume_label[--i] == ' ')
20905121Sfrankho ;
20910Sstevel@tonic-gate ll = i;
20920Sstevel@tonic-gate
20930Sstevel@tonic-gate if (ll == strlen(DEFAULT_LABEL) - 1) {
20940Sstevel@tonic-gate char cmpbuf[11];
20950Sstevel@tonic-gate
20960Sstevel@tonic-gate (void) strcpy(cmpbuf, DEFAULT_LABEL);
20970Sstevel@tonic-gate for (i = ll; i >= 0; i--) {
20980Sstevel@tonic-gate if (cmpbuf[i] !=
20990Sstevel@tonic-gate toupper((int)(wbpb->ebpb.volume_label[i]))) {
21000Sstevel@tonic-gate break;
21010Sstevel@tonic-gate }
21020Sstevel@tonic-gate }
21030Sstevel@tonic-gate if (i < 0)
21040Sstevel@tonic-gate ll = i;
21050Sstevel@tonic-gate }
21060Sstevel@tonic-gate
21070Sstevel@tonic-gate if (ll >= 0) {
21080Sstevel@tonic-gate (void) printf(" -o ");
21090Sstevel@tonic-gate (void) printf("b=\"");
21100Sstevel@tonic-gate for (i = 0; i <= ll; i++) {
21110Sstevel@tonic-gate (void) printf("%c", wbpb->ebpb.volume_label[i]);
21120Sstevel@tonic-gate }
21130Sstevel@tonic-gate (void) printf("\"");
21140Sstevel@tonic-gate needcomma++;
21150Sstevel@tonic-gate } else if (dashos) {
21160Sstevel@tonic-gate (void) printf(" -o ");
21170Sstevel@tonic-gate }
21180Sstevel@tonic-gate
21190Sstevel@tonic-gate #define NEXT_DASH_O dashos--; needcomma++; continue
21200Sstevel@tonic-gate
21210Sstevel@tonic-gate while (dashos) {
21220Sstevel@tonic-gate if (needcomma) {
21230Sstevel@tonic-gate (void) printf(",");
21240Sstevel@tonic-gate needcomma = 0;
21250Sstevel@tonic-gate }
21260Sstevel@tonic-gate if (prtfdisk) {
21270Sstevel@tonic-gate (void) printf("nofdisk");
21280Sstevel@tonic-gate prtfdisk--;
21290Sstevel@tonic-gate NEXT_DASH_O;
21300Sstevel@tonic-gate }
21310Sstevel@tonic-gate if (prtsize) {
21320Sstevel@tonic-gate (void) printf("size=%u", wbpb->bpb.sectors_in_volume ?
21330Sstevel@tonic-gate wbpb->bpb.sectors_in_volume :
21340Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume);
21350Sstevel@tonic-gate prtsize--;
21360Sstevel@tonic-gate NEXT_DASH_O;
21370Sstevel@tonic-gate }
21380Sstevel@tonic-gate if (prtnsect) {
21390Sstevel@tonic-gate (void) printf("nsect=%d", wbpb->bpb.sectors_per_track);
21400Sstevel@tonic-gate prtnsect--;
21410Sstevel@tonic-gate NEXT_DASH_O;
21420Sstevel@tonic-gate }
21430Sstevel@tonic-gate if (prtspc) {
21440Sstevel@tonic-gate (void) printf("spc=%d", wbpb->bpb.sectors_per_cluster);
21450Sstevel@tonic-gate prtspc--;
21460Sstevel@tonic-gate NEXT_DASH_O;
21470Sstevel@tonic-gate }
21480Sstevel@tonic-gate if (prtntrk) {
21490Sstevel@tonic-gate (void) printf("ntrack=%d", wbpb->bpb.heads);
21500Sstevel@tonic-gate prtntrk--;
21510Sstevel@tonic-gate NEXT_DASH_O;
21520Sstevel@tonic-gate }
21530Sstevel@tonic-gate if (prtbpf) {
21540Sstevel@tonic-gate (void) printf("fat=%d", Fatentsize);
21550Sstevel@tonic-gate prtbpf--;
21560Sstevel@tonic-gate NEXT_DASH_O;
21570Sstevel@tonic-gate }
21580Sstevel@tonic-gate if (prthidden) {
21590Sstevel@tonic-gate (void) printf("hidden=%u", wbpb->bpb.hidden_sectors);
21600Sstevel@tonic-gate prthidden--;
21610Sstevel@tonic-gate NEXT_DASH_O;
21620Sstevel@tonic-gate }
21630Sstevel@tonic-gate if (prtrsrvd) {
21640Sstevel@tonic-gate (void) printf("reserve=%d", wbpb->bpb.resv_sectors);
21650Sstevel@tonic-gate prtrsrvd--;
21660Sstevel@tonic-gate NEXT_DASH_O;
21670Sstevel@tonic-gate }
21680Sstevel@tonic-gate }
21690Sstevel@tonic-gate
21700Sstevel@tonic-gate (void) printf(" %s%c%c\n", actualdisk,
21710Sstevel@tonic-gate suffix ? ':' : '\0', suffix ? *suffix : '\0');
21720Sstevel@tonic-gate }
21730Sstevel@tonic-gate
21740Sstevel@tonic-gate /*
21750Sstevel@tonic-gate * open_and_examine
21760Sstevel@tonic-gate *
21770Sstevel@tonic-gate * Open the requested 'dev_name'. Seek to point where
21780Sstevel@tonic-gate * we'd expect to find boot sectors, etc., based on any ':partition'
21790Sstevel@tonic-gate * attachments to the dev_name.
21800Sstevel@tonic-gate *
21810Sstevel@tonic-gate * Examine the fields of any existing boot sector and display best
21820Sstevel@tonic-gate * approximation of how this fs could be reproduced with this command.
21830Sstevel@tonic-gate */
21840Sstevel@tonic-gate static
21850Sstevel@tonic-gate int
open_and_examine(char * dn,bpb_t * wbpb)21860Sstevel@tonic-gate open_and_examine(char *dn, bpb_t *wbpb)
21870Sstevel@tonic-gate {
21880Sstevel@tonic-gate struct stat di;
21890Sstevel@tonic-gate off64_t ignored;
21900Sstevel@tonic-gate char *actualdisk = NULL;
21910Sstevel@tonic-gate char *suffix = NULL;
21920Sstevel@tonic-gate int fd;
2193*9889SLarry.Liu@Sun.COM struct dk_minfo dkminfo;
21940Sstevel@tonic-gate
21950Sstevel@tonic-gate if (Verbose)
21960Sstevel@tonic-gate (void) printf(gettext("Opening destination device/file.\n"));
21970Sstevel@tonic-gate
21980Sstevel@tonic-gate actualdisk = stat_actual_disk(dn, &di, &suffix);
21990Sstevel@tonic-gate
22000Sstevel@tonic-gate /*
22010Sstevel@tonic-gate * Destination exists, now find more about it.
22020Sstevel@tonic-gate */
22030Sstevel@tonic-gate if (!(S_ISCHR(di.st_mode))) {
22040Sstevel@tonic-gate (void) fprintf(stderr,
22050Sstevel@tonic-gate gettext("\n%s: device name must be a "
22065121Sfrankho "character special device.\n"), actualdisk);
22070Sstevel@tonic-gate exit(2);
22083925Sartem } else if ((fd = open(actualdisk, O_RDWR)) < 0) {
22090Sstevel@tonic-gate perror(actualdisk);
22100Sstevel@tonic-gate exit(2);
22110Sstevel@tonic-gate }
22120Sstevel@tonic-gate
22130Sstevel@tonic-gate /*
2214*9889SLarry.Liu@Sun.COM * Check the media sector size
2215*9889SLarry.Liu@Sun.COM */
2216*9889SLarry.Liu@Sun.COM if (ioctl(fd, DKIOCGMEDIAINFO, &dkminfo) != -1) {
2217*9889SLarry.Liu@Sun.COM if (dkminfo.dki_lbsize != 0 &&
2218*9889SLarry.Liu@Sun.COM ISP2(dkminfo.dki_lbsize / DEV_BSIZE) &&
2219*9889SLarry.Liu@Sun.COM dkminfo.dki_lbsize != DEV_BSIZE) {
2220*9889SLarry.Liu@Sun.COM (void) fprintf(stderr,
2221*9889SLarry.Liu@Sun.COM gettext("The device sector size %u is not "
2222*9889SLarry.Liu@Sun.COM "supported by pcfs!\n"), dkminfo.dki_lbsize);
2223*9889SLarry.Liu@Sun.COM (void) close(fd);
2224*9889SLarry.Liu@Sun.COM exit(1);
2225*9889SLarry.Liu@Sun.COM }
2226*9889SLarry.Liu@Sun.COM }
2227*9889SLarry.Liu@Sun.COM
2228*9889SLarry.Liu@Sun.COM /*
22290Sstevel@tonic-gate * Find appropriate partition if we were requested to do so.
22300Sstevel@tonic-gate */
22310Sstevel@tonic-gate if (suffix && !(seek_partn(fd, suffix, wbpb, &ignored))) {
22320Sstevel@tonic-gate (void) close(fd);
22330Sstevel@tonic-gate exit(2);
22340Sstevel@tonic-gate }
22350Sstevel@tonic-gate
22360Sstevel@tonic-gate read_existing_bpb(fd, wbpb);
22370Sstevel@tonic-gate print_reproducing_command(fd, actualdisk, suffix, wbpb);
22380Sstevel@tonic-gate
22390Sstevel@tonic-gate return (fd);
22400Sstevel@tonic-gate }
22410Sstevel@tonic-gate
22420Sstevel@tonic-gate /*
22430Sstevel@tonic-gate * open_and_seek
22440Sstevel@tonic-gate *
22450Sstevel@tonic-gate * Open the requested 'dev_name'. Seek to point where
22460Sstevel@tonic-gate * we'll write boot sectors, etc., based on any ':partition'
22470Sstevel@tonic-gate * attachments to the dev_name.
22480Sstevel@tonic-gate *
22490Sstevel@tonic-gate * By the time we are finished here, the entire BPB will be
22500Sstevel@tonic-gate * filled in, excepting the volume label.
22510Sstevel@tonic-gate */
22520Sstevel@tonic-gate static
22530Sstevel@tonic-gate int
open_and_seek(char * dn,bpb_t * wbpb,off64_t * seekto)22540Sstevel@tonic-gate open_and_seek(char *dn, bpb_t *wbpb, off64_t *seekto)
22550Sstevel@tonic-gate {
22560Sstevel@tonic-gate struct fd_char fdchar;
2257585Sps156622 struct dk_geom dg;
22580Sstevel@tonic-gate struct stat di;
2259*9889SLarry.Liu@Sun.COM struct dk_minfo dkminfo;
22600Sstevel@tonic-gate char *actualdisk = NULL;
22610Sstevel@tonic-gate char *suffix = NULL;
22620Sstevel@tonic-gate int fd;
22630Sstevel@tonic-gate
22640Sstevel@tonic-gate if (Verbose)
22650Sstevel@tonic-gate (void) printf(gettext("Opening destination device/file.\n"));
22660Sstevel@tonic-gate
22670Sstevel@tonic-gate /*
22680Sstevel@tonic-gate * We hold these truths to be self evident, all BPBs we create
22690Sstevel@tonic-gate * will have these values in these fields.
22700Sstevel@tonic-gate */
22710Sstevel@tonic-gate wbpb->bpb.num_fats = 2;
22720Sstevel@tonic-gate wbpb->bpb.bytes_sector = BPSEC;
22730Sstevel@tonic-gate
22740Sstevel@tonic-gate /*
22750Sstevel@tonic-gate * Assign or use supplied numbers for hidden and
22760Sstevel@tonic-gate * reserved sectors in the file system.
22770Sstevel@tonic-gate */
22780Sstevel@tonic-gate if (GetResrvd)
22790Sstevel@tonic-gate if (MakeFAT32)
22800Sstevel@tonic-gate wbpb->bpb.resv_sectors = 32;
22810Sstevel@tonic-gate else
22820Sstevel@tonic-gate wbpb->bpb.resv_sectors = 1;
22830Sstevel@tonic-gate else
22840Sstevel@tonic-gate wbpb->bpb.resv_sectors = Resrvd;
22850Sstevel@tonic-gate
22860Sstevel@tonic-gate wbpb->ebpb.ext_signature = 0x29; /* Magic number for modern format */
22870Sstevel@tonic-gate wbpb->ebpb.volume_id = 0;
22880Sstevel@tonic-gate
22890Sstevel@tonic-gate if (MakeFAT32)
22900Sstevel@tonic-gate fill_fat32_bpb(wbpb);
22910Sstevel@tonic-gate
22920Sstevel@tonic-gate /*
22930Sstevel@tonic-gate * If all output goes to a simple file, call a routine to setup
22940Sstevel@tonic-gate * that scenario. Otherwise, try to find the device.
22950Sstevel@tonic-gate */
22960Sstevel@tonic-gate if (Outputtofile)
22970Sstevel@tonic-gate return (fd = prepare_image_file(dn, wbpb));
22980Sstevel@tonic-gate
22990Sstevel@tonic-gate actualdisk = stat_actual_disk(dn, &di, &suffix);
23000Sstevel@tonic-gate
23010Sstevel@tonic-gate /*
23020Sstevel@tonic-gate * Sanity check. If we've been provided a partition-specifying
23030Sstevel@tonic-gate * suffix, we shouldn't also have been told to ignore the
23040Sstevel@tonic-gate * fdisk table.
23050Sstevel@tonic-gate */
23060Sstevel@tonic-gate if (DontUseFdisk && suffix) {
23070Sstevel@tonic-gate (void) fprintf(stderr,
23080Sstevel@tonic-gate gettext("Using 'nofdisk' option precludes "
23095121Sfrankho "appending logical drive\nspecifier "
23105121Sfrankho "to the device name.\n"));
23110Sstevel@tonic-gate exit(2);
23120Sstevel@tonic-gate }
23130Sstevel@tonic-gate
23140Sstevel@tonic-gate /*
23150Sstevel@tonic-gate * Destination exists, now find more about it.
23160Sstevel@tonic-gate */
23170Sstevel@tonic-gate if (!(S_ISCHR(di.st_mode))) {
23180Sstevel@tonic-gate (void) fprintf(stderr,
23190Sstevel@tonic-gate gettext("\n%s: device name must indicate a "
23205121Sfrankho "character special device.\n"), actualdisk);
23210Sstevel@tonic-gate exit(2);
23223925Sartem } else if ((fd = open(actualdisk, O_RDWR)) < 0) {
23230Sstevel@tonic-gate perror(actualdisk);
23240Sstevel@tonic-gate exit(2);
23250Sstevel@tonic-gate }
23260Sstevel@tonic-gate
23270Sstevel@tonic-gate /*
2328*9889SLarry.Liu@Sun.COM * Check the media sector size
2329*9889SLarry.Liu@Sun.COM */
2330*9889SLarry.Liu@Sun.COM if (ioctl(fd, DKIOCGMEDIAINFO, &dkminfo) != -1) {
2331*9889SLarry.Liu@Sun.COM if (dkminfo.dki_lbsize != 0 &&
2332*9889SLarry.Liu@Sun.COM ISP2(dkminfo.dki_lbsize / DEV_BSIZE) &&
2333*9889SLarry.Liu@Sun.COM dkminfo.dki_lbsize != DEV_BSIZE) {
2334*9889SLarry.Liu@Sun.COM (void) fprintf(stderr,
2335*9889SLarry.Liu@Sun.COM gettext("The device sector size %u is not "
2336*9889SLarry.Liu@Sun.COM "supported by pcfs!\n"), dkminfo.dki_lbsize);
2337*9889SLarry.Liu@Sun.COM (void) close(fd);
2338*9889SLarry.Liu@Sun.COM exit(1);
2339*9889SLarry.Liu@Sun.COM }
2340*9889SLarry.Liu@Sun.COM }
2341*9889SLarry.Liu@Sun.COM
2342*9889SLarry.Liu@Sun.COM /*
23430Sstevel@tonic-gate * Find appropriate partition if we were requested to do so.
23440Sstevel@tonic-gate */
23450Sstevel@tonic-gate if (suffix && !(seek_partn(fd, suffix, wbpb, seekto))) {
23460Sstevel@tonic-gate (void) close(fd);
23470Sstevel@tonic-gate exit(2);
23480Sstevel@tonic-gate }
23490Sstevel@tonic-gate
23500Sstevel@tonic-gate if (!suffix) {
23510Sstevel@tonic-gate /*
23520Sstevel@tonic-gate * We have one of two possibilities. Chances are we have
23530Sstevel@tonic-gate * a floppy drive. But the user may be trying to format
23540Sstevel@tonic-gate * some weird drive that we don't know about and is supplying
23550Sstevel@tonic-gate * all the important values. In that case, they should have set
23560Sstevel@tonic-gate * the 'nofdisk' flag.
23570Sstevel@tonic-gate *
23580Sstevel@tonic-gate * If 'nofdisk' isn't set, do a floppy-specific ioctl to
23590Sstevel@tonic-gate * get the remainder of our info. If the ioctl fails, we have
23600Sstevel@tonic-gate * a good idea that they aren't really on a floppy. In that
23610Sstevel@tonic-gate * case, they should have given us a partition specifier.
23620Sstevel@tonic-gate */
23630Sstevel@tonic-gate if (DontUseFdisk) {
23640Sstevel@tonic-gate if (!(seek_nofdisk(fd, wbpb, seekto))) {
23650Sstevel@tonic-gate (void) close(fd);
23660Sstevel@tonic-gate exit(2);
23670Sstevel@tonic-gate }
23680Sstevel@tonic-gate find_fixed_details(fd, wbpb);
23690Sstevel@tonic-gate } else if (ioctl(fd, FDIOGCHAR, &fdchar) == -1) {
2370585Sps156622 /*
2371585Sps156622 * It is possible that we are trying to use floppy
2372585Sps156622 * specific FDIOGCHAR ioctl on USB floppy. Since sd
2373585Sps156622 * driver, by which USB floppy is handled, doesn't
2374585Sps156622 * support it, we can try to use disk DKIOCGGEOM ioctl
2375585Sps156622 * to retrieve data we need. sd driver itself
2376585Sps156622 * determines floppy disk by number of blocks
2377585Sps156622 * (<=0x1000), then it sets geometry to 80 cylinders,
2378585Sps156622 * 2 heads.
2379585Sps156622 *
2380585Sps156622 * Note that DKIOCGGEOM cannot supply us with type
2381585Sps156622 * of media (e.g. 3.5" or 5.25"). We will set it to
2382585Sps156622 * 3 (3.5") which is most probable value.
2383585Sps156622 */
23840Sstevel@tonic-gate if (errno == ENOTTY) {
2385585Sps156622 if (ioctl(fd, DKIOCGGEOM, &dg) != -1 &&
2386585Sps156622 dg.dkg_ncyl == 80 && dg.dkg_nhead == 2) {
2387585Sps156622 fdchar.fdc_ncyl = dg.dkg_ncyl;
2388585Sps156622 fdchar.fdc_medium = 3;
2389585Sps156622 fdchar.fdc_secptrack = dg.dkg_nsect;
2390585Sps156622 fdchar.fdc_nhead = dg.dkg_nhead;
2391585Sps156622 lookup_floppy(&fdchar, wbpb);
2392585Sps156622 } else {
2393585Sps156622 partn_lecture(actualdisk);
2394585Sps156622 (void) close(fd);
2395585Sps156622 exit(2);
2396585Sps156622 }
23970Sstevel@tonic-gate }
23980Sstevel@tonic-gate } else {
23990Sstevel@tonic-gate #ifdef sparc
24000Sstevel@tonic-gate fdchar.fdc_medium = 3;
24010Sstevel@tonic-gate #endif
24020Sstevel@tonic-gate lookup_floppy(&fdchar, wbpb);
24030Sstevel@tonic-gate }
24040Sstevel@tonic-gate } else {
24050Sstevel@tonic-gate find_fixed_details(fd, wbpb);
24060Sstevel@tonic-gate }
24070Sstevel@tonic-gate
24080Sstevel@tonic-gate return (fd);
24090Sstevel@tonic-gate }
24100Sstevel@tonic-gate
24110Sstevel@tonic-gate /*
24120Sstevel@tonic-gate * The following is a copy of MS-DOS 4.0 boot block.
24130Sstevel@tonic-gate * It consists of the BIOS parameter block, and a disk
24140Sstevel@tonic-gate * bootstrap program.
24150Sstevel@tonic-gate *
24160Sstevel@tonic-gate * The BIOS parameter block contains the right values
24170Sstevel@tonic-gate * for the 3.5" high-density 1.44MB floppy format.
24180Sstevel@tonic-gate *
24190Sstevel@tonic-gate * This will be our default boot sector, if the user
24200Sstevel@tonic-gate * didn't point us at a different one.
24210Sstevel@tonic-gate *
24220Sstevel@tonic-gate */
24230Sstevel@tonic-gate static
24240Sstevel@tonic-gate uchar_t DefBootSec[512] = {
24250Sstevel@tonic-gate 0xeb, 0x3c, 0x90, /* 8086 short jump + displacement + NOP */
24260Sstevel@tonic-gate 'M', 'S', 'D', 'O', 'S', '4', '.', '0', /* OEM name & version */
24270Sstevel@tonic-gate 0x00, 0x02, 0x01, 0x01, 0x00,
24280Sstevel@tonic-gate 0x02, 0xe0, 0x00, 0x40, 0x0b,
24290Sstevel@tonic-gate 0xf0, 0x09, 0x00, 0x12, 0x00,
24300Sstevel@tonic-gate 0x02, 0x00,
24310Sstevel@tonic-gate 0x00, 0x00, 0x00, 0x00,
24320Sstevel@tonic-gate 0x00, 0x00, 0x00, 0x00,
24330Sstevel@tonic-gate 0x00, 0x00,
24340Sstevel@tonic-gate 0x29, 0x00, 0x00, 0x00, 0x00,
24350Sstevel@tonic-gate 'N', 'O', 'N', 'A', 'M', 'E', ' ', ' ', ' ', ' ', ' ',
24360Sstevel@tonic-gate 'F', 'A', 'T', '1', '2', ' ', ' ', ' ',
24370Sstevel@tonic-gate 0xfa, 0x33,
24380Sstevel@tonic-gate 0xc0, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x16, 0x07,
24390Sstevel@tonic-gate 0xbb, 0x78, 0x00, 0x36, 0xc5, 0x37, 0x1e, 0x56,
24400Sstevel@tonic-gate 0x16, 0x53, 0xbf, 0x3e, 0x7c, 0xb9, 0x0b, 0x00,
24410Sstevel@tonic-gate 0xfc, 0xf3, 0xa4, 0x06, 0x1f, 0xc6, 0x45, 0xfe,
24420Sstevel@tonic-gate 0x0f, 0x8b, 0x0e, 0x18, 0x7c, 0x88, 0x4d, 0xf9,
24430Sstevel@tonic-gate 0x89, 0x47, 0x02, 0xc7, 0x07, 0x3e, 0x7c, 0xfb,
24440Sstevel@tonic-gate 0xcd, 0x13, 0x72, 0x7c, 0x33, 0xc0, 0x39, 0x06,
24450Sstevel@tonic-gate 0x13, 0x7c, 0x74, 0x08, 0x8b, 0x0e, 0x13, 0x7c,
24460Sstevel@tonic-gate 0x89, 0x0e, 0x20, 0x7c, 0xa0, 0x10, 0x7c, 0xf7,
24470Sstevel@tonic-gate 0x26, 0x16, 0x7c, 0x03, 0x06, 0x1c, 0x7c, 0x13,
24480Sstevel@tonic-gate 0x16, 0x1e, 0x7c, 0x03, 0x06, 0x0e, 0x7c, 0x83,
24490Sstevel@tonic-gate 0xd2, 0x00, 0xa3, 0x50, 0x7c, 0x89, 0x16, 0x52,
24500Sstevel@tonic-gate 0x7c, 0xa3, 0x49, 0x7c, 0x89, 0x16, 0x4b, 0x7c,
24510Sstevel@tonic-gate 0xb8, 0x20, 0x00, 0xf7, 0x26, 0x11, 0x7c, 0x8b,
24520Sstevel@tonic-gate 0x1e, 0x0b, 0x7c, 0x03, 0xc3, 0x48, 0xf7, 0xf3,
24530Sstevel@tonic-gate 0x01, 0x06, 0x49, 0x7c, 0x83, 0x16, 0x4b, 0x7c,
24540Sstevel@tonic-gate 0x00, 0xbb, 0x00, 0x05, 0x8b, 0x16, 0x52, 0x7c,
24550Sstevel@tonic-gate 0xa1, 0x50, 0x7c, 0xe8, 0x87, 0x00, 0x72, 0x20,
24560Sstevel@tonic-gate 0xb0, 0x01, 0xe8, 0xa1, 0x00, 0x72, 0x19, 0x8b,
24570Sstevel@tonic-gate 0xfb, 0xb9, 0x0b, 0x00, 0xbe, 0xdb, 0x7d, 0xf3,
24580Sstevel@tonic-gate 0xa6, 0x75, 0x0d, 0x8d, 0x7f, 0x20, 0xbe, 0xe6,
24590Sstevel@tonic-gate 0x7d, 0xb9, 0x0b, 0x00, 0xf3, 0xa6, 0x74, 0x18,
24600Sstevel@tonic-gate 0xbe, 0x93, 0x7d, 0xe8, 0x51, 0x00, 0x32, 0xe4,
24610Sstevel@tonic-gate 0xcd, 0x16, 0x5e, 0x1f, 0x8f, 0x04, 0x8f, 0x44,
24620Sstevel@tonic-gate 0x02, 0xcd, 0x19, 0x58, 0x58, 0x58, 0xeb, 0xe8,
24630Sstevel@tonic-gate 0xbb, 0x00, 0x07, 0xb9, 0x03, 0x00, 0xa1, 0x49,
24640Sstevel@tonic-gate 0x7c, 0x8b, 0x16, 0x4b, 0x7c, 0x50, 0x52, 0x51,
24650Sstevel@tonic-gate 0xe8, 0x3a, 0x00, 0x72, 0xe6, 0xb0, 0x01, 0xe8,
24660Sstevel@tonic-gate 0x54, 0x00, 0x59, 0x5a, 0x58, 0x72, 0xc9, 0x05,
24670Sstevel@tonic-gate 0x01, 0x00, 0x83, 0xd2, 0x00, 0x03, 0x1e, 0x0b,
24680Sstevel@tonic-gate 0x7c, 0xe2, 0xe2, 0x8a, 0x2e, 0x15, 0x7c, 0x8a,
24690Sstevel@tonic-gate 0x16, 0x24, 0x7c, 0x8b, 0x1e, 0x49, 0x7c, 0xa1,
24700Sstevel@tonic-gate 0x4b, 0x7c, 0xea, 0x00, 0x00, 0x70, 0x00, 0xac,
24710Sstevel@tonic-gate 0x0a, 0xc0, 0x74, 0x29, 0xb4, 0x0e, 0xbb, 0x07,
24720Sstevel@tonic-gate 0x00, 0xcd, 0x10, 0xeb, 0xf2, 0x3b, 0x16, 0x18,
24730Sstevel@tonic-gate 0x7c, 0x73, 0x19, 0xf7, 0x36, 0x18, 0x7c, 0xfe,
24740Sstevel@tonic-gate 0xc2, 0x88, 0x16, 0x4f, 0x7c, 0x33, 0xd2, 0xf7,
24750Sstevel@tonic-gate 0x36, 0x1a, 0x7c, 0x88, 0x16, 0x25, 0x7c, 0xa3,
24760Sstevel@tonic-gate 0x4d, 0x7c, 0xf8, 0xc3, 0xf9, 0xc3, 0xb4, 0x02,
24770Sstevel@tonic-gate 0x8b, 0x16, 0x4d, 0x7c, 0xb1, 0x06, 0xd2, 0xe6,
24780Sstevel@tonic-gate 0x0a, 0x36, 0x4f, 0x7c, 0x8b, 0xca, 0x86, 0xe9,
24790Sstevel@tonic-gate 0x8a, 0x16, 0x24, 0x7c, 0x8a, 0x36, 0x25, 0x7c,
24800Sstevel@tonic-gate 0xcd, 0x13, 0xc3, 0x0d, 0x0a, 0x4e, 0x6f, 0x6e,
24810Sstevel@tonic-gate 0x2d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20,
24820Sstevel@tonic-gate 0x64, 0x69, 0x73, 0x6b, 0x20, 0x6f, 0x72, 0x20,
24830Sstevel@tonic-gate 0x64, 0x69, 0x73, 0x6b, 0x20, 0x65, 0x72, 0x72,
24840Sstevel@tonic-gate 0x6f, 0x72, 0x0d, 0x0a, 0x52, 0x65, 0x70, 0x6c,
24850Sstevel@tonic-gate 0x61, 0x63, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20,
24860Sstevel@tonic-gate 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6e,
24870Sstevel@tonic-gate 0x79, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x77, 0x68,
24880Sstevel@tonic-gate 0x65, 0x6e, 0x20, 0x72, 0x65, 0x61, 0x64, 0x79,
24890Sstevel@tonic-gate 0x0d, 0x0a, 0x00, 0x49, 0x4f, 0x20, 0x20, 0x20,
24900Sstevel@tonic-gate 0x20, 0x20, 0x20, 0x53, 0x59, 0x53, 0x4d, 0x53,
24910Sstevel@tonic-gate 0x44, 0x4f, 0x53, 0x20, 0x20, 0x20, 0x53, 0x59,
24920Sstevel@tonic-gate 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24930Sstevel@tonic-gate 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
24940Sstevel@tonic-gate };
24950Sstevel@tonic-gate
24960Sstevel@tonic-gate /*
24970Sstevel@tonic-gate * verify_bootblkfile
24980Sstevel@tonic-gate *
24990Sstevel@tonic-gate * We were provided with the name of a file containing the bootblk
25000Sstevel@tonic-gate * to install. Verify it has a valid boot sector as best we can. Any
25010Sstevel@tonic-gate * errors and we return a bad file descriptor. Otherwise we fill up the
25020Sstevel@tonic-gate * provided buffer with the boot sector, return the file
25030Sstevel@tonic-gate * descriptor for later use and leave the file pointer just
25040Sstevel@tonic-gate * past the boot sector part of the boot block file.
25050Sstevel@tonic-gate */
25060Sstevel@tonic-gate static
25070Sstevel@tonic-gate int
verify_bootblkfile(char * fn,boot_sector_t * bs,ulong_t * blkfilesize)25080Sstevel@tonic-gate verify_bootblkfile(char *fn, boot_sector_t *bs, ulong_t *blkfilesize)
25090Sstevel@tonic-gate {
25100Sstevel@tonic-gate struct stat fi;
25110Sstevel@tonic-gate int bsfd = -1;
25120Sstevel@tonic-gate
25130Sstevel@tonic-gate if (stat(fn, &fi)) {
25140Sstevel@tonic-gate perror(fn);
25150Sstevel@tonic-gate } else if (fi.st_size < BPSEC) {
25160Sstevel@tonic-gate (void) fprintf(stderr,
25170Sstevel@tonic-gate gettext("%s: Too short to be a boot sector.\n"), fn);
25180Sstevel@tonic-gate } else if ((bsfd = open(fn, O_RDONLY)) < 0) {
25190Sstevel@tonic-gate perror(fn);
25200Sstevel@tonic-gate } else if (read(bsfd, bs->buf, BPSEC) < BPSEC) {
25210Sstevel@tonic-gate (void) close(bsfd);
25220Sstevel@tonic-gate bsfd = -1;
25230Sstevel@tonic-gate perror(gettext("Boot block read"));
25240Sstevel@tonic-gate } else {
25255121Sfrankho if ((bs->bs.bs_signature[0] != (BOOTSECSIG & 0xFF) &&
25265121Sfrankho bs->bs.bs_signature[1] != ((BOOTSECSIG >> 8) & 0xFF)) ||
25270Sstevel@tonic-gate #ifdef i386
25285121Sfrankho (bs->bs.bs_front.bs_jump_code[0] != OPCODE1 &&
25295121Sfrankho bs->bs.bs_front.bs_jump_code[0] != OPCODE2)
25300Sstevel@tonic-gate #else
25315121Sfrankho (bs->bs.bs_jump_code[0] != OPCODE1 &&
25325121Sfrankho bs->bs.bs_jump_code[0] != OPCODE2)
25330Sstevel@tonic-gate #endif
25345122Sfrankho /* CSTYLED */
25355121Sfrankho ) {
25360Sstevel@tonic-gate (void) close(bsfd);
25370Sstevel@tonic-gate bsfd = -1;
25380Sstevel@tonic-gate (void) fprintf(stderr,
25390Sstevel@tonic-gate gettext("Boot block (%s) bogus.\n"), fn);
25400Sstevel@tonic-gate }
25410Sstevel@tonic-gate *blkfilesize = fi.st_size;
25420Sstevel@tonic-gate }
25430Sstevel@tonic-gate return (bsfd);
25440Sstevel@tonic-gate }
25450Sstevel@tonic-gate
25460Sstevel@tonic-gate /*
25470Sstevel@tonic-gate * verify_firstfile
25480Sstevel@tonic-gate *
25490Sstevel@tonic-gate * We were provided with the name of a file to be the first file
25500Sstevel@tonic-gate * installed on the disk. We just need to verify it exists and
25510Sstevel@tonic-gate * find out how big it is. If it doesn't exist, we print a warning
25520Sstevel@tonic-gate * message about how the file wasn't found. We don't exit fatally,
25530Sstevel@tonic-gate * though, rather we return a size of 0 and the FAT will be built
25540Sstevel@tonic-gate * without installing any first file. They can then presumably
25550Sstevel@tonic-gate * install the correct first file by hand.
25560Sstevel@tonic-gate */
25570Sstevel@tonic-gate static
25580Sstevel@tonic-gate int
verify_firstfile(char * fn,ulong_t * filesize)25590Sstevel@tonic-gate verify_firstfile(char *fn, ulong_t *filesize)
25600Sstevel@tonic-gate {
25610Sstevel@tonic-gate struct stat fi;
25620Sstevel@tonic-gate int fd = -1;
25630Sstevel@tonic-gate
25640Sstevel@tonic-gate *filesize = 0;
25650Sstevel@tonic-gate if (stat(fn, &fi) || (fd = open(fn, O_RDONLY)) < 0) {
25660Sstevel@tonic-gate perror(fn);
25670Sstevel@tonic-gate (void) fprintf(stderr,
25680Sstevel@tonic-gate gettext("Could not access requested file. It will not\n"
25695121Sfrankho "be installed in the new file system.\n"));
25700Sstevel@tonic-gate } else {
25710Sstevel@tonic-gate *filesize = fi.st_size;
25720Sstevel@tonic-gate }
25730Sstevel@tonic-gate
25740Sstevel@tonic-gate return (fd);
25750Sstevel@tonic-gate }
25760Sstevel@tonic-gate
25770Sstevel@tonic-gate /*
25780Sstevel@tonic-gate * label_volume
25790Sstevel@tonic-gate *
25800Sstevel@tonic-gate * Fill in BPB with volume label.
25810Sstevel@tonic-gate */
25820Sstevel@tonic-gate static
25830Sstevel@tonic-gate void
label_volume(char * lbl,bpb_t * wbpb)25840Sstevel@tonic-gate label_volume(char *lbl, bpb_t *wbpb)
25850Sstevel@tonic-gate {
25860Sstevel@tonic-gate int ll, i;
25870Sstevel@tonic-gate
25880Sstevel@tonic-gate /* Put a volume label into our BPB. */
25890Sstevel@tonic-gate if (!lbl)
25900Sstevel@tonic-gate lbl = DEFAULT_LABEL;
25910Sstevel@tonic-gate
25920Sstevel@tonic-gate ll = min(11, (int)strlen(lbl));
25930Sstevel@tonic-gate for (i = 0; i < ll; i++) {
25940Sstevel@tonic-gate wbpb->ebpb.volume_label[i] = toupper(lbl[i]);
25950Sstevel@tonic-gate }
25960Sstevel@tonic-gate for (; i < 11; i++) {
25970Sstevel@tonic-gate wbpb->ebpb.volume_label[i] = ' ';
25980Sstevel@tonic-gate }
25990Sstevel@tonic-gate }
26000Sstevel@tonic-gate
26010Sstevel@tonic-gate static
26020Sstevel@tonic-gate int
copy_bootblk(char * fn,boot_sector_t * bootsect,ulong_t * bootblksize)26030Sstevel@tonic-gate copy_bootblk(char *fn, boot_sector_t *bootsect, ulong_t *bootblksize)
26040Sstevel@tonic-gate {
26050Sstevel@tonic-gate int bsfd = -1;
26060Sstevel@tonic-gate
26070Sstevel@tonic-gate if (Verbose && fn)
26080Sstevel@tonic-gate (void) printf(gettext("Request to install boot "
26090Sstevel@tonic-gate "block file %s.\n"), fn);
26100Sstevel@tonic-gate else if (Verbose)
26110Sstevel@tonic-gate (void) printf(gettext("Request to install DOS boot block.\n"));
26120Sstevel@tonic-gate
26130Sstevel@tonic-gate /*
26140Sstevel@tonic-gate * If they want to install their own boot block, sanity check
26150Sstevel@tonic-gate * that block.
26160Sstevel@tonic-gate */
26170Sstevel@tonic-gate if (fn) {
26180Sstevel@tonic-gate bsfd = verify_bootblkfile(fn, bootsect, bootblksize);
26190Sstevel@tonic-gate if (bsfd < 0) {
26200Sstevel@tonic-gate exit(3);
26210Sstevel@tonic-gate }
26220Sstevel@tonic-gate *bootblksize = roundup(*bootblksize, BPSEC);
26230Sstevel@tonic-gate } else {
26240Sstevel@tonic-gate (void) memcpy(bootsect, DefBootSec, BPSEC);
26250Sstevel@tonic-gate *bootblksize = BPSEC;
26260Sstevel@tonic-gate }
26270Sstevel@tonic-gate
26280Sstevel@tonic-gate return (bsfd);
26290Sstevel@tonic-gate }
26300Sstevel@tonic-gate
26310Sstevel@tonic-gate /*
26320Sstevel@tonic-gate * mark_cluster
26330Sstevel@tonic-gate *
26340Sstevel@tonic-gate * This routine fills a FAT entry with the value supplied to it as an
26350Sstevel@tonic-gate * argument. The fatp argument is assumed to be a pointer to the FAT's
26360Sstevel@tonic-gate * 0th entry. The clustnum is the cluster entry that should be updated.
26370Sstevel@tonic-gate * The value is the new value for the entry.
26380Sstevel@tonic-gate */
26390Sstevel@tonic-gate static
26400Sstevel@tonic-gate void
mark_cluster(uchar_t * fatp,pc_cluster32_t clustnum,uint32_t value)26410Sstevel@tonic-gate mark_cluster(uchar_t *fatp, pc_cluster32_t clustnum, uint32_t value)
26420Sstevel@tonic-gate {
26430Sstevel@tonic-gate uchar_t *ep;
26440Sstevel@tonic-gate ulong_t idx;
26450Sstevel@tonic-gate
26460Sstevel@tonic-gate idx = (Fatentsize == 32) ? clustnum * 4 :
26475121Sfrankho (Fatentsize == 16) ? clustnum * 2 : clustnum + clustnum/2;
26480Sstevel@tonic-gate ep = fatp + idx;
26490Sstevel@tonic-gate
26500Sstevel@tonic-gate if (Fatentsize == 32) {
26510Sstevel@tonic-gate store_32_bits(&ep, value);
26520Sstevel@tonic-gate } else if (Fatentsize == 16) {
26530Sstevel@tonic-gate store_16_bits(&ep, value);
26540Sstevel@tonic-gate } else {
26550Sstevel@tonic-gate if (clustnum & 1) {
26560Sstevel@tonic-gate *ep = (*ep & 0x0f) | ((value << 4) & 0xf0);
26570Sstevel@tonic-gate ep++;
26580Sstevel@tonic-gate *ep = (value >> 4) & 0xff;
26590Sstevel@tonic-gate } else {
26600Sstevel@tonic-gate *ep++ = value & 0xff;
26610Sstevel@tonic-gate *ep = (*ep & 0xf0) | ((value >> 8) & 0x0f);
26620Sstevel@tonic-gate }
26630Sstevel@tonic-gate }
26640Sstevel@tonic-gate }
26650Sstevel@tonic-gate
26660Sstevel@tonic-gate static
26670Sstevel@tonic-gate uchar_t *
build_fat(bpb_t * wbpb,struct fat_od_fsi * fsinfop,ulong_t bootblksize,ulong_t * fatsize,char * ffn,int * fffd,ulong_t * ffsize,pc_cluster32_t * ffstartclust)26685121Sfrankho build_fat(bpb_t *wbpb, struct fat_od_fsi *fsinfop, ulong_t bootblksize,
26690Sstevel@tonic-gate ulong_t *fatsize, char *ffn, int *fffd, ulong_t *ffsize,
26700Sstevel@tonic-gate pc_cluster32_t *ffstartclust)
26710Sstevel@tonic-gate {
26720Sstevel@tonic-gate pc_cluster32_t nextfree, ci;
26730Sstevel@tonic-gate uchar_t *fatp;
26740Sstevel@tonic-gate ushort_t numclust, numsect;
26750Sstevel@tonic-gate int remclust;
26760Sstevel@tonic-gate
26770Sstevel@tonic-gate /* Alloc space for a FAT and then null it out. */
26780Sstevel@tonic-gate if (Verbose) {
26790Sstevel@tonic-gate (void) printf(gettext("BUILD FAT.\n%d sectors per fat.\n"),
26800Sstevel@tonic-gate wbpb->bpb.sectors_per_fat ? wbpb->bpb.sectors_per_fat :
26815121Sfrankho wbpb->bpb32.big_sectors_per_fat);
26820Sstevel@tonic-gate }
26830Sstevel@tonic-gate
26840Sstevel@tonic-gate if (MakeFAT32) {
26850Sstevel@tonic-gate *fatsize = BPSEC * wbpb->bpb32.big_sectors_per_fat;
26860Sstevel@tonic-gate } else {
26870Sstevel@tonic-gate *fatsize = BPSEC * wbpb->bpb.sectors_per_fat;
26880Sstevel@tonic-gate }
2689607Swyllys
26900Sstevel@tonic-gate if (!(fatp = (uchar_t *)malloc(*fatsize))) {
26910Sstevel@tonic-gate perror(gettext("FAT table alloc"));
26920Sstevel@tonic-gate exit(4);
26930Sstevel@tonic-gate } else {
26940Sstevel@tonic-gate (void) memset(fatp, 0, *fatsize);
26950Sstevel@tonic-gate }
26960Sstevel@tonic-gate
26970Sstevel@tonic-gate /* Build in-memory FAT */
26980Sstevel@tonic-gate *fatp = wbpb->bpb.media;
26990Sstevel@tonic-gate *(fatp + 1) = 0xFF;
27000Sstevel@tonic-gate *(fatp + 2) = 0xFF;
27010Sstevel@tonic-gate
27020Sstevel@tonic-gate if (Fatentsize == 16) {
27030Sstevel@tonic-gate *(fatp + 3) = 0xFF;
27040Sstevel@tonic-gate } else if (Fatentsize == 32) {
27050Sstevel@tonic-gate *(fatp + 3) = 0x0F;
27060Sstevel@tonic-gate *(fatp + 4) = 0xFF;
27070Sstevel@tonic-gate *(fatp + 5) = 0xFF;
27080Sstevel@tonic-gate *(fatp + 6) = 0xFF;
27090Sstevel@tonic-gate *(fatp + 7) = 0x0F;
27100Sstevel@tonic-gate }
27110Sstevel@tonic-gate
27120Sstevel@tonic-gate /*
27130Sstevel@tonic-gate * Keep track of clusters used.
27140Sstevel@tonic-gate */
27150Sstevel@tonic-gate remclust = TotalClusters;
27160Sstevel@tonic-gate nextfree = 2;
27170Sstevel@tonic-gate
27180Sstevel@tonic-gate /*
27190Sstevel@tonic-gate * Get info on first file to install, if any.
27200Sstevel@tonic-gate */
27210Sstevel@tonic-gate if (ffn)
27220Sstevel@tonic-gate *fffd = verify_firstfile(ffn, ffsize);
27230Sstevel@tonic-gate
27240Sstevel@tonic-gate /*
27250Sstevel@tonic-gate * Compute number of clusters to preserve for bootblk overage.
27260Sstevel@tonic-gate * Remember that we already wrote the first sector of the boot block.
27270Sstevel@tonic-gate * These clusters are marked BAD to prevent them from being deleted
27280Sstevel@tonic-gate * or used. The first available cluster is 2, so we always offset
27290Sstevel@tonic-gate * the clusters.
27300Sstevel@tonic-gate */
27310Sstevel@tonic-gate numsect = idivceil((bootblksize - BPSEC), BPSEC);
27320Sstevel@tonic-gate numclust = idivceil(numsect, wbpb->bpb.sectors_per_cluster);
27330Sstevel@tonic-gate
27340Sstevel@tonic-gate if (Verbose && numclust)
27350Sstevel@tonic-gate (void) printf(gettext("Hiding %d excess bootblk cluster(s).\n"),
27360Sstevel@tonic-gate numclust);
27370Sstevel@tonic-gate for (ci = 0; ci < numclust; ci++)
27380Sstevel@tonic-gate mark_cluster(fatp, nextfree++,
27395121Sfrankho MakeFAT32 ? PCF_BADCLUSTER32 : PCF_BADCLUSTER);
27400Sstevel@tonic-gate remclust -= numclust;
27410Sstevel@tonic-gate
27420Sstevel@tonic-gate /*
27430Sstevel@tonic-gate * Reserve a cluster for the root directory on a FAT32.
27440Sstevel@tonic-gate */
27450Sstevel@tonic-gate if (MakeFAT32) {
27460Sstevel@tonic-gate mark_cluster(fatp, nextfree, PCF_LASTCLUSTER32);
27470Sstevel@tonic-gate wbpb->bpb32.root_dir_clust = nextfree++;
27480Sstevel@tonic-gate remclust--;
27490Sstevel@tonic-gate }
27500Sstevel@tonic-gate
27510Sstevel@tonic-gate /*
27520Sstevel@tonic-gate * Compute and preserve number of clusters for first file.
27530Sstevel@tonic-gate */
27540Sstevel@tonic-gate if (*fffd >= 0) {
27550Sstevel@tonic-gate *ffstartclust = nextfree;
27560Sstevel@tonic-gate numsect = idivceil(*ffsize, BPSEC);
27570Sstevel@tonic-gate numclust = idivceil(numsect, wbpb->bpb.sectors_per_cluster);
27580Sstevel@tonic-gate
27590Sstevel@tonic-gate if (numclust > remclust) {
27600Sstevel@tonic-gate (void) fprintf(stderr,
27615121Sfrankho gettext("Requested first file too large to be\n"
27625121Sfrankho "installed in the new file system.\n"));
27630Sstevel@tonic-gate (void) close(*fffd);
27640Sstevel@tonic-gate *fffd = -1;
27650Sstevel@tonic-gate goto finish;
27660Sstevel@tonic-gate }
27670Sstevel@tonic-gate
27680Sstevel@tonic-gate if (Verbose)
27690Sstevel@tonic-gate (void) printf(gettext("Reserving %d first file "
27700Sstevel@tonic-gate "cluster(s).\n"), numclust);
27710Sstevel@tonic-gate for (ci = 0; (int)ci < (int)(numclust-1); ci++, nextfree++)
27720Sstevel@tonic-gate mark_cluster(fatp, nextfree, nextfree + 1);
27730Sstevel@tonic-gate mark_cluster(fatp, nextfree++,
27745121Sfrankho MakeFAT32 ? PCF_LASTCLUSTER32 : PCF_LASTCLUSTER);
27750Sstevel@tonic-gate remclust -= numclust;
27760Sstevel@tonic-gate }
27770Sstevel@tonic-gate
27780Sstevel@tonic-gate finish:
27790Sstevel@tonic-gate if (Verbose) {
27800Sstevel@tonic-gate (void) printf(gettext("First sector of FAT"));
27810Sstevel@tonic-gate header_for_dump();
27820Sstevel@tonic-gate dump_bytes(fatp, BPSEC);
27830Sstevel@tonic-gate }
27840Sstevel@tonic-gate
27855121Sfrankho (void) memset(fsinfop, 0, sizeof (*fsinfop));
27865121Sfrankho fsinfop->fsi_leadsig = LE_32(FSI_LEADSIG);
27875121Sfrankho fsinfop->fsi_strucsig = LE_32(FSI_STRUCSIG);
27885121Sfrankho fsinfop->fsi_trailsig = LE_32(FSI_TRAILSIG);
27895121Sfrankho fsinfop->fsi_incore.fs_free_clusters = LE_32(remclust);
27905121Sfrankho fsinfop->fsi_incore.fs_next_free = LE_32(nextfree);
27910Sstevel@tonic-gate return (fatp);
27920Sstevel@tonic-gate }
27930Sstevel@tonic-gate
27940Sstevel@tonic-gate static
27950Sstevel@tonic-gate void
dirent_time_fill(struct pcdir * dep)27960Sstevel@tonic-gate dirent_time_fill(struct pcdir *dep)
27970Sstevel@tonic-gate {
27980Sstevel@tonic-gate struct timeval tv;
27990Sstevel@tonic-gate struct tm *tp;
28000Sstevel@tonic-gate ushort_t dostime;
28010Sstevel@tonic-gate ushort_t dosday;
28020Sstevel@tonic-gate
28030Sstevel@tonic-gate (void) gettimeofday(&tv, (struct timezone *)0);
28040Sstevel@tonic-gate tp = localtime(&tv.tv_sec);
28050Sstevel@tonic-gate /* get the time & day into DOS format */
28060Sstevel@tonic-gate dostime = tp->tm_sec / 2;
28070Sstevel@tonic-gate dostime |= tp->tm_min << 5;
28080Sstevel@tonic-gate dostime |= tp->tm_hour << 11;
28090Sstevel@tonic-gate dosday = tp->tm_mday;
28100Sstevel@tonic-gate dosday |= (tp->tm_mon + 1) << 5;
28110Sstevel@tonic-gate dosday |= (tp->tm_year - 80) << 9;
28120Sstevel@tonic-gate dep->pcd_mtime.pct_time = htols(dostime);
28130Sstevel@tonic-gate dep->pcd_mtime.pct_date = htols(dosday);
28140Sstevel@tonic-gate }
28150Sstevel@tonic-gate
28160Sstevel@tonic-gate static
28170Sstevel@tonic-gate void
dirent_label_fill(struct pcdir * dep,char * fn)28180Sstevel@tonic-gate dirent_label_fill(struct pcdir *dep, char *fn)
28190Sstevel@tonic-gate {
28200Sstevel@tonic-gate int nl, i;
28210Sstevel@tonic-gate
28220Sstevel@tonic-gate /*
28230Sstevel@tonic-gate * We spread the volume label across both the NAME and EXT fields
28240Sstevel@tonic-gate */
28250Sstevel@tonic-gate nl = min(PCFNAMESIZE, strlen(fn));
28260Sstevel@tonic-gate for (i = 0; i < nl; i++) {
28270Sstevel@tonic-gate dep->pcd_filename[i] = toupper(fn[i]);
28280Sstevel@tonic-gate }
28290Sstevel@tonic-gate if (i < PCFNAMESIZE) {
28300Sstevel@tonic-gate for (; i < PCFNAMESIZE; i++)
28310Sstevel@tonic-gate dep->pcd_filename[i] = ' ';
28320Sstevel@tonic-gate for (i = 0; i < PCFEXTSIZE; i++)
28330Sstevel@tonic-gate dep->pcd_ext[i] = ' ';
28340Sstevel@tonic-gate return;
28350Sstevel@tonic-gate }
28360Sstevel@tonic-gate nl = min(PCFEXTSIZE, strlen(fn) - PCFNAMESIZE);
28370Sstevel@tonic-gate for (i = 0; i < nl; i++)
28380Sstevel@tonic-gate dep->pcd_ext[i] = toupper(fn[i + PCFNAMESIZE]);
28390Sstevel@tonic-gate if (i < PCFEXTSIZE) {
28400Sstevel@tonic-gate for (; i < PCFEXTSIZE; i++)
28410Sstevel@tonic-gate dep->pcd_ext[i] = ' ';
28420Sstevel@tonic-gate }
28430Sstevel@tonic-gate }
28440Sstevel@tonic-gate
28450Sstevel@tonic-gate static
28460Sstevel@tonic-gate void
dirent_fname_fill(struct pcdir * dep,char * fn)28470Sstevel@tonic-gate dirent_fname_fill(struct pcdir *dep, char *fn)
28480Sstevel@tonic-gate {
28490Sstevel@tonic-gate char *fname, *fext;
28500Sstevel@tonic-gate int nl, i;
28510Sstevel@tonic-gate
28520Sstevel@tonic-gate if (fname = strrchr(fn, '/')) {
28530Sstevel@tonic-gate fname++;
28540Sstevel@tonic-gate } else {
28550Sstevel@tonic-gate fname = fn;
28560Sstevel@tonic-gate }
28570Sstevel@tonic-gate
28580Sstevel@tonic-gate if (fext = strrchr(fname, '.')) {
28590Sstevel@tonic-gate fext++;
28600Sstevel@tonic-gate } else {
28610Sstevel@tonic-gate fext = "";
28620Sstevel@tonic-gate }
28630Sstevel@tonic-gate
28640Sstevel@tonic-gate fname = strtok(fname, ".");
28650Sstevel@tonic-gate
28660Sstevel@tonic-gate nl = min(PCFNAMESIZE, (int)strlen(fname));
28670Sstevel@tonic-gate for (i = 0; i < nl; i++) {
28680Sstevel@tonic-gate dep->pcd_filename[i] = toupper(fname[i]);
28690Sstevel@tonic-gate }
28700Sstevel@tonic-gate for (; i < PCFNAMESIZE; i++) {
28710Sstevel@tonic-gate dep->pcd_filename[i] = ' ';
28720Sstevel@tonic-gate }
28730Sstevel@tonic-gate
28740Sstevel@tonic-gate nl = min(PCFEXTSIZE, (int)strlen(fext));
28750Sstevel@tonic-gate for (i = 0; i < nl; i++) {
28760Sstevel@tonic-gate dep->pcd_ext[i] = toupper(fext[i]);
28770Sstevel@tonic-gate }
28780Sstevel@tonic-gate for (; i < PCFEXTSIZE; i++) {
28790Sstevel@tonic-gate dep->pcd_ext[i] = ' ';
28800Sstevel@tonic-gate }
28810Sstevel@tonic-gate }
28820Sstevel@tonic-gate
28830Sstevel@tonic-gate static
28840Sstevel@tonic-gate uchar_t *
build_rootdir(bpb_t * wbpb,char * ffn,int fffd,ulong_t ffsize,pc_cluster32_t ffstart,ulong_t * rdirsize)28850Sstevel@tonic-gate build_rootdir(bpb_t *wbpb, char *ffn, int fffd,
28860Sstevel@tonic-gate ulong_t ffsize, pc_cluster32_t ffstart, ulong_t *rdirsize)
28870Sstevel@tonic-gate {
28880Sstevel@tonic-gate struct pcdir *rootdirp;
28890Sstevel@tonic-gate struct pcdir *entry;
28900Sstevel@tonic-gate
28910Sstevel@tonic-gate /*
28920Sstevel@tonic-gate * Build a root directory. It will have at least one entry,
28930Sstevel@tonic-gate * the volume label and a second if the first file was defined.
28940Sstevel@tonic-gate */
28950Sstevel@tonic-gate if (MakeFAT32) {
28960Sstevel@tonic-gate /*
28970Sstevel@tonic-gate * We devote an entire cluster to the root
28980Sstevel@tonic-gate * directory on FAT32.
28990Sstevel@tonic-gate */
29000Sstevel@tonic-gate *rdirsize = wbpb->bpb.sectors_per_cluster * BPSEC;
29010Sstevel@tonic-gate } else {
29020Sstevel@tonic-gate *rdirsize = wbpb->bpb.num_root_entries * sizeof (struct pcdir);
29030Sstevel@tonic-gate }
29040Sstevel@tonic-gate if ((rootdirp = (struct pcdir *)malloc(*rdirsize)) == NULL) {
29050Sstevel@tonic-gate perror(gettext("Root directory allocation"));
29060Sstevel@tonic-gate exit(4);
29070Sstevel@tonic-gate } else {
29080Sstevel@tonic-gate entry = rootdirp;
29090Sstevel@tonic-gate (void) memset((char *)rootdirp, 0, *rdirsize);
29100Sstevel@tonic-gate }
29110Sstevel@tonic-gate
29120Sstevel@tonic-gate /* Create directory entry for first file, if there is one */
29130Sstevel@tonic-gate if (fffd >= 0) {
29140Sstevel@tonic-gate dirent_fname_fill(entry, ffn);
29150Sstevel@tonic-gate entry->pcd_attr = Firstfileattr;
29160Sstevel@tonic-gate dirent_time_fill(entry);
29170Sstevel@tonic-gate entry->pcd_scluster_lo = htols(ffstart);
29180Sstevel@tonic-gate if (MakeFAT32) {
29190Sstevel@tonic-gate ffstart = ffstart >> 16;
29200Sstevel@tonic-gate entry->un.pcd_scluster_hi = htols(ffstart);
29210Sstevel@tonic-gate }
29220Sstevel@tonic-gate entry->pcd_size = htoli(ffsize);
29230Sstevel@tonic-gate entry++;
29240Sstevel@tonic-gate }
29250Sstevel@tonic-gate
29260Sstevel@tonic-gate /* Create directory entry for volume label, if there is one */
29270Sstevel@tonic-gate if (Label != NULL) {
29280Sstevel@tonic-gate dirent_label_fill(entry, Label);
29290Sstevel@tonic-gate entry->pcd_attr = PCA_ARCH | PCA_LABEL;
29300Sstevel@tonic-gate dirent_time_fill(entry);
29310Sstevel@tonic-gate entry->pcd_scluster_lo = 0;
29320Sstevel@tonic-gate if (MakeFAT32) {
29330Sstevel@tonic-gate entry->un.pcd_scluster_hi = 0;
29340Sstevel@tonic-gate }
29350Sstevel@tonic-gate entry->pcd_size = 0;
29360Sstevel@tonic-gate entry++;
29370Sstevel@tonic-gate }
29380Sstevel@tonic-gate
29390Sstevel@tonic-gate if (Verbose) {
29400Sstevel@tonic-gate (void) printf(gettext("First two directory entries"));
29410Sstevel@tonic-gate header_for_dump();
29420Sstevel@tonic-gate dump_bytes((uchar_t *)rootdirp, 2 * sizeof (struct pcdir));
29430Sstevel@tonic-gate }
29440Sstevel@tonic-gate
29450Sstevel@tonic-gate return ((uchar_t *)rootdirp);
29460Sstevel@tonic-gate }
29470Sstevel@tonic-gate
29480Sstevel@tonic-gate /*
29490Sstevel@tonic-gate * write_rest
29500Sstevel@tonic-gate *
29510Sstevel@tonic-gate * Write all the bytes from the current file pointer to end of file
29520Sstevel@tonic-gate * in the source file out to the destination file. The writes should
29530Sstevel@tonic-gate * be padded to whole clusters with 0's if necessary.
29540Sstevel@tonic-gate */
29550Sstevel@tonic-gate static
29560Sstevel@tonic-gate void
write_rest(bpb_t * wbpb,char * efn,int dfd,int sfd,int remaining)29570Sstevel@tonic-gate write_rest(bpb_t *wbpb, char *efn, int dfd, int sfd, int remaining)
29580Sstevel@tonic-gate {
29590Sstevel@tonic-gate char buf[BPSEC];
29600Sstevel@tonic-gate ushort_t numsect, numclust;
29610Sstevel@tonic-gate ushort_t wnumsect, s;
29620Sstevel@tonic-gate int doneread = 0;
29630Sstevel@tonic-gate int rstat;
29640Sstevel@tonic-gate
29650Sstevel@tonic-gate /*
29660Sstevel@tonic-gate * Compute number of clusters required to contain remaining bytes.
29670Sstevel@tonic-gate */
29680Sstevel@tonic-gate numsect = idivceil(remaining, BPSEC);
29690Sstevel@tonic-gate numclust = idivceil(numsect, wbpb->bpb.sectors_per_cluster);
29700Sstevel@tonic-gate
29710Sstevel@tonic-gate wnumsect = numclust * wbpb->bpb.sectors_per_cluster;
29720Sstevel@tonic-gate for (s = 0; s < wnumsect; s++) {
29730Sstevel@tonic-gate if (!doneread) {
29740Sstevel@tonic-gate if ((rstat = read(sfd, buf, BPSEC)) < 0) {
29750Sstevel@tonic-gate perror(efn);
29760Sstevel@tonic-gate doneread = 1;
29770Sstevel@tonic-gate rstat = 0;
29780Sstevel@tonic-gate } else if (rstat == 0) {
29790Sstevel@tonic-gate doneread = 1;
29800Sstevel@tonic-gate }
29810Sstevel@tonic-gate (void) memset(&(buf[rstat]), 0, BPSEC - rstat);
29820Sstevel@tonic-gate }
29830Sstevel@tonic-gate if (write(dfd, buf, BPSEC) != BPSEC) {
29840Sstevel@tonic-gate (void) fprintf(stderr, gettext("Copying "));
29850Sstevel@tonic-gate perror(efn);
29860Sstevel@tonic-gate }
29870Sstevel@tonic-gate }
29880Sstevel@tonic-gate }
29890Sstevel@tonic-gate
29900Sstevel@tonic-gate static
29910Sstevel@tonic-gate void
write_fat32_bootstuff(int fd,boot_sector_t * bsp,struct fat_od_fsi * fsinfop,off64_t seekto)29920Sstevel@tonic-gate write_fat32_bootstuff(int fd, boot_sector_t *bsp,
29935121Sfrankho struct fat_od_fsi *fsinfop, off64_t seekto)
29940Sstevel@tonic-gate {
29950Sstevel@tonic-gate if (Verbose) {
29960Sstevel@tonic-gate (void) printf(gettext("Dump of the fs info sector"));
29970Sstevel@tonic-gate header_for_dump();
29985121Sfrankho dump_bytes((uchar_t *)fsinfop, sizeof (*fsinfop));
29990Sstevel@tonic-gate }
30000Sstevel@tonic-gate
30010Sstevel@tonic-gate if (!Notreally) {
30020Sstevel@tonic-gate /*
30030Sstevel@tonic-gate * FAT32's have an FS info sector, then a backup of the boot
30040Sstevel@tonic-gate * sector, and a modified backup of the FS Info sector.
30050Sstevel@tonic-gate */
30065121Sfrankho if (write(fd, fsinfop, sizeof (*fsinfop)) != BPSEC) {
30070Sstevel@tonic-gate perror(gettext("FS info sector write"));
30080Sstevel@tonic-gate exit(4);
30090Sstevel@tonic-gate }
30100Sstevel@tonic-gate if (lseek64(fd, seekto + BKUP_BOOTSECT_OFFSET, SEEK_SET) < 0) {
30110Sstevel@tonic-gate (void) close(fd);
30120Sstevel@tonic-gate perror(gettext("Boot sector backup seek"));
30130Sstevel@tonic-gate exit(4);
30140Sstevel@tonic-gate }
30150Sstevel@tonic-gate if (write(fd, bsp->buf, sizeof (bsp->buf)) != BPSEC) {
30160Sstevel@tonic-gate perror(gettext("Boot sector backup write"));
30170Sstevel@tonic-gate exit(4);
30180Sstevel@tonic-gate }
30190Sstevel@tonic-gate }
30200Sstevel@tonic-gate
30210Sstevel@tonic-gate /*
30220Sstevel@tonic-gate * Second copy of fs info sector is modified to have "don't know"
30230Sstevel@tonic-gate * as the number of free clusters
30240Sstevel@tonic-gate */
30255121Sfrankho fsinfop->fsi_incore.fs_next_free = LE_32(FSINFO_UNKNOWN);
30260Sstevel@tonic-gate
30270Sstevel@tonic-gate if (Verbose) {
30280Sstevel@tonic-gate (void) printf(gettext("Dump of the backup fs info sector"));
30290Sstevel@tonic-gate header_for_dump();
30305121Sfrankho dump_bytes((uchar_t *)fsinfop, sizeof (*fsinfop));
30310Sstevel@tonic-gate }
30320Sstevel@tonic-gate
30330Sstevel@tonic-gate if (!Notreally) {
30345121Sfrankho if (write(fd, fsinfop, sizeof (*fsinfop)) != BPSEC) {
30350Sstevel@tonic-gate perror(gettext("FS info sector backup write"));
30360Sstevel@tonic-gate exit(4);
30370Sstevel@tonic-gate }
30380Sstevel@tonic-gate }
30390Sstevel@tonic-gate }
30400Sstevel@tonic-gate
30410Sstevel@tonic-gate static
30420Sstevel@tonic-gate void
write_bootsects(int fd,boot_sector_t * bsp,bpb_t * wbpb,struct fat_od_fsi * fsinfop,off64_t seekto)30430Sstevel@tonic-gate write_bootsects(int fd, boot_sector_t *bsp, bpb_t *wbpb,
30445121Sfrankho struct fat_od_fsi *fsinfop, off64_t seekto)
30450Sstevel@tonic-gate {
30460Sstevel@tonic-gate if (MakeFAT32) {
30470Sstevel@tonic-gate /* Copy our BPB into bootsec structure */
30480Sstevel@tonic-gate #ifdef i386
30490Sstevel@tonic-gate (void) memcpy(&(bsp->bs32.bs_front.bs_bpb), &(wbpb->bpb),
30505121Sfrankho sizeof (wbpb->bpb));
30510Sstevel@tonic-gate (void) memcpy(&(bsp->bs32.bs_bpb32), &(wbpb->bpb32),
30525121Sfrankho sizeof (wbpb->bpb32));
30530Sstevel@tonic-gate (void) memcpy(&(bsp->bs32.bs_ebpb), &(wbpb->ebpb),
30545121Sfrankho sizeof (wbpb->ebpb));
30550Sstevel@tonic-gate #else
30560Sstevel@tonic-gate swap_pack_bpb32cpy(&(bsp->bs32), wbpb);
30570Sstevel@tonic-gate #endif
30580Sstevel@tonic-gate } else {
30590Sstevel@tonic-gate /* Copy our BPB into bootsec structure */
30600Sstevel@tonic-gate #ifdef i386
30610Sstevel@tonic-gate (void) memcpy(&(bsp->bs.bs_front.bs_bpb), &(wbpb->bpb),
30625121Sfrankho sizeof (wbpb->bpb));
30630Sstevel@tonic-gate (void) memcpy(&(bsp->bs.bs_ebpb), &(wbpb->ebpb),
30645121Sfrankho sizeof (wbpb->ebpb));
30650Sstevel@tonic-gate #else
30660Sstevel@tonic-gate swap_pack_bpbcpy(&(bsp->bs), wbpb);
30670Sstevel@tonic-gate #endif
30680Sstevel@tonic-gate
30690Sstevel@tonic-gate /* Copy SUN BPB extensions into bootsec structure */
30700Sstevel@tonic-gate if (SunBPBfields) {
30710Sstevel@tonic-gate #ifdef i386
30720Sstevel@tonic-gate (void) memcpy(&(bsp->bs.bs_sebpb), &(wbpb->sunbpb),
30735121Sfrankho sizeof (wbpb->sunbpb));
30740Sstevel@tonic-gate #else
30750Sstevel@tonic-gate swap_pack_sebpbcpy(&(bsp->bs), wbpb);
30760Sstevel@tonic-gate #endif
30770Sstevel@tonic-gate }
30780Sstevel@tonic-gate }
30790Sstevel@tonic-gate
30800Sstevel@tonic-gate /* Write boot sector */
30810Sstevel@tonic-gate if (!Notreally && write(fd, bsp->buf, sizeof (bsp->buf)) != BPSEC) {
30820Sstevel@tonic-gate perror(gettext("Boot sector write"));
30830Sstevel@tonic-gate exit(4);
30840Sstevel@tonic-gate }
30850Sstevel@tonic-gate
30860Sstevel@tonic-gate if (Verbose) {
30870Sstevel@tonic-gate (void) printf(gettext("Dump of the boot sector"));
30880Sstevel@tonic-gate header_for_dump();
30890Sstevel@tonic-gate dump_bytes(bsp->buf, sizeof (bsp->buf));
30900Sstevel@tonic-gate }
30910Sstevel@tonic-gate
30920Sstevel@tonic-gate if (MakeFAT32)
30930Sstevel@tonic-gate write_fat32_bootstuff(fd, bsp, fsinfop, seekto);
30940Sstevel@tonic-gate }
30950Sstevel@tonic-gate
30960Sstevel@tonic-gate static
30970Sstevel@tonic-gate void
write_fat(int fd,off64_t seekto,char * fn,char * lbl,char * ffn,bpb_t * wbpb)30980Sstevel@tonic-gate write_fat(int fd, off64_t seekto, char *fn, char *lbl, char *ffn, bpb_t *wbpb)
30990Sstevel@tonic-gate {
31005121Sfrankho struct fat_od_fsi fsinfo;
31010Sstevel@tonic-gate pc_cluster32_t ffsc;
31020Sstevel@tonic-gate boot_sector_t bootsect;
31030Sstevel@tonic-gate uchar_t *fatp, *rdirp;
31040Sstevel@tonic-gate ulong_t bootblksize, fatsize, rdirsize, ffsize;
31050Sstevel@tonic-gate int bsfd = -1;
31060Sstevel@tonic-gate int fffd = -1;
31070Sstevel@tonic-gate
31080Sstevel@tonic-gate compute_file_area_size(wbpb);
31090Sstevel@tonic-gate
31100Sstevel@tonic-gate bsfd = copy_bootblk(fn, &bootsect, &bootblksize);
31110Sstevel@tonic-gate label_volume(lbl, wbpb);
31120Sstevel@tonic-gate
31130Sstevel@tonic-gate if (Verbose)
31140Sstevel@tonic-gate (void) printf(gettext("Building FAT.\n"));
31150Sstevel@tonic-gate fatp = build_fat(wbpb, &fsinfo, bootblksize, &fatsize,
31160Sstevel@tonic-gate ffn, &fffd, &ffsize, &ffsc);
31170Sstevel@tonic-gate
31180Sstevel@tonic-gate write_bootsects(fd, &bootsect, wbpb, &fsinfo, seekto);
31190Sstevel@tonic-gate
31200Sstevel@tonic-gate if (lseek64(fd,
31210Sstevel@tonic-gate seekto + (BPSEC * wbpb->bpb.resv_sectors), SEEK_SET) < 0) {
31220Sstevel@tonic-gate (void) close(fd);
31230Sstevel@tonic-gate perror(gettext("Seek to end of reserved sectors"));
31240Sstevel@tonic-gate exit(4);
31250Sstevel@tonic-gate }
31260Sstevel@tonic-gate
31270Sstevel@tonic-gate /* Write FAT */
31280Sstevel@tonic-gate if (Verbose)
31290Sstevel@tonic-gate (void) printf(gettext("Writing FAT(s). %d bytes times %d.\n"),
31300Sstevel@tonic-gate fatsize, wbpb->bpb.num_fats);
31310Sstevel@tonic-gate if (!Notreally) {
31320Sstevel@tonic-gate int nf, wb;
31330Sstevel@tonic-gate for (nf = 0; nf < (int)wbpb->bpb.num_fats; nf++)
31340Sstevel@tonic-gate if ((wb = write(fd, fatp, fatsize)) != fatsize) {
31350Sstevel@tonic-gate perror(gettext("FAT write"));
31360Sstevel@tonic-gate exit(4);
31370Sstevel@tonic-gate } else {
31380Sstevel@tonic-gate if (Verbose)
31390Sstevel@tonic-gate (void) printf(
31400Sstevel@tonic-gate gettext("Wrote %d bytes\n"), wb);
31410Sstevel@tonic-gate }
31420Sstevel@tonic-gate }
31430Sstevel@tonic-gate free(fatp);
31440Sstevel@tonic-gate
31450Sstevel@tonic-gate if (Verbose)
31460Sstevel@tonic-gate (void) printf(gettext("Building root directory.\n"));
31470Sstevel@tonic-gate rdirp = build_rootdir(wbpb, ffn, fffd, ffsize, ffsc, &rdirsize);
31480Sstevel@tonic-gate
31490Sstevel@tonic-gate /*
31500Sstevel@tonic-gate * In non FAT32, root directory exists outside of the file area
31510Sstevel@tonic-gate */
31520Sstevel@tonic-gate if (!MakeFAT32) {
31530Sstevel@tonic-gate if (Verbose)
31545121Sfrankho (void) printf(gettext("Writing root directory. "
31555121Sfrankho "%d bytes.\n"), rdirsize);
31560Sstevel@tonic-gate if (!Notreally) {
31570Sstevel@tonic-gate if (write(fd, rdirp, rdirsize) != rdirsize) {
31580Sstevel@tonic-gate perror(gettext("Root directory write"));
31590Sstevel@tonic-gate exit(4);
31600Sstevel@tonic-gate }
31610Sstevel@tonic-gate }
31620Sstevel@tonic-gate free(rdirp);
31630Sstevel@tonic-gate }
31640Sstevel@tonic-gate
31650Sstevel@tonic-gate /*
31660Sstevel@tonic-gate * Now write anything that needs to be in the file space.
31670Sstevel@tonic-gate */
31680Sstevel@tonic-gate if (bootblksize > BPSEC) {
31690Sstevel@tonic-gate if (Verbose)
31700Sstevel@tonic-gate (void) printf(gettext("Writing remainder of "
31715121Sfrankho "boot block.\n"));
31720Sstevel@tonic-gate if (!Notreally)
31730Sstevel@tonic-gate write_rest(wbpb, fn, fd, bsfd, bootblksize - BPSEC);
31740Sstevel@tonic-gate }
31750Sstevel@tonic-gate
31760Sstevel@tonic-gate if (MakeFAT32) {
31770Sstevel@tonic-gate if (Verbose)
31785121Sfrankho (void) printf(gettext("Writing root directory. "
31795121Sfrankho "%d bytes.\n"), rdirsize);
31800Sstevel@tonic-gate if (!Notreally) {
31810Sstevel@tonic-gate if (write(fd, rdirp, rdirsize) != rdirsize) {
31820Sstevel@tonic-gate perror(gettext("Root directory write"));
31830Sstevel@tonic-gate exit(4);
31840Sstevel@tonic-gate }
31850Sstevel@tonic-gate }
31860Sstevel@tonic-gate free(rdirp);
31870Sstevel@tonic-gate }
31880Sstevel@tonic-gate
31890Sstevel@tonic-gate if (fffd >= 0) {
31900Sstevel@tonic-gate if (Verbose)
31910Sstevel@tonic-gate (void) printf(gettext("Writing first file.\n"));
31920Sstevel@tonic-gate if (!Notreally)
31930Sstevel@tonic-gate write_rest(wbpb, ffn, fd, fffd, ffsize);
31940Sstevel@tonic-gate }
31950Sstevel@tonic-gate }
31960Sstevel@tonic-gate
31970Sstevel@tonic-gate static
31980Sstevel@tonic-gate char *LegalOpts[] = {
31990Sstevel@tonic-gate #define NFLAG 0
32000Sstevel@tonic-gate "N",
32010Sstevel@tonic-gate #define VFLAG 1
32020Sstevel@tonic-gate "v",
32030Sstevel@tonic-gate #define RFLAG 2
32040Sstevel@tonic-gate "r",
32050Sstevel@tonic-gate #define HFLAG 3
32060Sstevel@tonic-gate "h",
32070Sstevel@tonic-gate #define SFLAG 4
32080Sstevel@tonic-gate "s",
32090Sstevel@tonic-gate #define SUNFLAG 5
32100Sstevel@tonic-gate "S",
32110Sstevel@tonic-gate #define LABFLAG 6
32120Sstevel@tonic-gate "b",
32130Sstevel@tonic-gate #define BTRFLAG 7
32140Sstevel@tonic-gate "B",
32150Sstevel@tonic-gate #define INITFLAG 8
32160Sstevel@tonic-gate "i",
32170Sstevel@tonic-gate #define SZFLAG 9
32180Sstevel@tonic-gate "size",
32190Sstevel@tonic-gate #define SECTFLAG 10
32200Sstevel@tonic-gate "nsect",
32210Sstevel@tonic-gate #define TRKFLAG 11
32220Sstevel@tonic-gate "ntrack",
32230Sstevel@tonic-gate #define SPCFLAG 12
32240Sstevel@tonic-gate "spc",
32250Sstevel@tonic-gate #define BPFFLAG 13
32260Sstevel@tonic-gate "fat",
32270Sstevel@tonic-gate #define FFLAG 14
32280Sstevel@tonic-gate "f",
32290Sstevel@tonic-gate #define DFLAG 15
32300Sstevel@tonic-gate "d",
32310Sstevel@tonic-gate #define NOFDISKFLAG 16
32320Sstevel@tonic-gate "nofdisk",
32330Sstevel@tonic-gate #define RESRVFLAG 17
32340Sstevel@tonic-gate "reserve",
32350Sstevel@tonic-gate #define HIDDENFLAG 18
32360Sstevel@tonic-gate "hidden",
32370Sstevel@tonic-gate NULL
32380Sstevel@tonic-gate };
32390Sstevel@tonic-gate
32400Sstevel@tonic-gate static
32410Sstevel@tonic-gate void
bad_arg(char * option)32420Sstevel@tonic-gate bad_arg(char *option)
32430Sstevel@tonic-gate {
32440Sstevel@tonic-gate (void) fprintf(stderr,
32455121Sfrankho gettext("Unrecognized option %s.\n"), option);
32460Sstevel@tonic-gate usage();
32470Sstevel@tonic-gate exit(2);
32480Sstevel@tonic-gate }
32490Sstevel@tonic-gate
32500Sstevel@tonic-gate static
32510Sstevel@tonic-gate void
missing_arg(char * option)32520Sstevel@tonic-gate missing_arg(char *option)
32530Sstevel@tonic-gate {
32540Sstevel@tonic-gate (void) fprintf(stderr,
32555121Sfrankho gettext("Option %s requires a value.\n"), option);
32560Sstevel@tonic-gate usage();
32570Sstevel@tonic-gate exit(3);
32580Sstevel@tonic-gate }
32590Sstevel@tonic-gate
32600Sstevel@tonic-gate static
32610Sstevel@tonic-gate void
parse_suboptions(char * optsstr)32620Sstevel@tonic-gate parse_suboptions(char *optsstr)
32630Sstevel@tonic-gate {
32640Sstevel@tonic-gate char *value;
32650Sstevel@tonic-gate int c;
32660Sstevel@tonic-gate
32670Sstevel@tonic-gate while (*optsstr != '\0') {
32680Sstevel@tonic-gate switch (c = getsubopt(&optsstr, LegalOpts, &value)) {
32690Sstevel@tonic-gate case NFLAG:
32700Sstevel@tonic-gate Notreally++;
32710Sstevel@tonic-gate break;
32720Sstevel@tonic-gate case VFLAG:
32730Sstevel@tonic-gate Verbose++;
32740Sstevel@tonic-gate break;
32750Sstevel@tonic-gate case RFLAG:
32760Sstevel@tonic-gate Firstfileattr |= 0x01;
32770Sstevel@tonic-gate break;
32780Sstevel@tonic-gate case HFLAG:
32790Sstevel@tonic-gate Firstfileattr |= 0x02;
32800Sstevel@tonic-gate break;
32810Sstevel@tonic-gate case SFLAG:
32820Sstevel@tonic-gate Firstfileattr |= 0x04;
32830Sstevel@tonic-gate break;
32840Sstevel@tonic-gate case SUNFLAG:
32850Sstevel@tonic-gate SunBPBfields = 1;
32860Sstevel@tonic-gate break;
32870Sstevel@tonic-gate case LABFLAG:
32880Sstevel@tonic-gate if (value == NULL) {
32890Sstevel@tonic-gate missing_arg(LegalOpts[c]);
32900Sstevel@tonic-gate } else {
32910Sstevel@tonic-gate Label = value;
32920Sstevel@tonic-gate }
32930Sstevel@tonic-gate break;
32940Sstevel@tonic-gate case BTRFLAG:
32950Sstevel@tonic-gate if (value == NULL) {
32960Sstevel@tonic-gate missing_arg(LegalOpts[c]);
32970Sstevel@tonic-gate } else {
32980Sstevel@tonic-gate BootBlkFn = value;
32990Sstevel@tonic-gate }
33000Sstevel@tonic-gate break;
33010Sstevel@tonic-gate case INITFLAG:
33020Sstevel@tonic-gate if (value == NULL) {
33030Sstevel@tonic-gate missing_arg(LegalOpts[c]);
33040Sstevel@tonic-gate } else {
33050Sstevel@tonic-gate FirstFn = value;
33060Sstevel@tonic-gate }
33070Sstevel@tonic-gate break;
33080Sstevel@tonic-gate case SZFLAG:
33090Sstevel@tonic-gate if (value == NULL) {
33100Sstevel@tonic-gate missing_arg(LegalOpts[c]);
33110Sstevel@tonic-gate } else {
33120Sstevel@tonic-gate TotSize = atoi(value);
33130Sstevel@tonic-gate GetSize = 0;
33140Sstevel@tonic-gate }
33150Sstevel@tonic-gate break;
33160Sstevel@tonic-gate case SECTFLAG:
33170Sstevel@tonic-gate if (value == NULL) {
33180Sstevel@tonic-gate missing_arg(LegalOpts[c]);
33190Sstevel@tonic-gate } else {
33200Sstevel@tonic-gate SecPerTrk = atoi(value);
33210Sstevel@tonic-gate GetSPT = 0;
33220Sstevel@tonic-gate }
33230Sstevel@tonic-gate break;
33240Sstevel@tonic-gate case TRKFLAG:
33250Sstevel@tonic-gate if (value == NULL) {
33260Sstevel@tonic-gate missing_arg(LegalOpts[c]);
33270Sstevel@tonic-gate } else {
33280Sstevel@tonic-gate TrkPerCyl = atoi(value);
33290Sstevel@tonic-gate GetTPC = 0;
33300Sstevel@tonic-gate }
33310Sstevel@tonic-gate break;
33320Sstevel@tonic-gate case SPCFLAG:
33330Sstevel@tonic-gate if (value == NULL) {
33340Sstevel@tonic-gate missing_arg(LegalOpts[c]);
33350Sstevel@tonic-gate } else {
33360Sstevel@tonic-gate SecPerClust = atoi(value);
33370Sstevel@tonic-gate GetSPC = 0;
33380Sstevel@tonic-gate }
33390Sstevel@tonic-gate break;
33400Sstevel@tonic-gate case BPFFLAG:
33410Sstevel@tonic-gate if (value == NULL) {
33420Sstevel@tonic-gate missing_arg(LegalOpts[c]);
33430Sstevel@tonic-gate } else {
33440Sstevel@tonic-gate BitsPerFAT = atoi(value);
33450Sstevel@tonic-gate GetBPF = 0;
33460Sstevel@tonic-gate }
33470Sstevel@tonic-gate break;
33480Sstevel@tonic-gate case NOFDISKFLAG:
33490Sstevel@tonic-gate DontUseFdisk = 1;
33500Sstevel@tonic-gate break;
33510Sstevel@tonic-gate case RESRVFLAG:
33520Sstevel@tonic-gate if (value == NULL) {
33530Sstevel@tonic-gate missing_arg(LegalOpts[c]);
33540Sstevel@tonic-gate } else {
33550Sstevel@tonic-gate Resrvd = atoi(value);
33560Sstevel@tonic-gate GetResrvd = 0;
33570Sstevel@tonic-gate }
33580Sstevel@tonic-gate break;
33590Sstevel@tonic-gate case HIDDENFLAG:
33600Sstevel@tonic-gate if (value == NULL) {
33610Sstevel@tonic-gate missing_arg(LegalOpts[c]);
33620Sstevel@tonic-gate } else {
33630Sstevel@tonic-gate RelOffset = atoi(value);
33640Sstevel@tonic-gate GetOffset = 0;
33650Sstevel@tonic-gate }
33660Sstevel@tonic-gate break;
33670Sstevel@tonic-gate case FFLAG:
33680Sstevel@tonic-gate if (value == NULL) {
33690Sstevel@tonic-gate missing_arg(LegalOpts[c]);
33700Sstevel@tonic-gate } else {
33710Sstevel@tonic-gate DiskName = value;
33720Sstevel@tonic-gate Outputtofile = 1;
33730Sstevel@tonic-gate }
33740Sstevel@tonic-gate break;
33750Sstevel@tonic-gate case DFLAG:
33760Sstevel@tonic-gate if (value == NULL) {
33770Sstevel@tonic-gate missing_arg(LegalOpts[c]);
33780Sstevel@tonic-gate } else {
33790Sstevel@tonic-gate Imagesize = atoi(value);
33800Sstevel@tonic-gate }
33810Sstevel@tonic-gate break;
33820Sstevel@tonic-gate default:
33830Sstevel@tonic-gate bad_arg(value);
33840Sstevel@tonic-gate break;
33850Sstevel@tonic-gate }
33860Sstevel@tonic-gate }
33870Sstevel@tonic-gate }
33880Sstevel@tonic-gate
33890Sstevel@tonic-gate static
33900Sstevel@tonic-gate void
sanity_check_options(int argc,int optind)33910Sstevel@tonic-gate sanity_check_options(int argc, int optind)
33920Sstevel@tonic-gate {
33930Sstevel@tonic-gate if (GetFsParams) {
33940Sstevel@tonic-gate if (argc - optind != 1)
33950Sstevel@tonic-gate usage();
33960Sstevel@tonic-gate return;
33970Sstevel@tonic-gate }
33980Sstevel@tonic-gate
33990Sstevel@tonic-gate if (DontUseFdisk && GetOffset) {
34000Sstevel@tonic-gate /* Set default relative offset of zero */
34010Sstevel@tonic-gate RelOffset = 0;
34020Sstevel@tonic-gate }
34030Sstevel@tonic-gate
34040Sstevel@tonic-gate if (BitsPerFAT == 32)
34050Sstevel@tonic-gate MakeFAT32 = 1;
34060Sstevel@tonic-gate
34070Sstevel@tonic-gate if (Outputtofile && (argc - optind)) {
34080Sstevel@tonic-gate usage();
34090Sstevel@tonic-gate } else if (Outputtofile && !DiskName) {
34100Sstevel@tonic-gate usage();
34110Sstevel@tonic-gate } else if (!Outputtofile && (argc - optind != 1)) {
34120Sstevel@tonic-gate usage();
34130Sstevel@tonic-gate } else if (SunBPBfields && !BootBlkFn) {
34140Sstevel@tonic-gate (void) fprintf(stderr,
34150Sstevel@tonic-gate gettext("Use of the 'S' option requires that\n"
34165121Sfrankho "the 'B=' option also be used.\n\n"));
34170Sstevel@tonic-gate usage();
34180Sstevel@tonic-gate } else if (Firstfileattr != 0x20 && !FirstFn) {
34190Sstevel@tonic-gate (void) fprintf(stderr,
34200Sstevel@tonic-gate gettext("Use of the 'r', 'h', or 's' options requires\n"
34215121Sfrankho "that the 'i=' option also be used.\n\n"));
34220Sstevel@tonic-gate usage();
34230Sstevel@tonic-gate } else if (!GetOffset && !DontUseFdisk) {
34240Sstevel@tonic-gate (void) fprintf(stderr,
34250Sstevel@tonic-gate gettext("Use of the 'hidden' option requires that\n"
34265121Sfrankho "the 'nofdisk' option also be used.\n\n"));
34270Sstevel@tonic-gate usage();
34280Sstevel@tonic-gate } else if (DontUseFdisk && GetSize) {
34290Sstevel@tonic-gate (void) fprintf(stderr,
34300Sstevel@tonic-gate gettext("Use of the 'nofdisk' option requires that\n"
34315121Sfrankho "the 'size=' option also be used.\n\n"));
34320Sstevel@tonic-gate usage();
34330Sstevel@tonic-gate } else if (!GetBPF &&
34345121Sfrankho BitsPerFAT != 12 && BitsPerFAT != 16 && BitsPerFAT != 32) {
34355121Sfrankho (void) fprintf(stderr, gettext("Invalid Bits/Fat value."
34365121Sfrankho " Must be 12, 16 or 32.\n"));
34370Sstevel@tonic-gate exit(2);
34380Sstevel@tonic-gate } else if (!GetSPC && !powerofx_le_y(2, 128, SecPerClust)) {
34390Sstevel@tonic-gate (void) fprintf(stderr,
34400Sstevel@tonic-gate gettext("Invalid Sectors/Cluster value. Must be a "
34415121Sfrankho "power of 2 between 1 and 128.\n"));
34420Sstevel@tonic-gate exit(2);
34430Sstevel@tonic-gate } else if (!GetResrvd && (Resrvd < 1 || Resrvd > 0xffff)) {
34440Sstevel@tonic-gate (void) fprintf(stderr,
34450Sstevel@tonic-gate gettext("Invalid number of reserved sectors. "
34465121Sfrankho "Must be at least 1 but\nno larger than 65535."));
34470Sstevel@tonic-gate exit(2);
34480Sstevel@tonic-gate } else if (!GetResrvd && MakeFAT32 &&
34495121Sfrankho (Resrvd < 32 || Resrvd > 0xffff)) {
34500Sstevel@tonic-gate (void) fprintf(stderr,
34510Sstevel@tonic-gate gettext("Invalid number of reserved sectors. "
34525121Sfrankho "Must be at least 32 but\nno larger than 65535."));
34530Sstevel@tonic-gate exit(2);
34540Sstevel@tonic-gate } else if (Imagesize != 3 && Imagesize != 5) {
34550Sstevel@tonic-gate usage();
34560Sstevel@tonic-gate }
34570Sstevel@tonic-gate }
34580Sstevel@tonic-gate
3459452Sjkennedy int
main(int argc,char ** argv)34600Sstevel@tonic-gate main(int argc, char **argv)
34610Sstevel@tonic-gate {
34620Sstevel@tonic-gate off64_t AbsBootSect = 0;
34630Sstevel@tonic-gate bpb_t dskparamblk;
34640Sstevel@tonic-gate char *string;
34650Sstevel@tonic-gate int fd;
34660Sstevel@tonic-gate int c;
34670Sstevel@tonic-gate
34680Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
34690Sstevel@tonic-gate
34700Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
34710Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
34720Sstevel@tonic-gate #endif
34730Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
34740Sstevel@tonic-gate
34750Sstevel@tonic-gate while ((c = getopt(argc, argv, "F:Vmo:")) != EOF) {
34760Sstevel@tonic-gate switch (c) {
34770Sstevel@tonic-gate case 'F':
34780Sstevel@tonic-gate string = optarg;
34790Sstevel@tonic-gate if (strcmp(string, "pcfs") != 0)
34800Sstevel@tonic-gate usage();
34810Sstevel@tonic-gate break;
34820Sstevel@tonic-gate case 'V':
34830Sstevel@tonic-gate {
34840Sstevel@tonic-gate char *opt_text;
34850Sstevel@tonic-gate int opt_count;
34860Sstevel@tonic-gate
34870Sstevel@tonic-gate (void) fprintf(stdout,
34880Sstevel@tonic-gate gettext("mkfs -F pcfs "));
34890Sstevel@tonic-gate for (opt_count = 1; opt_count < argc;
34905121Sfrankho opt_count++) {
34910Sstevel@tonic-gate opt_text = argv[opt_count];
34920Sstevel@tonic-gate if (opt_text)
34935121Sfrankho (void) fprintf(stdout,
34945121Sfrankho " %s ", opt_text);
34950Sstevel@tonic-gate }
34960Sstevel@tonic-gate (void) fprintf(stdout, "\n");
34970Sstevel@tonic-gate }
34980Sstevel@tonic-gate break;
34990Sstevel@tonic-gate case 'm':
35000Sstevel@tonic-gate GetFsParams++;
35010Sstevel@tonic-gate break;
35020Sstevel@tonic-gate case 'o':
35030Sstevel@tonic-gate string = optarg;
35040Sstevel@tonic-gate parse_suboptions(string);
35050Sstevel@tonic-gate break;
35060Sstevel@tonic-gate }
35070Sstevel@tonic-gate }
35080Sstevel@tonic-gate
35090Sstevel@tonic-gate sanity_check_options(argc, optind);
35100Sstevel@tonic-gate
35110Sstevel@tonic-gate if (!Outputtofile)
35120Sstevel@tonic-gate DiskName = argv[optind];
35130Sstevel@tonic-gate
35140Sstevel@tonic-gate (void) memset(&dskparamblk, 0, sizeof (dskparamblk));
35150Sstevel@tonic-gate
35160Sstevel@tonic-gate if (GetFsParams) {
35170Sstevel@tonic-gate fd = open_and_examine(DiskName, &dskparamblk);
35180Sstevel@tonic-gate } else {
35190Sstevel@tonic-gate fd = open_and_seek(DiskName, &dskparamblk, &AbsBootSect);
35200Sstevel@tonic-gate if (ask_nicely(DiskName))
35210Sstevel@tonic-gate write_fat(fd, AbsBootSect, BootBlkFn, Label,
35220Sstevel@tonic-gate FirstFn, &dskparamblk);
35230Sstevel@tonic-gate }
35240Sstevel@tonic-gate (void) close(fd);
3525452Sjkennedy return (0);
35260Sstevel@tonic-gate }
3527