1 /* libparted - a library for manipulating disk partitions
2 Copyright (C) 1999 - 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #define PROC_DEVICES_BUFSIZ 16384
21 #include <arch/linux.h>
23 #include <parted/parted.h>
24 #include <parted/debug.h>
25 #if defined __s390__ || defined __s390x__
26 #include <parted/fdasd.h>
38 #include <sys/ioctl.h>
40 #include <sys/types.h>
41 #include <sys/utsname.h> /* for uname() */
42 #include <scsi/scsi.h>
43 #ifdef ENABLE_DEVICE_MAPPER
44 #include <libdevmapper.h>
47 #include "../architecture.h"
52 # define _(String) dgettext (PACKAGE, String)
54 # define _(String) (String)
55 #endif /* ENABLE_NLS */
57 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
60 #define __NR__llseek 140
63 #ifndef SCSI_IOCTL_SEND_COMMAND
64 #define SCSI_IOCTL_SEND_COMMAND 1
67 /* from <linux/hdreg.h> */
68 #define HDIO_GETGEO 0x0301 /* get device geometry */
69 #define HDIO_GET_IDENTITY 0x030d /* get IDE identification info */
71 #define RD_MODE (O_RDONLY)
72 #define WR_MODE (O_WRONLY)
73 #define RW_MODE (O_RDWR)
77 unsigned char sectors;
78 unsigned short cylinders;
82 struct ata7_sectinfo {
89 /* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
91 unsigned short config; /* lots of obsolete bit flags */
92 unsigned short cyls; /* "physical" cyls */
93 unsigned short reserved2; /* reserved (word 2) */
94 unsigned short heads; /* "physical" heads */
95 unsigned short track_bytes; /* unformatted bytes per track */
96 unsigned short sector_bytes; /* unformatted bytes per sector */
97 unsigned short sectors; /* "physical" sectors per track */
98 unsigned short vendor0; /* vendor unique */
99 unsigned short vendor1; /* vendor unique */
100 unsigned short vendor2; /* vendor unique */
101 unsigned char serial_no[20]; /* 0 = not_specified */
102 unsigned short buf_type;
103 unsigned short buf_size; /* 512 byte increments;
105 unsigned short ecc_bytes; /* for r/w long cmds;
107 unsigned char fw_rev[8]; /* 0 = not_specified */
108 char model[40]; /* 0 = not_specified */
109 unsigned char max_multsect; /* 0=not_implemented */
110 unsigned char vendor3; /* vendor unique */
111 unsigned short dword_io; /* 0=not_implemented; 1=implemented */
112 unsigned char vendor4; /* vendor unique */
113 unsigned char capability; /* bits 0:DMA 1:LBA 2:IORDYsw
115 unsigned short reserved50; /* reserved (word 50) */
116 unsigned char vendor5; /* vendor unique */
117 unsigned char tPIO; /* 0=slow, 1=medium, 2=fast */
118 unsigned char vendor6; /* vendor unique */
119 unsigned char tDMA; /* 0=slow, 1=medium, 2=fast */
120 unsigned short field_valid; /* bits 0:cur_ok 1:eide_ok */
121 unsigned short cur_cyls; /* logical cylinders */
122 unsigned short cur_heads; /* logical heads */
123 unsigned short cur_sectors; /* logical sectors per track */
124 unsigned short cur_capacity0; /* logical total sectors on drive */
125 unsigned short cur_capacity1; /* (2 words, misaligned int) */
126 unsigned char multsect; /* current multiple sector count */
127 unsigned char multsect_valid; /* when (bit0==1) multsect is ok */
128 unsigned int lba_capacity; /* total number of sectors */
129 unsigned short dma_1word; /* single-word dma info */
130 unsigned short dma_mword; /* multiple-word dma info */
131 unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */
132 unsigned short eide_dma_min; /* min mword dma cycle time (ns) */
133 unsigned short eide_dma_time; /* recommended mword dma cycle
135 unsigned short eide_pio; /* min cycle time (ns), no IORDY */
136 unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */
137 unsigned short words69_70[2]; /* reserved words 69-70 */
138 /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
139 unsigned short words71_74[4]; /* reserved words 71-74 */
140 unsigned short queue_depth; /* */
141 unsigned short words76_79[4]; /* reserved words 76-79 */
142 unsigned short major_rev_num; /* */
143 unsigned short minor_rev_num; /* */
144 unsigned short command_set_1; /* bits 0:Smart 1:Security 2:Removable
146 unsigned short command_set_2; /* bits 14:Smart Enabled 13:0 zero */
147 unsigned short cfsse; /* command set-feature supported
149 unsigned short cfs_enable_1; /* command set-feature enabled */
150 unsigned short cfs_enable_2; /* command set-feature enabled */
151 unsigned short csf_default; /* command set-feature default */
152 unsigned short dma_ultra; /* */
153 unsigned short word89; /* reserved (word 89) */
154 unsigned short word90; /* reserved (word 90) */
155 unsigned short CurAPMvalues; /* current APM values */
156 unsigned short word92; /* reserved (word 92) */
157 unsigned short hw_config; /* hardware config */
158 unsigned short words94_105[12];/* reserved words 94-105 */
159 struct ata7_sectinfo ata7_sectinfo; /* ATAPI/ATA7 physical and logical
161 unsigned short words107_116[10];/* reserved words 107-116 */
162 unsigned int logical_sectsize;/* ATAPI/ATA7 logical sector size */
163 unsigned short words119_125[7];/* reserved words 119-125 */
164 unsigned short last_lun; /* reserved (word 126) */
165 unsigned short word127; /* reserved (word 127) */
166 unsigned short dlf; /* device lock function
168 * 8 security level 1:max 0:high
177 unsigned short csfo; /* current set features options
184 unsigned short words130_155[26];/* reserved vendor words 130-155 */
185 unsigned short word156;
186 unsigned short words157_159[3]; /* reserved vendor words 157-159 */
187 unsigned short words160_255[95];/* reserved words 160-255 */
190 /* from <linux/fs.h> */
191 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
192 #define BLKGETSIZE _IO(0x12,96) /* return device size */
193 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
194 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
195 #define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
196 #define BLKSETLASTSECT _IO(0x12,109) /* set last sector of block device */
198 /* return device size in bytes (u64 *arg) */
199 #define BLKGETSIZE64 _IOR(0x12,114,size_t)
201 struct blkdev_ioctl_param {
203 size_t content_length;
204 char * block_contents;
207 /* from <linux/major.h> */
209 #define IDE1_MAJOR 22
210 #define IDE2_MAJOR 33
211 #define IDE3_MAJOR 34
212 #define IDE4_MAJOR 56
213 #define IDE5_MAJOR 57
214 #define SCSI_CDROM_MAJOR 11
215 #define SCSI_DISK0_MAJOR 8
216 #define SCSI_DISK1_MAJOR 65
217 #define SCSI_DISK2_MAJOR 66
218 #define SCSI_DISK3_MAJOR 67
219 #define SCSI_DISK4_MAJOR 68
220 #define SCSI_DISK5_MAJOR 69
221 #define SCSI_DISK6_MAJOR 70
222 #define SCSI_DISK7_MAJOR 71
223 #define COMPAQ_SMART2_MAJOR 72
224 #define COMPAQ_SMART2_MAJOR1 73
225 #define COMPAQ_SMART2_MAJOR2 74
226 #define COMPAQ_SMART2_MAJOR3 75
227 #define COMPAQ_SMART2_MAJOR4 76
228 #define COMPAQ_SMART2_MAJOR5 77
229 #define COMPAQ_SMART2_MAJOR6 78
230 #define COMPAQ_SMART2_MAJOR7 79
231 #define COMPAQ_SMART_MAJOR 104
232 #define COMPAQ_SMART_MAJOR1 105
233 #define COMPAQ_SMART_MAJOR2 106
234 #define COMPAQ_SMART_MAJOR3 107
235 #define COMPAQ_SMART_MAJOR4 108
236 #define COMPAQ_SMART_MAJOR5 109
237 #define COMPAQ_SMART_MAJOR6 110
238 #define COMPAQ_SMART_MAJOR7 111
239 #define DAC960_MAJOR 48
240 #define ATARAID_MAJOR 114
241 #define I2O_MAJOR1 80
242 #define I2O_MAJOR2 81
243 #define I2O_MAJOR3 82
244 #define I2O_MAJOR4 83
245 #define I2O_MAJOR5 84
246 #define I2O_MAJOR6 85
247 #define I2O_MAJOR7 86
248 #define I2O_MAJOR8 87
250 #define DASD_MAJOR 94
251 #define VIODASD_MAJOR 112
252 #define SX8_MAJOR1 160
253 #define SX8_MAJOR2 161
254 #define XVD_MAJOR 202
255 #define SDMMC_MAJOR 179
258 #define SCSI_BLK_MAJOR(M) ( \
259 (M) == SCSI_DISK0_MAJOR \
260 || (M) == SCSI_CDROM_MAJOR \
261 || ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
263 /* Maximum number of partitions supported by linux. */
264 #define MAX_NUM_PARTS 64
266 static char* _device_get_part_path (PedDevice* dev, int num);
267 static int _partition_is_mounted_by_path (const char* path);
270 _read_fd (int fd, char **buf)
273 size_t size = PROC_DEVICES_BUFSIZ;
276 *buf = malloc (size * sizeof (char));
282 p = &(*buf) [filesize];
283 s = read (fd, p, PROC_DEVICES_BUFSIZ);
284 /* exit if there is an error or EOF is reached */
289 char *new_buf = realloc (*buf, size);
290 if (new_buf == NULL) {
291 int saved_errno = errno;
299 if (filesize == 0 && s < 0) {
304 char *new_buf = realloc (*buf, filesize + 1);
305 if (new_buf == NULL) {
306 int saved_errno = errno;
312 (*buf)[filesize] = '\0';
319 _major_type_in_devices (int major, const char* type)
328 fd = open ("/proc/devices", O_RDONLY);
332 if (_read_fd(fd, &buf) < 0) {
338 end = strchr(line, '\n');
347 if (!strncmp(line, "Block devices:", 14))
352 name = strrchr(line, ' ');
353 if (!name || strcmp(name+1, type))
356 maj = strtol(line, &name, 10);
366 end = strchr(line, '\n');
374 _is_ide_major (int major)
391 _is_cpqarray_major (int major)
393 return ((COMPAQ_SMART2_MAJOR <= major && major <= COMPAQ_SMART2_MAJOR7)
394 || (COMPAQ_SMART_MAJOR <= major && major <= COMPAQ_SMART_MAJOR7));
398 _is_i2o_major (int major)
400 return (I2O_MAJOR1 <= major && major <= I2O_MAJOR8);
404 _is_sx8_major (int major)
406 return (SX8_MAJOR1 <= major && major <= SX8_MAJOR2);
410 _is_virtblk_major (int major)
412 return _major_type_in_devices (major, "virtblk");
415 #ifdef ENABLE_DEVICE_MAPPER
417 _is_dm_major (int major)
419 return _major_type_in_devices (major, "device-mapper");
423 _dm_maptype (PedDevice *dev)
425 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
427 uint64_t start, length;
428 char *target_type = NULL;
431 const char* dev_dir = getenv ("DM_DEV_DIR");
433 if (dev_dir && *dev_dir && !dm_set_dev_dir(dev_dir))
436 if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
439 if (!dm_task_set_major_minor(dmt, arch_specific->major,
440 arch_specific->minor, 0))
443 dm_task_no_open_count(dmt);
445 if (!dm_task_run(dmt))
448 dm_get_next_target(dmt, NULL, &start, &length, &target_type, ¶ms);
450 arch_specific->dmtype = strdup(target_type ? target_type : "NO-TARGET");
451 if (arch_specific->dmtype == NULL)
455 dm_task_destroy(dmt);
465 char buf [512]; /* readdir(3) claims d_name[256] */
468 mapper_dir = opendir ("/dev/mapper");
472 /* Search the /dev/mapper directory for devices w/ the same major
473 * number that was returned from _probe_lvm_major().
475 while ((dent = readdir (mapper_dir))) {
476 if (strcmp (dent->d_name, ".") == 0 ||
477 strcmp (dent->d_name, "..") == 0)
480 snprintf (buf, sizeof (buf), "/dev/mapper/%s", dent->d_name);
482 if (stat (buf, &st) != 0)
485 if (_is_dm_major(major(st.st_rdev)))
486 _ped_device_probe (buf);
488 closedir (mapper_dir);
495 _device_stat (PedDevice* dev, struct stat * dev_stat)
497 PED_ASSERT (dev != NULL, return 0);
498 PED_ASSERT (!dev->external_mode, return 0);
501 if (!stat (dev->path, dev_stat)) {
504 if (ped_exception_throw (
506 PED_EXCEPTION_RETRY_CANCEL,
507 _("Could not stat device %s - %s."),
510 != PED_EXCEPTION_RETRY)
517 _device_probe_type (PedDevice* dev)
519 struct stat dev_stat;
522 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
524 if (!_device_stat (dev, &dev_stat))
527 if (!S_ISBLK(dev_stat.st_mode)) {
528 dev->type = PED_DEVICE_FILE;
532 arch_specific->major = dev_major = major (dev_stat.st_rdev);
533 arch_specific->minor = dev_minor = minor (dev_stat.st_rdev);
535 if (SCSI_BLK_MAJOR (dev_major) && (dev_minor % 0x10 == 0)) {
536 dev->type = PED_DEVICE_SCSI;
537 } else if (_is_ide_major (dev_major) && (dev_minor % 0x40 == 0)) {
538 dev->type = PED_DEVICE_IDE;
539 } else if (dev_major == DAC960_MAJOR && (dev_minor % 0x8 == 0)) {
540 dev->type = PED_DEVICE_DAC960;
541 } else if (dev_major == ATARAID_MAJOR && (dev_minor % 0x10 == 0)) {
542 dev->type = PED_DEVICE_ATARAID;
543 } else if (dev_major == DASD_MAJOR && (dev_minor % 0x4 == 0)) {
544 dev->type = PED_DEVICE_DASD;
545 } else if (dev_major == VIODASD_MAJOR && (dev_minor % 0x8 == 0)) {
546 dev->type = PED_DEVICE_VIODASD;
547 } else if (_is_sx8_major(dev_major) && (dev_minor % 0x20 == 0)) {
548 dev->type = PED_DEVICE_SX8;
549 } else if (_is_i2o_major (dev_major) && (dev_minor % 0x10 == 0)) {
550 dev->type = PED_DEVICE_I2O;
551 } else if (_is_cpqarray_major (dev_major) && (dev_minor % 0x10 == 0)) {
552 dev->type = PED_DEVICE_CPQARRAY;
553 } else if (dev_major == UBD_MAJOR && (dev_minor % 0x10 == 0)) {
554 dev->type = PED_DEVICE_UBD;
555 #ifdef ENABLE_DEVICE_MAPPER
556 } else if (_is_dm_major(dev_major)) {
557 dev->type = PED_DEVICE_DM;
558 if (_dm_maptype(dev)) {
559 ped_exception_throw (
561 PED_EXCEPTION_CANCEL,
562 _("Unable to determine the dm type of %s."),
566 } else if (dev_major == XVD_MAJOR && (dev_minor % 0x10 == 0)) {
567 dev->type = PED_DEVICE_XVD;
568 } else if (dev_major == SDMMC_MAJOR && (dev_minor % 0x08 == 0)) {
569 dev->type = PED_DEVICE_SDMMC;
570 } else if (_is_virtblk_major(dev_major)) {
571 dev->type = PED_DEVICE_VIRTBLK;
572 } else if (dev_major == LOOP_MAJOR) {
573 dev->type = PED_DEVICE_FILE;
575 dev->type = PED_DEVICE_UNKNOWN;
582 _get_linux_version ()
584 static int kver = -1;
596 if (sscanf (uts.release, "%u.%u.%u", &major, &minor, &teeny) != 3)
599 return kver = KERNEL_VERSION (major, minor, teeny);
605 static int have_kern26 = -1;
608 if (have_kern26 != -1)
611 kver = _get_linux_version();
612 return have_kern26 = kver >= KERNEL_VERSION (2,6,0) ? 1 : 0;
617 get_blkid_topology (LinuxSpecific *arch_specific)
619 arch_specific->probe = blkid_new_probe ();
620 if (!arch_specific->probe)
623 if (blkid_probe_set_device(arch_specific->probe,
624 arch_specific->fd, 0, 0))
627 arch_specific->topology =
628 blkid_probe_get_topology(arch_specific->probe);
633 _device_set_sector_size (PedDevice* dev)
635 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
638 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
639 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
641 PED_ASSERT (dev->open_count, return);
643 if (_get_linux_version() < KERNEL_VERSION (2,3,0)) {
644 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
648 if (ioctl (arch_specific->fd, BLKSSZGET, §or_size)) {
649 ped_exception_throw (
650 PED_EXCEPTION_WARNING,
652 _("Could not determine sector size for %s: %s.\n"
653 "Using the default sector size (%lld)."),
654 dev->path, strerror (errno), PED_SECTOR_SIZE_DEFAULT);
656 dev->sector_size = (long long)sector_size;
657 dev->phys_sector_size = dev->sector_size;
661 get_blkid_topology(arch_specific);
662 if (!arch_specific->topology) {
663 dev->phys_sector_size = 0;
665 dev->phys_sector_size =
666 blkid_topology_get_physical_sector_size(
667 arch_specific->topology);
669 if (dev->phys_sector_size == 0) {
670 ped_exception_throw (
671 PED_EXCEPTION_WARNING,
673 _("Could not determine physical sector size for %s.\n"
674 "Using the logical sector size (%lld)."),
675 dev->path, dev->sector_size);
676 dev->phys_sector_size = dev->sector_size;
680 #if defined __s390__ || defined __s390x__
681 /* Return PED_SECTOR_SIZE_DEFAULT for DASDs. */
682 if (dev->type == PED_DEVICE_DASD) {
683 arch_specific->real_sector_size = dev->sector_size;
684 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
688 if (dev->sector_size != PED_SECTOR_SIZE_DEFAULT) {
689 ped_exception_throw (
690 PED_EXCEPTION_WARNING,
692 _("Device %s has a logical sector size of %lld. Not "
693 "all parts of GNU Parted support this at the moment, "
694 "and the working code is HIGHLY EXPERIMENTAL.\n"),
695 dev->path, dev->sector_size);
700 _kernel_has_blkgetsize64(void)
702 int version = _get_linux_version();
704 if (version >= KERNEL_VERSION (2,5,4)) return 1;
705 if (version < KERNEL_VERSION (2,5,0) &&
706 version >= KERNEL_VERSION (2,4,18)) return 1;
710 /* TODO: do a binary search if BLKGETSIZE doesn't work?! */
712 _device_get_length (PedDevice* dev)
715 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
719 PED_ASSERT (dev->open_count > 0, return 0);
720 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
722 if (_kernel_has_blkgetsize64()) {
723 if (ioctl(arch_specific->fd, BLKGETSIZE64, &bytes) == 0) {
724 return bytes / dev->sector_size;
728 if (ioctl (arch_specific->fd, BLKGETSIZE, &size)) {
729 ped_exception_throw (
731 PED_EXCEPTION_CANCEL,
732 _("Unable to determine the size of %s (%s)."),
742 _device_probe_geometry (PedDevice* dev)
744 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
745 struct stat dev_stat;
746 struct hd_geometry geometry;
748 if (!_device_stat (dev, &dev_stat))
750 PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
752 _device_set_sector_size (dev);
754 dev->length = _device_get_length (dev);
758 /* The GETGEO ioctl is no longer useful (as of linux 2.6.x). We could
759 * still use it in 2.4.x, but this is contentious. Perhaps we should
761 dev->bios_geom.sectors = 63;
762 dev->bios_geom.heads = 255;
763 dev->bios_geom.cylinders
764 = dev->length / (63 * 255);
766 /* FIXME: what should we put here? (TODO: discuss on linux-kernel) */
767 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geometry)
768 && geometry.sectors && geometry.heads) {
769 dev->hw_geom.sectors = geometry.sectors;
770 dev->hw_geom.heads = geometry.heads;
771 dev->hw_geom.cylinders
772 = dev->length / (dev->hw_geom.heads
773 * dev->hw_geom.sectors);
775 dev->hw_geom = dev->bios_geom;
782 strip_name(char* str)
787 for (i = 0; str[i] != 0; i++) {
788 if (!isspace (str[i])
789 || (isspace (str[i]) && !isspace (str[i+1]) && str[i+1])) {
799 init_ide (PedDevice* dev)
801 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
802 struct stat dev_stat;
803 struct hd_driveid hdi;
804 PedExceptionOption ex_status;
806 int sector_multiplier = 0;
808 if (!_device_stat (dev, &dev_stat))
811 if (!ped_device_open (dev))
814 if (ioctl (arch_specific->fd, HDIO_GET_IDENTITY, &hdi)) {
815 ex_status = ped_exception_throw (
816 PED_EXCEPTION_WARNING,
817 PED_EXCEPTION_IGNORE_CANCEL,
818 _("Could not get identity of device %s - %s"),
819 dev->path, strerror (errno));
821 case PED_EXCEPTION_CANCEL:
822 goto error_close_dev;
824 case PED_EXCEPTION_UNHANDLED:
825 ped_exception_catch ();
826 case PED_EXCEPTION_IGNORE:
827 dev->model = strdup(_("Generic IDE"));
830 PED_ASSERT (0, (void) 0);
834 /* hdi.model is not guaranteed to be NULL terminated */
835 memcpy (hdi_buf, hdi.model, 40);
837 dev->model = strip_name (hdi_buf);
839 if (!hdi.ata7_sectinfo.valid1 && hdi.ata7_sectinfo.valid2)
840 sector_multiplier = hdi.ata7_sectinfo.multiplier;
842 sector_multiplier = 1;
844 if (sector_multiplier != 1) {
845 ex_status = ped_exception_throw (
846 PED_EXCEPTION_WARNING,
847 PED_EXCEPTION_IGNORE_CANCEL,
848 _("Device %s has multiple (%d) logical sectors "
849 "per physical sector.\n"
850 "GNU Parted supports this EXPERIMENTALLY for "
851 "some special disk label/file system "
852 "combinations, e.g. GPT and ext2/3.\n"
853 "Please consult the web site for up-to-date "
855 dev->path, sector_multiplier);
858 case PED_EXCEPTION_CANCEL:
859 goto error_close_dev;
861 case PED_EXCEPTION_UNHANDLED:
862 ped_exception_catch ();
863 case PED_EXCEPTION_IGNORE:
866 PED_ASSERT (0, (void) 0);
871 /* XXX sector_size has not been set yet! */
872 /* dev->phys_sector_size = dev->sector_size
873 * sector_multiplier;*/
874 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
877 if (!_device_probe_geometry (dev))
878 goto error_close_dev;
880 ped_device_close (dev);
884 ped_device_close (dev);
889 /* This function reads the /sys entry named "file" for device "dev". */
891 read_device_sysfs_file (PedDevice *dev, const char *file)
897 snprintf (name_buf, 127, "/sys/block/%s/device/%s",
898 last_component (dev->path), file);
900 if ((f = fopen (name_buf, "r")) == NULL)
903 if (fgets (buf, 255, f) == NULL)
907 return strip_name (buf);
910 /* This function sends a query to a SCSI device for vendor and product
911 * information. It uses the deprecated SCSI_IOCTL_SEND_COMMAND to
915 scsi_query_product_info (PedDevice* dev, char **vendor, char **product)
917 /* The following are defined by the SCSI-2 specification. */
918 typedef struct _scsi_inquiry_cmd
921 uint8_t lun; /* bits 5-7 denote the LUN */
924 uint8_t alloc_length;
926 } __attribute__((packed)) scsi_inquiry_cmd_t;
928 typedef struct _scsi_inquiry_data
930 uint8_t peripheral_info;
932 uint8_t version_info;
934 uint8_t additional_length;
938 uint8_t vendor_id[8];
939 uint8_t product_id[16];
940 uint8_t product_revision[4];
941 uint8_t vendor_specific[20];
942 uint8_t _reserved3[40];
943 } __attribute__((packed)) scsi_inquiry_data_t;
952 scsi_inquiry_data_t out;
953 scsi_inquiry_cmd_t in;
957 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
963 memset (&arg, 0x00, sizeof(struct scsi_arg));
965 arg.outlen = sizeof(scsi_inquiry_data_t);
966 arg.data.in.op = INQUIRY;
967 arg.data.in.lun = dev->host << 5;
968 arg.data.in.alloc_length = sizeof(scsi_inquiry_data_t);
969 arg.data.in.page_code = 0;
970 arg.data.in.reserved = 0;
971 arg.data.in.control = 0;
973 if (ioctl (arch_specific->fd, SCSI_IOCTL_SEND_COMMAND, &arg) < 0)
976 memcpy (buf, arg.data.out.vendor_id, 8);
978 *vendor = strip_name (buf);
980 memcpy (buf, arg.data.out.product_id, 16);
982 *product = strip_name (buf);
987 /* This function provides the vendor and product name for a SCSI device.
988 * It supports both the modern /sys interface and direct queries
989 * via the deprecated ioctl, SCSI_IOCTL_SEND_COMMAND.
992 scsi_get_product_info (PedDevice* dev, char **vendor, char **product)
994 *vendor = read_device_sysfs_file (dev, "vendor");
995 *product = read_device_sysfs_file (dev, "model");
996 if (*vendor && *product)
999 return scsi_query_product_info (dev, vendor, product);
1003 init_scsi (PedDevice* dev)
1008 uint32_t host_unique_id;
1011 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1015 if (!ped_device_open (dev))
1018 if (ioctl (arch_specific->fd, SCSI_IOCTL_GET_IDLUN, &idlun) < 0) {
1021 if (ped_exception_throw (
1022 PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
1023 _("Error initialising SCSI device %s - %s"),
1024 dev->path, strerror (errno))
1025 != PED_EXCEPTION_IGNORE)
1026 goto error_close_dev;
1027 if (!_device_probe_geometry (dev))
1028 goto error_close_dev;
1029 ped_device_close (dev);
1033 dev->host = idlun.host_unique_id;
1034 dev->did = idlun.dev_id;
1036 dev->model = (char*) ped_malloc (8 + 16 + 2);
1038 goto error_close_dev;
1040 if (scsi_get_product_info (dev, &vendor, &product)) {
1041 sprintf (dev->model, "%.8s %.16s", vendor, product);
1045 strcpy (dev->model, "Generic SCSI");
1048 if (!_device_probe_geometry (dev))
1049 goto error_close_dev;
1051 ped_device_close (dev);
1055 ped_device_close (dev);
1061 init_file (PedDevice* dev)
1063 struct stat dev_stat;
1065 if (!_device_stat (dev, &dev_stat))
1067 if (!ped_device_open (dev))
1070 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1071 char *p = getenv ("PARTED_SECTOR_SIZE");
1074 if (0 < s && s % 512 == 0)
1075 dev->sector_size = s;
1077 dev->phys_sector_size = dev->sector_size;
1079 if (S_ISBLK(dev_stat.st_mode))
1080 dev->length = _device_get_length (dev);
1082 dev->length = dev_stat.st_size / dev->sector_size;
1083 if (dev->length <= 0) {
1084 ped_exception_throw (
1085 PED_EXCEPTION_ERROR,
1086 PED_EXCEPTION_CANCEL,
1087 _("The device %s has zero length, and can't possibly "
1088 "store a file system or partition table. Perhaps "
1089 "you selected the wrong device?"),
1091 goto error_close_dev;
1094 ped_device_close (dev);
1096 dev->bios_geom.cylinders = dev->length / 4 / 32;
1097 dev->bios_geom.heads = 4;
1098 dev->bios_geom.sectors = 32;
1099 dev->hw_geom = dev->bios_geom;
1100 dev->model = strdup ("");
1105 ped_device_close (dev);
1110 #if defined __s390__ || defined __s390x__
1112 init_dasd (PedDevice* dev, const char* model_name)
1114 struct stat dev_stat;
1115 struct hd_geometry geo;
1116 dasd_information_t dasd_info;
1118 if (!_device_stat (dev, &dev_stat))
1121 if (!ped_device_open (dev))
1124 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1126 PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
1128 _device_set_sector_size (dev);
1129 if (!dev->sector_size)
1130 goto error_close_dev;
1132 dev->length = _device_get_length (dev);
1134 goto error_close_dev;
1136 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geo)) {
1137 dev->hw_geom.sectors = geo.sectors;
1138 dev->hw_geom.heads = geo.heads;
1139 dev->hw_geom.cylinders = dev->length
1140 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1141 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1142 dev->bios_geom = dev->hw_geom;
1144 dev->bios_geom.sectors = 12;
1145 dev->bios_geom.heads = 15;
1146 dev->bios_geom.cylinders = dev->length
1147 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1148 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1149 dev->hw_geom = dev->bios_geom;
1152 if (!ioctl(arch_specific->fd, BIODASDINFO, &dasd_info)) {
1153 arch_specific->devno = dasd_info.devno;
1155 arch_specific->devno = arch_specific->major * 256 +
1156 arch_specific->minor;
1159 dev->model = strdup (model_name);
1161 ped_device_close (dev);
1165 ped_device_close (dev);
1172 init_generic (PedDevice* dev, const char* model_name)
1174 struct stat dev_stat;
1175 PedExceptionOption ex_status;
1177 if (!_device_stat (dev, &dev_stat))
1180 if (!ped_device_open (dev))
1183 ped_exception_fetch_all ();
1184 if (_device_probe_geometry (dev)) {
1185 ped_exception_leave_all ();
1187 /* hack to allow use of files, for testing */
1188 ped_exception_catch ();
1189 ped_exception_leave_all ();
1191 ex_status = ped_exception_throw (
1192 PED_EXCEPTION_WARNING,
1193 PED_EXCEPTION_IGNORE_CANCEL,
1194 _("Unable to determine geometry of "
1195 "file/device %s. You should not use Parted "
1196 "unless you REALLY know what you're doing!"),
1198 switch (ex_status) {
1199 case PED_EXCEPTION_CANCEL:
1200 goto error_close_dev;
1202 case PED_EXCEPTION_UNHANDLED:
1203 ped_exception_catch ();
1204 case PED_EXCEPTION_IGNORE:
1207 PED_ASSERT (0, (void) 0);
1211 /* what should we stick in here? */
1212 dev->length = dev_stat.st_size / PED_SECTOR_SIZE_DEFAULT;
1213 dev->bios_geom.cylinders = dev->length / 4 / 32;
1214 dev->bios_geom.heads = 4;
1215 dev->bios_geom.sectors = 32;
1216 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1217 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
1220 dev->model = strdup (model_name);
1222 ped_device_close (dev);
1226 ped_device_close (dev);
1232 sdmmc_get_product_info (PedDevice* dev, char **type, char **name)
1234 *type = read_device_sysfs_file (dev, "type");
1235 *name = read_device_sysfs_file (dev, "name");
1243 init_sdmmc (PedDevice* dev)
1248 if (sdmmc_get_product_info (dev, &type, &name)) {
1249 snprintf (id, sizeof(id) - 1, "%s %s", type, name);
1253 snprintf (id, sizeof(id) - 1, "%s",
1254 _("Generic SD/MMC Storage Card"));
1256 return init_generic(dev, id);
1260 linux_new (const char* path)
1263 LinuxSpecific* arch_specific;
1265 PED_ASSERT (path != NULL, return NULL);
1267 dev = (PedDevice*) ped_malloc (sizeof (PedDevice));
1271 dev->path = strdup (path);
1273 goto error_free_dev;
1276 = (LinuxSpecific*) ped_malloc (sizeof (LinuxSpecific));
1277 if (!dev->arch_specific)
1278 goto error_free_path;
1279 arch_specific = LINUX_SPECIFIC (dev);
1280 arch_specific->dmtype = NULL;
1282 arch_specific->probe = NULL;
1283 arch_specific->topology = NULL;
1286 dev->open_count = 0;
1288 dev->external_mode = 0;
1290 dev->boot_dirty = 0;
1292 if (!_device_probe_type (dev))
1293 goto error_free_arch_specific;
1295 switch (dev->type) {
1296 case PED_DEVICE_IDE:
1297 if (!init_ide (dev))
1298 goto error_free_arch_specific;
1301 case PED_DEVICE_SCSI:
1302 if (!init_scsi (dev))
1303 goto error_free_arch_specific;
1306 case PED_DEVICE_DAC960:
1307 if (!init_generic (dev, _("DAC960 RAID controller")))
1308 goto error_free_arch_specific;
1311 case PED_DEVICE_SX8:
1312 if (!init_generic (dev, _("Promise SX8 SATA Device")))
1313 goto error_free_arch_specific;
1316 #if defined __s390__ || defined __s390x__
1317 case PED_DEVICE_DASD:
1318 if (!init_dasd (dev, _("IBM S390 DASD drive")))
1319 goto error_free_arch_specific;
1323 case PED_DEVICE_VIODASD:
1324 if (!init_generic (dev, _("IBM iSeries Virtual DASD")))
1325 goto error_free_arch_specific;
1328 case PED_DEVICE_CPQARRAY:
1329 if (!init_generic (dev, _("Compaq Smart Array")))
1330 goto error_free_arch_specific;
1333 case PED_DEVICE_ATARAID:
1334 if (!init_generic (dev, _("ATARAID Controller")))
1335 goto error_free_arch_specific;
1338 case PED_DEVICE_I2O:
1339 if (!init_generic (dev, _("I2O Controller")))
1340 goto error_free_arch_specific;
1343 case PED_DEVICE_UBD:
1344 if (!init_generic (dev, _("User-Mode Linux UBD")))
1345 goto error_free_arch_specific;
1348 case PED_DEVICE_FILE:
1349 if (!init_file (dev))
1350 goto error_free_arch_specific;
1356 if (arch_specific->dmtype == NULL
1357 || asprintf(&type, _("Linux device-mapper (%s)"),
1358 arch_specific->dmtype) == -1)
1359 goto error_free_arch_specific;
1360 bool ok = init_generic (dev, type);
1363 goto error_free_arch_specific;
1367 case PED_DEVICE_XVD:
1368 if (!init_generic (dev, _("Xen Virtual Block Device")))
1369 goto error_free_arch_specific;
1372 case PED_DEVICE_UNKNOWN:
1373 if (!init_generic (dev, _("Unknown")))
1374 goto error_free_arch_specific;
1377 case PED_DEVICE_SDMMC:
1378 if (!init_sdmmc (dev))
1379 goto error_free_arch_specific;
1381 case PED_DEVICE_VIRTBLK:
1382 if (!init_generic(dev, _("Virtio Block Device")))
1383 goto error_free_arch_specific;
1387 ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
1388 PED_EXCEPTION_CANCEL,
1389 _("ped_device_new() Unsupported device type"));
1390 goto error_free_arch_specific;
1394 error_free_arch_specific:
1395 free (dev->arch_specific);
1405 linux_destroy (PedDevice* dev)
1407 LinuxSpecific *arch_specific = LINUX_SPECIFIC(dev);
1408 void *p = arch_specific->dmtype;
1411 if (arch_specific->probe)
1412 blkid_free_probe(arch_specific->probe);
1415 free (dev->arch_specific);
1422 linux_is_busy (PedDevice* dev)
1427 if (_partition_is_mounted_by_path (dev->path))
1430 for (i = 0; i < 32; i++) {
1433 part_name = _device_get_part_path (dev, i);
1436 status = _partition_is_mounted_by_path (part_name);
1446 /* we need to flush the master device, and with kernel < 2.6 all the partition
1447 * devices, because there is no coherency between the caches with old kernels.
1448 * We should only flush unmounted partition devices, because:
1449 * - there is never a need to flush them (we're not doing IO there)
1450 * - flushing a device that is mounted causes unnecessary IO, and can
1451 * even screw journaling & friends up. Even cause oopsen!
1454 _flush_cache (PedDevice* dev)
1456 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1463 ioctl (arch_specific->fd, BLKFLSBUF);
1465 /* With linux-2.6.0 and newer, we're done. */
1469 for (i = 1; i < 16; i++) {
1473 name = _device_get_part_path (dev, i);
1476 if (!_partition_is_mounted_by_path (name)) {
1477 fd = open (name, WR_MODE, 0);
1479 ioctl (fd, BLKFLSBUF);
1481 if (fsync (fd) < 0 || close (fd) < 0)
1482 if (ped_exception_throw (
1483 PED_EXCEPTION_WARNING,
1484 PED_EXCEPTION_RETRY +
1485 PED_EXCEPTION_IGNORE,
1486 _("Error fsyncing/closing %s: %s"),
1487 name, strerror (errno))
1488 == PED_EXCEPTION_RETRY)
1497 linux_open (PedDevice* dev)
1499 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1502 arch_specific->fd = open (dev->path, RW_MODE);
1504 if (arch_specific->fd == -1) {
1505 char* rw_error_msg = strerror (errno);
1507 arch_specific->fd = open (dev->path, RD_MODE);
1509 if (arch_specific->fd == -1) {
1510 if (ped_exception_throw (
1511 PED_EXCEPTION_ERROR,
1512 PED_EXCEPTION_RETRY_CANCEL,
1513 _("Error opening %s: %s"),
1514 dev->path, strerror (errno))
1515 != PED_EXCEPTION_RETRY) {
1521 ped_exception_throw (
1522 PED_EXCEPTION_WARNING,
1524 _("Unable to open %s read-write (%s). %s has "
1525 "been opened read-only."),
1526 dev->path, rw_error_msg, dev->path);
1533 /* With kernels < 2.6 flush cache for cache coherence issues */
1534 if (!_have_kern26())
1541 linux_refresh_open (PedDevice* dev)
1547 linux_close (PedDevice* dev)
1549 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1554 if (fsync (arch_specific->fd) < 0 || close (arch_specific->fd) < 0)
1555 if (ped_exception_throw (
1556 PED_EXCEPTION_WARNING,
1557 PED_EXCEPTION_RETRY + PED_EXCEPTION_IGNORE,
1558 _("Error fsyncing/closing %s: %s"),
1559 dev->path, strerror (errno))
1560 == PED_EXCEPTION_RETRY)
1566 linux_refresh_close (PedDevice* dev)
1573 #if SIZEOF_OFF_T < 8
1575 static _syscall5(int,_llseek,
1577 unsigned long, offset_high,
1578 unsigned long, offset_low,
1580 unsigned int, origin)
1583 llseek (unsigned int fd, loff_t offset, unsigned int whence)
1588 retval = _llseek(fd,
1589 ((unsigned long long)offset) >> 32,
1590 ((unsigned long long)offset) & 0xffffffff,
1593 return (retval==-1 ? (loff_t) retval : result);
1596 #endif /* SIZEOF_OFF_T < 8 */
1599 _device_seek (const PedDevice* dev, PedSector sector)
1601 LinuxSpecific* arch_specific;
1603 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1604 PED_ASSERT (dev != NULL, return 0);
1605 PED_ASSERT (!dev->external_mode, return 0);
1607 arch_specific = LINUX_SPECIFIC (dev);
1609 #if SIZEOF_OFF_T < 8
1610 if (sizeof (off_t) < 8) {
1611 loff_t pos = (loff_t)(sector * dev->sector_size);
1612 return llseek (arch_specific->fd, pos, SEEK_SET) == pos;
1616 off_t pos = sector * dev->sector_size;
1617 return lseek (arch_specific->fd, pos, SEEK_SET) == pos;
1622 _read_lastoddsector (const PedDevice* dev, void* buffer)
1624 LinuxSpecific* arch_specific;
1625 struct blkdev_ioctl_param ioctl_param;
1627 PED_ASSERT(dev != NULL, return 0);
1628 PED_ASSERT(buffer != NULL, return 0);
1630 arch_specific = LINUX_SPECIFIC (dev);
1633 ioctl_param.block = 0; /* read the last sector */
1634 ioctl_param.content_length = dev->sector_size;
1635 ioctl_param.block_contents = buffer;
1637 if (ioctl(arch_specific->fd, BLKGETLASTSECT, &ioctl_param) == -1) {
1638 PedExceptionOption opt;
1639 opt = ped_exception_throw (
1640 PED_EXCEPTION_ERROR,
1641 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1642 _("%s during read on %s"),
1643 strerror (errno), dev->path);
1645 if (opt == PED_EXCEPTION_CANCEL)
1647 if (opt == PED_EXCEPTION_RETRY)
1655 linux_read (const PedDevice* dev, void* buffer, PedSector start,
1658 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1659 PedExceptionOption ex_status;
1660 void* diobuf = NULL;
1662 PED_ASSERT (dev != NULL, return 0);
1663 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1665 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1666 /* Kludge. This is necessary to read/write the last
1667 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1669 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1670 && start + count - 1 == dev->length - 1)
1671 return ped_device_read (dev, buffer, start, count - 1)
1672 && _read_lastoddsector (
1673 dev, (char *) buffer + (count-1) * 512);
1676 if (_device_seek (dev, start))
1679 ex_status = ped_exception_throw (
1680 PED_EXCEPTION_ERROR,
1681 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1682 _("%s during seek for read on %s"),
1683 strerror (errno), dev->path);
1685 switch (ex_status) {
1686 case PED_EXCEPTION_IGNORE:
1689 case PED_EXCEPTION_RETRY:
1692 case PED_EXCEPTION_UNHANDLED:
1693 ped_exception_catch ();
1694 case PED_EXCEPTION_CANCEL:
1697 PED_ASSERT (0, (void) 0);
1702 size_t read_length = count * dev->sector_size;
1703 if (posix_memalign (&diobuf, dev->sector_size, read_length) != 0)
1707 ssize_t status = read (arch_specific->fd, diobuf, read_length);
1709 memcpy(buffer, diobuf, status);
1710 if (status == (ssize_t) read_length)
1713 read_length -= status;
1714 buffer = (char *) buffer + status;
1718 ex_status = ped_exception_throw (
1719 PED_EXCEPTION_ERROR,
1720 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1722 ? _("end of file while reading %s")
1723 : _("%s during read on %s")),
1727 switch (ex_status) {
1728 case PED_EXCEPTION_IGNORE:
1732 case PED_EXCEPTION_RETRY:
1735 case PED_EXCEPTION_UNHANDLED:
1736 ped_exception_catch ();
1737 case PED_EXCEPTION_CANCEL:
1741 PED_ASSERT (0, (void) 0);
1752 _write_lastoddsector (PedDevice* dev, const void* buffer)
1754 LinuxSpecific* arch_specific;
1755 struct blkdev_ioctl_param ioctl_param;
1757 PED_ASSERT(dev != NULL, return 0);
1758 PED_ASSERT(buffer != NULL, return 0);
1760 arch_specific = LINUX_SPECIFIC (dev);
1763 ioctl_param.block = 0; /* write the last sector */
1764 ioctl_param.content_length = dev->sector_size;
1765 ioctl_param.block_contents = (void*) buffer;
1767 if (ioctl(arch_specific->fd, BLKSETLASTSECT, &ioctl_param) == -1) {
1768 PedExceptionOption opt;
1769 opt = ped_exception_throw (
1770 PED_EXCEPTION_ERROR,
1771 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1772 _("%s during write on %s"),
1773 strerror (errno), dev->path);
1775 if (opt == PED_EXCEPTION_CANCEL)
1777 if (opt == PED_EXCEPTION_RETRY)
1785 linux_write (PedDevice* dev, const void* buffer, PedSector start,
1788 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1789 PedExceptionOption ex_status;
1793 PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1795 if (dev->read_only) {
1796 if (ped_exception_throw (
1797 PED_EXCEPTION_ERROR,
1798 PED_EXCEPTION_IGNORE_CANCEL,
1799 _("Can't write to %s, because it is opened read-only."),
1801 != PED_EXCEPTION_IGNORE)
1807 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1808 /* Kludge. This is necessary to read/write the last
1809 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1811 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1812 && start + count - 1 == dev->length - 1)
1813 return ped_device_write (dev, buffer, start, count - 1)
1814 && _write_lastoddsector (
1815 dev, ((char*) buffer
1816 + (count-1) * dev->sector_size));
1819 if (_device_seek (dev, start))
1822 ex_status = ped_exception_throw (
1823 PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1824 _("%s during seek for write on %s"),
1825 strerror (errno), dev->path);
1827 switch (ex_status) {
1828 case PED_EXCEPTION_IGNORE:
1831 case PED_EXCEPTION_RETRY:
1834 case PED_EXCEPTION_UNHANDLED:
1835 ped_exception_catch ();
1836 case PED_EXCEPTION_CANCEL:
1839 PED_ASSERT (0, (void) 0);
1845 printf ("ped_device_write (\"%s\", %p, %d, %d)\n",
1846 dev->path, buffer, (int) start, (int) count);
1848 size_t write_length = count * dev->sector_size;
1850 if (posix_memalign(&diobuf, dev->sector_size, write_length) != 0)
1852 memcpy(diobuf, buffer, write_length);
1853 diobuf_start = diobuf;
1855 ssize_t status = write (arch_specific->fd, diobuf, write_length);
1856 if (status == write_length) break;
1858 write_length -= status;
1859 diobuf = (char *) diobuf + status;
1863 ex_status = ped_exception_throw (
1864 PED_EXCEPTION_ERROR,
1865 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1866 _("%s during write on %s"),
1867 strerror (errno), dev->path);
1869 switch (ex_status) {
1870 case PED_EXCEPTION_IGNORE:
1874 case PED_EXCEPTION_RETRY:
1877 case PED_EXCEPTION_UNHANDLED:
1878 ped_exception_catch ();
1879 case PED_EXCEPTION_CANCEL:
1883 PED_ASSERT (0, (void) 0);
1888 #endif /* !READ_ONLY */
1892 /* returns the number of sectors that are ok.
1895 linux_check (PedDevice* dev, void* buffer, PedSector start, PedSector count)
1897 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1902 PED_ASSERT(dev != NULL, return 0);
1904 if (!_device_seek (dev, start))
1907 if (posix_memalign(&diobuf, PED_SECTOR_SIZE_DEFAULT,
1908 count * PED_SECTOR_SIZE_DEFAULT) != 0)
1911 for (done = 0; done < count; done += status / dev->sector_size) {
1912 status = read (arch_specific->fd, diobuf,
1913 (size_t) ((count-done) * dev->sector_size));
1915 memcpy(buffer, diobuf, status);
1925 _do_fsync (PedDevice* dev)
1927 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1929 PedExceptionOption ex_status;
1932 status = fsync (arch_specific->fd);
1933 if (status >= 0) break;
1935 ex_status = ped_exception_throw (
1936 PED_EXCEPTION_ERROR,
1937 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1938 _("%s during write on %s"),
1939 strerror (errno), dev->path);
1941 switch (ex_status) {
1942 case PED_EXCEPTION_IGNORE:
1945 case PED_EXCEPTION_RETRY:
1948 case PED_EXCEPTION_UNHANDLED:
1949 ped_exception_catch ();
1950 case PED_EXCEPTION_CANCEL:
1953 PED_ASSERT (0, (void) 0);
1961 linux_sync (PedDevice* dev)
1963 PED_ASSERT (dev != NULL, return 0);
1964 PED_ASSERT (!dev->external_mode, return 0);
1968 if (!_do_fsync (dev))
1975 linux_sync_fast (PedDevice* dev)
1977 PED_ASSERT (dev != NULL, return 0);
1978 PED_ASSERT (!dev->external_mode, return 0);
1982 if (!_do_fsync (dev))
1984 /* no cache flush... */
1989 _compare_digit_state (char ch, int need_digit)
1991 return !!isdigit (ch) == need_digit;
1994 /* matches the regexp "[^0-9]+[0-9]+[^0-9]+[0-9]+$".
1995 * Motivation: accept devices looking like /dev/rd/c0d0, but
1996 * not looking like /dev/hda1 and /dev/rd/c0d0p1
1999 _match_rd_device (const char* name)
2004 /* exclude directory names from test */
2005 pos = strrchr(name, '/') ?: name;
2013 for (state = 0; state < 4; state++) {
2014 int want_digits = (state % 2 == 1);
2018 if (!_compare_digit_state (*pos, want_digits))
2021 } while (_compare_digit_state (*pos, want_digits));
2028 _probe_proc_partitions ()
2030 FILE* proc_part_file;
2031 int major, minor, size;
2033 char part_name [256];
2034 char dev_name [256];
2036 proc_part_file = fopen ("/proc/partitions", "r");
2037 if (!proc_part_file)
2040 if (fgets (buf, 256, proc_part_file) == NULL)
2043 if (fgets (buf, 256, proc_part_file) == NULL)
2046 while (fgets (buf, 512, proc_part_file)
2047 && sscanf (buf, "%d %d %d %255s", &major, &minor, &size,
2049 /* Heuristic for telling partitions and devices apart
2050 * Probably needs to be improved
2052 if (!_match_rd_device (part_name)
2053 && isdigit (part_name [strlen (part_name) - 1]))
2056 strcpy (dev_name, "/dev/");
2057 strcat (dev_name, part_name);
2058 _ped_device_probe (dev_name);
2061 fclose (proc_part_file);
2071 _skip_entry (const char *name)
2074 static struct _entry entries[] = {
2075 { ".", sizeof (".") - 1 },
2076 { "..", sizeof ("..") - 1 },
2077 { "dm-", sizeof ("dm-") - 1 },
2078 { "loop", sizeof ("loop") - 1 },
2079 { "ram", sizeof ("ram") - 1 },
2083 for (i = entries; i->name != 0; i++) {
2084 if (strncmp (name, i->name, i->len) == 0)
2095 struct dirent *dirent;
2096 char dev_name [256];
2099 if (!(blockdir = opendir ("/sys/block")))
2101 while ((dirent = readdir (blockdir))) {
2102 if (_skip_entry (dirent->d_name))
2105 if (strlen (dirent->d_name) > sizeof (dev_name) - 6)
2106 continue; /* device name too long! */
2108 strcpy (dev_name, "/dev/");
2109 strcat (dev_name, dirent->d_name);
2110 /* in /sys/block, '/'s are replaced with '!' or '.' */
2111 for (ptr = dev_name; *ptr != '\0'; ptr++) {
2112 if (*ptr == '!' || *ptr == '.')
2115 _ped_device_probe (dev_name);
2118 closedir (blockdir);
2123 _probe_standard_devices ()
2125 _ped_device_probe ("/dev/hda");
2126 _ped_device_probe ("/dev/hdb");
2127 _ped_device_probe ("/dev/hdc");
2128 _ped_device_probe ("/dev/hdd");
2129 _ped_device_probe ("/dev/hde");
2130 _ped_device_probe ("/dev/hdf");
2131 _ped_device_probe ("/dev/hdg");
2132 _ped_device_probe ("/dev/hdh");
2134 _ped_device_probe ("/dev/sda");
2135 _ped_device_probe ("/dev/sdb");
2136 _ped_device_probe ("/dev/sdc");
2137 _ped_device_probe ("/dev/sdd");
2138 _ped_device_probe ("/dev/sde");
2139 _ped_device_probe ("/dev/sdf");
2147 /* we should probe the standard devs too, even with /proc/partitions,
2148 * because /proc/partitions might return devfs stuff, and we might not
2149 * have devfs available
2151 _probe_standard_devices ();
2153 #ifdef ENABLE_DEVICE_MAPPER
2154 /* device-mapper devices aren't listed in /proc/partitions; or, if
2155 * they are, they're listed as dm-X. So, instead of relying on that,
2156 * we do our own checks.
2158 _probe_dm_devices ();
2161 /* /sys/block is more reliable and consistent; fall back to using
2162 * /proc/partitions if the former is unavailable, however.
2164 if (!_probe_sys_block ())
2165 _probe_proc_partitions ();
2169 _device_get_part_path (PedDevice* dev, int num)
2171 int path_len = strlen (dev->path);
2172 int result_len = path_len + 16;
2175 result = (char*) ped_malloc (result_len);
2179 /* Check for devfs-style /disc => /partN transformation
2180 unconditionally; the system might be using udev with devfs rules,
2181 and if not the test is harmless. */
2182 if (!strcmp (dev->path + path_len - 5, "/disc")) {
2183 /* replace /disc with /path%d */
2184 strcpy (result, dev->path);
2185 snprintf (result + path_len - 5, 16, "/part%d", num);
2186 } else if (dev->type == PED_DEVICE_DAC960
2187 || dev->type == PED_DEVICE_CPQARRAY
2188 || dev->type == PED_DEVICE_ATARAID
2189 || dev->type == PED_DEVICE_DM
2190 || isdigit (dev->path[path_len - 1]))
2191 snprintf (result, result_len, "%sp%d", dev->path, num);
2193 snprintf (result, result_len, "%s%d", dev->path, num);
2199 linux_partition_get_path (const PedPartition* part)
2201 return _device_get_part_path (part->disk->dev, part->num);
2205 _partition_get_part_dev (const PedPartition* part)
2207 struct stat dev_stat;
2208 int dev_major, dev_minor;
2210 if (stat (part->disk->dev->path, &dev_stat))
2212 dev_major = major (dev_stat.st_rdev);
2213 dev_minor = minor (dev_stat.st_rdev);
2214 return (dev_t)makedev (dev_major, dev_minor + part->num);
2218 _mount_table_search (const char* file_name, dev_t dev)
2220 struct stat part_stat;
2222 char part_name[512];
2225 file = fopen (file_name, "r");
2228 while (fgets (line, 512, file)) {
2229 if (sscanf (line, "%s", part_name) == 1
2230 && stat (part_name, &part_stat) == 0) {
2231 if (part_stat.st_rdev == dev) {
2242 _partition_is_mounted_by_dev (dev_t dev)
2244 return _mount_table_search( "/proc/mounts", dev)
2245 || _mount_table_search( "/proc/swaps", dev)
2246 || _mount_table_search( "/etc/mtab", dev);
2250 _partition_is_mounted_by_path (const char *path)
2252 struct stat part_stat;
2253 if (stat (path, &part_stat) != 0)
2255 if (!S_ISBLK(part_stat.st_mode))
2257 return _partition_is_mounted_by_dev (part_stat.st_rdev);
2261 _partition_is_mounted (const PedPartition *part)
2264 if (!ped_partition_is_active (part))
2266 dev = _partition_get_part_dev (part);
2269 return _partition_is_mounted_by_dev (dev);
2273 _has_partitions (const PedDisk* disk)
2275 PED_ASSERT(disk != NULL, return 0);
2277 /* Some devices can't be partitioned. */
2278 if (!strcmp (disk->type->name, "loop"))
2285 linux_partition_is_busy (const PedPartition* part)
2289 PED_ASSERT (part != NULL, return 0);
2291 if (_partition_is_mounted (part))
2293 if (part->type == PED_PARTITION_EXTENDED) {
2294 for (walk = part->part_list; walk; walk = walk->next) {
2295 if (linux_partition_is_busy (walk))
2302 #ifdef ENABLE_DEVICE_MAPPER
2304 _dm_remove_map_name(char *name)
2306 struct dm_task *task = NULL;
2309 task = dm_task_create(DM_DEVICE_REMOVE);
2313 dm_task_set_name (task, name);
2315 rc = dm_task_run(task);
2316 dm_task_update_nodes();
2317 dm_task_destroy(task);
2325 _dm_is_part (struct dm_info *this, char *name)
2327 struct dm_task* task = NULL;
2328 struct dm_info* info = alloca(sizeof *info);
2329 struct dm_deps* deps = NULL;
2333 task = dm_task_create(DM_DEVICE_DEPS);
2337 dm_task_set_name(task, name);
2338 rc = dm_task_run(task);
2345 memset(info, '\0', sizeof *info);
2346 dm_task_get_info(task, info);
2350 deps = dm_task_get_deps(task);
2355 for (i = 0; i < deps->count; i++) {
2356 unsigned int ma = major(deps->device[i]),
2357 mi = minor(deps->device[i]);
2359 if (ma == this->major && mi == this->minor)
2364 dm_task_destroy(task);
2369 _dm_remove_parts (PedDevice* dev)
2371 struct dm_task* task = NULL;
2372 struct dm_info* info = alloca(sizeof *info);
2373 struct dm_names* names = NULL;
2374 unsigned int next = 0;
2376 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2378 task = dm_task_create(DM_DEVICE_LIST);
2382 if (!dm_task_set_major_minor (task, arch_specific->major,
2383 arch_specific->minor, 0))
2386 rc = dm_task_run(task);
2390 memset(info, '\0', sizeof *info);
2391 dm_task_get_info(task, info);
2395 names = dm_task_get_names(task);
2401 names = (void *) ((char *) names + next);
2403 if (_dm_is_part(info, names->name))
2404 rc += _dm_remove_map_name(names->name);
2409 dm_task_update_nodes();
2410 dm_task_destroy(task);
2417 dm_task_destroy(task);
2418 ped_exception_throw (PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE,
2419 _("parted was unable to re-read the partition "
2420 "table on %s (%s). This means Linux won't know "
2421 "anything about the modifications you made. "),
2422 dev->path, strerror (errno));
2427 _dm_add_partition (PedDisk* disk, PedPartition* part)
2430 char* vol_name = NULL;
2431 const char* dev_name = NULL;
2432 char* params = NULL;
2433 LinuxSpecific* arch_specific = LINUX_SPECIFIC (disk->dev);
2435 if (!_has_partitions(disk))
2438 /* Get map name from devicemapper */
2439 struct dm_task *task = dm_task_create (DM_DEVICE_INFO);
2443 if (!dm_task_set_major_minor (task, arch_specific->major,
2444 arch_specific->minor, 0))
2447 rc = dm_task_run(task);
2451 dev_name = dm_task_get_name (task);
2453 if (asprintf (&vol_name, "%sp%d", dev_name, part->num) == -1)
2456 /* Caution: dm_task_destroy frees dev_name. */
2457 dm_task_destroy (task);
2460 if (asprintf (¶ms, "%d:%d %lld", arch_specific->major,
2461 arch_specific->minor, part->geom.start) == -1)
2464 task = dm_task_create (DM_DEVICE_CREATE);
2468 dm_task_set_name (task, vol_name);
2469 dm_task_add_target (task, 0, part->geom.length,
2471 rc = dm_task_run (task);
2473 //printf("0 %ld linear %s\n", part->geom.length, params);
2474 dm_task_update_nodes();
2475 dm_task_destroy(task);
2480 _dm_remove_map_name(vol_name);
2483 dm_task_update_nodes();
2485 dm_task_destroy (task);
2492 _dm_reread_part_table (PedDisk* disk)
2494 int largest_partnum = ped_disk_get_last_partition_num (disk);
2495 if (largest_partnum <= 0)
2499 int last = PED_MIN (largest_partnum, 16);
2503 if (!_dm_remove_parts(disk->dev))
2506 for (i = 1; i <= last; i++) {
2509 part = ped_disk_get_partition (disk, i);
2513 if (!_dm_add_partition (disk, part))
2521 _kernel_reread_part_table (PedDevice* dev)
2523 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2524 int retry_count = 5;
2527 while (ioctl (arch_specific->fd, BLKRRPART)) {
2531 ped_exception_throw (
2532 PED_EXCEPTION_WARNING,
2533 PED_EXCEPTION_IGNORE,
2534 _("WARNING: the kernel failed to re-read the partition "
2535 "table on %s (%s). As a result, it may not "
2536 "reflect all of your changes until after reboot."),
2537 dev->path, strerror (errno));
2546 linux_disk_commit (PedDisk* disk)
2548 if (!_has_partitions (disk))
2551 #ifdef ENABLE_DEVICE_MAPPER
2552 if (disk->dev->type == PED_DEVICE_DM)
2553 return _dm_reread_part_table (disk);
2555 if (disk->dev->type != PED_DEVICE_FILE) {
2556 return _kernel_reread_part_table (disk->dev);
2564 linux_get_minimum_alignment(const PedDevice *dev)
2566 blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
2570 if (blkid_topology_get_minimum_io_size(tp) == 0)
2571 return ped_alignment_new(
2572 blkid_topology_get_alignment_offset(tp) /
2574 dev->phys_sector_size / dev->sector_size);
2576 return ped_alignment_new(
2577 blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2578 blkid_topology_get_minimum_io_size(tp) / dev->sector_size);
2582 linux_get_optimum_alignment(const PedDevice *dev)
2584 blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
2588 /* If optimal_io_size is 0 _and_ alignment_offset is 0 _and_
2589 minimum_io_size is a power of 2 then go with the device.c default */
2590 unsigned long minimum_io_size = blkid_topology_get_minimum_io_size(tp);
2591 if (blkid_topology_get_optimal_io_size(tp) == 0 &&
2592 blkid_topology_get_alignment_offset(tp) == 0 &&
2593 (minimum_io_size & (minimum_io_size - 1)) == 0)
2596 /* If optimal_io_size is 0 and we don't meet the other criteria
2597 for using the device.c default, return the minimum alignment. */
2598 if (blkid_topology_get_optimal_io_size(tp) == 0)
2599 return linux_get_minimum_alignment(dev);
2601 return ped_alignment_new(
2602 blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2603 blkid_topology_get_optimal_io_size(tp) / dev->sector_size);
2607 static PedDeviceArchOps linux_dev_ops = {
2609 destroy: linux_destroy,
2610 is_busy: linux_is_busy,
2612 refresh_open: linux_refresh_open,
2614 refresh_close: linux_refresh_close,
2619 sync_fast: linux_sync_fast,
2620 probe_all: linux_probe_all,
2622 get_minimum_alignment: linux_get_minimum_alignment,
2623 get_optimum_alignment: linux_get_optimum_alignment,
2627 PedDiskArchOps linux_disk_ops = {
2628 partition_get_path: linux_partition_get_path,
2629 partition_is_busy: linux_partition_is_busy,
2630 disk_commit: linux_disk_commit
2633 PedArchitecture ped_linux_arch = {
2634 dev_ops: &linux_dev_ops,
2635 disk_ops: &linux_disk_ops