1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright (c) 1996, 1998-2001 by Sun Microsystems, Inc. 24*0Sstevel@tonic-gate * All rights reserved. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/types.h> 30*0Sstevel@tonic-gate #include <ctype.h> 31*0Sstevel@tonic-gate #include <unistd.h> 32*0Sstevel@tonic-gate #include <stdio.h> 33*0Sstevel@tonic-gate #include <stdlib.h> 34*0Sstevel@tonic-gate #include <string.h> 35*0Sstevel@tonic-gate #include <errno.h> 36*0Sstevel@tonic-gate #include <fcntl.h> 37*0Sstevel@tonic-gate #include <libintl.h> 38*0Sstevel@tonic-gate #include <locale.h> 39*0Sstevel@tonic-gate #include <sys/fdio.h> 40*0Sstevel@tonic-gate #include <sys/dktp/fdisk.h> 41*0Sstevel@tonic-gate #include <sys/dkio.h> 42*0Sstevel@tonic-gate #include <sys/sysmacros.h> 43*0Sstevel@tonic-gate #include "mkfs_pcfs.h" 44*0Sstevel@tonic-gate #include <sys/fs/pc_fs.h> 45*0Sstevel@tonic-gate #include <sys/fs/pc_dir.h> 46*0Sstevel@tonic-gate #include <sys/fs/pc_label.h> 47*0Sstevel@tonic-gate #include <macros.h> 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate /* 50*0Sstevel@tonic-gate * mkfs (for pcfs) 51*0Sstevel@tonic-gate * 52*0Sstevel@tonic-gate * Install a boot block, FAT, and (if desired) the first resident 53*0Sstevel@tonic-gate * of the new fs. 54*0Sstevel@tonic-gate * 55*0Sstevel@tonic-gate * XXX -- floppy opens need O_NDELAY? 56*0Sstevel@tonic-gate */ 57*0Sstevel@tonic-gate #define DEFAULT_LABEL "NONAME" 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate static char *BootBlkFn = NULL; 60*0Sstevel@tonic-gate static char *DiskName = NULL; 61*0Sstevel@tonic-gate static char *FirstFn = NULL; 62*0Sstevel@tonic-gate static char *Label = NULL; 63*0Sstevel@tonic-gate static char Firstfileattr = 0x20; 64*0Sstevel@tonic-gate static int Outputtofile = 0; 65*0Sstevel@tonic-gate static int SunBPBfields = 0; 66*0Sstevel@tonic-gate static int GetFsParams = 0; 67*0Sstevel@tonic-gate static int Fatentsize = 0; 68*0Sstevel@tonic-gate static int Imagesize = 3; 69*0Sstevel@tonic-gate static int Notreally = 0; 70*0Sstevel@tonic-gate static int Verbose = 0; 71*0Sstevel@tonic-gate static int MakeFAT32 = 0; 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate /* 74*0Sstevel@tonic-gate * If there is an FDISK entry for the device where we're about to 75*0Sstevel@tonic-gate * make the file system, we ought to make a file system that has the 76*0Sstevel@tonic-gate * same size FAT as the FDISK table claims. We track the size FDISK 77*0Sstevel@tonic-gate * thinks in this variable. 78*0Sstevel@tonic-gate */ 79*0Sstevel@tonic-gate static int FdiskFATsize = 0; 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate static int GetSize = 1; /* Unless we're given as arg, must look it up */ 82*0Sstevel@tonic-gate static ulong_t TotSize; /* Total size of FS in # of sectors */ 83*0Sstevel@tonic-gate static int GetSPC = 1; /* Unless we're given as arg, must calculate */ 84*0Sstevel@tonic-gate static ulong_t SecPerClust; /* # of sectors per cluster */ 85*0Sstevel@tonic-gate static int GetOffset = 1; /* Unless we're given as arg, must look it up */ 86*0Sstevel@tonic-gate static ulong_t RelOffset; /* Relative start sector (hidden sectors) */ 87*0Sstevel@tonic-gate static int GetSPT = 1; /* Unless we're given as arg, must look it up */ 88*0Sstevel@tonic-gate static ushort_t SecPerTrk; /* # of sectors per track */ 89*0Sstevel@tonic-gate static int GetTPC = 1; /* Unless we're given as arg, must look it up */ 90*0Sstevel@tonic-gate static ushort_t TrkPerCyl; /* # of tracks per cylinder */ 91*0Sstevel@tonic-gate static int GetResrvd = 1; /* Unless we're given as arg, must calculate */ 92*0Sstevel@tonic-gate static ushort_t Resrvd; /* Number of reserved sectors */ 93*0Sstevel@tonic-gate static int GetBPF = 1; /* Unless we're given as arg, must calculate */ 94*0Sstevel@tonic-gate static int BitsPerFAT; /* Total size of FS in # of sectors */ 95*0Sstevel@tonic-gate 96*0Sstevel@tonic-gate static ulong_t TotalClusters; /* Computed total number of clusters */ 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate /* 99*0Sstevel@tonic-gate * Unless we are told otherwise, we should use fdisk table for non-diskettes. 100*0Sstevel@tonic-gate */ 101*0Sstevel@tonic-gate static int DontUseFdisk = 0; 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate /* 104*0Sstevel@tonic-gate * Function prototypes 105*0Sstevel@tonic-gate */ 106*0Sstevel@tonic-gate #ifndef i386 107*0Sstevel@tonic-gate static void swap_pack_grabsebpb(bpb_t *wbpb, struct _boot_sector *bsp); 108*0Sstevel@tonic-gate static void swap_pack_bpb32cpy(struct _boot_sector32 *bsp, bpb_t *wbpb); 109*0Sstevel@tonic-gate static void swap_pack_sebpbcpy(struct _boot_sector *bsp, bpb_t *wbpb); 110*0Sstevel@tonic-gate static void swap_pack_grabbpb(bpb_t *wbpb, struct _boot_sector *bsp); 111*0Sstevel@tonic-gate static void swap_pack_bpbcpy(struct _boot_sector *bsp, bpb_t *wbpb); 112*0Sstevel@tonic-gate #endif 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate static uchar_t *build_rootdir(bpb_t *wbpb, char *ffn, int fffd, 115*0Sstevel@tonic-gate ulong_t ffsize, pc_cluster32_t ffstart, ulong_t *rdirsize); 116*0Sstevel@tonic-gate static uchar_t *build_fat(bpb_t *wbpb, struct fat32_boot_fsinfo *fsinfop, 117*0Sstevel@tonic-gate ulong_t bootblksize, ulong_t *fatsize, char *ffn, int *fffd, 118*0Sstevel@tonic-gate ulong_t *ffsize, pc_cluster32_t *ffstartclust); 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate static char *stat_actual_disk(char *diskname, struct stat *info, char **suffix); 121*0Sstevel@tonic-gate 122*0Sstevel@tonic-gate static void compare_existing_with_computed(int fd, char *suffix, 123*0Sstevel@tonic-gate bpb_t *wbpb, int *prtsize, int *prtspc, int *prtbpf, int *prtnsect, 124*0Sstevel@tonic-gate int *prtntrk, int *prtfdisk, int *prthidden, int *prtrsrvd, 125*0Sstevel@tonic-gate int *dashos); 126*0Sstevel@tonic-gate static void print_reproducing_command(int fd, char *actualdisk, char *suffix, 127*0Sstevel@tonic-gate bpb_t *wbpb); 128*0Sstevel@tonic-gate static void compute_file_area_size(bpb_t *wbpb); 129*0Sstevel@tonic-gate static void write_fat32_bootstuff(int fd, boot_sector_t *bsp, 130*0Sstevel@tonic-gate struct fat32_boot_fsinfo *fsinfop, off64_t seekto); 131*0Sstevel@tonic-gate static void sanity_check_options(int argc, int optind); 132*0Sstevel@tonic-gate static void compute_cluster_size(bpb_t *wbpb); 133*0Sstevel@tonic-gate static void find_fixed_details(int fd, bpb_t *wbpb); 134*0Sstevel@tonic-gate static void dirent_fname_fill(struct pcdir *dep, char *fn); 135*0Sstevel@tonic-gate static void floppy_bpb_fillin(bpb_t *wbpb, 136*0Sstevel@tonic-gate int diam, int hds, int spt); 137*0Sstevel@tonic-gate static void read_existing_bpb(int fd, bpb_t *wbpb); 138*0Sstevel@tonic-gate static void warn_funky_fatsize(void); 139*0Sstevel@tonic-gate static void warn_funky_floppy(void); 140*0Sstevel@tonic-gate static void dirent_time_fill(struct pcdir *dep); 141*0Sstevel@tonic-gate static void parse_suboptions(char *optsstr); 142*0Sstevel@tonic-gate static void header_for_dump(void); 143*0Sstevel@tonic-gate static void write_bootsects(int fd, boot_sector_t *bsp, bpb_t *wbpb, 144*0Sstevel@tonic-gate struct fat32_boot_fsinfo *fsinfop, off64_t seekto); 145*0Sstevel@tonic-gate static void fill_bpb_sizes(bpb_t *wbpb, struct ipart part[], 146*0Sstevel@tonic-gate int partno, off64_t offset); 147*0Sstevel@tonic-gate static void set_fat_string(bpb_t *wbpb, int fatsize); 148*0Sstevel@tonic-gate static void partn_lecture(char *dn); 149*0Sstevel@tonic-gate static void store_16_bits(uchar_t **bp, uint32_t v); 150*0Sstevel@tonic-gate static void store_32_bits(uchar_t **bp, uint32_t v); 151*0Sstevel@tonic-gate static void lookup_floppy(struct fd_char *fdchar, bpb_t *wbpb); 152*0Sstevel@tonic-gate static void label_volume(char *lbl, bpb_t *wbpb); 153*0Sstevel@tonic-gate static void mark_cluster(uchar_t *fatp, pc_cluster32_t clustnum, 154*0Sstevel@tonic-gate uint32_t value); 155*0Sstevel@tonic-gate static void missing_arg(char *option); 156*0Sstevel@tonic-gate static void dashm_bail(int fd); 157*0Sstevel@tonic-gate static void dump_bytes(uchar_t *, int); 158*0Sstevel@tonic-gate static void write_rest(bpb_t *wbpb, char *efn, 159*0Sstevel@tonic-gate int dfd, int sfd, int remaining); 160*0Sstevel@tonic-gate static void write_fat(int fd, off64_t seekto, char *fn, char *lbl, 161*0Sstevel@tonic-gate char *ffn, bpb_t *wbpb); 162*0Sstevel@tonic-gate static void bad_arg(char *option); 163*0Sstevel@tonic-gate static void usage(void); 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate static int prepare_image_file(char *fn, bpb_t *wbpb); 166*0Sstevel@tonic-gate static int verify_bootblkfile(char *fn, boot_sector_t *bs, 167*0Sstevel@tonic-gate ulong_t *blkfilesize); 168*0Sstevel@tonic-gate static int open_and_examine(char *dn, bpb_t *wbpb); 169*0Sstevel@tonic-gate static int verify_firstfile(char *fn, ulong_t *filesize); 170*0Sstevel@tonic-gate static int lookup_FAT_size(uchar_t partid); 171*0Sstevel@tonic-gate static int powerofx_le_y(int x, int y, int value); 172*0Sstevel@tonic-gate static int open_and_seek(char *dn, bpb_t *wbpb, off64_t *seekto); 173*0Sstevel@tonic-gate static int warn_mismatch(char *desc, char *src, int expect, int assigned); 174*0Sstevel@tonic-gate static int copy_bootblk(char *fn, boot_sector_t *bootsect, 175*0Sstevel@tonic-gate ulong_t *bootblksize); 176*0Sstevel@tonic-gate static int parse_drvnum(char *pn); 177*0Sstevel@tonic-gate static int seek_nofdisk(int fd, bpb_t *wbpb, off64_t *seekto); 178*0Sstevel@tonic-gate static int ask_nicely(char *special); 179*0Sstevel@tonic-gate static int seek_partn(int fd, char *pn, bpb_t *wbpb, off64_t *seekto); 180*0Sstevel@tonic-gate static int yes(void); 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate /* 183*0Sstevel@tonic-gate * usage 184*0Sstevel@tonic-gate * 185*0Sstevel@tonic-gate * Display usage message and exit. 186*0Sstevel@tonic-gate */ 187*0Sstevel@tonic-gate static 188*0Sstevel@tonic-gate void 189*0Sstevel@tonic-gate usage(void) 190*0Sstevel@tonic-gate { 191*0Sstevel@tonic-gate (void) fprintf(stderr, 192*0Sstevel@tonic-gate gettext("pcfs usage: mkfs [-F FSType] [-V] [-m] " 193*0Sstevel@tonic-gate "[-o specific_options] special\n")); 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate (void) fprintf(stderr, 196*0Sstevel@tonic-gate gettext(" -V: print this command line and return\n" 197*0Sstevel@tonic-gate " -m: dump command line used to create a FAT on this media\n" 198*0Sstevel@tonic-gate "\t(other options are ignored if this option is chosen).\n" 199*0Sstevel@tonic-gate " -o: pcfs_specific_options:\n" 200*0Sstevel@tonic-gate "\t'pcfs_specific_options' is a comma separated list\n" 201*0Sstevel@tonic-gate "\tincluding one or more of the following options:\n" 202*0Sstevel@tonic-gate "\t N,v,r,h,s,b=label,B=filename,i=filename,\n" 203*0Sstevel@tonic-gate "\t spc=n,fat=n,nsect=n,ntrack=n,nofdisk,size=n,\n" 204*0Sstevel@tonic-gate "\t reserve=n,hidden=n\n\n")); 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate (void) fprintf(stderr, 207*0Sstevel@tonic-gate gettext("'Special' should specify a raw diskette " 208*0Sstevel@tonic-gate "or raw fixed disk device. \"Fixed\"\n" 209*0Sstevel@tonic-gate "disks (which include high-capacity removable " 210*0Sstevel@tonic-gate "media such as Zip disks)\n" 211*0Sstevel@tonic-gate "may be further qualified with a logical " 212*0Sstevel@tonic-gate "drive specifier.\n" 213*0Sstevel@tonic-gate "Examples are: /dev/rdiskette and " 214*0Sstevel@tonic-gate "/dev/rdsk/c0t0d0p0:c\n")); 215*0Sstevel@tonic-gate exit(1); 216*0Sstevel@tonic-gate } 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate static 219*0Sstevel@tonic-gate int 220*0Sstevel@tonic-gate yes(void) 221*0Sstevel@tonic-gate { 222*0Sstevel@tonic-gate char *affirmative = gettext("yY"); 223*0Sstevel@tonic-gate char *a = affirmative; 224*0Sstevel@tonic-gate int b; 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate b = getchar(); 227*0Sstevel@tonic-gate while (b == '\n' && b != '\0' && b != EOF) 228*0Sstevel@tonic-gate b = getchar(); 229*0Sstevel@tonic-gate while (*a) { 230*0Sstevel@tonic-gate if (b == (int)*a) 231*0Sstevel@tonic-gate break; 232*0Sstevel@tonic-gate a++; 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate return (*a); 235*0Sstevel@tonic-gate } 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate /* 238*0Sstevel@tonic-gate * powerofx_le_y 239*0Sstevel@tonic-gate * args of x,y, and value to be checked 240*0Sstevel@tonic-gate * returns 1 if x**n == value and n >= 0 and value <= y 241*0Sstevel@tonic-gate * returns 0 otherwise 242*0Sstevel@tonic-gate */ 243*0Sstevel@tonic-gate static 244*0Sstevel@tonic-gate int 245*0Sstevel@tonic-gate powerofx_le_y(int x, int y, int value) 246*0Sstevel@tonic-gate { 247*0Sstevel@tonic-gate int ispower = 0; 248*0Sstevel@tonic-gate int pow = 1; 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate if (value < 1 || value > y) 251*0Sstevel@tonic-gate return (ispower); 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate do { 254*0Sstevel@tonic-gate if (pow == value) { 255*0Sstevel@tonic-gate ispower = 1; 256*0Sstevel@tonic-gate break; 257*0Sstevel@tonic-gate } 258*0Sstevel@tonic-gate pow *= x; 259*0Sstevel@tonic-gate } while (pow <= y); 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate return (ispower); 262*0Sstevel@tonic-gate } 263*0Sstevel@tonic-gate 264*0Sstevel@tonic-gate static 265*0Sstevel@tonic-gate int 266*0Sstevel@tonic-gate ask_nicely(char *special) 267*0Sstevel@tonic-gate { 268*0Sstevel@tonic-gate /* 269*0Sstevel@tonic-gate * 4228473 - No way to non-interactively make a pcfs filesystem 270*0Sstevel@tonic-gate * 271*0Sstevel@tonic-gate * If we don't have an input TTY, or we aren't really doing 272*0Sstevel@tonic-gate * anything, then don't ask questions. Assume a yes answer 273*0Sstevel@tonic-gate * to any questions we would ask. 274*0Sstevel@tonic-gate */ 275*0Sstevel@tonic-gate if (Notreally || !isatty(fileno(stdin))) 276*0Sstevel@tonic-gate return (1); 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate (void) printf( 279*0Sstevel@tonic-gate gettext("Construct a new FAT file system on %s: (y/n)? "), special); 280*0Sstevel@tonic-gate (void) fflush(stdout); 281*0Sstevel@tonic-gate return (yes()); 282*0Sstevel@tonic-gate } 283*0Sstevel@tonic-gate 284*0Sstevel@tonic-gate /* 285*0Sstevel@tonic-gate * store_16_bits 286*0Sstevel@tonic-gate * Save the lower 16 bits of a 32 bit value (v) into the provided 287*0Sstevel@tonic-gate * buffer (pointed at by *bp), and increment the buffer pointer 288*0Sstevel@tonic-gate * as well. This way the routine can be called multiple times in 289*0Sstevel@tonic-gate * succession to fill buffers. The value is stored in little-endian 290*0Sstevel@tonic-gate * order. 291*0Sstevel@tonic-gate */ 292*0Sstevel@tonic-gate static 293*0Sstevel@tonic-gate void 294*0Sstevel@tonic-gate store_16_bits(uchar_t **bp, uint32_t v) 295*0Sstevel@tonic-gate { 296*0Sstevel@tonic-gate uchar_t *l = *bp; 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate *l++ = v & 0xff; 299*0Sstevel@tonic-gate *l = (v >> 8) & 0xff; 300*0Sstevel@tonic-gate *bp += 2; 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate /* 304*0Sstevel@tonic-gate * store_32_bits 305*0Sstevel@tonic-gate * Save the 32 bit value (v) into the provided buffer (pointed 306*0Sstevel@tonic-gate * at by *bp), and increment the buffer pointer as well. This way 307*0Sstevel@tonic-gate * the routine can be called multiple times in succession to fill 308*0Sstevel@tonic-gate * buffers. The value is stored in little-endian order. 309*0Sstevel@tonic-gate */ 310*0Sstevel@tonic-gate static 311*0Sstevel@tonic-gate void 312*0Sstevel@tonic-gate store_32_bits(uchar_t **bp, uint32_t v) 313*0Sstevel@tonic-gate { 314*0Sstevel@tonic-gate uchar_t *l = *bp; 315*0Sstevel@tonic-gate int b; 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate for (b = 0; b < 4; b++) { 318*0Sstevel@tonic-gate *l++ = v & 0xff; 319*0Sstevel@tonic-gate v = v >> 8; 320*0Sstevel@tonic-gate } 321*0Sstevel@tonic-gate *bp += 4; 322*0Sstevel@tonic-gate } 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate /* 325*0Sstevel@tonic-gate * dump_bytes -- display bytes as hex numbers. 326*0Sstevel@tonic-gate * b is the pointer to the byte buffer 327*0Sstevel@tonic-gate * n is the number of bytes in the buffer 328*0Sstevel@tonic-gate */ 329*0Sstevel@tonic-gate /* Note: BPL = bytes to display per line */ 330*0Sstevel@tonic-gate #define BPL 16 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate static 333*0Sstevel@tonic-gate void 334*0Sstevel@tonic-gate dump_bytes(uchar_t *b, int n) 335*0Sstevel@tonic-gate { 336*0Sstevel@tonic-gate int cd = n; 337*0Sstevel@tonic-gate int cu = 0; 338*0Sstevel@tonic-gate int o = 0; 339*0Sstevel@tonic-gate int bl; 340*0Sstevel@tonic-gate int ac; 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate /* Display offset, 16 bytes per line, and printable ascii version */ 343*0Sstevel@tonic-gate while (cd > 0) { 344*0Sstevel@tonic-gate ac = 0; 345*0Sstevel@tonic-gate (void) printf("\n%06x: ", o); 346*0Sstevel@tonic-gate for (bl = 0; bl < BPL; bl++) { 347*0Sstevel@tonic-gate if (cu+bl < n) { 348*0Sstevel@tonic-gate (void) printf("%02x ", (b[cu+bl] & 0xff)); 349*0Sstevel@tonic-gate ac++; 350*0Sstevel@tonic-gate } 351*0Sstevel@tonic-gate else 352*0Sstevel@tonic-gate (void) printf(" "); 353*0Sstevel@tonic-gate } 354*0Sstevel@tonic-gate for (bl = 0; bl < BPL; bl++) { 355*0Sstevel@tonic-gate if ((cu+bl < n) && 356*0Sstevel@tonic-gate ((b[cu+bl] >= ' ') && (b[cu+bl] <= '~'))) 357*0Sstevel@tonic-gate (void) printf("%c", b[cu+bl]); 358*0Sstevel@tonic-gate else 359*0Sstevel@tonic-gate (void) printf("."); 360*0Sstevel@tonic-gate } 361*0Sstevel@tonic-gate cu += ac; o += ac; cd -= ac; 362*0Sstevel@tonic-gate } 363*0Sstevel@tonic-gate (void) printf("\n\n"); 364*0Sstevel@tonic-gate } 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate /* 367*0Sstevel@tonic-gate * header_for_dump -- display simple header over what will be output. 368*0Sstevel@tonic-gate */ 369*0Sstevel@tonic-gate static 370*0Sstevel@tonic-gate void 371*0Sstevel@tonic-gate header_for_dump(void) 372*0Sstevel@tonic-gate { 373*0Sstevel@tonic-gate int bl; 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate (void) printf("\n "); 376*0Sstevel@tonic-gate for (bl = 0; bl < BPL; bl++) 377*0Sstevel@tonic-gate (void) printf("%02x ", bl); 378*0Sstevel@tonic-gate (void) printf("\n "); 379*0Sstevel@tonic-gate bl = 3*BPL; 380*0Sstevel@tonic-gate while (bl-- > 0) 381*0Sstevel@tonic-gate (void) printf("-"); 382*0Sstevel@tonic-gate } 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate /* 385*0Sstevel@tonic-gate * parse_drvnum 386*0Sstevel@tonic-gate * Convert a partition name into a drive number. 387*0Sstevel@tonic-gate */ 388*0Sstevel@tonic-gate static 389*0Sstevel@tonic-gate int 390*0Sstevel@tonic-gate parse_drvnum(char *pn) 391*0Sstevel@tonic-gate { 392*0Sstevel@tonic-gate int drvnum; 393*0Sstevel@tonic-gate 394*0Sstevel@tonic-gate /* 395*0Sstevel@tonic-gate * Determine logical drive to seek after. 396*0Sstevel@tonic-gate */ 397*0Sstevel@tonic-gate if (strlen(pn) == 1 && *pn >= 'c' && *pn <= 'z') { 398*0Sstevel@tonic-gate drvnum = *pn - 'c' + 1; 399*0Sstevel@tonic-gate } else if (*pn >= '0' && *pn <= '9') { 400*0Sstevel@tonic-gate char *d; 401*0Sstevel@tonic-gate int v, m, c; 402*0Sstevel@tonic-gate 403*0Sstevel@tonic-gate v = 0; 404*0Sstevel@tonic-gate d = pn; 405*0Sstevel@tonic-gate while (*d && *d >= '0' && *d <= '9') { 406*0Sstevel@tonic-gate c = strlen(d); 407*0Sstevel@tonic-gate m = 1; 408*0Sstevel@tonic-gate while (--c) 409*0Sstevel@tonic-gate m *= 10; 410*0Sstevel@tonic-gate v += m * (*d - '0'); 411*0Sstevel@tonic-gate d++; 412*0Sstevel@tonic-gate } 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate if (*d || v > 24) { 415*0Sstevel@tonic-gate (void) fprintf(stderr, 416*0Sstevel@tonic-gate gettext("%s: bogus logical drive specification.\n"), 417*0Sstevel@tonic-gate pn); 418*0Sstevel@tonic-gate return (-1); 419*0Sstevel@tonic-gate } 420*0Sstevel@tonic-gate drvnum = v; 421*0Sstevel@tonic-gate } else if (strcmp(pn, "boot") == 0) { 422*0Sstevel@tonic-gate drvnum = 99; 423*0Sstevel@tonic-gate } else { 424*0Sstevel@tonic-gate (void) fprintf(stderr, 425*0Sstevel@tonic-gate gettext("%s: bogus logical drive specification.\n"), pn); 426*0Sstevel@tonic-gate return (-1); 427*0Sstevel@tonic-gate } 428*0Sstevel@tonic-gate 429*0Sstevel@tonic-gate return (drvnum); 430*0Sstevel@tonic-gate } 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate /* 433*0Sstevel@tonic-gate * Define some special logical drives we use. 434*0Sstevel@tonic-gate */ 435*0Sstevel@tonic-gate #define BOOT_PARTITION_DRIVE 99 436*0Sstevel@tonic-gate #define PRIMARY_DOS_DRIVE 1 437*0Sstevel@tonic-gate 438*0Sstevel@tonic-gate /* 439*0Sstevel@tonic-gate * isDosDrive() 440*0Sstevel@tonic-gate * Boolean function. Give it the systid field for an fdisk partition 441*0Sstevel@tonic-gate * and it decides if that's a systid that describes a DOS drive. We 442*0Sstevel@tonic-gate * use systid values defined in sys/dktp/fdisk.h. 443*0Sstevel@tonic-gate */ 444*0Sstevel@tonic-gate static int 445*0Sstevel@tonic-gate isDosDrive(uchar_t checkMe) 446*0Sstevel@tonic-gate { 447*0Sstevel@tonic-gate return ((checkMe == DOSOS12) || (checkMe == DOSOS16) || 448*0Sstevel@tonic-gate (checkMe == DOSHUGE) || (checkMe == FDISK_WINDOWS) || 449*0Sstevel@tonic-gate (checkMe == FDISK_EXT_WIN) || (checkMe == FDISK_FAT95) || 450*0Sstevel@tonic-gate (checkMe == DIAGPART)); 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate /* 454*0Sstevel@tonic-gate * isDosExtended() 455*0Sstevel@tonic-gate * Boolean function. Give it the systid field for an fdisk partition 456*0Sstevel@tonic-gate * and it decides if that's a systid that describes an extended DOS 457*0Sstevel@tonic-gate * partition. 458*0Sstevel@tonic-gate */ 459*0Sstevel@tonic-gate static int 460*0Sstevel@tonic-gate isDosExtended(uchar_t checkMe) 461*0Sstevel@tonic-gate { 462*0Sstevel@tonic-gate return ((checkMe == EXTDOS) || (checkMe == FDISK_EXTLBA)); 463*0Sstevel@tonic-gate } 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate /* 466*0Sstevel@tonic-gate * isBootPart() 467*0Sstevel@tonic-gate * Boolean function. Give it the systid field for an fdisk partition 468*0Sstevel@tonic-gate * and it decides if that's a systid that describes a Solaris boot 469*0Sstevel@tonic-gate * partition. 470*0Sstevel@tonic-gate */ 471*0Sstevel@tonic-gate static int 472*0Sstevel@tonic-gate isBootPart(uchar_t checkMe) 473*0Sstevel@tonic-gate { 474*0Sstevel@tonic-gate return (checkMe == X86BOOT); 475*0Sstevel@tonic-gate } 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gate static 478*0Sstevel@tonic-gate int 479*0Sstevel@tonic-gate warn_mismatch(char *desc, char *src, int expect, int assigned) 480*0Sstevel@tonic-gate { 481*0Sstevel@tonic-gate if (expect == assigned) 482*0Sstevel@tonic-gate return (assigned); 483*0Sstevel@tonic-gate 484*0Sstevel@tonic-gate /* 485*0Sstevel@tonic-gate * 4228473 - No way to non-interactively make a pcfs filesystem 486*0Sstevel@tonic-gate * 487*0Sstevel@tonic-gate * If we don't have an input TTY, or we aren't really doing 488*0Sstevel@tonic-gate * anything, then don't ask questions. Assume a yes answer 489*0Sstevel@tonic-gate * to any questions we would ask. 490*0Sstevel@tonic-gate */ 491*0Sstevel@tonic-gate if (Notreally || !isatty(fileno(stdin))) { 492*0Sstevel@tonic-gate (void) printf(gettext("WARNING: User supplied %s is %d," 493*0Sstevel@tonic-gate "\nbut value obtained from the %s is %d.\n" 494*0Sstevel@tonic-gate "Using user supplied value.\n"), 495*0Sstevel@tonic-gate desc, assigned, src, expect); 496*0Sstevel@tonic-gate return (assigned); 497*0Sstevel@tonic-gate } 498*0Sstevel@tonic-gate 499*0Sstevel@tonic-gate (void) printf(gettext("User supplied %s is %d." 500*0Sstevel@tonic-gate "\nThe value obtained from the %s is %d.\n"), 501*0Sstevel@tonic-gate desc, assigned, src, expect); 502*0Sstevel@tonic-gate 503*0Sstevel@tonic-gate (void) printf( 504*0Sstevel@tonic-gate gettext("Continue with value given on command line (y/n)? ")); 505*0Sstevel@tonic-gate (void) fflush(stdout); 506*0Sstevel@tonic-gate if (yes()) 507*0Sstevel@tonic-gate return (assigned); 508*0Sstevel@tonic-gate else 509*0Sstevel@tonic-gate exit(2); 510*0Sstevel@tonic-gate /*NOTREACHED*/ 511*0Sstevel@tonic-gate } 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate static 514*0Sstevel@tonic-gate void 515*0Sstevel@tonic-gate fill_fat32_bpb(bpb_t *wbpb) 516*0Sstevel@tonic-gate { 517*0Sstevel@tonic-gate /* 518*0Sstevel@tonic-gate * ExtFlags means (according to MSDN BPB (FAT32) document) 519*0Sstevel@tonic-gate * 520*0Sstevel@tonic-gate * Bit 8 indicates info written to the active FAT is written 521*0Sstevel@tonic-gate * to all copies of the FAT. (I think they mean bit 7, with 522*0Sstevel@tonic-gate * numbering starting at 0) 523*0Sstevel@tonic-gate * 524*0Sstevel@tonic-gate * Lowest 4 bits of field are the 0 based FAT number of the 525*0Sstevel@tonic-gate * Active FAT. (only meaningful if bit 8 is set) 526*0Sstevel@tonic-gate * 527*0Sstevel@tonic-gate * Field contains combination of these values: 528*0Sstevel@tonic-gate * 529*0Sstevel@tonic-gate * VALUE DESCRIPTION 530*0Sstevel@tonic-gate * BGBPB_F_ActiveFATMsk Mask for low four bits 531*0Sstevel@tonic-gate * (0x000F) 532*0Sstevel@tonic-gate * BGBPB_F_NoFATMirror If set FAT mirroring disabled. 533*0Sstevel@tonic-gate * (0x0080) If clear, FAT mirroring enabled. 534*0Sstevel@tonic-gate * 535*0Sstevel@tonic-gate * We set the value based on what I've seen on all the FAT32 drives 536*0Sstevel@tonic-gate * I've seen created by Windows. 537*0Sstevel@tonic-gate * 538*0Sstevel@tonic-gate */ 539*0Sstevel@tonic-gate wbpb->bpb32.ext_flags = 0x0; 540*0Sstevel@tonic-gate /* 541*0Sstevel@tonic-gate * No real explanation of the fs_vers file in the BPB doc. The 542*0Sstevel@tonic-gate * high byte is supposed to be the major version and the low the 543*0Sstevel@tonic-gate * minor version. Again I set according to what I've seen on Windows. 544*0Sstevel@tonic-gate */ 545*0Sstevel@tonic-gate wbpb->bpb32.fs_vers_lo = '\0'; 546*0Sstevel@tonic-gate wbpb->bpb32.fs_vers_hi = '\0'; 547*0Sstevel@tonic-gate /* 548*0Sstevel@tonic-gate * The convention appears to be to place the fs info sector 549*0Sstevel@tonic-gate * immediately after the boot sector, and that the backup boot 550*0Sstevel@tonic-gate * sector should be at sector 6. (based on what I see with 551*0Sstevel@tonic-gate * Windows) 552*0Sstevel@tonic-gate */ 553*0Sstevel@tonic-gate wbpb->bpb32.fsinfosec = 1; 554*0Sstevel@tonic-gate wbpb->bpb32.backupboot = 6; 555*0Sstevel@tonic-gate } 556*0Sstevel@tonic-gate 557*0Sstevel@tonic-gate static 558*0Sstevel@tonic-gate void 559*0Sstevel@tonic-gate fill_bpb_sizes(bpb_t *wbpb, struct ipart part[], int partno, off64_t offset) 560*0Sstevel@tonic-gate { 561*0Sstevel@tonic-gate ulong_t usesize; 562*0Sstevel@tonic-gate 563*0Sstevel@tonic-gate if (GetFsParams || GetSize) { 564*0Sstevel@tonic-gate usesize = ltohi(part[partno].numsect); 565*0Sstevel@tonic-gate if (Verbose) { 566*0Sstevel@tonic-gate (void) printf( 567*0Sstevel@tonic-gate gettext("Partition size (from FDISK table) " 568*0Sstevel@tonic-gate "= %d sectors.\n"), usesize); 569*0Sstevel@tonic-gate } 570*0Sstevel@tonic-gate } else { 571*0Sstevel@tonic-gate usesize = warn_mismatch( 572*0Sstevel@tonic-gate gettext("length of partition (in sectors)"), 573*0Sstevel@tonic-gate gettext("FDISK table"), 574*0Sstevel@tonic-gate ltohi(part[partno].numsect), TotSize); 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate if (GetFsParams) { 578*0Sstevel@tonic-gate TotSize = usesize; 579*0Sstevel@tonic-gate } else { 580*0Sstevel@tonic-gate if (usesize > 0xffff) 581*0Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = 0; 582*0Sstevel@tonic-gate else 583*0Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = usesize; 584*0Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = usesize; 585*0Sstevel@tonic-gate } 586*0Sstevel@tonic-gate 587*0Sstevel@tonic-gate wbpb->bpb.hidden_sectors = offset; 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate if (GetFsParams) { 590*0Sstevel@tonic-gate RelOffset = offset; 591*0Sstevel@tonic-gate } else { 592*0Sstevel@tonic-gate wbpb->sunbpb.bs_offset_high = offset >> 16; 593*0Sstevel@tonic-gate wbpb->sunbpb.bs_offset_low = offset & 0xFFFF; 594*0Sstevel@tonic-gate } 595*0Sstevel@tonic-gate } 596*0Sstevel@tonic-gate 597*0Sstevel@tonic-gate /* 598*0Sstevel@tonic-gate * lookup_FAT_size 599*0Sstevel@tonic-gate * 600*0Sstevel@tonic-gate * Given the FDISK partition file system identifier, return the 601*0Sstevel@tonic-gate * expected FAT size for the partition. 602*0Sstevel@tonic-gate */ 603*0Sstevel@tonic-gate static 604*0Sstevel@tonic-gate int 605*0Sstevel@tonic-gate lookup_FAT_size(uchar_t partid) 606*0Sstevel@tonic-gate { 607*0Sstevel@tonic-gate int rval; 608*0Sstevel@tonic-gate 609*0Sstevel@tonic-gate switch (partid) { 610*0Sstevel@tonic-gate case DOSOS12: 611*0Sstevel@tonic-gate rval = 12; 612*0Sstevel@tonic-gate break; 613*0Sstevel@tonic-gate case DOSOS16: 614*0Sstevel@tonic-gate case DOSHUGE: 615*0Sstevel@tonic-gate case FDISK_FAT95: 616*0Sstevel@tonic-gate case X86BOOT: 617*0Sstevel@tonic-gate rval = 16; 618*0Sstevel@tonic-gate break; 619*0Sstevel@tonic-gate case FDISK_WINDOWS: 620*0Sstevel@tonic-gate case FDISK_EXT_WIN: 621*0Sstevel@tonic-gate rval = 32; 622*0Sstevel@tonic-gate break; 623*0Sstevel@tonic-gate case EXTDOS: 624*0Sstevel@tonic-gate case FDISK_EXTLBA: 625*0Sstevel@tonic-gate default: 626*0Sstevel@tonic-gate rval = -1; 627*0Sstevel@tonic-gate break; 628*0Sstevel@tonic-gate } 629*0Sstevel@tonic-gate 630*0Sstevel@tonic-gate return (rval); 631*0Sstevel@tonic-gate } 632*0Sstevel@tonic-gate 633*0Sstevel@tonic-gate /* 634*0Sstevel@tonic-gate * seek_partn 635*0Sstevel@tonic-gate * 636*0Sstevel@tonic-gate * Seek to the beginning of the partition where we need to install 637*0Sstevel@tonic-gate * the new FAT. Zero return for any error, but print error 638*0Sstevel@tonic-gate * messages here. 639*0Sstevel@tonic-gate */ 640*0Sstevel@tonic-gate static 641*0Sstevel@tonic-gate int 642*0Sstevel@tonic-gate seek_partn(int fd, char *pn, bpb_t *wbpb, off64_t *seekto) 643*0Sstevel@tonic-gate { 644*0Sstevel@tonic-gate struct ipart part[FD_NUMPART]; 645*0Sstevel@tonic-gate struct mboot extmboot; 646*0Sstevel@tonic-gate struct mboot mb; 647*0Sstevel@tonic-gate daddr_t xstartsect; 648*0Sstevel@tonic-gate off64_t nextseek = 0; 649*0Sstevel@tonic-gate off64_t lastseek = 0; 650*0Sstevel@tonic-gate int logicalDriveCount = 0; 651*0Sstevel@tonic-gate int extendedPart = -1; 652*0Sstevel@tonic-gate int primaryPart = -1; 653*0Sstevel@tonic-gate int bootPart = -1; 654*0Sstevel@tonic-gate int xnumsect = -1; 655*0Sstevel@tonic-gate int drvnum; 656*0Sstevel@tonic-gate int driveIndex; 657*0Sstevel@tonic-gate int i; 658*0Sstevel@tonic-gate /* 659*0Sstevel@tonic-gate * Count of drives in the current extended partition's 660*0Sstevel@tonic-gate * FDISK table, and indexes of the drives themselves. 661*0Sstevel@tonic-gate */ 662*0Sstevel@tonic-gate int extndDrives[FD_NUMPART]; 663*0Sstevel@tonic-gate int numDrives = 0; 664*0Sstevel@tonic-gate /* 665*0Sstevel@tonic-gate * Count of drives (beyond primary) in master boot record's 666*0Sstevel@tonic-gate * FDISK table, and indexes of the drives themselves. 667*0Sstevel@tonic-gate */ 668*0Sstevel@tonic-gate int extraDrives[FD_NUMPART]; 669*0Sstevel@tonic-gate int numExtraDrives = 0; 670*0Sstevel@tonic-gate 671*0Sstevel@tonic-gate if ((drvnum = parse_drvnum(pn)) < 0) 672*0Sstevel@tonic-gate return (PART_NOT_FOUND); 673*0Sstevel@tonic-gate 674*0Sstevel@tonic-gate if (read(fd, &mb, sizeof (mb)) != sizeof (mb)) { 675*0Sstevel@tonic-gate (void) fprintf(stderr, 676*0Sstevel@tonic-gate gettext("Couldn't read a Master Boot Record?!\n")); 677*0Sstevel@tonic-gate return (PART_NOT_FOUND); 678*0Sstevel@tonic-gate } 679*0Sstevel@tonic-gate 680*0Sstevel@tonic-gate if (ltohs(mb.signature) != BOOTSECSIG) { 681*0Sstevel@tonic-gate (void) fprintf(stderr, 682*0Sstevel@tonic-gate gettext("Bad Sig on master boot record!\n")); 683*0Sstevel@tonic-gate return (PART_NOT_FOUND); 684*0Sstevel@tonic-gate } 685*0Sstevel@tonic-gate 686*0Sstevel@tonic-gate *seekto = 0; 687*0Sstevel@tonic-gate 688*0Sstevel@tonic-gate /* 689*0Sstevel@tonic-gate * Copy partition table into memory 690*0Sstevel@tonic-gate */ 691*0Sstevel@tonic-gate (void) memcpy(part, mb.parts, sizeof (part)); 692*0Sstevel@tonic-gate 693*0Sstevel@tonic-gate /* 694*0Sstevel@tonic-gate * Get a summary of what is in the Master FDISK table. 695*0Sstevel@tonic-gate * Normally we expect to find one partition marked as a DOS drive. 696*0Sstevel@tonic-gate * This partition is the one Windows calls the primary dos partition. 697*0Sstevel@tonic-gate * If the machine has any logical drives then we also expect 698*0Sstevel@tonic-gate * to find a partition marked as an extended DOS partition. 699*0Sstevel@tonic-gate * 700*0Sstevel@tonic-gate * Sometimes we'll find multiple partitions marked as DOS drives. 701*0Sstevel@tonic-gate * The Solaris fdisk program allows these partitions 702*0Sstevel@tonic-gate * to be created, but Windows fdisk no longer does. We still need 703*0Sstevel@tonic-gate * to support these, though, since Windows does. We also need to fix 704*0Sstevel@tonic-gate * our fdisk to behave like the Windows version. 705*0Sstevel@tonic-gate * 706*0Sstevel@tonic-gate * It turns out that some off-the-shelf media have *only* an 707*0Sstevel@tonic-gate * Extended partition, so we need to deal with that case as 708*0Sstevel@tonic-gate * well. 709*0Sstevel@tonic-gate * 710*0Sstevel@tonic-gate * Only a single (the first) Extended or Boot Partition will 711*0Sstevel@tonic-gate * be recognized. Any others will be ignored. 712*0Sstevel@tonic-gate */ 713*0Sstevel@tonic-gate for (i = 0; i < FD_NUMPART; i++) { 714*0Sstevel@tonic-gate if (isDosDrive(part[i].systid)) { 715*0Sstevel@tonic-gate if (primaryPart < 0) { 716*0Sstevel@tonic-gate logicalDriveCount++; 717*0Sstevel@tonic-gate primaryPart = i; 718*0Sstevel@tonic-gate } else { 719*0Sstevel@tonic-gate extraDrives[numExtraDrives++] = i; 720*0Sstevel@tonic-gate } 721*0Sstevel@tonic-gate continue; 722*0Sstevel@tonic-gate } 723*0Sstevel@tonic-gate if ((extendedPart < 0) && isDosExtended(part[i].systid)) { 724*0Sstevel@tonic-gate extendedPart = i; 725*0Sstevel@tonic-gate continue; 726*0Sstevel@tonic-gate } 727*0Sstevel@tonic-gate if ((bootPart < 0) && isBootPart(part[i].systid)) { 728*0Sstevel@tonic-gate bootPart = i; 729*0Sstevel@tonic-gate continue; 730*0Sstevel@tonic-gate } 731*0Sstevel@tonic-gate } 732*0Sstevel@tonic-gate 733*0Sstevel@tonic-gate if (drvnum == BOOT_PARTITION_DRIVE) { 734*0Sstevel@tonic-gate if (bootPart < 0) { 735*0Sstevel@tonic-gate (void) fprintf(stderr, 736*0Sstevel@tonic-gate gettext("No boot partition found on drive\n")); 737*0Sstevel@tonic-gate return (PART_NOT_FOUND); 738*0Sstevel@tonic-gate } 739*0Sstevel@tonic-gate if ((*seekto = ltohi(part[bootPart].relsect)) == 0) { 740*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("Bogus FDISK entry? " 741*0Sstevel@tonic-gate "A boot partition starting\nat sector 0 would " 742*0Sstevel@tonic-gate "collide with the FDISK table!\n")); 743*0Sstevel@tonic-gate return (PART_NOT_FOUND); 744*0Sstevel@tonic-gate } 745*0Sstevel@tonic-gate 746*0Sstevel@tonic-gate fill_bpb_sizes(wbpb, part, bootPart, *seekto); 747*0Sstevel@tonic-gate *seekto *= BPSEC; 748*0Sstevel@tonic-gate FdiskFATsize = lookup_FAT_size(part[bootPart].systid); 749*0Sstevel@tonic-gate if (Verbose) 750*0Sstevel@tonic-gate (void) printf(gettext("Boot partition's offset: " 751*0Sstevel@tonic-gate "Sector %x.\n"), *seekto/BPSEC); 752*0Sstevel@tonic-gate if (lseek64(fd, *seekto, SEEK_SET) < 0) { 753*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("Partition %s: "), pn); 754*0Sstevel@tonic-gate perror(""); 755*0Sstevel@tonic-gate return (PART_NOT_FOUND); 756*0Sstevel@tonic-gate } 757*0Sstevel@tonic-gate return (PART_FOUND); 758*0Sstevel@tonic-gate } 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate if (drvnum == PRIMARY_DOS_DRIVE && primaryPart >= 0) { 761*0Sstevel@tonic-gate if ((*seekto = ltohi(part[primaryPart].relsect)) == 0) { 762*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("Bogus FDISK entry? " 763*0Sstevel@tonic-gate "A partition starting\nat sector 0 would " 764*0Sstevel@tonic-gate "collide with the FDISK table!\n")); 765*0Sstevel@tonic-gate return (PART_NOT_FOUND); 766*0Sstevel@tonic-gate } 767*0Sstevel@tonic-gate 768*0Sstevel@tonic-gate fill_bpb_sizes(wbpb, part, primaryPart, *seekto); 769*0Sstevel@tonic-gate *seekto *= BPSEC; 770*0Sstevel@tonic-gate FdiskFATsize = lookup_FAT_size(part[primaryPart].systid); 771*0Sstevel@tonic-gate if (Verbose) 772*0Sstevel@tonic-gate (void) printf(gettext("Partition's offset: " 773*0Sstevel@tonic-gate "Sector %x.\n"), *seekto/BPSEC); 774*0Sstevel@tonic-gate if (lseek64(fd, *seekto, SEEK_SET) < 0) { 775*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("Partition %s: "), pn); 776*0Sstevel@tonic-gate perror(""); 777*0Sstevel@tonic-gate return (PART_NOT_FOUND); 778*0Sstevel@tonic-gate } 779*0Sstevel@tonic-gate return (PART_FOUND); 780*0Sstevel@tonic-gate } 781*0Sstevel@tonic-gate 782*0Sstevel@tonic-gate /* 783*0Sstevel@tonic-gate * We are not looking for the C: drive (or there was no primary 784*0Sstevel@tonic-gate * drive found), so we had better have an extended partition or 785*0Sstevel@tonic-gate * extra drives in the Master FDISK table. 786*0Sstevel@tonic-gate */ 787*0Sstevel@tonic-gate if ((extendedPart < 0) && (numExtraDrives == 0)) { 788*0Sstevel@tonic-gate (void) fprintf(stderr, 789*0Sstevel@tonic-gate gettext("No such logical drive " 790*0Sstevel@tonic-gate "(missing extended partition entry)\n")); 791*0Sstevel@tonic-gate return (PART_NOT_FOUND); 792*0Sstevel@tonic-gate } 793*0Sstevel@tonic-gate 794*0Sstevel@tonic-gate if (extendedPart >= 0) { 795*0Sstevel@tonic-gate nextseek = xstartsect = ltohi(part[extendedPart].relsect); 796*0Sstevel@tonic-gate xnumsect = ltohi(part[extendedPart].numsect); 797*0Sstevel@tonic-gate do { 798*0Sstevel@tonic-gate /* 799*0Sstevel@tonic-gate * If the seek would not cause us to change 800*0Sstevel@tonic-gate * position on the drive, then we're out of 801*0Sstevel@tonic-gate * extended partitions to examine. 802*0Sstevel@tonic-gate */ 803*0Sstevel@tonic-gate if (nextseek == lastseek) 804*0Sstevel@tonic-gate break; 805*0Sstevel@tonic-gate logicalDriveCount += numDrives; 806*0Sstevel@tonic-gate /* 807*0Sstevel@tonic-gate * Seek the next extended partition, and find 808*0Sstevel@tonic-gate * logical drives within it. 809*0Sstevel@tonic-gate */ 810*0Sstevel@tonic-gate if (lseek64(fd, nextseek * BPSEC, SEEK_SET) < 0 || 811*0Sstevel@tonic-gate read(fd, &extmboot, sizeof (extmboot)) != 812*0Sstevel@tonic-gate sizeof (extmboot)) { 813*0Sstevel@tonic-gate perror(gettext("Unable to read extended " 814*0Sstevel@tonic-gate "partition record")); 815*0Sstevel@tonic-gate return (PART_NOT_FOUND); 816*0Sstevel@tonic-gate } 817*0Sstevel@tonic-gate (void) memcpy(part, extmboot.parts, sizeof (part)); 818*0Sstevel@tonic-gate lastseek = nextseek; 819*0Sstevel@tonic-gate if (ltohs(extmboot.signature) != MBB_MAGIC) { 820*0Sstevel@tonic-gate (void) fprintf(stderr, 821*0Sstevel@tonic-gate gettext("Bad signature on " 822*0Sstevel@tonic-gate "extended partition\n")); 823*0Sstevel@tonic-gate return (PART_NOT_FOUND); 824*0Sstevel@tonic-gate } 825*0Sstevel@tonic-gate /* 826*0Sstevel@tonic-gate * Count up drives, and track where the next 827*0Sstevel@tonic-gate * extended partition is in case we need it. We 828*0Sstevel@tonic-gate * are expecting only one extended partition. If 829*0Sstevel@tonic-gate * there is more than one we'll only go to the 830*0Sstevel@tonic-gate * first one we see, but warn about ignoring. 831*0Sstevel@tonic-gate */ 832*0Sstevel@tonic-gate numDrives = 0; 833*0Sstevel@tonic-gate for (i = 0; i < FD_NUMPART; i++) { 834*0Sstevel@tonic-gate if (isDosDrive(part[i].systid)) { 835*0Sstevel@tonic-gate extndDrives[numDrives++] = i; 836*0Sstevel@tonic-gate continue; 837*0Sstevel@tonic-gate } else if (isDosExtended(part[i].systid)) { 838*0Sstevel@tonic-gate if (nextseek != lastseek) { 839*0Sstevel@tonic-gate /* 840*0Sstevel@tonic-gate * Already found an extended 841*0Sstevel@tonic-gate * partition in this table. 842*0Sstevel@tonic-gate */ 843*0Sstevel@tonic-gate (void) fprintf(stderr, 844*0Sstevel@tonic-gate gettext("WARNING: " 845*0Sstevel@tonic-gate "Ignoring unexpected " 846*0Sstevel@tonic-gate "additional extended " 847*0Sstevel@tonic-gate "partition")); 848*0Sstevel@tonic-gate continue; 849*0Sstevel@tonic-gate } 850*0Sstevel@tonic-gate nextseek = xstartsect + 851*0Sstevel@tonic-gate ltohi(part[i].relsect); 852*0Sstevel@tonic-gate continue; 853*0Sstevel@tonic-gate } 854*0Sstevel@tonic-gate } 855*0Sstevel@tonic-gate } while (drvnum > logicalDriveCount + numDrives); 856*0Sstevel@tonic-gate 857*0Sstevel@tonic-gate if (drvnum <= logicalDriveCount + numDrives) { 858*0Sstevel@tonic-gate /* 859*0Sstevel@tonic-gate * The number of logical drives we've found thus 860*0Sstevel@tonic-gate * far is enough to get us to the one we were 861*0Sstevel@tonic-gate * searching for. 862*0Sstevel@tonic-gate */ 863*0Sstevel@tonic-gate driveIndex = logicalDriveCount + numDrives - drvnum; 864*0Sstevel@tonic-gate *seekto = 865*0Sstevel@tonic-gate ltohi(part[extndDrives[driveIndex]].relsect) + 866*0Sstevel@tonic-gate lastseek; 867*0Sstevel@tonic-gate if (*seekto == lastseek) { 868*0Sstevel@tonic-gate (void) fprintf(stderr, 869*0Sstevel@tonic-gate gettext("Bogus FDISK entry? A logical " 870*0Sstevel@tonic-gate "drive starting at\nsector 0x%llx would " 871*0Sstevel@tonic-gate "collide with the\nFDISK information in " 872*0Sstevel@tonic-gate "that sector.\n"), *seekto); 873*0Sstevel@tonic-gate return (PART_NOT_FOUND); 874*0Sstevel@tonic-gate } else if (*seekto <= xstartsect || 875*0Sstevel@tonic-gate *seekto >= (xstartsect + xnumsect)) { 876*0Sstevel@tonic-gate (void) fprintf(stderr, 877*0Sstevel@tonic-gate gettext("Bogus FDISK entry? " 878*0Sstevel@tonic-gate "Logical drive start sector (0x%llx)\n" 879*0Sstevel@tonic-gate "not within extended partition! " 880*0Sstevel@tonic-gate "(Expected in range 0x%x - 0x%x)\n"), 881*0Sstevel@tonic-gate *seekto, xstartsect + 1, 882*0Sstevel@tonic-gate xstartsect + xnumsect - 1); 883*0Sstevel@tonic-gate return (PART_NOT_FOUND); 884*0Sstevel@tonic-gate } 885*0Sstevel@tonic-gate fill_bpb_sizes(wbpb, part, extndDrives[driveIndex], 886*0Sstevel@tonic-gate *seekto); 887*0Sstevel@tonic-gate *seekto *= BPSEC; 888*0Sstevel@tonic-gate FdiskFATsize = lookup_FAT_size( 889*0Sstevel@tonic-gate part[extndDrives[driveIndex]].systid); 890*0Sstevel@tonic-gate if (Verbose) 891*0Sstevel@tonic-gate (void) printf(gettext("Partition's offset: " 892*0Sstevel@tonic-gate "Sector 0x%x.\n"), *seekto/BPSEC); 893*0Sstevel@tonic-gate if (lseek64(fd, *seekto, SEEK_SET) < 0) { 894*0Sstevel@tonic-gate (void) fprintf(stderr, 895*0Sstevel@tonic-gate gettext("Partition %s: "), pn); 896*0Sstevel@tonic-gate perror(""); 897*0Sstevel@tonic-gate return (PART_NOT_FOUND); 898*0Sstevel@tonic-gate } 899*0Sstevel@tonic-gate return (PART_FOUND); 900*0Sstevel@tonic-gate } else { 901*0Sstevel@tonic-gate /* 902*0Sstevel@tonic-gate * We ran out of extended dos partition 903*0Sstevel@tonic-gate * drives. The only hope now is to go 904*0Sstevel@tonic-gate * back to extra drives defined in the master 905*0Sstevel@tonic-gate * fdisk table. But we overwrote that table 906*0Sstevel@tonic-gate * already, so we must load it in again. 907*0Sstevel@tonic-gate */ 908*0Sstevel@tonic-gate logicalDriveCount += numDrives; 909*0Sstevel@tonic-gate (void) memcpy(part, mb.parts, sizeof (part)); 910*0Sstevel@tonic-gate } 911*0Sstevel@tonic-gate } 912*0Sstevel@tonic-gate /* 913*0Sstevel@tonic-gate * Still haven't found the drive, is it an extra 914*0Sstevel@tonic-gate * drive defined in the main FDISK table? 915*0Sstevel@tonic-gate */ 916*0Sstevel@tonic-gate if (drvnum <= logicalDriveCount + numExtraDrives) { 917*0Sstevel@tonic-gate driveIndex = logicalDriveCount + numExtraDrives - drvnum; 918*0Sstevel@tonic-gate *seekto = ltohi(part[extraDrives[driveIndex]].relsect); 919*0Sstevel@tonic-gate if (*seekto == 0) { 920*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("Bogus FDISK entry? " 921*0Sstevel@tonic-gate "A partition starting\nat sector 0 would " 922*0Sstevel@tonic-gate "collide with the FDISK table!\n")); 923*0Sstevel@tonic-gate return (PART_NOT_FOUND); 924*0Sstevel@tonic-gate } 925*0Sstevel@tonic-gate 926*0Sstevel@tonic-gate fill_bpb_sizes(wbpb, part, extraDrives[driveIndex], *seekto); 927*0Sstevel@tonic-gate *seekto *= BPSEC; 928*0Sstevel@tonic-gate FdiskFATsize = 929*0Sstevel@tonic-gate lookup_FAT_size(part[extraDrives[driveIndex]].systid); 930*0Sstevel@tonic-gate if (Verbose) 931*0Sstevel@tonic-gate (void) printf(gettext("Partition's offset: " 932*0Sstevel@tonic-gate "Sector %x.\n"), *seekto/BPSEC); 933*0Sstevel@tonic-gate if (lseek64(fd, *seekto, SEEK_SET) < 0) { 934*0Sstevel@tonic-gate (void) fprintf(stderr, 935*0Sstevel@tonic-gate gettext("Partition %s: "), pn); 936*0Sstevel@tonic-gate perror(""); 937*0Sstevel@tonic-gate return (PART_NOT_FOUND); 938*0Sstevel@tonic-gate } 939*0Sstevel@tonic-gate return (PART_FOUND); 940*0Sstevel@tonic-gate } 941*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("No such logical drive\n")); 942*0Sstevel@tonic-gate return (PART_NOT_FOUND); 943*0Sstevel@tonic-gate } 944*0Sstevel@tonic-gate 945*0Sstevel@tonic-gate /* 946*0Sstevel@tonic-gate * seek_nofdisk 947*0Sstevel@tonic-gate * 948*0Sstevel@tonic-gate * User is asking us to trust them that they know best. 949*0Sstevel@tonic-gate * We basically won't do much seeking here, the only seeking we'll do 950*0Sstevel@tonic-gate * is if the 'hidden' parameter was given. 951*0Sstevel@tonic-gate */ 952*0Sstevel@tonic-gate static 953*0Sstevel@tonic-gate int 954*0Sstevel@tonic-gate seek_nofdisk(int fd, bpb_t *wbpb, off64_t *seekto) 955*0Sstevel@tonic-gate { 956*0Sstevel@tonic-gate if (TotSize > 0xffff) 957*0Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = 0; 958*0Sstevel@tonic-gate else 959*0Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = (short)TotSize; 960*0Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = TotSize; 961*0Sstevel@tonic-gate 962*0Sstevel@tonic-gate *seekto = RelOffset * BPSEC; 963*0Sstevel@tonic-gate wbpb->bpb.hidden_sectors = RelOffset; 964*0Sstevel@tonic-gate wbpb->sunbpb.bs_offset_high = RelOffset >> 16; 965*0Sstevel@tonic-gate wbpb->sunbpb.bs_offset_low = RelOffset & 0xFFFF; 966*0Sstevel@tonic-gate 967*0Sstevel@tonic-gate if (Verbose) 968*0Sstevel@tonic-gate (void) printf(gettext("Requested offset: Sector %x.\n"), 969*0Sstevel@tonic-gate *seekto/BPSEC); 970*0Sstevel@tonic-gate 971*0Sstevel@tonic-gate if (lseek64(fd, *seekto, SEEK_SET) < 0) { 972*0Sstevel@tonic-gate (void) fprintf(stderr, 973*0Sstevel@tonic-gate gettext("User specified start sector %d"), RelOffset); 974*0Sstevel@tonic-gate perror(""); 975*0Sstevel@tonic-gate return (PART_NOT_FOUND); 976*0Sstevel@tonic-gate } 977*0Sstevel@tonic-gate return (PART_FOUND); 978*0Sstevel@tonic-gate } 979*0Sstevel@tonic-gate 980*0Sstevel@tonic-gate /* 981*0Sstevel@tonic-gate * set_fat_string 982*0Sstevel@tonic-gate * 983*0Sstevel@tonic-gate * Fill in the type string of the FAT 984*0Sstevel@tonic-gate */ 985*0Sstevel@tonic-gate static 986*0Sstevel@tonic-gate void 987*0Sstevel@tonic-gate set_fat_string(bpb_t *wbpb, int fatsize) 988*0Sstevel@tonic-gate { 989*0Sstevel@tonic-gate if (fatsize == 12) { 990*0Sstevel@tonic-gate (void) strncpy((char *)wbpb->ebpb.type, FAT12_TYPE_STRING, 991*0Sstevel@tonic-gate strlen(FAT12_TYPE_STRING)); 992*0Sstevel@tonic-gate } else if (fatsize == 16) { 993*0Sstevel@tonic-gate (void) strncpy((char *)wbpb->ebpb.type, FAT16_TYPE_STRING, 994*0Sstevel@tonic-gate strlen(FAT16_TYPE_STRING)); 995*0Sstevel@tonic-gate } else { 996*0Sstevel@tonic-gate (void) strncpy((char *)wbpb->ebpb.type, FAT32_TYPE_STRING, 997*0Sstevel@tonic-gate strlen(FAT32_TYPE_STRING)); 998*0Sstevel@tonic-gate } 999*0Sstevel@tonic-gate } 1000*0Sstevel@tonic-gate 1001*0Sstevel@tonic-gate /* 1002*0Sstevel@tonic-gate * prepare_image_file 1003*0Sstevel@tonic-gate * 1004*0Sstevel@tonic-gate * Open the file that will hold the image (as opposed to the image 1005*0Sstevel@tonic-gate * being written to the boot sector of an actual disk). 1006*0Sstevel@tonic-gate */ 1007*0Sstevel@tonic-gate static 1008*0Sstevel@tonic-gate int 1009*0Sstevel@tonic-gate prepare_image_file(char *fn, bpb_t *wbpb) 1010*0Sstevel@tonic-gate { 1011*0Sstevel@tonic-gate int fd; 1012*0Sstevel@tonic-gate char zerobyte = '\0'; 1013*0Sstevel@tonic-gate 1014*0Sstevel@tonic-gate if ((fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0666)) < 0) { 1015*0Sstevel@tonic-gate perror(fn); 1016*0Sstevel@tonic-gate exit(2); 1017*0Sstevel@tonic-gate } 1018*0Sstevel@tonic-gate 1019*0Sstevel@tonic-gate if (Imagesize == 5) { 1020*0Sstevel@tonic-gate /* Disk image of a 1.2M floppy */ 1021*0Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = 2 * 80 * 15; 1022*0Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = 2 * 80 * 15; 1023*0Sstevel@tonic-gate wbpb->bpb.sectors_per_track = 15; 1024*0Sstevel@tonic-gate wbpb->bpb.heads = 2; 1025*0Sstevel@tonic-gate wbpb->bpb.media = 0xF9; 1026*0Sstevel@tonic-gate wbpb->bpb.num_root_entries = 224; 1027*0Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1; 1028*0Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 7; 1029*0Sstevel@tonic-gate } else { 1030*0Sstevel@tonic-gate /* Disk image of a 1.44M floppy */ 1031*0Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = 2 * 80 * 18; 1032*0Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = 2 * 80 * 18; 1033*0Sstevel@tonic-gate wbpb->bpb.sectors_per_track = 18; 1034*0Sstevel@tonic-gate wbpb->bpb.heads = 2; 1035*0Sstevel@tonic-gate wbpb->bpb.media = 0xF0; 1036*0Sstevel@tonic-gate wbpb->bpb.num_root_entries = 224; 1037*0Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1; 1038*0Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 9; 1039*0Sstevel@tonic-gate } 1040*0Sstevel@tonic-gate 1041*0Sstevel@tonic-gate /* 1042*0Sstevel@tonic-gate * Make a holey file, with length the exact 1043*0Sstevel@tonic-gate * size of the floppy image. 1044*0Sstevel@tonic-gate */ 1045*0Sstevel@tonic-gate if (lseek(fd, (wbpb->bpb.sectors_in_volume * BPSEC)-1, SEEK_SET) < 0) { 1046*0Sstevel@tonic-gate (void) close(fd); 1047*0Sstevel@tonic-gate perror(fn); 1048*0Sstevel@tonic-gate exit(2); 1049*0Sstevel@tonic-gate } 1050*0Sstevel@tonic-gate 1051*0Sstevel@tonic-gate if (write(fd, &zerobyte, 1) != 1) { 1052*0Sstevel@tonic-gate (void) close(fd); 1053*0Sstevel@tonic-gate perror(fn); 1054*0Sstevel@tonic-gate exit(2); 1055*0Sstevel@tonic-gate } 1056*0Sstevel@tonic-gate 1057*0Sstevel@tonic-gate if (lseek(fd, 0, SEEK_SET) < 0) { 1058*0Sstevel@tonic-gate (void) close(fd); 1059*0Sstevel@tonic-gate perror(fn); 1060*0Sstevel@tonic-gate exit(2); 1061*0Sstevel@tonic-gate } 1062*0Sstevel@tonic-gate 1063*0Sstevel@tonic-gate Fatentsize = 12; /* Size of fat entry in bits */ 1064*0Sstevel@tonic-gate set_fat_string(wbpb, Fatentsize); 1065*0Sstevel@tonic-gate 1066*0Sstevel@tonic-gate wbpb->ebpb.phys_drive_num = 0; 1067*0Sstevel@tonic-gate 1068*0Sstevel@tonic-gate wbpb->sunbpb.bs_offset_high = 0; 1069*0Sstevel@tonic-gate wbpb->sunbpb.bs_offset_low = 0; 1070*0Sstevel@tonic-gate 1071*0Sstevel@tonic-gate return (fd); 1072*0Sstevel@tonic-gate } 1073*0Sstevel@tonic-gate 1074*0Sstevel@tonic-gate /* 1075*0Sstevel@tonic-gate * partn_lecture 1076*0Sstevel@tonic-gate * 1077*0Sstevel@tonic-gate * Give a brief sermon on dev_name user should pass to 1078*0Sstevel@tonic-gate * the program from the command line. 1079*0Sstevel@tonic-gate * 1080*0Sstevel@tonic-gate */ 1081*0Sstevel@tonic-gate static 1082*0Sstevel@tonic-gate void 1083*0Sstevel@tonic-gate partn_lecture(char *dn) 1084*0Sstevel@tonic-gate { 1085*0Sstevel@tonic-gate (void) fprintf(stderr, 1086*0Sstevel@tonic-gate gettext("\nDevice %s was assumed to be a diskette.\n" 1087*0Sstevel@tonic-gate "A diskette specific operation failed on this device.\n" 1088*0Sstevel@tonic-gate "If the device is a hard disk, provide the name of " 1089*0Sstevel@tonic-gate "the full physical disk,\n" 1090*0Sstevel@tonic-gate "and qualify that name with a logical drive specifier.\n\n" 1091*0Sstevel@tonic-gate "Hint: the device is usually something similar to\n\n" 1092*0Sstevel@tonic-gate "/dev/rdsk/c0d0p0 or /dev/rdsk/c0t0d0p0 (x86)\n" 1093*0Sstevel@tonic-gate "/dev/rdsk/c0t5d0s2 (sparc)\n\n" 1094*0Sstevel@tonic-gate "The drive specifier is appended to the device name." 1095*0Sstevel@tonic-gate " For example:\n\n" 1096*0Sstevel@tonic-gate "/dev/rdsk/c0t5d0s2:c or /dev/rdsk/c0d0p0:boot\n\n"), dn); 1097*0Sstevel@tonic-gate } 1098*0Sstevel@tonic-gate 1099*0Sstevel@tonic-gate static 1100*0Sstevel@tonic-gate void 1101*0Sstevel@tonic-gate warn_funky_floppy(void) 1102*0Sstevel@tonic-gate { 1103*0Sstevel@tonic-gate (void) fprintf(stderr, 1104*0Sstevel@tonic-gate gettext("Use the 'nofdisk' option to create file systems\n" 1105*0Sstevel@tonic-gate "on non-standard floppies.\n\n")); 1106*0Sstevel@tonic-gate exit(4); 1107*0Sstevel@tonic-gate } 1108*0Sstevel@tonic-gate 1109*0Sstevel@tonic-gate static 1110*0Sstevel@tonic-gate void 1111*0Sstevel@tonic-gate warn_funky_fatsize(void) 1112*0Sstevel@tonic-gate { 1113*0Sstevel@tonic-gate (void) fprintf(stderr, 1114*0Sstevel@tonic-gate gettext("Non-standard FAT size requested for floppy.\n" 1115*0Sstevel@tonic-gate "The 'nofdisk' option must be used to\n" 1116*0Sstevel@tonic-gate "override the 12 bit floppy default.\n\n")); 1117*0Sstevel@tonic-gate exit(4); 1118*0Sstevel@tonic-gate } 1119*0Sstevel@tonic-gate 1120*0Sstevel@tonic-gate static 1121*0Sstevel@tonic-gate void 1122*0Sstevel@tonic-gate floppy_bpb_fillin(bpb_t *wbpb, int diam, int hds, int spt) 1123*0Sstevel@tonic-gate { 1124*0Sstevel@tonic-gate switch (diam) { 1125*0Sstevel@tonic-gate case 3: 1126*0Sstevel@tonic-gate switch (hds) { 1127*0Sstevel@tonic-gate case 2: 1128*0Sstevel@tonic-gate switch (spt) { 1129*0Sstevel@tonic-gate case 9: 1130*0Sstevel@tonic-gate wbpb->bpb.media = 0xF9; 1131*0Sstevel@tonic-gate wbpb->bpb.num_root_entries = 112; 1132*0Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 2; 1133*0Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 3; 1134*0Sstevel@tonic-gate break; 1135*0Sstevel@tonic-gate case 18: 1136*0Sstevel@tonic-gate wbpb->bpb.media = 0xF0; 1137*0Sstevel@tonic-gate wbpb->bpb.num_root_entries = 224; 1138*0Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1; 1139*0Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 9; 1140*0Sstevel@tonic-gate break; 1141*0Sstevel@tonic-gate case 36: 1142*0Sstevel@tonic-gate wbpb->bpb.media = 0xF0; 1143*0Sstevel@tonic-gate wbpb->bpb.num_root_entries = 240; 1144*0Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 2; 1145*0Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 9; 1146*0Sstevel@tonic-gate break; 1147*0Sstevel@tonic-gate default: 1148*0Sstevel@tonic-gate (void) fprintf(stderr, 1149*0Sstevel@tonic-gate gettext("Unknown diskette parameters! " 1150*0Sstevel@tonic-gate "3.5'' diskette with %d heads " 1151*0Sstevel@tonic-gate "and %d sectors/track.\n"), hds, spt); 1152*0Sstevel@tonic-gate warn_funky_floppy(); 1153*0Sstevel@tonic-gate } 1154*0Sstevel@tonic-gate break; 1155*0Sstevel@tonic-gate case 1: 1156*0Sstevel@tonic-gate default: 1157*0Sstevel@tonic-gate (void) fprintf(stderr, 1158*0Sstevel@tonic-gate gettext("Unknown diskette parameters! " 1159*0Sstevel@tonic-gate "3.5'' diskette with %d heads "), hds); 1160*0Sstevel@tonic-gate warn_funky_floppy(); 1161*0Sstevel@tonic-gate } 1162*0Sstevel@tonic-gate break; 1163*0Sstevel@tonic-gate case 5: 1164*0Sstevel@tonic-gate switch (hds) { 1165*0Sstevel@tonic-gate case 2: 1166*0Sstevel@tonic-gate switch (spt) { 1167*0Sstevel@tonic-gate case 15: 1168*0Sstevel@tonic-gate wbpb->bpb.media = 0xF9; 1169*0Sstevel@tonic-gate wbpb->bpb.num_root_entries = 224; 1170*0Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1; 1171*0Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 7; 1172*0Sstevel@tonic-gate break; 1173*0Sstevel@tonic-gate case 9: 1174*0Sstevel@tonic-gate wbpb->bpb.media = 0xFD; 1175*0Sstevel@tonic-gate wbpb->bpb.num_root_entries = 112; 1176*0Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 2; 1177*0Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 2; 1178*0Sstevel@tonic-gate break; 1179*0Sstevel@tonic-gate case 8: 1180*0Sstevel@tonic-gate wbpb->bpb.media = 0xFF; 1181*0Sstevel@tonic-gate wbpb->bpb.num_root_entries = 112; 1182*0Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1; 1183*0Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 2; 1184*0Sstevel@tonic-gate break; 1185*0Sstevel@tonic-gate default: 1186*0Sstevel@tonic-gate (void) fprintf(stderr, 1187*0Sstevel@tonic-gate gettext("Unknown diskette parameters! " 1188*0Sstevel@tonic-gate "5.25'' diskette with %d heads " 1189*0Sstevel@tonic-gate "and %d sectors/track.\n"), hds, spt); 1190*0Sstevel@tonic-gate warn_funky_floppy(); 1191*0Sstevel@tonic-gate } 1192*0Sstevel@tonic-gate break; 1193*0Sstevel@tonic-gate case 1: 1194*0Sstevel@tonic-gate switch (spt) { 1195*0Sstevel@tonic-gate case 9: 1196*0Sstevel@tonic-gate wbpb->bpb.media = 0xFC; 1197*0Sstevel@tonic-gate wbpb->bpb.num_root_entries = 64; 1198*0Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1; 1199*0Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 2; 1200*0Sstevel@tonic-gate break; 1201*0Sstevel@tonic-gate case 8: 1202*0Sstevel@tonic-gate wbpb->bpb.media = 0xFE; 1203*0Sstevel@tonic-gate wbpb->bpb.num_root_entries = 64; 1204*0Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1; 1205*0Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 1; 1206*0Sstevel@tonic-gate break; 1207*0Sstevel@tonic-gate default: 1208*0Sstevel@tonic-gate (void) fprintf(stderr, 1209*0Sstevel@tonic-gate gettext("Unknown diskette parameters! " 1210*0Sstevel@tonic-gate "5.25'' diskette with %d heads " 1211*0Sstevel@tonic-gate "and %d sectors/track.\n"), hds, spt); 1212*0Sstevel@tonic-gate warn_funky_floppy(); 1213*0Sstevel@tonic-gate } 1214*0Sstevel@tonic-gate break; 1215*0Sstevel@tonic-gate default: 1216*0Sstevel@tonic-gate (void) fprintf(stderr, 1217*0Sstevel@tonic-gate gettext("Unknown diskette parameters! " 1218*0Sstevel@tonic-gate "5.25'' diskette with %d heads."), hds); 1219*0Sstevel@tonic-gate warn_funky_floppy(); 1220*0Sstevel@tonic-gate } 1221*0Sstevel@tonic-gate break; 1222*0Sstevel@tonic-gate default: 1223*0Sstevel@tonic-gate (void) fprintf(stderr, 1224*0Sstevel@tonic-gate gettext("\nUnknown diskette type. Only know about " 1225*0Sstevel@tonic-gate "5.25'' and 3.5'' diskettes.\n")); 1226*0Sstevel@tonic-gate warn_funky_floppy(); 1227*0Sstevel@tonic-gate } 1228*0Sstevel@tonic-gate } 1229*0Sstevel@tonic-gate 1230*0Sstevel@tonic-gate /* 1231*0Sstevel@tonic-gate * lookup_floppy 1232*0Sstevel@tonic-gate * 1233*0Sstevel@tonic-gate * Look up a media descriptor byte and other crucial BPB values 1234*0Sstevel@tonic-gate * based on floppy characteristics. 1235*0Sstevel@tonic-gate */ 1236*0Sstevel@tonic-gate static 1237*0Sstevel@tonic-gate void 1238*0Sstevel@tonic-gate lookup_floppy(struct fd_char *fdchar, bpb_t *wbpb) 1239*0Sstevel@tonic-gate { 1240*0Sstevel@tonic-gate ulong_t tsize; 1241*0Sstevel@tonic-gate ulong_t cyls, spt, hds, diam; 1242*0Sstevel@tonic-gate 1243*0Sstevel@tonic-gate cyls = fdchar->fdc_ncyl; 1244*0Sstevel@tonic-gate diam = fdchar->fdc_medium; 1245*0Sstevel@tonic-gate spt = fdchar->fdc_secptrack; 1246*0Sstevel@tonic-gate hds = fdchar->fdc_nhead; 1247*0Sstevel@tonic-gate 1248*0Sstevel@tonic-gate tsize = cyls * hds * spt; 1249*0Sstevel@tonic-gate 1250*0Sstevel@tonic-gate if (GetFsParams) 1251*0Sstevel@tonic-gate TotSize = tsize; 1252*0Sstevel@tonic-gate 1253*0Sstevel@tonic-gate if (GetSize) { 1254*0Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = tsize; 1255*0Sstevel@tonic-gate } else { 1256*0Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = 1257*0Sstevel@tonic-gate warn_mismatch( 1258*0Sstevel@tonic-gate gettext("length of partition (in sectors)"), 1259*0Sstevel@tonic-gate gettext("FDIOGCHAR call"), tsize, TotSize); 1260*0Sstevel@tonic-gate } 1261*0Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = 1262*0Sstevel@tonic-gate (short)wbpb->bpb.sectors_in_logical_volume; 1263*0Sstevel@tonic-gate 1264*0Sstevel@tonic-gate if (GetSPT) { 1265*0Sstevel@tonic-gate wbpb->bpb.sectors_per_track = spt; 1266*0Sstevel@tonic-gate } else { 1267*0Sstevel@tonic-gate wbpb->bpb.sectors_per_track = 1268*0Sstevel@tonic-gate warn_mismatch( 1269*0Sstevel@tonic-gate gettext("sectors per track"), 1270*0Sstevel@tonic-gate gettext("FDIOGCHAR call"), spt, SecPerTrk); 1271*0Sstevel@tonic-gate spt = wbpb->bpb.sectors_per_track; 1272*0Sstevel@tonic-gate } 1273*0Sstevel@tonic-gate 1274*0Sstevel@tonic-gate if (GetTPC) { 1275*0Sstevel@tonic-gate wbpb->bpb.heads = hds; 1276*0Sstevel@tonic-gate } else { 1277*0Sstevel@tonic-gate wbpb->bpb.heads = 1278*0Sstevel@tonic-gate warn_mismatch( 1279*0Sstevel@tonic-gate gettext("number of heads"), 1280*0Sstevel@tonic-gate gettext("FDIOGCHAR call"), hds, TrkPerCyl); 1281*0Sstevel@tonic-gate hds = wbpb->bpb.heads; 1282*0Sstevel@tonic-gate } 1283*0Sstevel@tonic-gate 1284*0Sstevel@tonic-gate Fatentsize = 12; /* Size of fat entry in bits */ 1285*0Sstevel@tonic-gate if (!GetBPF && BitsPerFAT != Fatentsize) { 1286*0Sstevel@tonic-gate warn_funky_fatsize(); 1287*0Sstevel@tonic-gate } 1288*0Sstevel@tonic-gate set_fat_string(wbpb, Fatentsize); 1289*0Sstevel@tonic-gate 1290*0Sstevel@tonic-gate wbpb->ebpb.phys_drive_num = 0; 1291*0Sstevel@tonic-gate 1292*0Sstevel@tonic-gate wbpb->bpb.hidden_sectors = 0; 1293*0Sstevel@tonic-gate wbpb->sunbpb.bs_offset_high = 0; 1294*0Sstevel@tonic-gate wbpb->sunbpb.bs_offset_low = 0; 1295*0Sstevel@tonic-gate 1296*0Sstevel@tonic-gate floppy_bpb_fillin(wbpb, diam, hds, spt); 1297*0Sstevel@tonic-gate } 1298*0Sstevel@tonic-gate 1299*0Sstevel@tonic-gate /* 1300*0Sstevel@tonic-gate * compute_cluster_size 1301*0Sstevel@tonic-gate * 1302*0Sstevel@tonic-gate * Compute an acceptable sectors/cluster value. 1303*0Sstevel@tonic-gate * 1304*0Sstevel@tonic-gate * Values taken from a table found on p. 407 of "Windows 98 1305*0Sstevel@tonic-gate * Professional Reference", by Bruce A. Hallberg & Joe 1306*0Sstevel@tonic-gate * Casad. (ISBN 0-56205-786-3) I believe they've taken their 1307*0Sstevel@tonic-gate * table directly from the MSDN docs. 1308*0Sstevel@tonic-gate * 1309*0Sstevel@tonic-gate * FAT32 information taken from "Partition Magic 6.0", User Guide, p67. 1310*0Sstevel@tonic-gate * It uses strange values as 8.01, 16.02 and 32.04; the windows support 1311*0Sstevel@tonic-gate * site uses 8G and 16G. 1312*0Sstevel@tonic-gate */ 1313*0Sstevel@tonic-gate static 1314*0Sstevel@tonic-gate void 1315*0Sstevel@tonic-gate compute_cluster_size(bpb_t *wbpb) 1316*0Sstevel@tonic-gate { 1317*0Sstevel@tonic-gate ulong_t volsize, maxclusters; 1318*0Sstevel@tonic-gate ulong_t spc, spf; 1319*0Sstevel@tonic-gate 1320*0Sstevel@tonic-gate volsize = wbpb->bpb.sectors_in_volume ? wbpb->bpb.sectors_in_volume : 1321*0Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume; 1322*0Sstevel@tonic-gate volsize -= wbpb->bpb.resv_sectors; 1323*0Sstevel@tonic-gate 1324*0Sstevel@tonic-gate if (GetSPC) { 1325*0Sstevel@tonic-gate if (MakeFAT32) { 1326*0Sstevel@tonic-gate if (volsize <= 0x1000000) { /* 8G */ 1327*0Sstevel@tonic-gate spc = 8; 1328*0Sstevel@tonic-gate } else if (volsize <= 0x2000000) { /* 16G */ 1329*0Sstevel@tonic-gate spc = 16; 1330*0Sstevel@tonic-gate } else if (volsize <= 0x4000000) { /* 32G */ 1331*0Sstevel@tonic-gate spc = 32; 1332*0Sstevel@tonic-gate } else { 1333*0Sstevel@tonic-gate spc = 64; 1334*0Sstevel@tonic-gate } 1335*0Sstevel@tonic-gate } else { 1336*0Sstevel@tonic-gate if (volsize <= 0x10000) { /* 32M */ 1337*0Sstevel@tonic-gate spc = 1; 1338*0Sstevel@tonic-gate } else if (volsize <= 0x20000) { /* 64M */ 1339*0Sstevel@tonic-gate spc = 2; 1340*0Sstevel@tonic-gate } else if (volsize <= 0x40000) { /* 128M */ 1341*0Sstevel@tonic-gate spc = 4; 1342*0Sstevel@tonic-gate } else if (volsize <= 0x7f800) { /* 255M */ 1343*0Sstevel@tonic-gate spc = 8; 1344*0Sstevel@tonic-gate } else if (volsize <= 0xff800) { /* 511M */ 1345*0Sstevel@tonic-gate spc = 16; 1346*0Sstevel@tonic-gate } else if (volsize <= 0x1ff800) { /* 1023M */ 1347*0Sstevel@tonic-gate spc = 32; 1348*0Sstevel@tonic-gate } else if (volsize <= 0x3ff800) { /* 2047M */ 1349*0Sstevel@tonic-gate spc = 64; 1350*0Sstevel@tonic-gate } else if (volsize <= 0x7ff800) { /* 4095M */ 1351*0Sstevel@tonic-gate spc = 128; 1352*0Sstevel@tonic-gate } else { 1353*0Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1354*0Sstevel@tonic-gate "Partition too large for a FAT!\n")); 1355*0Sstevel@tonic-gate exit(4); 1356*0Sstevel@tonic-gate } 1357*0Sstevel@tonic-gate } 1358*0Sstevel@tonic-gate } else { 1359*0Sstevel@tonic-gate spc = SecPerClust; 1360*0Sstevel@tonic-gate } 1361*0Sstevel@tonic-gate 1362*0Sstevel@tonic-gate if (GetBPF) { 1363*0Sstevel@tonic-gate if (MakeFAT32) 1364*0Sstevel@tonic-gate Fatentsize = 32; 1365*0Sstevel@tonic-gate else 1366*0Sstevel@tonic-gate Fatentsize = 16; 1367*0Sstevel@tonic-gate } else { 1368*0Sstevel@tonic-gate Fatentsize = BitsPerFAT; 1369*0Sstevel@tonic-gate if (Fatentsize == 12 && volsize > DOS_F12MAXC * spc) { 1370*0Sstevel@tonic-gate /* 1371*0Sstevel@tonic-gate * 4228473 No way to non-interactively make a 1372*0Sstevel@tonic-gate * pcfs filesystem 1373*0Sstevel@tonic-gate * 1374*0Sstevel@tonic-gate * If we don't have an input TTY, or we aren't 1375*0Sstevel@tonic-gate * really doing anything, then don't ask 1376*0Sstevel@tonic-gate * questions. Assume a yes answer to any 1377*0Sstevel@tonic-gate * questions we would ask. 1378*0Sstevel@tonic-gate */ 1379*0Sstevel@tonic-gate if (Notreally || !isatty(fileno(stdin))) { 1380*0Sstevel@tonic-gate (void) printf( 1381*0Sstevel@tonic-gate gettext("Volume too large for 12 bit FAT," 1382*0Sstevel@tonic-gate " increasing to 16 bit FAT size.\n")); 1383*0Sstevel@tonic-gate (void) fflush(stdout); 1384*0Sstevel@tonic-gate Fatentsize = 16; 1385*0Sstevel@tonic-gate } else { 1386*0Sstevel@tonic-gate (void) printf( 1387*0Sstevel@tonic-gate gettext("Volume too large for a 12 bit FAT.\n" 1388*0Sstevel@tonic-gate "Increase to 16 bit FAT " 1389*0Sstevel@tonic-gate "and continue (y/n)? ")); 1390*0Sstevel@tonic-gate (void) fflush(stdout); 1391*0Sstevel@tonic-gate if (yes()) 1392*0Sstevel@tonic-gate Fatentsize = 16; 1393*0Sstevel@tonic-gate else 1394*0Sstevel@tonic-gate exit(5); 1395*0Sstevel@tonic-gate } 1396*0Sstevel@tonic-gate } 1397*0Sstevel@tonic-gate } 1398*0Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = spc; 1399*0Sstevel@tonic-gate 1400*0Sstevel@tonic-gate if (!GetFsParams && FdiskFATsize < 0) { 1401*0Sstevel@tonic-gate (void) printf( 1402*0Sstevel@tonic-gate gettext("Cannot verify chosen/computed FAT " 1403*0Sstevel@tonic-gate "entry size (%d bits) with FDISK table.\n" 1404*0Sstevel@tonic-gate "FDISK table has an unknown file system " 1405*0Sstevel@tonic-gate "type for this device. Giving up...\n"), 1406*0Sstevel@tonic-gate Fatentsize, Fatentsize); 1407*0Sstevel@tonic-gate exit(6); 1408*0Sstevel@tonic-gate } else if (!GetFsParams && FdiskFATsize && FdiskFATsize != Fatentsize) { 1409*0Sstevel@tonic-gate (void) printf( 1410*0Sstevel@tonic-gate gettext("Chosen/computed FAT entry size (%d bits) " 1411*0Sstevel@tonic-gate "does not match FDISK table (%d bits).\n"), 1412*0Sstevel@tonic-gate Fatentsize, FdiskFATsize); 1413*0Sstevel@tonic-gate (void) printf( 1414*0Sstevel@tonic-gate gettext("Use -o fat=%d to build a FAT " 1415*0Sstevel@tonic-gate "that matches the FDISK entry.\n"), FdiskFATsize); 1416*0Sstevel@tonic-gate exit(6); 1417*0Sstevel@tonic-gate } 1418*0Sstevel@tonic-gate set_fat_string(wbpb, Fatentsize); 1419*0Sstevel@tonic-gate 1420*0Sstevel@tonic-gate /* Compute a sector/fat figure */ 1421*0Sstevel@tonic-gate switch (Fatentsize) { 1422*0Sstevel@tonic-gate case 32: 1423*0Sstevel@tonic-gate /* 1424*0Sstevel@tonic-gate * We arrive at a formula for sectors/fat by simultaneously 1425*0Sstevel@tonic-gate * solving two equations: 1426*0Sstevel@tonic-gate * 1427*0Sstevel@tonic-gate * F = size of FAT (in sectors) 1428*0Sstevel@tonic-gate * V = volume size (in sectors) 1429*0Sstevel@tonic-gate * X = file area size (in clusters) 1430*0Sstevel@tonic-gate * 1431*0Sstevel@tonic-gate * X = (V - 2F)/8 <--- always 8 sectors/cluster for FAT32 1432*0Sstevel@tonic-gate * F = 4(X+2)/512 <--- 4 bytes/cluster-entry, 1433*0Sstevel@tonic-gate * 512 bytes/sector 1434*0Sstevel@tonic-gate * and so, 1435*0Sstevel@tonic-gate * F = 4(((V - 2F)/8)+2)/512 1436*0Sstevel@tonic-gate * ... 1437*0Sstevel@tonic-gate * F = V + 16 / 1026 1438*0Sstevel@tonic-gate */ 1439*0Sstevel@tonic-gate spf = idivceil(volsize + 16, 1026); 1440*0Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 0; 1441*0Sstevel@tonic-gate wbpb->bpb32.big_sectors_per_fat = spf; 1442*0Sstevel@tonic-gate break; 1443*0Sstevel@tonic-gate case 12: 1444*0Sstevel@tonic-gate maxclusters = idivceil(volsize, spc) + 2; 1445*0Sstevel@tonic-gate spf = idivceil(maxclusters, FAT12_ENTSPERSECT); 1446*0Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = (ushort_t)spf; 1447*0Sstevel@tonic-gate break; 1448*0Sstevel@tonic-gate default: /* 16 bit FAT */ 1449*0Sstevel@tonic-gate maxclusters = idivceil(volsize, spc) + 2; 1450*0Sstevel@tonic-gate spf = idivceil(maxclusters, FAT16_ENTSPERSECT); 1451*0Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = (ushort_t)spf; 1452*0Sstevel@tonic-gate break; 1453*0Sstevel@tonic-gate } 1454*0Sstevel@tonic-gate } 1455*0Sstevel@tonic-gate 1456*0Sstevel@tonic-gate static 1457*0Sstevel@tonic-gate void 1458*0Sstevel@tonic-gate find_fixed_details(int fd, bpb_t *wbpb) 1459*0Sstevel@tonic-gate { 1460*0Sstevel@tonic-gate struct dk_geom dginfo; 1461*0Sstevel@tonic-gate 1462*0Sstevel@tonic-gate /* 1463*0Sstevel@tonic-gate * Look up the last remaining bits of info we need 1464*0Sstevel@tonic-gate * that is specific to the hard drive using a disk ioctl. 1465*0Sstevel@tonic-gate */ 1466*0Sstevel@tonic-gate if (GetSPT || GetTPC) { 1467*0Sstevel@tonic-gate if ((ioctl(fd, DKIOCG_VIRTGEOM, &dginfo)) == -1) { 1468*0Sstevel@tonic-gate if ((ioctl(fd, DKIOCG_PHYGEOM, &dginfo)) == -1) { 1469*0Sstevel@tonic-gate if ((ioctl(fd, DKIOCGGEOM, &dginfo)) == -1) { 1470*0Sstevel@tonic-gate (void) close(fd); 1471*0Sstevel@tonic-gate perror( 1472*0Sstevel@tonic-gate gettext("Drive geometry lookup (need " 1473*0Sstevel@tonic-gate "tracks/cylinder and/or sectors/track")); 1474*0Sstevel@tonic-gate exit(2); 1475*0Sstevel@tonic-gate } 1476*0Sstevel@tonic-gate } 1477*0Sstevel@tonic-gate } 1478*0Sstevel@tonic-gate } 1479*0Sstevel@tonic-gate 1480*0Sstevel@tonic-gate wbpb->bpb.heads = (GetTPC ? dginfo.dkg_nhead : TrkPerCyl); 1481*0Sstevel@tonic-gate wbpb->bpb.sectors_per_track = (GetSPT ? dginfo.dkg_nsect : SecPerTrk); 1482*0Sstevel@tonic-gate 1483*0Sstevel@tonic-gate if (Verbose) { 1484*0Sstevel@tonic-gate if (GetTPC) { 1485*0Sstevel@tonic-gate (void) printf( 1486*0Sstevel@tonic-gate gettext("DKIOCG determined number of heads = %d\n"), 1487*0Sstevel@tonic-gate dginfo.dkg_nhead); 1488*0Sstevel@tonic-gate } 1489*0Sstevel@tonic-gate if (GetSPT) { 1490*0Sstevel@tonic-gate (void) printf( 1491*0Sstevel@tonic-gate gettext("DKIOCG determined sectors per track = %d\n"), 1492*0Sstevel@tonic-gate dginfo.dkg_nsect); 1493*0Sstevel@tonic-gate } 1494*0Sstevel@tonic-gate } 1495*0Sstevel@tonic-gate 1496*0Sstevel@tonic-gate /* 1497*0Sstevel@tonic-gate * XXX - MAY need an additional flag (or flags) to set media 1498*0Sstevel@tonic-gate * and physical drive number fields. That in the case of weird 1499*0Sstevel@tonic-gate * floppies that have to go through 'nofdisk' route for formatting. 1500*0Sstevel@tonic-gate */ 1501*0Sstevel@tonic-gate wbpb->bpb.media = 0xF8; 1502*0Sstevel@tonic-gate if (MakeFAT32) 1503*0Sstevel@tonic-gate wbpb->bpb.num_root_entries = 0; 1504*0Sstevel@tonic-gate else 1505*0Sstevel@tonic-gate wbpb->bpb.num_root_entries = 512; 1506*0Sstevel@tonic-gate wbpb->ebpb.phys_drive_num = 0x80; 1507*0Sstevel@tonic-gate compute_cluster_size(wbpb); 1508*0Sstevel@tonic-gate } 1509*0Sstevel@tonic-gate 1510*0Sstevel@tonic-gate static 1511*0Sstevel@tonic-gate char * 1512*0Sstevel@tonic-gate stat_actual_disk(char *diskname, struct stat *info, char **suffix) 1513*0Sstevel@tonic-gate { 1514*0Sstevel@tonic-gate char *actualdisk; 1515*0Sstevel@tonic-gate 1516*0Sstevel@tonic-gate if (stat(diskname, info)) { 1517*0Sstevel@tonic-gate /* 1518*0Sstevel@tonic-gate * Device named on command line doesn't exist. That 1519*0Sstevel@tonic-gate * probably means there is a partition-specifying 1520*0Sstevel@tonic-gate * suffix attached to the actual disk name. 1521*0Sstevel@tonic-gate */ 1522*0Sstevel@tonic-gate actualdisk = strtok(strdup(diskname), ":"); 1523*0Sstevel@tonic-gate if (*suffix = strchr(diskname, ':')) 1524*0Sstevel@tonic-gate (*suffix)++; 1525*0Sstevel@tonic-gate 1526*0Sstevel@tonic-gate if (stat(actualdisk, info)) { 1527*0Sstevel@tonic-gate perror(actualdisk); 1528*0Sstevel@tonic-gate exit(2); 1529*0Sstevel@tonic-gate } 1530*0Sstevel@tonic-gate } else { 1531*0Sstevel@tonic-gate actualdisk = strdup(diskname); 1532*0Sstevel@tonic-gate } 1533*0Sstevel@tonic-gate 1534*0Sstevel@tonic-gate return (actualdisk); 1535*0Sstevel@tonic-gate } 1536*0Sstevel@tonic-gate 1537*0Sstevel@tonic-gate static 1538*0Sstevel@tonic-gate void 1539*0Sstevel@tonic-gate compute_file_area_size(bpb_t *wbpb) 1540*0Sstevel@tonic-gate { 1541*0Sstevel@tonic-gate /* 1542*0Sstevel@tonic-gate * First we'll find total number of sectors in the file area... 1543*0Sstevel@tonic-gate */ 1544*0Sstevel@tonic-gate if (wbpb->bpb.sectors_in_volume > 0) 1545*0Sstevel@tonic-gate TotalClusters = wbpb->bpb.sectors_in_volume; 1546*0Sstevel@tonic-gate else 1547*0Sstevel@tonic-gate TotalClusters = wbpb->bpb.sectors_in_logical_volume; 1548*0Sstevel@tonic-gate 1549*0Sstevel@tonic-gate TotalClusters -= wbpb->bpb.resv_sectors; 1550*0Sstevel@tonic-gate TotalClusters -= wbpb->bpb.num_root_entries * sizeof (struct pcdir) / 1551*0Sstevel@tonic-gate BPSEC; 1552*0Sstevel@tonic-gate 1553*0Sstevel@tonic-gate if (wbpb->bpb.sectors_per_fat) { 1554*0Sstevel@tonic-gate /* 1555*0Sstevel@tonic-gate * Good old FAT12 or FAT16 1556*0Sstevel@tonic-gate */ 1557*0Sstevel@tonic-gate TotalClusters -= 2 * wbpb->bpb.sectors_per_fat; 1558*0Sstevel@tonic-gate } else { 1559*0Sstevel@tonic-gate /* 1560*0Sstevel@tonic-gate * FAT32 1561*0Sstevel@tonic-gate */ 1562*0Sstevel@tonic-gate TotalClusters -= 2 * wbpb->bpb32.big_sectors_per_fat; 1563*0Sstevel@tonic-gate } 1564*0Sstevel@tonic-gate 1565*0Sstevel@tonic-gate /* 1566*0Sstevel@tonic-gate * Now change sectors to clusters 1567*0Sstevel@tonic-gate */ 1568*0Sstevel@tonic-gate TotalClusters = TotalClusters / wbpb->bpb.sectors_per_cluster; 1569*0Sstevel@tonic-gate 1570*0Sstevel@tonic-gate if (Verbose) 1571*0Sstevel@tonic-gate (void) printf(gettext("Disk has a file area of %d " 1572*0Sstevel@tonic-gate "allocation units,\neach with %d sectors = %d " 1573*0Sstevel@tonic-gate "bytes.\n"), TotalClusters, wbpb->bpb.sectors_per_cluster, 1574*0Sstevel@tonic-gate TotalClusters * wbpb->bpb.sectors_per_cluster * BPSEC); 1575*0Sstevel@tonic-gate } 1576*0Sstevel@tonic-gate 1577*0Sstevel@tonic-gate #ifndef i386 1578*0Sstevel@tonic-gate /* 1579*0Sstevel@tonic-gate * swap_pack_{bpb,bpb32,sebpb}cpy 1580*0Sstevel@tonic-gate * 1581*0Sstevel@tonic-gate * If not on an x86 we assume the structures making up the bpb 1582*0Sstevel@tonic-gate * were not packed and that longs and shorts need to be byte swapped 1583*0Sstevel@tonic-gate * (we've kept everything in host order up until now). A new architecture 1584*0Sstevel@tonic-gate * might not need to swap or might not need to pack, in which case 1585*0Sstevel@tonic-gate * new routines will have to be written. Of course if an architecture 1586*0Sstevel@tonic-gate * supports both packing and little-endian host order, it can follow the 1587*0Sstevel@tonic-gate * same path as the x86 code. 1588*0Sstevel@tonic-gate */ 1589*0Sstevel@tonic-gate static 1590*0Sstevel@tonic-gate void 1591*0Sstevel@tonic-gate swap_pack_bpbcpy(struct _boot_sector *bsp, bpb_t *wbpb) 1592*0Sstevel@tonic-gate { 1593*0Sstevel@tonic-gate uchar_t *fillp; 1594*0Sstevel@tonic-gate 1595*0Sstevel@tonic-gate fillp = (uchar_t *)&(bsp->bs_filler[ORIG_BPB_START_INDEX]); 1596*0Sstevel@tonic-gate 1597*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.bytes_sector); 1598*0Sstevel@tonic-gate *fillp++ = wbpb->bpb.sectors_per_cluster; 1599*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.resv_sectors); 1600*0Sstevel@tonic-gate *fillp++ = wbpb->bpb.num_fats; 1601*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.num_root_entries); 1602*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_in_volume); 1603*0Sstevel@tonic-gate *fillp++ = wbpb->bpb.media; 1604*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_per_fat); 1605*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_per_track); 1606*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.heads); 1607*0Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb.hidden_sectors); 1608*0Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb.sectors_in_logical_volume); 1609*0Sstevel@tonic-gate 1610*0Sstevel@tonic-gate *fillp++ = wbpb->ebpb.phys_drive_num; 1611*0Sstevel@tonic-gate *fillp++ = wbpb->ebpb.reserved; 1612*0Sstevel@tonic-gate *fillp++ = wbpb->ebpb.ext_signature; 1613*0Sstevel@tonic-gate store_32_bits(&fillp, wbpb->ebpb.volume_id); 1614*0Sstevel@tonic-gate (void) strncpy((char *)fillp, (char *)wbpb->ebpb.volume_label, 11); 1615*0Sstevel@tonic-gate fillp += 11; 1616*0Sstevel@tonic-gate (void) strncpy((char *)fillp, (char *)wbpb->ebpb.type, 8); 1617*0Sstevel@tonic-gate } 1618*0Sstevel@tonic-gate 1619*0Sstevel@tonic-gate static 1620*0Sstevel@tonic-gate void 1621*0Sstevel@tonic-gate swap_pack_bpb32cpy(struct _boot_sector32 *bsp, bpb_t *wbpb) 1622*0Sstevel@tonic-gate { 1623*0Sstevel@tonic-gate uchar_t *fillp; 1624*0Sstevel@tonic-gate int r; 1625*0Sstevel@tonic-gate 1626*0Sstevel@tonic-gate fillp = (uchar_t *)&(bsp->bs_filler[ORIG_BPB_START_INDEX]); 1627*0Sstevel@tonic-gate 1628*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.bytes_sector); 1629*0Sstevel@tonic-gate *fillp++ = wbpb->bpb.sectors_per_cluster; 1630*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.resv_sectors); 1631*0Sstevel@tonic-gate *fillp++ = wbpb->bpb.num_fats; 1632*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.num_root_entries); 1633*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_in_volume); 1634*0Sstevel@tonic-gate *fillp++ = wbpb->bpb.media; 1635*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_per_fat); 1636*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_per_track); 1637*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.heads); 1638*0Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb.hidden_sectors); 1639*0Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb.sectors_in_logical_volume); 1640*0Sstevel@tonic-gate 1641*0Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb32.big_sectors_per_fat); 1642*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb32.ext_flags); 1643*0Sstevel@tonic-gate *fillp++ = wbpb->bpb32.fs_vers_lo; 1644*0Sstevel@tonic-gate *fillp++ = wbpb->bpb32.fs_vers_hi; 1645*0Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb32.root_dir_clust); 1646*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb32.fsinfosec); 1647*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb32.backupboot); 1648*0Sstevel@tonic-gate for (r = 0; r < 6; r++) 1649*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb32.reserved[r]); 1650*0Sstevel@tonic-gate 1651*0Sstevel@tonic-gate *fillp++ = wbpb->ebpb.phys_drive_num; 1652*0Sstevel@tonic-gate *fillp++ = wbpb->ebpb.reserved; 1653*0Sstevel@tonic-gate *fillp++ = wbpb->ebpb.ext_signature; 1654*0Sstevel@tonic-gate store_32_bits(&fillp, wbpb->ebpb.volume_id); 1655*0Sstevel@tonic-gate (void) strncpy((char *)fillp, (char *)wbpb->ebpb.volume_label, 11); 1656*0Sstevel@tonic-gate fillp += 11; 1657*0Sstevel@tonic-gate (void) strncpy((char *)fillp, (char *)wbpb->ebpb.type, 8); 1658*0Sstevel@tonic-gate } 1659*0Sstevel@tonic-gate 1660*0Sstevel@tonic-gate static 1661*0Sstevel@tonic-gate void 1662*0Sstevel@tonic-gate swap_pack_sebpbcpy(struct _boot_sector *bsp, bpb_t *wbpb) 1663*0Sstevel@tonic-gate { 1664*0Sstevel@tonic-gate uchar_t *fillp; 1665*0Sstevel@tonic-gate 1666*0Sstevel@tonic-gate fillp = bsp->bs_sun_bpb; 1667*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->sunbpb.bs_offset_high); 1668*0Sstevel@tonic-gate store_16_bits(&fillp, wbpb->sunbpb.bs_offset_low); 1669*0Sstevel@tonic-gate } 1670*0Sstevel@tonic-gate 1671*0Sstevel@tonic-gate static 1672*0Sstevel@tonic-gate void 1673*0Sstevel@tonic-gate swap_pack_grabbpb(bpb_t *wbpb, struct _boot_sector *bsp) 1674*0Sstevel@tonic-gate { 1675*0Sstevel@tonic-gate uchar_t *grabp; 1676*0Sstevel@tonic-gate 1677*0Sstevel@tonic-gate grabp = (uchar_t *)&(bsp->bs_filler[ORIG_BPB_START_INDEX]); 1678*0Sstevel@tonic-gate 1679*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.bytes_sector))[1] = *grabp++; 1680*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.bytes_sector))[0] = *grabp++; 1681*0Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = *grabp++; 1682*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.resv_sectors))[1] = *grabp++; 1683*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.resv_sectors))[0] = *grabp++; 1684*0Sstevel@tonic-gate wbpb->bpb.num_fats = *grabp++; 1685*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.num_root_entries))[1] = *grabp++; 1686*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.num_root_entries))[0] = *grabp++; 1687*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_volume))[1] = *grabp++; 1688*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_volume))[0] = *grabp++; 1689*0Sstevel@tonic-gate wbpb->bpb.media = *grabp++; 1690*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_per_fat))[1] = *grabp++; 1691*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_per_fat))[0] = *grabp++; 1692*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_per_track))[1] = *grabp++; 1693*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_per_track))[0] = *grabp++; 1694*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.heads))[1] = *grabp++; 1695*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.heads))[0] = *grabp++; 1696*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.hidden_sectors))[3] = *grabp++; 1697*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.hidden_sectors))[2] = *grabp++; 1698*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.hidden_sectors))[1] = *grabp++; 1699*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.hidden_sectors))[0] = *grabp++; 1700*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[3] = *grabp++; 1701*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[2] = *grabp++; 1702*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[1] = *grabp++; 1703*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[0] = *grabp++; 1704*0Sstevel@tonic-gate wbpb->ebpb.phys_drive_num = *grabp++; 1705*0Sstevel@tonic-gate wbpb->ebpb.reserved = *grabp++; 1706*0Sstevel@tonic-gate wbpb->ebpb.ext_signature = *grabp++; 1707*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->ebpb.volume_id))[3] = *grabp++; 1708*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->ebpb.volume_id))[2] = *grabp++; 1709*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->ebpb.volume_id))[1] = *grabp++; 1710*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->ebpb.volume_id))[0] = *grabp++; 1711*0Sstevel@tonic-gate 1712*0Sstevel@tonic-gate (void) strncpy((char *)wbpb->ebpb.volume_label, (char *)grabp, 11); 1713*0Sstevel@tonic-gate grabp += 11; 1714*0Sstevel@tonic-gate (void) strncpy((char *)wbpb->ebpb.type, (char *)grabp, 8); 1715*0Sstevel@tonic-gate } 1716*0Sstevel@tonic-gate 1717*0Sstevel@tonic-gate static 1718*0Sstevel@tonic-gate void 1719*0Sstevel@tonic-gate swap_pack_grabsebpb(bpb_t *wbpb, struct _boot_sector *bsp) 1720*0Sstevel@tonic-gate { 1721*0Sstevel@tonic-gate uchar_t *grabp; 1722*0Sstevel@tonic-gate 1723*0Sstevel@tonic-gate grabp = bsp->bs_sun_bpb; 1724*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->sunbpb.bs_offset_high))[1] = *grabp++; 1725*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->sunbpb.bs_offset_high))[0] = *grabp++; 1726*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->sunbpb.bs_offset_low))[1] = *grabp++; 1727*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->sunbpb.bs_offset_low))[0] = *grabp++; 1728*0Sstevel@tonic-gate } 1729*0Sstevel@tonic-gate 1730*0Sstevel@tonic-gate static 1731*0Sstevel@tonic-gate void 1732*0Sstevel@tonic-gate swap_pack_grab32bpb(bpb_t *wbpb, struct _boot_sector *bsp) 1733*0Sstevel@tonic-gate { 1734*0Sstevel@tonic-gate uchar_t *grabp; 1735*0Sstevel@tonic-gate 1736*0Sstevel@tonic-gate grabp = (uchar_t *)&(bsp->bs_filler[BPB_32_START_INDEX]); 1737*0Sstevel@tonic-gate 1738*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[3] = *grabp++; 1739*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[2] = *grabp++; 1740*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[1] = *grabp++; 1741*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[0] = *grabp++; 1742*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.ext_flags))[1] = *grabp++; 1743*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.ext_flags))[0] = *grabp++; 1744*0Sstevel@tonic-gate wbpb->bpb32.fs_vers_lo = *grabp++; 1745*0Sstevel@tonic-gate wbpb->bpb32.fs_vers_hi = *grabp++; 1746*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.root_dir_clust))[3] = *grabp++; 1747*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.root_dir_clust))[2] = *grabp++; 1748*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.root_dir_clust))[1] = *grabp++; 1749*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.root_dir_clust))[0] = *grabp++; 1750*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.fsinfosec))[1] = *grabp++; 1751*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.fsinfosec))[0] = *grabp++; 1752*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.backupboot))[1] = *grabp++; 1753*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.backupboot))[0] = *grabp++; 1754*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[0]))[1] = *grabp++; 1755*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[0]))[0] = *grabp++; 1756*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[1]))[1] = *grabp++; 1757*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[1]))[0] = *grabp++; 1758*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[2]))[1] = *grabp++; 1759*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[2]))[0] = *grabp++; 1760*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[3]))[1] = *grabp++; 1761*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[3]))[0] = *grabp++; 1762*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[4]))[1] = *grabp++; 1763*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[4]))[0] = *grabp++; 1764*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[5]))[1] = *grabp++; 1765*0Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[5]))[0] = *grabp++; 1766*0Sstevel@tonic-gate } 1767*0Sstevel@tonic-gate #endif /* ! i386 */ 1768*0Sstevel@tonic-gate 1769*0Sstevel@tonic-gate static 1770*0Sstevel@tonic-gate void 1771*0Sstevel@tonic-gate dashm_bail(int fd) 1772*0Sstevel@tonic-gate { 1773*0Sstevel@tonic-gate (void) fprintf(stderr, 1774*0Sstevel@tonic-gate gettext("This media does not appear to be " 1775*0Sstevel@tonic-gate "formatted with a FAT file system.\n")); 1776*0Sstevel@tonic-gate (void) close(fd); 1777*0Sstevel@tonic-gate exit(6); 1778*0Sstevel@tonic-gate } 1779*0Sstevel@tonic-gate 1780*0Sstevel@tonic-gate /* 1781*0Sstevel@tonic-gate * read_existing_bpb 1782*0Sstevel@tonic-gate * 1783*0Sstevel@tonic-gate * Grab the first sector, which we think is a bios parameter block. 1784*0Sstevel@tonic-gate * If it looks bad, bail. Otherwise fill in the parameter struct 1785*0Sstevel@tonic-gate * fields that matter. 1786*0Sstevel@tonic-gate */ 1787*0Sstevel@tonic-gate static 1788*0Sstevel@tonic-gate void 1789*0Sstevel@tonic-gate read_existing_bpb(int fd, bpb_t *wbpb) 1790*0Sstevel@tonic-gate { 1791*0Sstevel@tonic-gate boot_sector_t ubpb; 1792*0Sstevel@tonic-gate 1793*0Sstevel@tonic-gate if (read(fd, ubpb.buf, BPSEC) < BPSEC) { 1794*0Sstevel@tonic-gate perror(gettext("Read BIOS parameter block " 1795*0Sstevel@tonic-gate "from previously formatted media")); 1796*0Sstevel@tonic-gate (void) close(fd); 1797*0Sstevel@tonic-gate exit(6); 1798*0Sstevel@tonic-gate } 1799*0Sstevel@tonic-gate 1800*0Sstevel@tonic-gate if (ltohs(ubpb.mb.signature) != BOOTSECSIG) { 1801*0Sstevel@tonic-gate dashm_bail(fd); 1802*0Sstevel@tonic-gate } 1803*0Sstevel@tonic-gate 1804*0Sstevel@tonic-gate #ifdef i386 1805*0Sstevel@tonic-gate (void) memcpy(&(wbpb->bpb), &(ubpb.bs.bs_front.bs_bpb), 1806*0Sstevel@tonic-gate sizeof (wbpb->bpb)); 1807*0Sstevel@tonic-gate (void) memcpy(&(wbpb->ebpb), &(ubpb.bs.bs_ebpb), sizeof (wbpb->ebpb)); 1808*0Sstevel@tonic-gate #else 1809*0Sstevel@tonic-gate swap_pack_grabbpb(wbpb, &(ubpb.bs)); 1810*0Sstevel@tonic-gate #endif 1811*0Sstevel@tonic-gate if (SunBPBfields) { 1812*0Sstevel@tonic-gate #ifdef i386 1813*0Sstevel@tonic-gate (void) memcpy(&(wbpb->sunbpb), &(ubpb.bs.bs_sebpb), 1814*0Sstevel@tonic-gate sizeof (wbpb->sunbpb)); 1815*0Sstevel@tonic-gate #else 1816*0Sstevel@tonic-gate swap_pack_grabsebpb(wbpb, &(ubpb.bs)); 1817*0Sstevel@tonic-gate #endif 1818*0Sstevel@tonic-gate } 1819*0Sstevel@tonic-gate if (wbpb->bpb.bytes_sector != BPSEC) { 1820*0Sstevel@tonic-gate (void) fprintf(stderr, 1821*0Sstevel@tonic-gate gettext("Bogus bytes per sector value.\n")); 1822*0Sstevel@tonic-gate if (!powerofx_le_y(2, BPSEC * 8, wbpb->bpb.bytes_sector)) { 1823*0Sstevel@tonic-gate (void) fprintf(stderr, 1824*0Sstevel@tonic-gate gettext("The device name may be missing a " 1825*0Sstevel@tonic-gate "logical drive specifier.\n")); 1826*0Sstevel@tonic-gate (void) close(fd); 1827*0Sstevel@tonic-gate exit(6); 1828*0Sstevel@tonic-gate } else { 1829*0Sstevel@tonic-gate (void) fprintf(stderr, 1830*0Sstevel@tonic-gate gettext("Do not know how to build FATs with a\n" 1831*0Sstevel@tonic-gate "non-standard sector size. Standard " 1832*0Sstevel@tonic-gate "size is %d bytes,\nyour sector size " 1833*0Sstevel@tonic-gate "is %d bytes.\n"), BPSEC, 1834*0Sstevel@tonic-gate wbpb->bpb.bytes_sector); 1835*0Sstevel@tonic-gate (void) close(fd); 1836*0Sstevel@tonic-gate exit(6); 1837*0Sstevel@tonic-gate } 1838*0Sstevel@tonic-gate } 1839*0Sstevel@tonic-gate if (!(powerofx_le_y(2, 128, wbpb->bpb.sectors_per_cluster))) { 1840*0Sstevel@tonic-gate (void) fprintf(stderr, 1841*0Sstevel@tonic-gate gettext("Bogus sectors per cluster value.\n")); 1842*0Sstevel@tonic-gate (void) fprintf(stderr, 1843*0Sstevel@tonic-gate gettext("The device name may be missing a " 1844*0Sstevel@tonic-gate "logical drive specifier.\n")); 1845*0Sstevel@tonic-gate (void) close(fd); 1846*0Sstevel@tonic-gate exit(6); 1847*0Sstevel@tonic-gate } 1848*0Sstevel@tonic-gate 1849*0Sstevel@tonic-gate if (wbpb->bpb.sectors_per_fat == 0) { 1850*0Sstevel@tonic-gate #ifdef i386 1851*0Sstevel@tonic-gate (void) memcpy(&(wbpb->bpb32), &(ubpb.bs32.bs_bpb32), 1852*0Sstevel@tonic-gate sizeof (wbpb->bpb32)); 1853*0Sstevel@tonic-gate #else 1854*0Sstevel@tonic-gate swap_pack_grab32bpb(wbpb, &(ubpb.bs)); 1855*0Sstevel@tonic-gate #endif 1856*0Sstevel@tonic-gate compute_file_area_size(wbpb); 1857*0Sstevel@tonic-gate if ((wbpb->bpb32.big_sectors_per_fat * BPSEC / 4) >= 1858*0Sstevel@tonic-gate TotalClusters) { 1859*0Sstevel@tonic-gate MakeFAT32 = 1; 1860*0Sstevel@tonic-gate } else { 1861*0Sstevel@tonic-gate dashm_bail(fd); 1862*0Sstevel@tonic-gate } 1863*0Sstevel@tonic-gate } else { 1864*0Sstevel@tonic-gate compute_file_area_size(wbpb); 1865*0Sstevel@tonic-gate } 1866*0Sstevel@tonic-gate } 1867*0Sstevel@tonic-gate 1868*0Sstevel@tonic-gate /* 1869*0Sstevel@tonic-gate * compare_existing_with_computed 1870*0Sstevel@tonic-gate * 1871*0Sstevel@tonic-gate * We use this function when we the user specifies the -m option. 1872*0Sstevel@tonic-gate * We compute and look up things like we would if they had asked 1873*0Sstevel@tonic-gate * us to make the fs, and compare that to what's already layed down 1874*0Sstevel@tonic-gate * in the existing fs. If there's a difference we can tell them what 1875*0Sstevel@tonic-gate * options to specify in order to reproduce their existing layout. 1876*0Sstevel@tonic-gate * Note that they still may not get an exact duplicate, because we 1877*0Sstevel@tonic-gate * don't, for example, preserve their existing boot code. We think 1878*0Sstevel@tonic-gate * we've got all the fields that matter covered, though. 1879*0Sstevel@tonic-gate * 1880*0Sstevel@tonic-gate * XXX - We're basically ignoring sbpb at this point. I'm unsure 1881*0Sstevel@tonic-gate * if we'll ever care about those fields, in terms of the -m option. 1882*0Sstevel@tonic-gate */ 1883*0Sstevel@tonic-gate static 1884*0Sstevel@tonic-gate void 1885*0Sstevel@tonic-gate compare_existing_with_computed(int fd, char *suffix, 1886*0Sstevel@tonic-gate bpb_t *wbpb, int *prtsize, int *prtspc, int *prtbpf, int *prtnsect, 1887*0Sstevel@tonic-gate int *prtntrk, int *prtfdisk, int *prthidden, int *prtrsrvd, int *dashos) 1888*0Sstevel@tonic-gate { 1889*0Sstevel@tonic-gate struct dk_geom dginfo; 1890*0Sstevel@tonic-gate struct fd_char fdchar; 1891*0Sstevel@tonic-gate bpb_t compare; 1892*0Sstevel@tonic-gate int fd_ioctl_worked = 0; 1893*0Sstevel@tonic-gate int fatents; 1894*0Sstevel@tonic-gate 1895*0Sstevel@tonic-gate /* 1896*0Sstevel@tonic-gate * For all non-floppy cases we expect to find a 16-bit FAT 1897*0Sstevel@tonic-gate */ 1898*0Sstevel@tonic-gate int expectfatsize = 16; 1899*0Sstevel@tonic-gate 1900*0Sstevel@tonic-gate compare = *wbpb; 1901*0Sstevel@tonic-gate 1902*0Sstevel@tonic-gate if (!suffix) { 1903*0Sstevel@tonic-gate if (ioctl(fd, FDIOGCHAR, &fdchar) != -1) { 1904*0Sstevel@tonic-gate expectfatsize = 12; 1905*0Sstevel@tonic-gate fd_ioctl_worked++; 1906*0Sstevel@tonic-gate } 1907*0Sstevel@tonic-gate } 1908*0Sstevel@tonic-gate 1909*0Sstevel@tonic-gate if (fd_ioctl_worked) { 1910*0Sstevel@tonic-gate #ifdef sparc 1911*0Sstevel@tonic-gate fdchar.fdc_medium = 3; 1912*0Sstevel@tonic-gate #endif 1913*0Sstevel@tonic-gate GetSize = GetSPT = GetSPC = GetTPC = GetBPF = 1; 1914*0Sstevel@tonic-gate lookup_floppy(&fdchar, &compare); 1915*0Sstevel@tonic-gate if (compare.bpb.heads != wbpb->bpb.heads) { 1916*0Sstevel@tonic-gate (*prtntrk)++; 1917*0Sstevel@tonic-gate (*dashos)++; 1918*0Sstevel@tonic-gate } 1919*0Sstevel@tonic-gate if (compare.bpb.sectors_per_track != 1920*0Sstevel@tonic-gate wbpb->bpb.sectors_per_track) { 1921*0Sstevel@tonic-gate (*prtnsect)++; 1922*0Sstevel@tonic-gate (*dashos)++; 1923*0Sstevel@tonic-gate } 1924*0Sstevel@tonic-gate } else { 1925*0Sstevel@tonic-gate int dk_ioctl_worked = 1; 1926*0Sstevel@tonic-gate 1927*0Sstevel@tonic-gate if (!suffix) { 1928*0Sstevel@tonic-gate (*prtfdisk)++; 1929*0Sstevel@tonic-gate (*prtsize)++; 1930*0Sstevel@tonic-gate *dashos += 2; 1931*0Sstevel@tonic-gate } 1932*0Sstevel@tonic-gate if ((ioctl(fd, DKIOCG_VIRTGEOM, &dginfo)) == -1) { 1933*0Sstevel@tonic-gate if ((ioctl(fd, DKIOCG_PHYGEOM, &dginfo)) == -1) { 1934*0Sstevel@tonic-gate if ((ioctl(fd, DKIOCGGEOM, &dginfo)) == -1) { 1935*0Sstevel@tonic-gate *prtnsect = *prtntrk = 1; 1936*0Sstevel@tonic-gate *dashos += 2; 1937*0Sstevel@tonic-gate dk_ioctl_worked = 0; 1938*0Sstevel@tonic-gate } 1939*0Sstevel@tonic-gate } 1940*0Sstevel@tonic-gate } 1941*0Sstevel@tonic-gate if (dk_ioctl_worked) { 1942*0Sstevel@tonic-gate if (dginfo.dkg_nhead != wbpb->bpb.heads) { 1943*0Sstevel@tonic-gate (*prtntrk)++; 1944*0Sstevel@tonic-gate (*dashos)++; 1945*0Sstevel@tonic-gate } 1946*0Sstevel@tonic-gate if (dginfo.dkg_nsect != 1947*0Sstevel@tonic-gate wbpb->bpb.sectors_per_track) { 1948*0Sstevel@tonic-gate (*prtnsect)++; 1949*0Sstevel@tonic-gate (*dashos)++; 1950*0Sstevel@tonic-gate } 1951*0Sstevel@tonic-gate } 1952*0Sstevel@tonic-gate GetBPF = GetSPC = 1; 1953*0Sstevel@tonic-gate compute_cluster_size(&compare); 1954*0Sstevel@tonic-gate } 1955*0Sstevel@tonic-gate 1956*0Sstevel@tonic-gate if (!*prtfdisk && TotSize != wbpb->bpb.sectors_in_volume && 1957*0Sstevel@tonic-gate TotSize != wbpb->bpb.sectors_in_logical_volume) { 1958*0Sstevel@tonic-gate (*dashos)++; 1959*0Sstevel@tonic-gate (*prtsize)++; 1960*0Sstevel@tonic-gate } 1961*0Sstevel@tonic-gate 1962*0Sstevel@tonic-gate if (compare.bpb.sectors_per_cluster != wbpb->bpb.sectors_per_cluster) { 1963*0Sstevel@tonic-gate (*dashos)++; 1964*0Sstevel@tonic-gate (*prtspc)++; 1965*0Sstevel@tonic-gate } 1966*0Sstevel@tonic-gate 1967*0Sstevel@tonic-gate if (compare.bpb.hidden_sectors != wbpb->bpb.hidden_sectors) { 1968*0Sstevel@tonic-gate (*dashos)++; 1969*0Sstevel@tonic-gate (*prthidden)++; 1970*0Sstevel@tonic-gate } 1971*0Sstevel@tonic-gate 1972*0Sstevel@tonic-gate if (compare.bpb.resv_sectors != wbpb->bpb.resv_sectors) { 1973*0Sstevel@tonic-gate (*dashos)++; 1974*0Sstevel@tonic-gate (*prtrsrvd)++; 1975*0Sstevel@tonic-gate } 1976*0Sstevel@tonic-gate 1977*0Sstevel@tonic-gate /* 1978*0Sstevel@tonic-gate * Compute approximate Fatentsize. It's approximate because the 1979*0Sstevel@tonic-gate * size of the FAT may not be exactly a multiple of the number of 1980*0Sstevel@tonic-gate * clusters. It should be close, though. 1981*0Sstevel@tonic-gate */ 1982*0Sstevel@tonic-gate if (MakeFAT32) { 1983*0Sstevel@tonic-gate Fatentsize = 32; 1984*0Sstevel@tonic-gate (*dashos)++; 1985*0Sstevel@tonic-gate (*prtbpf)++; 1986*0Sstevel@tonic-gate } else { 1987*0Sstevel@tonic-gate fatents = wbpb->bpb.sectors_per_fat * BPSEC * 2 / 3; 1988*0Sstevel@tonic-gate if (fatents >= TotalClusters && wbpb->ebpb.type[4] == '2') 1989*0Sstevel@tonic-gate Fatentsize = 12; 1990*0Sstevel@tonic-gate else 1991*0Sstevel@tonic-gate Fatentsize = 16; 1992*0Sstevel@tonic-gate if (Fatentsize != expectfatsize) { 1993*0Sstevel@tonic-gate (*dashos)++; 1994*0Sstevel@tonic-gate (*prtbpf)++; 1995*0Sstevel@tonic-gate } 1996*0Sstevel@tonic-gate } 1997*0Sstevel@tonic-gate } 1998*0Sstevel@tonic-gate 1999*0Sstevel@tonic-gate static 2000*0Sstevel@tonic-gate void 2001*0Sstevel@tonic-gate print_reproducing_command(int fd, char *actualdisk, char *suffix, bpb_t *wbpb) 2002*0Sstevel@tonic-gate { 2003*0Sstevel@tonic-gate int needcomma = 0; 2004*0Sstevel@tonic-gate int prthidden = 0; 2005*0Sstevel@tonic-gate int prtrsrvd = 0; 2006*0Sstevel@tonic-gate int prtfdisk = 0; 2007*0Sstevel@tonic-gate int prtnsect = 0; 2008*0Sstevel@tonic-gate int prtntrk = 0; 2009*0Sstevel@tonic-gate int prtsize = 0; 2010*0Sstevel@tonic-gate int prtbpf = 0; 2011*0Sstevel@tonic-gate int prtspc = 0; 2012*0Sstevel@tonic-gate int dashos = 0; 2013*0Sstevel@tonic-gate int ll, i; 2014*0Sstevel@tonic-gate 2015*0Sstevel@tonic-gate compare_existing_with_computed(fd, suffix, wbpb, 2016*0Sstevel@tonic-gate &prtsize, &prtspc, &prtbpf, &prtnsect, &prtntrk, 2017*0Sstevel@tonic-gate &prtfdisk, &prthidden, &prtrsrvd, &dashos); 2018*0Sstevel@tonic-gate 2019*0Sstevel@tonic-gate /* 2020*0Sstevel@tonic-gate * Print out the command line they can use to reproduce the 2021*0Sstevel@tonic-gate * file system. 2022*0Sstevel@tonic-gate */ 2023*0Sstevel@tonic-gate (void) printf("mkfs -F pcfs"); 2024*0Sstevel@tonic-gate 2025*0Sstevel@tonic-gate ll = min(11, (int)strlen((char *)wbpb->ebpb.volume_label)); 2026*0Sstevel@tonic-gate /* 2027*0Sstevel@tonic-gate * First, eliminate trailing spaces. Now compare the name against 2028*0Sstevel@tonic-gate * our default label. If there's a match we don't need to print 2029*0Sstevel@tonic-gate * any label info. 2030*0Sstevel@tonic-gate */ 2031*0Sstevel@tonic-gate i = ll; 2032*0Sstevel@tonic-gate while (wbpb->ebpb.volume_label[--i] == ' '); 2033*0Sstevel@tonic-gate ll = i; 2034*0Sstevel@tonic-gate 2035*0Sstevel@tonic-gate if (ll == strlen(DEFAULT_LABEL) - 1) { 2036*0Sstevel@tonic-gate char cmpbuf[11]; 2037*0Sstevel@tonic-gate 2038*0Sstevel@tonic-gate (void) strcpy(cmpbuf, DEFAULT_LABEL); 2039*0Sstevel@tonic-gate for (i = ll; i >= 0; i--) { 2040*0Sstevel@tonic-gate if (cmpbuf[i] != 2041*0Sstevel@tonic-gate toupper((int)(wbpb->ebpb.volume_label[i]))) { 2042*0Sstevel@tonic-gate break; 2043*0Sstevel@tonic-gate } 2044*0Sstevel@tonic-gate } 2045*0Sstevel@tonic-gate if (i < 0) 2046*0Sstevel@tonic-gate ll = i; 2047*0Sstevel@tonic-gate } 2048*0Sstevel@tonic-gate 2049*0Sstevel@tonic-gate if (ll >= 0) { 2050*0Sstevel@tonic-gate (void) printf(" -o "); 2051*0Sstevel@tonic-gate (void) printf("b=\""); 2052*0Sstevel@tonic-gate for (i = 0; i <= ll; i++) { 2053*0Sstevel@tonic-gate (void) printf("%c", wbpb->ebpb.volume_label[i]); 2054*0Sstevel@tonic-gate } 2055*0Sstevel@tonic-gate (void) printf("\""); 2056*0Sstevel@tonic-gate needcomma++; 2057*0Sstevel@tonic-gate } else if (dashos) { 2058*0Sstevel@tonic-gate (void) printf(" -o "); 2059*0Sstevel@tonic-gate } 2060*0Sstevel@tonic-gate 2061*0Sstevel@tonic-gate #define NEXT_DASH_O dashos--; needcomma++; continue 2062*0Sstevel@tonic-gate 2063*0Sstevel@tonic-gate while (dashos) { 2064*0Sstevel@tonic-gate if (needcomma) { 2065*0Sstevel@tonic-gate (void) printf(","); 2066*0Sstevel@tonic-gate needcomma = 0; 2067*0Sstevel@tonic-gate } 2068*0Sstevel@tonic-gate if (prtfdisk) { 2069*0Sstevel@tonic-gate (void) printf("nofdisk"); 2070*0Sstevel@tonic-gate prtfdisk--; 2071*0Sstevel@tonic-gate NEXT_DASH_O; 2072*0Sstevel@tonic-gate } 2073*0Sstevel@tonic-gate if (prtsize) { 2074*0Sstevel@tonic-gate (void) printf("size=%u", wbpb->bpb.sectors_in_volume ? 2075*0Sstevel@tonic-gate wbpb->bpb.sectors_in_volume : 2076*0Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume); 2077*0Sstevel@tonic-gate prtsize--; 2078*0Sstevel@tonic-gate NEXT_DASH_O; 2079*0Sstevel@tonic-gate } 2080*0Sstevel@tonic-gate if (prtnsect) { 2081*0Sstevel@tonic-gate (void) printf("nsect=%d", wbpb->bpb.sectors_per_track); 2082*0Sstevel@tonic-gate prtnsect--; 2083*0Sstevel@tonic-gate NEXT_DASH_O; 2084*0Sstevel@tonic-gate } 2085*0Sstevel@tonic-gate if (prtspc) { 2086*0Sstevel@tonic-gate (void) printf("spc=%d", wbpb->bpb.sectors_per_cluster); 2087*0Sstevel@tonic-gate prtspc--; 2088*0Sstevel@tonic-gate NEXT_DASH_O; 2089*0Sstevel@tonic-gate } 2090*0Sstevel@tonic-gate if (prtntrk) { 2091*0Sstevel@tonic-gate (void) printf("ntrack=%d", wbpb->bpb.heads); 2092*0Sstevel@tonic-gate prtntrk--; 2093*0Sstevel@tonic-gate NEXT_DASH_O; 2094*0Sstevel@tonic-gate } 2095*0Sstevel@tonic-gate if (prtbpf) { 2096*0Sstevel@tonic-gate (void) printf("fat=%d", Fatentsize); 2097*0Sstevel@tonic-gate prtbpf--; 2098*0Sstevel@tonic-gate NEXT_DASH_O; 2099*0Sstevel@tonic-gate } 2100*0Sstevel@tonic-gate if (prthidden) { 2101*0Sstevel@tonic-gate (void) printf("hidden=%u", wbpb->bpb.hidden_sectors); 2102*0Sstevel@tonic-gate prthidden--; 2103*0Sstevel@tonic-gate NEXT_DASH_O; 2104*0Sstevel@tonic-gate } 2105*0Sstevel@tonic-gate if (prtrsrvd) { 2106*0Sstevel@tonic-gate (void) printf("reserve=%d", wbpb->bpb.resv_sectors); 2107*0Sstevel@tonic-gate prtrsrvd--; 2108*0Sstevel@tonic-gate NEXT_DASH_O; 2109*0Sstevel@tonic-gate } 2110*0Sstevel@tonic-gate } 2111*0Sstevel@tonic-gate 2112*0Sstevel@tonic-gate (void) printf(" %s%c%c\n", actualdisk, 2113*0Sstevel@tonic-gate suffix ? ':' : '\0', suffix ? *suffix : '\0'); 2114*0Sstevel@tonic-gate } 2115*0Sstevel@tonic-gate 2116*0Sstevel@tonic-gate /* 2117*0Sstevel@tonic-gate * open_and_examine 2118*0Sstevel@tonic-gate * 2119*0Sstevel@tonic-gate * Open the requested 'dev_name'. Seek to point where 2120*0Sstevel@tonic-gate * we'd expect to find boot sectors, etc., based on any ':partition' 2121*0Sstevel@tonic-gate * attachments to the dev_name. 2122*0Sstevel@tonic-gate * 2123*0Sstevel@tonic-gate * Examine the fields of any existing boot sector and display best 2124*0Sstevel@tonic-gate * approximation of how this fs could be reproduced with this command. 2125*0Sstevel@tonic-gate */ 2126*0Sstevel@tonic-gate static 2127*0Sstevel@tonic-gate int 2128*0Sstevel@tonic-gate open_and_examine(char *dn, bpb_t *wbpb) 2129*0Sstevel@tonic-gate { 2130*0Sstevel@tonic-gate struct stat di; 2131*0Sstevel@tonic-gate off64_t ignored; 2132*0Sstevel@tonic-gate char *actualdisk = NULL; 2133*0Sstevel@tonic-gate char *suffix = NULL; 2134*0Sstevel@tonic-gate int fd; 2135*0Sstevel@tonic-gate 2136*0Sstevel@tonic-gate if (Verbose) 2137*0Sstevel@tonic-gate (void) printf(gettext("Opening destination device/file.\n")); 2138*0Sstevel@tonic-gate 2139*0Sstevel@tonic-gate actualdisk = stat_actual_disk(dn, &di, &suffix); 2140*0Sstevel@tonic-gate 2141*0Sstevel@tonic-gate /* 2142*0Sstevel@tonic-gate * Destination exists, now find more about it. 2143*0Sstevel@tonic-gate */ 2144*0Sstevel@tonic-gate if (!(S_ISCHR(di.st_mode))) { 2145*0Sstevel@tonic-gate (void) fprintf(stderr, 2146*0Sstevel@tonic-gate gettext("\n%s: device name must be a " 2147*0Sstevel@tonic-gate "character special device.\n"), actualdisk); 2148*0Sstevel@tonic-gate exit(2); 2149*0Sstevel@tonic-gate } else if ((fd = open(actualdisk, O_RDWR | O_EXCL)) < 0) { 2150*0Sstevel@tonic-gate perror(actualdisk); 2151*0Sstevel@tonic-gate exit(2); 2152*0Sstevel@tonic-gate } 2153*0Sstevel@tonic-gate 2154*0Sstevel@tonic-gate /* 2155*0Sstevel@tonic-gate * Find appropriate partition if we were requested to do so. 2156*0Sstevel@tonic-gate */ 2157*0Sstevel@tonic-gate if (suffix && !(seek_partn(fd, suffix, wbpb, &ignored))) { 2158*0Sstevel@tonic-gate (void) close(fd); 2159*0Sstevel@tonic-gate exit(2); 2160*0Sstevel@tonic-gate } 2161*0Sstevel@tonic-gate 2162*0Sstevel@tonic-gate read_existing_bpb(fd, wbpb); 2163*0Sstevel@tonic-gate print_reproducing_command(fd, actualdisk, suffix, wbpb); 2164*0Sstevel@tonic-gate 2165*0Sstevel@tonic-gate return (fd); 2166*0Sstevel@tonic-gate } 2167*0Sstevel@tonic-gate 2168*0Sstevel@tonic-gate /* 2169*0Sstevel@tonic-gate * open_and_seek 2170*0Sstevel@tonic-gate * 2171*0Sstevel@tonic-gate * Open the requested 'dev_name'. Seek to point where 2172*0Sstevel@tonic-gate * we'll write boot sectors, etc., based on any ':partition' 2173*0Sstevel@tonic-gate * attachments to the dev_name. 2174*0Sstevel@tonic-gate * 2175*0Sstevel@tonic-gate * By the time we are finished here, the entire BPB will be 2176*0Sstevel@tonic-gate * filled in, excepting the volume label. 2177*0Sstevel@tonic-gate */ 2178*0Sstevel@tonic-gate static 2179*0Sstevel@tonic-gate int 2180*0Sstevel@tonic-gate open_and_seek(char *dn, bpb_t *wbpb, off64_t *seekto) 2181*0Sstevel@tonic-gate { 2182*0Sstevel@tonic-gate struct fd_char fdchar; 2183*0Sstevel@tonic-gate struct stat di; 2184*0Sstevel@tonic-gate char *actualdisk = NULL; 2185*0Sstevel@tonic-gate char *suffix = NULL; 2186*0Sstevel@tonic-gate int fd; 2187*0Sstevel@tonic-gate 2188*0Sstevel@tonic-gate if (Verbose) 2189*0Sstevel@tonic-gate (void) printf(gettext("Opening destination device/file.\n")); 2190*0Sstevel@tonic-gate 2191*0Sstevel@tonic-gate /* 2192*0Sstevel@tonic-gate * We hold these truths to be self evident, all BPBs we create 2193*0Sstevel@tonic-gate * will have these values in these fields. 2194*0Sstevel@tonic-gate */ 2195*0Sstevel@tonic-gate wbpb->bpb.num_fats = 2; 2196*0Sstevel@tonic-gate wbpb->bpb.bytes_sector = BPSEC; 2197*0Sstevel@tonic-gate 2198*0Sstevel@tonic-gate /* 2199*0Sstevel@tonic-gate * Assign or use supplied numbers for hidden and 2200*0Sstevel@tonic-gate * reserved sectors in the file system. 2201*0Sstevel@tonic-gate */ 2202*0Sstevel@tonic-gate if (GetResrvd) 2203*0Sstevel@tonic-gate if (MakeFAT32) 2204*0Sstevel@tonic-gate wbpb->bpb.resv_sectors = 32; 2205*0Sstevel@tonic-gate else 2206*0Sstevel@tonic-gate wbpb->bpb.resv_sectors = 1; 2207*0Sstevel@tonic-gate else 2208*0Sstevel@tonic-gate wbpb->bpb.resv_sectors = Resrvd; 2209*0Sstevel@tonic-gate 2210*0Sstevel@tonic-gate wbpb->ebpb.ext_signature = 0x29; /* Magic number for modern format */ 2211*0Sstevel@tonic-gate wbpb->ebpb.volume_id = 0; 2212*0Sstevel@tonic-gate 2213*0Sstevel@tonic-gate if (MakeFAT32) 2214*0Sstevel@tonic-gate fill_fat32_bpb(wbpb); 2215*0Sstevel@tonic-gate 2216*0Sstevel@tonic-gate /* 2217*0Sstevel@tonic-gate * If all output goes to a simple file, call a routine to setup 2218*0Sstevel@tonic-gate * that scenario. Otherwise, try to find the device. 2219*0Sstevel@tonic-gate */ 2220*0Sstevel@tonic-gate if (Outputtofile) 2221*0Sstevel@tonic-gate return (fd = prepare_image_file(dn, wbpb)); 2222*0Sstevel@tonic-gate 2223*0Sstevel@tonic-gate actualdisk = stat_actual_disk(dn, &di, &suffix); 2224*0Sstevel@tonic-gate 2225*0Sstevel@tonic-gate /* 2226*0Sstevel@tonic-gate * Sanity check. If we've been provided a partition-specifying 2227*0Sstevel@tonic-gate * suffix, we shouldn't also have been told to ignore the 2228*0Sstevel@tonic-gate * fdisk table. 2229*0Sstevel@tonic-gate */ 2230*0Sstevel@tonic-gate if (DontUseFdisk && suffix) { 2231*0Sstevel@tonic-gate (void) fprintf(stderr, 2232*0Sstevel@tonic-gate gettext("Using 'nofdisk' option precludes " 2233*0Sstevel@tonic-gate "appending logical drive\nspecifier " 2234*0Sstevel@tonic-gate "to the device name.\n")); 2235*0Sstevel@tonic-gate exit(2); 2236*0Sstevel@tonic-gate } 2237*0Sstevel@tonic-gate 2238*0Sstevel@tonic-gate /* 2239*0Sstevel@tonic-gate * Destination exists, now find more about it. 2240*0Sstevel@tonic-gate */ 2241*0Sstevel@tonic-gate if (!(S_ISCHR(di.st_mode))) { 2242*0Sstevel@tonic-gate (void) fprintf(stderr, 2243*0Sstevel@tonic-gate gettext("\n%s: device name must indicate a " 2244*0Sstevel@tonic-gate "character special device.\n"), actualdisk); 2245*0Sstevel@tonic-gate exit(2); 2246*0Sstevel@tonic-gate } else if ((fd = open(actualdisk, O_RDWR | O_EXCL)) < 0) { 2247*0Sstevel@tonic-gate perror(actualdisk); 2248*0Sstevel@tonic-gate exit(2); 2249*0Sstevel@tonic-gate } 2250*0Sstevel@tonic-gate 2251*0Sstevel@tonic-gate /* 2252*0Sstevel@tonic-gate * Find appropriate partition if we were requested to do so. 2253*0Sstevel@tonic-gate */ 2254*0Sstevel@tonic-gate if (suffix && !(seek_partn(fd, suffix, wbpb, seekto))) { 2255*0Sstevel@tonic-gate (void) close(fd); 2256*0Sstevel@tonic-gate exit(2); 2257*0Sstevel@tonic-gate } 2258*0Sstevel@tonic-gate 2259*0Sstevel@tonic-gate if (!suffix) { 2260*0Sstevel@tonic-gate /* 2261*0Sstevel@tonic-gate * We have one of two possibilities. Chances are we have 2262*0Sstevel@tonic-gate * a floppy drive. But the user may be trying to format 2263*0Sstevel@tonic-gate * some weird drive that we don't know about and is supplying 2264*0Sstevel@tonic-gate * all the important values. In that case, they should have set 2265*0Sstevel@tonic-gate * the 'nofdisk' flag. 2266*0Sstevel@tonic-gate * 2267*0Sstevel@tonic-gate * If 'nofdisk' isn't set, do a floppy-specific ioctl to 2268*0Sstevel@tonic-gate * get the remainder of our info. If the ioctl fails, we have 2269*0Sstevel@tonic-gate * a good idea that they aren't really on a floppy. In that 2270*0Sstevel@tonic-gate * case, they should have given us a partition specifier. 2271*0Sstevel@tonic-gate */ 2272*0Sstevel@tonic-gate if (DontUseFdisk) { 2273*0Sstevel@tonic-gate if (!(seek_nofdisk(fd, wbpb, seekto))) { 2274*0Sstevel@tonic-gate (void) close(fd); 2275*0Sstevel@tonic-gate exit(2); 2276*0Sstevel@tonic-gate } 2277*0Sstevel@tonic-gate find_fixed_details(fd, wbpb); 2278*0Sstevel@tonic-gate } else if (ioctl(fd, FDIOGCHAR, &fdchar) == -1) { 2279*0Sstevel@tonic-gate if (errno == ENOTTY) { 2280*0Sstevel@tonic-gate partn_lecture(actualdisk); 2281*0Sstevel@tonic-gate (void) close(fd); 2282*0Sstevel@tonic-gate exit(2); 2283*0Sstevel@tonic-gate } 2284*0Sstevel@tonic-gate } else { 2285*0Sstevel@tonic-gate #ifdef sparc 2286*0Sstevel@tonic-gate fdchar.fdc_medium = 3; 2287*0Sstevel@tonic-gate #endif 2288*0Sstevel@tonic-gate lookup_floppy(&fdchar, wbpb); 2289*0Sstevel@tonic-gate } 2290*0Sstevel@tonic-gate } else { 2291*0Sstevel@tonic-gate find_fixed_details(fd, wbpb); 2292*0Sstevel@tonic-gate } 2293*0Sstevel@tonic-gate 2294*0Sstevel@tonic-gate return (fd); 2295*0Sstevel@tonic-gate } 2296*0Sstevel@tonic-gate 2297*0Sstevel@tonic-gate /* 2298*0Sstevel@tonic-gate * The following is a copy of MS-DOS 4.0 boot block. 2299*0Sstevel@tonic-gate * It consists of the BIOS parameter block, and a disk 2300*0Sstevel@tonic-gate * bootstrap program. 2301*0Sstevel@tonic-gate * 2302*0Sstevel@tonic-gate * The BIOS parameter block contains the right values 2303*0Sstevel@tonic-gate * for the 3.5" high-density 1.44MB floppy format. 2304*0Sstevel@tonic-gate * 2305*0Sstevel@tonic-gate * This will be our default boot sector, if the user 2306*0Sstevel@tonic-gate * didn't point us at a different one. 2307*0Sstevel@tonic-gate * 2308*0Sstevel@tonic-gate */ 2309*0Sstevel@tonic-gate static 2310*0Sstevel@tonic-gate uchar_t DefBootSec[512] = { 2311*0Sstevel@tonic-gate 0xeb, 0x3c, 0x90, /* 8086 short jump + displacement + NOP */ 2312*0Sstevel@tonic-gate 'M', 'S', 'D', 'O', 'S', '4', '.', '0', /* OEM name & version */ 2313*0Sstevel@tonic-gate 0x00, 0x02, 0x01, 0x01, 0x00, 2314*0Sstevel@tonic-gate 0x02, 0xe0, 0x00, 0x40, 0x0b, 2315*0Sstevel@tonic-gate 0xf0, 0x09, 0x00, 0x12, 0x00, 2316*0Sstevel@tonic-gate 0x02, 0x00, 2317*0Sstevel@tonic-gate 0x00, 0x00, 0x00, 0x00, 2318*0Sstevel@tonic-gate 0x00, 0x00, 0x00, 0x00, 2319*0Sstevel@tonic-gate 0x00, 0x00, 2320*0Sstevel@tonic-gate 0x29, 0x00, 0x00, 0x00, 0x00, 2321*0Sstevel@tonic-gate 'N', 'O', 'N', 'A', 'M', 'E', ' ', ' ', ' ', ' ', ' ', 2322*0Sstevel@tonic-gate 'F', 'A', 'T', '1', '2', ' ', ' ', ' ', 2323*0Sstevel@tonic-gate 0xfa, 0x33, 2324*0Sstevel@tonic-gate 0xc0, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x16, 0x07, 2325*0Sstevel@tonic-gate 0xbb, 0x78, 0x00, 0x36, 0xc5, 0x37, 0x1e, 0x56, 2326*0Sstevel@tonic-gate 0x16, 0x53, 0xbf, 0x3e, 0x7c, 0xb9, 0x0b, 0x00, 2327*0Sstevel@tonic-gate 0xfc, 0xf3, 0xa4, 0x06, 0x1f, 0xc6, 0x45, 0xfe, 2328*0Sstevel@tonic-gate 0x0f, 0x8b, 0x0e, 0x18, 0x7c, 0x88, 0x4d, 0xf9, 2329*0Sstevel@tonic-gate 0x89, 0x47, 0x02, 0xc7, 0x07, 0x3e, 0x7c, 0xfb, 2330*0Sstevel@tonic-gate 0xcd, 0x13, 0x72, 0x7c, 0x33, 0xc0, 0x39, 0x06, 2331*0Sstevel@tonic-gate 0x13, 0x7c, 0x74, 0x08, 0x8b, 0x0e, 0x13, 0x7c, 2332*0Sstevel@tonic-gate 0x89, 0x0e, 0x20, 0x7c, 0xa0, 0x10, 0x7c, 0xf7, 2333*0Sstevel@tonic-gate 0x26, 0x16, 0x7c, 0x03, 0x06, 0x1c, 0x7c, 0x13, 2334*0Sstevel@tonic-gate 0x16, 0x1e, 0x7c, 0x03, 0x06, 0x0e, 0x7c, 0x83, 2335*0Sstevel@tonic-gate 0xd2, 0x00, 0xa3, 0x50, 0x7c, 0x89, 0x16, 0x52, 2336*0Sstevel@tonic-gate 0x7c, 0xa3, 0x49, 0x7c, 0x89, 0x16, 0x4b, 0x7c, 2337*0Sstevel@tonic-gate 0xb8, 0x20, 0x00, 0xf7, 0x26, 0x11, 0x7c, 0x8b, 2338*0Sstevel@tonic-gate 0x1e, 0x0b, 0x7c, 0x03, 0xc3, 0x48, 0xf7, 0xf3, 2339*0Sstevel@tonic-gate 0x01, 0x06, 0x49, 0x7c, 0x83, 0x16, 0x4b, 0x7c, 2340*0Sstevel@tonic-gate 0x00, 0xbb, 0x00, 0x05, 0x8b, 0x16, 0x52, 0x7c, 2341*0Sstevel@tonic-gate 0xa1, 0x50, 0x7c, 0xe8, 0x87, 0x00, 0x72, 0x20, 2342*0Sstevel@tonic-gate 0xb0, 0x01, 0xe8, 0xa1, 0x00, 0x72, 0x19, 0x8b, 2343*0Sstevel@tonic-gate 0xfb, 0xb9, 0x0b, 0x00, 0xbe, 0xdb, 0x7d, 0xf3, 2344*0Sstevel@tonic-gate 0xa6, 0x75, 0x0d, 0x8d, 0x7f, 0x20, 0xbe, 0xe6, 2345*0Sstevel@tonic-gate 0x7d, 0xb9, 0x0b, 0x00, 0xf3, 0xa6, 0x74, 0x18, 2346*0Sstevel@tonic-gate 0xbe, 0x93, 0x7d, 0xe8, 0x51, 0x00, 0x32, 0xe4, 2347*0Sstevel@tonic-gate 0xcd, 0x16, 0x5e, 0x1f, 0x8f, 0x04, 0x8f, 0x44, 2348*0Sstevel@tonic-gate 0x02, 0xcd, 0x19, 0x58, 0x58, 0x58, 0xeb, 0xe8, 2349*0Sstevel@tonic-gate 0xbb, 0x00, 0x07, 0xb9, 0x03, 0x00, 0xa1, 0x49, 2350*0Sstevel@tonic-gate 0x7c, 0x8b, 0x16, 0x4b, 0x7c, 0x50, 0x52, 0x51, 2351*0Sstevel@tonic-gate 0xe8, 0x3a, 0x00, 0x72, 0xe6, 0xb0, 0x01, 0xe8, 2352*0Sstevel@tonic-gate 0x54, 0x00, 0x59, 0x5a, 0x58, 0x72, 0xc9, 0x05, 2353*0Sstevel@tonic-gate 0x01, 0x00, 0x83, 0xd2, 0x00, 0x03, 0x1e, 0x0b, 2354*0Sstevel@tonic-gate 0x7c, 0xe2, 0xe2, 0x8a, 0x2e, 0x15, 0x7c, 0x8a, 2355*0Sstevel@tonic-gate 0x16, 0x24, 0x7c, 0x8b, 0x1e, 0x49, 0x7c, 0xa1, 2356*0Sstevel@tonic-gate 0x4b, 0x7c, 0xea, 0x00, 0x00, 0x70, 0x00, 0xac, 2357*0Sstevel@tonic-gate 0x0a, 0xc0, 0x74, 0x29, 0xb4, 0x0e, 0xbb, 0x07, 2358*0Sstevel@tonic-gate 0x00, 0xcd, 0x10, 0xeb, 0xf2, 0x3b, 0x16, 0x18, 2359*0Sstevel@tonic-gate 0x7c, 0x73, 0x19, 0xf7, 0x36, 0x18, 0x7c, 0xfe, 2360*0Sstevel@tonic-gate 0xc2, 0x88, 0x16, 0x4f, 0x7c, 0x33, 0xd2, 0xf7, 2361*0Sstevel@tonic-gate 0x36, 0x1a, 0x7c, 0x88, 0x16, 0x25, 0x7c, 0xa3, 2362*0Sstevel@tonic-gate 0x4d, 0x7c, 0xf8, 0xc3, 0xf9, 0xc3, 0xb4, 0x02, 2363*0Sstevel@tonic-gate 0x8b, 0x16, 0x4d, 0x7c, 0xb1, 0x06, 0xd2, 0xe6, 2364*0Sstevel@tonic-gate 0x0a, 0x36, 0x4f, 0x7c, 0x8b, 0xca, 0x86, 0xe9, 2365*0Sstevel@tonic-gate 0x8a, 0x16, 0x24, 0x7c, 0x8a, 0x36, 0x25, 0x7c, 2366*0Sstevel@tonic-gate 0xcd, 0x13, 0xc3, 0x0d, 0x0a, 0x4e, 0x6f, 0x6e, 2367*0Sstevel@tonic-gate 0x2d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 2368*0Sstevel@tonic-gate 0x64, 0x69, 0x73, 0x6b, 0x20, 0x6f, 0x72, 0x20, 2369*0Sstevel@tonic-gate 0x64, 0x69, 0x73, 0x6b, 0x20, 0x65, 0x72, 0x72, 2370*0Sstevel@tonic-gate 0x6f, 0x72, 0x0d, 0x0a, 0x52, 0x65, 0x70, 0x6c, 2371*0Sstevel@tonic-gate 0x61, 0x63, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 2372*0Sstevel@tonic-gate 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6e, 2373*0Sstevel@tonic-gate 0x79, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x77, 0x68, 2374*0Sstevel@tonic-gate 0x65, 0x6e, 0x20, 0x72, 0x65, 0x61, 0x64, 0x79, 2375*0Sstevel@tonic-gate 0x0d, 0x0a, 0x00, 0x49, 0x4f, 0x20, 0x20, 0x20, 2376*0Sstevel@tonic-gate 0x20, 0x20, 0x20, 0x53, 0x59, 0x53, 0x4d, 0x53, 2377*0Sstevel@tonic-gate 0x44, 0x4f, 0x53, 0x20, 0x20, 0x20, 0x53, 0x59, 2378*0Sstevel@tonic-gate 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2379*0Sstevel@tonic-gate 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa 2380*0Sstevel@tonic-gate }; 2381*0Sstevel@tonic-gate 2382*0Sstevel@tonic-gate /* 2383*0Sstevel@tonic-gate * verify_bootblkfile 2384*0Sstevel@tonic-gate * 2385*0Sstevel@tonic-gate * We were provided with the name of a file containing the bootblk 2386*0Sstevel@tonic-gate * to install. Verify it has a valid boot sector as best we can. Any 2387*0Sstevel@tonic-gate * errors and we return a bad file descriptor. Otherwise we fill up the 2388*0Sstevel@tonic-gate * provided buffer with the boot sector, return the file 2389*0Sstevel@tonic-gate * descriptor for later use and leave the file pointer just 2390*0Sstevel@tonic-gate * past the boot sector part of the boot block file. 2391*0Sstevel@tonic-gate */ 2392*0Sstevel@tonic-gate static 2393*0Sstevel@tonic-gate int 2394*0Sstevel@tonic-gate verify_bootblkfile(char *fn, boot_sector_t *bs, ulong_t *blkfilesize) 2395*0Sstevel@tonic-gate { 2396*0Sstevel@tonic-gate struct stat fi; 2397*0Sstevel@tonic-gate int bsfd = -1; 2398*0Sstevel@tonic-gate 2399*0Sstevel@tonic-gate if (stat(fn, &fi)) { 2400*0Sstevel@tonic-gate perror(fn); 2401*0Sstevel@tonic-gate } else if (fi.st_size < BPSEC) { 2402*0Sstevel@tonic-gate (void) fprintf(stderr, 2403*0Sstevel@tonic-gate gettext("%s: Too short to be a boot sector.\n"), fn); 2404*0Sstevel@tonic-gate } else if ((bsfd = open(fn, O_RDONLY)) < 0) { 2405*0Sstevel@tonic-gate perror(fn); 2406*0Sstevel@tonic-gate } else if (read(bsfd, bs->buf, BPSEC) < BPSEC) { 2407*0Sstevel@tonic-gate (void) close(bsfd); 2408*0Sstevel@tonic-gate bsfd = -1; 2409*0Sstevel@tonic-gate perror(gettext("Boot block read")); 2410*0Sstevel@tonic-gate } else { 2411*0Sstevel@tonic-gate #ifdef i386 2412*0Sstevel@tonic-gate if ((bs->bs.bs_front.bs_jump_code[0] != OPCODE1 && 2413*0Sstevel@tonic-gate bs->bs.bs_front.bs_jump_code[0] != OPCODE2) || 2414*0Sstevel@tonic-gate #else 2415*0Sstevel@tonic-gate if ((bs->bs.bs_jump_code[0] != OPCODE1 && 2416*0Sstevel@tonic-gate bs->bs.bs_jump_code[0] != OPCODE2) || 2417*0Sstevel@tonic-gate #endif 2418*0Sstevel@tonic-gate (bs->bs.bs_signature[0] != (BOOTSECSIG & 0xFF) && 2419*0Sstevel@tonic-gate bs->bs.bs_signature[1] != ((BOOTSECSIG >> 8) & 0xFF))) { 2420*0Sstevel@tonic-gate (void) close(bsfd); 2421*0Sstevel@tonic-gate bsfd = -1; 2422*0Sstevel@tonic-gate (void) fprintf(stderr, 2423*0Sstevel@tonic-gate gettext("Boot block (%s) bogus.\n"), fn); 2424*0Sstevel@tonic-gate } 2425*0Sstevel@tonic-gate *blkfilesize = fi.st_size; 2426*0Sstevel@tonic-gate } 2427*0Sstevel@tonic-gate return (bsfd); 2428*0Sstevel@tonic-gate } 2429*0Sstevel@tonic-gate 2430*0Sstevel@tonic-gate /* 2431*0Sstevel@tonic-gate * verify_firstfile 2432*0Sstevel@tonic-gate * 2433*0Sstevel@tonic-gate * We were provided with the name of a file to be the first file 2434*0Sstevel@tonic-gate * installed on the disk. We just need to verify it exists and 2435*0Sstevel@tonic-gate * find out how big it is. If it doesn't exist, we print a warning 2436*0Sstevel@tonic-gate * message about how the file wasn't found. We don't exit fatally, 2437*0Sstevel@tonic-gate * though, rather we return a size of 0 and the FAT will be built 2438*0Sstevel@tonic-gate * without installing any first file. They can then presumably 2439*0Sstevel@tonic-gate * install the correct first file by hand. 2440*0Sstevel@tonic-gate */ 2441*0Sstevel@tonic-gate static 2442*0Sstevel@tonic-gate int 2443*0Sstevel@tonic-gate verify_firstfile(char *fn, ulong_t *filesize) 2444*0Sstevel@tonic-gate { 2445*0Sstevel@tonic-gate struct stat fi; 2446*0Sstevel@tonic-gate int fd = -1; 2447*0Sstevel@tonic-gate 2448*0Sstevel@tonic-gate *filesize = 0; 2449*0Sstevel@tonic-gate if (stat(fn, &fi) || (fd = open(fn, O_RDONLY)) < 0) { 2450*0Sstevel@tonic-gate perror(fn); 2451*0Sstevel@tonic-gate (void) fprintf(stderr, 2452*0Sstevel@tonic-gate gettext("Could not access requested file. It will not\n" 2453*0Sstevel@tonic-gate "be installed in the new file system.\n")); 2454*0Sstevel@tonic-gate } else { 2455*0Sstevel@tonic-gate *filesize = fi.st_size; 2456*0Sstevel@tonic-gate } 2457*0Sstevel@tonic-gate 2458*0Sstevel@tonic-gate return (fd); 2459*0Sstevel@tonic-gate } 2460*0Sstevel@tonic-gate 2461*0Sstevel@tonic-gate /* 2462*0Sstevel@tonic-gate * label_volume 2463*0Sstevel@tonic-gate * 2464*0Sstevel@tonic-gate * Fill in BPB with volume label. 2465*0Sstevel@tonic-gate */ 2466*0Sstevel@tonic-gate static 2467*0Sstevel@tonic-gate void 2468*0Sstevel@tonic-gate label_volume(char *lbl, bpb_t *wbpb) 2469*0Sstevel@tonic-gate { 2470*0Sstevel@tonic-gate int ll, i; 2471*0Sstevel@tonic-gate 2472*0Sstevel@tonic-gate /* Put a volume label into our BPB. */ 2473*0Sstevel@tonic-gate if (!lbl) 2474*0Sstevel@tonic-gate lbl = DEFAULT_LABEL; 2475*0Sstevel@tonic-gate 2476*0Sstevel@tonic-gate ll = min(11, (int)strlen(lbl)); 2477*0Sstevel@tonic-gate for (i = 0; i < ll; i++) { 2478*0Sstevel@tonic-gate wbpb->ebpb.volume_label[i] = toupper(lbl[i]); 2479*0Sstevel@tonic-gate } 2480*0Sstevel@tonic-gate for (; i < 11; i++) { 2481*0Sstevel@tonic-gate wbpb->ebpb.volume_label[i] = ' '; 2482*0Sstevel@tonic-gate } 2483*0Sstevel@tonic-gate } 2484*0Sstevel@tonic-gate 2485*0Sstevel@tonic-gate static 2486*0Sstevel@tonic-gate int 2487*0Sstevel@tonic-gate copy_bootblk(char *fn, boot_sector_t *bootsect, ulong_t *bootblksize) 2488*0Sstevel@tonic-gate { 2489*0Sstevel@tonic-gate int bsfd = -1; 2490*0Sstevel@tonic-gate 2491*0Sstevel@tonic-gate if (Verbose && fn) 2492*0Sstevel@tonic-gate (void) printf(gettext("Request to install boot " 2493*0Sstevel@tonic-gate "block file %s.\n"), fn); 2494*0Sstevel@tonic-gate else if (Verbose) 2495*0Sstevel@tonic-gate (void) printf(gettext("Request to install DOS boot block.\n")); 2496*0Sstevel@tonic-gate 2497*0Sstevel@tonic-gate /* 2498*0Sstevel@tonic-gate * If they want to install their own boot block, sanity check 2499*0Sstevel@tonic-gate * that block. 2500*0Sstevel@tonic-gate */ 2501*0Sstevel@tonic-gate if (fn) { 2502*0Sstevel@tonic-gate bsfd = verify_bootblkfile(fn, bootsect, bootblksize); 2503*0Sstevel@tonic-gate if (bsfd < 0) { 2504*0Sstevel@tonic-gate exit(3); 2505*0Sstevel@tonic-gate } 2506*0Sstevel@tonic-gate *bootblksize = roundup(*bootblksize, BPSEC); 2507*0Sstevel@tonic-gate } else { 2508*0Sstevel@tonic-gate (void) memcpy(bootsect, DefBootSec, BPSEC); 2509*0Sstevel@tonic-gate *bootblksize = BPSEC; 2510*0Sstevel@tonic-gate } 2511*0Sstevel@tonic-gate 2512*0Sstevel@tonic-gate return (bsfd); 2513*0Sstevel@tonic-gate } 2514*0Sstevel@tonic-gate 2515*0Sstevel@tonic-gate /* 2516*0Sstevel@tonic-gate * mark_cluster 2517*0Sstevel@tonic-gate * 2518*0Sstevel@tonic-gate * This routine fills a FAT entry with the value supplied to it as an 2519*0Sstevel@tonic-gate * argument. The fatp argument is assumed to be a pointer to the FAT's 2520*0Sstevel@tonic-gate * 0th entry. The clustnum is the cluster entry that should be updated. 2521*0Sstevel@tonic-gate * The value is the new value for the entry. 2522*0Sstevel@tonic-gate */ 2523*0Sstevel@tonic-gate static 2524*0Sstevel@tonic-gate void 2525*0Sstevel@tonic-gate mark_cluster(uchar_t *fatp, pc_cluster32_t clustnum, uint32_t value) 2526*0Sstevel@tonic-gate { 2527*0Sstevel@tonic-gate uchar_t *ep; 2528*0Sstevel@tonic-gate ulong_t idx; 2529*0Sstevel@tonic-gate 2530*0Sstevel@tonic-gate idx = (Fatentsize == 32) ? clustnum * 4 : 2531*0Sstevel@tonic-gate (Fatentsize == 16) ? clustnum * 2 : clustnum + clustnum/2; 2532*0Sstevel@tonic-gate ep = fatp + idx; 2533*0Sstevel@tonic-gate 2534*0Sstevel@tonic-gate if (Fatentsize == 32) { 2535*0Sstevel@tonic-gate store_32_bits(&ep, value); 2536*0Sstevel@tonic-gate } else if (Fatentsize == 16) { 2537*0Sstevel@tonic-gate store_16_bits(&ep, value); 2538*0Sstevel@tonic-gate } else { 2539*0Sstevel@tonic-gate if (clustnum & 1) { 2540*0Sstevel@tonic-gate *ep = (*ep & 0x0f) | ((value << 4) & 0xf0); 2541*0Sstevel@tonic-gate ep++; 2542*0Sstevel@tonic-gate *ep = (value >> 4) & 0xff; 2543*0Sstevel@tonic-gate } else { 2544*0Sstevel@tonic-gate *ep++ = value & 0xff; 2545*0Sstevel@tonic-gate *ep = (*ep & 0xf0) | ((value >> 8) & 0x0f); 2546*0Sstevel@tonic-gate } 2547*0Sstevel@tonic-gate } 2548*0Sstevel@tonic-gate } 2549*0Sstevel@tonic-gate 2550*0Sstevel@tonic-gate static 2551*0Sstevel@tonic-gate uchar_t * 2552*0Sstevel@tonic-gate build_fat(bpb_t *wbpb, struct fat32_boot_fsinfo *fsinfop, ulong_t bootblksize, 2553*0Sstevel@tonic-gate ulong_t *fatsize, char *ffn, int *fffd, ulong_t *ffsize, 2554*0Sstevel@tonic-gate pc_cluster32_t *ffstartclust) 2555*0Sstevel@tonic-gate { 2556*0Sstevel@tonic-gate pc_cluster32_t nextfree, ci; 2557*0Sstevel@tonic-gate uchar_t *fatp; 2558*0Sstevel@tonic-gate ushort_t numclust, numsect; 2559*0Sstevel@tonic-gate int remclust; 2560*0Sstevel@tonic-gate 2561*0Sstevel@tonic-gate /* Alloc space for a FAT and then null it out. */ 2562*0Sstevel@tonic-gate if (Verbose) { 2563*0Sstevel@tonic-gate (void) printf(gettext("BUILD FAT.\n%d sectors per fat.\n"), 2564*0Sstevel@tonic-gate wbpb->bpb.sectors_per_fat ? wbpb->bpb.sectors_per_fat : 2565*0Sstevel@tonic-gate wbpb->bpb32.big_sectors_per_fat); 2566*0Sstevel@tonic-gate } 2567*0Sstevel@tonic-gate 2568*0Sstevel@tonic-gate if (MakeFAT32) { 2569*0Sstevel@tonic-gate *fatsize = BPSEC * wbpb->bpb32.big_sectors_per_fat; 2570*0Sstevel@tonic-gate } else { 2571*0Sstevel@tonic-gate *fatsize = BPSEC * wbpb->bpb.sectors_per_fat; 2572*0Sstevel@tonic-gate } 2573*0Sstevel@tonic-gate if (!(fatp = (uchar_t *)malloc(*fatsize))) { 2574*0Sstevel@tonic-gate perror(gettext("FAT table alloc")); 2575*0Sstevel@tonic-gate exit(4); 2576*0Sstevel@tonic-gate } else { 2577*0Sstevel@tonic-gate (void) memset(fatp, 0, *fatsize); 2578*0Sstevel@tonic-gate } 2579*0Sstevel@tonic-gate 2580*0Sstevel@tonic-gate /* Build in-memory FAT */ 2581*0Sstevel@tonic-gate *fatp = wbpb->bpb.media; 2582*0Sstevel@tonic-gate *(fatp + 1) = 0xFF; 2583*0Sstevel@tonic-gate *(fatp + 2) = 0xFF; 2584*0Sstevel@tonic-gate 2585*0Sstevel@tonic-gate if (Fatentsize == 16) { 2586*0Sstevel@tonic-gate *(fatp + 3) = 0xFF; 2587*0Sstevel@tonic-gate } else if (Fatentsize == 32) { 2588*0Sstevel@tonic-gate *(fatp + 3) = 0x0F; 2589*0Sstevel@tonic-gate *(fatp + 4) = 0xFF; 2590*0Sstevel@tonic-gate *(fatp + 5) = 0xFF; 2591*0Sstevel@tonic-gate *(fatp + 6) = 0xFF; 2592*0Sstevel@tonic-gate *(fatp + 7) = 0x0F; 2593*0Sstevel@tonic-gate } 2594*0Sstevel@tonic-gate 2595*0Sstevel@tonic-gate /* 2596*0Sstevel@tonic-gate * Keep track of clusters used. 2597*0Sstevel@tonic-gate */ 2598*0Sstevel@tonic-gate remclust = TotalClusters; 2599*0Sstevel@tonic-gate nextfree = 2; 2600*0Sstevel@tonic-gate 2601*0Sstevel@tonic-gate /* 2602*0Sstevel@tonic-gate * Get info on first file to install, if any. 2603*0Sstevel@tonic-gate */ 2604*0Sstevel@tonic-gate if (ffn) 2605*0Sstevel@tonic-gate *fffd = verify_firstfile(ffn, ffsize); 2606*0Sstevel@tonic-gate 2607*0Sstevel@tonic-gate /* 2608*0Sstevel@tonic-gate * Compute number of clusters to preserve for bootblk overage. 2609*0Sstevel@tonic-gate * Remember that we already wrote the first sector of the boot block. 2610*0Sstevel@tonic-gate * These clusters are marked BAD to prevent them from being deleted 2611*0Sstevel@tonic-gate * or used. The first available cluster is 2, so we always offset 2612*0Sstevel@tonic-gate * the clusters. 2613*0Sstevel@tonic-gate */ 2614*0Sstevel@tonic-gate numsect = idivceil((bootblksize - BPSEC), BPSEC); 2615*0Sstevel@tonic-gate numclust = idivceil(numsect, wbpb->bpb.sectors_per_cluster); 2616*0Sstevel@tonic-gate 2617*0Sstevel@tonic-gate if (Verbose && numclust) 2618*0Sstevel@tonic-gate (void) printf(gettext("Hiding %d excess bootblk cluster(s).\n"), 2619*0Sstevel@tonic-gate numclust); 2620*0Sstevel@tonic-gate for (ci = 0; ci < numclust; ci++) 2621*0Sstevel@tonic-gate mark_cluster(fatp, nextfree++, 2622*0Sstevel@tonic-gate MakeFAT32 ? PCF_BADCLUSTER32 : PCF_BADCLUSTER); 2623*0Sstevel@tonic-gate remclust -= numclust; 2624*0Sstevel@tonic-gate 2625*0Sstevel@tonic-gate /* 2626*0Sstevel@tonic-gate * Reserve a cluster for the root directory on a FAT32. 2627*0Sstevel@tonic-gate */ 2628*0Sstevel@tonic-gate if (MakeFAT32) { 2629*0Sstevel@tonic-gate mark_cluster(fatp, nextfree, PCF_LASTCLUSTER32); 2630*0Sstevel@tonic-gate wbpb->bpb32.root_dir_clust = nextfree++; 2631*0Sstevel@tonic-gate remclust--; 2632*0Sstevel@tonic-gate } 2633*0Sstevel@tonic-gate 2634*0Sstevel@tonic-gate /* 2635*0Sstevel@tonic-gate * Compute and preserve number of clusters for first file. 2636*0Sstevel@tonic-gate */ 2637*0Sstevel@tonic-gate if (*fffd >= 0) { 2638*0Sstevel@tonic-gate *ffstartclust = nextfree; 2639*0Sstevel@tonic-gate numsect = idivceil(*ffsize, BPSEC); 2640*0Sstevel@tonic-gate numclust = idivceil(numsect, wbpb->bpb.sectors_per_cluster); 2641*0Sstevel@tonic-gate 2642*0Sstevel@tonic-gate if (numclust > remclust) { 2643*0Sstevel@tonic-gate (void) fprintf(stderr, 2644*0Sstevel@tonic-gate gettext("Requested first file too large to be\n" 2645*0Sstevel@tonic-gate "installed in the new file system.\n")); 2646*0Sstevel@tonic-gate (void) close(*fffd); 2647*0Sstevel@tonic-gate *fffd = -1; 2648*0Sstevel@tonic-gate goto finish; 2649*0Sstevel@tonic-gate } 2650*0Sstevel@tonic-gate 2651*0Sstevel@tonic-gate if (Verbose) 2652*0Sstevel@tonic-gate (void) printf(gettext("Reserving %d first file " 2653*0Sstevel@tonic-gate "cluster(s).\n"), numclust); 2654*0Sstevel@tonic-gate for (ci = 0; (int)ci < (int)(numclust-1); ci++, nextfree++) 2655*0Sstevel@tonic-gate mark_cluster(fatp, nextfree, nextfree + 1); 2656*0Sstevel@tonic-gate mark_cluster(fatp, nextfree++, 2657*0Sstevel@tonic-gate MakeFAT32 ? PCF_LASTCLUSTER32 : PCF_LASTCLUSTER); 2658*0Sstevel@tonic-gate remclust -= numclust; 2659*0Sstevel@tonic-gate } 2660*0Sstevel@tonic-gate 2661*0Sstevel@tonic-gate finish: 2662*0Sstevel@tonic-gate if (Verbose) { 2663*0Sstevel@tonic-gate (void) printf(gettext("First sector of FAT")); 2664*0Sstevel@tonic-gate header_for_dump(); 2665*0Sstevel@tonic-gate dump_bytes(fatp, BPSEC); 2666*0Sstevel@tonic-gate } 2667*0Sstevel@tonic-gate 2668*0Sstevel@tonic-gate fsinfop->fs_signature = FAT32_FS_SIGN; 2669*0Sstevel@tonic-gate fsinfop->fs_free_clusters = remclust; 2670*0Sstevel@tonic-gate fsinfop->fs_next_cluster = nextfree; 2671*0Sstevel@tonic-gate return (fatp); 2672*0Sstevel@tonic-gate } 2673*0Sstevel@tonic-gate 2674*0Sstevel@tonic-gate static 2675*0Sstevel@tonic-gate void 2676*0Sstevel@tonic-gate dirent_time_fill(struct pcdir *dep) 2677*0Sstevel@tonic-gate { 2678*0Sstevel@tonic-gate struct timeval tv; 2679*0Sstevel@tonic-gate struct tm *tp; 2680*0Sstevel@tonic-gate ushort_t dostime; 2681*0Sstevel@tonic-gate ushort_t dosday; 2682*0Sstevel@tonic-gate 2683*0Sstevel@tonic-gate (void) gettimeofday(&tv, (struct timezone *)0); 2684*0Sstevel@tonic-gate tp = localtime(&tv.tv_sec); 2685*0Sstevel@tonic-gate /* get the time & day into DOS format */ 2686*0Sstevel@tonic-gate dostime = tp->tm_sec / 2; 2687*0Sstevel@tonic-gate dostime |= tp->tm_min << 5; 2688*0Sstevel@tonic-gate dostime |= tp->tm_hour << 11; 2689*0Sstevel@tonic-gate dosday = tp->tm_mday; 2690*0Sstevel@tonic-gate dosday |= (tp->tm_mon + 1) << 5; 2691*0Sstevel@tonic-gate dosday |= (tp->tm_year - 80) << 9; 2692*0Sstevel@tonic-gate dep->pcd_mtime.pct_time = htols(dostime); 2693*0Sstevel@tonic-gate dep->pcd_mtime.pct_date = htols(dosday); 2694*0Sstevel@tonic-gate } 2695*0Sstevel@tonic-gate 2696*0Sstevel@tonic-gate static 2697*0Sstevel@tonic-gate void 2698*0Sstevel@tonic-gate dirent_label_fill(struct pcdir *dep, char *fn) 2699*0Sstevel@tonic-gate { 2700*0Sstevel@tonic-gate int nl, i; 2701*0Sstevel@tonic-gate 2702*0Sstevel@tonic-gate /* 2703*0Sstevel@tonic-gate * We spread the volume label across both the NAME and EXT fields 2704*0Sstevel@tonic-gate */ 2705*0Sstevel@tonic-gate nl = min(PCFNAMESIZE, strlen(fn)); 2706*0Sstevel@tonic-gate for (i = 0; i < nl; i++) { 2707*0Sstevel@tonic-gate dep->pcd_filename[i] = toupper(fn[i]); 2708*0Sstevel@tonic-gate } 2709*0Sstevel@tonic-gate if (i < PCFNAMESIZE) { 2710*0Sstevel@tonic-gate for (; i < PCFNAMESIZE; i++) 2711*0Sstevel@tonic-gate dep->pcd_filename[i] = ' '; 2712*0Sstevel@tonic-gate for (i = 0; i < PCFEXTSIZE; i++) 2713*0Sstevel@tonic-gate dep->pcd_ext[i] = ' '; 2714*0Sstevel@tonic-gate return; 2715*0Sstevel@tonic-gate } 2716*0Sstevel@tonic-gate nl = min(PCFEXTSIZE, strlen(fn) - PCFNAMESIZE); 2717*0Sstevel@tonic-gate for (i = 0; i < nl; i++) 2718*0Sstevel@tonic-gate dep->pcd_ext[i] = toupper(fn[i + PCFNAMESIZE]); 2719*0Sstevel@tonic-gate if (i < PCFEXTSIZE) { 2720*0Sstevel@tonic-gate for (; i < PCFEXTSIZE; i++) 2721*0Sstevel@tonic-gate dep->pcd_ext[i] = ' '; 2722*0Sstevel@tonic-gate } 2723*0Sstevel@tonic-gate } 2724*0Sstevel@tonic-gate 2725*0Sstevel@tonic-gate static 2726*0Sstevel@tonic-gate void 2727*0Sstevel@tonic-gate dirent_fname_fill(struct pcdir *dep, char *fn) 2728*0Sstevel@tonic-gate { 2729*0Sstevel@tonic-gate char *fname, *fext; 2730*0Sstevel@tonic-gate int nl, i; 2731*0Sstevel@tonic-gate 2732*0Sstevel@tonic-gate if (fname = strrchr(fn, '/')) { 2733*0Sstevel@tonic-gate fname++; 2734*0Sstevel@tonic-gate } else { 2735*0Sstevel@tonic-gate fname = fn; 2736*0Sstevel@tonic-gate } 2737*0Sstevel@tonic-gate 2738*0Sstevel@tonic-gate if (fext = strrchr(fname, '.')) { 2739*0Sstevel@tonic-gate fext++; 2740*0Sstevel@tonic-gate } else { 2741*0Sstevel@tonic-gate fext = ""; 2742*0Sstevel@tonic-gate } 2743*0Sstevel@tonic-gate 2744*0Sstevel@tonic-gate fname = strtok(fname, "."); 2745*0Sstevel@tonic-gate 2746*0Sstevel@tonic-gate nl = min(PCFNAMESIZE, (int)strlen(fname)); 2747*0Sstevel@tonic-gate for (i = 0; i < nl; i++) { 2748*0Sstevel@tonic-gate dep->pcd_filename[i] = toupper(fname[i]); 2749*0Sstevel@tonic-gate } 2750*0Sstevel@tonic-gate for (; i < PCFNAMESIZE; i++) { 2751*0Sstevel@tonic-gate dep->pcd_filename[i] = ' '; 2752*0Sstevel@tonic-gate } 2753*0Sstevel@tonic-gate 2754*0Sstevel@tonic-gate nl = min(PCFEXTSIZE, (int)strlen(fext)); 2755*0Sstevel@tonic-gate for (i = 0; i < nl; i++) { 2756*0Sstevel@tonic-gate dep->pcd_ext[i] = toupper(fext[i]); 2757*0Sstevel@tonic-gate } 2758*0Sstevel@tonic-gate for (; i < PCFEXTSIZE; i++) { 2759*0Sstevel@tonic-gate dep->pcd_ext[i] = ' '; 2760*0Sstevel@tonic-gate } 2761*0Sstevel@tonic-gate } 2762*0Sstevel@tonic-gate 2763*0Sstevel@tonic-gate static 2764*0Sstevel@tonic-gate uchar_t * 2765*0Sstevel@tonic-gate build_rootdir(bpb_t *wbpb, char *ffn, int fffd, 2766*0Sstevel@tonic-gate ulong_t ffsize, pc_cluster32_t ffstart, ulong_t *rdirsize) 2767*0Sstevel@tonic-gate { 2768*0Sstevel@tonic-gate struct pcdir *rootdirp; 2769*0Sstevel@tonic-gate struct pcdir *entry; 2770*0Sstevel@tonic-gate 2771*0Sstevel@tonic-gate /* 2772*0Sstevel@tonic-gate * Build a root directory. It will have at least one entry, 2773*0Sstevel@tonic-gate * the volume label and a second if the first file was defined. 2774*0Sstevel@tonic-gate */ 2775*0Sstevel@tonic-gate if (MakeFAT32) { 2776*0Sstevel@tonic-gate /* 2777*0Sstevel@tonic-gate * We devote an entire cluster to the root 2778*0Sstevel@tonic-gate * directory on FAT32. 2779*0Sstevel@tonic-gate */ 2780*0Sstevel@tonic-gate *rdirsize = wbpb->bpb.sectors_per_cluster * BPSEC; 2781*0Sstevel@tonic-gate } else { 2782*0Sstevel@tonic-gate *rdirsize = wbpb->bpb.num_root_entries * sizeof (struct pcdir); 2783*0Sstevel@tonic-gate } 2784*0Sstevel@tonic-gate if ((rootdirp = (struct pcdir *)malloc(*rdirsize)) == NULL) { 2785*0Sstevel@tonic-gate perror(gettext("Root directory allocation")); 2786*0Sstevel@tonic-gate exit(4); 2787*0Sstevel@tonic-gate } else { 2788*0Sstevel@tonic-gate entry = rootdirp; 2789*0Sstevel@tonic-gate (void) memset((char *)rootdirp, 0, *rdirsize); 2790*0Sstevel@tonic-gate } 2791*0Sstevel@tonic-gate 2792*0Sstevel@tonic-gate /* Create directory entry for first file, if there is one */ 2793*0Sstevel@tonic-gate if (fffd >= 0) { 2794*0Sstevel@tonic-gate dirent_fname_fill(entry, ffn); 2795*0Sstevel@tonic-gate entry->pcd_attr = Firstfileattr; 2796*0Sstevel@tonic-gate dirent_time_fill(entry); 2797*0Sstevel@tonic-gate entry->pcd_scluster_lo = htols(ffstart); 2798*0Sstevel@tonic-gate if (MakeFAT32) { 2799*0Sstevel@tonic-gate ffstart = ffstart >> 16; 2800*0Sstevel@tonic-gate entry->un.pcd_scluster_hi = htols(ffstart); 2801*0Sstevel@tonic-gate } 2802*0Sstevel@tonic-gate entry->pcd_size = htoli(ffsize); 2803*0Sstevel@tonic-gate entry++; 2804*0Sstevel@tonic-gate } 2805*0Sstevel@tonic-gate 2806*0Sstevel@tonic-gate /* Create directory entry for volume label, if there is one */ 2807*0Sstevel@tonic-gate if (Label != NULL) { 2808*0Sstevel@tonic-gate dirent_label_fill(entry, Label); 2809*0Sstevel@tonic-gate entry->pcd_attr = PCA_ARCH | PCA_LABEL; 2810*0Sstevel@tonic-gate dirent_time_fill(entry); 2811*0Sstevel@tonic-gate entry->pcd_scluster_lo = 0; 2812*0Sstevel@tonic-gate if (MakeFAT32) { 2813*0Sstevel@tonic-gate entry->un.pcd_scluster_hi = 0; 2814*0Sstevel@tonic-gate } 2815*0Sstevel@tonic-gate entry->pcd_size = 0; 2816*0Sstevel@tonic-gate entry++; 2817*0Sstevel@tonic-gate } 2818*0Sstevel@tonic-gate 2819*0Sstevel@tonic-gate if (Verbose) { 2820*0Sstevel@tonic-gate (void) printf(gettext("First two directory entries")); 2821*0Sstevel@tonic-gate header_for_dump(); 2822*0Sstevel@tonic-gate dump_bytes((uchar_t *)rootdirp, 2 * sizeof (struct pcdir)); 2823*0Sstevel@tonic-gate } 2824*0Sstevel@tonic-gate 2825*0Sstevel@tonic-gate return ((uchar_t *)rootdirp); 2826*0Sstevel@tonic-gate } 2827*0Sstevel@tonic-gate 2828*0Sstevel@tonic-gate /* 2829*0Sstevel@tonic-gate * write_rest 2830*0Sstevel@tonic-gate * 2831*0Sstevel@tonic-gate * Write all the bytes from the current file pointer to end of file 2832*0Sstevel@tonic-gate * in the source file out to the destination file. The writes should 2833*0Sstevel@tonic-gate * be padded to whole clusters with 0's if necessary. 2834*0Sstevel@tonic-gate */ 2835*0Sstevel@tonic-gate static 2836*0Sstevel@tonic-gate void 2837*0Sstevel@tonic-gate write_rest(bpb_t *wbpb, char *efn, int dfd, int sfd, int remaining) 2838*0Sstevel@tonic-gate { 2839*0Sstevel@tonic-gate char buf[BPSEC]; 2840*0Sstevel@tonic-gate ushort_t numsect, numclust; 2841*0Sstevel@tonic-gate ushort_t wnumsect, s; 2842*0Sstevel@tonic-gate int doneread = 0; 2843*0Sstevel@tonic-gate int rstat; 2844*0Sstevel@tonic-gate 2845*0Sstevel@tonic-gate /* 2846*0Sstevel@tonic-gate * Compute number of clusters required to contain remaining bytes. 2847*0Sstevel@tonic-gate */ 2848*0Sstevel@tonic-gate numsect = idivceil(remaining, BPSEC); 2849*0Sstevel@tonic-gate numclust = idivceil(numsect, wbpb->bpb.sectors_per_cluster); 2850*0Sstevel@tonic-gate 2851*0Sstevel@tonic-gate wnumsect = numclust * wbpb->bpb.sectors_per_cluster; 2852*0Sstevel@tonic-gate for (s = 0; s < wnumsect; s++) { 2853*0Sstevel@tonic-gate if (!doneread) { 2854*0Sstevel@tonic-gate if ((rstat = read(sfd, buf, BPSEC)) < 0) { 2855*0Sstevel@tonic-gate perror(efn); 2856*0Sstevel@tonic-gate doneread = 1; 2857*0Sstevel@tonic-gate rstat = 0; 2858*0Sstevel@tonic-gate } else if (rstat == 0) { 2859*0Sstevel@tonic-gate doneread = 1; 2860*0Sstevel@tonic-gate } 2861*0Sstevel@tonic-gate (void) memset(&(buf[rstat]), 0, BPSEC - rstat); 2862*0Sstevel@tonic-gate } 2863*0Sstevel@tonic-gate if (write(dfd, buf, BPSEC) != BPSEC) { 2864*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("Copying ")); 2865*0Sstevel@tonic-gate perror(efn); 2866*0Sstevel@tonic-gate } 2867*0Sstevel@tonic-gate } 2868*0Sstevel@tonic-gate } 2869*0Sstevel@tonic-gate 2870*0Sstevel@tonic-gate static 2871*0Sstevel@tonic-gate void 2872*0Sstevel@tonic-gate write_fat32_bootstuff(int fd, boot_sector_t *bsp, 2873*0Sstevel@tonic-gate struct fat32_boot_fsinfo *fsinfop, off64_t seekto) 2874*0Sstevel@tonic-gate { 2875*0Sstevel@tonic-gate uchar_t fsinfobuf[BPSEC]; 2876*0Sstevel@tonic-gate uchar_t *fp; 2877*0Sstevel@tonic-gate 2878*0Sstevel@tonic-gate /* 2879*0Sstevel@tonic-gate * Construct the fsinfo buf 2880*0Sstevel@tonic-gate */ 2881*0Sstevel@tonic-gate (void) memset(fsinfobuf, 0, BPSEC); 2882*0Sstevel@tonic-gate /* 2883*0Sstevel@tonic-gate * Not sure if this magic signature at the beginning of the 2884*0Sstevel@tonic-gate * sector is necessary for us to create or not. For now, I'm 2885*0Sstevel@tonic-gate * going to assume it is, since I haven't seen any Windows FAT32s 2886*0Sstevel@tonic-gate * without it. 2887*0Sstevel@tonic-gate */ 2888*0Sstevel@tonic-gate fsinfobuf[0] = 'R'; 2889*0Sstevel@tonic-gate fsinfobuf[1] = 'R'; 2890*0Sstevel@tonic-gate fsinfobuf[2] = 'a'; 2891*0Sstevel@tonic-gate fsinfobuf[3] = 'A'; 2892*0Sstevel@tonic-gate /* 2893*0Sstevel@tonic-gate * We also appear to want the magic Boot sector signature at the 2894*0Sstevel@tonic-gate * end of the sector. 2895*0Sstevel@tonic-gate */ 2896*0Sstevel@tonic-gate fsinfobuf[BPSEC - 2] = BOOTSECSIG & 0xFF; 2897*0Sstevel@tonic-gate fsinfobuf[BPSEC - 1] = (BOOTSECSIG >> 8) & 0xFF; 2898*0Sstevel@tonic-gate 2899*0Sstevel@tonic-gate fp = &(fsinfobuf[FAT32_BOOT_FSINFO_OFF]); 2900*0Sstevel@tonic-gate fp += 4; /* skip first reserved field */ 2901*0Sstevel@tonic-gate store_32_bits(&fp, fsinfop->fs_signature); 2902*0Sstevel@tonic-gate store_32_bits(&fp, fsinfop->fs_free_clusters); 2903*0Sstevel@tonic-gate store_32_bits(&fp, fsinfop->fs_next_cluster); 2904*0Sstevel@tonic-gate 2905*0Sstevel@tonic-gate if (Verbose) { 2906*0Sstevel@tonic-gate (void) printf(gettext("Dump of the fs info sector")); 2907*0Sstevel@tonic-gate header_for_dump(); 2908*0Sstevel@tonic-gate dump_bytes(fsinfobuf, sizeof (fsinfobuf)); 2909*0Sstevel@tonic-gate } 2910*0Sstevel@tonic-gate 2911*0Sstevel@tonic-gate if (!Notreally) { 2912*0Sstevel@tonic-gate /* 2913*0Sstevel@tonic-gate * FAT32's have an FS info sector, then a backup of the boot 2914*0Sstevel@tonic-gate * sector, and a modified backup of the FS Info sector. 2915*0Sstevel@tonic-gate */ 2916*0Sstevel@tonic-gate if (write(fd, fsinfobuf, sizeof (fsinfobuf)) != BPSEC) { 2917*0Sstevel@tonic-gate perror(gettext("FS info sector write")); 2918*0Sstevel@tonic-gate exit(4); 2919*0Sstevel@tonic-gate } 2920*0Sstevel@tonic-gate if (lseek64(fd, seekto + BKUP_BOOTSECT_OFFSET, SEEK_SET) < 0) { 2921*0Sstevel@tonic-gate (void) close(fd); 2922*0Sstevel@tonic-gate perror(gettext("Boot sector backup seek")); 2923*0Sstevel@tonic-gate exit(4); 2924*0Sstevel@tonic-gate } 2925*0Sstevel@tonic-gate if (write(fd, bsp->buf, sizeof (bsp->buf)) != BPSEC) { 2926*0Sstevel@tonic-gate perror(gettext("Boot sector backup write")); 2927*0Sstevel@tonic-gate exit(4); 2928*0Sstevel@tonic-gate } 2929*0Sstevel@tonic-gate } 2930*0Sstevel@tonic-gate 2931*0Sstevel@tonic-gate /* 2932*0Sstevel@tonic-gate * Second copy of fs info sector is modified to have "don't know" 2933*0Sstevel@tonic-gate * as the number of free clusters 2934*0Sstevel@tonic-gate */ 2935*0Sstevel@tonic-gate fp = &(fsinfobuf[FAT32_BOOT_FSINFO_OFF]); 2936*0Sstevel@tonic-gate fp += 8; /* skip first reserved field and signature */ 2937*0Sstevel@tonic-gate store_32_bits(&fp, -1); 2938*0Sstevel@tonic-gate 2939*0Sstevel@tonic-gate if (Verbose) { 2940*0Sstevel@tonic-gate (void) printf(gettext("Dump of the backup fs info sector")); 2941*0Sstevel@tonic-gate header_for_dump(); 2942*0Sstevel@tonic-gate dump_bytes(fsinfobuf, sizeof (fsinfobuf)); 2943*0Sstevel@tonic-gate } 2944*0Sstevel@tonic-gate 2945*0Sstevel@tonic-gate if (!Notreally) { 2946*0Sstevel@tonic-gate if (write(fd, fsinfobuf, sizeof (fsinfobuf)) != BPSEC) { 2947*0Sstevel@tonic-gate perror(gettext("FS info sector backup write")); 2948*0Sstevel@tonic-gate exit(4); 2949*0Sstevel@tonic-gate } 2950*0Sstevel@tonic-gate } 2951*0Sstevel@tonic-gate } 2952*0Sstevel@tonic-gate 2953*0Sstevel@tonic-gate static 2954*0Sstevel@tonic-gate void 2955*0Sstevel@tonic-gate write_bootsects(int fd, boot_sector_t *bsp, bpb_t *wbpb, 2956*0Sstevel@tonic-gate struct fat32_boot_fsinfo *fsinfop, off64_t seekto) 2957*0Sstevel@tonic-gate { 2958*0Sstevel@tonic-gate if (MakeFAT32) { 2959*0Sstevel@tonic-gate /* Copy our BPB into bootsec structure */ 2960*0Sstevel@tonic-gate #ifdef i386 2961*0Sstevel@tonic-gate (void) memcpy(&(bsp->bs32.bs_front.bs_bpb), &(wbpb->bpb), 2962*0Sstevel@tonic-gate sizeof (wbpb->bpb)); 2963*0Sstevel@tonic-gate (void) memcpy(&(bsp->bs32.bs_bpb32), &(wbpb->bpb32), 2964*0Sstevel@tonic-gate sizeof (wbpb->bpb32)); 2965*0Sstevel@tonic-gate (void) memcpy(&(bsp->bs32.bs_ebpb), &(wbpb->ebpb), 2966*0Sstevel@tonic-gate sizeof (wbpb->ebpb)); 2967*0Sstevel@tonic-gate #else 2968*0Sstevel@tonic-gate swap_pack_bpb32cpy(&(bsp->bs32), wbpb); 2969*0Sstevel@tonic-gate #endif 2970*0Sstevel@tonic-gate } else { 2971*0Sstevel@tonic-gate /* Copy our BPB into bootsec structure */ 2972*0Sstevel@tonic-gate #ifdef i386 2973*0Sstevel@tonic-gate (void) memcpy(&(bsp->bs.bs_front.bs_bpb), &(wbpb->bpb), 2974*0Sstevel@tonic-gate sizeof (wbpb->bpb)); 2975*0Sstevel@tonic-gate (void) memcpy(&(bsp->bs.bs_ebpb), &(wbpb->ebpb), 2976*0Sstevel@tonic-gate sizeof (wbpb->ebpb)); 2977*0Sstevel@tonic-gate #else 2978*0Sstevel@tonic-gate swap_pack_bpbcpy(&(bsp->bs), wbpb); 2979*0Sstevel@tonic-gate #endif 2980*0Sstevel@tonic-gate 2981*0Sstevel@tonic-gate /* Copy SUN BPB extensions into bootsec structure */ 2982*0Sstevel@tonic-gate if (SunBPBfields) { 2983*0Sstevel@tonic-gate #ifdef i386 2984*0Sstevel@tonic-gate (void) memcpy(&(bsp->bs.bs_sebpb), &(wbpb->sunbpb), 2985*0Sstevel@tonic-gate sizeof (wbpb->sunbpb)); 2986*0Sstevel@tonic-gate #else 2987*0Sstevel@tonic-gate swap_pack_sebpbcpy(&(bsp->bs), wbpb); 2988*0Sstevel@tonic-gate #endif 2989*0Sstevel@tonic-gate } 2990*0Sstevel@tonic-gate } 2991*0Sstevel@tonic-gate 2992*0Sstevel@tonic-gate /* Write boot sector */ 2993*0Sstevel@tonic-gate if (!Notreally && write(fd, bsp->buf, sizeof (bsp->buf)) != BPSEC) { 2994*0Sstevel@tonic-gate perror(gettext("Boot sector write")); 2995*0Sstevel@tonic-gate exit(4); 2996*0Sstevel@tonic-gate } 2997*0Sstevel@tonic-gate 2998*0Sstevel@tonic-gate if (Verbose) { 2999*0Sstevel@tonic-gate (void) printf(gettext("Dump of the boot sector")); 3000*0Sstevel@tonic-gate header_for_dump(); 3001*0Sstevel@tonic-gate dump_bytes(bsp->buf, sizeof (bsp->buf)); 3002*0Sstevel@tonic-gate } 3003*0Sstevel@tonic-gate 3004*0Sstevel@tonic-gate if (MakeFAT32) 3005*0Sstevel@tonic-gate write_fat32_bootstuff(fd, bsp, fsinfop, seekto); 3006*0Sstevel@tonic-gate } 3007*0Sstevel@tonic-gate 3008*0Sstevel@tonic-gate static 3009*0Sstevel@tonic-gate void 3010*0Sstevel@tonic-gate write_fat(int fd, off64_t seekto, char *fn, char *lbl, char *ffn, bpb_t *wbpb) 3011*0Sstevel@tonic-gate { 3012*0Sstevel@tonic-gate struct fat32_boot_fsinfo fsinfo; 3013*0Sstevel@tonic-gate pc_cluster32_t ffsc; 3014*0Sstevel@tonic-gate boot_sector_t bootsect; 3015*0Sstevel@tonic-gate uchar_t *fatp, *rdirp; 3016*0Sstevel@tonic-gate ulong_t bootblksize, fatsize, rdirsize, ffsize; 3017*0Sstevel@tonic-gate int bsfd = -1; 3018*0Sstevel@tonic-gate int fffd = -1; 3019*0Sstevel@tonic-gate 3020*0Sstevel@tonic-gate compute_file_area_size(wbpb); 3021*0Sstevel@tonic-gate 3022*0Sstevel@tonic-gate bsfd = copy_bootblk(fn, &bootsect, &bootblksize); 3023*0Sstevel@tonic-gate label_volume(lbl, wbpb); 3024*0Sstevel@tonic-gate 3025*0Sstevel@tonic-gate if (Verbose) 3026*0Sstevel@tonic-gate (void) printf(gettext("Building FAT.\n")); 3027*0Sstevel@tonic-gate fatp = build_fat(wbpb, &fsinfo, bootblksize, &fatsize, 3028*0Sstevel@tonic-gate ffn, &fffd, &ffsize, &ffsc); 3029*0Sstevel@tonic-gate 3030*0Sstevel@tonic-gate write_bootsects(fd, &bootsect, wbpb, &fsinfo, seekto); 3031*0Sstevel@tonic-gate 3032*0Sstevel@tonic-gate if (lseek64(fd, 3033*0Sstevel@tonic-gate seekto + (BPSEC * wbpb->bpb.resv_sectors), SEEK_SET) < 0) { 3034*0Sstevel@tonic-gate (void) close(fd); 3035*0Sstevel@tonic-gate perror(gettext("Seek to end of reserved sectors")); 3036*0Sstevel@tonic-gate exit(4); 3037*0Sstevel@tonic-gate } 3038*0Sstevel@tonic-gate 3039*0Sstevel@tonic-gate /* Write FAT */ 3040*0Sstevel@tonic-gate if (Verbose) 3041*0Sstevel@tonic-gate (void) printf(gettext("Writing FAT(s). %d bytes times %d.\n"), 3042*0Sstevel@tonic-gate fatsize, wbpb->bpb.num_fats); 3043*0Sstevel@tonic-gate if (!Notreally) { 3044*0Sstevel@tonic-gate int nf, wb; 3045*0Sstevel@tonic-gate for (nf = 0; nf < (int)wbpb->bpb.num_fats; nf++) 3046*0Sstevel@tonic-gate if ((wb = write(fd, fatp, fatsize)) != fatsize) { 3047*0Sstevel@tonic-gate perror(gettext("FAT write")); 3048*0Sstevel@tonic-gate exit(4); 3049*0Sstevel@tonic-gate } else { 3050*0Sstevel@tonic-gate if (Verbose) 3051*0Sstevel@tonic-gate (void) printf( 3052*0Sstevel@tonic-gate gettext("Wrote %d bytes\n"), wb); 3053*0Sstevel@tonic-gate } 3054*0Sstevel@tonic-gate } 3055*0Sstevel@tonic-gate free(fatp); 3056*0Sstevel@tonic-gate 3057*0Sstevel@tonic-gate if (Verbose) 3058*0Sstevel@tonic-gate (void) printf(gettext("Building root directory.\n")); 3059*0Sstevel@tonic-gate rdirp = build_rootdir(wbpb, ffn, fffd, ffsize, ffsc, &rdirsize); 3060*0Sstevel@tonic-gate 3061*0Sstevel@tonic-gate /* 3062*0Sstevel@tonic-gate * In non FAT32, root directory exists outside of the file area 3063*0Sstevel@tonic-gate */ 3064*0Sstevel@tonic-gate if (!MakeFAT32) { 3065*0Sstevel@tonic-gate if (Verbose) 3066*0Sstevel@tonic-gate (void) printf( 3067*0Sstevel@tonic-gate gettext("Writing root directory. " 3068*0Sstevel@tonic-gate "%d bytes.\n"), rdirsize); 3069*0Sstevel@tonic-gate if (!Notreally) { 3070*0Sstevel@tonic-gate if (write(fd, rdirp, rdirsize) != rdirsize) { 3071*0Sstevel@tonic-gate perror(gettext("Root directory write")); 3072*0Sstevel@tonic-gate exit(4); 3073*0Sstevel@tonic-gate } 3074*0Sstevel@tonic-gate } 3075*0Sstevel@tonic-gate free(rdirp); 3076*0Sstevel@tonic-gate } 3077*0Sstevel@tonic-gate 3078*0Sstevel@tonic-gate /* 3079*0Sstevel@tonic-gate * Now write anything that needs to be in the file space. 3080*0Sstevel@tonic-gate */ 3081*0Sstevel@tonic-gate if (bootblksize > BPSEC) { 3082*0Sstevel@tonic-gate if (Verbose) 3083*0Sstevel@tonic-gate (void) printf(gettext("Writing remainder of " 3084*0Sstevel@tonic-gate "boot block.\n")); 3085*0Sstevel@tonic-gate if (!Notreally) 3086*0Sstevel@tonic-gate write_rest(wbpb, fn, fd, bsfd, bootblksize - BPSEC); 3087*0Sstevel@tonic-gate } 3088*0Sstevel@tonic-gate 3089*0Sstevel@tonic-gate if (MakeFAT32) { 3090*0Sstevel@tonic-gate if (Verbose) 3091*0Sstevel@tonic-gate (void) printf( 3092*0Sstevel@tonic-gate gettext("Writing root directory. " 3093*0Sstevel@tonic-gate "%d bytes.\n"), rdirsize); 3094*0Sstevel@tonic-gate if (!Notreally) { 3095*0Sstevel@tonic-gate if (write(fd, rdirp, rdirsize) != rdirsize) { 3096*0Sstevel@tonic-gate perror(gettext("Root directory write")); 3097*0Sstevel@tonic-gate exit(4); 3098*0Sstevel@tonic-gate } 3099*0Sstevel@tonic-gate } 3100*0Sstevel@tonic-gate free(rdirp); 3101*0Sstevel@tonic-gate } 3102*0Sstevel@tonic-gate 3103*0Sstevel@tonic-gate if (fffd >= 0) { 3104*0Sstevel@tonic-gate if (Verbose) 3105*0Sstevel@tonic-gate (void) printf(gettext("Writing first file.\n")); 3106*0Sstevel@tonic-gate if (!Notreally) 3107*0Sstevel@tonic-gate write_rest(wbpb, ffn, fd, fffd, ffsize); 3108*0Sstevel@tonic-gate } 3109*0Sstevel@tonic-gate } 3110*0Sstevel@tonic-gate 3111*0Sstevel@tonic-gate static 3112*0Sstevel@tonic-gate char *LegalOpts[] = { 3113*0Sstevel@tonic-gate #define NFLAG 0 3114*0Sstevel@tonic-gate "N", 3115*0Sstevel@tonic-gate #define VFLAG 1 3116*0Sstevel@tonic-gate "v", 3117*0Sstevel@tonic-gate #define RFLAG 2 3118*0Sstevel@tonic-gate "r", 3119*0Sstevel@tonic-gate #define HFLAG 3 3120*0Sstevel@tonic-gate "h", 3121*0Sstevel@tonic-gate #define SFLAG 4 3122*0Sstevel@tonic-gate "s", 3123*0Sstevel@tonic-gate #define SUNFLAG 5 3124*0Sstevel@tonic-gate "S", 3125*0Sstevel@tonic-gate #define LABFLAG 6 3126*0Sstevel@tonic-gate "b", 3127*0Sstevel@tonic-gate #define BTRFLAG 7 3128*0Sstevel@tonic-gate "B", 3129*0Sstevel@tonic-gate #define INITFLAG 8 3130*0Sstevel@tonic-gate "i", 3131*0Sstevel@tonic-gate #define SZFLAG 9 3132*0Sstevel@tonic-gate "size", 3133*0Sstevel@tonic-gate #define SECTFLAG 10 3134*0Sstevel@tonic-gate "nsect", 3135*0Sstevel@tonic-gate #define TRKFLAG 11 3136*0Sstevel@tonic-gate "ntrack", 3137*0Sstevel@tonic-gate #define SPCFLAG 12 3138*0Sstevel@tonic-gate "spc", 3139*0Sstevel@tonic-gate #define BPFFLAG 13 3140*0Sstevel@tonic-gate "fat", 3141*0Sstevel@tonic-gate #define FFLAG 14 3142*0Sstevel@tonic-gate "f", 3143*0Sstevel@tonic-gate #define DFLAG 15 3144*0Sstevel@tonic-gate "d", 3145*0Sstevel@tonic-gate #define NOFDISKFLAG 16 3146*0Sstevel@tonic-gate "nofdisk", 3147*0Sstevel@tonic-gate #define RESRVFLAG 17 3148*0Sstevel@tonic-gate "reserve", 3149*0Sstevel@tonic-gate #define HIDDENFLAG 18 3150*0Sstevel@tonic-gate "hidden", 3151*0Sstevel@tonic-gate NULL 3152*0Sstevel@tonic-gate }; 3153*0Sstevel@tonic-gate 3154*0Sstevel@tonic-gate static 3155*0Sstevel@tonic-gate void 3156*0Sstevel@tonic-gate bad_arg(char *option) 3157*0Sstevel@tonic-gate { 3158*0Sstevel@tonic-gate (void) fprintf(stderr, 3159*0Sstevel@tonic-gate gettext("Unrecognized option %s.\n"), option); 3160*0Sstevel@tonic-gate usage(); 3161*0Sstevel@tonic-gate exit(2); 3162*0Sstevel@tonic-gate } 3163*0Sstevel@tonic-gate 3164*0Sstevel@tonic-gate static 3165*0Sstevel@tonic-gate void 3166*0Sstevel@tonic-gate missing_arg(char *option) 3167*0Sstevel@tonic-gate { 3168*0Sstevel@tonic-gate (void) fprintf(stderr, 3169*0Sstevel@tonic-gate gettext("Option %s requires a value.\n"), option); 3170*0Sstevel@tonic-gate usage(); 3171*0Sstevel@tonic-gate exit(3); 3172*0Sstevel@tonic-gate } 3173*0Sstevel@tonic-gate 3174*0Sstevel@tonic-gate static 3175*0Sstevel@tonic-gate void 3176*0Sstevel@tonic-gate parse_suboptions(char *optsstr) 3177*0Sstevel@tonic-gate { 3178*0Sstevel@tonic-gate char *value; 3179*0Sstevel@tonic-gate int c; 3180*0Sstevel@tonic-gate 3181*0Sstevel@tonic-gate while (*optsstr != '\0') { 3182*0Sstevel@tonic-gate switch (c = getsubopt(&optsstr, LegalOpts, &value)) { 3183*0Sstevel@tonic-gate case NFLAG: 3184*0Sstevel@tonic-gate Notreally++; 3185*0Sstevel@tonic-gate break; 3186*0Sstevel@tonic-gate case VFLAG: 3187*0Sstevel@tonic-gate Verbose++; 3188*0Sstevel@tonic-gate break; 3189*0Sstevel@tonic-gate case RFLAG: 3190*0Sstevel@tonic-gate Firstfileattr |= 0x01; 3191*0Sstevel@tonic-gate break; 3192*0Sstevel@tonic-gate case HFLAG: 3193*0Sstevel@tonic-gate Firstfileattr |= 0x02; 3194*0Sstevel@tonic-gate break; 3195*0Sstevel@tonic-gate case SFLAG: 3196*0Sstevel@tonic-gate Firstfileattr |= 0x04; 3197*0Sstevel@tonic-gate break; 3198*0Sstevel@tonic-gate case SUNFLAG: 3199*0Sstevel@tonic-gate SunBPBfields = 1; 3200*0Sstevel@tonic-gate break; 3201*0Sstevel@tonic-gate case LABFLAG: 3202*0Sstevel@tonic-gate if (value == NULL) { 3203*0Sstevel@tonic-gate missing_arg(LegalOpts[c]); 3204*0Sstevel@tonic-gate } else { 3205*0Sstevel@tonic-gate Label = value; 3206*0Sstevel@tonic-gate } 3207*0Sstevel@tonic-gate break; 3208*0Sstevel@tonic-gate case BTRFLAG: 3209*0Sstevel@tonic-gate if (value == NULL) { 3210*0Sstevel@tonic-gate missing_arg(LegalOpts[c]); 3211*0Sstevel@tonic-gate } else { 3212*0Sstevel@tonic-gate BootBlkFn = value; 3213*0Sstevel@tonic-gate } 3214*0Sstevel@tonic-gate break; 3215*0Sstevel@tonic-gate case INITFLAG: 3216*0Sstevel@tonic-gate if (value == NULL) { 3217*0Sstevel@tonic-gate missing_arg(LegalOpts[c]); 3218*0Sstevel@tonic-gate } else { 3219*0Sstevel@tonic-gate FirstFn = value; 3220*0Sstevel@tonic-gate } 3221*0Sstevel@tonic-gate break; 3222*0Sstevel@tonic-gate case SZFLAG: 3223*0Sstevel@tonic-gate if (value == NULL) { 3224*0Sstevel@tonic-gate missing_arg(LegalOpts[c]); 3225*0Sstevel@tonic-gate } else { 3226*0Sstevel@tonic-gate TotSize = atoi(value); 3227*0Sstevel@tonic-gate GetSize = 0; 3228*0Sstevel@tonic-gate } 3229*0Sstevel@tonic-gate break; 3230*0Sstevel@tonic-gate case SECTFLAG: 3231*0Sstevel@tonic-gate if (value == NULL) { 3232*0Sstevel@tonic-gate missing_arg(LegalOpts[c]); 3233*0Sstevel@tonic-gate } else { 3234*0Sstevel@tonic-gate SecPerTrk = atoi(value); 3235*0Sstevel@tonic-gate GetSPT = 0; 3236*0Sstevel@tonic-gate } 3237*0Sstevel@tonic-gate break; 3238*0Sstevel@tonic-gate case TRKFLAG: 3239*0Sstevel@tonic-gate if (value == NULL) { 3240*0Sstevel@tonic-gate missing_arg(LegalOpts[c]); 3241*0Sstevel@tonic-gate } else { 3242*0Sstevel@tonic-gate TrkPerCyl = atoi(value); 3243*0Sstevel@tonic-gate GetTPC = 0; 3244*0Sstevel@tonic-gate } 3245*0Sstevel@tonic-gate break; 3246*0Sstevel@tonic-gate case SPCFLAG: 3247*0Sstevel@tonic-gate if (value == NULL) { 3248*0Sstevel@tonic-gate missing_arg(LegalOpts[c]); 3249*0Sstevel@tonic-gate } else { 3250*0Sstevel@tonic-gate SecPerClust = atoi(value); 3251*0Sstevel@tonic-gate GetSPC = 0; 3252*0Sstevel@tonic-gate } 3253*0Sstevel@tonic-gate break; 3254*0Sstevel@tonic-gate case BPFFLAG: 3255*0Sstevel@tonic-gate if (value == NULL) { 3256*0Sstevel@tonic-gate missing_arg(LegalOpts[c]); 3257*0Sstevel@tonic-gate } else { 3258*0Sstevel@tonic-gate BitsPerFAT = atoi(value); 3259*0Sstevel@tonic-gate GetBPF = 0; 3260*0Sstevel@tonic-gate } 3261*0Sstevel@tonic-gate break; 3262*0Sstevel@tonic-gate case NOFDISKFLAG: 3263*0Sstevel@tonic-gate DontUseFdisk = 1; 3264*0Sstevel@tonic-gate break; 3265*0Sstevel@tonic-gate case RESRVFLAG: 3266*0Sstevel@tonic-gate if (value == NULL) { 3267*0Sstevel@tonic-gate missing_arg(LegalOpts[c]); 3268*0Sstevel@tonic-gate } else { 3269*0Sstevel@tonic-gate Resrvd = atoi(value); 3270*0Sstevel@tonic-gate GetResrvd = 0; 3271*0Sstevel@tonic-gate } 3272*0Sstevel@tonic-gate break; 3273*0Sstevel@tonic-gate case HIDDENFLAG: 3274*0Sstevel@tonic-gate if (value == NULL) { 3275*0Sstevel@tonic-gate missing_arg(LegalOpts[c]); 3276*0Sstevel@tonic-gate } else { 3277*0Sstevel@tonic-gate RelOffset = atoi(value); 3278*0Sstevel@tonic-gate GetOffset = 0; 3279*0Sstevel@tonic-gate } 3280*0Sstevel@tonic-gate break; 3281*0Sstevel@tonic-gate case FFLAG: 3282*0Sstevel@tonic-gate if (value == NULL) { 3283*0Sstevel@tonic-gate missing_arg(LegalOpts[c]); 3284*0Sstevel@tonic-gate } else { 3285*0Sstevel@tonic-gate DiskName = value; 3286*0Sstevel@tonic-gate Outputtofile = 1; 3287*0Sstevel@tonic-gate } 3288*0Sstevel@tonic-gate break; 3289*0Sstevel@tonic-gate case DFLAG: 3290*0Sstevel@tonic-gate if (value == NULL) { 3291*0Sstevel@tonic-gate missing_arg(LegalOpts[c]); 3292*0Sstevel@tonic-gate } else { 3293*0Sstevel@tonic-gate Imagesize = atoi(value); 3294*0Sstevel@tonic-gate } 3295*0Sstevel@tonic-gate break; 3296*0Sstevel@tonic-gate default: 3297*0Sstevel@tonic-gate bad_arg(value); 3298*0Sstevel@tonic-gate break; 3299*0Sstevel@tonic-gate } 3300*0Sstevel@tonic-gate } 3301*0Sstevel@tonic-gate } 3302*0Sstevel@tonic-gate 3303*0Sstevel@tonic-gate static 3304*0Sstevel@tonic-gate void 3305*0Sstevel@tonic-gate sanity_check_options(int argc, int optind) 3306*0Sstevel@tonic-gate { 3307*0Sstevel@tonic-gate if (GetFsParams) { 3308*0Sstevel@tonic-gate if (argc - optind != 1) 3309*0Sstevel@tonic-gate usage(); 3310*0Sstevel@tonic-gate return; 3311*0Sstevel@tonic-gate } 3312*0Sstevel@tonic-gate 3313*0Sstevel@tonic-gate if (DontUseFdisk && GetOffset) { 3314*0Sstevel@tonic-gate /* Set default relative offset of zero */ 3315*0Sstevel@tonic-gate RelOffset = 0; 3316*0Sstevel@tonic-gate } 3317*0Sstevel@tonic-gate 3318*0Sstevel@tonic-gate if (BitsPerFAT == 32) 3319*0Sstevel@tonic-gate MakeFAT32 = 1; 3320*0Sstevel@tonic-gate 3321*0Sstevel@tonic-gate if (Outputtofile && (argc - optind)) { 3322*0Sstevel@tonic-gate usage(); 3323*0Sstevel@tonic-gate } else if (Outputtofile && !DiskName) { 3324*0Sstevel@tonic-gate usage(); 3325*0Sstevel@tonic-gate } else if (!Outputtofile && (argc - optind != 1)) { 3326*0Sstevel@tonic-gate usage(); 3327*0Sstevel@tonic-gate } else if (SunBPBfields && !BootBlkFn) { 3328*0Sstevel@tonic-gate (void) fprintf(stderr, 3329*0Sstevel@tonic-gate gettext("Use of the 'S' option requires that\n" 3330*0Sstevel@tonic-gate "the 'B=' option also be used.\n\n")); 3331*0Sstevel@tonic-gate usage(); 3332*0Sstevel@tonic-gate } else if (Firstfileattr != 0x20 && !FirstFn) { 3333*0Sstevel@tonic-gate (void) fprintf(stderr, 3334*0Sstevel@tonic-gate gettext("Use of the 'r', 'h', or 's' options requires\n" 3335*0Sstevel@tonic-gate "that the 'i=' option also be used.\n\n")); 3336*0Sstevel@tonic-gate usage(); 3337*0Sstevel@tonic-gate } else if (!GetOffset && !DontUseFdisk) { 3338*0Sstevel@tonic-gate (void) fprintf(stderr, 3339*0Sstevel@tonic-gate gettext("Use of the 'hidden' option requires that\n" 3340*0Sstevel@tonic-gate "the 'nofdisk' option also be used.\n\n")); 3341*0Sstevel@tonic-gate usage(); 3342*0Sstevel@tonic-gate } else if (DontUseFdisk && GetSize) { 3343*0Sstevel@tonic-gate (void) fprintf(stderr, 3344*0Sstevel@tonic-gate gettext("Use of the 'nofdisk' option requires that\n" 3345*0Sstevel@tonic-gate "the 'size=' option also be used.\n\n")); 3346*0Sstevel@tonic-gate usage(); 3347*0Sstevel@tonic-gate } else if (!GetBPF && 3348*0Sstevel@tonic-gate BitsPerFAT != 12 && BitsPerFAT != 16 && BitsPerFAT != 32) { 3349*0Sstevel@tonic-gate (void) fprintf(stderr, 3350*0Sstevel@tonic-gate gettext("Invalid Bits/Fat value." 3351*0Sstevel@tonic-gate " Must be 12, 16 or 32.\n")); 3352*0Sstevel@tonic-gate exit(2); 3353*0Sstevel@tonic-gate } else if (!GetSPC && !powerofx_le_y(2, 128, SecPerClust)) { 3354*0Sstevel@tonic-gate (void) fprintf(stderr, 3355*0Sstevel@tonic-gate gettext("Invalid Sectors/Cluster value. Must be a " 3356*0Sstevel@tonic-gate "power of 2 between 1 and 128.\n")); 3357*0Sstevel@tonic-gate exit(2); 3358*0Sstevel@tonic-gate } else if (!GetResrvd && (Resrvd < 1 || Resrvd > 0xffff)) { 3359*0Sstevel@tonic-gate (void) fprintf(stderr, 3360*0Sstevel@tonic-gate gettext("Invalid number of reserved sectors. " 3361*0Sstevel@tonic-gate "Must be at least 1 but\nno larger than 65535.")); 3362*0Sstevel@tonic-gate exit(2); 3363*0Sstevel@tonic-gate } else if (!GetResrvd && MakeFAT32 && 3364*0Sstevel@tonic-gate (Resrvd < 32 || Resrvd > 0xffff)) { 3365*0Sstevel@tonic-gate (void) fprintf(stderr, 3366*0Sstevel@tonic-gate gettext("Invalid number of reserved sectors. " 3367*0Sstevel@tonic-gate "Must be at least 32 but\nno larger than 65535.")); 3368*0Sstevel@tonic-gate exit(2); 3369*0Sstevel@tonic-gate } else if (Imagesize != 3 && Imagesize != 5) { 3370*0Sstevel@tonic-gate usage(); 3371*0Sstevel@tonic-gate } 3372*0Sstevel@tonic-gate } 3373*0Sstevel@tonic-gate 3374*0Sstevel@tonic-gate void 3375*0Sstevel@tonic-gate main(int argc, char **argv) 3376*0Sstevel@tonic-gate { 3377*0Sstevel@tonic-gate off64_t AbsBootSect = 0; 3378*0Sstevel@tonic-gate bpb_t dskparamblk; 3379*0Sstevel@tonic-gate char *string; 3380*0Sstevel@tonic-gate int fd; 3381*0Sstevel@tonic-gate int c; 3382*0Sstevel@tonic-gate 3383*0Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 3384*0Sstevel@tonic-gate 3385*0Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 3386*0Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 3387*0Sstevel@tonic-gate #endif 3388*0Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 3389*0Sstevel@tonic-gate 3390*0Sstevel@tonic-gate while ((c = getopt(argc, argv, "F:Vmo:")) != EOF) { 3391*0Sstevel@tonic-gate switch (c) { 3392*0Sstevel@tonic-gate case 'F': 3393*0Sstevel@tonic-gate string = optarg; 3394*0Sstevel@tonic-gate if (strcmp(string, "pcfs") != 0) 3395*0Sstevel@tonic-gate usage(); 3396*0Sstevel@tonic-gate break; 3397*0Sstevel@tonic-gate case 'V': 3398*0Sstevel@tonic-gate { 3399*0Sstevel@tonic-gate char *opt_text; 3400*0Sstevel@tonic-gate int opt_count; 3401*0Sstevel@tonic-gate 3402*0Sstevel@tonic-gate (void) fprintf(stdout, 3403*0Sstevel@tonic-gate gettext("mkfs -F pcfs ")); 3404*0Sstevel@tonic-gate for (opt_count = 1; opt_count < argc; 3405*0Sstevel@tonic-gate opt_count++) { 3406*0Sstevel@tonic-gate opt_text = argv[opt_count]; 3407*0Sstevel@tonic-gate if (opt_text) 3408*0Sstevel@tonic-gate (void) fprintf(stdout, " %s ", 3409*0Sstevel@tonic-gate opt_text); 3410*0Sstevel@tonic-gate } 3411*0Sstevel@tonic-gate (void) fprintf(stdout, "\n"); 3412*0Sstevel@tonic-gate } 3413*0Sstevel@tonic-gate break; 3414*0Sstevel@tonic-gate case 'm': 3415*0Sstevel@tonic-gate GetFsParams++; 3416*0Sstevel@tonic-gate break; 3417*0Sstevel@tonic-gate case 'o': 3418*0Sstevel@tonic-gate string = optarg; 3419*0Sstevel@tonic-gate parse_suboptions(string); 3420*0Sstevel@tonic-gate break; 3421*0Sstevel@tonic-gate } 3422*0Sstevel@tonic-gate } 3423*0Sstevel@tonic-gate 3424*0Sstevel@tonic-gate sanity_check_options(argc, optind); 3425*0Sstevel@tonic-gate 3426*0Sstevel@tonic-gate if (!Outputtofile) 3427*0Sstevel@tonic-gate DiskName = argv[optind]; 3428*0Sstevel@tonic-gate 3429*0Sstevel@tonic-gate (void) memset(&dskparamblk, 0, sizeof (dskparamblk)); 3430*0Sstevel@tonic-gate 3431*0Sstevel@tonic-gate if (GetFsParams) { 3432*0Sstevel@tonic-gate fd = open_and_examine(DiskName, &dskparamblk); 3433*0Sstevel@tonic-gate } else { 3434*0Sstevel@tonic-gate fd = open_and_seek(DiskName, &dskparamblk, &AbsBootSect); 3435*0Sstevel@tonic-gate if (ask_nicely(DiskName)) 3436*0Sstevel@tonic-gate write_fat(fd, AbsBootSect, BootBlkFn, Label, 3437*0Sstevel@tonic-gate FirstFn, &dskparamblk); 3438*0Sstevel@tonic-gate } 3439*0Sstevel@tonic-gate (void) close(fd); 3440*0Sstevel@tonic-gate exit(0); 3441*0Sstevel@tonic-gate } 3442