/* libparted - a library for manipulating disk partitions
- Copyright (C) 1999-2010 Free Software Foundation, Inc.
+ Copyright (C) 1999-2011 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <sys/types.h>
#include <sys/utsname.h> /* for uname() */
#include <scsi/scsi.h>
+#include <assert.h>
#ifdef ENABLE_DEVICE_MAPPER
#include <libdevmapper.h>
#endif
#include "../architecture.h"
#include "dirname.h"
+#include "xstrtol.h"
#if ENABLE_NLS
# include <libintl.h>
#define SCSI_DISK5_MAJOR 69
#define SCSI_DISK6_MAJOR 70
#define SCSI_DISK7_MAJOR 71
+#define SCSI_DISK8_MAJOR 128
+#define SCSI_DISK9_MAJOR 129
+#define SCSI_DISK10_MAJOR 130
+#define SCSI_DISK11_MAJOR 131
+#define SCSI_DISK12_MAJOR 132
+#define SCSI_DISK13_MAJOR 133
+#define SCSI_DISK14_MAJOR 134
+#define SCSI_DISK15_MAJOR 135
#define COMPAQ_SMART2_MAJOR 72
#define COMPAQ_SMART2_MAJOR1 73
#define COMPAQ_SMART2_MAJOR2 74
#define SCSI_BLK_MAJOR(M) ( \
(M) == SCSI_DISK0_MAJOR \
|| (M) == SCSI_CDROM_MAJOR \
- || ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
+ || ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR) \
+ || ((M) >= SCSI_DISK8_MAJOR && (M) <= SCSI_DISK15_MAJOR))
/* Maximum number of partitions supported by linux. */
#define MAX_NUM_PARTS 64
static int
_device_stat (PedDevice* dev, struct stat * dev_stat)
{
- PED_ASSERT (dev != NULL, return 0);
- PED_ASSERT (!dev->external_mode, return 0);
+ PED_ASSERT (dev != NULL);
+ PED_ASSERT (!dev->external_mode);
while (1) {
if (!stat (dev->path, dev_stat)) {
dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
- PED_ASSERT (dev->open_count, return);
+ PED_ASSERT (dev->open_count);
if (_get_linux_version() < KERNEL_VERSION (2,3,0)) {
dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
unsigned long size;
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
uint64_t bytes=0;
+ const char* test_str;
+ PedSector test_size;
- PED_ASSERT (dev->open_count > 0, return 0);
- PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
+ PED_ASSERT (dev->open_count > 0);
+ PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
+
+ test_str = getenv ("PARTED_TEST_DEVICE_LENGTH");
+ if (test_str
+ && xstrtoll (test_str, NULL, 10, &test_size, NULL) == LONGINT_OK)
+ return test_size;
if (_kernel_has_blkgetsize64()) {
if (ioctl(arch_specific->fd, BLKGETSIZE64, &bytes) == 0) {
if (!_device_stat (dev, &dev_stat))
return 0;
- PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
+ PED_ASSERT (S_ISBLK (dev_stat.st_mode));
_device_set_sector_size (dev);
dev->model = strdup(_("Generic IDE"));
break;
default:
- PED_ASSERT (0, (void) 0);
+ PED_ASSERT (0);
break;
}
} else {
case PED_EXCEPTION_IGNORE:
break;
default:
- PED_ASSERT (0, (void) 0);
+ PED_ASSERT (0);
break;
}
}
LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
- PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
+ PED_ASSERT (S_ISBLK (dev_stat.st_mode));
_device_set_sector_size (dev);
if (!dev->sector_size)
if (_device_probe_geometry (dev)) {
ped_exception_leave_all ();
} else {
+ if (!_device_get_length (dev)) {
+ ped_exception_catch ();
+ ped_exception_leave_all ();
+ goto error_close_dev;
+ }
+
/* hack to allow use of files, for testing */
ped_exception_catch ();
ped_exception_leave_all ();
case PED_EXCEPTION_IGNORE:
break;
default:
- PED_ASSERT (0, (void) 0);
+ PED_ASSERT (0);
break;
}
PedDevice* dev;
LinuxSpecific* arch_specific;
- PED_ASSERT (path != NULL, return NULL);
+ PED_ASSERT (path != NULL);
dev = (PedDevice*) ped_malloc (sizeof (PedDevice));
if (!dev)
{
LinuxSpecific* arch_specific;
- PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
- PED_ASSERT (dev != NULL, return 0);
- PED_ASSERT (!dev->external_mode, return 0);
+ PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
+ PED_ASSERT (dev != NULL);
+ PED_ASSERT (!dev->external_mode);
arch_specific = LINUX_SPECIFIC (dev);
LinuxSpecific* arch_specific;
struct blkdev_ioctl_param ioctl_param;
- PED_ASSERT(dev != NULL, return 0);
- PED_ASSERT(buffer != NULL, return 0);
+ PED_ASSERT(dev != NULL);
+ PED_ASSERT(buffer != NULL);
arch_specific = LINUX_SPECIFIC (dev);
PedExceptionOption ex_status;
void* diobuf = NULL;
- PED_ASSERT (dev != NULL, return 0);
- PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
+ PED_ASSERT (dev != NULL);
+ PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
/* Kludge. This is necessary to read/write the last
case PED_EXCEPTION_CANCEL:
return 0;
default:
- PED_ASSERT (0, (void) 0);
+ PED_ASSERT (0);
break;
}
}
free(diobuf);
return 0;
default:
- PED_ASSERT (0, (void) 0);
+ PED_ASSERT (0);
break;
}
}
LinuxSpecific* arch_specific;
struct blkdev_ioctl_param ioctl_param;
- PED_ASSERT(dev != NULL, return 0);
- PED_ASSERT(buffer != NULL, return 0);
+ PED_ASSERT(dev != NULL);
+ PED_ASSERT(buffer != NULL);
arch_specific = LINUX_SPECIFIC (dev);
void* diobuf;
void* diobuf_start;
- PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
+ PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
if (dev->read_only) {
if (ped_exception_throw (
case PED_EXCEPTION_CANCEL:
return 0;
default:
- PED_ASSERT (0, (void) 0);
+ PED_ASSERT (0);
break;
}
}
free(diobuf_start);
return 0;
default:
- PED_ASSERT (0, (void) 0);
+ PED_ASSERT (0);
break;
}
}
int status;
void* diobuf;
- PED_ASSERT(dev != NULL, return 0);
+ PED_ASSERT(dev != NULL);
if (!_device_seek (dev, start))
return 0;
case PED_EXCEPTION_CANCEL:
return 0;
default:
- PED_ASSERT (0, (void) 0);
+ PED_ASSERT (0);
break;
}
}
static int
linux_sync (PedDevice* dev)
{
- PED_ASSERT (dev != NULL, return 0);
- PED_ASSERT (!dev->external_mode, return 0);
+ PED_ASSERT (dev != NULL);
+ PED_ASSERT (!dev->external_mode);
if (dev->read_only)
return 1;
static int
linux_sync_fast (PedDevice* dev)
{
- PED_ASSERT (dev != NULL, return 0);
- PED_ASSERT (!dev->external_mode, return 0);
+ PED_ASSERT (dev != NULL);
+ PED_ASSERT (!dev->external_mode);
if (dev->read_only)
return 1;
_probe_proc_partitions ();
}
-static char*
-_device_get_part_path (PedDevice* dev, int num)
+static char * _GL_ATTRIBUTE_FORMAT ((__printf__, 1, 2))
+zasprintf (const char *format, ...)
{
- int path_len = strlen (dev->path);
- int result_len = path_len + 16;
- char* result;
+ va_list args;
+ char *resultp;
+ va_start (args, format);
+ int r = vasprintf (&resultp, format, args);
+ va_end (args);
+ return r < 0 ? NULL : resultp;
+}
- result = (char*) ped_malloc (result_len);
- if (!result)
- return NULL;
+static char*
+_device_get_part_path (PedDevice *dev, int num)
+{
+ size_t path_len = strlen (dev->path);
+ char *result;
/* Check for devfs-style /disc => /partN transformation
unconditionally; the system might be using udev with devfs rules,
and if not the test is harmless. */
- if (!strcmp (dev->path + path_len - 5, "/disc")) {
+ if (5 < path_len && !strcmp (dev->path + path_len - 5, "/disc")) {
/* replace /disc with /path%d */
- strcpy (result, dev->path);
- snprintf (result + path_len - 5, 16, "/part%d", num);
- } else if (dev->type == PED_DEVICE_DAC960
- || dev->type == PED_DEVICE_CPQARRAY
- || dev->type == PED_DEVICE_ATARAID
- || dev->type == PED_DEVICE_DM
- || isdigit (dev->path[path_len - 1]))
- snprintf (result, result_len, "%sp%d", dev->path, num);
- else
- snprintf (result, result_len, "%s%d", dev->path, num);
+ result = zasprintf ("%.*s/part%d",
+ (int) (path_len - 5), dev->path, num);
+ } else {
+ char const *p = (dev->type == PED_DEVICE_DAC960
+ || dev->type == PED_DEVICE_CPQARRAY
+ || dev->type == PED_DEVICE_ATARAID
+ || dev->type == PED_DEVICE_DM
+ || isdigit (dev->path[path_len - 1])
+ ? "p" : "");
+ result = zasprintf ("%s%s%d", dev->path, p, num);
+ }
return result;
}
static int
_has_partitions (const PedDisk* disk)
{
- PED_ASSERT(disk != NULL, return 0);
+ PED_ASSERT(disk != NULL);
/* Some devices can't be partitioned. */
if (!strcmp (disk->type->name, "loop"))
{
PedPartition* walk;
- PED_ASSERT (part != NULL, return 0);
+ PED_ASSERT (part != NULL);
if (_partition_is_mounted (part))
return 1;
const char* vol_name;
char* dev_name;
- PED_ASSERT(disk != NULL, return 0);
- PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0,
- return 0);
+ PED_ASSERT(disk != NULL);
+ PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
if (!_has_partitions (disk))
return 0;
static int
_disk_sync_part_table (PedDisk* disk)
{
- PED_ASSERT(disk != NULL, return 0);
- PED_ASSERT(disk->dev != NULL, return 0);
+ PED_ASSERT(disk != NULL);
+ PED_ASSERT(disk->dev != NULL);
int lpn;
/* lpn = largest partition number. */
return _dm_reread_part_table (disk);
#endif
if (disk->dev->type != PED_DEVICE_FILE) {
- /* The ioctl() command BLKPG_ADD_PARTITION does not notify
- * the devfs system; consequently, /proc/partitions will not
- * be up to date, and the proper links in /dev are not
- * created. Therefore, if using DevFS, we must get the kernel
- * to re-read and grok the partition table.
- */
- /* Work around kernel dasd problem so we really do BLKRRPART */
- int ok = 1;
- if (disk->dev->type != PED_DEVICE_DASD && _have_blkpg ()) {
- if (!_disk_sync_part_table (disk))
- ok = 0;
- }
- return ok;
+ /* We now require BLKPG support. If this assertion fails,
+ please write to the mailing list describing your system.
+ Assuming it's never triggered, ...
+ FIXME: remove this assertion in 2012. */
+ assert (_have_blkpg ());
+
+ if (!_disk_sync_part_table (disk))
+ return 0;
}
return 1;
if (!tp)
return NULL;
- /* If optimal_io_size is 0 _and_ alignment_offset is 0 _and_
- minimum_io_size is a power of 2 then go with the device.c default */
- unsigned long minimum_io_size = blkid_topology_get_minimum_io_size(tp);
- if (blkid_topology_get_optimal_io_size(tp) == 0 &&
- blkid_topology_get_alignment_offset(tp) == 0 &&
- (minimum_io_size & (minimum_io_size - 1)) == 0)
- return NULL;
+ /* When PED_DEFAULT_ALIGNMENT is divisible by the *_io_size or
+ there are no *_io_size values, use the PED_DEFAULT_ALIGNMENT
+ If one or the other will not divide evenly, fall through to
+ previous logic. */
+ unsigned long optimal_io = blkid_topology_get_optimal_io_size(tp);
+ unsigned long minimum_io = blkid_topology_get_minimum_io_size(tp);
+ if (
+ (!optimal_io && !minimum_io)
+ || (optimal_io && PED_DEFAULT_ALIGNMENT % optimal_io == 0
+ && minimum_io && PED_DEFAULT_ALIGNMENT % minimum_io == 0)
+ || (!minimum_io && optimal_io
+ && PED_DEFAULT_ALIGNMENT % optimal_io == 0)
+ || (!optimal_io && minimum_io
+ && PED_DEFAULT_ALIGNMENT % minimum_io == 0)
+ ) {
+ /* DASD needs to use minimum alignment */
+ if (dev->type == PED_DEVICE_DASD)
+ return linux_get_minimum_alignment(dev);
+
+ return ped_alignment_new(
+ blkid_topology_get_alignment_offset(tp) / dev->sector_size,
+ PED_DEFAULT_ALIGNMENT / dev->sector_size);
+ }
/* If optimal_io_size is 0 and we don't meet the other criteria
for using the device.c default, return the minimum alignment. */