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 3 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, see <http://www.gnu.org/licenses/>.
19 #define PROC_DEVICES_BUFSIZ 16384
23 #include <parted/parted.h>
24 #include <parted/debug.h>
25 #include <parted/linux.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>
48 # define _(String) dgettext (PACKAGE, String)
50 # define _(String) (String)
51 #endif /* ENABLE_NLS */
53 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
56 #define __NR__llseek 140
59 #ifndef SCSI_IOCTL_SEND_COMMAND
60 #define SCSI_IOCTL_SEND_COMMAND 1
63 /* from <linux/hdreg.h> */
64 #define HDIO_GETGEO 0x0301 /* get device geometry */
65 #define HDIO_GET_IDENTITY 0x030d /* get IDE identification info */
67 #if defined(O_DIRECT) && (!defined(__s390__) || !defined(__s390x__))
68 #define RD_MODE (O_RDONLY | O_DIRECT)
69 #define WR_MODE (O_WRONLY | O_DIRECT)
70 #define RW_MODE (O_RDWR | O_DIRECT)
72 #define RD_MODE (O_RDONLY)
73 #define WR_MODE (O_WRONLY)
74 #define RW_MODE (O_RDWR)
79 unsigned char sectors;
80 unsigned short cylinders;
84 struct ata7_sectinfo {
91 /* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
93 unsigned short config; /* lots of obsolete bit flags */
94 unsigned short cyls; /* "physical" cyls */
95 unsigned short reserved2; /* reserved (word 2) */
96 unsigned short heads; /* "physical" heads */
97 unsigned short track_bytes; /* unformatted bytes per track */
98 unsigned short sector_bytes; /* unformatted bytes per sector */
99 unsigned short sectors; /* "physical" sectors per track */
100 unsigned short vendor0; /* vendor unique */
101 unsigned short vendor1; /* vendor unique */
102 unsigned short vendor2; /* vendor unique */
103 unsigned char serial_no[20]; /* 0 = not_specified */
104 unsigned short buf_type;
105 unsigned short buf_size; /* 512 byte increments;
107 unsigned short ecc_bytes; /* for r/w long cmds;
109 unsigned char fw_rev[8]; /* 0 = not_specified */
110 char model[40]; /* 0 = not_specified */
111 unsigned char max_multsect; /* 0=not_implemented */
112 unsigned char vendor3; /* vendor unique */
113 unsigned short dword_io; /* 0=not_implemented; 1=implemented */
114 unsigned char vendor4; /* vendor unique */
115 unsigned char capability; /* bits 0:DMA 1:LBA 2:IORDYsw
117 unsigned short reserved50; /* reserved (word 50) */
118 unsigned char vendor5; /* vendor unique */
119 unsigned char tPIO; /* 0=slow, 1=medium, 2=fast */
120 unsigned char vendor6; /* vendor unique */
121 unsigned char tDMA; /* 0=slow, 1=medium, 2=fast */
122 unsigned short field_valid; /* bits 0:cur_ok 1:eide_ok */
123 unsigned short cur_cyls; /* logical cylinders */
124 unsigned short cur_heads; /* logical heads */
125 unsigned short cur_sectors; /* logical sectors per track */
126 unsigned short cur_capacity0; /* logical total sectors on drive */
127 unsigned short cur_capacity1; /* (2 words, misaligned int) */
128 unsigned char multsect; /* current multiple sector count */
129 unsigned char multsect_valid; /* when (bit0==1) multsect is ok */
130 unsigned int lba_capacity; /* total number of sectors */
131 unsigned short dma_1word; /* single-word dma info */
132 unsigned short dma_mword; /* multiple-word dma info */
133 unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */
134 unsigned short eide_dma_min; /* min mword dma cycle time (ns) */
135 unsigned short eide_dma_time; /* recommended mword dma cycle
137 unsigned short eide_pio; /* min cycle time (ns), no IORDY */
138 unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */
139 unsigned short words69_70[2]; /* reserved words 69-70 */
140 /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
141 unsigned short words71_74[4]; /* reserved words 71-74 */
142 unsigned short queue_depth; /* */
143 unsigned short words76_79[4]; /* reserved words 76-79 */
144 unsigned short major_rev_num; /* */
145 unsigned short minor_rev_num; /* */
146 unsigned short command_set_1; /* bits 0:Smart 1:Security 2:Removable
148 unsigned short command_set_2; /* bits 14:Smart Enabled 13:0 zero */
149 unsigned short cfsse; /* command set-feature supported
151 unsigned short cfs_enable_1; /* command set-feature enabled */
152 unsigned short cfs_enable_2; /* command set-feature enabled */
153 unsigned short csf_default; /* command set-feature default */
154 unsigned short dma_ultra; /* */
155 unsigned short word89; /* reserved (word 89) */
156 unsigned short word90; /* reserved (word 90) */
157 unsigned short CurAPMvalues; /* current APM values */
158 unsigned short word92; /* reserved (word 92) */
159 unsigned short hw_config; /* hardware config */
160 unsigned short words94_105[12];/* reserved words 94-105 */
161 struct ata7_sectinfo ata7_sectinfo; /* ATAPI/ATA7 physical and logical
163 unsigned short words107_116[10];/* reserved words 107-116 */
164 unsigned int logical_sectsize;/* ATAPI/ATA7 logical sector size */
165 unsigned short words119_125[7];/* reserved words 119-125 */
166 unsigned short last_lun; /* reserved (word 126) */
167 unsigned short word127; /* reserved (word 127) */
168 unsigned short dlf; /* device lock function
170 * 8 security level 1:max 0:high
179 unsigned short csfo; /* current set features options
186 unsigned short words130_155[26];/* reserved vendor words 130-155 */
187 unsigned short word156;
188 unsigned short words157_159[3]; /* reserved vendor words 157-159 */
189 unsigned short words160_255[95];/* reserved words 160-255 */
192 /* from <linux/fs.h> */
193 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
194 #define BLKGETSIZE _IO(0x12,96) /* return device size */
195 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
196 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
197 #define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
198 #define BLKSETLASTSECT _IO(0x12,109) /* set last sector of block device */
200 /* return device size in bytes (u64 *arg) */
201 #define BLKGETSIZE64 _IOR(0x12,114,size_t)
203 struct blkdev_ioctl_param {
205 size_t content_length;
206 char * block_contents;
209 /* from <linux/major.h> */
211 #define IDE1_MAJOR 22
212 #define IDE2_MAJOR 33
213 #define IDE3_MAJOR 34
214 #define IDE4_MAJOR 56
215 #define IDE5_MAJOR 57
216 #define SCSI_CDROM_MAJOR 11
217 #define SCSI_DISK0_MAJOR 8
218 #define SCSI_DISK1_MAJOR 65
219 #define SCSI_DISK2_MAJOR 66
220 #define SCSI_DISK3_MAJOR 67
221 #define SCSI_DISK4_MAJOR 68
222 #define SCSI_DISK5_MAJOR 69
223 #define SCSI_DISK6_MAJOR 70
224 #define SCSI_DISK7_MAJOR 71
225 #define COMPAQ_SMART2_MAJOR 72
226 #define COMPAQ_SMART2_MAJOR1 73
227 #define COMPAQ_SMART2_MAJOR2 74
228 #define COMPAQ_SMART2_MAJOR3 75
229 #define COMPAQ_SMART2_MAJOR4 76
230 #define COMPAQ_SMART2_MAJOR5 77
231 #define COMPAQ_SMART2_MAJOR6 78
232 #define COMPAQ_SMART2_MAJOR7 79
233 #define COMPAQ_SMART_MAJOR 104
234 #define COMPAQ_SMART_MAJOR1 105
235 #define COMPAQ_SMART_MAJOR2 106
236 #define COMPAQ_SMART_MAJOR3 107
237 #define COMPAQ_SMART_MAJOR4 108
238 #define COMPAQ_SMART_MAJOR5 109
239 #define COMPAQ_SMART_MAJOR6 110
240 #define COMPAQ_SMART_MAJOR7 111
241 #define DAC960_MAJOR 48
242 #define ATARAID_MAJOR 114
243 #define I2O_MAJOR1 80
244 #define I2O_MAJOR2 81
245 #define I2O_MAJOR3 82
246 #define I2O_MAJOR4 83
247 #define I2O_MAJOR5 84
248 #define I2O_MAJOR6 85
249 #define I2O_MAJOR7 86
250 #define I2O_MAJOR8 87
252 #define DASD_MAJOR 94
253 #define VIODASD_MAJOR 112
254 #define SX8_MAJOR1 160
255 #define SX8_MAJOR2 161
256 #define XVD_MAJOR 202
258 #define SCSI_BLK_MAJOR(M) ( \
259 (M) == SCSI_DISK0_MAJOR \
260 || (M) == SCSI_CDROM_MAJOR \
261 || ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
263 static char* _device_get_part_path (PedDevice* dev, int num);
264 static int _partition_is_mounted_by_path (const char* path);
267 _is_ide_major (int major)
284 _is_cpqarray_major (int major)
286 return ((COMPAQ_SMART2_MAJOR <= major && major <= COMPAQ_SMART2_MAJOR7)
287 || (COMPAQ_SMART_MAJOR <= major && major <= COMPAQ_SMART_MAJOR7));
291 _is_i2o_major (int major)
293 return (I2O_MAJOR1 <= major && major <= I2O_MAJOR8);
297 _is_sx8_major (int major)
299 return (SX8_MAJOR1 <= major && major <= SX8_MAJOR2);
302 #ifdef ENABLE_DEVICE_MAPPER
304 readFD (int fd, char **buf)
307 size_t size = PROC_DEVICES_BUFSIZ;
310 *buf = malloc (size * sizeof (char));
316 p = &(*buf) [filesize];
317 s = read (fd, p, PROC_DEVICES_BUFSIZ);
318 /* exit if there is an error or EOF is reached */
323 *buf = realloc (*buf, size);
326 if (filesize == 0 && s < 0) {
331 /* there is always some excess memory left unused */
332 *buf = realloc (*buf, filesize+1);
333 (*buf)[filesize] = '\0';
340 _is_dm_major (int major)
349 fd = open ("/proc/devices", O_RDONLY);
353 if (readFD(fd, &buf) < 0) {
359 end = strchr(line, '\n');
368 if (!strncmp(line, "Block devices:", 14))
373 name = strrchr(line, ' ');
374 if (!name || strcmp(name+1, "device-mapper"))
377 maj = strtol(line, &name, 10);
387 end = strchr(line, '\n');
399 char buf [512]; /* readdir(3) claims d_name[256] */
402 mapper_dir = opendir ("/dev/mapper");
406 /* Search the /dev/mapper directory for devices w/ the same major
407 * number that was returned from _probe_lvm_major().
409 while ((dent = readdir (mapper_dir))) {
410 if (strcmp (dent->d_name, ".") == 0 ||
411 strcmp (dent->d_name, "..") == 0)
414 snprintf (buf, sizeof (buf), "/dev/mapper/%s", dent->d_name);
416 if (stat (buf, &st) != 0)
419 if (_is_dm_major(major(st.st_rdev)))
420 _ped_device_probe (buf);
422 closedir (mapper_dir);
429 _device_stat (PedDevice* dev, struct stat * dev_stat)
431 PED_ASSERT (dev != NULL, return 0);
432 PED_ASSERT (!dev->external_mode, return 0);
435 if (!stat (dev->path, dev_stat)) {
438 if (ped_exception_throw (
440 PED_EXCEPTION_RETRY_CANCEL,
441 _("Could not stat device %s - %s."),
444 != PED_EXCEPTION_RETRY)
451 _device_probe_type (PedDevice* dev)
453 struct stat dev_stat;
457 if (!_device_stat (dev, &dev_stat))
460 if (!S_ISBLK(dev_stat.st_mode)) {
461 dev->type = PED_DEVICE_FILE;
465 dev_major = major (dev_stat.st_rdev);
466 dev_minor = minor (dev_stat.st_rdev);
468 if (SCSI_BLK_MAJOR (dev_major) && (dev_minor % 0x10 == 0)) {
469 dev->type = PED_DEVICE_SCSI;
470 } else if (_is_ide_major (dev_major) && (dev_minor % 0x40 == 0)) {
471 dev->type = PED_DEVICE_IDE;
472 } else if (dev_major == DAC960_MAJOR && (dev_minor % 0x8 == 0)) {
473 dev->type = PED_DEVICE_DAC960;
474 } else if (dev_major == ATARAID_MAJOR && (dev_minor % 0x10 == 0)) {
475 dev->type = PED_DEVICE_ATARAID;
476 } else if (dev_major == DASD_MAJOR && (dev_minor % 0x4 == 0)) {
477 dev->type = PED_DEVICE_DASD;
478 } else if (dev_major == VIODASD_MAJOR && (dev_minor % 0x8 == 0)) {
479 dev->type = PED_DEVICE_VIODASD;
480 } else if (_is_sx8_major(dev_major) && (dev_minor % 0x20 == 0)) {
481 dev->type = PED_DEVICE_SX8;
482 } else if (_is_i2o_major (dev_major) && (dev_minor % 0x10 == 0)) {
483 dev->type = PED_DEVICE_I2O;
484 } else if (_is_cpqarray_major (dev_major) && (dev_minor % 0x10 == 0)) {
485 dev->type = PED_DEVICE_CPQARRAY;
486 } else if (dev_major == UBD_MAJOR && (dev_minor % 0x10 == 0)) {
487 dev->type = PED_DEVICE_UBD;
488 #ifdef ENABLE_DEVICE_MAPPER
489 } else if (_is_dm_major(dev_major)) {
490 dev->type = PED_DEVICE_DM;
492 } else if (dev_major == XVD_MAJOR && (dev_minor % 0x10 == 0)) {
493 dev->type = PED_DEVICE_XVD;
495 dev->type = PED_DEVICE_UNKNOWN;
502 _get_linux_version ()
504 static int kver = -1;
516 if (sscanf (uts.release, "%u.%u.%u", &major, &minor, &teeny) != 3)
519 return kver = KERNEL_VERSION (major, minor, teeny);
525 static int have_devfs = -1;
528 if (have_devfs != -1)
531 /* the presence of /dev/.devfsd implies that DevFS is active */
532 if (stat("/dev/.devfsd", &sb) < 0)
533 return have_devfs = 0;
535 return have_devfs = S_ISCHR(sb.st_mode) ? 1 : 0;
539 _device_set_sector_size (PedDevice* dev)
541 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
544 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
545 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
547 PED_ASSERT (dev->open_count, return);
549 if (_get_linux_version() < KERNEL_VERSION (2,3,0)) {
550 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
554 if (ioctl (arch_specific->fd, BLKSSZGET, §or_size)) {
555 ped_exception_throw (
556 PED_EXCEPTION_WARNING,
558 _("Could not determine sector size for %s: %s.\n"
559 "Using the default sector size (%lld)."),
560 dev->path, strerror (errno), PED_SECTOR_SIZE_DEFAULT);
562 dev->sector_size = (long long)sector_size;
565 /* Return PED_SECTOR_SIZE_DEFAULT for DASDs. */
566 if (dev->type == PED_DEVICE_DASD) {
567 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
570 if (dev->sector_size != PED_SECTOR_SIZE_DEFAULT) {
571 ped_exception_throw (
572 PED_EXCEPTION_WARNING,
574 _("Device %s has a logical sector size of %lld. Not "
575 "all parts of GNU Parted support this at the moment, "
576 "and the working code is HIGHLY EXPERIMENTAL.\n"),
577 dev->path, dev->sector_size);
582 _kernel_has_blkgetsize64(void)
584 int version = _get_linux_version();
586 if (version >= KERNEL_VERSION (2,5,4)) return 1;
587 if (version < KERNEL_VERSION (2,5,0) &&
588 version >= KERNEL_VERSION (2,4,18)) return 1;
592 /* TODO: do a binary search if BLKGETSIZE doesn't work?! */
594 _device_get_length (PedDevice* dev)
597 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
601 PED_ASSERT (dev->open_count > 0, return 0);
602 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
604 if (_kernel_has_blkgetsize64()) {
605 if (ioctl(arch_specific->fd, BLKGETSIZE64, &bytes) == 0) {
606 return bytes / dev->sector_size;
610 if (ioctl (arch_specific->fd, BLKGETSIZE, &size)) {
611 ped_exception_throw (
613 PED_EXCEPTION_CANCEL,
614 _("Unable to determine the size of %s (%s)."),
624 _device_probe_geometry (PedDevice* dev)
626 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
627 struct stat dev_stat;
628 struct hd_geometry geometry;
630 if (!_device_stat (dev, &dev_stat))
632 PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
634 _device_set_sector_size (dev);
636 dev->length = _device_get_length (dev);
640 /* The GETGEO ioctl is no longer useful (as of linux 2.6.x). We could
641 * still use it in 2.4.x, but this is contentious. Perhaps we should
643 dev->bios_geom.sectors = 63;
644 dev->bios_geom.heads = 255;
645 dev->bios_geom.cylinders
646 = dev->length / (63 * 255);
648 /* FIXME: what should we put here? (TODO: discuss on linux-kernel) */
649 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geometry)
650 && geometry.sectors && geometry.heads) {
651 dev->hw_geom.sectors = geometry.sectors;
652 dev->hw_geom.heads = geometry.heads;
653 dev->hw_geom.cylinders
654 = dev->length / (dev->hw_geom.heads
655 * dev->hw_geom.sectors);
657 dev->hw_geom = dev->bios_geom;
664 strip_name(char* str)
669 for (i = 0; str[i] != 0; i++) {
670 if (!isspace (str[i])
671 || (isspace (str[i]) && !isspace (str[i+1]) && str[i+1])) {
681 init_ide (PedDevice* dev)
683 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
684 struct stat dev_stat;
686 struct hd_driveid hdi;
687 PedExceptionOption ex_status;
689 int sector_multiplier = 0;
691 if (!_device_stat (dev, &dev_stat))
694 dev_major = major (dev_stat.st_rdev);
696 if (!ped_device_open (dev))
699 if (ioctl (arch_specific->fd, HDIO_GET_IDENTITY, &hdi)) {
700 ex_status = ped_exception_throw (
701 PED_EXCEPTION_WARNING,
702 PED_EXCEPTION_IGNORE_CANCEL,
703 _("Could not get identity of device %s - %s"),
704 dev->path, strerror (errno));
706 case PED_EXCEPTION_CANCEL:
707 goto error_close_dev;
709 case PED_EXCEPTION_UNHANDLED:
710 ped_exception_catch ();
711 case PED_EXCEPTION_IGNORE:
712 dev->model = strdup(_("Generic IDE"));
715 PED_ASSERT (0, (void) 0);
719 /* hdi.model is not guaranteed to be NULL terminated */
720 memcpy (hdi_buf, hdi.model, 40);
722 dev->model = strip_name (hdi_buf);
724 if (!hdi.ata7_sectinfo.valid1 && hdi.ata7_sectinfo.valid2)
725 sector_multiplier = hdi.ata7_sectinfo.multiplier;
727 sector_multiplier = 1;
729 if (sector_multiplier != 1) {
730 ex_status = ped_exception_throw (
731 PED_EXCEPTION_WARNING,
732 PED_EXCEPTION_IGNORE_CANCEL,
733 _("Device %s has multiple (%d) logical sectors "
734 "per physical sector.\n"
735 "GNU Parted supports this EXPERIMENTALLY for "
736 "some special disk label/file system "
737 "combinations, e.g. GPT and ext2/3.\n"
738 "Please consult the web site for up-to-date "
740 dev->path, sector_multiplier);
743 case PED_EXCEPTION_CANCEL:
744 goto error_close_dev;
746 case PED_EXCEPTION_UNHANDLED:
747 ped_exception_catch ();
748 case PED_EXCEPTION_IGNORE:
751 PED_ASSERT (0, (void) 0);
756 /* XXX sector_size has not been set yet! */
757 /* dev->phys_sector_size = dev->sector_size
758 * sector_multiplier;*/
759 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
762 if (!_device_probe_geometry (dev))
763 goto error_close_dev;
765 ped_device_close (dev);
769 ped_device_close (dev);
774 /* This function reads the /sys entry named "file" for device "dev". */
776 read_device_sysfs_file (PedDevice *dev, const char *file)
782 snprintf (name_buf, 127, "/sys/block/%s/device/%s",
783 basename (dev->path), file);
785 if ((f = fopen (name_buf, "r")) == NULL)
788 if (fgets (buf, 255, f) == NULL)
792 return strip_name (buf);
795 /* This function sends a query to a SCSI device for vendor and product
796 * information. It uses the deprecated SCSI_IOCTL_SEND_COMMAND to
800 scsi_query_product_info (PedDevice* dev, char **vendor, char **product)
802 /* The following are defined by the SCSI-2 specification. */
803 typedef struct _scsi_inquiry_cmd
806 uint8_t lun; /* bits 5-7 denote the LUN */
809 uint8_t alloc_length;
811 } __attribute__((packed)) scsi_inquiry_cmd_t;
813 typedef struct _scsi_inquiry_data
815 uint8_t peripheral_info;
817 uint8_t version_info;
819 uint8_t additional_length;
823 uint8_t vendor_id[8];
824 uint8_t product_id[16];
825 uint8_t product_revision[4];
826 uint8_t vendor_specific[20];
827 uint8_t _reserved3[40];
828 } __attribute__((packed)) scsi_inquiry_data_t;
837 scsi_inquiry_data_t out;
838 scsi_inquiry_cmd_t in;
842 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
848 memset (&arg, 0x00, sizeof(struct scsi_arg));
850 arg.outlen = sizeof(scsi_inquiry_data_t);
851 arg.data.in.op = INQUIRY;
852 arg.data.in.lun = dev->host << 5;
853 arg.data.in.alloc_length = sizeof(scsi_inquiry_data_t);
854 arg.data.in.page_code = 0;
855 arg.data.in.reserved = 0;
856 arg.data.in.control = 0;
858 if (ioctl (arch_specific->fd, SCSI_IOCTL_SEND_COMMAND, &arg) < 0)
861 memcpy (buf, arg.data.out.vendor_id, 8);
863 *vendor = strip_name (buf);
865 memcpy (buf, arg.data.out.product_id, 16);
867 *product = strip_name (buf);
872 /* This function provides the vendor and product name for a SCSI device.
873 * It supports both the modern /sys interface and direct queries
874 * via the deprecated ioctl, SCSI_IOCTL_SEND_COMMAND.
877 scsi_get_product_info (PedDevice* dev, char **vendor, char **product)
879 *vendor = read_device_sysfs_file (dev, "vendor");
880 *product = read_device_sysfs_file (dev, "model");
881 if (*vendor && *product)
884 return scsi_query_product_info (dev, vendor, product);
888 init_scsi (PedDevice* dev)
893 uint32_t host_unique_id;
896 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
900 if (!ped_device_open (dev))
903 if (ioctl (arch_specific->fd, SCSI_IOCTL_GET_IDLUN, &idlun) < 0) {
906 if (ped_exception_throw (
907 PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
908 _("Error initialising SCSI device %s - %s"),
909 dev->path, strerror (errno))
910 != PED_EXCEPTION_IGNORE)
911 goto error_close_dev;
912 if (!_device_probe_geometry (dev))
913 goto error_close_dev;
914 ped_device_close (dev);
918 dev->host = idlun.host_unique_id;
919 dev->did = idlun.dev_id;
921 dev->model = (char*) ped_malloc (8 + 16 + 2);
923 goto error_close_dev;
925 if (scsi_get_product_info (dev, &vendor, &product)) {
926 sprintf (dev->model, "%.8s %.16s", vendor, product);
930 strcpy (dev->model, "Generic SCSI");
933 if (!_device_probe_geometry (dev))
934 goto error_close_dev;
936 ped_device_close (dev);
940 ped_device_close (dev);
946 init_file (PedDevice* dev)
948 struct stat dev_stat;
950 if (!_device_stat (dev, &dev_stat))
952 if (!ped_device_open (dev))
955 if (S_ISBLK(dev_stat.st_mode))
956 dev->length = _device_get_length (dev);
958 dev->length = dev_stat.st_size / 512;
959 if (dev->length <= 0) {
960 ped_exception_throw (
962 PED_EXCEPTION_CANCEL,
963 _("The device %s has zero length, and can't possibly "
964 "store a file system or partition table. Perhaps "
965 "you selected the wrong device?"),
967 goto error_close_dev;
970 ped_device_close (dev);
972 dev->bios_geom.cylinders = dev->length / 4 / 32;
973 dev->bios_geom.heads = 4;
974 dev->bios_geom.sectors = 32;
975 dev->hw_geom = dev->bios_geom;
976 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
977 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
978 dev->model = strdup ("");
983 ped_device_close (dev);
989 init_dasd (PedDevice* dev, char* model_name)
991 struct stat dev_stat;
992 struct hd_geometry geo;
995 if (!_device_stat (dev, &dev_stat))
998 if (!ped_device_open (dev))
1001 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1003 PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
1005 _device_set_sector_size (dev);
1006 if (!dev->sector_size)
1007 goto error_close_dev;
1009 dev->length = _device_get_length (dev);
1011 goto error_close_dev;
1013 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geo)) {
1014 dev->hw_geom.sectors = geo.sectors;
1015 dev->hw_geom.heads = geo.heads;
1016 dev->hw_geom.cylinders = dev->length
1017 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1018 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1019 dev->bios_geom = dev->hw_geom;
1021 dev->bios_geom.sectors = 12;
1022 dev->bios_geom.heads = 15;
1023 dev->bios_geom.cylinders = dev->length
1024 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1025 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1026 dev->hw_geom = dev->bios_geom;
1029 dev->model = strdup (model_name);
1031 ped_device_close (dev);
1034 ped_exception_throw ( PED_EXCEPTION_ERROR,
1035 PED_EXCEPTION_IGNORE_CANCEL,
1039 ped_device_close (dev);
1045 init_generic (PedDevice* dev, char* model_name)
1047 struct stat dev_stat;
1048 PedExceptionOption ex_status;
1050 if (!_device_stat (dev, &dev_stat))
1053 if (!ped_device_open (dev))
1056 ped_exception_fetch_all ();
1057 if (_device_probe_geometry (dev)) {
1058 ped_exception_leave_all ();
1060 /* hack to allow use of files, for testing */
1061 ped_exception_catch ();
1062 ped_exception_leave_all ();
1064 ex_status = ped_exception_throw (
1065 PED_EXCEPTION_WARNING,
1066 PED_EXCEPTION_IGNORE_CANCEL,
1067 _("Unable to determine geometry of "
1068 "file/device %s. You should not use Parted "
1069 "unless you REALLY know what you're doing!"),
1071 switch (ex_status) {
1072 case PED_EXCEPTION_CANCEL:
1073 goto error_close_dev;
1075 case PED_EXCEPTION_UNHANDLED:
1076 ped_exception_catch ();
1077 case PED_EXCEPTION_IGNORE:
1080 PED_ASSERT (0, (void) 0);
1084 /* what should we stick in here? */
1085 dev->length = dev_stat.st_size / PED_SECTOR_SIZE_DEFAULT;
1086 dev->bios_geom.cylinders = dev->length / 4 / 32;
1087 dev->bios_geom.heads = 4;
1088 dev->bios_geom.sectors = 32;
1089 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1090 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
1093 dev->model = strdup (model_name);
1095 ped_device_close (dev);
1099 ped_device_close (dev);
1105 linux_new (const char* path)
1109 PED_ASSERT (path != NULL, return NULL);
1111 dev = (PedDevice*) ped_malloc (sizeof (PedDevice));
1115 dev->path = strdup (path);
1117 goto error_free_dev;
1120 = (LinuxSpecific*) ped_malloc (sizeof (LinuxSpecific));
1121 if (!dev->arch_specific)
1122 goto error_free_path;
1124 dev->open_count = 0;
1126 dev->external_mode = 0;
1128 dev->boot_dirty = 0;
1130 if (!_device_probe_type (dev))
1131 goto error_free_arch_specific;
1133 switch (dev->type) {
1134 case PED_DEVICE_IDE:
1135 if (!init_ide (dev))
1136 goto error_free_arch_specific;
1139 case PED_DEVICE_SCSI:
1140 if (!init_scsi (dev))
1141 goto error_free_arch_specific;
1144 case PED_DEVICE_DAC960:
1145 if (!init_generic (dev, _("DAC960 RAID controller")))
1146 goto error_free_arch_specific;
1149 case PED_DEVICE_SX8:
1150 if (!init_generic (dev, _("Promise SX8 SATA Device")))
1151 goto error_free_arch_specific;
1154 case PED_DEVICE_DASD:
1155 if (!init_dasd (dev, _("IBM S390 DASD drive")))
1156 goto error_free_arch_specific;
1159 case PED_DEVICE_VIODASD:
1160 if (!init_generic (dev, _("IBM iSeries Virtual DASD")))
1161 goto error_free_arch_specific;
1164 case PED_DEVICE_CPQARRAY:
1165 if (!init_generic (dev, _("Compaq Smart Array")))
1166 goto error_free_arch_specific;
1169 case PED_DEVICE_ATARAID:
1170 if (!init_generic (dev, _("ATARAID Controller")))
1171 goto error_free_arch_specific;
1174 case PED_DEVICE_I2O:
1175 if (!init_generic (dev, _("I2O Controller")))
1176 goto error_free_arch_specific;
1179 case PED_DEVICE_UBD:
1180 if (!init_generic (dev, _("User-Mode Linux UBD")))
1181 goto error_free_arch_specific;
1184 case PED_DEVICE_FILE:
1185 if (!init_file (dev))
1186 goto error_free_arch_specific;
1189 #ifdef ENABLE_DEVICE_MAPPER
1191 if (!init_generic (dev, _("Linux device-mapper")))
1192 goto error_free_arch_specific;
1196 case PED_DEVICE_XVD:
1197 if (!init_generic (dev, _("Xen Virtual Block Device")))
1198 goto error_free_arch_specific;
1201 case PED_DEVICE_UNKNOWN:
1202 if (!init_generic (dev, _("Unknown")))
1203 goto error_free_arch_specific;
1207 ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
1208 PED_EXCEPTION_CANCEL,
1209 _("ped_device_new() Unsupported device type"));
1210 goto error_free_arch_specific;
1214 error_free_arch_specific:
1215 ped_free (dev->arch_specific);
1217 ped_free (dev->path);
1225 linux_destroy (PedDevice* dev)
1227 ped_free (dev->arch_specific);
1228 ped_free (dev->path);
1229 ped_free (dev->model);
1234 linux_is_busy (PedDevice* dev)
1239 if (_partition_is_mounted_by_path (dev->path))
1242 for (i = 0; i < 32; i++) {
1245 part_name = _device_get_part_path (dev, i);
1248 status = _partition_is_mounted_by_path (part_name);
1249 ped_free (part_name);
1258 /* we need to flush the master device, and all the partition devices,
1259 * because there is no coherency between the caches.
1260 * We should only flush unmounted partition devices, because:
1261 * - there is never a need to flush them (we're not doing IO there)
1262 * - flushing a device that is mounted causes unnecessary IO, and can
1263 * even screw journaling & friends up. Even cause oopsen!
1266 _flush_cache (PedDevice* dev)
1268 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1275 ioctl (arch_specific->fd, BLKFLSBUF);
1277 for (i = 1; i < 16; i++) {
1281 name = _device_get_part_path (dev, i);
1284 if (!_partition_is_mounted_by_path (name)) {
1285 fd = open (name, WR_MODE, 0);
1287 ioctl (fd, BLKFLSBUF);
1296 linux_open (PedDevice* dev)
1298 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1301 arch_specific->fd = open (dev->path, RW_MODE);
1303 if (arch_specific->fd == -1) {
1304 char* rw_error_msg = strerror (errno);
1306 arch_specific->fd = open (dev->path, RD_MODE);
1308 if (arch_specific->fd == -1) {
1309 if (ped_exception_throw (
1310 PED_EXCEPTION_ERROR,
1311 PED_EXCEPTION_RETRY_CANCEL,
1312 _("Error opening %s: %s"),
1313 dev->path, strerror (errno))
1314 != PED_EXCEPTION_RETRY) {
1320 ped_exception_throw (
1321 PED_EXCEPTION_WARNING,
1323 _("Unable to open %s read-write (%s). %s has "
1324 "been opened read-only."),
1325 dev->path, rw_error_msg, dev->path);
1338 linux_refresh_open (PedDevice* dev)
1344 linux_close (PedDevice* dev)
1346 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1350 close (arch_specific->fd);
1355 linux_refresh_close (PedDevice* dev)
1362 #if SIZEOF_OFF_T < 8
1364 static _syscall5(int,_llseek,
1366 unsigned long, offset_high,
1367 unsigned long, offset_low,
1369 unsigned int, origin)
1372 llseek (unsigned int fd, loff_t offset, unsigned int whence)
1377 retval = _llseek(fd,
1378 ((unsigned long long)offset) >> 32,
1379 ((unsigned long long)offset) & 0xffffffff,
1382 return (retval==-1 ? (loff_t) retval : result);
1385 #endif /* SIZEOF_OFF_T < 8 */
1388 _device_seek (const PedDevice* dev, PedSector sector)
1390 LinuxSpecific* arch_specific;
1392 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1393 PED_ASSERT (dev != NULL, return 0);
1394 PED_ASSERT (!dev->external_mode, return 0);
1396 arch_specific = LINUX_SPECIFIC (dev);
1398 #if SIZEOF_OFF_T < 8
1399 if (sizeof (off_t) < 8) {
1400 loff_t pos = (loff_t)(sector * dev->sector_size);
1401 return llseek (arch_specific->fd, pos, SEEK_SET) == pos;
1405 off_t pos = sector * dev->sector_size;
1406 return lseek (arch_specific->fd, pos, SEEK_SET) == pos;
1411 _read_lastoddsector (const PedDevice* dev, void* buffer)
1413 LinuxSpecific* arch_specific;
1414 struct blkdev_ioctl_param ioctl_param;
1416 PED_ASSERT(dev != NULL, return 0);
1417 PED_ASSERT(buffer != NULL, return 0);
1419 arch_specific = LINUX_SPECIFIC (dev);
1422 ioctl_param.block = 0; /* read the last sector */
1423 ioctl_param.content_length = dev->sector_size;
1424 ioctl_param.block_contents = buffer;
1426 if (ioctl(arch_specific->fd, BLKGETLASTSECT, &ioctl_param) == -1) {
1427 PedExceptionOption opt;
1428 opt = ped_exception_throw (
1429 PED_EXCEPTION_ERROR,
1430 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1431 _("%s during read on %s"),
1432 strerror (errno), dev->path);
1434 if (opt == PED_EXCEPTION_CANCEL)
1436 if (opt == PED_EXCEPTION_RETRY)
1444 linux_read (const PedDevice* dev, void* buffer, PedSector start,
1447 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1448 PedExceptionOption ex_status;
1449 void* diobuf = NULL;
1451 PED_ASSERT (dev != NULL, return 0);
1452 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1454 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1455 /* Kludge. This is necessary to read/write the last
1456 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1458 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1459 && start + count - 1 == dev->length - 1)
1460 return ped_device_read (dev, buffer, start, count - 1)
1461 && _read_lastoddsector (
1462 dev, (char *) buffer + (count-1) * 512);
1465 if (_device_seek (dev, start))
1468 ex_status = ped_exception_throw (
1469 PED_EXCEPTION_ERROR,
1470 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1471 _("%s during seek for read on %s"),
1472 strerror (errno), dev->path);
1474 switch (ex_status) {
1475 case PED_EXCEPTION_IGNORE:
1478 case PED_EXCEPTION_RETRY:
1481 case PED_EXCEPTION_UNHANDLED:
1482 ped_exception_catch ();
1483 case PED_EXCEPTION_CANCEL:
1486 PED_ASSERT (0, (void) 0);
1491 size_t read_length = count * dev->sector_size;
1492 if (posix_memalign (&diobuf, dev->sector_size, read_length) != 0)
1496 ssize_t status = read (arch_specific->fd, diobuf, read_length);
1498 memcpy(buffer, diobuf, status);
1499 if (status == (ssize_t) read_length)
1502 read_length -= status;
1503 buffer = (char *) buffer + status;
1507 ex_status = ped_exception_throw (
1508 PED_EXCEPTION_ERROR,
1509 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1510 _("%s during read on %s"),
1514 switch (ex_status) {
1515 case PED_EXCEPTION_IGNORE:
1519 case PED_EXCEPTION_RETRY:
1522 case PED_EXCEPTION_UNHANDLED:
1523 ped_exception_catch ();
1524 case PED_EXCEPTION_CANCEL:
1528 PED_ASSERT (0, (void) 0);
1539 _write_lastoddsector (PedDevice* dev, const void* buffer)
1541 LinuxSpecific* arch_specific;
1542 struct blkdev_ioctl_param ioctl_param;
1544 PED_ASSERT(dev != NULL, return 0);
1545 PED_ASSERT(buffer != NULL, return 0);
1547 arch_specific = LINUX_SPECIFIC (dev);
1550 ioctl_param.block = 0; /* write the last sector */
1551 ioctl_param.content_length = dev->sector_size;
1552 ioctl_param.block_contents = (void*) buffer;
1554 if (ioctl(arch_specific->fd, BLKSETLASTSECT, &ioctl_param) == -1) {
1555 PedExceptionOption opt;
1556 opt = ped_exception_throw (
1557 PED_EXCEPTION_ERROR,
1558 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1559 _("%s during write on %s"),
1560 strerror (errno), dev->path);
1562 if (opt == PED_EXCEPTION_CANCEL)
1564 if (opt == PED_EXCEPTION_RETRY)
1572 linux_write (PedDevice* dev, const void* buffer, PedSector start,
1575 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1576 PedExceptionOption ex_status;
1580 PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1582 if (dev->read_only) {
1583 if (ped_exception_throw (
1584 PED_EXCEPTION_ERROR,
1585 PED_EXCEPTION_IGNORE_CANCEL,
1586 _("Can't write to %s, because it is opened read-only."),
1588 != PED_EXCEPTION_IGNORE)
1594 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1595 /* Kludge. This is necessary to read/write the last
1596 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1598 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1599 && start + count - 1 == dev->length - 1)
1600 return ped_device_write (dev, buffer, start, count - 1)
1601 && _write_lastoddsector (
1602 dev, (char*) buffer + (count-1) * 512);
1605 if (_device_seek (dev, start))
1608 ex_status = ped_exception_throw (
1609 PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1610 _("%s during seek for write on %s"),
1611 strerror (errno), dev->path);
1613 switch (ex_status) {
1614 case PED_EXCEPTION_IGNORE:
1617 case PED_EXCEPTION_RETRY:
1620 case PED_EXCEPTION_UNHANDLED:
1621 ped_exception_catch ();
1622 case PED_EXCEPTION_CANCEL:
1625 PED_ASSERT (0, (void) 0);
1631 printf ("ped_device_write (\"%s\", %p, %d, %d)\n",
1632 dev->path, buffer, (int) start, (int) count);
1634 size_t write_length = count * dev->sector_size;
1636 if (posix_memalign(&diobuf, dev->sector_size, write_length) != 0)
1638 memcpy(diobuf, buffer, write_length);
1639 diobuf_start = diobuf;
1641 ssize_t status = write (arch_specific->fd, diobuf, write_length);
1642 if (status == write_length) break;
1644 write_length -= status;
1645 diobuf = (char *) diobuf + status;
1649 ex_status = ped_exception_throw (
1650 PED_EXCEPTION_ERROR,
1651 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1652 _("%s during write on %s"),
1653 strerror (errno), dev->path);
1655 switch (ex_status) {
1656 case PED_EXCEPTION_IGNORE:
1660 case PED_EXCEPTION_RETRY:
1663 case PED_EXCEPTION_UNHANDLED:
1664 ped_exception_catch ();
1665 case PED_EXCEPTION_CANCEL:
1669 PED_ASSERT (0, (void) 0);
1674 #endif /* !READ_ONLY */
1678 /* returns the number of sectors that are ok.
1681 linux_check (PedDevice* dev, void* buffer, PedSector start, PedSector count)
1683 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1688 PED_ASSERT(dev != NULL, return 0);
1690 if (!_device_seek (dev, start))
1693 if (posix_memalign(&diobuf, PED_SECTOR_SIZE_DEFAULT,
1694 count * PED_SECTOR_SIZE_DEFAULT) != 0)
1697 for (done = 0; done < count; done += status / dev->sector_size) {
1698 status = read (arch_specific->fd, diobuf,
1699 (size_t) ((count-done) * dev->sector_size));
1701 memcpy(buffer, diobuf, status);
1711 _do_fsync (PedDevice* dev)
1713 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1715 PedExceptionOption ex_status;
1718 status = fsync (arch_specific->fd);
1719 if (status >= 0) break;
1721 ex_status = ped_exception_throw (
1722 PED_EXCEPTION_ERROR,
1723 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1724 _("%s during write on %s"),
1725 strerror (errno), dev->path);
1727 switch (ex_status) {
1728 case PED_EXCEPTION_IGNORE:
1731 case PED_EXCEPTION_RETRY:
1734 case PED_EXCEPTION_UNHANDLED:
1735 ped_exception_catch ();
1736 case PED_EXCEPTION_CANCEL:
1739 PED_ASSERT (0, (void) 0);
1747 linux_sync (PedDevice* dev)
1749 PED_ASSERT (dev != NULL, return 0);
1750 PED_ASSERT (!dev->external_mode, return 0);
1754 if (!_do_fsync (dev))
1761 linux_sync_fast (PedDevice* dev)
1763 PED_ASSERT (dev != NULL, return 0);
1764 PED_ASSERT (!dev->external_mode, return 0);
1768 if (!_do_fsync (dev))
1770 /* no cache flush... */
1775 _compare_digit_state (char ch, int need_digit)
1777 return !!isdigit (ch) == need_digit;
1780 /* matches the regexp "[^0-9]+[0-9]+[^0-9]+[0-9]+$".
1781 * Motivation: accept devices looking like /dev/rd/c0d0, but
1782 * not looking like /dev/hda1 and /dev/rd/c0d0p1
1785 _match_rd_device (const char* name)
1790 /* exclude directory names from test */
1791 pos = strrchr(name, '/') ?: name;
1799 for (state = 0; state < 4; state++) {
1800 int want_digits = (state % 2 == 1);
1804 if (!_compare_digit_state (*pos, want_digits))
1807 } while (_compare_digit_state (*pos, want_digits));
1814 _probe_proc_partitions ()
1816 FILE* proc_part_file;
1817 int major, minor, size;
1819 char part_name [256];
1820 char dev_name [256];
1822 proc_part_file = fopen ("/proc/partitions", "r");
1823 if (!proc_part_file)
1826 if (fgets (buf, 256, proc_part_file) == NULL)
1829 if (fgets (buf, 256, proc_part_file) == NULL)
1832 while (fgets (buf, 512, proc_part_file)
1833 && sscanf (buf, "%d %d %d %255s", &major, &minor, &size,
1835 /* Heuristic for telling partitions and devices apart
1836 * Probably needs to be improved
1838 if (!_match_rd_device (part_name)
1839 && isdigit (part_name [strlen (part_name) - 1]))
1842 strcpy (dev_name, "/dev/");
1843 strcat (dev_name, part_name);
1844 _ped_device_probe (dev_name);
1847 fclose (proc_part_file);
1857 _skip_entry (const char *name)
1860 static struct _entry entries[] = {
1861 { ".", sizeof (".") - 1 },
1862 { "..", sizeof ("..") - 1 },
1863 { "dm-", sizeof ("dm-") - 1 },
1864 { "loop", sizeof ("loop") - 1 },
1865 { "ram", sizeof ("ram") - 1 },
1869 for (i = entries; i->name != 0; i++) {
1870 if (strncmp (name, i->name, i->len) == 0)
1881 struct dirent *dirent;
1882 char dev_name [256];
1885 if (!(blockdir = opendir ("/sys/block")))
1887 while ((dirent = readdir (blockdir))) {
1888 if (_skip_entry (dirent->d_name))
1891 if (strlen (dirent->d_name) > sizeof (dev_name) - 6)
1892 continue; /* device name too long! */
1894 strcpy (dev_name, "/dev/");
1895 strcat (dev_name, dirent->d_name);
1896 /* in /sys/block, '/'s are replaced with '!' or '.' */
1897 for (ptr = dev_name; *ptr != '\0'; ptr++) {
1898 if (*ptr == '!' || *ptr == '.')
1901 _ped_device_probe (dev_name);
1904 closedir (blockdir);
1909 _probe_standard_devices ()
1911 _ped_device_probe ("/dev/hda");
1912 _ped_device_probe ("/dev/hdb");
1913 _ped_device_probe ("/dev/hdc");
1914 _ped_device_probe ("/dev/hdd");
1915 _ped_device_probe ("/dev/hde");
1916 _ped_device_probe ("/dev/hdf");
1917 _ped_device_probe ("/dev/hdg");
1918 _ped_device_probe ("/dev/hdh");
1920 _ped_device_probe ("/dev/sda");
1921 _ped_device_probe ("/dev/sdb");
1922 _ped_device_probe ("/dev/sdc");
1923 _ped_device_probe ("/dev/sdd");
1924 _ped_device_probe ("/dev/sde");
1925 _ped_device_probe ("/dev/sdf");
1933 /* we should probe the standard devs too, even with /proc/partitions,
1934 * because /proc/partitions might return devfs stuff, and we might not
1935 * have devfs available
1937 _probe_standard_devices ();
1939 #ifdef ENABLE_DEVICE_MAPPER
1940 /* device-mapper devices aren't listed in /proc/partitions; or, if
1941 * they are, they're listed as dm-X. So, instead of relying on that,
1942 * we do our own checks.
1944 _probe_dm_devices ();
1947 /* /sys/block is more reliable and consistent; fall back to using
1948 * /proc/partitions if the former is unavailable, however.
1950 if (!_probe_sys_block ())
1951 _probe_proc_partitions ();
1955 _device_get_part_path (PedDevice* dev, int num)
1957 int path_len = strlen (dev->path);
1958 int result_len = path_len + 16;
1961 result = (char*) ped_malloc (result_len);
1965 /* Check for devfs-style /disc => /partN transformation
1966 unconditionally; the system might be using udev with devfs rules,
1967 and if not the test is harmless. */
1968 if (!strcmp (dev->path + path_len - 5, "/disc")) {
1969 /* replace /disc with /path%d */
1970 strcpy (result, dev->path);
1971 snprintf (result + path_len - 5, 16, "/part%d", num);
1972 } else if (dev->type == PED_DEVICE_DAC960
1973 || dev->type == PED_DEVICE_CPQARRAY
1974 || dev->type == PED_DEVICE_ATARAID
1975 #ifdef ENABLE_DEVICE_MAPPER
1976 || dev->type == PED_DEVICE_DM
1978 || isdigit (dev->path[path_len - 1]))
1979 snprintf (result, result_len, "%sp%d", dev->path, num);
1981 snprintf (result, result_len, "%s%d", dev->path, num);
1987 linux_partition_get_path (const PedPartition* part)
1989 return _device_get_part_path (part->disk->dev, part->num);
1993 _partition_get_part_dev (const PedPartition* part)
1995 struct stat dev_stat;
1996 int dev_major, dev_minor;
1998 if (!_device_stat (part->disk->dev, &dev_stat))
2000 dev_major = major (dev_stat.st_rdev);
2001 dev_minor = minor (dev_stat.st_rdev);
2002 return (dev_t)makedev (dev_major, dev_minor + part->num);
2006 _mount_table_search (const char* file_name, dev_t dev)
2008 struct stat part_stat;
2010 char part_name[512];
2014 file = fopen (file_name, "r");
2017 while (fgets (line, 512, file)) {
2018 junk = sscanf (line, "%s", part_name);
2019 if (stat (part_name, &part_stat) == 0) {
2020 if (part_stat.st_rdev == dev) {
2031 _partition_is_mounted_by_dev (dev_t dev)
2033 return _mount_table_search( "/proc/mounts", dev)
2034 || _mount_table_search( "/proc/swaps", dev)
2035 || _mount_table_search( "/etc/mtab", dev);
2039 _partition_is_mounted_by_path (const char *path)
2041 struct stat part_stat;
2042 if (stat (path, &part_stat) != 0)
2044 if (!S_ISBLK(part_stat.st_mode))
2046 return _partition_is_mounted_by_dev (part_stat.st_rdev);
2050 _partition_is_mounted (const PedPartition *part)
2053 if (!ped_partition_is_active (part))
2055 dev = _partition_get_part_dev (part);
2056 return _partition_is_mounted_by_dev (dev);
2060 linux_partition_is_busy (const PedPartition* part)
2064 PED_ASSERT (part != NULL, return 0);
2066 if (_partition_is_mounted (part))
2068 if (part->type == PED_PARTITION_EXTENDED) {
2069 for (walk = part->part_list; walk; walk = walk->next) {
2070 if (linux_partition_is_busy (walk))
2078 _blkpg_part_command (PedDevice* dev, struct blkpg_partition* part, int op)
2080 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2081 struct blkpg_ioctl_arg ioctl_arg;
2084 ioctl_arg.flags = 0;
2085 ioctl_arg.datalen = sizeof (struct blkpg_partition);
2086 ioctl_arg.data = (void*) part;
2088 return ioctl (arch_specific->fd, BLKPG, &ioctl_arg) == 0;
2092 _blkpg_add_partition (PedDisk* disk, PedPartition* part)
2094 struct blkpg_partition linux_part;
2095 const char* vol_name;
2098 PED_ASSERT(disk != NULL, return 0);
2099 PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0,
2102 if (ped_disk_type_check_feature (disk->type,
2103 PED_DISK_TYPE_PARTITION_NAME))
2104 vol_name = ped_partition_get_name (part);
2108 dev_name = _device_get_part_path (disk->dev, part->num);
2112 memset (&linux_part, 0, sizeof (linux_part));
2113 linux_part.start = part->geom.start * disk->dev->sector_size;
2114 /* see fs/partitions/msdos.c:msdos_partition(): "leave room for LILO" */
2115 if (part->type & PED_PARTITION_EXTENDED)
2116 linux_part.length = part->geom.length == 1 ? 512 : 1024;
2118 linux_part.length = part->geom.length * disk->dev->sector_size;
2119 linux_part.pno = part->num;
2120 strncpy (linux_part.devname, dev_name, BLKPG_DEVNAMELTH);
2122 strncpy (linux_part.volname, vol_name, BLKPG_VOLNAMELTH);
2124 ped_free (dev_name);
2126 if (!_blkpg_part_command (disk->dev, &linux_part,
2127 BLKPG_ADD_PARTITION)) {
2128 return ped_exception_throw (
2129 PED_EXCEPTION_ERROR,
2130 PED_EXCEPTION_IGNORE_CANCEL,
2131 _("Error informing the kernel about modifications to "
2132 "partition %s -- %s. This means Linux won't know "
2133 "about any changes you made to %s until you reboot "
2134 "-- so you shouldn't mount it or use it in any way "
2135 "before rebooting."),
2139 == PED_EXCEPTION_IGNORE;
2146 _blkpg_remove_partition (PedDisk* disk, int n)
2148 struct blkpg_partition linux_part;
2150 memset (&linux_part, 0, sizeof (linux_part));
2152 return _blkpg_part_command (disk->dev, &linux_part,
2153 BLKPG_DEL_PARTITION);
2157 _disk_sync_part_table (PedDisk* disk)
2160 int last = PED_MAX (ped_disk_get_last_partition_num (disk), 16);
2161 int* rets = ped_malloc(sizeof(int) * last);
2162 int* errnums = ped_malloc(sizeof(int) * last);
2165 for (i = 1; i <= last; i++) {
2166 rets[i - 1] = _blkpg_remove_partition (disk, i);
2167 errnums[i - 1] = errno;
2170 for (i = 1; i <= last; i++) {
2173 part = ped_disk_get_partition (disk, i);
2175 /* busy... so we won't (can't!) disturb ;) Prolly
2176 * doesn't matter anyway, because users shouldn't be
2177 * changing mounted partitions anyway...
2179 if (!rets[i - 1] && errnums[i - 1] == EBUSY)
2182 /* add the (possibly modified or new) partition */
2183 if (!_blkpg_add_partition (disk, part))
2191 #ifdef ENABLE_DEVICE_MAPPER
2193 _dm_remove_map_name(char *name)
2195 struct dm_task *task = NULL;
2198 task = dm_task_create(DM_DEVICE_REMOVE);
2202 dm_task_set_name (task, name);
2204 rc = dm_task_run(task);
2205 dm_task_update_nodes();
2206 dm_task_destroy(task);
2214 _dm_is_part (struct dm_info *this, char *name)
2216 struct dm_task* task = NULL;
2217 struct dm_info* info = alloca(sizeof *info);
2218 struct dm_deps* deps = NULL;
2222 task = dm_task_create(DM_DEVICE_DEPS);
2226 dm_task_set_name(task, name);
2227 rc = dm_task_run(task);
2234 memset(info, '\0', sizeof *info);
2235 dm_task_get_info(task, info);
2239 deps = dm_task_get_deps(task);
2244 for (i = 0; i < deps->count; i++) {
2245 unsigned int ma = major(deps->device[i]),
2246 mi = minor(deps->device[i]);
2248 if (ma == this->major && mi == this->minor)
2253 dm_task_destroy(task);
2258 _dm_remove_parts (PedDevice* dev)
2260 struct stat dev_stat;
2261 struct dm_task* task = NULL;
2262 struct dm_info* info = alloca(sizeof *info);
2263 struct dm_names* names = NULL;
2264 unsigned int next = 0;
2267 if (!_device_stat (dev, &dev_stat))
2270 task = dm_task_create(DM_DEVICE_LIST);
2274 dm_task_set_major (task, major (dev_stat.st_rdev));
2275 dm_task_set_minor (task, minor (dev_stat.st_rdev));
2277 rc = dm_task_run(task);
2281 memset(info, '\0', sizeof *info);
2282 dm_task_get_info(task, info);
2286 names = dm_task_get_names(task);
2292 names = (void *)names + next;
2294 if (_dm_is_part(info, names->name))
2295 rc += _dm_remove_map_name(names->name);
2300 dm_task_update_nodes();
2301 dm_task_destroy(task);
2308 dm_task_destroy(task);
2309 ped_exception_throw (PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE,
2310 _("parted was unable to re-read the partition "
2311 "table on %s (%s). This means Linux won't know "
2312 "anything about the modifications you made. "),
2313 dev->path, strerror (errno));
2318 _dm_add_partition (PedDisk* disk, PedPartition* part)
2320 struct stat dev_stat;
2321 struct dm_task* task = NULL;
2323 char* vol_name = NULL;
2324 char* dev_name = NULL;
2325 char* params = NULL;
2327 dev_name = _device_get_part_path (disk->dev, part->num);
2331 vol_name = strrchr (dev_name, '/');
2332 if (vol_name && *vol_name && *(++vol_name))
2333 vol_name = strdup (vol_name);
2335 vol_name = strdup (dev_name);
2339 if (!_device_stat (disk->dev, &dev_stat))
2342 if (asprintf (¶ms, "%d:%d %lld", major (dev_stat.st_rdev),
2343 minor (dev_stat.st_rdev), part->geom.start) == -1)
2349 task = dm_task_create (DM_DEVICE_CREATE);
2353 dm_task_set_name (task, vol_name);
2354 dm_task_add_target (task, 0, part->geom.length,
2356 rc = dm_task_run(task);
2358 //printf("0 %ld linear %s\n", part->geom.length, params);
2359 dm_task_update_nodes();
2360 dm_task_destroy(task);
2365 _dm_remove_map_name(vol_name);
2368 dm_task_update_nodes();
2370 dm_task_destroy (task);
2378 _dm_reread_part_table (PedDisk* disk)
2381 int last = PED_MAX (ped_disk_get_last_partition_num (disk), 16);
2385 if (!_dm_remove_parts(disk->dev))
2388 for (i = 1; i <= last; i++) {
2391 part = ped_disk_get_partition (disk, i);
2395 if (!_dm_add_partition (disk, part))
2403 _kernel_reread_part_table (PedDevice* dev)
2405 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2406 int retry_count = 5;
2409 while (ioctl (arch_specific->fd, BLKRRPART)) {
2413 ped_exception_throw (
2414 PED_EXCEPTION_WARNING,
2415 PED_EXCEPTION_IGNORE,
2416 _("The kernel was unable to re-read the partition "
2417 "table on %s (%s). This means Linux won't know "
2418 "anything about the modifications you made "
2419 "until you reboot. You should reboot your computer "
2420 "before doing anything with %s."),
2421 dev->path, strerror (errno), dev->path);
2432 static int have_blkpg = -1;
2435 if (have_blkpg != -1)
2438 kver = _get_linux_version();
2439 return have_blkpg = kver >= KERNEL_VERSION (2,4,0) ? 1 : 0;
2443 linux_disk_commit (PedDisk* disk)
2445 #ifdef ENABLE_DEVICE_MAPPER
2446 if (disk->dev->type == PED_DEVICE_DM)
2447 return _dm_reread_part_table (disk);
2449 if (disk->dev->type != PED_DEVICE_FILE) {
2450 /* The ioctl() command BLKPG_ADD_PARTITION does not notify
2451 * the devfs system; consequently, /proc/partitions will not
2452 * be up to date, and the proper links in /dev are not
2453 * created. Therefore, if using DevFS, we must get the kernel
2454 * to re-read and grok the partition table.
2456 /* Work around kernel dasd problem so we really do BLKRRPART */
2457 if (disk->dev->type != PED_DEVICE_DASD &&
2458 _have_blkpg () && !_have_devfs ()) {
2459 if (_disk_sync_part_table (disk))
2463 return _kernel_reread_part_table (disk->dev);
2469 static PedDeviceArchOps linux_dev_ops = {
2471 destroy: linux_destroy,
2472 is_busy: linux_is_busy,
2474 refresh_open: linux_refresh_open,
2476 refresh_close: linux_refresh_close,
2481 sync_fast: linux_sync_fast,
2482 probe_all: linux_probe_all
2485 PedDiskArchOps linux_disk_ops = {
2486 partition_get_path: linux_partition_get_path,
2487 partition_is_busy: linux_partition_is_busy,
2488 disk_commit: linux_disk_commit
2491 PedArchitecture ped_linux_arch = {
2492 dev_ops: &linux_dev_ops,
2493 disk_ops: &linux_disk_ops