/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* This file contains functions implementing the analyze menu commands.
*/
#include <string.h>
#include "global.h"
#include "analyze.h"
#include "misc.h"
#include "menu_analyze.h"
#include "param.h"
/*
* This routine implements the 'read' command. It performs surface
* analysis by reading the disk. It is ok to run this command on
* mounted file systems.
*/
int
a_read()
{
/*
* The current disk must be formatted before disk analysis.
*/
if (!(cur_flags & DISK_FORMATTED)) {
err_print("Current Disk is unformatted.\n");
return (-1);
}
if (check(
"Ready to analyze (won't harm SunOS). This takes a long time, \n"
"but is interruptible with CTRL-C. Continue"))
return (-1);
}
/*
* This routine implements the 'refresh' command. It performs surface
* analysis by reading the disk then writing the same data back to the
* disk. It is ok to run this command on file systems, but not while
* they are mounted.
*/
int
{
/*
* The current disk must be formatted before disk analysis.
*/
if (!(cur_flags & DISK_FORMATTED)) {
err_print("Current Disk is unformatted.\n");
return (-1);
}
if (check(
"Ready to analyze (won't harm data). This takes a long time, \n"
"but is interruptible with CTRL-C. Continue"))
return (-1);
}
/*
* This routine implements the 'test' command. It performs surface
* analysis by reading the disk, writing then reading a pattern on the disk,
* then writing the original data back to the disk.
* It is ok to run this command on file systems, but not while they are
* mounted.
*/
int
a_test()
{
/*
* The current disk must be formatted before disk analysis.
*/
if (!(cur_flags & DISK_FORMATTED)) {
err_print("Current Disk is unformatted.\n");
return (-1);
}
if (check(
"Ready to analyze (won't harm data). This takes a long time, \n"
"but is interruptible with CTRL-C. Continue"))
return (-1);
}
/*
* This routine implements the 'write' command. It performs surface
* analysis by writing a pattern to the disk then reading it back.
* It is not ok to run this command on any data you want to keep.
*/
int
a_write()
{
/*
* The current disk must be formatted before disk analysis.
*/
if (!(cur_flags & DISK_FORMATTED)) {
err_print("Current Disk is unformatted.\n");
return (-1);
}
if (check(
"Ready to analyze (will corrupt data). This takes a long time, \n"
"but is interruptible with CTRL-C. Continue"))
return (-1);
}
/*
* This routine implements the 'compare' command. It performs surface
* analysis by writing a pattern to the disk, reading it back, then
* checking the data to be sure it's the same.
* It is not ok to run this command on any data you want to keep.
*/
int
{
/*
* The current disk must be formatted before disk analysis.
*/
if (!(cur_flags & DISK_FORMATTED)) {
err_print("Current Disk is unformatted.\n");
return (-1);
}
if (check(
"Ready to analyze (will corrupt data). This takes a long time, \n"
"but is interruptible with CTRL-C. Continue"))
return (-1);
}
/*
* This routine implements the 'print' command. It displays the data
* buffer in hexadecimal. It is only useful for checking the disk for
* a specific set of data (by reading it then printing it).
*/
int
a_print()
{
int c, one_line = 0;
/*
* If we are running out of command file, don't page the output.
* Otherwise we are running with a user. Turn off echoing of
* input characters so we can page the output.
*/
nomore++;
else {
echo_off();
charmode_on();
}
/*
* Loop through the data buffer.
*/
lines = 0;
/*
* Print the data.
*/
for (j = 0; j < 6; j++)
fmt_print("0x%08x ",
*((int *)((int *)cur_buf + i + j)));
fmt_print("\n");
lines++;
/*
* If we are paging and hit the end of a page, wait for
* the user to hit either space-bar, "q", return,
* or ctrl-C before going on.
*/
if (one_line ||
/*
* Print until first screenfull
*/
continue;
/*
* Get the next character.
*/
(void) printf("- hit space for more - ");
c = getchar();
(void) printf("\015");
one_line = 0;
/*
* Handle display one line command (return key)
*/
if (c == '\012') {
one_line++;
}
/* Handle Quit command */
if (c == 'q') {
(void) printf(
" \015");
goto PRINT_EXIT;
}
/* handle ^D */
if (c == '\004')
fullabort();
}
}
/*
* If we were doing paging, turn echoing back on.
*/
if (!nomore) {
charmode_off();
echo_on();
}
return (0);
}
/*
* This routine implements the 'setup' command. It allows the user
* to program the variables that drive surface analysis. The approach
* is to prompt the user for the value of each variable, with the current
* value as the default.
*/
int
a_setup()
{
int deflt;
/*
*/
deflt = !scan_entire;
/*
* If we are not scanning the whole disk, input the bounds of the scan.
*/
if (!scan_entire) {
}
"Enter starting block number", ':',
if (scan_upper < scan_lower)
"Enter ending block number", ':',
}
/*
* If we are not looping continuously, input the number of passes.
*/
if (!scan_loop) {
}
deflt = !scan_correct;
deflt = !scan_random;
/*
* The number of blocks per transfer is limited by the buffer
* size, or the scan boundaries, whichever is smaller.
*/
} else {
}
deflt = !option_msg;
fmt_print("\n");
return (0);
}
/*
* This routine implements the 'config' command. It simply prints out
* the values of all the variables controlling surface analysis. It
* is meant to complement the 'setup' command by allowing the user to
* check the current setup.
*/
int
a_config()
{
fmt_print(" Analyze entire disk? ");
if (!scan_entire) {
fmt_print(")\n");
}
fmt_print(" Loop continuously? ");
if (!scan_loop) {
}
fmt_print(" Repair defective blocks? ");
fmt_print(" Stop after first error? ");
fmt_print(" Use random bit patterns? ");
fmt_print(")\n");
fmt_print(" Verify media after formatting? ");
fmt_print(" Enable extended messages? ");
fmt_print(" Restore defect list? ");
fmt_print(" Restore disk label? ");
fmt_print("\n");
return (0);
}
/*
* This routine implements the 'purge' command. It purges the disk
* by writing three patterns to the disk then reading the last one back.
* It is not ok to run this command on any data you want to keep.
*/
int
a_purge()
{
int status = 0;
/*
* The current disk must be formatted before disk analysis.
*/
if (!(cur_flags & DISK_FORMATTED)) {
err_print("Current Disk is unformatted.\n");
return (-1);
}
if (scan_random) {
fmt_print("The purge command does not write random data\n");
scan_random = 0;
}
if (scan_passes < NPPATTERNS) {
fmt_print("The purge command runs for a minimum of ");
fmt_print("%d passes plus a last pass if the\n",
fmt_print("first %d passes were successful.\n",
}
}
if (check(
"Ready to purge (will corrupt data). This takes a long time, \n"
"but is interruptible with CTRL-C. Continue"))
return (-1);
return (status);
}
/*
* This routine implements the 'verify' command. It writes the disk
* by writing unique data for each block; after the write pass, it
* reads the data and verifies for correctness. Note that the entire
* disk (or the range of disk) is fully written first and then read.
* This should eliminate any caching effect on the drives.
* It is not ok to run this command on any data you want to keep.
*/
int
a_verify()
{
/*
* The current disk must be formatted before disk analysis.
*/
if (!(cur_flags & DISK_FORMATTED)) {
err_print("Current Disk is unformatted.\n");
return (-1);
}
if (scan_random) {
fmt_print("The verify command does not write random data\n");
scan_random = 0;
}
scan_passes = 2;
fmt_print("The verify command runs minimum of 2 passes, one"
" for writing and \nanother for reading and verfying."
" Resetting the number of passes to 2.\n");
}
if (check("Ready to verify (will corrupt data). This takes a long time,"
"\nbut is interruptible with CTRL-C. Continue")) {
return (-1);
}
}