pcfs_common.c revision 342440ec94087b8c751c580ab9ed6c693d31d418
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* fsck_pcfs -- common.c
* All the routines in this file are being swiped directly from
* mkfs_pcfs. Eventually this file should only exist in one place
* and be part of a library that both mkfs and fsck link against.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <libintl.h>
#include <sys/isa_defs.h>
#include "fsck_pcfs.h"
#include "pcfs_common.h"
#include "pcfs_bpb.h"
/*
* The assumption here is that _BIG_ENDIAN implies sparc, and
* so in addition to swapping bytes we also have to construct
* packed structures by hand to avoid bus errors due to improperly
* aligned pointers.
*/
#ifdef _BIG_ENDIAN
#endif /* _BIG_ENDIAN */
/*
* Global variables related to input questions
*/
extern int AlwaysYes;
extern int AlwaysNo;
int
is_z_a_power_of_x_le_y(int x, int y, int z)
{
int ispower = 0;
int pow = 1;
do {
if (pow == z) {
ispower = 1;
break;
}
pow *= x;
} while (pow <= y);
return (ispower);
}
/*
* store_16_bits
* Save the lower 16 bits of a 32 bit value (v) into the provided
* buffer (pointed at by *bp), and increment the buffer pointer
* as well. This way the routine can be called multiple times in
* succession to fill buffers. The value is stored in little-endian
* order.
*/
void
{
*l++ = v & 0xff;
*l = (v >> 8) & 0xff;
*bp += 2;
}
void
{
}
/*
* store_32_bits
* Save the 32 bit value (v) into the provided buffer (pointed
* at by *bp), and increment the buffer pointer as well. This way
* the routine can be called multiple times in succession to fill
* buffers. The value is stored in little-endian order.
*/
void
{
int b;
for (b = 0; b < 4; b++) {
*l++ = v & 0xff;
v = v >> 8;
}
*bp += 4;
}
void
{
}
/*
* dump_bytes -- display bytes as hex numbers.
* b is the pointer to the byte buffer
* n is the number of bytes in the buffer
*/
/* Note: BPL = bytes to display per line */
#define BPL 16
void
{
int printedCount;
int countdown = n;
int countup = 0;
int offset = 0;
int byte;
/* Display offset, 16 bytes per line, and printable ascii version */
while (countdown > 0) {
printedCount = 0;
/*
* Print Hex value of characters in columns on left
*/
printedCount++;
} else {
}
}
/*
* Right side has the printable character or '.' for
* unprintable for each column of the left.
*/
} else {
}
}
countup += printedCount;
offset += printedCount;
}
}
/*
* header_for_dump -- display simple header over what will be output.
*/
void
header_for_dump(void)
{
int byte;
while (byte-- > 0)
}
/*
* We are basically (incorrectly) assuming that if you aren't running
* on x86 the BPB has to be packed by hand AND that the bytes must
* be swapped. One or both of these assumptions may one day be invalid.
* (if they aren't already :-))
*/
#ifdef _BIG_ENDIAN
/*
* swap_pack_grab{32}bpb
* If not on an x86 we assume the structures making up the bpb
* were not packed and that longs and shorts need to be byte swapped
* (we've kept everything in host order up until now). A new architecture
* might not need to swap or might not need to pack, in which case
* new routines will have to be written. Of course if an architecture
* supports both packing and little-endian host order, it can follow the
* same path as the x86 code.
*/
void
{
grabp += 11;
}
void
{
}
#endif /* _BIG_ENDIAN */
int
yes(void)
{
char *a = affirmative;
char input[80];
if (AlwaysYes) {
(void) printf("y\n");
return (1);
} else if (AlwaysNo) {
(void) printf("n\n");
return (0);
}
AlwaysNo = 1;
(void) printf("n\n");
return (0);
}
while (*a) {
if (input[0] == (int)*a)
break;
a++;
}
return ((int)*a);
}
char *
{
char *actualdisk;
/*
* Device named on command line doesn't exist. That
* probably means there is a partition-specifying
* suffix attached to the actual disk name.
*/
gettext("Out of memory for disk name.\n"));
exit(2);
}
**suffix = '\0';
(*suffix)++;
}
exit(2);
}
} else {
gettext("Out of memory for disk name.\n"));
exit(2);
}
}
return (actualdisk);
}
extern void usage(void);
void
{
usage();
exit(2);
}
void
missing_arg(char *option)
{
usage();
exit(3);
}
static int
parse_drvnum(char *pn)
{
int drvnum;
/*
* Determine logical drive to seek after.
*/
char *d;
int v = 0;
d = pn;
while ((*d != '\0') && (*d >= '0') && (*d <= '9')) {
v *= 10;
v += *d - '0';
d++;
}
if ((*d != '\0') || (v > 24)) {
gettext("%s: bogus logical drive specification.\n"),
pn);
return (-1);
}
drvnum = v;
drvnum = 99;
} else {
return (-1);
}
return (drvnum);
}
/*
* isDosDrive()
* Boolean function. Give it the systid field for an fdisk partition
* and it decides if that's a systid that describes a DOS drive. We
*/
static int
{
}
/*
* isDosExtended()
* Boolean function. Give it the systid field for an fdisk partition
* and it decides if that's a systid that describes an extended DOS
* partition.
*/
static int
{
}
/*
* isBootPart()
* Boolean function. Give it the systid field for an fdisk partition
* and it decides if that's a systid that describes a Solaris boot
* partition.
*/
static int
{
}
{
int logicalDriveCount = 0;
int extendedPart = -1;
int primaryPart = -1;
int bootPart = -1;
int drvnum;
int driveIndex;
int i;
/*
* Count of drives in the current extended partition's
* FDISK table, and indexes of the drives themselves.
*/
int extndDrives[FD_NUMPART];
int numDrives = 0;
/*
* Count of drives (beyond primary) in master boot record's
* FDISK table, and indexes of the drives themselves.
*/
int extraDrives[FD_NUMPART];
int numExtraDrives = 0;
return (error);
gettext("Couldn't read a Master Boot Record\n"));
return (error);
}
gettext("Bad signature on master boot record (%x)\n"),
return (error);
}
/*
* Copy partition table into memory
*/
/*
* Get a summary of what is in the Master FDISK table.
* Normally we expect to find one partition marked as a DOS drive.
* This partition is the one Windows calls the primary dos partition.
* If the machine has any logical drives then we also expect
* to find a partition marked as an extended DOS partition.
*
* Sometimes we'll find multiple partitions marked as DOS drives.
* The Solaris fdisk program allows these partitions
* to be created, but Windows fdisk no longer does. We still need
* to support these, though, since Windows does. We also need to fix
* our fdisk to behave like the Windows version.
*
* It turns out that some off-the-shelf media have *only* an
* Extended partition, so we need to deal with that case as
* well.
*
* Only a single (the first) Extended or Boot Partition will
* be recognized. Any others will be ignored.
*/
for (i = 0; i < FD_NUMPART; i++) {
if (primaryPart < 0) {
primaryPart = i;
} else {
extraDrives[numExtraDrives++] = i;
}
continue;
}
extendedPart = i;
continue;
}
bootPart = i;
continue;
}
}
if (drvnum == BOOT_PARTITION_DRIVE) {
if (bootPart < 0) {
gettext("No boot partition found on drive\n"));
return (error);
}
return (found);
}
return (found);
}
/*
* We are not looking for the C: drive (or there was no primary
* drive found), so we had better have an extended partition or
* extra drives in the Master FDISK table.
*/
if ((extendedPart < 0) && (numExtraDrives == 0)) {
gettext("No such logical drive "
"(missing extended partition entry)\n"));
return (error);
}
if (extendedPart >= 0) {
do {
/*
* If the seek would not cause us to change
* position on the drive, then we're out of
* extended partitions to examine.
*/
break;
/*
* Seek the next extended partition, and find
* logical drives within it.
*/
sizeof (extmboot)) {
"partition record"));
return (error);
}
gettext("Bad signature on "
"extended partition\n"));
return (error);
}
/*
* Count up drives, and track where the next
* extended partition is in case we need it. We
* are expecting only one extended partition. If
* there is more than one we'll only go to the
* first one we see, but warn about ignoring.
*/
numDrives = 0;
for (i = 0; i < FD_NUMPART; i++) {
extndDrives[numDrives++] = i;
continue;
/*
* Already found an extended
* partition in this table.
*/
gettext("WARNING: "
"Ignoring unexpected "
"additional extended "
"partition"));
continue;
}
nextseek = xstartsect +
continue;
}
}
/*
* The number of logical drives we've found thus
* far is enough to get us to the one we were
* searching for.
*/
found =
gettext("Logical drive start sector (%d) "
"is not within the partition!\n"), found);
return (error);
} else {
}
return (found);
} else {
/*
* We ran out of extended dos partition
* drives. The only hope now is to go
* back to extra drives defined in the master
* fdisk table. But we overwrote that table
* already, so we must load it in again.
*/
}
}
/*
* Still haven't found the drive, is it an extra
* drive defined in the main FDISK table?
*/
return (found);
}
return (error);
}