2 libparted - a library for manipulating disk partitions
3 Copyright (C) 1999 - 2005, 2007 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define PROC_DEVICES_BUFSIZ 16384
24 #include <parted/parted.h>
25 #include <parted/debug.h>
26 #include <parted/linux.h>
36 #include <sys/ioctl.h>
38 #include <sys/types.h>
39 #include <sys/utsname.h> /* for uname() */
40 #include <scsi/scsi.h>
41 #ifdef ENABLE_DEVICE_MAPPER
42 #include <libdevmapper.h>
49 # define _(String) dgettext (PACKAGE, String)
51 # define _(String) (String)
52 #endif /* ENABLE_NLS */
54 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
57 #define __NR__llseek 140
60 #ifndef SCSI_IOCTL_SEND_COMMAND
61 #define SCSI_IOCTL_SEND_COMMAND 1
64 /* from <linux/hdreg.h> */
65 #define HDIO_GETGEO 0x0301 /* get device geometry */
66 #define HDIO_GET_IDENTITY 0x030d /* get IDE identification info */
68 #include <parted/vtoc.h>
69 #include <parted/fdasd.h>
71 #if defined(O_DIRECT) && (!defined(__s390__) || !defined(__s390x__))
72 #define RD_MODE (O_RDONLY | O_DIRECT)
73 #define WR_MODE (O_WRONLY | O_DIRECT)
74 #define RW_MODE (O_RDWR | O_DIRECT)
76 #define RD_MODE (O_RDONLY)
77 #define WR_MODE (O_WRONLY)
78 #define RW_MODE (O_RDWR)
83 unsigned char sectors;
84 unsigned short cylinders;
88 struct ata7_sectinfo {
95 /* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
97 unsigned short config; /* lots of obsolete bit flags */
98 unsigned short cyls; /* "physical" cyls */
99 unsigned short reserved2; /* reserved (word 2) */
100 unsigned short heads; /* "physical" heads */
101 unsigned short track_bytes; /* unformatted bytes per track */
102 unsigned short sector_bytes; /* unformatted bytes per sector */
103 unsigned short sectors; /* "physical" sectors per track */
104 unsigned short vendor0; /* vendor unique */
105 unsigned short vendor1; /* vendor unique */
106 unsigned short vendor2; /* vendor unique */
107 unsigned char serial_no[20]; /* 0 = not_specified */
108 unsigned short buf_type;
109 unsigned short buf_size; /* 512 byte increments;
111 unsigned short ecc_bytes; /* for r/w long cmds;
113 unsigned char fw_rev[8]; /* 0 = not_specified */
114 char model[40]; /* 0 = not_specified */
115 unsigned char max_multsect; /* 0=not_implemented */
116 unsigned char vendor3; /* vendor unique */
117 unsigned short dword_io; /* 0=not_implemented; 1=implemented */
118 unsigned char vendor4; /* vendor unique */
119 unsigned char capability; /* bits 0:DMA 1:LBA 2:IORDYsw
121 unsigned short reserved50; /* reserved (word 50) */
122 unsigned char vendor5; /* vendor unique */
123 unsigned char tPIO; /* 0=slow, 1=medium, 2=fast */
124 unsigned char vendor6; /* vendor unique */
125 unsigned char tDMA; /* 0=slow, 1=medium, 2=fast */
126 unsigned short field_valid; /* bits 0:cur_ok 1:eide_ok */
127 unsigned short cur_cyls; /* logical cylinders */
128 unsigned short cur_heads; /* logical heads */
129 unsigned short cur_sectors; /* logical sectors per track */
130 unsigned short cur_capacity0; /* logical total sectors on drive */
131 unsigned short cur_capacity1; /* (2 words, misaligned int) */
132 unsigned char multsect; /* current multiple sector count */
133 unsigned char multsect_valid; /* when (bit0==1) multsect is ok */
134 unsigned int lba_capacity; /* total number of sectors */
135 unsigned short dma_1word; /* single-word dma info */
136 unsigned short dma_mword; /* multiple-word dma info */
137 unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */
138 unsigned short eide_dma_min; /* min mword dma cycle time (ns) */
139 unsigned short eide_dma_time; /* recommended mword dma cycle
141 unsigned short eide_pio; /* min cycle time (ns), no IORDY */
142 unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */
143 unsigned short words69_70[2]; /* reserved words 69-70 */
144 /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
145 unsigned short words71_74[4]; /* reserved words 71-74 */
146 unsigned short queue_depth; /* */
147 unsigned short words76_79[4]; /* reserved words 76-79 */
148 unsigned short major_rev_num; /* */
149 unsigned short minor_rev_num; /* */
150 unsigned short command_set_1; /* bits 0:Smart 1:Security 2:Removable
152 unsigned short command_set_2; /* bits 14:Smart Enabled 13:0 zero */
153 unsigned short cfsse; /* command set-feature supported
155 unsigned short cfs_enable_1; /* command set-feature enabled */
156 unsigned short cfs_enable_2; /* command set-feature enabled */
157 unsigned short csf_default; /* command set-feature default */
158 unsigned short dma_ultra; /* */
159 unsigned short word89; /* reserved (word 89) */
160 unsigned short word90; /* reserved (word 90) */
161 unsigned short CurAPMvalues; /* current APM values */
162 unsigned short word92; /* reserved (word 92) */
163 unsigned short hw_config; /* hardware config */
164 unsigned short words94_105[12];/* reserved words 94-105 */
165 struct ata7_sectinfo ata7_sectinfo; /* ATAPI/ATA7 physical and logical
167 unsigned short words107_116[10];/* reserved words 107-116 */
168 unsigned int logical_sectsize;/* ATAPI/ATA7 logical sector size */
169 unsigned short words119_125[7];/* reserved words 119-125 */
170 unsigned short last_lun; /* reserved (word 126) */
171 unsigned short word127; /* reserved (word 127) */
172 unsigned short dlf; /* device lock function
174 * 8 security level 1:max 0:high
183 unsigned short csfo; /* current set features options
190 unsigned short words130_155[26];/* reserved vendor words 130-155 */
191 unsigned short word156;
192 unsigned short words157_159[3]; /* reserved vendor words 157-159 */
193 unsigned short words160_255[95];/* reserved words 160-255 */
196 /* from <linux/fs.h> */
197 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
198 #define BLKGETSIZE _IO(0x12,96) /* return device size */
199 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
200 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
201 #define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
202 #define BLKSETLASTSECT _IO(0x12,109) /* set last sector of block device */
204 /* return device size in bytes (u64 *arg) */
205 #define BLKGETSIZE64 _IOR(0x12,114,size_t)
207 struct blkdev_ioctl_param {
209 size_t content_length;
210 char * block_contents;
213 /* from <linux/major.h> */
215 #define IDE1_MAJOR 22
216 #define IDE2_MAJOR 33
217 #define IDE3_MAJOR 34
218 #define IDE4_MAJOR 56
219 #define IDE5_MAJOR 57
220 #define SCSI_CDROM_MAJOR 11
221 #define SCSI_DISK0_MAJOR 8
222 #define SCSI_DISK1_MAJOR 65
223 #define SCSI_DISK2_MAJOR 66
224 #define SCSI_DISK3_MAJOR 67
225 #define SCSI_DISK4_MAJOR 68
226 #define SCSI_DISK5_MAJOR 69
227 #define SCSI_DISK6_MAJOR 70
228 #define SCSI_DISK7_MAJOR 71
229 #define COMPAQ_SMART2_MAJOR 72
230 #define COMPAQ_SMART2_MAJOR1 73
231 #define COMPAQ_SMART2_MAJOR2 74
232 #define COMPAQ_SMART2_MAJOR3 75
233 #define COMPAQ_SMART2_MAJOR4 76
234 #define COMPAQ_SMART2_MAJOR5 77
235 #define COMPAQ_SMART2_MAJOR6 78
236 #define COMPAQ_SMART2_MAJOR7 79
237 #define COMPAQ_SMART_MAJOR 104
238 #define COMPAQ_SMART_MAJOR1 105
239 #define COMPAQ_SMART_MAJOR2 106
240 #define COMPAQ_SMART_MAJOR3 107
241 #define COMPAQ_SMART_MAJOR4 108
242 #define COMPAQ_SMART_MAJOR5 109
243 #define COMPAQ_SMART_MAJOR6 110
244 #define COMPAQ_SMART_MAJOR7 111
245 #define DAC960_MAJOR 48
246 #define ATARAID_MAJOR 114
247 #define I2O_MAJOR1 80
248 #define I2O_MAJOR2 81
249 #define I2O_MAJOR3 82
250 #define I2O_MAJOR4 83
251 #define I2O_MAJOR5 84
252 #define I2O_MAJOR6 85
253 #define I2O_MAJOR7 86
254 #define I2O_MAJOR8 87
256 #define DASD_MAJOR 94
257 #define VIODASD_MAJOR 112
258 #define SX8_MAJOR1 160
259 #define SX8_MAJOR2 161
261 #define SCSI_BLK_MAJOR(M) ( \
262 (M) == SCSI_DISK0_MAJOR \
263 || (M) == SCSI_CDROM_MAJOR \
264 || ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
266 static char* _device_get_part_path (PedDevice* dev, int num);
267 static int _partition_is_mounted_by_path (const char* path);
270 _is_ide_major (int major)
287 _is_cpqarray_major (int major)
289 return ((COMPAQ_SMART2_MAJOR <= major && major <= COMPAQ_SMART2_MAJOR7)
290 || (COMPAQ_SMART_MAJOR <= major && major <= COMPAQ_SMART_MAJOR7));
294 _is_i2o_major (int major)
296 return (I2O_MAJOR1 <= major && major <= I2O_MAJOR8);
300 _is_sx8_major (int major)
302 return (SX8_MAJOR1 <= major && major <= SX8_MAJOR2);
305 #ifdef ENABLE_DEVICE_MAPPER
307 readFD (int fd, char **buf)
310 size_t size = PROC_DEVICES_BUFSIZ;
313 *buf = malloc (size * sizeof (char));
319 p = &(*buf) [filesize];
320 s = read (fd, p, PROC_DEVICES_BUFSIZ);
321 /* exit if there is an error or EOF is reached */
326 *buf = realloc (*buf, size);
329 if (filesize == 0 && s < 0) {
334 /* there is always some excess memory left unused */
335 *buf = realloc (*buf, filesize+1);
336 (*buf)[filesize] = '\0';
343 _is_dm_major (int major)
353 fd = open ("/proc/devices", O_RDONLY);
357 if (readFD(fd, &buf) < 0) {
363 end = strchr(line, '\n');
372 if (!strncmp(line, "Block devices:", 14))
377 name = strrchr(line, ' ');
378 if (!name || strcmp(name+1, "device-mapper"))
381 maj = strtol(line, &name, 10);
391 end = strchr(line, '\n');
400 _device_stat (PedDevice* dev, struct stat * dev_stat)
402 PED_ASSERT (dev != NULL, return 0);
403 PED_ASSERT (!dev->external_mode, return 0);
406 if (!stat (dev->path, dev_stat)) {
409 if (ped_exception_throw (
411 PED_EXCEPTION_RETRY_CANCEL,
412 _("Could not stat device %s - %s."),
415 != PED_EXCEPTION_RETRY)
422 _device_probe_type (PedDevice* dev)
424 struct stat dev_stat;
428 if (!_device_stat (dev, &dev_stat))
431 if (!S_ISBLK(dev_stat.st_mode)) {
432 dev->type = PED_DEVICE_FILE;
436 dev_major = major (dev_stat.st_rdev);
437 dev_minor = minor (dev_stat.st_rdev);
439 if (SCSI_BLK_MAJOR (dev_major) && (dev_minor % 0x10 == 0)) {
440 dev->type = PED_DEVICE_SCSI;
441 } else if (_is_ide_major (dev_major) && (dev_minor % 0x40 == 0)) {
442 dev->type = PED_DEVICE_IDE;
443 } else if (dev_major == DAC960_MAJOR && (dev_minor % 0x8 == 0)) {
444 dev->type = PED_DEVICE_DAC960;
445 } else if (dev_major == ATARAID_MAJOR && (dev_minor % 0x10 == 0)) {
446 dev->type = PED_DEVICE_ATARAID;
447 } else if (dev_major == DASD_MAJOR && (dev_minor % 0x4 == 0)) {
448 dev->type = PED_DEVICE_DASD;
449 } else if (dev_major == VIODASD_MAJOR && (dev_minor % 0x8 == 0)) {
450 dev->type = PED_DEVICE_VIODASD;
451 } else if (_is_sx8_major(dev_major) && (dev_minor % 0x20 == 0)) {
452 dev->type = PED_DEVICE_SX8;
453 } else if (_is_i2o_major (dev_major) && (dev_minor % 0x10 == 0)) {
454 dev->type = PED_DEVICE_I2O;
455 } else if (_is_cpqarray_major (dev_major) && (dev_minor % 0x10 == 0)) {
456 dev->type = PED_DEVICE_CPQARRAY;
457 } else if (dev_major == UBD_MAJOR && (dev_minor % 0x10 == 0)) {
458 dev->type = PED_DEVICE_UBD;
459 #ifdef ENABLE_DEVICE_MAPPER
460 } else if (_is_dm_major(dev_major)) {
461 dev->type = PED_DEVICE_DM;
464 dev->type = PED_DEVICE_UNKNOWN;
471 _get_linux_version ()
473 static int kver = -1;
485 if (sscanf (uts.release, "%u.%u.%u", &major, &minor, &teeny) != 3)
488 return kver = KERNEL_VERSION (major, minor, teeny);
494 static int have_devfs = -1;
497 if (have_devfs != -1)
500 /* the presence of /dev/.devfsd implies that DevFS is active */
501 if (stat("/dev/.devfsd", &sb) < 0)
502 return have_devfs = 0;
504 return have_devfs = S_ISCHR(sb.st_mode) ? 1 : 0;
508 _device_set_sector_size (PedDevice* dev)
510 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
513 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
514 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
516 PED_ASSERT (dev->open_count, return);
518 if (_get_linux_version() < KERNEL_VERSION (2,3,0)) {
519 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
523 if (ioctl (arch_specific->fd, BLKSSZGET, §or_size)) {
524 ped_exception_throw (
525 PED_EXCEPTION_WARNING,
527 _("Could not determine sector size for %s: %s.\n"
528 "Using the default sector size (%lld)."),
529 dev->path, strerror (errno), PED_SECTOR_SIZE_DEFAULT);
531 dev->sector_size = (long long)sector_size;
534 /* Return PED_SECTOR_SIZE_DEFAULT for DASDs. */
535 if (dev->type == PED_DEVICE_DASD) {
536 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
539 if (dev->sector_size != PED_SECTOR_SIZE_DEFAULT) {
540 ped_exception_throw (
541 PED_EXCEPTION_WARNING,
543 _("Device %s has a logical sector size of %lld. Not "
544 "all parts of GNU Parted support this at the moment, "
545 "and the working code is HIGHLY EXPERIMENTAL.\n"),
546 dev->path, dev->sector_size);
551 _kernel_has_blkgetsize64(void)
553 int version = _get_linux_version();
555 if (version >= KERNEL_VERSION (2,5,4)) return 1;
556 if (version < KERNEL_VERSION (2,5,0) &&
557 version >= KERNEL_VERSION (2,4,18)) return 1;
561 /* TODO: do a binary search if BLKGETSIZE doesn't work?! */
563 _device_get_length (PedDevice* dev)
566 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
570 PED_ASSERT (dev->open_count > 0, return 0);
571 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
573 if (_kernel_has_blkgetsize64()) {
574 if (ioctl(arch_specific->fd, BLKGETSIZE64, &bytes) == 0) {
575 return bytes / dev->sector_size;
579 if (ioctl (arch_specific->fd, BLKGETSIZE, &size)) {
580 ped_exception_throw (
582 PED_EXCEPTION_CANCEL,
583 _("Unable to determine the size of %s (%s)."),
593 _device_probe_geometry (PedDevice* dev)
595 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
596 struct stat dev_stat;
597 struct hd_geometry geometry;
599 if (!_device_stat (dev, &dev_stat))
601 PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
603 _device_set_sector_size (dev);
605 dev->length = _device_get_length (dev);
609 /* The GETGEO ioctl is no longer useful (as of linux 2.6.x). We could
610 * still use it in 2.4.x, but this is contentious. Perhaps we should
612 dev->bios_geom.sectors = 63;
613 dev->bios_geom.heads = 255;
614 dev->bios_geom.cylinders
615 = dev->length / (63 * 255);
617 /* FIXME: what should we put here? (TODO: discuss on linux-kernel) */
618 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geometry)
619 && geometry.sectors && geometry.heads) {
620 dev->hw_geom.sectors = geometry.sectors;
621 dev->hw_geom.heads = geometry.heads;
622 dev->hw_geom.cylinders
623 = dev->length / (dev->hw_geom.heads
624 * dev->hw_geom.sectors);
626 dev->hw_geom = dev->bios_geom;
633 strip_name(char* str)
638 for (i = 0; str[i] != 0; i++) {
639 if (!isspace (str[i])
640 || (isspace (str[i]) && !isspace (str[i+1]) && str[i+1])) {
650 init_ide (PedDevice* dev)
652 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
653 struct stat dev_stat;
655 struct hd_driveid hdi;
656 PedExceptionOption ex_status;
658 int sector_multiplier = 0;
660 if (!_device_stat (dev, &dev_stat))
663 dev_major = major (dev_stat.st_rdev);
665 if (!ped_device_open (dev))
668 if (ioctl (arch_specific->fd, HDIO_GET_IDENTITY, &hdi)) {
669 ex_status = ped_exception_throw (
670 PED_EXCEPTION_WARNING,
671 PED_EXCEPTION_IGNORE_CANCEL,
672 _("Could not get identity of device %s - %s"),
673 dev->path, strerror (errno));
675 case PED_EXCEPTION_CANCEL:
676 goto error_close_dev;
678 case PED_EXCEPTION_UNHANDLED:
679 ped_exception_catch ();
680 case PED_EXCEPTION_IGNORE:
681 dev->model = strdup(_("Generic IDE"));
684 PED_ASSERT (0, (void) 0);
688 /* hdi.model is not guaranteed to be NULL terminated */
689 memcpy (hdi_buf, hdi.model, 40);
691 dev->model = strip_name (hdi_buf);
693 if (!hdi.ata7_sectinfo.valid1 && hdi.ata7_sectinfo.valid2)
694 sector_multiplier = hdi.ata7_sectinfo.multiplier;
696 sector_multiplier = 1;
698 if (sector_multiplier != 1) {
699 ex_status = ped_exception_throw (
700 PED_EXCEPTION_WARNING,
701 PED_EXCEPTION_IGNORE_CANCEL,
702 _("Device %s has multiple (%d) logical sectors "
703 "per physical sector.\n"
704 "GNU Parted supports this EXPERIMENTALLY for "
705 "some special disk label/file system "
706 "combinations, e.g. GPT and ext2/3.\n"
707 "Please consult the web site for up-to-date "
709 dev->path, sector_multiplier);
712 case PED_EXCEPTION_CANCEL:
713 goto error_close_dev;
715 case PED_EXCEPTION_UNHANDLED:
716 ped_exception_catch ();
717 case PED_EXCEPTION_IGNORE:
720 PED_ASSERT (0, (void) 0);
725 /* XXX sector_size has not been set yet! */
726 /* dev->phys_sector_size = dev->sector_size
727 * sector_multiplier;*/
728 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
731 if (!_device_probe_geometry (dev))
732 goto error_close_dev;
734 ped_device_close (dev);
738 ped_device_close (dev);
743 /* This function reads the /sys entry named "file" for device "dev". */
745 read_device_sysfs_file (PedDevice *dev, const char *file)
751 snprintf (name_buf, 127, "/sys/block/%s/device/%s",
752 basename (dev->path), file);
754 if ((f = fopen (name_buf, "r")) == NULL)
759 return strip_name (buf);
762 /* This function sends a query to a SCSI device for vendor and product
763 * information. It uses the deprecated SCSI_IOCTL_SEND_COMMAND to
767 scsi_query_product_info (PedDevice* dev, char **vendor, char **product)
769 /* The following are defined by the SCSI-2 specification. */
770 typedef struct _scsi_inquiry_cmd
773 uint8_t lun; /* bits 5-7 denote the LUN */
776 uint8_t alloc_length;
778 } __attribute__((packed)) scsi_inquiry_cmd_t;
780 typedef struct _scsi_inquiry_data
782 uint8_t peripheral_info;
784 uint8_t version_info;
786 uint8_t additional_length;
790 uint8_t vendor_id[8];
791 uint8_t product_id[16];
792 uint8_t product_revision[4];
793 uint8_t vendor_specific[20];
794 uint8_t _reserved3[40];
795 } __attribute__((packed)) scsi_inquiry_data_t;
804 scsi_inquiry_data_t out;
805 scsi_inquiry_cmd_t in;
809 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
815 memset (&arg, 0x00, sizeof(struct scsi_arg));
817 arg.outlen = sizeof(scsi_inquiry_data_t);
818 arg.data.in.op = INQUIRY;
819 arg.data.in.lun = dev->host << 5;
820 arg.data.in.alloc_length = sizeof(scsi_inquiry_data_t);
821 arg.data.in.page_code = 0;
822 arg.data.in.reserved = 0;
823 arg.data.in.control = 0;
825 if (ioctl (arch_specific->fd, SCSI_IOCTL_SEND_COMMAND, &arg) < 0)
828 memcpy (buf, arg.data.out.vendor_id, 8);
830 *vendor = strip_name (buf);
832 memcpy (buf, arg.data.out.product_id, 16);
834 *product = strip_name (buf);
839 /* This function provides the vendor and product name for a SCSI device.
840 * It supports both the modern /sys interface and direct queries
841 * via the deprecated ioctl, SCSI_IOCTL_SEND_COMMAND.
844 scsi_get_product_info (PedDevice* dev, char **vendor, char **product)
846 *vendor = read_device_sysfs_file (dev, "vendor");
847 *product = read_device_sysfs_file (dev, "model");
848 if (*vendor && *product)
851 return scsi_query_product_info (dev, vendor, product);
855 init_scsi (PedDevice* dev)
860 uint32_t host_unique_id;
863 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
867 if (!ped_device_open (dev))
870 if (ioctl (arch_specific->fd, SCSI_IOCTL_GET_IDLUN, &idlun) < 0) {
873 if (ped_exception_throw (
874 PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
875 _("Error initialising SCSI device %s - %s"),
876 dev->path, strerror (errno))
877 != PED_EXCEPTION_IGNORE)
878 goto error_close_dev;
879 if (!_device_probe_geometry (dev))
880 goto error_close_dev;
881 ped_device_close (dev);
885 dev->host = idlun.host_unique_id;
886 dev->did = idlun.dev_id;
888 dev->model = (char*) ped_malloc (8 + 16 + 2);
890 goto error_close_dev;
892 if (scsi_get_product_info (dev, &vendor, &product)) {
893 sprintf (dev->model, "%.8s %.16s", vendor, product);
897 strcpy (dev->model, "Generic SCSI");
900 if (!_device_probe_geometry (dev))
901 goto error_close_dev;
903 ped_device_close (dev);
907 ped_device_close (dev);
913 init_file (PedDevice* dev)
915 struct stat dev_stat;
917 if (!_device_stat (dev, &dev_stat))
919 if (!ped_device_open (dev))
922 if (S_ISBLK(dev_stat.st_mode))
923 dev->length = _device_get_length (dev);
925 dev->length = dev_stat.st_size / 512;
926 if (dev->length <= 0) {
927 ped_exception_throw (
929 PED_EXCEPTION_CANCEL,
930 _("The device %s has zero length, and can't possibly "
931 "store a file system or partition table. Perhaps "
932 "you selected the wrong device?"),
934 goto error_close_dev;
937 ped_device_close (dev);
939 dev->bios_geom.cylinders = dev->length / 4 / 32;
940 dev->bios_geom.heads = 4;
941 dev->bios_geom.sectors = 32;
942 dev->hw_geom = dev->bios_geom;
943 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
944 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
945 dev->model = strdup ("");
950 ped_device_close (dev);
956 init_dasd (PedDevice* dev, char* model_name)
958 struct stat dev_stat;
959 struct hd_geometry geo;
962 if (!_device_stat (dev, &dev_stat))
965 if (!ped_device_open (dev))
968 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
970 PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
972 _device_set_sector_size (dev);
973 if (!dev->sector_size)
974 goto error_close_dev;
976 dev->length = _device_get_length (dev);
978 goto error_close_dev;
980 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geo)) {
981 dev->hw_geom.sectors = geo.sectors;
982 dev->hw_geom.heads = geo.heads;
983 dev->hw_geom.cylinders = dev->length
984 / (dev->hw_geom.heads * dev->hw_geom.sectors)
985 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
986 dev->bios_geom = dev->hw_geom;
988 dev->bios_geom.sectors = 12;
989 dev->bios_geom.heads = 15;
990 dev->bios_geom.cylinders = dev->length
991 / (dev->hw_geom.heads * dev->hw_geom.sectors)
992 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
993 dev->hw_geom = dev->bios_geom;
996 dev->model = strdup (model_name);
998 ped_device_close (dev);
1001 ped_exception_throw ( PED_EXCEPTION_ERROR,
1002 PED_EXCEPTION_IGNORE_CANCEL,
1006 ped_device_close (dev);
1012 init_generic (PedDevice* dev, char* model_name)
1014 struct stat dev_stat;
1015 PedExceptionOption ex_status;
1017 if (!_device_stat (dev, &dev_stat))
1020 if (!ped_device_open (dev))
1023 ped_exception_fetch_all ();
1024 if (_device_probe_geometry (dev)) {
1025 ped_exception_leave_all ();
1027 /* hack to allow use of files, for testing */
1028 ped_exception_catch ();
1029 ped_exception_leave_all ();
1031 ex_status = ped_exception_throw (
1032 PED_EXCEPTION_WARNING,
1033 PED_EXCEPTION_IGNORE_CANCEL,
1034 _("Unable to determine geometry of "
1035 "file/device %s. You should not use Parted "
1036 "unless you REALLY know what you're doing!"),
1038 switch (ex_status) {
1039 case PED_EXCEPTION_CANCEL:
1040 goto error_close_dev;
1042 case PED_EXCEPTION_UNHANDLED:
1043 ped_exception_catch ();
1044 case PED_EXCEPTION_IGNORE:
1047 PED_ASSERT (0, (void) 0);
1051 /* what should we stick in here? */
1052 dev->length = dev_stat.st_size / PED_SECTOR_SIZE_DEFAULT;
1053 dev->bios_geom.cylinders = dev->length / 4 / 32;
1054 dev->bios_geom.heads = 4;
1055 dev->bios_geom.sectors = 32;
1056 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1057 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
1060 dev->model = strdup (model_name);
1062 ped_device_close (dev);
1066 ped_device_close (dev);
1072 linux_new (const char* path)
1076 PED_ASSERT (path != NULL, return NULL);
1078 dev = (PedDevice*) ped_malloc (sizeof (PedDevice));
1082 dev->path = strdup (path);
1084 goto error_free_dev;
1087 = (LinuxSpecific*) ped_malloc (sizeof (LinuxSpecific));
1088 if (!dev->arch_specific)
1089 goto error_free_path;
1091 dev->open_count = 0;
1093 dev->external_mode = 0;
1095 dev->boot_dirty = 0;
1097 if (!_device_probe_type (dev))
1098 goto error_free_arch_specific;
1100 switch (dev->type) {
1101 case PED_DEVICE_IDE:
1102 if (!init_ide (dev))
1103 goto error_free_arch_specific;
1106 case PED_DEVICE_SCSI:
1107 if (!init_scsi (dev))
1108 goto error_free_arch_specific;
1111 case PED_DEVICE_DAC960:
1112 if (!init_generic (dev, _("DAC960 RAID controller")))
1113 goto error_free_arch_specific;
1116 case PED_DEVICE_SX8:
1117 if (!init_generic (dev, _("Promise SX8 SATA Device")))
1118 goto error_free_arch_specific;
1121 case PED_DEVICE_DASD:
1122 if (!init_dasd (dev, _("IBM S390 DASD drive")))
1123 goto error_free_arch_specific;
1126 case PED_DEVICE_VIODASD:
1127 if (!init_generic (dev, _("IBM iSeries Virtual DASD")))
1128 goto error_free_arch_specific;
1131 case PED_DEVICE_CPQARRAY:
1132 if (!init_generic (dev, _("Compaq Smart Array")))
1133 goto error_free_arch_specific;
1136 case PED_DEVICE_ATARAID:
1137 if (!init_generic (dev, _("ATARAID Controller")))
1138 goto error_free_arch_specific;
1141 case PED_DEVICE_I2O:
1142 if (!init_generic (dev, _("I2O Controller")))
1143 goto error_free_arch_specific;
1146 case PED_DEVICE_UBD:
1147 if (!init_generic (dev, _("User-Mode Linux UBD")))
1148 goto error_free_arch_specific;
1151 case PED_DEVICE_FILE:
1152 if (!init_file (dev))
1153 goto error_free_arch_specific;
1156 #ifdef ENABLE_DEVICE_MAPPER
1158 if (!init_generic (dev, _("Linux device-mapper")))
1159 goto error_free_arch_specific;
1163 case PED_DEVICE_UNKNOWN:
1164 if (!init_generic (dev, _("Unknown")))
1165 goto error_free_arch_specific;
1169 ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
1170 PED_EXCEPTION_CANCEL,
1171 _("ped_device_new() Unsupported device type"));
1172 goto error_free_arch_specific;
1176 error_free_arch_specific:
1177 ped_free (dev->arch_specific);
1179 ped_free (dev->path);
1187 linux_destroy (PedDevice* dev)
1189 ped_free (dev->arch_specific);
1190 ped_free (dev->path);
1191 ped_free (dev->model);
1196 linux_is_busy (PedDevice* dev)
1201 if (_partition_is_mounted_by_path (dev->path))
1204 for (i = 0; i < 32; i++) {
1207 part_name = _device_get_part_path (dev, i);
1210 status = _partition_is_mounted_by_path (part_name);
1211 ped_free (part_name);
1220 /* we need to flush the master device, and all the partition devices,
1221 * because there is no coherency between the caches.
1222 * We should only flush unmounted partition devices, because:
1223 * - there is never a need to flush them (we're not doing IO there)
1224 * - flushing a device that is mounted causes unnecessary IO, and can
1225 * even screw journaling & friends up. Even cause oopsen!
1228 _flush_cache (PedDevice* dev)
1230 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1237 ioctl (arch_specific->fd, BLKFLSBUF);
1239 for (i = 1; i < 16; i++) {
1243 name = _device_get_part_path (dev, i);
1246 if (!_partition_is_mounted_by_path (name)) {
1247 fd = open (name, WR_MODE, 0);
1249 ioctl (fd, BLKFLSBUF);
1258 linux_open (PedDevice* dev)
1260 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1263 arch_specific->fd = open (dev->path, RW_MODE);
1265 if (arch_specific->fd == -1) {
1266 char* rw_error_msg = strerror (errno);
1268 arch_specific->fd = open (dev->path, RD_MODE);
1270 if (arch_specific->fd == -1) {
1271 if (ped_exception_throw (
1272 PED_EXCEPTION_ERROR,
1273 PED_EXCEPTION_RETRY_CANCEL,
1274 _("Error opening %s: %s"),
1275 dev->path, strerror (errno))
1276 != PED_EXCEPTION_RETRY) {
1282 ped_exception_throw (
1283 PED_EXCEPTION_WARNING,
1285 _("Unable to open %s read-write (%s). %s has "
1286 "been opened read-only."),
1287 dev->path, rw_error_msg, dev->path);
1300 linux_refresh_open (PedDevice* dev)
1306 linux_close (PedDevice* dev)
1308 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1312 close (arch_specific->fd);
1317 linux_refresh_close (PedDevice* dev)
1324 #if SIZEOF_OFF_T < 8
1326 static _syscall5(int,_llseek,
1328 unsigned long, offset_high,
1329 unsigned long, offset_low,
1331 unsigned int, origin)
1334 llseek (unsigned int fd, loff_t offset, unsigned int whence)
1339 retval = _llseek(fd,
1340 ((unsigned long long)offset) >> 32,
1341 ((unsigned long long)offset) & 0xffffffff,
1344 return (retval==-1 ? (loff_t) retval : result);
1347 #endif /* SIZEOF_OFF_T < 8 */
1350 _device_seek (const PedDevice* dev, PedSector sector)
1352 LinuxSpecific* arch_specific;
1354 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1355 PED_ASSERT (dev != NULL, return 0);
1356 PED_ASSERT (!dev->external_mode, return 0);
1358 arch_specific = LINUX_SPECIFIC (dev);
1360 #if SIZEOF_OFF_T < 8
1361 if (sizeof (off_t) < 8) {
1362 loff_t pos = (loff_t)(sector * dev->sector_size);
1363 return llseek (arch_specific->fd, pos, SEEK_SET) == pos;
1367 off_t pos = sector * dev->sector_size;
1368 return lseek (arch_specific->fd, pos, SEEK_SET) == pos;
1373 _read_lastoddsector (const PedDevice* dev, void* buffer)
1375 LinuxSpecific* arch_specific;
1376 struct blkdev_ioctl_param ioctl_param;
1378 PED_ASSERT(dev != NULL, return 0);
1379 PED_ASSERT(buffer != NULL, return 0);
1381 arch_specific = LINUX_SPECIFIC (dev);
1384 ioctl_param.block = 0; /* read the last sector */
1385 ioctl_param.content_length = dev->sector_size;
1386 ioctl_param.block_contents = buffer;
1388 if (ioctl(arch_specific->fd, BLKGETLASTSECT, &ioctl_param) == -1) {
1389 PedExceptionOption opt;
1390 opt = ped_exception_throw (
1391 PED_EXCEPTION_ERROR,
1392 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1393 _("%s during read on %s"),
1394 strerror (errno), dev->path);
1396 if (opt == PED_EXCEPTION_CANCEL)
1398 if (opt == PED_EXCEPTION_RETRY)
1406 linux_read (const PedDevice* dev, void* buffer, PedSector start,
1409 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1411 PedExceptionOption ex_status;
1414 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1416 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1417 /* Kludge. This is necessary to read/write the last
1418 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1420 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1421 && start + count - 1 == dev->length - 1)
1422 return ped_device_read (dev, buffer, start, count - 1)
1423 && _read_lastoddsector (
1424 dev, (char *) buffer + (count-1) * 512);
1427 if (_device_seek (dev, start))
1430 ex_status = ped_exception_throw (
1431 PED_EXCEPTION_ERROR,
1432 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1433 _("%s during seek for read on %s"),
1434 strerror (errno), dev->path);
1436 switch (ex_status) {
1437 case PED_EXCEPTION_IGNORE:
1440 case PED_EXCEPTION_RETRY:
1443 case PED_EXCEPTION_UNHANDLED:
1444 ped_exception_catch ();
1445 case PED_EXCEPTION_CANCEL:
1448 PED_ASSERT (0, (void) 0);
1453 size_t read_length = count * dev->sector_size;
1454 if (posix_memalign (&diobuf, dev->sector_size, read_length) != 0)
1458 status = read (arch_specific->fd, diobuf, read_length);
1460 memcpy(buffer, diobuf, status);
1461 if (status == count * dev->sector_size) break;
1463 read_length -= status;
1464 buffer = (char *) buffer + status;
1468 ex_status = ped_exception_throw (
1469 PED_EXCEPTION_ERROR,
1470 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1471 _("%s during read on %s"),
1475 switch (ex_status) {
1476 case PED_EXCEPTION_IGNORE:
1480 case PED_EXCEPTION_RETRY:
1483 case PED_EXCEPTION_UNHANDLED:
1484 ped_exception_catch ();
1485 case PED_EXCEPTION_CANCEL:
1489 PED_ASSERT (0, (void) 0);
1499 _write_lastoddsector (PedDevice* dev, const void* buffer)
1501 LinuxSpecific* arch_specific;
1502 struct blkdev_ioctl_param ioctl_param;
1504 PED_ASSERT(dev != NULL, return 0);
1505 PED_ASSERT(buffer != NULL, return 0);
1507 arch_specific = LINUX_SPECIFIC (dev);
1510 ioctl_param.block = 0; /* write the last sector */
1511 ioctl_param.content_length = dev->sector_size;
1512 ioctl_param.block_contents = (void*) buffer;
1514 if (ioctl(arch_specific->fd, BLKSETLASTSECT, &ioctl_param) == -1) {
1515 PedExceptionOption opt;
1516 opt = ped_exception_throw (
1517 PED_EXCEPTION_ERROR,
1518 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1519 _("%s during write on %s"),
1520 strerror (errno), dev->path);
1522 if (opt == PED_EXCEPTION_CANCEL)
1524 if (opt == PED_EXCEPTION_RETRY)
1532 linux_write (PedDevice* dev, const void* buffer, PedSector start,
1535 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1537 PedExceptionOption ex_status;
1538 size_t write_length = count * dev->sector_size;
1542 PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1544 if (dev->read_only) {
1545 if (ped_exception_throw (
1546 PED_EXCEPTION_ERROR,
1547 PED_EXCEPTION_IGNORE_CANCEL,
1548 _("Can't write to %s, because it is opened read-only."),
1550 != PED_EXCEPTION_IGNORE)
1556 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1557 /* Kludge. This is necessary to read/write the last
1558 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1560 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1561 && start + count - 1 == dev->length - 1)
1562 return ped_device_write (dev, buffer, start, count - 1)
1563 && _write_lastoddsector (
1564 dev, (char*) buffer + (count-1) * 512);
1567 if (_device_seek (dev, start))
1570 ex_status = ped_exception_throw (
1571 PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1572 _("%s during seek for write on %s"),
1573 strerror (errno), dev->path);
1575 switch (ex_status) {
1576 case PED_EXCEPTION_IGNORE:
1579 case PED_EXCEPTION_RETRY:
1582 case PED_EXCEPTION_UNHANDLED:
1583 ped_exception_catch ();
1584 case PED_EXCEPTION_CANCEL:
1587 PED_ASSERT (0, (void) 0);
1593 printf ("ped_device_write (\"%s\", %p, %d, %d)\n",
1594 dev->path, buffer, (int) start, (int) count);
1597 if (posix_memalign(&diobuf, PED_SECTOR_SIZE_DEFAULT,
1598 count * PED_SECTOR_SIZE_DEFAULT) != 0)
1600 memcpy(diobuf, buffer, count * PED_SECTOR_SIZE_DEFAULT);
1601 diobuf_start = diobuf;
1603 status = write (arch_specific->fd, diobuf, write_length);
1604 if (status == count * dev->sector_size) break;
1606 write_length -= status;
1607 diobuf = (char *) diobuf + status;
1611 ex_status = ped_exception_throw (
1612 PED_EXCEPTION_ERROR,
1613 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1614 _("%s during write on %s"),
1615 strerror (errno), dev->path);
1617 switch (ex_status) {
1618 case PED_EXCEPTION_IGNORE:
1622 case PED_EXCEPTION_RETRY:
1625 case PED_EXCEPTION_UNHANDLED:
1626 ped_exception_catch ();
1627 case PED_EXCEPTION_CANCEL:
1631 PED_ASSERT (0, (void) 0);
1636 #endif /* !READ_ONLY */
1640 /* returns the number of sectors that are ok.
1643 linux_check (PedDevice* dev, void* buffer, PedSector start, PedSector count)
1645 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1650 PED_ASSERT(dev != NULL, return 0);
1652 if (!_device_seek (dev, start))
1655 if (posix_memalign(&diobuf, PED_SECTOR_SIZE_DEFAULT,
1656 count * PED_SECTOR_SIZE_DEFAULT) != 0)
1659 for (done = 0; done < count; done += status / dev->sector_size) {
1660 status = read (arch_specific->fd, diobuf,
1661 (size_t) ((count-done) * dev->sector_size));
1663 memcpy(buffer, diobuf, status);
1673 _do_fsync (PedDevice* dev)
1675 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1677 PedExceptionOption ex_status;
1680 status = fsync (arch_specific->fd);
1681 if (status >= 0) break;
1683 ex_status = ped_exception_throw (
1684 PED_EXCEPTION_ERROR,
1685 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1686 _("%s during write on %s"),
1687 strerror (errno), dev->path);
1689 switch (ex_status) {
1690 case PED_EXCEPTION_IGNORE:
1693 case PED_EXCEPTION_RETRY:
1696 case PED_EXCEPTION_UNHANDLED:
1697 ped_exception_catch ();
1698 case PED_EXCEPTION_CANCEL:
1701 PED_ASSERT (0, (void) 0);
1709 linux_sync (PedDevice* dev)
1711 PED_ASSERT (dev != NULL, return 0);
1712 PED_ASSERT (!dev->external_mode, return 0);
1716 if (!_do_fsync (dev))
1723 linux_sync_fast (PedDevice* dev)
1725 PED_ASSERT (dev != NULL, return 0);
1726 PED_ASSERT (!dev->external_mode, return 0);
1730 if (!_do_fsync (dev))
1732 /* no cache flush... */
1737 _compare_digit_state (char ch, int need_digit)
1739 return !!isdigit (ch) == need_digit;
1742 /* matches the regexp "[^0-9]+[0-9]+[^0-9]+[0-9]+$".
1743 * Motivation: accept devices looking like /dev/rd/c0d0, but
1744 * not looking like /dev/hda1 and /dev/rd/c0d0p1
1747 _match_rd_device (const char* name)
1752 /* exclude directory names from test */
1753 pos = strrchr(name, '/') ?: name;
1761 for (state = 0; state < 4; state++) {
1762 int want_digits = (state % 2 == 1);
1766 if (!_compare_digit_state (*pos, want_digits))
1769 } while (_compare_digit_state (*pos, want_digits));
1776 _probe_proc_partitions ()
1778 FILE* proc_part_file;
1779 int major, minor, size;
1781 char part_name [256];
1782 char dev_name [256];
1784 proc_part_file = fopen ("/proc/partitions", "r");
1785 if (!proc_part_file)
1788 fgets (buf, 256, proc_part_file);
1789 fgets (buf, 256, proc_part_file);
1791 while (fgets (buf, 512, proc_part_file)
1792 && sscanf (buf, "%d %d %d %255s", &major, &minor, &size,
1794 /* Heuristic for telling partitions and devices apart
1795 * Probably needs to be improved
1797 if (!_match_rd_device (part_name)
1798 && isdigit (part_name [strlen (part_name) - 1]))
1801 strcpy (dev_name, "/dev/");
1802 strcat (dev_name, part_name);
1803 _ped_device_probe (dev_name);
1806 fclose (proc_part_file);
1816 _skip_entry (const char *name)
1819 static struct _entry entries[] = {
1820 { ".", sizeof (".") - 1 },
1821 { "..", sizeof ("..") - 1 },
1822 { "dm-", sizeof ("dm-") - 1 },
1823 { "loop", sizeof ("loop") - 1 },
1824 { "ram", sizeof ("ram") - 1 },
1828 for (i = entries; i->name != 0; i++) {
1829 if (strncmp (name, i->name, i->len) == 0)
1840 struct dirent *dirent;
1841 char dev_name [256];
1844 if (!(blockdir = opendir ("/sys/block")))
1846 while ((dirent = readdir (blockdir))) {
1847 if (_skip_entry (dirent->d_name))
1850 if (strlen (dirent->d_name) > sizeof (dev_name) - 6)
1851 continue; /* device name too long! */
1853 strcpy (dev_name, "/dev/");
1854 strcat (dev_name, dirent->d_name);
1855 /* in /sys/block, '/'s are replaced with '!' or '.' */
1856 for (ptr = dev_name; *ptr != '\0'; ptr++) {
1857 if (*ptr == '!' || *ptr == '.')
1860 _ped_device_probe (dev_name);
1863 closedir (blockdir);
1868 _probe_standard_devices ()
1870 _ped_device_probe ("/dev/hda");
1871 _ped_device_probe ("/dev/hdb");
1872 _ped_device_probe ("/dev/hdc");
1873 _ped_device_probe ("/dev/hdd");
1874 _ped_device_probe ("/dev/hde");
1875 _ped_device_probe ("/dev/hdf");
1876 _ped_device_probe ("/dev/hdg");
1877 _ped_device_probe ("/dev/hdh");
1879 _ped_device_probe ("/dev/sda");
1880 _ped_device_probe ("/dev/sdb");
1881 _ped_device_probe ("/dev/sdc");
1882 _ped_device_probe ("/dev/sdd");
1883 _ped_device_probe ("/dev/sde");
1884 _ped_device_probe ("/dev/sdf");
1892 /* we should probe the standard devs too, even with /proc/partitions,
1893 * because /proc/partitions might return devfs stuff, and we might not
1894 * have devfs available
1896 _probe_standard_devices ();
1898 /* /sys/block is more reliable and consistent; fall back to using
1899 * /proc/partitions if the former is unavailable, however.
1901 if (!_probe_sys_block ())
1902 _probe_proc_partitions ();
1906 _device_get_part_path (PedDevice* dev, int num)
1908 int path_len = strlen (dev->path);
1909 int result_len = path_len + 16;
1912 result = (char*) ped_malloc (result_len);
1916 /* Check for devfs-style /disc => /partN transformation
1917 unconditionally; the system might be using udev with devfs rules,
1918 and if not the test is harmless. */
1919 if (!strcmp (dev->path + path_len - 5, "/disc")) {
1920 /* replace /disc with /path%d */
1921 strcpy (result, dev->path);
1922 snprintf (result + path_len - 5, 16, "/part%d", num);
1923 } else if (dev->type == PED_DEVICE_DAC960
1924 || dev->type == PED_DEVICE_CPQARRAY
1925 || dev->type == PED_DEVICE_ATARAID
1926 #ifdef ENABLE_DEVICE_MAPPER
1927 || dev->type == PED_DEVICE_DM
1929 || isdigit (dev->path[path_len - 1]))
1930 snprintf (result, result_len, "%sp%d", dev->path, num);
1932 snprintf (result, result_len, "%s%d", dev->path, num);
1938 linux_partition_get_path (const PedPartition* part)
1940 return _device_get_part_path (part->disk->dev, part->num);
1944 _partition_get_part_dev (const PedPartition* part)
1946 struct stat dev_stat;
1947 int dev_major, dev_minor;
1949 if (!_device_stat (part->disk->dev, &dev_stat))
1951 dev_major = major (dev_stat.st_rdev);
1952 dev_minor = minor (dev_stat.st_rdev);
1953 return (dev_t)makedev (dev_major, dev_minor + part->num);
1957 _mount_table_search (const char* file_name, dev_t dev)
1959 struct stat part_stat;
1961 char part_name[512];
1965 file = fopen (file_name, "r");
1968 while (fgets (line, 512, file)) {
1969 junk = sscanf (line, "%s", part_name);
1970 if (stat (part_name, &part_stat) == 0) {
1971 if (part_stat.st_rdev == dev) {
1982 _partition_is_mounted_by_dev (dev_t dev)
1984 return _mount_table_search( "/proc/mounts", dev)
1985 || _mount_table_search( "/proc/swaps", dev)
1986 || _mount_table_search( "/etc/mtab", dev);
1990 _partition_is_mounted_by_path (const char *path)
1992 struct stat part_stat;
1993 if (stat (path, &part_stat) != 0)
1995 if (!S_ISBLK(part_stat.st_mode))
1997 return _partition_is_mounted_by_dev (part_stat.st_rdev);
2001 _partition_is_mounted (const PedPartition *part)
2004 if (!ped_partition_is_active (part))
2006 dev = _partition_get_part_dev (part);
2007 return _partition_is_mounted_by_dev (dev);
2011 linux_partition_is_busy (const PedPartition* part)
2015 PED_ASSERT (part != NULL, return 0);
2017 if (_partition_is_mounted (part))
2019 if (part->type == PED_PARTITION_EXTENDED) {
2020 for (walk = part->part_list; walk; walk = walk->next) {
2021 if (linux_partition_is_busy (walk))
2029 _blkpg_part_command (PedDevice* dev, struct blkpg_partition* part, int op)
2031 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2032 struct blkpg_ioctl_arg ioctl_arg;
2035 ioctl_arg.flags = 0;
2036 ioctl_arg.datalen = sizeof (struct blkpg_partition);
2037 ioctl_arg.data = (void*) part;
2039 return ioctl (arch_specific->fd, BLKPG, &ioctl_arg) == 0;
2043 _blkpg_add_partition (PedDisk* disk, PedPartition* part)
2045 struct blkpg_partition linux_part;
2046 const char* vol_name;
2049 PED_ASSERT(disk != NULL, return 0);
2050 PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0,
2053 if (ped_disk_type_check_feature (disk->type,
2054 PED_DISK_TYPE_PARTITION_NAME))
2055 vol_name = ped_partition_get_name (part);
2059 dev_name = _device_get_part_path (disk->dev, part->num);
2063 memset (&linux_part, 0, sizeof (linux_part));
2064 linux_part.start = part->geom.start * disk->dev->sector_size;
2065 /* see fs/partitions/msdos.c:msdos_partition(): "leave room for LILO" */
2066 if (part->type & PED_PARTITION_EXTENDED)
2067 linux_part.length = part->geom.length == 1 ? 512 : 1024;
2069 linux_part.length = part->geom.length * disk->dev->sector_size;
2070 linux_part.pno = part->num;
2071 strncpy (linux_part.devname, dev_name, BLKPG_DEVNAMELTH);
2073 strncpy (linux_part.volname, vol_name, BLKPG_VOLNAMELTH);
2075 ped_free (dev_name);
2077 if (!_blkpg_part_command (disk->dev, &linux_part,
2078 BLKPG_ADD_PARTITION)) {
2079 return ped_exception_throw (
2080 PED_EXCEPTION_ERROR,
2081 PED_EXCEPTION_IGNORE_CANCEL,
2082 _("Error informing the kernel about modifications to "
2083 "partition %s -- %s. This means Linux won't know "
2084 "about any changes you made to %s until you reboot "
2085 "-- so you shouldn't mount it or use it in any way "
2086 "before rebooting."),
2090 == PED_EXCEPTION_IGNORE;
2097 _blkpg_remove_partition (PedDisk* disk, int n)
2099 struct blkpg_partition linux_part;
2101 memset (&linux_part, 0, sizeof (linux_part));
2103 return _blkpg_part_command (disk->dev, &linux_part,
2104 BLKPG_DEL_PARTITION);
2108 _disk_sync_part_table (PedDisk* disk)
2111 int last = PED_MAX (ped_disk_get_last_partition_num (disk), 16);
2112 int* rets = ped_malloc(sizeof(int) * last);
2113 int* errnums = ped_malloc(sizeof(int) * last);
2116 for (i = 1; i <= last; i++) {
2117 rets[i - 1] = _blkpg_remove_partition (disk, i);
2118 errnums[i - 1] = errno;
2121 for (i = 1; i <= last; i++) {
2124 part = ped_disk_get_partition (disk, i);
2126 /* busy... so we won't (can't!) disturb ;) Prolly
2127 * doesn't matter anyway, because users shouldn't be
2128 * changing mounted partitions anyway...
2130 if (!rets[i - 1] && errnums[i - 1] == EBUSY)
2133 /* add the (possibly modified or new) partition */
2134 if (!_blkpg_add_partition (disk, part))
2142 #ifdef ENABLE_DEVICE_MAPPER
2144 _dm_remove_map(int major, int minor)
2146 struct dm_task *task = NULL;
2149 task = dm_task_create(DM_DEVICE_REMOVE);
2153 dm_task_set_major (task, major);
2154 dm_task_set_minor (task, minor);
2156 rc = dm_task_run(task);
2157 dm_task_update_nodes();
2158 dm_task_destroy(task);
2166 _dm_remove_map_name(char *name)
2168 struct dm_task *task = NULL;
2171 task = dm_task_create(DM_DEVICE_REMOVE);
2175 dm_task_set_name (task, name);
2177 rc = dm_task_run(task);
2178 dm_task_update_nodes();
2179 dm_task_destroy(task);
2187 _dm_is_part (struct dm_info *this, char *name)
2189 struct dm_task* task = NULL;
2190 struct dm_info* info = alloca(sizeof *info);
2191 struct dm_deps* deps = NULL;
2195 task = dm_task_create(DM_DEVICE_DEPS);
2199 dm_task_set_name(task, name);
2200 rc = dm_task_run(task);
2207 memset(info, '\0', sizeof *info);
2208 dm_task_get_info(task, info);
2212 deps = dm_task_get_deps(task);
2217 for (i = 0; i < deps->count; i++) {
2218 unsigned int ma = major(deps->device[i]),
2219 mi = minor(deps->device[i]);
2221 if (ma == this->major && mi == this->minor)
2226 dm_task_destroy(task);
2231 _dm_remove_parts (PedDevice* dev)
2233 struct stat dev_stat;
2234 struct dm_task* task = NULL;
2235 struct dm_info* info = alloca(sizeof *info);
2236 struct dm_names* names = NULL;
2237 unsigned int next = 0;
2241 if (!_device_stat (dev, &dev_stat))
2244 task = dm_task_create(DM_DEVICE_LIST);
2248 dm_task_set_major (task, major (dev_stat.st_rdev));
2249 dm_task_set_minor (task, minor (dev_stat.st_rdev));
2251 rc = dm_task_run(task);
2255 memset(info, '\0', sizeof *info);
2256 dm_task_get_info(task, info);
2260 names = dm_task_get_names(task);
2266 names = (void *)names + next;
2268 if (_dm_is_part(info, names->name))
2269 rc += _dm_remove_map_name(names->name);
2274 dm_task_update_nodes();
2275 dm_task_destroy(task);
2282 dm_task_destroy(task);
2283 ped_exception_throw (PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE,
2284 _("parted was unable to re-read the partition "
2285 "table on %s (%s). This means Linux won't know "
2286 "anything about the modifications you made. "),
2287 dev->path, strerror (errno));
2292 _dm_add_partition (PedDisk* disk, PedPartition* part)
2294 struct stat dev_stat;
2295 struct dm_task* task = NULL;
2297 char* vol_name = NULL;
2298 char* dev_name = NULL;
2299 char* params = NULL;
2301 dev_name = _device_get_part_path (disk->dev, part->num);
2305 vol_name = strrchr (dev_name, '/');
2306 if (vol_name && *vol_name && *(++vol_name))
2307 vol_name = strdup (vol_name);
2309 vol_name = strdup (dev_name);
2313 if (!_device_stat (disk->dev, &dev_stat))
2316 asprintf (¶ms, "%d:%d %lu", major (dev_stat.st_rdev),
2317 minor (dev_stat.st_rdev),
2322 task = dm_task_create (DM_DEVICE_CREATE);
2326 dm_task_set_name (task, vol_name);
2327 dm_task_add_target (task, 0, part->geom.length,
2329 rc = dm_task_run(task);
2331 //printf("0 %ld linear %s\n", part->geom.length, params);
2332 dm_task_update_nodes();
2333 dm_task_destroy(task);
2338 _dm_remove_map_name(vol_name);
2341 dm_task_update_nodes();
2343 dm_task_destroy (task);
2351 _dm_reread_part_table (PedDisk* disk)
2354 int last = PED_MAX (ped_disk_get_last_partition_num (disk), 16);
2358 if (!_dm_remove_parts(disk->dev))
2361 for (i = 1; i <= last; i++) {
2364 part = ped_disk_get_partition (disk, i);
2368 if (!_dm_add_partition (disk, part))
2376 _kernel_reread_part_table (PedDevice* dev)
2378 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2379 int retry_count = 5;
2382 while (ioctl (arch_specific->fd, BLKRRPART)) {
2386 ped_exception_throw (
2387 PED_EXCEPTION_WARNING,
2388 PED_EXCEPTION_IGNORE,
2389 _("The kernel was unable to re-read the partition "
2390 "table on %s (%s). This means Linux won't know "
2391 "anything about the modifications you made "
2392 "until you reboot. You should reboot your computer "
2393 "before doing anything with %s."),
2394 dev->path, strerror (errno), dev->path);
2405 static int have_blkpg = -1;
2408 if (have_blkpg != -1)
2411 kver = _get_linux_version();
2412 return have_blkpg = kver >= KERNEL_VERSION (2,4,0) ? 1 : 0;
2416 linux_disk_commit (PedDisk* disk)
2418 #ifdef ENABLE_DEVICE_MAPPER
2419 if (disk->dev->type == PED_DEVICE_DM)
2420 return _dm_reread_part_table (disk);
2422 if (disk->dev->type != PED_DEVICE_FILE) {
2423 /* The ioctl() command BLKPG_ADD_PARTITION does not notify
2424 * the devfs system; consequently, /proc/partitions will not
2425 * be up to date, and the proper links in /dev are not
2426 * created. Therefore, if using DevFS, we must get the kernel
2427 * to re-read and grok the partition table.
2429 /* Work around kernel dasd problem so we really do BLKRRPART */
2430 if (disk->dev->type != PED_DEVICE_DASD &&
2431 _have_blkpg () && !_have_devfs ()) {
2432 if (_disk_sync_part_table (disk))
2436 return _kernel_reread_part_table (disk->dev);
2442 static PedDeviceArchOps linux_dev_ops = {
2444 destroy: linux_destroy,
2445 is_busy: linux_is_busy,
2447 refresh_open: linux_refresh_open,
2449 refresh_close: linux_refresh_close,
2454 sync_fast: linux_sync_fast,
2455 probe_all: linux_probe_all
2458 PedDiskArchOps linux_disk_ops = {
2459 partition_get_path: linux_partition_get_path,
2460 partition_is_busy: linux_partition_is_busy,
2461 disk_commit: linux_disk_commit
2464 PedArchitecture ped_linux_arch = {
2465 dev_ops: &linux_dev_ops,
2466 disk_ops: &linux_disk_ops