1 /* libparted - a library for manipulating disk partitions
2 Copyright (C) 1999-2010 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 AOE_MAJOR 152
253 #define SX8_MAJOR1 160
254 #define SX8_MAJOR2 161
255 #define XVD_MAJOR 202
256 #define SDMMC_MAJOR 179
259 #define SCSI_BLK_MAJOR(M) ( \
260 (M) == SCSI_DISK0_MAJOR \
261 || (M) == SCSI_CDROM_MAJOR \
262 || ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
264 /* Maximum number of partitions supported by linux. */
265 #define MAX_NUM_PARTS 64
267 static char* _device_get_part_path (PedDevice* dev, int num);
268 static int _partition_is_mounted_by_path (const char* path);
271 _read_fd (int fd, char **buf)
274 size_t size = PROC_DEVICES_BUFSIZ;
277 *buf = malloc (size * sizeof (char));
283 p = &(*buf) [filesize];
284 s = read (fd, p, PROC_DEVICES_BUFSIZ);
285 /* exit if there is an error or EOF is reached */
290 char *new_buf = realloc (*buf, size);
291 if (new_buf == NULL) {
292 int saved_errno = errno;
300 if (filesize == 0 && s < 0) {
305 char *new_buf = realloc (*buf, filesize + 1);
306 if (new_buf == NULL) {
307 int saved_errno = errno;
313 (*buf)[filesize] = '\0';
320 _major_type_in_devices (int major, const char* type)
329 fd = open ("/proc/devices", O_RDONLY);
333 if (_read_fd(fd, &buf) < 0) {
339 end = strchr(line, '\n');
348 if (!strncmp(line, "Block devices:", 14))
353 name = strrchr(line, ' ');
354 if (!name || strcmp(name+1, type))
357 maj = strtol(line, &name, 10);
367 end = strchr(line, '\n');
375 _is_ide_major (int major)
392 _is_cpqarray_major (int major)
394 return ((COMPAQ_SMART2_MAJOR <= major && major <= COMPAQ_SMART2_MAJOR7)
395 || (COMPAQ_SMART_MAJOR <= major && major <= COMPAQ_SMART_MAJOR7));
399 _is_i2o_major (int major)
401 return (I2O_MAJOR1 <= major && major <= I2O_MAJOR8);
405 _is_sx8_major (int major)
407 return (SX8_MAJOR1 <= major && major <= SX8_MAJOR2);
411 _is_virtblk_major (int major)
413 return _major_type_in_devices (major, "virtblk");
416 #ifdef ENABLE_DEVICE_MAPPER
418 _is_dm_major (int major)
420 return _major_type_in_devices (major, "device-mapper");
424 _dm_maptype (PedDevice *dev)
426 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
428 uint64_t start, length;
429 char *target_type = NULL;
432 const char* dev_dir = getenv ("DM_DEV_DIR");
434 if (dev_dir && *dev_dir && !dm_set_dev_dir(dev_dir))
437 if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
440 if (!dm_task_set_major_minor(dmt, arch_specific->major,
441 arch_specific->minor, 0))
444 dm_task_no_open_count(dmt);
446 if (!dm_task_run(dmt))
449 dm_get_next_target(dmt, NULL, &start, &length, &target_type, ¶ms);
451 arch_specific->dmtype = strdup(target_type ? target_type : "NO-TARGET");
452 if (arch_specific->dmtype == NULL)
456 dm_task_destroy(dmt);
466 char buf [512]; /* readdir(3) claims d_name[256] */
469 mapper_dir = opendir ("/dev/mapper");
473 /* Search the /dev/mapper directory for devices w/ the same major
474 * number that was returned from _probe_lvm_major().
476 while ((dent = readdir (mapper_dir))) {
477 if (strcmp (dent->d_name, ".") == 0 ||
478 strcmp (dent->d_name, "..") == 0)
481 snprintf (buf, sizeof (buf), "/dev/mapper/%s", dent->d_name);
483 if (stat (buf, &st) != 0)
486 if (_is_dm_major(major(st.st_rdev)))
487 _ped_device_probe (buf);
489 closedir (mapper_dir);
496 _device_stat (PedDevice* dev, struct stat * dev_stat)
498 PED_ASSERT (dev != NULL, return 0);
499 PED_ASSERT (!dev->external_mode, return 0);
502 if (!stat (dev->path, dev_stat)) {
505 if (ped_exception_throw (
507 PED_EXCEPTION_RETRY_CANCEL,
508 _("Could not stat device %s - %s."),
511 != PED_EXCEPTION_RETRY)
518 _device_probe_type (PedDevice* dev)
520 struct stat dev_stat;
523 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
525 if (!_device_stat (dev, &dev_stat))
528 if (!S_ISBLK(dev_stat.st_mode)) {
529 dev->type = PED_DEVICE_FILE;
533 arch_specific->major = dev_major = major (dev_stat.st_rdev);
534 arch_specific->minor = dev_minor = minor (dev_stat.st_rdev);
536 if (SCSI_BLK_MAJOR (dev_major) && (dev_minor % 0x10 == 0)) {
537 dev->type = PED_DEVICE_SCSI;
538 } else if (_is_ide_major (dev_major) && (dev_minor % 0x40 == 0)) {
539 dev->type = PED_DEVICE_IDE;
540 } else if (dev_major == DAC960_MAJOR && (dev_minor % 0x8 == 0)) {
541 dev->type = PED_DEVICE_DAC960;
542 } else if (dev_major == ATARAID_MAJOR && (dev_minor % 0x10 == 0)) {
543 dev->type = PED_DEVICE_ATARAID;
544 } else if (dev_major == AOE_MAJOR && (dev_minor % 0x10 == 0)) {
545 dev->type = PED_DEVICE_AOE;
546 } else if (dev_major == DASD_MAJOR && (dev_minor % 0x4 == 0)) {
547 dev->type = PED_DEVICE_DASD;
548 } else if (dev_major == VIODASD_MAJOR && (dev_minor % 0x8 == 0)) {
549 dev->type = PED_DEVICE_VIODASD;
550 } else if (_is_sx8_major(dev_major) && (dev_minor % 0x20 == 0)) {
551 dev->type = PED_DEVICE_SX8;
552 } else if (_is_i2o_major (dev_major) && (dev_minor % 0x10 == 0)) {
553 dev->type = PED_DEVICE_I2O;
554 } else if (_is_cpqarray_major (dev_major) && (dev_minor % 0x10 == 0)) {
555 dev->type = PED_DEVICE_CPQARRAY;
556 } else if (dev_major == UBD_MAJOR && (dev_minor % 0x10 == 0)) {
557 dev->type = PED_DEVICE_UBD;
558 #ifdef ENABLE_DEVICE_MAPPER
559 } else if (_is_dm_major(dev_major)) {
560 dev->type = PED_DEVICE_DM;
561 if (_dm_maptype(dev)) {
562 ped_exception_throw (
564 PED_EXCEPTION_CANCEL,
565 _("Unable to determine the dm type of %s."),
569 } else if (dev_major == XVD_MAJOR && (dev_minor % 0x10 == 0)) {
570 dev->type = PED_DEVICE_XVD;
571 } else if (dev_major == SDMMC_MAJOR && (dev_minor % 0x08 == 0)) {
572 dev->type = PED_DEVICE_SDMMC;
573 } else if (_is_virtblk_major(dev_major)) {
574 dev->type = PED_DEVICE_VIRTBLK;
575 } else if (dev_major == LOOP_MAJOR) {
576 dev->type = PED_DEVICE_FILE;
578 dev->type = PED_DEVICE_UNKNOWN;
585 _get_linux_version ()
587 static int kver = -1;
599 if (sscanf (uts.release, "%u.%u.%u", &major, &minor, &teeny) != 3)
602 return kver = KERNEL_VERSION (major, minor, teeny);
608 static int have_kern26 = -1;
611 if (have_kern26 != -1)
614 kver = _get_linux_version();
615 return have_kern26 = kver >= KERNEL_VERSION (2,6,0) ? 1 : 0;
620 get_blkid_topology (LinuxSpecific *arch_specific)
622 arch_specific->probe = blkid_new_probe ();
623 if (!arch_specific->probe)
626 if (blkid_probe_set_device(arch_specific->probe,
627 arch_specific->fd, 0, 0))
630 arch_specific->topology =
631 blkid_probe_get_topology(arch_specific->probe);
636 _device_set_sector_size (PedDevice* dev)
638 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
641 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
642 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
644 PED_ASSERT (dev->open_count, return);
646 if (_get_linux_version() < KERNEL_VERSION (2,3,0)) {
647 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
651 if (ioctl (arch_specific->fd, BLKSSZGET, §or_size)) {
652 ped_exception_throw (
653 PED_EXCEPTION_WARNING,
655 _("Could not determine sector size for %s: %s.\n"
656 "Using the default sector size (%lld)."),
657 dev->path, strerror (errno), PED_SECTOR_SIZE_DEFAULT);
659 dev->sector_size = (long long)sector_size;
660 dev->phys_sector_size = dev->sector_size;
664 get_blkid_topology(arch_specific);
665 if (!arch_specific->topology) {
666 dev->phys_sector_size = 0;
668 dev->phys_sector_size =
669 blkid_topology_get_physical_sector_size(
670 arch_specific->topology);
672 if (dev->phys_sector_size == 0) {
673 ped_exception_throw (
674 PED_EXCEPTION_WARNING,
676 _("Could not determine physical sector size for %s.\n"
677 "Using the logical sector size (%lld)."),
678 dev->path, dev->sector_size);
679 dev->phys_sector_size = dev->sector_size;
683 #if defined __s390__ || defined __s390x__
684 /* Return PED_SECTOR_SIZE_DEFAULT for DASDs. */
685 if (dev->type == PED_DEVICE_DASD) {
686 arch_specific->real_sector_size = dev->sector_size;
687 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
693 _kernel_has_blkgetsize64(void)
695 int version = _get_linux_version();
697 if (version >= KERNEL_VERSION (2,5,4)) return 1;
698 if (version < KERNEL_VERSION (2,5,0) &&
699 version >= KERNEL_VERSION (2,4,18)) return 1;
703 /* TODO: do a binary search if BLKGETSIZE doesn't work?! */
705 _device_get_length (PedDevice* dev)
708 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
712 PED_ASSERT (dev->open_count > 0, return 0);
713 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
715 if (_kernel_has_blkgetsize64()) {
716 if (ioctl(arch_specific->fd, BLKGETSIZE64, &bytes) == 0) {
717 return bytes / dev->sector_size;
721 if (ioctl (arch_specific->fd, BLKGETSIZE, &size)) {
722 ped_exception_throw (
724 PED_EXCEPTION_CANCEL,
725 _("Unable to determine the size of %s (%s)."),
735 _device_probe_geometry (PedDevice* dev)
737 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
738 struct stat dev_stat;
739 struct hd_geometry geometry;
741 if (!_device_stat (dev, &dev_stat))
743 PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
745 _device_set_sector_size (dev);
747 dev->length = _device_get_length (dev);
751 /* The GETGEO ioctl is no longer useful (as of linux 2.6.x). We could
752 * still use it in 2.4.x, but this is contentious. Perhaps we should
754 dev->bios_geom.sectors = 63;
755 dev->bios_geom.heads = 255;
756 dev->bios_geom.cylinders
757 = dev->length / (63 * 255);
759 /* FIXME: what should we put here? (TODO: discuss on linux-kernel) */
760 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geometry)
761 && geometry.sectors && geometry.heads) {
762 dev->hw_geom.sectors = geometry.sectors;
763 dev->hw_geom.heads = geometry.heads;
764 dev->hw_geom.cylinders
765 = dev->length / (dev->hw_geom.heads
766 * dev->hw_geom.sectors);
768 dev->hw_geom = dev->bios_geom;
775 strip_name(char* str)
780 for (i = 0; str[i] != 0; i++) {
781 if (!isspace (str[i])
782 || (isspace (str[i]) && !isspace (str[i+1]) && str[i+1])) {
792 init_ide (PedDevice* dev)
794 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
795 struct stat dev_stat;
796 struct hd_driveid hdi;
797 PedExceptionOption ex_status;
799 int sector_multiplier = 0;
801 if (!_device_stat (dev, &dev_stat))
804 if (!ped_device_open (dev))
807 if (ioctl (arch_specific->fd, HDIO_GET_IDENTITY, &hdi)) {
808 ex_status = ped_exception_throw (
809 PED_EXCEPTION_WARNING,
810 PED_EXCEPTION_IGNORE_CANCEL,
811 _("Could not get identity of device %s - %s"),
812 dev->path, strerror (errno));
814 case PED_EXCEPTION_CANCEL:
815 goto error_close_dev;
817 case PED_EXCEPTION_UNHANDLED:
818 ped_exception_catch ();
819 case PED_EXCEPTION_IGNORE:
820 dev->model = strdup(_("Generic IDE"));
823 PED_ASSERT (0, (void) 0);
827 /* hdi.model is not guaranteed to be NULL terminated */
828 memcpy (hdi_buf, hdi.model, 40);
830 dev->model = strip_name (hdi_buf);
832 if (!hdi.ata7_sectinfo.valid1 && hdi.ata7_sectinfo.valid2)
833 sector_multiplier = hdi.ata7_sectinfo.multiplier;
835 sector_multiplier = 1;
837 if (sector_multiplier != 1) {
838 ex_status = ped_exception_throw (
839 PED_EXCEPTION_WARNING,
840 PED_EXCEPTION_IGNORE_CANCEL,
841 _("Device %s has multiple (%d) logical sectors "
842 "per physical sector.\n"
843 "GNU Parted supports this EXPERIMENTALLY for "
844 "some special disk label/file system "
845 "combinations, e.g. GPT and ext2/3.\n"
846 "Please consult the web site for up-to-date "
848 dev->path, sector_multiplier);
851 case PED_EXCEPTION_CANCEL:
852 goto error_close_dev;
854 case PED_EXCEPTION_UNHANDLED:
855 ped_exception_catch ();
856 case PED_EXCEPTION_IGNORE:
859 PED_ASSERT (0, (void) 0);
864 /* XXX sector_size has not been set yet! */
865 /* dev->phys_sector_size = dev->sector_size
866 * sector_multiplier;*/
867 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
870 if (!_device_probe_geometry (dev))
871 goto error_close_dev;
873 ped_device_close (dev);
877 ped_device_close (dev);
882 /* This function reads the /sys entry named "file" for device "dev". */
884 read_device_sysfs_file (PedDevice *dev, const char *file)
890 snprintf (name_buf, 127, "/sys/block/%s/device/%s",
891 last_component (dev->path), file);
893 if ((f = fopen (name_buf, "r")) == NULL)
896 if (fgets (buf, 255, f) == NULL)
900 return strip_name (buf);
903 /* This function sends a query to a SCSI device for vendor and product
904 * information. It uses the deprecated SCSI_IOCTL_SEND_COMMAND to
908 scsi_query_product_info (PedDevice* dev, char **vendor, char **product)
910 /* The following are defined by the SCSI-2 specification. */
911 typedef struct _scsi_inquiry_cmd
914 uint8_t lun; /* bits 5-7 denote the LUN */
917 uint8_t alloc_length;
919 } __attribute__((packed)) scsi_inquiry_cmd_t;
921 typedef struct _scsi_inquiry_data
923 uint8_t peripheral_info;
925 uint8_t version_info;
927 uint8_t additional_length;
931 uint8_t vendor_id[8];
932 uint8_t product_id[16];
933 uint8_t product_revision[4];
934 uint8_t vendor_specific[20];
935 uint8_t _reserved3[40];
936 } __attribute__((packed)) scsi_inquiry_data_t;
945 scsi_inquiry_data_t out;
946 scsi_inquiry_cmd_t in;
950 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
956 memset (&arg, 0x00, sizeof(struct scsi_arg));
958 arg.outlen = sizeof(scsi_inquiry_data_t);
959 arg.data.in.op = INQUIRY;
960 arg.data.in.lun = dev->host << 5;
961 arg.data.in.alloc_length = sizeof(scsi_inquiry_data_t);
962 arg.data.in.page_code = 0;
963 arg.data.in.reserved = 0;
964 arg.data.in.control = 0;
966 if (ioctl (arch_specific->fd, SCSI_IOCTL_SEND_COMMAND, &arg) < 0)
969 memcpy (buf, arg.data.out.vendor_id, 8);
971 *vendor = strip_name (buf);
973 memcpy (buf, arg.data.out.product_id, 16);
975 *product = strip_name (buf);
980 /* This function provides the vendor and product name for a SCSI device.
981 * It supports both the modern /sys interface and direct queries
982 * via the deprecated ioctl, SCSI_IOCTL_SEND_COMMAND.
985 scsi_get_product_info (PedDevice* dev, char **vendor, char **product)
987 *vendor = read_device_sysfs_file (dev, "vendor");
988 *product = read_device_sysfs_file (dev, "model");
989 if (*vendor && *product)
992 return scsi_query_product_info (dev, vendor, product);
996 init_scsi (PedDevice* dev)
1001 uint32_t host_unique_id;
1004 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1008 if (!ped_device_open (dev))
1011 if (ioctl (arch_specific->fd, SCSI_IOCTL_GET_IDLUN, &idlun) < 0) {
1014 if (ped_exception_throw (
1015 PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
1016 _("Error initialising SCSI device %s - %s"),
1017 dev->path, strerror (errno))
1018 != PED_EXCEPTION_IGNORE)
1019 goto error_close_dev;
1020 if (!_device_probe_geometry (dev))
1021 goto error_close_dev;
1022 ped_device_close (dev);
1026 dev->host = idlun.host_unique_id;
1027 dev->did = idlun.dev_id;
1029 dev->model = (char*) ped_malloc (8 + 16 + 2);
1031 goto error_close_dev;
1033 if (scsi_get_product_info (dev, &vendor, &product)) {
1034 sprintf (dev->model, "%.8s %.16s", vendor, product);
1038 strcpy (dev->model, "Generic SCSI");
1041 if (!_device_probe_geometry (dev))
1042 goto error_close_dev;
1044 ped_device_close (dev);
1048 ped_device_close (dev);
1054 init_file (PedDevice* dev)
1056 struct stat dev_stat;
1058 if (!_device_stat (dev, &dev_stat))
1060 if (!ped_device_open (dev))
1063 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1064 char *p = getenv ("PARTED_SECTOR_SIZE");
1067 if (0 < s && s % 512 == 0)
1068 dev->sector_size = s;
1070 dev->phys_sector_size = dev->sector_size;
1072 if (S_ISBLK(dev_stat.st_mode))
1073 dev->length = _device_get_length (dev);
1075 dev->length = dev_stat.st_size / dev->sector_size;
1076 if (dev->length <= 0) {
1077 ped_exception_throw (
1078 PED_EXCEPTION_ERROR,
1079 PED_EXCEPTION_CANCEL,
1080 _("The device %s has zero length, and can't possibly "
1081 "store a file system or partition table. Perhaps "
1082 "you selected the wrong device?"),
1084 goto error_close_dev;
1087 ped_device_close (dev);
1089 dev->bios_geom.cylinders = dev->length / 4 / 32;
1090 dev->bios_geom.heads = 4;
1091 dev->bios_geom.sectors = 32;
1092 dev->hw_geom = dev->bios_geom;
1093 dev->model = strdup ("");
1098 ped_device_close (dev);
1103 #if defined __s390__ || defined __s390x__
1105 init_dasd (PedDevice* dev, const char* model_name)
1107 struct stat dev_stat;
1108 struct hd_geometry geo;
1109 dasd_information_t dasd_info;
1111 if (!_device_stat (dev, &dev_stat))
1114 if (!ped_device_open (dev))
1117 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1119 PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
1121 _device_set_sector_size (dev);
1122 if (!dev->sector_size)
1123 goto error_close_dev;
1125 dev->length = _device_get_length (dev);
1127 goto error_close_dev;
1129 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geo)) {
1130 dev->hw_geom.sectors = geo.sectors;
1131 dev->hw_geom.heads = geo.heads;
1132 dev->hw_geom.cylinders = dev->length
1133 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1134 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1135 dev->bios_geom = dev->hw_geom;
1137 dev->bios_geom.sectors = 12;
1138 dev->bios_geom.heads = 15;
1139 dev->bios_geom.cylinders = dev->length
1140 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1141 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1142 dev->hw_geom = dev->bios_geom;
1145 if (!ioctl(arch_specific->fd, BIODASDINFO, &dasd_info)) {
1146 arch_specific->devno = dasd_info.devno;
1148 arch_specific->devno = arch_specific->major * 256 +
1149 arch_specific->minor;
1152 dev->model = strdup (model_name);
1154 ped_device_close (dev);
1158 ped_device_close (dev);
1165 init_generic (PedDevice* dev, const char* model_name)
1167 struct stat dev_stat;
1168 PedExceptionOption ex_status;
1170 if (!_device_stat (dev, &dev_stat))
1173 if (!ped_device_open (dev))
1176 ped_exception_fetch_all ();
1177 if (_device_probe_geometry (dev)) {
1178 ped_exception_leave_all ();
1180 /* hack to allow use of files, for testing */
1181 ped_exception_catch ();
1182 ped_exception_leave_all ();
1184 ex_status = ped_exception_throw (
1185 PED_EXCEPTION_WARNING,
1186 PED_EXCEPTION_IGNORE_CANCEL,
1187 _("Unable to determine geometry of "
1188 "file/device %s. You should not use Parted "
1189 "unless you REALLY know what you're doing!"),
1191 switch (ex_status) {
1192 case PED_EXCEPTION_CANCEL:
1193 goto error_close_dev;
1195 case PED_EXCEPTION_UNHANDLED:
1196 ped_exception_catch ();
1197 case PED_EXCEPTION_IGNORE:
1200 PED_ASSERT (0, (void) 0);
1204 /* what should we stick in here? */
1205 dev->length = dev_stat.st_size / PED_SECTOR_SIZE_DEFAULT;
1206 dev->bios_geom.cylinders = dev->length / 4 / 32;
1207 dev->bios_geom.heads = 4;
1208 dev->bios_geom.sectors = 32;
1209 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1210 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
1213 dev->model = strdup (model_name);
1215 ped_device_close (dev);
1219 ped_device_close (dev);
1225 sdmmc_get_product_info (PedDevice* dev, char **type, char **name)
1227 *type = read_device_sysfs_file (dev, "type");
1228 *name = read_device_sysfs_file (dev, "name");
1236 init_sdmmc (PedDevice* dev)
1241 if (sdmmc_get_product_info (dev, &type, &name)) {
1242 snprintf (id, sizeof(id) - 1, "%s %s", type, name);
1246 snprintf (id, sizeof(id) - 1, "%s",
1247 _("Generic SD/MMC Storage Card"));
1249 return init_generic(dev, id);
1253 linux_new (const char* path)
1256 LinuxSpecific* arch_specific;
1258 PED_ASSERT (path != NULL, return NULL);
1260 dev = (PedDevice*) ped_malloc (sizeof (PedDevice));
1264 dev->path = strdup (path);
1266 goto error_free_dev;
1269 = (LinuxSpecific*) ped_malloc (sizeof (LinuxSpecific));
1270 if (!dev->arch_specific)
1271 goto error_free_path;
1272 arch_specific = LINUX_SPECIFIC (dev);
1273 arch_specific->dmtype = NULL;
1275 arch_specific->probe = NULL;
1276 arch_specific->topology = NULL;
1279 dev->open_count = 0;
1281 dev->external_mode = 0;
1283 dev->boot_dirty = 0;
1285 if (!_device_probe_type (dev))
1286 goto error_free_arch_specific;
1288 switch (dev->type) {
1289 case PED_DEVICE_IDE:
1290 if (!init_ide (dev))
1291 goto error_free_arch_specific;
1294 case PED_DEVICE_SCSI:
1295 if (!init_scsi (dev))
1296 goto error_free_arch_specific;
1299 case PED_DEVICE_DAC960:
1300 if (!init_generic (dev, _("DAC960 RAID controller")))
1301 goto error_free_arch_specific;
1304 case PED_DEVICE_SX8:
1305 if (!init_generic (dev, _("Promise SX8 SATA Device")))
1306 goto error_free_arch_specific;
1309 case PED_DEVICE_AOE:
1310 if (!init_generic (dev, _("ATA over Ethernet Device")))
1311 goto error_free_arch_specific;
1314 #if defined __s390__ || defined __s390x__
1315 case PED_DEVICE_DASD:
1316 if (!init_dasd (dev, _("IBM S390 DASD drive")))
1317 goto error_free_arch_specific;
1321 case PED_DEVICE_VIODASD:
1322 if (!init_generic (dev, _("IBM iSeries Virtual DASD")))
1323 goto error_free_arch_specific;
1326 case PED_DEVICE_CPQARRAY:
1327 if (!init_generic (dev, _("Compaq Smart Array")))
1328 goto error_free_arch_specific;
1331 case PED_DEVICE_ATARAID:
1332 if (!init_generic (dev, _("ATARAID Controller")))
1333 goto error_free_arch_specific;
1336 case PED_DEVICE_I2O:
1337 if (!init_generic (dev, _("I2O Controller")))
1338 goto error_free_arch_specific;
1341 case PED_DEVICE_UBD:
1342 if (!init_generic (dev, _("User-Mode Linux UBD")))
1343 goto error_free_arch_specific;
1346 case PED_DEVICE_FILE:
1347 if (!init_file (dev))
1348 goto error_free_arch_specific;
1354 if (arch_specific->dmtype == NULL
1355 || asprintf(&type, _("Linux device-mapper (%s)"),
1356 arch_specific->dmtype) == -1)
1357 goto error_free_arch_specific;
1358 bool ok = init_generic (dev, type);
1361 goto error_free_arch_specific;
1365 case PED_DEVICE_XVD:
1366 if (!init_generic (dev, _("Xen Virtual Block Device")))
1367 goto error_free_arch_specific;
1370 case PED_DEVICE_UNKNOWN:
1371 if (!init_generic (dev, _("Unknown")))
1372 goto error_free_arch_specific;
1375 case PED_DEVICE_SDMMC:
1376 if (!init_sdmmc (dev))
1377 goto error_free_arch_specific;
1379 case PED_DEVICE_VIRTBLK:
1380 if (!init_generic(dev, _("Virtio Block Device")))
1381 goto error_free_arch_specific;
1385 ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
1386 PED_EXCEPTION_CANCEL,
1387 _("ped_device_new() Unsupported device type"));
1388 goto error_free_arch_specific;
1392 error_free_arch_specific:
1393 free (dev->arch_specific);
1403 linux_destroy (PedDevice* dev)
1405 LinuxSpecific *arch_specific = LINUX_SPECIFIC(dev);
1406 void *p = arch_specific->dmtype;
1409 if (arch_specific->probe)
1410 blkid_free_probe(arch_specific->probe);
1413 free (dev->arch_specific);
1420 linux_is_busy (PedDevice* dev)
1425 if (_partition_is_mounted_by_path (dev->path))
1428 for (i = 0; i < 32; i++) {
1431 part_name = _device_get_part_path (dev, i);
1434 status = _partition_is_mounted_by_path (part_name);
1444 /* we need to flush the master device, and with kernel < 2.6 all the partition
1445 * devices, because there is no coherency between the caches with old kernels.
1446 * We should only flush unmounted partition devices, because:
1447 * - there is never a need to flush them (we're not doing IO there)
1448 * - flushing a device that is mounted causes unnecessary IO, and can
1449 * even screw journaling & friends up. Even cause oopsen!
1452 _flush_cache (PedDevice* dev)
1454 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1461 ioctl (arch_specific->fd, BLKFLSBUF);
1463 /* With linux-2.6.0 and newer, we're done. */
1467 for (i = 1; i < 16; i++) {
1471 name = _device_get_part_path (dev, i);
1474 if (!_partition_is_mounted_by_path (name)) {
1475 fd = open (name, WR_MODE, 0);
1477 ioctl (fd, BLKFLSBUF);
1479 if (fsync (fd) < 0 || close (fd) < 0)
1480 if (ped_exception_throw (
1481 PED_EXCEPTION_WARNING,
1482 PED_EXCEPTION_RETRY +
1483 PED_EXCEPTION_IGNORE,
1484 _("Error fsyncing/closing %s: %s"),
1485 name, strerror (errno))
1486 == PED_EXCEPTION_RETRY)
1495 linux_open (PedDevice* dev)
1497 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1500 arch_specific->fd = open (dev->path, RW_MODE);
1502 if (arch_specific->fd == -1) {
1503 char* rw_error_msg = strerror (errno);
1505 arch_specific->fd = open (dev->path, RD_MODE);
1507 if (arch_specific->fd == -1) {
1508 if (ped_exception_throw (
1509 PED_EXCEPTION_ERROR,
1510 PED_EXCEPTION_RETRY_CANCEL,
1511 _("Error opening %s: %s"),
1512 dev->path, strerror (errno))
1513 != PED_EXCEPTION_RETRY) {
1519 ped_exception_throw (
1520 PED_EXCEPTION_WARNING,
1522 _("Unable to open %s read-write (%s). %s has "
1523 "been opened read-only."),
1524 dev->path, rw_error_msg, dev->path);
1531 /* With kernels < 2.6 flush cache for cache coherence issues */
1532 if (!_have_kern26())
1539 linux_refresh_open (PedDevice* dev)
1545 linux_close (PedDevice* dev)
1547 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1552 if (fsync (arch_specific->fd) < 0 || close (arch_specific->fd) < 0)
1553 if (ped_exception_throw (
1554 PED_EXCEPTION_WARNING,
1555 PED_EXCEPTION_RETRY + PED_EXCEPTION_IGNORE,
1556 _("Error fsyncing/closing %s: %s"),
1557 dev->path, strerror (errno))
1558 == PED_EXCEPTION_RETRY)
1564 linux_refresh_close (PedDevice* dev)
1571 #if SIZEOF_OFF_T < 8
1573 static _syscall5(int,_llseek,
1575 unsigned long, offset_high,
1576 unsigned long, offset_low,
1578 unsigned int, origin)
1581 llseek (unsigned int fd, loff_t offset, unsigned int whence)
1586 retval = _llseek(fd,
1587 ((unsigned long long)offset) >> 32,
1588 ((unsigned long long)offset) & 0xffffffff,
1591 return (retval==-1 ? (loff_t) retval : result);
1594 #endif /* SIZEOF_OFF_T < 8 */
1597 _device_seek (const PedDevice* dev, PedSector sector)
1599 LinuxSpecific* arch_specific;
1601 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1602 PED_ASSERT (dev != NULL, return 0);
1603 PED_ASSERT (!dev->external_mode, return 0);
1605 arch_specific = LINUX_SPECIFIC (dev);
1607 #if SIZEOF_OFF_T < 8
1608 if (sizeof (off_t) < 8) {
1609 loff_t pos = (loff_t)(sector * dev->sector_size);
1610 return llseek (arch_specific->fd, pos, SEEK_SET) == pos;
1614 off_t pos = sector * dev->sector_size;
1615 return lseek (arch_specific->fd, pos, SEEK_SET) == pos;
1620 _read_lastoddsector (const PedDevice* dev, void* buffer)
1622 LinuxSpecific* arch_specific;
1623 struct blkdev_ioctl_param ioctl_param;
1625 PED_ASSERT(dev != NULL, return 0);
1626 PED_ASSERT(buffer != NULL, return 0);
1628 arch_specific = LINUX_SPECIFIC (dev);
1631 ioctl_param.block = 0; /* read the last sector */
1632 ioctl_param.content_length = dev->sector_size;
1633 ioctl_param.block_contents = buffer;
1635 if (ioctl(arch_specific->fd, BLKGETLASTSECT, &ioctl_param) == -1) {
1636 PedExceptionOption opt;
1637 opt = ped_exception_throw (
1638 PED_EXCEPTION_ERROR,
1639 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1640 _("%s during read on %s"),
1641 strerror (errno), dev->path);
1643 if (opt == PED_EXCEPTION_CANCEL)
1645 if (opt == PED_EXCEPTION_RETRY)
1653 linux_read (const PedDevice* dev, void* buffer, PedSector start,
1656 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1657 PedExceptionOption ex_status;
1658 void* diobuf = NULL;
1660 PED_ASSERT (dev != NULL, return 0);
1661 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1663 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1664 /* Kludge. This is necessary to read/write the last
1665 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1667 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1668 && start + count - 1 == dev->length - 1)
1669 return ped_device_read (dev, buffer, start, count - 1)
1670 && _read_lastoddsector (
1671 dev, (char *) buffer + (count-1) * 512);
1674 if (_device_seek (dev, start))
1677 ex_status = ped_exception_throw (
1678 PED_EXCEPTION_ERROR,
1679 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1680 _("%s during seek for read on %s"),
1681 strerror (errno), dev->path);
1683 switch (ex_status) {
1684 case PED_EXCEPTION_IGNORE:
1687 case PED_EXCEPTION_RETRY:
1690 case PED_EXCEPTION_UNHANDLED:
1691 ped_exception_catch ();
1692 case PED_EXCEPTION_CANCEL:
1695 PED_ASSERT (0, (void) 0);
1700 size_t read_length = count * dev->sector_size;
1701 if (posix_memalign (&diobuf, dev->sector_size, read_length) != 0)
1705 ssize_t status = read (arch_specific->fd, diobuf, read_length);
1707 memcpy(buffer, diobuf, status);
1708 if (status == (ssize_t) read_length)
1711 read_length -= status;
1712 buffer = (char *) buffer + status;
1716 ex_status = ped_exception_throw (
1717 PED_EXCEPTION_ERROR,
1718 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1720 ? _("end of file while reading %s")
1721 : _("%s during read on %s")),
1725 switch (ex_status) {
1726 case PED_EXCEPTION_IGNORE:
1730 case PED_EXCEPTION_RETRY:
1733 case PED_EXCEPTION_UNHANDLED:
1734 ped_exception_catch ();
1735 case PED_EXCEPTION_CANCEL:
1739 PED_ASSERT (0, (void) 0);
1750 _write_lastoddsector (PedDevice* dev, const void* buffer)
1752 LinuxSpecific* arch_specific;
1753 struct blkdev_ioctl_param ioctl_param;
1755 PED_ASSERT(dev != NULL, return 0);
1756 PED_ASSERT(buffer != NULL, return 0);
1758 arch_specific = LINUX_SPECIFIC (dev);
1761 ioctl_param.block = 0; /* write the last sector */
1762 ioctl_param.content_length = dev->sector_size;
1763 ioctl_param.block_contents = (void*) buffer;
1765 if (ioctl(arch_specific->fd, BLKSETLASTSECT, &ioctl_param) == -1) {
1766 PedExceptionOption opt;
1767 opt = ped_exception_throw (
1768 PED_EXCEPTION_ERROR,
1769 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1770 _("%s during write on %s"),
1771 strerror (errno), dev->path);
1773 if (opt == PED_EXCEPTION_CANCEL)
1775 if (opt == PED_EXCEPTION_RETRY)
1783 linux_write (PedDevice* dev, const void* buffer, PedSector start,
1786 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1787 PedExceptionOption ex_status;
1791 PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1793 if (dev->read_only) {
1794 if (ped_exception_throw (
1795 PED_EXCEPTION_ERROR,
1796 PED_EXCEPTION_IGNORE_CANCEL,
1797 _("Can't write to %s, because it is opened read-only."),
1799 != PED_EXCEPTION_IGNORE)
1805 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1806 /* Kludge. This is necessary to read/write the last
1807 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1809 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1810 && start + count - 1 == dev->length - 1)
1811 return ped_device_write (dev, buffer, start, count - 1)
1812 && _write_lastoddsector (
1813 dev, ((char*) buffer
1814 + (count-1) * dev->sector_size));
1817 if (_device_seek (dev, start))
1820 ex_status = ped_exception_throw (
1821 PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1822 _("%s during seek for write on %s"),
1823 strerror (errno), dev->path);
1825 switch (ex_status) {
1826 case PED_EXCEPTION_IGNORE:
1829 case PED_EXCEPTION_RETRY:
1832 case PED_EXCEPTION_UNHANDLED:
1833 ped_exception_catch ();
1834 case PED_EXCEPTION_CANCEL:
1837 PED_ASSERT (0, (void) 0);
1843 printf ("ped_device_write (\"%s\", %p, %d, %d)\n",
1844 dev->path, buffer, (int) start, (int) count);
1846 size_t write_length = count * dev->sector_size;
1848 if (posix_memalign(&diobuf, dev->sector_size, write_length) != 0)
1850 memcpy(diobuf, buffer, write_length);
1851 diobuf_start = diobuf;
1853 ssize_t status = write (arch_specific->fd, diobuf, write_length);
1854 if (status == write_length) break;
1856 write_length -= status;
1857 diobuf = (char *) diobuf + status;
1861 ex_status = ped_exception_throw (
1862 PED_EXCEPTION_ERROR,
1863 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1864 _("%s during write on %s"),
1865 strerror (errno), dev->path);
1867 switch (ex_status) {
1868 case PED_EXCEPTION_IGNORE:
1872 case PED_EXCEPTION_RETRY:
1875 case PED_EXCEPTION_UNHANDLED:
1876 ped_exception_catch ();
1877 case PED_EXCEPTION_CANCEL:
1881 PED_ASSERT (0, (void) 0);
1886 #endif /* !READ_ONLY */
1890 /* returns the number of sectors that are ok.
1893 linux_check (PedDevice* dev, void* buffer, PedSector start, PedSector count)
1895 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1900 PED_ASSERT(dev != NULL, return 0);
1902 if (!_device_seek (dev, start))
1905 if (posix_memalign(&diobuf, PED_SECTOR_SIZE_DEFAULT,
1906 count * PED_SECTOR_SIZE_DEFAULT) != 0)
1909 for (done = 0; done < count; done += status / dev->sector_size) {
1910 status = read (arch_specific->fd, diobuf,
1911 (size_t) ((count-done) * dev->sector_size));
1913 memcpy(buffer, diobuf, status);
1923 _do_fsync (PedDevice* dev)
1925 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1927 PedExceptionOption ex_status;
1930 status = fsync (arch_specific->fd);
1931 if (status >= 0) break;
1933 ex_status = ped_exception_throw (
1934 PED_EXCEPTION_ERROR,
1935 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1936 _("%s during write on %s"),
1937 strerror (errno), dev->path);
1939 switch (ex_status) {
1940 case PED_EXCEPTION_IGNORE:
1943 case PED_EXCEPTION_RETRY:
1946 case PED_EXCEPTION_UNHANDLED:
1947 ped_exception_catch ();
1948 case PED_EXCEPTION_CANCEL:
1951 PED_ASSERT (0, (void) 0);
1959 linux_sync (PedDevice* dev)
1961 PED_ASSERT (dev != NULL, return 0);
1962 PED_ASSERT (!dev->external_mode, return 0);
1966 if (!_do_fsync (dev))
1973 linux_sync_fast (PedDevice* dev)
1975 PED_ASSERT (dev != NULL, return 0);
1976 PED_ASSERT (!dev->external_mode, return 0);
1980 if (!_do_fsync (dev))
1982 /* no cache flush... */
1987 _compare_digit_state (char ch, int need_digit)
1989 return !!isdigit (ch) == need_digit;
1992 /* matches the regexp "[^0-9]+[0-9]+[^0-9]+[0-9]+$".
1993 * Motivation: accept devices looking like /dev/rd/c0d0, but
1994 * not looking like /dev/hda1 and /dev/rd/c0d0p1
1997 _match_rd_device (const char* name)
2002 /* exclude directory names from test */
2003 pos = strrchr(name, '/') ?: name;
2011 for (state = 0; state < 4; state++) {
2012 int want_digits = (state % 2 == 1);
2016 if (!_compare_digit_state (*pos, want_digits))
2019 } while (_compare_digit_state (*pos, want_digits));
2026 _probe_proc_partitions ()
2028 FILE* proc_part_file;
2029 int major, minor, size;
2031 char part_name [256];
2032 char dev_name [256];
2034 proc_part_file = fopen ("/proc/partitions", "r");
2035 if (!proc_part_file)
2038 if (fgets (buf, 256, proc_part_file) == NULL)
2041 if (fgets (buf, 256, proc_part_file) == NULL)
2044 while (fgets (buf, 512, proc_part_file)
2045 && sscanf (buf, "%d %d %d %255s", &major, &minor, &size,
2047 /* Heuristic for telling partitions and devices apart
2048 * Probably needs to be improved
2050 if (!_match_rd_device (part_name)
2051 && isdigit (part_name [strlen (part_name) - 1]))
2054 strcpy (dev_name, "/dev/");
2055 strcat (dev_name, part_name);
2056 _ped_device_probe (dev_name);
2059 fclose (proc_part_file);
2069 _skip_entry (const char *name)
2072 static struct _entry entries[] = {
2073 { ".", sizeof (".") - 1 },
2074 { "..", sizeof ("..") - 1 },
2075 { "dm-", sizeof ("dm-") - 1 },
2076 { "loop", sizeof ("loop") - 1 },
2077 { "ram", sizeof ("ram") - 1 },
2081 for (i = entries; i->name != 0; i++) {
2082 if (strncmp (name, i->name, i->len) == 0)
2093 struct dirent *dirent;
2094 char dev_name [256];
2097 if (!(blockdir = opendir ("/sys/block")))
2099 while ((dirent = readdir (blockdir))) {
2100 if (_skip_entry (dirent->d_name))
2103 if (strlen (dirent->d_name) > sizeof (dev_name) - 6)
2104 continue; /* device name too long! */
2106 strcpy (dev_name, "/dev/");
2107 strcat (dev_name, dirent->d_name);
2108 /* in /sys/block, '/'s are replaced with '!' or '.' */
2109 for (ptr = dev_name; *ptr != '\0'; ptr++) {
2110 if (*ptr == '!' || *ptr == '.')
2113 _ped_device_probe (dev_name);
2116 closedir (blockdir);
2121 _probe_standard_devices ()
2123 _ped_device_probe ("/dev/hda");
2124 _ped_device_probe ("/dev/hdb");
2125 _ped_device_probe ("/dev/hdc");
2126 _ped_device_probe ("/dev/hdd");
2127 _ped_device_probe ("/dev/hde");
2128 _ped_device_probe ("/dev/hdf");
2129 _ped_device_probe ("/dev/hdg");
2130 _ped_device_probe ("/dev/hdh");
2132 _ped_device_probe ("/dev/sda");
2133 _ped_device_probe ("/dev/sdb");
2134 _ped_device_probe ("/dev/sdc");
2135 _ped_device_probe ("/dev/sdd");
2136 _ped_device_probe ("/dev/sde");
2137 _ped_device_probe ("/dev/sdf");
2145 /* we should probe the standard devs too, even with /proc/partitions,
2146 * because /proc/partitions might return devfs stuff, and we might not
2147 * have devfs available
2149 _probe_standard_devices ();
2151 #ifdef ENABLE_DEVICE_MAPPER
2152 /* device-mapper devices aren't listed in /proc/partitions; or, if
2153 * they are, they're listed as dm-X. So, instead of relying on that,
2154 * we do our own checks.
2156 _probe_dm_devices ();
2159 /* /sys/block is more reliable and consistent; fall back to using
2160 * /proc/partitions if the former is unavailable, however.
2162 if (!_probe_sys_block ())
2163 _probe_proc_partitions ();
2167 _device_get_part_path (PedDevice* dev, int num)
2169 int path_len = strlen (dev->path);
2170 int result_len = path_len + 16;
2173 result = (char*) ped_malloc (result_len);
2177 /* Check for devfs-style /disc => /partN transformation
2178 unconditionally; the system might be using udev with devfs rules,
2179 and if not the test is harmless. */
2180 if (!strcmp (dev->path + path_len - 5, "/disc")) {
2181 /* replace /disc with /path%d */
2182 strcpy (result, dev->path);
2183 snprintf (result + path_len - 5, 16, "/part%d", num);
2184 } else if (dev->type == PED_DEVICE_DAC960
2185 || dev->type == PED_DEVICE_CPQARRAY
2186 || dev->type == PED_DEVICE_ATARAID
2187 || dev->type == PED_DEVICE_DM
2188 || isdigit (dev->path[path_len - 1]))
2189 snprintf (result, result_len, "%sp%d", dev->path, num);
2191 snprintf (result, result_len, "%s%d", dev->path, num);
2197 linux_partition_get_path (const PedPartition* part)
2199 return _device_get_part_path (part->disk->dev, part->num);
2203 _partition_get_part_dev (const PedPartition* part)
2205 struct stat dev_stat;
2206 int dev_major, dev_minor;
2208 if (stat (part->disk->dev->path, &dev_stat))
2210 dev_major = major (dev_stat.st_rdev);
2211 dev_minor = minor (dev_stat.st_rdev);
2212 return (dev_t)makedev (dev_major, dev_minor + part->num);
2216 _mount_table_search (const char* file_name, dev_t dev)
2218 struct stat part_stat;
2220 char part_name[512];
2223 file = fopen (file_name, "r");
2226 while (fgets (line, 512, file)) {
2227 if (sscanf (line, "%s", part_name) == 1
2228 && stat (part_name, &part_stat) == 0) {
2229 if (part_stat.st_rdev == dev) {
2240 _partition_is_mounted_by_dev (dev_t dev)
2242 return _mount_table_search( "/proc/mounts", dev)
2243 || _mount_table_search( "/proc/swaps", dev)
2244 || _mount_table_search( "/etc/mtab", dev);
2248 _partition_is_mounted_by_path (const char *path)
2250 struct stat part_stat;
2251 if (stat (path, &part_stat) != 0)
2253 if (!S_ISBLK(part_stat.st_mode))
2255 return _partition_is_mounted_by_dev (part_stat.st_rdev);
2259 _partition_is_mounted (const PedPartition *part)
2262 if (!ped_partition_is_active (part))
2264 dev = _partition_get_part_dev (part);
2267 return _partition_is_mounted_by_dev (dev);
2271 _has_partitions (const PedDisk* disk)
2273 PED_ASSERT(disk != NULL, return 0);
2275 /* Some devices can't be partitioned. */
2276 if (!strcmp (disk->type->name, "loop"))
2283 linux_partition_is_busy (const PedPartition* part)
2287 PED_ASSERT (part != NULL, return 0);
2289 if (_partition_is_mounted (part))
2291 if (part->type == PED_PARTITION_EXTENDED) {
2292 for (walk = part->part_list; walk; walk = walk->next) {
2293 if (linux_partition_is_busy (walk))
2300 #ifdef ENABLE_DEVICE_MAPPER
2302 _dm_remove_map_name(char *name)
2304 struct dm_task *task = NULL;
2307 task = dm_task_create(DM_DEVICE_REMOVE);
2311 dm_task_set_name (task, name);
2313 rc = dm_task_run(task);
2314 dm_task_update_nodes();
2315 dm_task_destroy(task);
2323 _dm_is_part (struct dm_info *this, char *name)
2325 struct dm_task* task = NULL;
2326 struct dm_info* info = alloca(sizeof *info);
2327 struct dm_deps* deps = NULL;
2331 task = dm_task_create(DM_DEVICE_DEPS);
2335 dm_task_set_name(task, name);
2336 rc = dm_task_run(task);
2343 memset(info, '\0', sizeof *info);
2344 dm_task_get_info(task, info);
2348 deps = dm_task_get_deps(task);
2353 for (i = 0; i < deps->count; i++) {
2354 unsigned int ma = major(deps->device[i]),
2355 mi = minor(deps->device[i]);
2357 if (ma == this->major && mi == this->minor)
2362 dm_task_destroy(task);
2367 _dm_remove_parts (PedDevice* dev)
2369 struct dm_task* task = NULL;
2370 struct dm_info* info = alloca(sizeof *info);
2371 struct dm_names* names = NULL;
2372 unsigned int next = 0;
2374 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2376 task = dm_task_create(DM_DEVICE_LIST);
2380 if (!dm_task_set_major_minor (task, arch_specific->major,
2381 arch_specific->minor, 0))
2384 rc = dm_task_run(task);
2388 memset(info, '\0', sizeof *info);
2389 dm_task_get_info(task, info);
2393 names = dm_task_get_names(task);
2399 names = (void *) ((char *) names + next);
2401 if (_dm_is_part(info, names->name))
2402 rc += _dm_remove_map_name(names->name);
2407 dm_task_update_nodes();
2408 dm_task_destroy(task);
2415 dm_task_destroy(task);
2416 ped_exception_throw (PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE,
2417 _("parted was unable to re-read the partition "
2418 "table on %s (%s). This means Linux won't know "
2419 "anything about the modifications you made. "),
2420 dev->path, strerror (errno));
2425 _dm_add_partition (PedDisk* disk, PedPartition* part)
2428 char* vol_name = NULL;
2429 const char* dev_name = NULL;
2430 char* params = NULL;
2431 LinuxSpecific* arch_specific = LINUX_SPECIFIC (disk->dev);
2433 if (!_has_partitions(disk))
2436 /* Get map name from devicemapper */
2437 struct dm_task *task = dm_task_create (DM_DEVICE_INFO);
2441 if (!dm_task_set_major_minor (task, arch_specific->major,
2442 arch_specific->minor, 0))
2445 rc = dm_task_run(task);
2449 dev_name = dm_task_get_name (task);
2451 if (asprintf (&vol_name, "%sp%d", dev_name, part->num) == -1)
2454 /* Caution: dm_task_destroy frees dev_name. */
2455 dm_task_destroy (task);
2458 if (asprintf (¶ms, "%d:%d %lld", arch_specific->major,
2459 arch_specific->minor, part->geom.start) == -1)
2462 task = dm_task_create (DM_DEVICE_CREATE);
2466 dm_task_set_name (task, vol_name);
2467 dm_task_add_target (task, 0, part->geom.length,
2469 rc = dm_task_run (task);
2471 //printf("0 %ld linear %s\n", part->geom.length, params);
2472 dm_task_update_nodes();
2473 dm_task_destroy(task);
2478 _dm_remove_map_name(vol_name);
2481 dm_task_update_nodes();
2483 dm_task_destroy (task);
2490 _dm_reread_part_table (PedDisk* disk)
2492 int largest_partnum = ped_disk_get_last_partition_num (disk);
2493 if (largest_partnum <= 0)
2497 int last = PED_MIN (largest_partnum, 16);
2501 if (!_dm_remove_parts(disk->dev))
2504 for (i = 1; i <= last; i++) {
2507 part = ped_disk_get_partition (disk, i);
2511 if (!_dm_add_partition (disk, part))
2519 _kernel_reread_part_table (PedDevice* dev)
2521 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2522 int retry_count = 9;
2525 while (ioctl (arch_specific->fd, BLKRRPART)) {
2528 if (retry_count == 3)
2529 sleep(1); /* Pause to allow system to settle */
2532 ped_exception_throw (
2533 PED_EXCEPTION_WARNING,
2534 PED_EXCEPTION_IGNORE,
2535 _("WARNING: the kernel failed to re-read the partition "
2536 "table on %s (%s). As a result, it may not "
2537 "reflect all of your changes until after reboot."),
2538 dev->path, strerror (errno));
2547 linux_disk_commit (PedDisk* disk)
2549 if (!_has_partitions (disk))
2552 #ifdef ENABLE_DEVICE_MAPPER
2553 if (disk->dev->type == PED_DEVICE_DM)
2554 return _dm_reread_part_table (disk);
2556 if (disk->dev->type != PED_DEVICE_FILE) {
2557 return _kernel_reread_part_table (disk->dev);
2564 static PedAlignment*
2565 linux_get_minimum_alignment(const PedDevice *dev)
2567 blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
2571 if (blkid_topology_get_minimum_io_size(tp) == 0)
2572 return ped_alignment_new(
2573 blkid_topology_get_alignment_offset(tp) /
2575 dev->phys_sector_size / dev->sector_size);
2577 return ped_alignment_new(
2578 blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2579 blkid_topology_get_minimum_io_size(tp) / dev->sector_size);
2582 static PedAlignment*
2583 linux_get_optimum_alignment(const PedDevice *dev)
2585 blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
2589 /* If optimal_io_size is 0 _and_ alignment_offset is 0 _and_
2590 minimum_io_size is a power of 2 then go with the device.c default */
2591 unsigned long minimum_io_size = blkid_topology_get_minimum_io_size(tp);
2592 if (blkid_topology_get_optimal_io_size(tp) == 0 &&
2593 blkid_topology_get_alignment_offset(tp) == 0 &&
2594 (minimum_io_size & (minimum_io_size - 1)) == 0)
2597 /* If optimal_io_size is 0 and we don't meet the other criteria
2598 for using the device.c default, return the minimum alignment. */
2599 if (blkid_topology_get_optimal_io_size(tp) == 0)
2600 return linux_get_minimum_alignment(dev);
2602 return ped_alignment_new(
2603 blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2604 blkid_topology_get_optimal_io_size(tp) / dev->sector_size);
2608 static PedDeviceArchOps linux_dev_ops = {
2610 destroy: linux_destroy,
2611 is_busy: linux_is_busy,
2613 refresh_open: linux_refresh_open,
2615 refresh_close: linux_refresh_close,
2620 sync_fast: linux_sync_fast,
2621 probe_all: linux_probe_all,
2623 get_minimum_alignment: linux_get_minimum_alignment,
2624 get_optimum_alignment: linux_get_optimum_alignment,
2628 PedDiskArchOps linux_disk_ops = {
2629 partition_get_path: linux_partition_get_path,
2630 partition_is_busy: linux_partition_is_busy,
2631 disk_commit: linux_disk_commit
2634 PedArchitecture ped_linux_arch = {
2635 dev_ops: &linux_dev_ops,
2636 disk_ops: &linux_disk_ops