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>
35 #include <sys/ioctl.h>
37 #include <sys/types.h>
38 #include <sys/utsname.h> /* for uname() */
39 #include <scsi/scsi.h>
40 #ifdef ENABLE_DEVICE_MAPPER
41 #include <libdevmapper.h>
45 #include "../architecture.h"
50 # define _(String) dgettext (PACKAGE, String)
52 # define _(String) (String)
53 #endif /* ENABLE_NLS */
55 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
58 #define __NR__llseek 140
61 #ifndef SCSI_IOCTL_SEND_COMMAND
62 #define SCSI_IOCTL_SEND_COMMAND 1
65 /* from <linux/hdreg.h> */
66 #define HDIO_GETGEO 0x0301 /* get device geometry */
67 #define HDIO_GET_IDENTITY 0x030d /* get IDE identification info */
69 #define RD_MODE (O_RDONLY)
70 #define WR_MODE (O_WRONLY)
71 #define RW_MODE (O_RDWR)
75 unsigned char sectors;
76 unsigned short cylinders;
80 struct ata7_sectinfo {
87 /* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
89 unsigned short config; /* lots of obsolete bit flags */
90 unsigned short cyls; /* "physical" cyls */
91 unsigned short reserved2; /* reserved (word 2) */
92 unsigned short heads; /* "physical" heads */
93 unsigned short track_bytes; /* unformatted bytes per track */
94 unsigned short sector_bytes; /* unformatted bytes per sector */
95 unsigned short sectors; /* "physical" sectors per track */
96 unsigned short vendor0; /* vendor unique */
97 unsigned short vendor1; /* vendor unique */
98 unsigned short vendor2; /* vendor unique */
99 unsigned char serial_no[20]; /* 0 = not_specified */
100 unsigned short buf_type;
101 unsigned short buf_size; /* 512 byte increments;
103 unsigned short ecc_bytes; /* for r/w long cmds;
105 unsigned char fw_rev[8]; /* 0 = not_specified */
106 char model[40]; /* 0 = not_specified */
107 unsigned char max_multsect; /* 0=not_implemented */
108 unsigned char vendor3; /* vendor unique */
109 unsigned short dword_io; /* 0=not_implemented; 1=implemented */
110 unsigned char vendor4; /* vendor unique */
111 unsigned char capability; /* bits 0:DMA 1:LBA 2:IORDYsw
113 unsigned short reserved50; /* reserved (word 50) */
114 unsigned char vendor5; /* vendor unique */
115 unsigned char tPIO; /* 0=slow, 1=medium, 2=fast */
116 unsigned char vendor6; /* vendor unique */
117 unsigned char tDMA; /* 0=slow, 1=medium, 2=fast */
118 unsigned short field_valid; /* bits 0:cur_ok 1:eide_ok */
119 unsigned short cur_cyls; /* logical cylinders */
120 unsigned short cur_heads; /* logical heads */
121 unsigned short cur_sectors; /* logical sectors per track */
122 unsigned short cur_capacity0; /* logical total sectors on drive */
123 unsigned short cur_capacity1; /* (2 words, misaligned int) */
124 unsigned char multsect; /* current multiple sector count */
125 unsigned char multsect_valid; /* when (bit0==1) multsect is ok */
126 unsigned int lba_capacity; /* total number of sectors */
127 unsigned short dma_1word; /* single-word dma info */
128 unsigned short dma_mword; /* multiple-word dma info */
129 unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */
130 unsigned short eide_dma_min; /* min mword dma cycle time (ns) */
131 unsigned short eide_dma_time; /* recommended mword dma cycle
133 unsigned short eide_pio; /* min cycle time (ns), no IORDY */
134 unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */
135 unsigned short words69_70[2]; /* reserved words 69-70 */
136 /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
137 unsigned short words71_74[4]; /* reserved words 71-74 */
138 unsigned short queue_depth; /* */
139 unsigned short words76_79[4]; /* reserved words 76-79 */
140 unsigned short major_rev_num; /* */
141 unsigned short minor_rev_num; /* */
142 unsigned short command_set_1; /* bits 0:Smart 1:Security 2:Removable
144 unsigned short command_set_2; /* bits 14:Smart Enabled 13:0 zero */
145 unsigned short cfsse; /* command set-feature supported
147 unsigned short cfs_enable_1; /* command set-feature enabled */
148 unsigned short cfs_enable_2; /* command set-feature enabled */
149 unsigned short csf_default; /* command set-feature default */
150 unsigned short dma_ultra; /* */
151 unsigned short word89; /* reserved (word 89) */
152 unsigned short word90; /* reserved (word 90) */
153 unsigned short CurAPMvalues; /* current APM values */
154 unsigned short word92; /* reserved (word 92) */
155 unsigned short hw_config; /* hardware config */
156 unsigned short words94_105[12];/* reserved words 94-105 */
157 struct ata7_sectinfo ata7_sectinfo; /* ATAPI/ATA7 physical and logical
159 unsigned short words107_116[10];/* reserved words 107-116 */
160 unsigned int logical_sectsize;/* ATAPI/ATA7 logical sector size */
161 unsigned short words119_125[7];/* reserved words 119-125 */
162 unsigned short last_lun; /* reserved (word 126) */
163 unsigned short word127; /* reserved (word 127) */
164 unsigned short dlf; /* device lock function
166 * 8 security level 1:max 0:high
175 unsigned short csfo; /* current set features options
182 unsigned short words130_155[26];/* reserved vendor words 130-155 */
183 unsigned short word156;
184 unsigned short words157_159[3]; /* reserved vendor words 157-159 */
185 unsigned short words160_255[95];/* reserved words 160-255 */
188 /* from <linux/fs.h> */
189 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
190 #define BLKGETSIZE _IO(0x12,96) /* return device size */
191 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
192 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
193 #define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
194 #define BLKSETLASTSECT _IO(0x12,109) /* set last sector of block device */
196 /* return device size in bytes (u64 *arg) */
197 #define BLKGETSIZE64 _IOR(0x12,114,size_t)
199 struct blkdev_ioctl_param {
201 size_t content_length;
202 char * block_contents;
205 /* from <linux/major.h> */
207 #define IDE1_MAJOR 22
208 #define IDE2_MAJOR 33
209 #define IDE3_MAJOR 34
210 #define IDE4_MAJOR 56
211 #define IDE5_MAJOR 57
212 #define SCSI_CDROM_MAJOR 11
213 #define SCSI_DISK0_MAJOR 8
214 #define SCSI_DISK1_MAJOR 65
215 #define SCSI_DISK2_MAJOR 66
216 #define SCSI_DISK3_MAJOR 67
217 #define SCSI_DISK4_MAJOR 68
218 #define SCSI_DISK5_MAJOR 69
219 #define SCSI_DISK6_MAJOR 70
220 #define SCSI_DISK7_MAJOR 71
221 #define COMPAQ_SMART2_MAJOR 72
222 #define COMPAQ_SMART2_MAJOR1 73
223 #define COMPAQ_SMART2_MAJOR2 74
224 #define COMPAQ_SMART2_MAJOR3 75
225 #define COMPAQ_SMART2_MAJOR4 76
226 #define COMPAQ_SMART2_MAJOR5 77
227 #define COMPAQ_SMART2_MAJOR6 78
228 #define COMPAQ_SMART2_MAJOR7 79
229 #define COMPAQ_SMART_MAJOR 104
230 #define COMPAQ_SMART_MAJOR1 105
231 #define COMPAQ_SMART_MAJOR2 106
232 #define COMPAQ_SMART_MAJOR3 107
233 #define COMPAQ_SMART_MAJOR4 108
234 #define COMPAQ_SMART_MAJOR5 109
235 #define COMPAQ_SMART_MAJOR6 110
236 #define COMPAQ_SMART_MAJOR7 111
237 #define DAC960_MAJOR 48
238 #define ATARAID_MAJOR 114
239 #define I2O_MAJOR1 80
240 #define I2O_MAJOR2 81
241 #define I2O_MAJOR3 82
242 #define I2O_MAJOR4 83
243 #define I2O_MAJOR5 84
244 #define I2O_MAJOR6 85
245 #define I2O_MAJOR7 86
246 #define I2O_MAJOR8 87
248 #define DASD_MAJOR 94
249 #define VIODASD_MAJOR 112
250 #define SX8_MAJOR1 160
251 #define SX8_MAJOR2 161
252 #define XVD_MAJOR 202
253 #define SDMMC_MAJOR 179
255 #define SCSI_BLK_MAJOR(M) ( \
256 (M) == SCSI_DISK0_MAJOR \
257 || (M) == SCSI_CDROM_MAJOR \
258 || ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
260 /* Maximum number of partitions supported by linux. */
261 #define MAX_NUM_PARTS 64
263 static char* _device_get_part_path (PedDevice* dev, int num);
264 static int _partition_is_mounted_by_path (const char* path);
267 _read_fd (int fd, char **buf)
270 size_t size = PROC_DEVICES_BUFSIZ;
273 *buf = malloc (size * sizeof (char));
279 p = &(*buf) [filesize];
280 s = read (fd, p, PROC_DEVICES_BUFSIZ);
281 /* exit if there is an error or EOF is reached */
286 *buf = realloc (*buf, size);
289 if (filesize == 0 && s < 0) {
294 /* there is always some excess memory left unused */
295 *buf = realloc (*buf, filesize+1);
296 (*buf)[filesize] = '\0';
303 _major_type_in_devices (int major, const char* type)
312 fd = open ("/proc/devices", O_RDONLY);
316 if (_read_fd(fd, &buf) < 0) {
322 end = strchr(line, '\n');
331 if (!strncmp(line, "Block devices:", 14))
336 name = strrchr(line, ' ');
337 if (!name || strcmp(name+1, type))
340 maj = strtol(line, &name, 10);
350 end = strchr(line, '\n');
358 _is_ide_major (int major)
375 _is_cpqarray_major (int major)
377 return ((COMPAQ_SMART2_MAJOR <= major && major <= COMPAQ_SMART2_MAJOR7)
378 || (COMPAQ_SMART_MAJOR <= major && major <= COMPAQ_SMART_MAJOR7));
382 _is_i2o_major (int major)
384 return (I2O_MAJOR1 <= major && major <= I2O_MAJOR8);
388 _is_sx8_major (int major)
390 return (SX8_MAJOR1 <= major && major <= SX8_MAJOR2);
394 _is_virtblk_major (int major)
396 return _major_type_in_devices (major, "virtblk");
399 #ifdef ENABLE_DEVICE_MAPPER
401 _is_dm_major (int major)
403 return _major_type_in_devices (major, "device-mapper");
407 _dm_maptype (PedDevice *dev)
409 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
412 uint64_t start, length;
413 char *target_type = NULL;
416 const char* dev_dir = getenv ("DM_DEV_DIR");
418 if (dev_dir && *dev_dir && !dm_set_dev_dir(dev_dir))
421 if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
424 if (!dm_task_set_name(dmt, dev->path))
427 dm_task_no_open_count(dmt);
429 if (!dm_task_run(dmt))
432 next = dm_get_next_target(dmt, NULL, &start, &length,
433 &target_type, ¶ms);
435 arch_specific->dmtype = strdup(target_type ? target_type : "NO-TARGET");
436 if (arch_specific->dmtype == NULL)
440 dm_task_destroy(dmt);
450 char buf [512]; /* readdir(3) claims d_name[256] */
453 mapper_dir = opendir ("/dev/mapper");
457 /* Search the /dev/mapper directory for devices w/ the same major
458 * number that was returned from _probe_lvm_major().
460 while ((dent = readdir (mapper_dir))) {
461 if (strcmp (dent->d_name, ".") == 0 ||
462 strcmp (dent->d_name, "..") == 0)
465 snprintf (buf, sizeof (buf), "/dev/mapper/%s", dent->d_name);
467 if (stat (buf, &st) != 0)
470 if (_is_dm_major(major(st.st_rdev)))
471 _ped_device_probe (buf);
473 closedir (mapper_dir);
480 _device_stat (PedDevice* dev, struct stat * dev_stat)
482 PED_ASSERT (dev != NULL, return 0);
483 PED_ASSERT (!dev->external_mode, return 0);
486 if (!stat (dev->path, dev_stat)) {
489 if (ped_exception_throw (
491 PED_EXCEPTION_RETRY_CANCEL,
492 _("Could not stat device %s - %s."),
495 != PED_EXCEPTION_RETRY)
502 _device_probe_type (PedDevice* dev)
504 struct stat dev_stat;
508 if (!_device_stat (dev, &dev_stat))
511 if (!S_ISBLK(dev_stat.st_mode)) {
512 dev->type = PED_DEVICE_FILE;
516 dev_major = major (dev_stat.st_rdev);
517 dev_minor = minor (dev_stat.st_rdev);
519 if (SCSI_BLK_MAJOR (dev_major) && (dev_minor % 0x10 == 0)) {
520 dev->type = PED_DEVICE_SCSI;
521 } else if (_is_ide_major (dev_major) && (dev_minor % 0x40 == 0)) {
522 dev->type = PED_DEVICE_IDE;
523 } else if (dev_major == DAC960_MAJOR && (dev_minor % 0x8 == 0)) {
524 dev->type = PED_DEVICE_DAC960;
525 } else if (dev_major == ATARAID_MAJOR && (dev_minor % 0x10 == 0)) {
526 dev->type = PED_DEVICE_ATARAID;
527 } else if (dev_major == DASD_MAJOR && (dev_minor % 0x4 == 0)) {
528 dev->type = PED_DEVICE_DASD;
529 } else if (dev_major == VIODASD_MAJOR && (dev_minor % 0x8 == 0)) {
530 dev->type = PED_DEVICE_VIODASD;
531 } else if (_is_sx8_major(dev_major) && (dev_minor % 0x20 == 0)) {
532 dev->type = PED_DEVICE_SX8;
533 } else if (_is_i2o_major (dev_major) && (dev_minor % 0x10 == 0)) {
534 dev->type = PED_DEVICE_I2O;
535 } else if (_is_cpqarray_major (dev_major) && (dev_minor % 0x10 == 0)) {
536 dev->type = PED_DEVICE_CPQARRAY;
537 } else if (dev_major == UBD_MAJOR && (dev_minor % 0x10 == 0)) {
538 dev->type = PED_DEVICE_UBD;
539 #ifdef ENABLE_DEVICE_MAPPER
540 } else if (_is_dm_major(dev_major)) {
541 dev->type = PED_DEVICE_DM;
542 if (_dm_maptype(dev)) {
543 ped_exception_throw (
545 PED_EXCEPTION_CANCEL,
546 _("Unable to determine the dm type of %s."),
550 } else if (dev_major == XVD_MAJOR && (dev_minor % 0x10 == 0)) {
551 dev->type = PED_DEVICE_XVD;
552 } else if (dev_major == SDMMC_MAJOR && (dev_minor % 0x08 == 0)) {
553 dev->type = PED_DEVICE_SDMMC;
554 } else if (_is_virtblk_major(dev_major)) {
555 dev->type = PED_DEVICE_VIRTBLK;
557 dev->type = PED_DEVICE_UNKNOWN;
564 _get_linux_version ()
566 static int kver = -1;
578 if (sscanf (uts.release, "%u.%u.%u", &major, &minor, &teeny) != 3)
581 return kver = KERNEL_VERSION (major, minor, teeny);
585 _device_set_sector_size (PedDevice* dev)
587 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
590 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
591 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
593 PED_ASSERT (dev->open_count, return);
595 if (_get_linux_version() < KERNEL_VERSION (2,3,0)) {
596 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
600 if (ioctl (arch_specific->fd, BLKSSZGET, §or_size)) {
601 ped_exception_throw (
602 PED_EXCEPTION_WARNING,
604 _("Could not determine sector size for %s: %s.\n"
605 "Using the default sector size (%lld)."),
606 dev->path, strerror (errno), PED_SECTOR_SIZE_DEFAULT);
608 dev->sector_size = (long long)sector_size;
611 /* Return PED_SECTOR_SIZE_DEFAULT for DASDs. */
612 if (dev->type == PED_DEVICE_DASD) {
613 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
616 if (dev->sector_size != PED_SECTOR_SIZE_DEFAULT) {
617 ped_exception_throw (
618 PED_EXCEPTION_WARNING,
620 _("Device %s has a logical sector size of %lld. Not "
621 "all parts of GNU Parted support this at the moment, "
622 "and the working code is HIGHLY EXPERIMENTAL.\n"),
623 dev->path, dev->sector_size);
628 _kernel_has_blkgetsize64(void)
630 int version = _get_linux_version();
632 if (version >= KERNEL_VERSION (2,5,4)) return 1;
633 if (version < KERNEL_VERSION (2,5,0) &&
634 version >= KERNEL_VERSION (2,4,18)) return 1;
638 /* TODO: do a binary search if BLKGETSIZE doesn't work?! */
640 _device_get_length (PedDevice* dev)
643 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
647 PED_ASSERT (dev->open_count > 0, return 0);
648 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
650 if (_kernel_has_blkgetsize64()) {
651 if (ioctl(arch_specific->fd, BLKGETSIZE64, &bytes) == 0) {
652 return bytes / dev->sector_size;
656 if (ioctl (arch_specific->fd, BLKGETSIZE, &size)) {
657 ped_exception_throw (
659 PED_EXCEPTION_CANCEL,
660 _("Unable to determine the size of %s (%s)."),
670 _device_probe_geometry (PedDevice* dev)
672 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
673 struct stat dev_stat;
674 struct hd_geometry geometry;
676 if (!_device_stat (dev, &dev_stat))
678 PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
680 _device_set_sector_size (dev);
682 dev->length = _device_get_length (dev);
686 /* The GETGEO ioctl is no longer useful (as of linux 2.6.x). We could
687 * still use it in 2.4.x, but this is contentious. Perhaps we should
689 dev->bios_geom.sectors = 63;
690 dev->bios_geom.heads = 255;
691 dev->bios_geom.cylinders
692 = dev->length / (63 * 255);
694 /* FIXME: what should we put here? (TODO: discuss on linux-kernel) */
695 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geometry)
696 && geometry.sectors && geometry.heads) {
697 dev->hw_geom.sectors = geometry.sectors;
698 dev->hw_geom.heads = geometry.heads;
699 dev->hw_geom.cylinders
700 = dev->length / (dev->hw_geom.heads
701 * dev->hw_geom.sectors);
703 dev->hw_geom = dev->bios_geom;
710 strip_name(char* str)
715 for (i = 0; str[i] != 0; i++) {
716 if (!isspace (str[i])
717 || (isspace (str[i]) && !isspace (str[i+1]) && str[i+1])) {
727 init_ide (PedDevice* dev)
729 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
730 struct stat dev_stat;
732 struct hd_driveid hdi;
733 PedExceptionOption ex_status;
735 int sector_multiplier = 0;
737 if (!_device_stat (dev, &dev_stat))
740 dev_major = major (dev_stat.st_rdev);
742 if (!ped_device_open (dev))
745 if (ioctl (arch_specific->fd, HDIO_GET_IDENTITY, &hdi)) {
746 ex_status = ped_exception_throw (
747 PED_EXCEPTION_WARNING,
748 PED_EXCEPTION_IGNORE_CANCEL,
749 _("Could not get identity of device %s - %s"),
750 dev->path, strerror (errno));
752 case PED_EXCEPTION_CANCEL:
753 goto error_close_dev;
755 case PED_EXCEPTION_UNHANDLED:
756 ped_exception_catch ();
757 case PED_EXCEPTION_IGNORE:
758 dev->model = strdup(_("Generic IDE"));
761 PED_ASSERT (0, (void) 0);
765 /* hdi.model is not guaranteed to be NULL terminated */
766 memcpy (hdi_buf, hdi.model, 40);
768 dev->model = strip_name (hdi_buf);
770 if (!hdi.ata7_sectinfo.valid1 && hdi.ata7_sectinfo.valid2)
771 sector_multiplier = hdi.ata7_sectinfo.multiplier;
773 sector_multiplier = 1;
775 if (sector_multiplier != 1) {
776 ex_status = ped_exception_throw (
777 PED_EXCEPTION_WARNING,
778 PED_EXCEPTION_IGNORE_CANCEL,
779 _("Device %s has multiple (%d) logical sectors "
780 "per physical sector.\n"
781 "GNU Parted supports this EXPERIMENTALLY for "
782 "some special disk label/file system "
783 "combinations, e.g. GPT and ext2/3.\n"
784 "Please consult the web site for up-to-date "
786 dev->path, sector_multiplier);
789 case PED_EXCEPTION_CANCEL:
790 goto error_close_dev;
792 case PED_EXCEPTION_UNHANDLED:
793 ped_exception_catch ();
794 case PED_EXCEPTION_IGNORE:
797 PED_ASSERT (0, (void) 0);
802 /* XXX sector_size has not been set yet! */
803 /* dev->phys_sector_size = dev->sector_size
804 * sector_multiplier;*/
805 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
808 if (!_device_probe_geometry (dev))
809 goto error_close_dev;
811 ped_device_close (dev);
815 ped_device_close (dev);
820 /* This function reads the /sys entry named "file" for device "dev". */
822 read_device_sysfs_file (PedDevice *dev, const char *file)
828 snprintf (name_buf, 127, "/sys/block/%s/device/%s",
829 last_component (dev->path), file);
831 if ((f = fopen (name_buf, "r")) == NULL)
834 if (fgets (buf, 255, f) == NULL)
838 return strip_name (buf);
841 /* This function sends a query to a SCSI device for vendor and product
842 * information. It uses the deprecated SCSI_IOCTL_SEND_COMMAND to
846 scsi_query_product_info (PedDevice* dev, char **vendor, char **product)
848 /* The following are defined by the SCSI-2 specification. */
849 typedef struct _scsi_inquiry_cmd
852 uint8_t lun; /* bits 5-7 denote the LUN */
855 uint8_t alloc_length;
857 } __attribute__((packed)) scsi_inquiry_cmd_t;
859 typedef struct _scsi_inquiry_data
861 uint8_t peripheral_info;
863 uint8_t version_info;
865 uint8_t additional_length;
869 uint8_t vendor_id[8];
870 uint8_t product_id[16];
871 uint8_t product_revision[4];
872 uint8_t vendor_specific[20];
873 uint8_t _reserved3[40];
874 } __attribute__((packed)) scsi_inquiry_data_t;
883 scsi_inquiry_data_t out;
884 scsi_inquiry_cmd_t in;
888 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
894 memset (&arg, 0x00, sizeof(struct scsi_arg));
896 arg.outlen = sizeof(scsi_inquiry_data_t);
897 arg.data.in.op = INQUIRY;
898 arg.data.in.lun = dev->host << 5;
899 arg.data.in.alloc_length = sizeof(scsi_inquiry_data_t);
900 arg.data.in.page_code = 0;
901 arg.data.in.reserved = 0;
902 arg.data.in.control = 0;
904 if (ioctl (arch_specific->fd, SCSI_IOCTL_SEND_COMMAND, &arg) < 0)
907 memcpy (buf, arg.data.out.vendor_id, 8);
909 *vendor = strip_name (buf);
911 memcpy (buf, arg.data.out.product_id, 16);
913 *product = strip_name (buf);
918 /* This function provides the vendor and product name for a SCSI device.
919 * It supports both the modern /sys interface and direct queries
920 * via the deprecated ioctl, SCSI_IOCTL_SEND_COMMAND.
923 scsi_get_product_info (PedDevice* dev, char **vendor, char **product)
925 *vendor = read_device_sysfs_file (dev, "vendor");
926 *product = read_device_sysfs_file (dev, "model");
927 if (*vendor && *product)
930 return scsi_query_product_info (dev, vendor, product);
934 init_scsi (PedDevice* dev)
939 uint32_t host_unique_id;
942 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
946 if (!ped_device_open (dev))
949 if (ioctl (arch_specific->fd, SCSI_IOCTL_GET_IDLUN, &idlun) < 0) {
952 if (ped_exception_throw (
953 PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
954 _("Error initialising SCSI device %s - %s"),
955 dev->path, strerror (errno))
956 != PED_EXCEPTION_IGNORE)
957 goto error_close_dev;
958 if (!_device_probe_geometry (dev))
959 goto error_close_dev;
960 ped_device_close (dev);
964 dev->host = idlun.host_unique_id;
965 dev->did = idlun.dev_id;
967 dev->model = (char*) ped_malloc (8 + 16 + 2);
969 goto error_close_dev;
971 if (scsi_get_product_info (dev, &vendor, &product)) {
972 sprintf (dev->model, "%.8s %.16s", vendor, product);
976 strcpy (dev->model, "Generic SCSI");
979 if (!_device_probe_geometry (dev))
980 goto error_close_dev;
982 ped_device_close (dev);
986 ped_device_close (dev);
992 init_file (PedDevice* dev)
994 struct stat dev_stat;
996 if (!_device_stat (dev, &dev_stat))
998 if (!ped_device_open (dev))
1001 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1002 char *p = getenv ("PARTED_SECTOR_SIZE");
1005 if (0 < s && s % 512 == 0)
1006 dev->sector_size = s;
1008 dev->phys_sector_size = dev->sector_size;
1010 if (S_ISBLK(dev_stat.st_mode))
1011 dev->length = _device_get_length (dev);
1013 dev->length = dev_stat.st_size / dev->sector_size;
1014 if (dev->length <= 0) {
1015 ped_exception_throw (
1016 PED_EXCEPTION_ERROR,
1017 PED_EXCEPTION_CANCEL,
1018 _("The device %s has zero length, and can't possibly "
1019 "store a file system or partition table. Perhaps "
1020 "you selected the wrong device?"),
1022 goto error_close_dev;
1025 ped_device_close (dev);
1027 dev->bios_geom.cylinders = dev->length / 4 / 32;
1028 dev->bios_geom.heads = 4;
1029 dev->bios_geom.sectors = 32;
1030 dev->hw_geom = dev->bios_geom;
1031 dev->model = strdup ("");
1036 ped_device_close (dev);
1042 init_dasd (PedDevice* dev, const char* model_name)
1044 struct stat dev_stat;
1045 struct hd_geometry geo;
1048 if (!_device_stat (dev, &dev_stat))
1051 if (!ped_device_open (dev))
1054 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1056 PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
1058 _device_set_sector_size (dev);
1059 if (!dev->sector_size)
1060 goto error_close_dev;
1062 dev->length = _device_get_length (dev);
1064 goto error_close_dev;
1066 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geo)) {
1067 dev->hw_geom.sectors = geo.sectors;
1068 dev->hw_geom.heads = geo.heads;
1069 dev->hw_geom.cylinders = dev->length
1070 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1071 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1072 dev->bios_geom = dev->hw_geom;
1074 dev->bios_geom.sectors = 12;
1075 dev->bios_geom.heads = 15;
1076 dev->bios_geom.cylinders = dev->length
1077 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1078 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1079 dev->hw_geom = dev->bios_geom;
1082 dev->model = strdup (model_name);
1084 ped_device_close (dev);
1087 ped_exception_throw ( PED_EXCEPTION_ERROR,
1088 PED_EXCEPTION_IGNORE_CANCEL,
1092 ped_device_close (dev);
1098 init_generic (PedDevice* dev, const char* model_name)
1100 struct stat dev_stat;
1101 PedExceptionOption ex_status;
1103 if (!_device_stat (dev, &dev_stat))
1106 if (!ped_device_open (dev))
1109 ped_exception_fetch_all ();
1110 if (_device_probe_geometry (dev)) {
1111 ped_exception_leave_all ();
1113 /* hack to allow use of files, for testing */
1114 ped_exception_catch ();
1115 ped_exception_leave_all ();
1117 ex_status = ped_exception_throw (
1118 PED_EXCEPTION_WARNING,
1119 PED_EXCEPTION_IGNORE_CANCEL,
1120 _("Unable to determine geometry of "
1121 "file/device %s. You should not use Parted "
1122 "unless you REALLY know what you're doing!"),
1124 switch (ex_status) {
1125 case PED_EXCEPTION_CANCEL:
1126 goto error_close_dev;
1128 case PED_EXCEPTION_UNHANDLED:
1129 ped_exception_catch ();
1130 case PED_EXCEPTION_IGNORE:
1133 PED_ASSERT (0, (void) 0);
1137 /* what should we stick in here? */
1138 dev->length = dev_stat.st_size / PED_SECTOR_SIZE_DEFAULT;
1139 dev->bios_geom.cylinders = dev->length / 4 / 32;
1140 dev->bios_geom.heads = 4;
1141 dev->bios_geom.sectors = 32;
1142 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1143 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
1146 dev->model = strdup (model_name);
1148 ped_device_close (dev);
1152 ped_device_close (dev);
1158 sdmmc_get_product_info (PedDevice* dev, char **type, char **name)
1160 *type = read_device_sysfs_file (dev, "type");
1161 *name = read_device_sysfs_file (dev, "name");
1169 init_sdmmc (PedDevice* dev)
1174 if (sdmmc_get_product_info (dev, &type, &name)) {
1175 snprintf (id, sizeof(id) - 1, "%s %s", type, name);
1179 snprintf (id, sizeof(id) - 1, "%s",
1180 _("Generic SD/MMC Storage Card"));
1182 return init_generic(dev, id);
1186 linux_new (const char* path)
1189 LinuxSpecific* arch_specific;
1191 PED_ASSERT (path != NULL, return NULL);
1193 dev = (PedDevice*) ped_malloc (sizeof (PedDevice));
1197 dev->path = strdup (path);
1199 goto error_free_dev;
1202 = (LinuxSpecific*) ped_malloc (sizeof (LinuxSpecific));
1203 if (!dev->arch_specific)
1204 goto error_free_path;
1205 arch_specific = LINUX_SPECIFIC (dev);
1206 arch_specific->dmtype = NULL;
1208 dev->open_count = 0;
1210 dev->external_mode = 0;
1212 dev->boot_dirty = 0;
1214 if (!_device_probe_type (dev))
1215 goto error_free_arch_specific;
1217 switch (dev->type) {
1218 case PED_DEVICE_IDE:
1219 if (!init_ide (dev))
1220 goto error_free_arch_specific;
1223 case PED_DEVICE_SCSI:
1224 if (!init_scsi (dev))
1225 goto error_free_arch_specific;
1228 case PED_DEVICE_DAC960:
1229 if (!init_generic (dev, _("DAC960 RAID controller")))
1230 goto error_free_arch_specific;
1233 case PED_DEVICE_SX8:
1234 if (!init_generic (dev, _("Promise SX8 SATA Device")))
1235 goto error_free_arch_specific;
1238 case PED_DEVICE_DASD:
1239 if (!init_dasd (dev, _("IBM S390 DASD drive")))
1240 goto error_free_arch_specific;
1243 case PED_DEVICE_VIODASD:
1244 if (!init_generic (dev, _("IBM iSeries Virtual DASD")))
1245 goto error_free_arch_specific;
1248 case PED_DEVICE_CPQARRAY:
1249 if (!init_generic (dev, _("Compaq Smart Array")))
1250 goto error_free_arch_specific;
1253 case PED_DEVICE_ATARAID:
1254 if (!init_generic (dev, _("ATARAID Controller")))
1255 goto error_free_arch_specific;
1258 case PED_DEVICE_I2O:
1259 if (!init_generic (dev, _("I2O Controller")))
1260 goto error_free_arch_specific;
1263 case PED_DEVICE_UBD:
1264 if (!init_generic (dev, _("User-Mode Linux UBD")))
1265 goto error_free_arch_specific;
1268 case PED_DEVICE_FILE:
1269 if (!init_file (dev))
1270 goto error_free_arch_specific;
1276 if (arch_specific->dmtype == NULL
1277 || asprintf(&type, _("Linux device-mapper (%s)"),
1278 arch_specific->dmtype) == -1)
1279 goto error_free_arch_specific;
1280 bool ok = init_generic (dev, type);
1283 goto error_free_arch_specific;
1287 case PED_DEVICE_XVD:
1288 if (!init_generic (dev, _("Xen Virtual Block Device")))
1289 goto error_free_arch_specific;
1292 case PED_DEVICE_UNKNOWN:
1293 if (!init_generic (dev, _("Unknown")))
1294 goto error_free_arch_specific;
1297 case PED_DEVICE_SDMMC:
1298 if (!init_sdmmc (dev))
1299 goto error_free_arch_specific;
1301 case PED_DEVICE_VIRTBLK:
1302 if (!init_generic(dev, _("Virtio Block Device")))
1303 goto error_free_arch_specific;
1307 ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
1308 PED_EXCEPTION_CANCEL,
1309 _("ped_device_new() Unsupported device type"));
1310 goto error_free_arch_specific;
1314 error_free_arch_specific:
1315 free (dev->arch_specific);
1325 linux_destroy (PedDevice* dev)
1327 free (((LinuxSpecific*)dev->arch_specific)->dmtype);
1328 free (dev->arch_specific);
1335 linux_is_busy (PedDevice* dev)
1340 if (_partition_is_mounted_by_path (dev->path))
1343 for (i = 0; i < 32; i++) {
1346 part_name = _device_get_part_path (dev, i);
1349 status = _partition_is_mounted_by_path (part_name);
1359 /* we need to flush the master device, and all the partition devices,
1360 * because there is no coherency between the caches.
1361 * We should only flush unmounted partition devices, because:
1362 * - there is never a need to flush them (we're not doing IO there)
1363 * - flushing a device that is mounted causes unnecessary IO, and can
1364 * even screw journaling & friends up. Even cause oopsen!
1367 _flush_cache (PedDevice* dev)
1369 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1376 ioctl (arch_specific->fd, BLKFLSBUF);
1378 for (i = 1; i < 16; i++) {
1382 name = _device_get_part_path (dev, i);
1385 if (!_partition_is_mounted_by_path (name)) {
1386 fd = open (name, WR_MODE, 0);
1388 ioctl (fd, BLKFLSBUF);
1390 if (fsync (fd) < 0 || close (fd) < 0)
1391 if (ped_exception_throw (
1392 PED_EXCEPTION_WARNING,
1393 PED_EXCEPTION_RETRY +
1394 PED_EXCEPTION_IGNORE,
1395 _("Error fsyncing/closing %s: %s"),
1396 name, strerror (errno))
1397 == PED_EXCEPTION_RETRY)
1406 linux_open (PedDevice* dev)
1408 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1411 arch_specific->fd = open (dev->path, RW_MODE);
1413 if (arch_specific->fd == -1) {
1414 char* rw_error_msg = strerror (errno);
1416 arch_specific->fd = open (dev->path, RD_MODE);
1418 if (arch_specific->fd == -1) {
1419 if (ped_exception_throw (
1420 PED_EXCEPTION_ERROR,
1421 PED_EXCEPTION_RETRY_CANCEL,
1422 _("Error opening %s: %s"),
1423 dev->path, strerror (errno))
1424 != PED_EXCEPTION_RETRY) {
1430 ped_exception_throw (
1431 PED_EXCEPTION_WARNING,
1433 _("Unable to open %s read-write (%s). %s has "
1434 "been opened read-only."),
1435 dev->path, rw_error_msg, dev->path);
1448 linux_refresh_open (PedDevice* dev)
1454 linux_close (PedDevice* dev)
1456 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1461 if (fsync (arch_specific->fd) < 0 || close (arch_specific->fd) < 0)
1462 if (ped_exception_throw (
1463 PED_EXCEPTION_WARNING,
1464 PED_EXCEPTION_RETRY + PED_EXCEPTION_IGNORE,
1465 _("Error fsyncing/closing %s: %s"),
1466 dev->path, strerror (errno))
1467 == PED_EXCEPTION_RETRY)
1473 linux_refresh_close (PedDevice* dev)
1480 #if SIZEOF_OFF_T < 8
1482 static _syscall5(int,_llseek,
1484 unsigned long, offset_high,
1485 unsigned long, offset_low,
1487 unsigned int, origin)
1490 llseek (unsigned int fd, loff_t offset, unsigned int whence)
1495 retval = _llseek(fd,
1496 ((unsigned long long)offset) >> 32,
1497 ((unsigned long long)offset) & 0xffffffff,
1500 return (retval==-1 ? (loff_t) retval : result);
1503 #endif /* SIZEOF_OFF_T < 8 */
1506 _device_seek (const PedDevice* dev, PedSector sector)
1508 LinuxSpecific* arch_specific;
1510 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1511 PED_ASSERT (dev != NULL, return 0);
1512 PED_ASSERT (!dev->external_mode, return 0);
1514 arch_specific = LINUX_SPECIFIC (dev);
1516 #if SIZEOF_OFF_T < 8
1517 if (sizeof (off_t) < 8) {
1518 loff_t pos = (loff_t)(sector * dev->sector_size);
1519 return llseek (arch_specific->fd, pos, SEEK_SET) == pos;
1523 off_t pos = sector * dev->sector_size;
1524 return lseek (arch_specific->fd, pos, SEEK_SET) == pos;
1529 _read_lastoddsector (const PedDevice* dev, void* buffer)
1531 LinuxSpecific* arch_specific;
1532 struct blkdev_ioctl_param ioctl_param;
1534 PED_ASSERT(dev != NULL, return 0);
1535 PED_ASSERT(buffer != NULL, return 0);
1537 arch_specific = LINUX_SPECIFIC (dev);
1540 ioctl_param.block = 0; /* read the last sector */
1541 ioctl_param.content_length = dev->sector_size;
1542 ioctl_param.block_contents = buffer;
1544 if (ioctl(arch_specific->fd, BLKGETLASTSECT, &ioctl_param) == -1) {
1545 PedExceptionOption opt;
1546 opt = ped_exception_throw (
1547 PED_EXCEPTION_ERROR,
1548 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1549 _("%s during read on %s"),
1550 strerror (errno), dev->path);
1552 if (opt == PED_EXCEPTION_CANCEL)
1554 if (opt == PED_EXCEPTION_RETRY)
1562 linux_read (const PedDevice* dev, void* buffer, PedSector start,
1565 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1566 PedExceptionOption ex_status;
1567 void* diobuf = NULL;
1569 PED_ASSERT (dev != NULL, return 0);
1570 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1572 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1573 /* Kludge. This is necessary to read/write the last
1574 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1576 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1577 && start + count - 1 == dev->length - 1)
1578 return ped_device_read (dev, buffer, start, count - 1)
1579 && _read_lastoddsector (
1580 dev, (char *) buffer + (count-1) * 512);
1583 if (_device_seek (dev, start))
1586 ex_status = ped_exception_throw (
1587 PED_EXCEPTION_ERROR,
1588 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1589 _("%s during seek for read on %s"),
1590 strerror (errno), dev->path);
1592 switch (ex_status) {
1593 case PED_EXCEPTION_IGNORE:
1596 case PED_EXCEPTION_RETRY:
1599 case PED_EXCEPTION_UNHANDLED:
1600 ped_exception_catch ();
1601 case PED_EXCEPTION_CANCEL:
1604 PED_ASSERT (0, (void) 0);
1609 size_t read_length = count * dev->sector_size;
1610 if (posix_memalign (&diobuf, dev->sector_size, read_length) != 0)
1614 ssize_t status = read (arch_specific->fd, diobuf, read_length);
1616 memcpy(buffer, diobuf, status);
1617 if (status == (ssize_t) read_length)
1620 read_length -= status;
1621 buffer = (char *) buffer + status;
1625 ex_status = ped_exception_throw (
1626 PED_EXCEPTION_ERROR,
1627 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1628 _("%s during read on %s"),
1632 switch (ex_status) {
1633 case PED_EXCEPTION_IGNORE:
1637 case PED_EXCEPTION_RETRY:
1640 case PED_EXCEPTION_UNHANDLED:
1641 ped_exception_catch ();
1642 case PED_EXCEPTION_CANCEL:
1646 PED_ASSERT (0, (void) 0);
1657 _write_lastoddsector (PedDevice* dev, const void* buffer)
1659 LinuxSpecific* arch_specific;
1660 struct blkdev_ioctl_param ioctl_param;
1662 PED_ASSERT(dev != NULL, return 0);
1663 PED_ASSERT(buffer != NULL, return 0);
1665 arch_specific = LINUX_SPECIFIC (dev);
1668 ioctl_param.block = 0; /* write the last sector */
1669 ioctl_param.content_length = dev->sector_size;
1670 ioctl_param.block_contents = (void*) buffer;
1672 if (ioctl(arch_specific->fd, BLKSETLASTSECT, &ioctl_param) == -1) {
1673 PedExceptionOption opt;
1674 opt = ped_exception_throw (
1675 PED_EXCEPTION_ERROR,
1676 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1677 _("%s during write on %s"),
1678 strerror (errno), dev->path);
1680 if (opt == PED_EXCEPTION_CANCEL)
1682 if (opt == PED_EXCEPTION_RETRY)
1690 linux_write (PedDevice* dev, const void* buffer, PedSector start,
1693 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1694 PedExceptionOption ex_status;
1698 PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1700 if (dev->read_only) {
1701 if (ped_exception_throw (
1702 PED_EXCEPTION_ERROR,
1703 PED_EXCEPTION_IGNORE_CANCEL,
1704 _("Can't write to %s, because it is opened read-only."),
1706 != PED_EXCEPTION_IGNORE)
1712 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1713 /* Kludge. This is necessary to read/write the last
1714 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1716 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1717 && start + count - 1 == dev->length - 1)
1718 return ped_device_write (dev, buffer, start, count - 1)
1719 && _write_lastoddsector (
1720 dev, ((char*) buffer
1721 + (count-1) * dev->sector_size));
1724 if (_device_seek (dev, start))
1727 ex_status = ped_exception_throw (
1728 PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1729 _("%s during seek for write on %s"),
1730 strerror (errno), dev->path);
1732 switch (ex_status) {
1733 case PED_EXCEPTION_IGNORE:
1736 case PED_EXCEPTION_RETRY:
1739 case PED_EXCEPTION_UNHANDLED:
1740 ped_exception_catch ();
1741 case PED_EXCEPTION_CANCEL:
1744 PED_ASSERT (0, (void) 0);
1750 printf ("ped_device_write (\"%s\", %p, %d, %d)\n",
1751 dev->path, buffer, (int) start, (int) count);
1753 size_t write_length = count * dev->sector_size;
1755 if (posix_memalign(&diobuf, dev->sector_size, write_length) != 0)
1757 memcpy(diobuf, buffer, write_length);
1758 diobuf_start = diobuf;
1760 ssize_t status = write (arch_specific->fd, diobuf, write_length);
1761 if (status == write_length) break;
1763 write_length -= status;
1764 diobuf = (char *) diobuf + status;
1768 ex_status = ped_exception_throw (
1769 PED_EXCEPTION_ERROR,
1770 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1771 _("%s during write on %s"),
1772 strerror (errno), dev->path);
1774 switch (ex_status) {
1775 case PED_EXCEPTION_IGNORE:
1779 case PED_EXCEPTION_RETRY:
1782 case PED_EXCEPTION_UNHANDLED:
1783 ped_exception_catch ();
1784 case PED_EXCEPTION_CANCEL:
1788 PED_ASSERT (0, (void) 0);
1793 #endif /* !READ_ONLY */
1797 /* returns the number of sectors that are ok.
1800 linux_check (PedDevice* dev, void* buffer, PedSector start, PedSector count)
1802 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1807 PED_ASSERT(dev != NULL, return 0);
1809 if (!_device_seek (dev, start))
1812 if (posix_memalign(&diobuf, PED_SECTOR_SIZE_DEFAULT,
1813 count * PED_SECTOR_SIZE_DEFAULT) != 0)
1816 for (done = 0; done < count; done += status / dev->sector_size) {
1817 status = read (arch_specific->fd, diobuf,
1818 (size_t) ((count-done) * dev->sector_size));
1820 memcpy(buffer, diobuf, status);
1830 _do_fsync (PedDevice* dev)
1832 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1834 PedExceptionOption ex_status;
1837 status = fsync (arch_specific->fd);
1838 if (status >= 0) break;
1840 ex_status = ped_exception_throw (
1841 PED_EXCEPTION_ERROR,
1842 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1843 _("%s during write on %s"),
1844 strerror (errno), dev->path);
1846 switch (ex_status) {
1847 case PED_EXCEPTION_IGNORE:
1850 case PED_EXCEPTION_RETRY:
1853 case PED_EXCEPTION_UNHANDLED:
1854 ped_exception_catch ();
1855 case PED_EXCEPTION_CANCEL:
1858 PED_ASSERT (0, (void) 0);
1866 linux_sync (PedDevice* dev)
1868 PED_ASSERT (dev != NULL, return 0);
1869 PED_ASSERT (!dev->external_mode, return 0);
1873 if (!_do_fsync (dev))
1880 linux_sync_fast (PedDevice* dev)
1882 PED_ASSERT (dev != NULL, return 0);
1883 PED_ASSERT (!dev->external_mode, return 0);
1887 if (!_do_fsync (dev))
1889 /* no cache flush... */
1894 _compare_digit_state (char ch, int need_digit)
1896 return !!isdigit (ch) == need_digit;
1899 /* matches the regexp "[^0-9]+[0-9]+[^0-9]+[0-9]+$".
1900 * Motivation: accept devices looking like /dev/rd/c0d0, but
1901 * not looking like /dev/hda1 and /dev/rd/c0d0p1
1904 _match_rd_device (const char* name)
1909 /* exclude directory names from test */
1910 pos = strrchr(name, '/') ?: name;
1918 for (state = 0; state < 4; state++) {
1919 int want_digits = (state % 2 == 1);
1923 if (!_compare_digit_state (*pos, want_digits))
1926 } while (_compare_digit_state (*pos, want_digits));
1933 _probe_proc_partitions ()
1935 FILE* proc_part_file;
1936 int major, minor, size;
1938 char part_name [256];
1939 char dev_name [256];
1941 proc_part_file = fopen ("/proc/partitions", "r");
1942 if (!proc_part_file)
1945 if (fgets (buf, 256, proc_part_file) == NULL)
1948 if (fgets (buf, 256, proc_part_file) == NULL)
1951 while (fgets (buf, 512, proc_part_file)
1952 && sscanf (buf, "%d %d %d %255s", &major, &minor, &size,
1954 /* Heuristic for telling partitions and devices apart
1955 * Probably needs to be improved
1957 if (!_match_rd_device (part_name)
1958 && isdigit (part_name [strlen (part_name) - 1]))
1961 strcpy (dev_name, "/dev/");
1962 strcat (dev_name, part_name);
1963 _ped_device_probe (dev_name);
1966 fclose (proc_part_file);
1976 _skip_entry (const char *name)
1979 static struct _entry entries[] = {
1980 { ".", sizeof (".") - 1 },
1981 { "..", sizeof ("..") - 1 },
1982 { "dm-", sizeof ("dm-") - 1 },
1983 { "loop", sizeof ("loop") - 1 },
1984 { "ram", sizeof ("ram") - 1 },
1988 for (i = entries; i->name != 0; i++) {
1989 if (strncmp (name, i->name, i->len) == 0)
2000 struct dirent *dirent;
2001 char dev_name [256];
2004 if (!(blockdir = opendir ("/sys/block")))
2006 while ((dirent = readdir (blockdir))) {
2007 if (_skip_entry (dirent->d_name))
2010 if (strlen (dirent->d_name) > sizeof (dev_name) - 6)
2011 continue; /* device name too long! */
2013 strcpy (dev_name, "/dev/");
2014 strcat (dev_name, dirent->d_name);
2015 /* in /sys/block, '/'s are replaced with '!' or '.' */
2016 for (ptr = dev_name; *ptr != '\0'; ptr++) {
2017 if (*ptr == '!' || *ptr == '.')
2020 _ped_device_probe (dev_name);
2023 closedir (blockdir);
2028 _probe_standard_devices ()
2030 _ped_device_probe ("/dev/hda");
2031 _ped_device_probe ("/dev/hdb");
2032 _ped_device_probe ("/dev/hdc");
2033 _ped_device_probe ("/dev/hdd");
2034 _ped_device_probe ("/dev/hde");
2035 _ped_device_probe ("/dev/hdf");
2036 _ped_device_probe ("/dev/hdg");
2037 _ped_device_probe ("/dev/hdh");
2039 _ped_device_probe ("/dev/sda");
2040 _ped_device_probe ("/dev/sdb");
2041 _ped_device_probe ("/dev/sdc");
2042 _ped_device_probe ("/dev/sdd");
2043 _ped_device_probe ("/dev/sde");
2044 _ped_device_probe ("/dev/sdf");
2052 /* we should probe the standard devs too, even with /proc/partitions,
2053 * because /proc/partitions might return devfs stuff, and we might not
2054 * have devfs available
2056 _probe_standard_devices ();
2058 #ifdef ENABLE_DEVICE_MAPPER
2059 /* device-mapper devices aren't listed in /proc/partitions; or, if
2060 * they are, they're listed as dm-X. So, instead of relying on that,
2061 * we do our own checks.
2063 _probe_dm_devices ();
2066 /* /sys/block is more reliable and consistent; fall back to using
2067 * /proc/partitions if the former is unavailable, however.
2069 if (!_probe_sys_block ())
2070 _probe_proc_partitions ();
2074 _device_get_part_path (PedDevice* dev, int num)
2076 int path_len = strlen (dev->path);
2077 int result_len = path_len + 16;
2080 result = (char*) ped_malloc (result_len);
2084 /* Check for devfs-style /disc => /partN transformation
2085 unconditionally; the system might be using udev with devfs rules,
2086 and if not the test is harmless. */
2087 if (!strcmp (dev->path + path_len - 5, "/disc")) {
2088 /* replace /disc with /path%d */
2089 strcpy (result, dev->path);
2090 snprintf (result + path_len - 5, 16, "/part%d", num);
2091 } else if (dev->type == PED_DEVICE_DAC960
2092 || dev->type == PED_DEVICE_CPQARRAY
2093 || dev->type == PED_DEVICE_ATARAID
2094 || dev->type == PED_DEVICE_DM
2095 || isdigit (dev->path[path_len - 1]))
2096 snprintf (result, result_len, "%sp%d", dev->path, num);
2098 snprintf (result, result_len, "%s%d", dev->path, num);
2104 linux_partition_get_path (const PedPartition* part)
2106 return _device_get_part_path (part->disk->dev, part->num);
2110 _partition_get_part_dev (const PedPartition* part)
2112 struct stat dev_stat;
2113 int dev_major, dev_minor;
2115 if (!_device_stat (part->disk->dev, &dev_stat))
2117 dev_major = major (dev_stat.st_rdev);
2118 dev_minor = minor (dev_stat.st_rdev);
2119 return (dev_t)makedev (dev_major, dev_minor + part->num);
2123 _mount_table_search (const char* file_name, dev_t dev)
2125 struct stat part_stat;
2127 char part_name[512];
2131 file = fopen (file_name, "r");
2134 while (fgets (line, 512, file)) {
2135 junk = sscanf (line, "%s", part_name);
2136 if (stat (part_name, &part_stat) == 0) {
2137 if (part_stat.st_rdev == dev) {
2148 _partition_is_mounted_by_dev (dev_t dev)
2150 return _mount_table_search( "/proc/mounts", dev)
2151 || _mount_table_search( "/proc/swaps", dev)
2152 || _mount_table_search( "/etc/mtab", dev);
2156 _partition_is_mounted_by_path (const char *path)
2158 struct stat part_stat;
2159 if (stat (path, &part_stat) != 0)
2161 if (!S_ISBLK(part_stat.st_mode))
2163 return _partition_is_mounted_by_dev (part_stat.st_rdev);
2167 _partition_is_mounted (const PedPartition *part)
2170 if (!ped_partition_is_active (part))
2172 dev = _partition_get_part_dev (part);
2173 return _partition_is_mounted_by_dev (dev);
2177 _has_partitions (const PedDisk* disk)
2179 PED_ASSERT(disk != NULL, return 0);
2181 /* Some devices can't be partitioned. */
2182 if (!strcmp (disk->type->name, "loop"))
2189 linux_partition_is_busy (const PedPartition* part)
2193 PED_ASSERT (part != NULL, return 0);
2195 if (_partition_is_mounted (part))
2197 if (part->type == PED_PARTITION_EXTENDED) {
2198 for (walk = part->part_list; walk; walk = walk->next) {
2199 if (linux_partition_is_busy (walk))
2206 #ifdef ENABLE_DEVICE_MAPPER
2208 _dm_remove_map_name(char *name)
2210 struct dm_task *task = NULL;
2213 task = dm_task_create(DM_DEVICE_REMOVE);
2217 dm_task_set_name (task, name);
2219 rc = dm_task_run(task);
2220 dm_task_update_nodes();
2221 dm_task_destroy(task);
2229 _dm_is_part (struct dm_info *this, char *name)
2231 struct dm_task* task = NULL;
2232 struct dm_info* info = alloca(sizeof *info);
2233 struct dm_deps* deps = NULL;
2237 task = dm_task_create(DM_DEVICE_DEPS);
2241 dm_task_set_name(task, name);
2242 rc = dm_task_run(task);
2249 memset(info, '\0', sizeof *info);
2250 dm_task_get_info(task, info);
2254 deps = dm_task_get_deps(task);
2259 for (i = 0; i < deps->count; i++) {
2260 unsigned int ma = major(deps->device[i]),
2261 mi = minor(deps->device[i]);
2263 if (ma == this->major && mi == this->minor)
2268 dm_task_destroy(task);
2273 _dm_remove_parts (PedDevice* dev)
2275 struct stat dev_stat;
2276 struct dm_task* task = NULL;
2277 struct dm_info* info = alloca(sizeof *info);
2278 struct dm_names* names = NULL;
2279 unsigned int next = 0;
2282 if (!_device_stat (dev, &dev_stat))
2285 task = dm_task_create(DM_DEVICE_LIST);
2289 dm_task_set_major (task, major (dev_stat.st_rdev));
2290 dm_task_set_minor (task, minor (dev_stat.st_rdev));
2292 rc = dm_task_run(task);
2296 memset(info, '\0', sizeof *info);
2297 dm_task_get_info(task, info);
2301 names = dm_task_get_names(task);
2307 names = (void *) ((char *) names + next);
2309 if (_dm_is_part(info, names->name))
2310 rc += _dm_remove_map_name(names->name);
2315 dm_task_update_nodes();
2316 dm_task_destroy(task);
2323 dm_task_destroy(task);
2324 ped_exception_throw (PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE,
2325 _("parted was unable to re-read the partition "
2326 "table on %s (%s). This means Linux won't know "
2327 "anything about the modifications you made. "),
2328 dev->path, strerror (errno));
2333 _dm_add_partition (PedDisk* disk, PedPartition* part)
2335 struct stat dev_stat;
2336 struct dm_task* task = NULL;
2338 char* vol_name = NULL;
2339 char* dev_name = NULL;
2340 char* params = NULL;
2342 if (!_has_partitions(disk))
2345 dev_name = _device_get_part_path (disk->dev, part->num);
2349 vol_name = strrchr (dev_name, '/');
2350 if (vol_name && *vol_name && *(++vol_name))
2351 vol_name = strdup (vol_name);
2353 vol_name = strdup (dev_name);
2357 if (!_device_stat (disk->dev, &dev_stat))
2360 if (asprintf (¶ms, "%d:%d %lld", major (dev_stat.st_rdev),
2361 minor (dev_stat.st_rdev), part->geom.start) == -1)
2367 task = dm_task_create (DM_DEVICE_CREATE);
2371 dm_task_set_name (task, vol_name);
2372 dm_task_add_target (task, 0, part->geom.length,
2374 rc = dm_task_run(task);
2376 //printf("0 %ld linear %s\n", part->geom.length, params);
2377 dm_task_update_nodes();
2378 dm_task_destroy(task);
2383 _dm_remove_map_name(vol_name);
2386 dm_task_update_nodes();
2388 dm_task_destroy (task);
2395 _dm_reread_part_table (PedDisk* disk)
2397 int largest_partnum = ped_disk_get_last_partition_num (disk);
2398 if (largest_partnum <= 0)
2402 int last = PED_MIN (largest_partnum, 16);
2406 if (!_dm_remove_parts(disk->dev))
2409 for (i = 1; i <= last; i++) {
2412 part = ped_disk_get_partition (disk, i);
2416 if (!_dm_add_partition (disk, part))
2424 _kernel_reread_part_table (PedDevice* dev)
2426 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2427 int retry_count = 5;
2430 while (ioctl (arch_specific->fd, BLKRRPART)) {
2434 ped_exception_throw (
2435 PED_EXCEPTION_WARNING,
2436 PED_EXCEPTION_IGNORE,
2437 _("The kernel was unable to re-read the partition "
2438 "table on %s (%s). This means Linux won't know "
2439 "anything about the modifications you made "
2440 "until you reboot. You should reboot your computer "
2441 "before doing anything with %s."),
2442 dev->path, strerror (errno), dev->path);
2451 linux_disk_commit (PedDisk* disk)
2453 if (!_has_partitions (disk))
2456 #ifdef ENABLE_DEVICE_MAPPER
2457 if (disk->dev->type == PED_DEVICE_DM)
2458 return _dm_reread_part_table (disk);
2460 if (disk->dev->type != PED_DEVICE_FILE) {
2461 return _kernel_reread_part_table (disk->dev);
2467 static PedDeviceArchOps linux_dev_ops = {
2469 destroy: linux_destroy,
2470 is_busy: linux_is_busy,
2472 refresh_open: linux_refresh_open,
2474 refresh_close: linux_refresh_close,
2479 sync_fast: linux_sync_fast,
2480 probe_all: linux_probe_all
2483 PedDiskArchOps linux_disk_ops = {
2484 partition_get_path: linux_partition_get_path,
2485 partition_is_busy: linux_partition_is_busy,
2486 disk_commit: linux_disk_commit
2489 PedArchitecture ped_linux_arch = {
2490 dev_ops: &linux_dev_ops,
2491 disk_ops: &linux_disk_ops