rmf_menu.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
* or http://www.opensolaris.org/os/licensing.
* 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.
*/
/*
* rmf_menu.c :
* Command line options to rmformat are processed in this file.
*/
#include "rmformat.h"
#include <sys/smedia.h>
#include <priv_utils.h>
extern int32_t D_flag;
extern int32_t e_flag;
extern int32_t H_flag;
extern int32_t U_flag;
extern int32_t V_flag;
extern int32_t b_flag;
extern int32_t w_flag;
extern int32_t W_flag;
extern int32_t s_flag;
extern int32_t c_flag;
extern int32_t F_flag;
extern int32_t R_flag;
extern int32_t p_flag;
extern int32_t l_flag;
extern char *myname;
extern char *slice_file;
extern diskaddr_t repair_blk_no;
extern int32_t quick_format;
extern int32_t long_format;
extern int32_t force_format;
extern int32_t rw_protect_enable;
extern int32_t rw_protect_disable;
extern int32_t wp_enable_passwd;
extern int32_t wp_disable_passwd;
extern int32_t wp_enable;
extern int32_t wp_disable;
extern int32_t verify_write;
extern char *dev_name;
extern char *label;
extern int total_devices_found;
extern int removable_found;
char *global_intr_msg;
smmedium_prop_t med_info;
int vol_running;
extern void check_invalid_combinations();
extern void check_invalid_combinations_again(int32_t);
extern void process_options();
extern void get_passwd(struct smwp_state *wp, int32_t confirm);
extern int32_t valid_slice_file(smedia_handle_t, int32_t, char *,
struct extvtoc *);
extern void trap_SIGINT();
extern void release_SIGINT();
extern int32_t verify(smedia_handle_t handle, int32_t fd,
diskaddr_t start_sector, uint32_t nblocks,
char *buf, int32_t flag, int32_t blocksize, int32_t no_raw_rw);
extern void my_perror(char *err_string);
extern void write_default_label(smedia_handle_t, int32_t fd);
extern int find_device(int defer, char *tmpstr);
void overwrite_metadata(int32_t fd, smedia_handle_t handle);
int32_t write_sunos_label(int32_t fd, int32_t media_type);
int32_t my_open(char *device_name, int32_t flags);
int32_t check_and_unmount_vold(char *device_name, int32_t flag);
int32_t check_and_unmount_scsi(char *device_name, int32_t flag);
int32_t check_and_unmount_floppy(int32_t fd, int32_t flag);
int32_t get_confirmation(void);
static void process_F_flag(smedia_handle_t handle, int32_t fd);
static void process_w_flag(smedia_handle_t handle);
static void process_W_flag(smedia_handle_t handle);
static void process_R_flag(smedia_handle_t handle);
void process_p_flag(smedia_handle_t handle, int32_t fd);
static void process_c_flag(smedia_handle_t handle);
static void process_V_flag(smedia_handle_t handle, int32_t fd);
static void process_s_flag(smedia_handle_t, int32_t fd);
static void process_e_flag(smedia_handle_t handle);
static void process_H_flag(smedia_handle_t handle, int32_t fd);
static void process_D_flag(smedia_handle_t handle, int32_t fd);
static void process_b_flag(int32_t fd);
static void process_l_flag(void);
void
process_options()
{
int32_t fd;
smedia_handle_t handle;
int32_t m_scsi_umount = 0;
int32_t m_flp_umount = 0;
int32_t v_device_umount = 0;
int32_t umount_required = 0;
int32_t removable;
int32_t umount_failed = 0;
struct dk_minfo media;
check_invalid_combinations();
if (l_flag && !dev_name) {
process_l_flag();
return;
}
if (U_flag) {
if (!(F_flag || H_flag || D_flag)) {
F_flag = 1;
long_format = 1;
}
}
if (F_flag || w_flag || W_flag || R_flag || D_flag || H_flag ||
V_flag || c_flag || b_flag || s_flag || e_flag) {
umount_required = 1;
}
fd = my_open(dev_name, O_RDONLY|O_NDELAY);
if (fd < 0) {
PERROR("Could not open device");
(void) close(fd);
exit(1);
}
if (ioctl(fd, DKIOCREMOVABLE, &removable) < 0) {
PERROR("DKIOCREMOVABLE ioctl failed");
(void) close(fd);
exit(1);
}
if (!removable) {
(void) fprintf(stderr,
gettext("Not a removable media device\n"));
(void) close(fd);
exit(1);
}
if (ioctl(fd, DKIOCGMEDIAINFO, &media) < 0) {
(void) fprintf(stderr,
gettext("No media in specified device\n"));
(void) close(fd);
exit(1);
}
/* Check if volume manager has mounted this */
if (umount_required) {
v_device_umount = check_and_unmount_vold(dev_name, U_flag);
if (v_device_umount != 1) {
m_scsi_umount = check_and_unmount_scsi(dev_name,
U_flag);
if (m_scsi_umount != 1) {
m_flp_umount = check_and_unmount_floppy(fd,
U_flag);
if (m_flp_umount != 1) {
umount_failed = 1;
}
}
}
}
if (umount_required && U_flag && umount_failed) {
if (v_device_umount || m_scsi_umount || m_flp_umount) {
(void) fprintf(stderr,
gettext("Could not unmount device.\n"));
(void) close(fd);
exit(1);
}
}
if (umount_required && !U_flag) {
if (v_device_umount || m_scsi_umount || m_flp_umount) {
(void) fprintf(stderr, gettext("Device mounted.\n"));
(void) fprintf(stderr,
gettext("Requested operation can not be \
performed on a mounted device.\n"));
(void) close(fd);
exit(1);
}
}
/* register the fd with the libsmedia */
handle = smedia_get_handle(fd);
if (handle == NULL) {
(void) fprintf(stderr,
gettext("Failed to get libsmedia handle.\n"));
(void) close(fd);
exit(1);
}
if (smedia_get_medium_property(handle, &med_info) < 0) {
(void) fprintf(stderr,
gettext("Get medium property failed \n"));
(void) smedia_release_handle(handle);
(void) close(fd);
exit(1);
}
DPRINTF1("media type %x\n", med_info.sm_media_type);
DPRINTF1("media block size %x\n", med_info.sm_blocksize);
DPRINTF1("media capacity %u\n", (uint32_t)med_info.sm_capacity);
DPRINTF3("media cyl %d head %d sect %d\n",
med_info.sm_pcyl, med_info.sm_nhead, med_info.sm_nsect);
check_invalid_combinations_again(med_info.sm_media_type);
/*
* Special handling for pcmcia, sometimes open the file in
* read-write mode.
*/
if (med_info.sm_media_type == SM_PCMCIA_MEM) {
if (F_flag || H_flag || D_flag || (V_flag && verify_write)) {
(void) close(fd);
DPRINTF("Reopening device\n");
fd = my_open(dev_name, O_RDWR|O_NDELAY);
if (fd < 0) {
PERROR("Could not open device");
(void) smedia_release_handle(handle);
(void) close(fd);
exit(1);
}
}
}
if (med_info.sm_media_type == SM_PCMCIA_ATA) {
if (V_flag || c_flag) {
(void) fprintf(stderr,
gettext("Option not supported on PC ATA cards\n"));
(void) smedia_release_handle(handle);
(void) close(fd);
exit(1);
}
if (F_flag) {
/* same text as used by the format command */
(void) fprintf(stderr,
gettext("Cannot format this drive. Please use your \
Manufacturer supplied formatting utility.\n"));
(void) smedia_release_handle(handle);
(void) close(fd);
exit(1);
}
}
if (F_flag)
process_F_flag(handle, fd);
if (w_flag)
process_w_flag(handle);
if (W_flag)
process_W_flag(handle);
if (R_flag)
process_R_flag(handle);
if (p_flag)
process_p_flag(handle, fd);
if (D_flag)
process_D_flag(handle, fd);
if (H_flag)
process_H_flag(handle, fd);
if (V_flag)
process_V_flag(handle, fd);
if (c_flag)
process_c_flag(handle);
if (b_flag)
process_b_flag(fd);
if (s_flag)
process_s_flag(handle, fd);
if (e_flag)
process_e_flag(handle);
if (l_flag) {
process_l_flag();
}
(void) smedia_release_handle(handle);
(void) close(fd);
}
/*
* This routine handles the F_flag.
* This options should not be used for floppy. However,
* if this option is used for floppy, the option will
* be forced to SM_FORMAT_HD and smedia_format is called.
* Note that smedia_format is a blocked mode format and it
* returns only after the complete formatting is over.
*/
static void
process_F_flag(smedia_handle_t handle, int32_t fd)
{
uint32_t format_flag;
int32_t old_per = 0;
int32_t new_per, ret_val;
if (force_format) {
(void) fprintf(stderr,
gettext("Formatting disk.\n"));
} else {
(void) fprintf(stderr,
gettext("Formatting will erase all the data on disk.\n"));
if (!get_confirmation())
return;
}
if (quick_format)
format_flag = SM_FORMAT_QUICK;
else if (long_format)
format_flag = SM_FORMAT_LONG;
else if (force_format)
format_flag = SM_FORMAT_FORCE;
if (med_info.sm_media_type == SM_FLOPPY)
format_flag = SM_FORMAT_HD;
if ((med_info.sm_media_type != SM_FLOPPY) &&
(med_info.sm_media_type != SM_PCMCIA_MEM) &&
(med_info.sm_media_type != SM_SCSI_FLOPPY)) {
global_intr_msg = "Interrupting format may render the \
medium useless";
} else {
global_intr_msg = "";
}
trap_SIGINT();
if (smedia_format(handle, format_flag, SM_FORMAT_IMMEDIATE) != 0) {
if (errno == EINVAL) {
(void) fprintf(stderr, gettext("Format failed.\n"));
(void) fprintf(stderr, gettext("The medium may not \
be compatible for format operation.\n"));
(void) fprintf(stderr, gettext("read/write surface \
scan may be used to get the effect of formatting.\n"));
} else {
PERROR("Format failed");
}
(void) smedia_release_handle(handle);
(void) close(fd);
exit(1);
}
/* CONSTCOND */
while (1) {
ret_val = smedia_check_format_status(handle);
if (ret_val == -1) {
if (errno != ENOTSUP) {
PERROR("Format failed");
(void) smedia_release_handle(handle);
(void) close(fd);
exit(1);
} else {
/* Background formatting is not supported */
break;
}
}
if (ret_val == 100) {
(void) printf("\n");
(void) fflush(stdout);
break;
}
new_per = (ret_val * 80)/100;
while (new_per >= old_per) {
(void) printf(".");
(void) fflush(stdout);
old_per++;
}
(void) sleep(6);
}
if ((med_info.sm_media_type == SM_FLOPPY) ||
(med_info.sm_media_type == SM_PCMCIA_MEM) ||
(med_info.sm_media_type == SM_SCSI_FLOPPY)) {
(void) write_sunos_label(fd, med_info.sm_media_type);
} else {
/*
* Iomega drives don't destroy the data in quick format.
* Do a best effort write to first 1024 sectors.
*/
if (quick_format)
overwrite_metadata(fd, handle);
(void) write_default_label(handle, fd);
}
release_SIGINT();
}
/*
* List removable devices.
*/
static void
process_l_flag()
{
int retry;
int removable;
int total_devices_found_last_time;
int defer = 0;
char *tmpstr;
#define MAX_RETRIES_FOR_SCANNING 3
vol_running = volmgt_running();
if (vol_running)
defer = 1;
(void) printf(gettext("Looking for devices...\n"));
total_devices_found_last_time = 0;
/*
* Strip out any leading path. For example, /dev/rdsk/c3t0d0s2
* will result in tmpstr = c3t0d0s2. dev_name is given as input
* argument.
*/
if (dev_name) {
if ((tmpstr = strrchr(dev_name, '/')) != NULL) {
tmpstr += sizeof (char);
} else {
tmpstr = dev_name;
}
}
for (retry = 0; retry < MAX_RETRIES_FOR_SCANNING; retry++) {
removable = find_device(defer, tmpstr);
if (removable == -1)
break;
/*
* We'll do a small sleep and retry the command if volume
* manager is running and no removable devices are found.
* This is because the device may be busy.
*/
if (defer || (vol_running && (removable == 0))) {
if ((total_devices_found == 0) ||
(total_devices_found !=
total_devices_found_last_time)) {
total_devices_found_last_time =
total_devices_found;
(void) sleep(2);
} else {
/* Do the printing this time */
defer = 0;
removable_found = 0;
}
} else
break;
}
if (removable_found == 0)
(void) printf(gettext("No removables found.\n"));
}
/*
* The following three routines handle the write protect
* options. These options are mostly Iomega ZIP/Jaz centric.
* The following options are allowed :
* No write protect <=> write protect without passwd : use -w flag
* from any state to WP with passwd : use -W flag
* from WP with passwd to no write protect : use -W flag
* from any state to RWP with passwd : use -R flag
* from RWP with passwd to no write protect : use -R flag
*
* The following transitions is not allowed
* WP with passwd or RWP to WP without passwd.
*/
static void
process_w_flag(smedia_handle_t handle)
{
int32_t rval;
int32_t med_status;
struct smwp_state wps;
if ((rval = smedia_get_protection_status((handle), &wps)) < 0) {
(void) fprintf(stderr,
gettext("Could not get medium status \n"));
return;
}
med_status = wps.sm_new_state;
wps.sm_version = SMWP_STATE_V_1;
if (wp_enable) { /* Enable write protect no password */
switch (med_status) {
case SM_WRITE_PROTECT_DISABLE :
wps.sm_new_state =
SM_WRITE_PROTECT_NOPASSWD;
wps.sm_passwd_len = 0;
rval = smedia_set_protection_status(handle,
&wps);
if (rval == -1)
PERROR(WP_ERROR);
break;
case SM_WRITE_PROTECT_NOPASSWD :
(void) fprintf(stderr, gettext(WP_MSG_0));
break;
case SM_WRITE_PROTECT_PASSWD :
(void) fprintf(stderr, gettext(WP_MSG_1));
break;
case SM_READ_WRITE_PROTECT :
(void) fprintf(stderr, gettext(WP_MSG_2));
break;
case SM_STATUS_UNKNOWN :
default :
(void) fprintf(stderr, gettext(WP_UNKNOWN));
break;
}
} else if (wp_disable) {
switch (med_status) {
case SM_WRITE_PROTECT_NOPASSWD :
wps.sm_new_state =
SM_WRITE_PROTECT_DISABLE;
wps.sm_passwd_len = 0;
rval = smedia_set_protection_status(handle,
&wps);
if (rval == -1)
PERROR(WP_ERROR);
break;
case SM_WRITE_PROTECT_DISABLE :
(void) fprintf(stderr, gettext(WP_MSG_3));
break;
case SM_WRITE_PROTECT_PASSWD :
(void) fprintf(stderr, gettext(WP_MSG_1));
break;
case SM_READ_WRITE_PROTECT :
(void) fprintf(stderr, gettext(WP_MSG_2));
break;
case SM_STATUS_UNKNOWN :
default :
(void) fprintf(stderr, gettext(WP_UNKNOWN));
break;
}
}
}
static void
process_W_flag(smedia_handle_t handle)
{
int32_t rval;
int32_t med_status;
struct smwp_state wps;
DPRINTF("Write protect with password\n");
if ((rval = smedia_get_protection_status((handle), &wps)) < 0) {
(void) fprintf(stderr,
gettext("Could not get medium status \n"));
return;
}
med_status = wps.sm_new_state;
wps.sm_version = SMWP_STATE_V_1;
if (wp_enable_passwd) { /* Enable write protect */
switch (med_status) {
case SM_WRITE_PROTECT_DISABLE :
case SM_WRITE_PROTECT_NOPASSWD :
DPRINTF("Getting passwd\n");
get_passwd(&wps, 1);
wps.sm_new_state =
SM_WRITE_PROTECT_PASSWD;
rval = smedia_set_protection_status(handle,
&wps);
if (rval == -1) {
PERROR(WP_ERROR);
}
break;
case SM_READ_WRITE_PROTECT :
(void) fprintf(stderr, gettext(WP_MSG_4));
(void) fprintf(stderr, gettext(WP_MSG_5));
get_passwd(&wps, 0);
wps.sm_new_state =
SM_WRITE_PROTECT_PASSWD;
rval = smedia_set_protection_status(handle,
&wps);
if (rval == -1) {
if (errno == EACCES) {
(void) fprintf(stderr,
gettext(WP_MSG_10));
} else {
PERROR(WP_ERROR);
}
}
break;
case SM_WRITE_PROTECT_PASSWD :
(void) fprintf(stderr, gettext(WP_MSG_6));
break;
case SM_STATUS_UNKNOWN :
default :
(void) fprintf(stderr,
gettext(WP_UNKNOWN));
break;
}
} else if (wp_disable_passwd) {
switch (med_status) {
case SM_WRITE_PROTECT_PASSWD :
get_passwd(&wps, 0);
wps.sm_new_state =
SM_WRITE_PROTECT_DISABLE;
rval = smedia_set_protection_status(handle,
&wps);
if (rval == -1) {
if (errno == EACCES) {
(void) fprintf(stderr,
gettext(WP_MSG_10));
} else {
PERROR(WP_ERROR);
}
}
break;
case SM_READ_WRITE_PROTECT :
(void) fprintf(stderr, gettext(WP_MSG_2));
break;
case SM_WRITE_PROTECT_NOPASSWD :
(void) fprintf(stderr, gettext(WP_MSG_7));
break;
case SM_WRITE_PROTECT_DISABLE :
(void) fprintf(stderr, gettext(WP_MSG_3));
break;
case SM_STATUS_UNKNOWN :
default :
(void) fprintf(stderr, gettext(WP_UNKNOWN));
break;
}
}
}
static void
process_R_flag(smedia_handle_t handle)
{
int32_t rval;
int32_t med_status;
struct smwp_state wps;
DPRINTF("Read Write protect \n");
if ((rval = smedia_get_protection_status((handle), &wps)) < 0) {
(void) fprintf(stderr,
gettext("Could not get medium status \n"));
return;
}
med_status = wps.sm_new_state;
wps.sm_version = SMWP_STATE_V_1;
if (rw_protect_enable) { /* Enable write protect */
switch (med_status) {
case SM_WRITE_PROTECT_DISABLE :
case SM_WRITE_PROTECT_NOPASSWD :
DPRINTF("Getting passwd\n");
get_passwd(&wps, 1);
wps.sm_new_state =
SM_READ_WRITE_PROTECT;
rval = smedia_set_protection_status(handle,
&wps);
if (rval == -1)
PERROR(WP_ERROR);
break;
case SM_WRITE_PROTECT_PASSWD :
(void) fprintf(stderr, gettext(WP_MSG_8));
(void) fprintf(stderr, gettext(WP_MSG_9));
get_passwd(&wps, 0);
wps.sm_new_state =
SM_READ_WRITE_PROTECT;
rval = smedia_set_protection_status(handle,
&wps);
if (rval == -1) {
if (errno == EACCES) {
(void) fprintf(stderr,
gettext(WP_MSG_10));
} else {
PERROR(WP_ERROR);
}
}
break;
case SM_READ_WRITE_PROTECT :
(void) fprintf(stderr, gettext(WP_MSG_4));
break;
case SM_STATUS_UNKNOWN :
default :
(void) fprintf(stderr, gettext(WP_UNKNOWN));
break;
}
} else if (rw_protect_disable) {
switch (med_status) {
case SM_READ_WRITE_PROTECT :
case SM_STATUS_UNKNOWN :
get_passwd(&wps, 0);
wps.sm_new_state =
SM_WRITE_PROTECT_DISABLE;
rval = smedia_set_protection_status(handle,
&wps);
if (rval == -1) {
if (errno == EACCES) {
(void) fprintf(stderr,
gettext(WP_MSG_10));
} else {
PERROR(WP_ERROR);
}
}
break;
case SM_WRITE_PROTECT_PASSWD :
(void) fprintf(stderr, gettext(WP_MSG_1));
break;
case SM_WRITE_PROTECT_NOPASSWD :
(void) fprintf(stderr, gettext(WP_MSG_7));
break;
case SM_WRITE_PROTECT_DISABLE :
(void) fprintf(stderr, gettext(WP_MSG_3));
break;
default :
(void) fprintf(stderr, gettext(WP_UNKNOWN));
break;
}
}
}
void
process_p_flag(smedia_handle_t handle, int32_t fd)
{
int32_t med_status;
smwp_state_t wps;
med_status = smedia_get_protection_status((handle), &wps);
DPRINTF("Could not get medium status \n");
/*
* Workaround in case mode sense fails.
*
* Also, special handling for PCMCIA. PCMCIA does not have any
* ioctl to find out the write protect status. So, open the
* device with O_RDWR. If it passes, it is not write protected,
* otherwise it is write protected.
* If it fails, reopen with O_RDONLY, may be some other
* operation can go through.
*/
if ((med_status < 0) || (med_info.sm_media_type == SM_PCMCIA_MEM) ||
(med_info.sm_media_type == SM_PCMCIA_ATA)) {
(void) close(fd);
DPRINTF("Reopening device for -p option\n");
fd = my_open(dev_name, O_RDONLY|O_NDELAY);
if (fd < 0) {
if (p_flag) {
PERROR("Could not open device");
(void) smedia_release_handle(handle);
(void) close(fd);
exit(1);
} else {
(void) fprintf(stderr,
gettext("<Unknown>\n"));
(void) smedia_release_handle(handle);
(void) close(fd);
return;
}
fd = my_open(dev_name, O_RDWR|O_NDELAY);
if (fd < 0) {
(void) fprintf(stderr,
gettext("Medium is write protected.\n"));
}
} else { /* Open succeeded */
(void) fprintf(stderr,
gettext("Medium is not write protected.\n"));
}
return;
}
med_status = wps.sm_new_state;
switch (med_status) {
case SM_READ_WRITE_PROTECT :
(void) fprintf(stderr,
gettext("Medium is read-write protected.\n"));
break;
case SM_WRITE_PROTECT_PASSWD :
(void) fprintf(stderr,
gettext("Medium is write protected with password.\n"));
break;
case SM_WRITE_PROTECT_NOPASSWD :
(void) fprintf(stderr,
gettext("Medium is write protected.\n"));
break;
case SM_WRITE_PROTECT_DISABLE :
(void) fprintf(stderr,
gettext("Medium is not write protected.\n"));
break;
case SM_STATUS_UNKNOWN :
default:
(void) fprintf(stderr,
gettext("Unknown write protect status.\n"));
break;
}
}
static void
process_c_flag(smedia_handle_t handle)
{
char error_string[256];
if (smedia_reassign_block(handle, repair_blk_no) != 0) {
(void) snprintf(error_string, 255,
gettext("Could not repair block no %llu"), repair_blk_no);
PERROR(error_string);
return;
}
}
/*
* This routine handles the -V (verify) option.
* There can be devices without rw_read option. If the raw_read
* and raw_write are not supported by the interface, then read and
* write system calls are used. It is assumed that either both
* raw_read and raw_write are supported or both are unsupported.
*/
static void
process_V_flag(smedia_handle_t handle, int32_t fd)
{
int32_t ret;
uint32_t j;
diskaddr_t bn;
char *read_buf, *write_buf;
int32_t old_per = 0;
int32_t new_per;
int32_t no_raw_rw = 0;
int32_t verify_size;
diskaddr_t capacity;
int32_t blocksize;
DPRINTF("ANALYSE MEDIA \n");
ret = smedia_get_medium_property(handle, &med_info);
if (ret == -1) {
DPRINTF("get_media_info failed\n");
return;
}
DPRINTF1("media_type %d\n", med_info.sm_media_type);
DPRINTF1("sector_size %d\n", med_info.sm_blocksize);
DPRINTF1("num_sectors %u\n", (uint32_t)med_info.sm_capacity);
DPRINTF1("nsect %d\n", med_info.sm_nsect);
blocksize = med_info.sm_blocksize;
capacity = (uint32_t)med_info.sm_capacity;
verify_size = (med_info.sm_nsect > 64) ? 64 : med_info.sm_nsect;
read_buf = (char *)malloc(blocksize * verify_size);
if (read_buf == NULL) {
DPRINTF("Could not allocate memory\n");
return;
}
write_buf = (char *)malloc(blocksize * verify_size);
if (write_buf == NULL) {
DPRINTF("Could not allocate memory\n");
free(read_buf);
return;
}
if (!verify_write) {
DPRINTF("Non-destructive verify \n");
for (bn = 0; bn < (uint32_t)med_info.sm_capacity;
bn += verify_size) {
new_per = (bn * 80)/(uint32_t)med_info.sm_capacity;
if (new_per >= old_per) {
(void) printf(".");
(void) fflush(stdout);
old_per++;
}
DPRINTF2("Reading %d blks starting at %llu\n",
verify_size, bn);
ret = verify(handle, fd, bn, verify_size, read_buf,
VERIFY_READ, blocksize, no_raw_rw);
if ((ret == -1) && (errno == ENOTSUP)) {
no_raw_rw = 1;
ret = verify(handle, fd, bn, verify_size,
read_buf,
VERIFY_READ, blocksize, no_raw_rw);
capacity = (diskaddr_t)med_info.sm_pcyl *
med_info.sm_nhead * med_info.sm_nsect;
}
if (ret != 0) {
for (j = 0; j < verify_size; j++) {
if ((bn + j) >= capacity)
return;
DPRINTF2(
"Reading %d blks starting "
"at %llu\n", 1, bn + j);
ret = verify(handle, fd, bn + j, 1,
read_buf,
VERIFY_READ, blocksize,
no_raw_rw);
if (ret == -1) {
(void) printf(
"Bad block %llu\n",
bn + j);
}
}
}
}
} else {
DPRINTF("Destrutive verify \n");
for (bn = 0; bn < (uint32_t)med_info.sm_capacity;
bn += verify_size) {
new_per = (bn * 80)/(uint32_t)med_info.sm_capacity;
if (new_per >= old_per) {
(void) printf(".");
(void) fflush(stdout);
old_per++;
}
for (j = 0; j < blocksize * verify_size; j++) {
write_buf[j] = (bn | j) & 0xFF;
}
DPRINTF2("Writing %d blks starting at %llu\n",
verify_size, bn);
ret = verify(handle, fd, bn, verify_size, write_buf,
VERIFY_WRITE, blocksize, no_raw_rw);
if (ret != 0) {
for (j = 0; j < verify_size; j++) {
if ((bn + j) >= capacity)
break;
DPRINTF2(
"Writing %d blks starting "
"at %llu\n", 1, bn + j);
ret = verify(handle, fd, bn + j, 1,
write_buf,
VERIFY_WRITE, blocksize,
no_raw_rw);
if (ret == -1) {
(void) printf(
"Bad block %llu\n", bn + j);
}
}
}
DPRINTF2("Read after write %d blks starting at %llu\n",
verify_size, bn);
ret = verify(handle, fd, bn, verify_size,
read_buf, VERIFY_READ, blocksize, no_raw_rw);
if (ret != 0) {
for (j = 0; j < verify_size; j++) {
if ((bn + j) >= capacity)
return;
DPRINTF2(
"Read after write %d blks "
"starting at %llu\n", 1, bn + j);
ret = verify(handle, fd, bn + j, 1,
read_buf, VERIFY_READ,
blocksize, no_raw_rw);
if (ret == -1) {
(void) printf(
"Bad block %llu\n", bn + j);
}
}
}
}
}
}
static void
process_s_flag(smedia_handle_t handle, int32_t fd)
{
int32_t i, ret;
struct extvtoc v_toc, t_vtoc;
if (valid_slice_file(handle, fd, slice_file, &v_toc)) {
(void) smedia_release_handle(handle);
(void) close(fd);
exit(1);
}
(void) memset(&t_vtoc, 0, sizeof (t_vtoc));
t_vtoc.v_nparts = V_NUMPAR;
t_vtoc.v_sanity = VTOC_SANE;
t_vtoc.v_version = V_VERSION;
t_vtoc.v_sectorsz = DEV_BSIZE;
/* Get existing Vtoc, don't bother if it fails. */
/* Turn on privileges. */
(void) __priv_bracket(PRIV_ON);
(void) read_extvtoc(fd, &t_vtoc);
/* Turn off privileges. */
(void) __priv_bracket(PRIV_OFF);
for (i = 0; i < V_NUMPAR; i++) {
t_vtoc.v_part[i].p_start = v_toc.v_part[i].p_start;
t_vtoc.v_part[i].p_size = v_toc.v_part[i].p_size;
t_vtoc.v_part[i].p_tag = v_toc.v_part[i].p_tag;
t_vtoc.v_part[i].p_flag = v_toc.v_part[i].p_flag;
}
errno = 0;
/* Turn on privileges. */
(void) __priv_bracket(PRIV_ON);
ret = write_extvtoc(fd, &t_vtoc);
/* Turn off privileges. */
(void) __priv_bracket(PRIV_OFF);
if (ret < 0) {
#ifdef sparc
PERROR("write VTOC failed");
DPRINTF1("Errno = %d\n", errno);
#else /* i386 */
if (errno == EIO) {
PERROR("No Solaris partition, eject & retry");
DPRINTF1("Errno = %d\n", errno);
} else {
PERROR("write VTOC failed");
DPRINTF1("Errno = %d\n", errno);
}
#endif
}
}
static void
process_e_flag(smedia_handle_t handle)
{
if (smedia_eject(handle) < 0) {
PERROR("Eject failed");
}
}
static void
process_H_flag(smedia_handle_t handle, int32_t fd)
{
uint32_t cyl, head;
int32_t old_per = 0;
int32_t new_per;
(void) fprintf(stderr,
gettext("Formatting will erase all the data on disk.\n"));
if (!get_confirmation())
return;
for (cyl = 0; cyl < med_info.sm_pcyl; cyl++) {
for (head = 0; head < med_info.sm_nhead; head++) {
if (smedia_format_track(handle, cyl, head, SM_FORMAT_HD)
< 0) {
PERROR("Format failed");
return;
}
}
new_per = (cyl * 80)/med_info.sm_pcyl;
while (new_per >= old_per) {
(void) printf(".");
(void) fflush(stdout);
old_per++;
}
}
(void) write_sunos_label(fd, med_info.sm_media_type);
}
static void
process_D_flag(smedia_handle_t handle, int32_t fd)
{
uint32_t cyl, head;
int32_t old_per = 0;
int32_t new_per;
(void) fprintf(stderr,
gettext("Formatting will erase all the data on disk.\n"));
if (!get_confirmation())
return;
for (cyl = 0; cyl < med_info.sm_pcyl; cyl++) {
for (head = 0; head < med_info.sm_nhead; head++) {
if (smedia_format_track(handle, cyl, head, SM_FORMAT_DD)
< 0) {
PERROR("Format failed");
return;
}
}
new_per = (cyl * 80)/med_info.sm_pcyl;
while (new_per >= old_per) {
(void) printf(".");
(void) fflush(stdout);
old_per++;
}
}
(void) write_sunos_label(fd, med_info.sm_media_type);
}
/*
* This routine handles the -b (label) option.
* Please note that, this will fail if there is no valid vtoc is
* there on the medium and the vtoc is not faked.
*/
static void
process_b_flag(int32_t fd)
{
int32_t ret, nparts;
struct extvtoc v_toc;
struct dk_gpt *vtoc64;
/* For EFI disks. */
if (efi_type(fd)) {
if (efi_alloc_and_read(fd, &vtoc64) < 0) {
/*
* If reading the vtoc failed, try to
* auto-sense the disk configuration.
*/
if (efi_auto_sense(fd, &vtoc64) < 0) {
(void) fprintf(stderr,
gettext("Could not write label.\n"));
return;
}
}
for (nparts = 0; nparts < vtoc64->efi_nparts;
nparts++) {
if (vtoc64->efi_parts[nparts].p_tag ==
V_RESERVED) {
if (vtoc64->efi_parts[nparts].p_name) {
(void) strncpy(
vtoc64->efi_parts[nparts].p_name, label,
EFI_PART_NAME_LEN);
}
break;
}
}
if (efi_write(fd, vtoc64) != 0) {
(void) efi_err_check(vtoc64);
(void) fprintf(stderr,
gettext("Could not write label.\n"));
}
return;
}
/* Get existing Vtoc */
/* Turn on privileges. */
(void) __priv_bracket(PRIV_ON);
ret = read_extvtoc(fd, &v_toc);
/* Turn off privileges */
(void) __priv_bracket(PRIV_OFF);
if (ret < 0) {
#ifdef sparc
PERROR("read VTOC failed");
DPRINTF1("Errno = %d\n", errno);
#else /* i386 */
if (errno == EIO) {
PERROR("No Solaris partition, eject & retry");
DPRINTF1("Errno = %d\n", errno);
} else {
PERROR("read VTOC failed");
DPRINTF1("Errno = %d\n", errno);
}
#endif
return;
}
(void) strncpy(v_toc.v_volume, label, LEN_DKL_VVOL);
/* Turn on the privileges. */
(void) __priv_bracket(PRIV_ON);
ret = write_extvtoc(fd, &v_toc);
/* Turn off the privileges. */
(void) __priv_bracket(PRIV_OFF);
if (ret < 0) {
#ifdef sparc
PERROR("write VTOC failed");
DPRINTF1("Errno = %d\n", errno);
#else /* i386 */
if (errno == EIO) {
PERROR("No Solaris partition, eject & retry");
DPRINTF1("Errno = %d\n", errno);
} else {
PERROR("write VTOC failed");
DPRINTF1("Errno = %d\n", errno);
}
#endif
}
}