/*
* 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.
*/
/*
* rmf_misc.c :
* Miscelleneous routines for rmformat.
*/
#include <stdio.h>
#include <volmgt.h>
#include <ctype.h>
#include <signal.h>
#include <dirent.h>
#include <priv_utils.h>
#include <stdarg.h>
#include "rmformat.h"
/*
* Definitions.
*/
int total_devices_found = 0;
int removable_found = 0;
extern char *global_intr_msg;
extern int vol_running;
extern char *dev_name;
/*
* ON-private functions from libvolmgt
*/
int _dev_mounted(char *path);
/*
* Function prototypes.
*/
static int my_volrmmount(char *real_name);
static char *get_physical_name(char *path);
struct uscsi_cmd *get_uscsi_cmd(void);
void
{
int error_no;
if (errno == 0)
return;
perror("");
}
{
char c;
c = getchar();
if (c == 'y' || c == 'Y')
return (1);
else if (c == 'n' || c == 'N')
return (0);
else {
return (0);
}
}
void
{
char *buf;
} else {
}
/* Turn echoing off if it is on now. */
PERROR("Echo off ioctl failed");
exit(1);
}
/* echo_off = tcsetattr(fileno(in), TCSAFLUSH, &tio) == 0; */
}
/* CONSTCOND */
while (1) {
(void) fputs(
gettext("Please enter password (32 chars maximum):"),
out);
PERROR("Error reading password");
continue;
}
len--; /* To offset the \n */
gettext("Invalid length of password \n"));
continue;
}
if (!confirm)
break;
} else {
break;
}
}
/* Restore echoing. */
if (echo_off)
}
{
char *real_name;
char *nm;
int nl;
if (volmgt_running() == 0) {
DPRINTF("Vold not running\n");
return (0);
}
DPRINTF("path not managed\n");
} else {
}
return (-1);
/*
* To find out whether the device has been mounted by
* volume manager...
*
* Convert the real name to a block device address.
* Do a partial match with the mnttab entries.
* Make sure the match is in the beginning to avoid if
* anybody puts a label similiar to volume manager path names.
* Then use "volrmmount -e <dev_name>" if -U flag is set.
*/
return (0);
} else {
}
if (ret_val < 0) {
PERROR("Could not stat");
return (-1);
}
return (-1);
}
PERROR("malloc failed");
return (-1);
}
errno = 0;
if (errno != 0) {
PERROR("Error with mnttab");
return (-1);
}
/* Is it a probable entry? */
mntp->mnt_special) {
/* Skip to next entry */
continue;
} else {
ret_val = 1;
break;
}
}
if (ret_val == 1) {
if (flag) {
if (my_volrmmount(real_name) < 0) {
ret_val = -1;
}
} else {
ret_val = -1;
}
}
return (ret_val);
}
/*
* This routine checks if a device has mounted partitions. The
* be used for SCSI and PCMCIA cards.
* Returns
* 0 : if not mounted
* 1 : if successfully unmounted
* -1 : Any error or umount failed
*/
{
int32_t i, j;
/*
* If the device name is not a character special, anyway we
* can not progress further
*/
return (0);
return (-1);
}
PERROR("malloc failed");
return (-1);
}
PERROR("malloc failed");
return (-1);
}
/* Try all the partitions */
errno = 0;
if (errno != 0) {
PERROR("Error with mnttab");
return (-1);
}
/* Is it a probable entry? */
/* Skip to next entry */
continue;
}
for (i = 0; i < NDKMAP; i++) {
/* Check for ufs style mount devices */
"%s%d", tmp_name, i);
if (flag) {
return (-1);
}
unmounted = 1;
} else {
return (-1);
}
/* Skip to next entry */
continue;
}
/* Try for :1 -> :24 for pcfs */
for (j = 1; j < 24; j++) {
"%s%d:%d", tmp_name, i, j);
block_dev_name) == 0) {
if (flag) {
< 0) {
return (-1);
}
unmounted = 1;
} else {
return (-1);
}
/* Skip to next entry */
continue;
}
block_dev_name) == 0) {
if (flag) {
< 0) {
return (-1);
}
unmounted = 1;
} else {
return (-1);
}
/* Skip to next entry */
continue;
}
}
}
}
if (unmounted)
return (1);
return (0);
}
/*
* This routine checks if a device has mounted partitions. The
* be used for Floppy controllers
* Returns
* 0 : if not mounted
* 1 : if successfully unmounted
* -1 : Any error or unmount failed
*/
{
return (-1);
}
exit(3);
}
continue;
}
/*
* Attempt to open the device. If it fails, skip it.
*/
/* Turn on the privileges. */
(void) __priv_bracket(PRIV_ON);
/* Turn off the privileges. */
(void) __priv_bracket(PRIV_OFF);
if (mfd < 0) {
continue;
}
/*
* Must be a character device
*/
continue;
}
/*
* Attempt to read the configuration info on the disk.
*/
continue;
}
/*
* Finished with the opened device
*/
/*
* If it's not the disk we're interested in, it doesn't apply.
*/
continue;
}
/*
* It's a mount on the disk we're checking. If we are
* checking whole disk, then we found trouble. We can
* quit searching.
*/
if (flag) {
return (-1);
}
found = 1;
} else {
return (-1);
}
}
return (found);
}
{
char *real_name;
char *nm;
DPRINTF("path not managed\n");
} else {
}
return (-1);
if (ret_val < 0) {
PERROR("Could not stat");
return (-1);
}
/*
* Open the directory and look for the
* first non '.' entry.
* Since raw_read and raw_writes are used, we don't
* need to access the backup slice.
* For PCMCIA Memory cards, raw_read and raw_writes are
* not supported, but that is not a problem as, only slice2
* is allowed on PCMCIA memory cards.
*/
/*
* First make sure we are operating with a /vol/....
* Otherwise it can dangerous,
* We should not look into the directory contents here.
*/
!= 0) {
is not a raw device.\n"));
exit(1);
}
/* Turn on the privileges. */
(void) __priv_bracket(PRIV_ON);
/* Turn off the privileges. */
(void) __priv_bracket(PRIV_OFF);
return (-1);
}
/* Turn on the privileges. */
(void) __priv_bracket(PRIV_ON);
have_read_priv = 1;
/* Turn off the privileges. */
(void) __priv_bracket(PRIV_OFF);
have_read_priv = 0;
break;
}
/* Turn on the privileges. */
(void) __priv_bracket(PRIV_ON);
have_read_priv = 1;
}
if (have_read_priv) {
/* drop the file_dac_read privilege */
(void) __priv_bracket(PRIV_OFF);
have_read_priv = 0;
}
}
if (volmgt_running() == 0) {
/* Turn on privileges. */
(void) __priv_bracket(PRIV_ON);
have_read_priv = 1;
}
if (have_read_priv) {
/* Turn off privileges. */
(void) __priv_bracket(PRIV_OFF);
have_read_priv = 0;
}
return (fd);
}
{
while (*tmp_ptr) {
tmp_ptr++;
else {
base = 16;
break;
}
}
if (base == 16) {
return (-1);
}
return (-1);
}
tmp_ptr++;
while (*tmp_ptr) {
tmp_ptr++;
else {
return (-1);
}
}
}
return (ret_val);
}
{
/* Initialize the vtoc information */
if (media_type == SM_FLOPPY) {
PERROR("FDIOGCHAR failed");
return (-1);
}
/* SPARC and x86 fd drivers use fdc_medium differently */
#if defined(__sparc)
#else
#endif /* defined(__sparc) */
/* initialize the vtoc structure */
} else if (media_type == SM_SCSI_FLOPPY) {
/*
* call smedia_get_medium_property to get the
* correct media information, since DKIOCGMEDIAINFO
* may fail for unformatted media.
*/
gettext("Failed to get libsmedia handle.\n"));
return (-1);
}
gettext("Get medium property failed \n"));
(void) smedia_release_handle(handle);
return (-1);
}
/* Fill in our own geometry information */
dkgeom.dkg_intrlv = 0;
/*
* Try to set vtoc, if not successful we will
* continue to use the faked geometry information.
*/
(void) smedia_release_handle(handle);
/* we want the same partitioning as used for normal floppies */
/* both write_vtoc and DKIOCSVTOC require V_NUMPAR partitions */
} else {
return (0);
}
/*
* The label structure is set up for DEV_BSIZE(512 byte) blocks,
* even though a medium density diskette has 1024 byte blocks
* See dklabel.h for more details.
*/
/* let the fd driver finish constructing the label and writing it. */
/* Turn on the privileges. */
(void) __priv_bracket(PRIV_ON);
/* Turn off the privileges. */
(void) __priv_bracket(PRIV_OFF);
if (ret < 0) {
PERROR("Write vtoc");
return (-1);
}
return (0);
}
static void
{
char c;
gettext("\nDo you want to stop formatting?(y/n)"));
while ((c = getchar()) == -1)
;
if (c == 'y' || c == 'Y') {
exit(1);
} else if (c == 'n' || c == 'N')
return;
else {
return;
}
}
void
{
DPRINTF("sigset failed\n");
return;
}
}
void
{
DPRINTF("sigunset failed\n");
return;
}
}
{
DPRINTF("ANALYSE MEDIA \n");
/* Turn on the privileges. */
(void) __priv_bracket(PRIV_ON);
/* Turn off the privileges. */
(void) __priv_bracket(PRIV_OFF);
return (-1);
return (0);
/* Turn on privileges. */
(void) __priv_bracket(PRIV_ON);
/* Turn off the privileges. */
(void) __priv_bracket(PRIV_OFF);
return (-1);
return (0);
return (-2);
}
/* Turn on the privileges. */
(void) __priv_bracket(PRIV_ON);
/* Turn off the privileges. */
(void) __priv_bracket(PRIV_OFF);
return (-1);
}
return (0);
return (-2);
}
/* Turn on the privileges. */
(void) __priv_bracket(PRIV_ON);
/* Turn off the privileges. */
(void) __priv_bracket(PRIV_OFF);
return (-1);
}
return (0);
} else {
DPRINTF("Illegal parameter to verify_analysis!\n");
return (-1);
}
}
static int
{
/* create a child to unmount the path */
/* Turn on the privileges */
(void) __priv_bracket(PRIV_ON);
/* Turn off the privileges. */
(void) __priv_bracket(PRIV_OFF);
if (pid < 0) {
PERROR("fork failed");
exit(0);
}
if (pid == 0) {
/* the child */
/* get rid of those nasty err messages */
/* Turn on the priviliges. */
(void) __priv_bracket(PRIV_ON);
NULL) < 0) {
perror("exec failed");
/* Turn off the privileges */
(void) __priv_bracket(PRIV_OFF);
exit(-1);
}
}
/* wait for the umount command to exit */
rval = 0;
if (WEXITSTATUS(rval) == 0) {
DPRINTF("umount : Success\n");
return (1);
}
}
}
return (-1);
}
static int
{
/* Turn on the privileges. */
(void) __priv_bracket(PRIV_ON);
/* Turn off the privileges. */
(void) __priv_bracket(PRIV_OFF);
/* create a child to unmount the path */
if (pid < 0) {
PERROR("fork failed");
exit(0);
}
if (pid == 0) {
/* the child */
/* get rid of those nasty err messages */
DPRINTF1("call_unmount_prog: calling %s \n",
"/usr/bin/volrmmount");
/* Turn on the privileges. */
(void) __priv_bracket(PRIV_ON);
PERROR("volrmmount exec failed");
/* Turn off the privileges */
(void) __priv_bracket(PRIV_OFF);
exit(-1);
}
if (WEXITSTATUS(rval) == 0) {
DPRINTF("volrmmount: Success\n");
return (1);
}
}
}
return (-1);
}
int
{
int removable = 0;
int device_type = 0;
int hotpluggable = 0;
static int found = 0;
return (-1);
total_devices_found = 0;
continue;
}
#ifdef sparc
continue;
}
#else /* x86 */
if (vol_running) {
continue;
}
} else {
continue;
}
}
#endif
continue;
}
continue;
}
/*
* dev_name is an optional command line input.
*/
if (dev_name) {
found = 1;
} else if (!vol_running) {
continue;
}
}
/*
* volmgt_symname() returns NULL if the device
* is not managed by volmgt.
*/
}
continue;
} else {
found = 1;
}
}
}
/*
*/
if (check_device(t_dev,
} else if (check_device(t_dev,
} else if (check_device(t_dev,
} else {
}
} else {
if (device_type < 0)
device_type = 0;
else
}
&hotpluggable)) {
if (removable || hotpluggable) {
if (sn) {
(void) printf(" %4d. "
"Volmgt Node: %s\n",
(void) printf(" "
"Logical Node: %s\n", sdev);
(void) printf(" "
"Physical Node: %s\n",
pname);
} else {
(void) printf(" %4d. "
"Logical Node: %s\n",
(void) printf(" "
"Physical Node: %s\n",
pname);
}
(void) printf(" Connected "
"Device: %-8.8s %-16.16s "
"%-4.4s\n",
(void) printf(" Device "
"Type: ");
} else
continue;
} else
continue;
switch (device_type) {
case DK_CDROM:
(void) printf("CD Reader\n");
break;
case DK_CDR:
case DK_CDRW:
break;
case DK_DVDROM:
(void) printf("DVD Reader\n");
break;
case DK_DVDR:
case DK_DVDRAM:
break;
case DK_FIXED_DISK:
if (strstr((const char *)
strstr((const char *)
(void) printf("Floppy "
"drive\n");
else
(void) printf("Removable\n");
break;
case DK_FLOPPY:
(void) printf("Floppy drive\n");
break;
case DK_ZIP:
(void) printf("Zip drive\n");
break;
case DK_JAZ:
(void) printf("Jaz drive\n");
break;
default:
(void) printf("<Unknown>\n");
break;
}
}
}
return (removable_found);
}
/*
* Returns a device_t handle for a node returned by lookup_device()
* and takes the user supplied name and stores it inside the node.
*/
static device_t *
{
int fd;
int size;
/*
* we need to resolve any link paths to avoid fake files
*/
return (NULL);
/* resolvepath may not return a null terminated string */
return (NULL);
/* Turn on the privileges. */
(void) __priv_bracket(PRIV_ON);
/*
* Since we are currently running with the user euid it is
* safe to try to open the file without checking access.
*/
/* Turn off the privileges. */
(void) __priv_bracket(PRIV_OFF);
if (fd < 0) {
return (NULL);
}
/* Turn on privileges. */
(void) __priv_bracket(PRIV_ON);
DPRINTF1("USCSI ioctl failed %d\n",
/* Turn off privileges. */
(void) __priv_bracket(PRIV_OFF);
return (NULL);
}
/* Turn off privileges. */
(void) __priv_bracket(PRIV_OFF);
if (user_supplied) {
}
return (dev);
}
/*
* Check for device specific characteristics.
*/
int
{
/* Look at the capabilities page for this information */
if (cond & CHECK_DEVICE_IS_CD_WRITABLE) {
return (1);
}
}
if (cond & CHECK_DEVICE_IS_DVD_WRITABLE) {
return (1);
}
}
if (cond & CHECK_DEVICE_IS_DVD_READABLE) {
return (1);
}
}
return (0);
}
/*
* Builds an open()able device path from a user supplied node which can be
* cdrom[n].
* Returns the path found in 'found' and returns 1. Otherwise returns 0.
*/
int
{
int fd;
/* Turn on privileges */
(void) __priv_bracket(PRIV_ON);
/* If everything is fine and proper, no need to analyze */
/* Turn off privilege */
(void) __priv_bracket(PRIV_OFF);
return (1);
}
/* Turn off privileges. */
(void) __priv_bracket(PRIV_OFF);
return (1);
}
else
return (0);
}
supplied);
}
return (1);
}
}
}
int
{
int fd;
if (fd < 0)
return (0);
return (0);
}
return (0);
return (1);
}
void
print_header(void)
{
/* l10n_NOTE : Column spacing should be kept same */
"Connected Device"));
/* l10n_NOTE : Column spacing should be kept same */
(void) printf(
"---------------------------+---------------------------");
(void) printf("-----+----------------\n");
}
void
print_divider(void)
{
(void) printf(
"---------------------------+---------------------------");
(void) printf("-----+----------------\n");
}
static void
{
}
void *
{
void *ret;
/* Lets wait a sec. and try again */
(void) sleep(1);
}
"Memory allocation failure, Exiting...\n"));
exit(1);
}
}
return (ret);
}
static int
{
char *p1;
int i;
return (0);
if (vol_running)
(void) volmgt_check(vname);
return (0);
return (0);
}
for (i = 0; i < 16; i++) {
break;
}
if (i == 16) {
return (0);
}
} else {
}
return (1);
}
/*
* Searches for volume manager's equivalent char device for the
*/
static int
{
int i, ret;
for (i = 0; i < 16; i++) {
tmpstr, i);
break;
}
for (i = 0; i < 5; i++) {
tmpstr, i);
break;
}
} else
return (0);
if (p == NULL)
return (0);
}
free(p);
return (ret);
}
/*PRINTFLIKE1*/
void
{
}
int
{
scmd = get_uscsi_cmd();
return (0);
return (1);
}
struct uscsi_cmd *
get_uscsi_cmd(void)
{
return (&uscmd);
}
int
{
int i;
/* set up for request sense extensions */
global_rqsense = 1;
} else {
global_rqsense = 0;
}
/*
* The device may be busy or slow and fail with a not ready status.
* we'll allow a limited number of retries to give the drive time
* to recover.
*/
scmd->uscsi_status = 0;
if (global_rqsense)
DPRINTF("cmd:[");
for (i = 0; i < scmd->uscsi_cdblen; i++)
DPRINTF1("0x%02x ",
DPRINTF("]\n");
/*
* We need to have root privledges in order to use
* uscsi commands on the device.
*/
/* maintain consistency in case of sgen */
ret = -1;
}
/* if error and extended request sense, retrieve errors */
/*
* The drive is not ready to recieve commands but
* may be in the process of becoming ready.
* sleep for a short time then retry command.
* ASCQ = 0 Not Reportable.
* ASCQ = 1 Becoming ready.
*/
(void) sleep(3);
continue;
}
/*
* Device is not ready to transmit or a device reset
* has occurred. wait for a short period of time then
* retry the command.
*/
(void) sleep(3);
continue;
}
DPRINTF3("cmd: 0x%02x ret:%i status:%02x ",
scmd->uscsi_status);
DPRINTF3(" sense: %02x ASC: %02x ASCQ:%02x\n",
}
/* no errors we'll return */
break;
}
/* store the error status for later debug printing */
if ((ret < 0) && (global_rqsense)) {
}
return (ret);
}
/*
* will get the mode page only i.e. will strip off the header.
*/
int
{
int ret;
/* Ask 254 bytes only to make our IDE driver happy */
if (ret == 0) {
return (0);
}
return (1);
}
int
{
scmd = get_uscsi_cmd();
if (dbd) {
/* don't return any block descriptors */
}
/* the page code we want */
/* allocation length */
return (0);
return (1);
}
{
return (ret);
}
/*
* Allocate space for and return a pointer to a string
* on the stack. If the string is null, create
* an empty string.
* Use destroy_data() to free when no longer used.
*/
char *
alloc_string(s)
char *s;
{
char *ns;
if (s == (char *)NULL) {
} else {
}
return (ns);
}
/*
* Follow symbolic links from the logical device name to
* the /devfs physical device name. To be complete, we
* handle the case of multiple links. This function
* either returns NULL (no links, or some other error),
* or the physical device name, alloc'ed on the heap.
*
* Note that the standard /devices prefix is stripped from
* the final pathname, if present. The trailing options
* are also removed (":c, raw").
*/
static char *
{
int i;
int level;
char *p;
char s[MAXPATHLEN];
return (NULL);
}
*p = 0;
}
if (s[0] == 0) {
(void) strcpy(s, "/");
}
if (chdir(s) == -1) {
DPRINTF2("cannot chdir() to %s - %s\n",
goto exit;
}
level = 0;
for (;;) {
/*
* See if there's a real file out there. If not,
* we have a dangling link and we ignore it.
*/
goto exit;
}
DPRINTF2("%s: lstat() failed - %s\n",
goto exit;
}
/*
* If the file is not a link, we're done one
* way or the other. If there were links,
* return the full pathname of the resulting
* file.
*/
if (level > 0) {
/*
* Strip trailing options from the
* physical device name
*/
*p = 0;
}
/*
* Get the current directory, and
* glue the pieces together.
*/
DPRINTF1("getcwd() failed - %s\n",
goto exit;
}
/*
* If we have the standard fixed
* /devices prefix, remove it.
*/
result = alloc_string(p);
}
goto exit;
}
if (i == -1) {
DPRINTF2("%s: readlink() failed - %s\n",
goto exit;
}
level++;
buf[i] = 0;
/*
* Break up the pathname into the directory
* reference, if applicable and simple filename.
* chdir()'ing to the directory allows us to
* handle links with relative pathnames correctly.
*/
*p = 0;
DPRINTF2("cannot chdir() to %s - %s\n",
goto exit;
}
(void) strcpy(s, p+1);
} else {
}
}
exit:
(void) printf("cannot chdir() to %s - %s\n",
}
return (result);
}
static void
{
float size;
int device_type;
/*
* Determine bus type.
*/
(void) printf("\tBus: USB\n");
(void) printf("\tBus: Firewire\n");
(void) printf("\tBus: IDE\n");
(void) printf("\tBus: SCSI\n");
} else {
(void) printf("\tBus: <Unknown>\n");
}
} else {
(void) printf("\tBus: <Unknown>\n");
}
/*
* Calculate size of media.
*/
if (!device_type &&
if (size < 1000) {
} else {
}
} else {
(void) printf("\tSize: <Unknown>\n");
}
/*
* Print label.
*/
} else {
(void) printf("\tLabel: <None>\n");
}
} else {
(void) printf("\tLabel: <Unknown>\n");
}
/*
* Acess permissions.
*/
if (device_type) {
(void) printf("\tAccess permissions: <Unknown>\n");
return;
}
if (sn) {
/*
* Set dev_name for process_p_flag().
*/
} else {
}
if (fd < 0) {
(void) printf("<Unknown>\n");
DPRINTF("Could not open device.\n");
} else {
/* register the fd with the libsmedia */
(void) printf("<Unknown>\n");
DPRINTF("Failed to get libsmedia handle.\n");
} else {
}
}
/* Clear dev_name */
}