solaris.c revision 7e7bd3dccbfe8f79e25e5c1554b5bc3a9aaca321
/*
libparted - a library for manipulating disk partitions
Copyright (C) 1999 - 2005 Free Software Foundation, Inc.
Copyright (C) 2007 Nikhil,Sujay,Nithin,Srivatsa.
Bug fixes and completion of the module in 2009 by Mark.Logan@sun.com.
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include "xalloc.h"
/*
* __attribute doesn't exist on solaris
*/
#define __attribute__(X) /* nothing */
#include <malloc.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <libdiskmgt.h>
#if ENABLE_NLS
#include <libintl.h>
#else
#endif /* ENABLE_NLS */
#ifndef UINT_MAX64
#define UINT_MAX64 0xffffffffffffffffULL
#endif
/*
* Macro to convert a device number into a partition number
*/
char *
canonicalize_file_name(const char *name)
{
char *buf;
if (!buf) {
return (NULL);
}
}
static int
{
while (1) {
return (1);
} else {
if (ped_exception_throw(
_("Could not stat device %s - %s."),
return (0);
}
}
}
static void
{
/* this ioctl requires the raw device */
printf("_device_get_length: ioctl DKIOCGMEDIAINFO failed\n");
_("Unable to determine the size of %s (%s)."),
} else {
_("Device %s has a logical sector size of "
"%lld. Not all parts of GNU Parted support "
"this at the moment, and the working code "
"is HIGHLY EXPERIMENTAL.\n"),
}
if (size > 0) {
return;
}
}
/*
* On some disks DKIOCGMEDIAINFO doesn't work, it returns 0,
* so try DKIOCG_PHYGEOM next.
*/
/* this ioctl requires the raw device */
printf("_device_get_length: ioctl DKIOCG_PHYGEOM failed\n");
_("Unable to determine the size of %s (%s)."),
return;
}
/*
* XXX For large disks, I am adding 16064 to the size of the disk.
* Solaris underreports the size of the disk, because it rounds down to
* a multiple of 16065. This causes a problem with Vista because Vista
* creates a partition that occupies the whole disk, including the
* blocks at the end of the disk that Solaris loses.
*/
(255 * 63)) + ((255*63)-1);
} else {
}
}
static int
{
printf("_device_probe_geometry: _device_get_length = 0\n");
return (0);
}
} else {
perror("_device_probe_geometry: DKIOCG_PHYGEOM");
}
return (1);
}
static int
{
printf("init_ide: _device_stat failed\n");
goto error;
}
if (!ped_device_open(dev)) {
printf("init_ide: ped_device_open failed\n");
goto error;
}
if (!_device_probe_geometry(dev)) {
printf("init_ide: _device_probe_geometry failed\n");
goto error_close_dev;
}
return (1);
return (0);
}
static PedDevice*
solaris_new(const char *path)
{
if (!dev)
goto error;
goto error_free_dev;
if (!dev->arch_specific)
goto error_free_path;
dev->open_count = 0;
dev->external_mode = 0;
dev->boot_dirty = 0;
goto error_free_arch_specific;
}
return (dev);
return (NULL);
}
static void
{
}
static char *
{
char *result;
if (!result)
return (NULL);
/*
* Create the path name to the *pn device, where n is the partition #
* geom->dev->path looks like this: "/devices/.../cmdk@0,0:q"
* :r is p1, :s is p2, :t is p3, :u is p4
* 'q' + 1 == 'r'
* '0' + 1 == '1'
*/
return (result);
}
static struct swaptable *
getswapentries(void)
{
int i, num;
char fullpathname[MAXPATHLEN];
/*
* get the number of swap entries
*/
perror("getswapentries: swapctl SC_GETNSWP");
return (NULL);
}
if (num == 0)
return (NULL);
== NULL) {
printf("getswapentries: malloc 1 failed.\n");
return (NULL);
}
printf("getswapentries: malloc 2 failed.\n");
goto error;
}
}
perror("getswapentries: swapctl SC_LIST");
goto error;
}
}
}
return (st);
return (NULL);
}
static void
{
int i;
}
/*
* function getpartition:
*/
static int
{
int mfd;
struct dk_cinfo cur_disk_dkinfo;
char raw_device[MAXPATHLEN];
int found = -1;
/*
* Map the block device name to the raw device name.
* If it doesn't appear to be a device name, skip it.
*/
return (found);
/*
* Determine if this appears to be a disk device.
* First attempt to open the device. If if fails, skip it.
*/
return (found);
}
perror("getpartition: fstat raw_device");
return (found);
}
/*
* Must be a character device
*/
printf("getpartition: not character device\n");
return (found);
}
/*
* Attempt to read the configuration info on the disk.
*/
perror("getpartition: ioctl DKIOCINFO raw_device");
return (found);
}
/*
* Finished with the opened device
*/
/*
* Now get the info about the current disk
*/
perror("getpartition: ioctl DKIOCINFO current disk");
return (found);
}
/*
* If it's not the disk we're interested in, it doesn't apply.
*/
return (found);
}
/*
* Extract the partition that is mounted.
*/
}
/*
* This Routine checks to see if there are partitions used for swapping overlaps
* a given portion of a disk. If the start parameter is < 0, it means
* that the entire disk should be checked
*/
static int
{
int i;
int found = 0;
int part;
return (0);
}
/*
* check for swap entries
*/
st = getswapentries();
/*
* if there are no swap entries return.
*/
return (0);
if (start == UINT_MAX64) {
found = -1;
break;
}
continue;
}
found = -1;
break;
}
}
return (found);
}
/*
* Determines if there are partitions that are a part of an SVM, VxVM, zpool
* volume or a live upgrade device, overlapping a given portion of a disk.
* Mounts and swap devices are checked in legacy format code.
*/
static int
{
int error;
int found = 0;
int check = 0;
int i;
int part = 0;
char *usage;
char *name;
char cur_disk_path[MAXPATHLEN];
char *pcur_disk_path;
/*
* Truncate the characters following "d*", such as "s*" or "p*"
*/
if (name) {
name++;
;
*name = (char)0;
}
/*
* For format, we get basic 'in use' details from libdiskmgt. After
* that we must do the appropriate checking to see if the 'in use'
* details require a bit of additional work.
*/
if (error) {
/*
* If ENODEV, it actually means the device is not in use.
* We will return (0) without displaying error.
*/
printf("checkdevinuse: Error1 occurred with device in "
return (found);
}
}
return (found);
/*
* If we are checking the whole disk
* then any and all in use data is
* relevant.
*/
if (start == UINT_MAX64) {
printf("checkdevinuse: Error2 occurred with "
"device in use checking: %s\n",
continue;
}
error) {
if (error != 0) {
printf("checkdevinuse: Error3 "
"occurred with device "
"in use checking: %s\n",
continue;
}
/*
* If this is a dump device, then it is
* a failure. You cannot format a slice
* that is a dedicated dump device.
*/
if (print) {
}
return (1);
}
/*
* We really found a device that is in use.
* Set 'found' for the return value.
*/
found ++;
check = 1;
if (print) {
}
}
} else {
/*
* Before getting the in use data, verify that the
* current slice is within the range we are checking.
*/
if (error) {
printf("checkdevinuse: Error4 occurred with "
"device in use checking: %s\n",
continue;
}
continue;
}
&slice_start);
&slice_size);
(end < slice_start)) {
continue;
}
printf("checkdevinuse: Error5 occurred with "
"device in use checking: %s\n",
continue;
}
if (error != 0) {
printf("checkdevinuse: Error6 "
"occurred with device "
"in use checking: %s\n",
continue;
}
/*
* If this is a dump device, then it is
* a failure. You cannot format a slice
* that is a dedicated dump device.
*/
if (print) {
}
return (1);
}
/*
* We really found a device that is in use.
* Set 'found' for the return value.
*/
found ++;
check = 1;
if (print) {
}
}
}
/*
* If check is set it means we found a slice(the current slice)
* on this device in use in some way. We potentially want
* to check this slice when labeling is requested.
*/
if (check) {
printf("checkdevinuse: Error7 occurred with "
"device in use checking: %s\n",
continue;
}
check = 0;
}
/*
* If we have attributes then we have successfully
* found the slice we were looking for and we also
* know this means we are not searching the whole
* disk so break out of the loop
* now.
*/
if (attrs) {
break;
}
}
if (slices) {
}
return (found);
}
/*
* This routine checks to see if there are mounted partitions overlapping
* a given portion of a disk. If the start parameter is < 0, it means
* that the entire disk should be checked.
*/
static int
{
int found = 0;
int part;
struct mnttab mnt_record;
return (0);
}
/*
* Open the mount table.
*/
printf("checkmount: Unable to open mount table.\n");
return (0);
}
/*
* Loop through the mount table until we run out of entries.
*/
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 (start == UINT_MAX64) {
found = -1;
break;
}
/*
* If the partition overlaps the zone we're checking,
* then we found trouble. We can quit searching.
*/
continue;
}
found = -1;
break;
}
/*
* Close down the mount table.
*/
return (found);
}
/*
* Return 1 if the device is busy, 0 otherwise.
*/
static int
{
return (1);
return (1);
return (1);
return (0);
}
/*
* This will accept a dev->path that looks like this:
* or this:
* It has to open the raw device, so it converts to it locally, if necessary.
*/
static int
{
char rawname[MAXPATHLEN];
/*
* Convert to the raw device, unless it already is.
*/
} else {
}
} else {
/*
*/
} else {
}
}
if (ped_exception_throw(
_("Error opening %s: %s"),
return (0);
} else {
goto retry;
}
} else {
_("Unable to open %s read-write (%s). %s has "
"been opened read-only."),
}
} else {
}
return (1);
}
static int
{
return (1);
}
static int
{
return (1);
}
static int
{
int status;
while (1) {
if (status >= 0)
break;
_("%s during fsync on %s"),
switch (ex_status) {
case PED_EXCEPTION_IGNORE:
return (1);
case PED_EXCEPTION_RETRY:
break;
case PED_EXCEPTION_UNHANDLED:
case PED_EXCEPTION_CANCEL:
return (0);
}
}
return (1);
}
static int
{
return (1);
}
static int
{
if (sizeof (off_t) < 8) {
} else {
}
}
static int
{
int status;
void *diobuf;
while (1) {
break;
_("%s during seek for read on %s"),
switch (ex_status) {
case PED_EXCEPTION_IGNORE:
return (1);
case PED_EXCEPTION_RETRY:
break;
case PED_EXCEPTION_UNHANDLED:
case PED_EXCEPTION_CANCEL:
return (0);
}
}
return (0);
}
while (1) {
if (status > 0)
if (status == read_length)
break;
if (status > 0) {
printf("solaris_read: partial read %d of %d\n",
read_length -= status;
continue;
}
_("%s during read on %s"),
switch (ex_status) {
case PED_EXCEPTION_IGNORE:
return (1);
case PED_EXCEPTION_RETRY:
break;
case PED_EXCEPTION_UNHANDLED:
case PED_EXCEPTION_CANCEL:
return (0);
}
}
return (1);
}
static int
{
int status;
char *diobuf;
char *diobuf_start;
if (ped_exception_throw(
_("Can't write to %s, because it is opened read-only."),
return (0);
else
return (1);
}
while (1) {
break;
_("%s during seek for write on %s"),
switch (ex_status) {
case PED_EXCEPTION_IGNORE:
return (1);
case PED_EXCEPTION_RETRY:
break;
case PED_EXCEPTION_UNHANDLED:
case PED_EXCEPTION_CANCEL:
return (0);
}
}
#ifdef READ_ONLY
printf("solaris_write(\"%s\", %p, %d, %d)\n",
#else
return (0);
}
while (1) {
if (status == write_length)
break;
if (status > 0) {
printf("solaris_write: partial write %d of %d\n",
write_length -= status;
continue;
}
_("%s during write on %s"),
switch (ex_status) {
case PED_EXCEPTION_IGNORE:
return (1);
case PED_EXCEPTION_RETRY:
break;
case PED_EXCEPTION_UNHANDLED:
case PED_EXCEPTION_CANCEL:
return (0);
}
}
#endif /* !READ_ONLY */
return (1);
}
/*
* returns the number of sectors that are ok.
* This is never called. It would get called through ped_device_check().
*/
static PedSector
{
int status;
void* diobuf;
return (0LL));
return (0LL);
printf("solaris_check: cannot memalign %u\n",
return (0LL);
}
if (status < 0)
break;
}
return (done);
}
static int
{
return (1);
return (0);
return (1);
}
/*
* Returns all *p0 block devices.
* open the raw device so ioctl works.
*/
static void
{
char *pname;
char block_path[256];
char raw_path[256];
int fd;
continue;
}
int n = 0;
char msg[MAXPATHLEN];
"ioctl(\"%s\", DKIOCREMOVABLE)",
raw_path);
} else if (!n) {
/*
* Not a removable device
* printf("solaris_probe_all: %s\n",
* block_path);
*/
}
#endif /* DONT_ALLOW_REMOVEABLE_DEVICES */
}
}
}
}
static char *
{
}
/*
* Returns 1 if the partition is busy in some way, 0 otherwise.
*/
static int
{
return (1);
return (0);
}
static int
{
return (1);
}
static PedDeviceArchOps solaris_dev_ops = {
._new = solaris_new,
.open = solaris_open,
.close = solaris_close,
.read = solaris_read,
.write = solaris_write,
.check = solaris_check,
.sync = solaris_sync,
};
};
.dev_ops = &solaris_dev_ops,
};