1 /* libparted - a library for manipulating disk partitions
2 Copyright (C) 1999 - 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #define PROC_DEVICES_BUFSIZ 16384
22 #include <parted/parted.h>
23 #include <parted/debug.h>
34 #include <sys/ioctl.h>
36 #include <sys/types.h>
37 #include <sys/utsname.h> /* for uname() */
38 #include <scsi/scsi.h>
39 #ifdef ENABLE_DEVICE_MAPPER
40 #include <libdevmapper.h>
44 #include "../architecture.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)
77 #if defined(__s390__) || defined(__s390x__)
78 # include <parted/fdasd.h>
81 #define LINUX_SPECIFIC(dev) ((LinuxSpecific*) (dev)->arch_specific)
83 typedef struct _LinuxSpecific LinuxSpecific;
85 struct _LinuxSpecific {
87 char* dmtype; /**< device map target type */
88 #if defined(__s390__) || defined(__s390x__)
89 unsigned int real_sector_size;
90 /* IBM internal dasd structure (i guess ;), required. */
91 struct fdasd_anchor *anchor;
97 unsigned char sectors;
98 unsigned short cylinders;
102 struct ata7_sectinfo {
109 /* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
111 unsigned short config; /* lots of obsolete bit flags */
112 unsigned short cyls; /* "physical" cyls */
113 unsigned short reserved2; /* reserved (word 2) */
114 unsigned short heads; /* "physical" heads */
115 unsigned short track_bytes; /* unformatted bytes per track */
116 unsigned short sector_bytes; /* unformatted bytes per sector */
117 unsigned short sectors; /* "physical" sectors per track */
118 unsigned short vendor0; /* vendor unique */
119 unsigned short vendor1; /* vendor unique */
120 unsigned short vendor2; /* vendor unique */
121 unsigned char serial_no[20]; /* 0 = not_specified */
122 unsigned short buf_type;
123 unsigned short buf_size; /* 512 byte increments;
125 unsigned short ecc_bytes; /* for r/w long cmds;
127 unsigned char fw_rev[8]; /* 0 = not_specified */
128 char model[40]; /* 0 = not_specified */
129 unsigned char max_multsect; /* 0=not_implemented */
130 unsigned char vendor3; /* vendor unique */
131 unsigned short dword_io; /* 0=not_implemented; 1=implemented */
132 unsigned char vendor4; /* vendor unique */
133 unsigned char capability; /* bits 0:DMA 1:LBA 2:IORDYsw
135 unsigned short reserved50; /* reserved (word 50) */
136 unsigned char vendor5; /* vendor unique */
137 unsigned char tPIO; /* 0=slow, 1=medium, 2=fast */
138 unsigned char vendor6; /* vendor unique */
139 unsigned char tDMA; /* 0=slow, 1=medium, 2=fast */
140 unsigned short field_valid; /* bits 0:cur_ok 1:eide_ok */
141 unsigned short cur_cyls; /* logical cylinders */
142 unsigned short cur_heads; /* logical heads */
143 unsigned short cur_sectors; /* logical sectors per track */
144 unsigned short cur_capacity0; /* logical total sectors on drive */
145 unsigned short cur_capacity1; /* (2 words, misaligned int) */
146 unsigned char multsect; /* current multiple sector count */
147 unsigned char multsect_valid; /* when (bit0==1) multsect is ok */
148 unsigned int lba_capacity; /* total number of sectors */
149 unsigned short dma_1word; /* single-word dma info */
150 unsigned short dma_mword; /* multiple-word dma info */
151 unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */
152 unsigned short eide_dma_min; /* min mword dma cycle time (ns) */
153 unsigned short eide_dma_time; /* recommended mword dma cycle
155 unsigned short eide_pio; /* min cycle time (ns), no IORDY */
156 unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */
157 unsigned short words69_70[2]; /* reserved words 69-70 */
158 /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
159 unsigned short words71_74[4]; /* reserved words 71-74 */
160 unsigned short queue_depth; /* */
161 unsigned short words76_79[4]; /* reserved words 76-79 */
162 unsigned short major_rev_num; /* */
163 unsigned short minor_rev_num; /* */
164 unsigned short command_set_1; /* bits 0:Smart 1:Security 2:Removable
166 unsigned short command_set_2; /* bits 14:Smart Enabled 13:0 zero */
167 unsigned short cfsse; /* command set-feature supported
169 unsigned short cfs_enable_1; /* command set-feature enabled */
170 unsigned short cfs_enable_2; /* command set-feature enabled */
171 unsigned short csf_default; /* command set-feature default */
172 unsigned short dma_ultra; /* */
173 unsigned short word89; /* reserved (word 89) */
174 unsigned short word90; /* reserved (word 90) */
175 unsigned short CurAPMvalues; /* current APM values */
176 unsigned short word92; /* reserved (word 92) */
177 unsigned short hw_config; /* hardware config */
178 unsigned short words94_105[12];/* reserved words 94-105 */
179 struct ata7_sectinfo ata7_sectinfo; /* ATAPI/ATA7 physical and logical
181 unsigned short words107_116[10];/* reserved words 107-116 */
182 unsigned int logical_sectsize;/* ATAPI/ATA7 logical sector size */
183 unsigned short words119_125[7];/* reserved words 119-125 */
184 unsigned short last_lun; /* reserved (word 126) */
185 unsigned short word127; /* reserved (word 127) */
186 unsigned short dlf; /* device lock function
188 * 8 security level 1:max 0:high
197 unsigned short csfo; /* current set features options
204 unsigned short words130_155[26];/* reserved vendor words 130-155 */
205 unsigned short word156;
206 unsigned short words157_159[3]; /* reserved vendor words 157-159 */
207 unsigned short words160_255[95];/* reserved words 160-255 */
210 /* from <linux/fs.h> */
211 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
212 #define BLKGETSIZE _IO(0x12,96) /* return device size */
213 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
214 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
215 #define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
216 #define BLKSETLASTSECT _IO(0x12,109) /* set last sector of block device */
218 /* return device size in bytes (u64 *arg) */
219 #define BLKGETSIZE64 _IOR(0x12,114,size_t)
221 struct blkdev_ioctl_param {
223 size_t content_length;
224 char * block_contents;
227 /* from <linux/major.h> */
229 #define IDE1_MAJOR 22
230 #define IDE2_MAJOR 33
231 #define IDE3_MAJOR 34
232 #define IDE4_MAJOR 56
233 #define IDE5_MAJOR 57
234 #define SCSI_CDROM_MAJOR 11
235 #define SCSI_DISK0_MAJOR 8
236 #define SCSI_DISK1_MAJOR 65
237 #define SCSI_DISK2_MAJOR 66
238 #define SCSI_DISK3_MAJOR 67
239 #define SCSI_DISK4_MAJOR 68
240 #define SCSI_DISK5_MAJOR 69
241 #define SCSI_DISK6_MAJOR 70
242 #define SCSI_DISK7_MAJOR 71
243 #define COMPAQ_SMART2_MAJOR 72
244 #define COMPAQ_SMART2_MAJOR1 73
245 #define COMPAQ_SMART2_MAJOR2 74
246 #define COMPAQ_SMART2_MAJOR3 75
247 #define COMPAQ_SMART2_MAJOR4 76
248 #define COMPAQ_SMART2_MAJOR5 77
249 #define COMPAQ_SMART2_MAJOR6 78
250 #define COMPAQ_SMART2_MAJOR7 79
251 #define COMPAQ_SMART_MAJOR 104
252 #define COMPAQ_SMART_MAJOR1 105
253 #define COMPAQ_SMART_MAJOR2 106
254 #define COMPAQ_SMART_MAJOR3 107
255 #define COMPAQ_SMART_MAJOR4 108
256 #define COMPAQ_SMART_MAJOR5 109
257 #define COMPAQ_SMART_MAJOR6 110
258 #define COMPAQ_SMART_MAJOR7 111
259 #define DAC960_MAJOR 48
260 #define ATARAID_MAJOR 114
261 #define I2O_MAJOR1 80
262 #define I2O_MAJOR2 81
263 #define I2O_MAJOR3 82
264 #define I2O_MAJOR4 83
265 #define I2O_MAJOR5 84
266 #define I2O_MAJOR6 85
267 #define I2O_MAJOR7 86
268 #define I2O_MAJOR8 87
270 #define DASD_MAJOR 94
271 #define VIODASD_MAJOR 112
272 #define SX8_MAJOR1 160
273 #define SX8_MAJOR2 161
274 #define XVD_MAJOR 202
275 #define SDMMC_MAJOR 179
277 #define SCSI_BLK_MAJOR(M) ( \
278 (M) == SCSI_DISK0_MAJOR \
279 || (M) == SCSI_CDROM_MAJOR \
280 || ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
282 static char* _device_get_part_path (PedDevice* dev, int num);
283 static int _partition_is_mounted_by_path (const char* path);
286 _is_ide_major (int major)
303 _is_cpqarray_major (int major)
305 return ((COMPAQ_SMART2_MAJOR <= major && major <= COMPAQ_SMART2_MAJOR7)
306 || (COMPAQ_SMART_MAJOR <= major && major <= COMPAQ_SMART_MAJOR7));
310 _is_i2o_major (int major)
312 return (I2O_MAJOR1 <= major && major <= I2O_MAJOR8);
316 _is_sx8_major (int major)
318 return (SX8_MAJOR1 <= major && major <= SX8_MAJOR2);
321 #ifdef ENABLE_DEVICE_MAPPER
323 _dm_maptype (PedDevice *dev)
325 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
328 uint64_t start, length;
329 char *target_type = NULL;
332 const char* dev_dir = getenv ("DM_DEV_DIR");
334 if (dev_dir && *dev_dir && !dm_set_dev_dir(dev_dir))
337 if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
340 if (!dm_task_set_name(dmt, dev->path))
343 dm_task_no_open_count(dmt);
345 if (!dm_task_run(dmt))
348 next = dm_get_next_target(dmt, NULL, &start, &length,
349 &target_type, ¶ms);
351 arch_specific->dmtype = strdup(target_type);
352 if (arch_specific->dmtype == NULL)
356 dm_task_destroy(dmt);
361 readFD (int fd, char **buf)
364 size_t size = PROC_DEVICES_BUFSIZ;
367 *buf = malloc (size * sizeof (char));
373 p = &(*buf) [filesize];
374 s = read (fd, p, PROC_DEVICES_BUFSIZ);
375 /* exit if there is an error or EOF is reached */
380 *buf = realloc (*buf, size);
383 if (filesize == 0 && s < 0) {
388 /* there is always some excess memory left unused */
389 *buf = realloc (*buf, filesize+1);
390 (*buf)[filesize] = '\0';
397 _is_dm_major (int major)
406 fd = open ("/proc/devices", O_RDONLY);
410 if (readFD(fd, &buf) < 0) {
416 end = strchr(line, '\n');
425 if (!strncmp(line, "Block devices:", 14))
430 name = strrchr(line, ' ');
431 if (!name || strcmp(name+1, "device-mapper"))
434 maj = strtol(line, &name, 10);
444 end = strchr(line, '\n');
456 char buf [512]; /* readdir(3) claims d_name[256] */
459 mapper_dir = opendir ("/dev/mapper");
463 /* Search the /dev/mapper directory for devices w/ the same major
464 * number that was returned from _probe_lvm_major().
466 while ((dent = readdir (mapper_dir))) {
467 if (strcmp (dent->d_name, ".") == 0 ||
468 strcmp (dent->d_name, "..") == 0)
471 snprintf (buf, sizeof (buf), "/dev/mapper/%s", dent->d_name);
473 if (stat (buf, &st) != 0)
476 if (_is_dm_major(major(st.st_rdev)))
477 _ped_device_probe (buf);
479 closedir (mapper_dir);
486 _device_stat (PedDevice* dev, struct stat * dev_stat)
488 PED_ASSERT (dev != NULL, return 0);
489 PED_ASSERT (!dev->external_mode, return 0);
492 if (!stat (dev->path, dev_stat)) {
495 if (ped_exception_throw (
497 PED_EXCEPTION_RETRY_CANCEL,
498 _("Could not stat device %s - %s."),
501 != PED_EXCEPTION_RETRY)
508 _device_probe_type (PedDevice* dev)
510 struct stat dev_stat;
514 if (!_device_stat (dev, &dev_stat))
517 if (!S_ISBLK(dev_stat.st_mode)) {
518 dev->type = PED_DEVICE_FILE;
522 dev_major = major (dev_stat.st_rdev);
523 dev_minor = minor (dev_stat.st_rdev);
525 if (SCSI_BLK_MAJOR (dev_major) && (dev_minor % 0x10 == 0)) {
526 dev->type = PED_DEVICE_SCSI;
527 } else if (_is_ide_major (dev_major) && (dev_minor % 0x40 == 0)) {
528 dev->type = PED_DEVICE_IDE;
529 } else if (dev_major == DAC960_MAJOR && (dev_minor % 0x8 == 0)) {
530 dev->type = PED_DEVICE_DAC960;
531 } else if (dev_major == ATARAID_MAJOR && (dev_minor % 0x10 == 0)) {
532 dev->type = PED_DEVICE_ATARAID;
533 } else if (dev_major == DASD_MAJOR && (dev_minor % 0x4 == 0)) {
534 dev->type = PED_DEVICE_DASD;
535 } else if (dev_major == VIODASD_MAJOR && (dev_minor % 0x8 == 0)) {
536 dev->type = PED_DEVICE_VIODASD;
537 } else if (_is_sx8_major(dev_major) && (dev_minor % 0x20 == 0)) {
538 dev->type = PED_DEVICE_SX8;
539 } else if (_is_i2o_major (dev_major) && (dev_minor % 0x10 == 0)) {
540 dev->type = PED_DEVICE_I2O;
541 } else if (_is_cpqarray_major (dev_major) && (dev_minor % 0x10 == 0)) {
542 dev->type = PED_DEVICE_CPQARRAY;
543 } else if (dev_major == UBD_MAJOR && (dev_minor % 0x10 == 0)) {
544 dev->type = PED_DEVICE_UBD;
545 #ifdef ENABLE_DEVICE_MAPPER
546 } else if (_is_dm_major(dev_major)) {
547 dev->type = PED_DEVICE_DM;
548 if (_dm_maptype(dev)) {
549 ped_exception_throw (
551 PED_EXCEPTION_CANCEL,
552 _("Unable to determine the dm type of %s."),
556 } else if (dev_major == XVD_MAJOR && (dev_minor % 0x10 == 0)) {
557 dev->type = PED_DEVICE_XVD;
558 } else if (dev_major == SDMMC_MAJOR && (dev_minor % 0x08 == 0)) {
559 dev->type = PED_DEVICE_SDMMC;
561 dev->type = PED_DEVICE_UNKNOWN;
568 _get_linux_version ()
570 static int kver = -1;
582 if (sscanf (uts.release, "%u.%u.%u", &major, &minor, &teeny) != 3)
585 return kver = KERNEL_VERSION (major, minor, teeny);
591 static int have_devfs = -1;
594 if (have_devfs != -1)
597 /* the presence of /dev/.devfsd implies that DevFS is active */
598 if (stat("/dev/.devfsd", &sb) < 0)
599 return have_devfs = 0;
601 return have_devfs = S_ISCHR(sb.st_mode) ? 1 : 0;
605 _device_set_sector_size (PedDevice* dev)
607 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
610 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
611 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
613 PED_ASSERT (dev->open_count, return);
615 if (_get_linux_version() < KERNEL_VERSION (2,3,0)) {
616 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
620 if (ioctl (arch_specific->fd, BLKSSZGET, §or_size)) {
621 ped_exception_throw (
622 PED_EXCEPTION_WARNING,
624 _("Could not determine sector size for %s: %s.\n"
625 "Using the default sector size (%lld)."),
626 dev->path, strerror (errno), PED_SECTOR_SIZE_DEFAULT);
628 dev->sector_size = (long long)sector_size;
631 /* Return PED_SECTOR_SIZE_DEFAULT for DASDs. */
632 if (dev->type == PED_DEVICE_DASD) {
633 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
636 if (dev->sector_size != PED_SECTOR_SIZE_DEFAULT) {
637 ped_exception_throw (
638 PED_EXCEPTION_WARNING,
640 _("Device %s has a logical sector size of %lld. Not "
641 "all parts of GNU Parted support this at the moment, "
642 "and the working code is HIGHLY EXPERIMENTAL.\n"),
643 dev->path, dev->sector_size);
648 _kernel_has_blkgetsize64(void)
650 int version = _get_linux_version();
652 if (version >= KERNEL_VERSION (2,5,4)) return 1;
653 if (version < KERNEL_VERSION (2,5,0) &&
654 version >= KERNEL_VERSION (2,4,18)) return 1;
658 /* TODO: do a binary search if BLKGETSIZE doesn't work?! */
660 _device_get_length (PedDevice* dev)
663 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
667 PED_ASSERT (dev->open_count > 0, return 0);
668 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
670 if (_kernel_has_blkgetsize64()) {
671 if (ioctl(arch_specific->fd, BLKGETSIZE64, &bytes) == 0) {
672 return bytes / dev->sector_size;
676 if (ioctl (arch_specific->fd, BLKGETSIZE, &size)) {
677 ped_exception_throw (
679 PED_EXCEPTION_CANCEL,
680 _("Unable to determine the size of %s (%s)."),
690 _device_probe_geometry (PedDevice* dev)
692 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
693 struct stat dev_stat;
694 struct hd_geometry geometry;
696 if (!_device_stat (dev, &dev_stat))
698 PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
700 _device_set_sector_size (dev);
702 dev->length = _device_get_length (dev);
706 /* The GETGEO ioctl is no longer useful (as of linux 2.6.x). We could
707 * still use it in 2.4.x, but this is contentious. Perhaps we should
709 dev->bios_geom.sectors = 63;
710 dev->bios_geom.heads = 255;
711 dev->bios_geom.cylinders
712 = dev->length / (63 * 255);
714 /* FIXME: what should we put here? (TODO: discuss on linux-kernel) */
715 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geometry)
716 && geometry.sectors && geometry.heads) {
717 dev->hw_geom.sectors = geometry.sectors;
718 dev->hw_geom.heads = geometry.heads;
719 dev->hw_geom.cylinders
720 = dev->length / (dev->hw_geom.heads
721 * dev->hw_geom.sectors);
723 dev->hw_geom = dev->bios_geom;
730 strip_name(char* str)
735 for (i = 0; str[i] != 0; i++) {
736 if (!isspace (str[i])
737 || (isspace (str[i]) && !isspace (str[i+1]) && str[i+1])) {
747 init_ide (PedDevice* dev)
749 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
750 struct stat dev_stat;
752 struct hd_driveid hdi;
753 PedExceptionOption ex_status;
755 int sector_multiplier = 0;
757 if (!_device_stat (dev, &dev_stat))
760 dev_major = major (dev_stat.st_rdev);
762 if (!ped_device_open (dev))
765 if (ioctl (arch_specific->fd, HDIO_GET_IDENTITY, &hdi)) {
766 ex_status = ped_exception_throw (
767 PED_EXCEPTION_WARNING,
768 PED_EXCEPTION_IGNORE_CANCEL,
769 _("Could not get identity of device %s - %s"),
770 dev->path, strerror (errno));
772 case PED_EXCEPTION_CANCEL:
773 goto error_close_dev;
775 case PED_EXCEPTION_UNHANDLED:
776 ped_exception_catch ();
777 case PED_EXCEPTION_IGNORE:
778 dev->model = strdup(_("Generic IDE"));
781 PED_ASSERT (0, (void) 0);
785 /* hdi.model is not guaranteed to be NULL terminated */
786 memcpy (hdi_buf, hdi.model, 40);
788 dev->model = strip_name (hdi_buf);
790 if (!hdi.ata7_sectinfo.valid1 && hdi.ata7_sectinfo.valid2)
791 sector_multiplier = hdi.ata7_sectinfo.multiplier;
793 sector_multiplier = 1;
795 if (sector_multiplier != 1) {
796 ex_status = ped_exception_throw (
797 PED_EXCEPTION_WARNING,
798 PED_EXCEPTION_IGNORE_CANCEL,
799 _("Device %s has multiple (%d) logical sectors "
800 "per physical sector.\n"
801 "GNU Parted supports this EXPERIMENTALLY for "
802 "some special disk label/file system "
803 "combinations, e.g. GPT and ext2/3.\n"
804 "Please consult the web site for up-to-date "
806 dev->path, sector_multiplier);
809 case PED_EXCEPTION_CANCEL:
810 goto error_close_dev;
812 case PED_EXCEPTION_UNHANDLED:
813 ped_exception_catch ();
814 case PED_EXCEPTION_IGNORE:
817 PED_ASSERT (0, (void) 0);
822 /* XXX sector_size has not been set yet! */
823 /* dev->phys_sector_size = dev->sector_size
824 * sector_multiplier;*/
825 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
828 if (!_device_probe_geometry (dev))
829 goto error_close_dev;
831 ped_device_close (dev);
835 ped_device_close (dev);
840 /* This function reads the /sys entry named "file" for device "dev". */
842 read_device_sysfs_file (PedDevice *dev, const char *file)
848 snprintf (name_buf, 127, "/sys/block/%s/device/%s",
849 basename (dev->path), file);
851 if ((f = fopen (name_buf, "r")) == NULL)
854 if (fgets (buf, 255, f) == NULL)
858 return strip_name (buf);
861 /* This function sends a query to a SCSI device for vendor and product
862 * information. It uses the deprecated SCSI_IOCTL_SEND_COMMAND to
866 scsi_query_product_info (PedDevice* dev, char **vendor, char **product)
868 /* The following are defined by the SCSI-2 specification. */
869 typedef struct _scsi_inquiry_cmd
872 uint8_t lun; /* bits 5-7 denote the LUN */
875 uint8_t alloc_length;
877 } __attribute__((packed)) scsi_inquiry_cmd_t;
879 typedef struct _scsi_inquiry_data
881 uint8_t peripheral_info;
883 uint8_t version_info;
885 uint8_t additional_length;
889 uint8_t vendor_id[8];
890 uint8_t product_id[16];
891 uint8_t product_revision[4];
892 uint8_t vendor_specific[20];
893 uint8_t _reserved3[40];
894 } __attribute__((packed)) scsi_inquiry_data_t;
903 scsi_inquiry_data_t out;
904 scsi_inquiry_cmd_t in;
908 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
914 memset (&arg, 0x00, sizeof(struct scsi_arg));
916 arg.outlen = sizeof(scsi_inquiry_data_t);
917 arg.data.in.op = INQUIRY;
918 arg.data.in.lun = dev->host << 5;
919 arg.data.in.alloc_length = sizeof(scsi_inquiry_data_t);
920 arg.data.in.page_code = 0;
921 arg.data.in.reserved = 0;
922 arg.data.in.control = 0;
924 if (ioctl (arch_specific->fd, SCSI_IOCTL_SEND_COMMAND, &arg) < 0)
927 memcpy (buf, arg.data.out.vendor_id, 8);
929 *vendor = strip_name (buf);
931 memcpy (buf, arg.data.out.product_id, 16);
933 *product = strip_name (buf);
938 /* This function provides the vendor and product name for a SCSI device.
939 * It supports both the modern /sys interface and direct queries
940 * via the deprecated ioctl, SCSI_IOCTL_SEND_COMMAND.
943 scsi_get_product_info (PedDevice* dev, char **vendor, char **product)
945 *vendor = read_device_sysfs_file (dev, "vendor");
946 *product = read_device_sysfs_file (dev, "model");
947 if (*vendor && *product)
950 return scsi_query_product_info (dev, vendor, product);
954 init_scsi (PedDevice* dev)
959 uint32_t host_unique_id;
962 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
966 if (!ped_device_open (dev))
969 if (ioctl (arch_specific->fd, SCSI_IOCTL_GET_IDLUN, &idlun) < 0) {
972 if (ped_exception_throw (
973 PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
974 _("Error initialising SCSI device %s - %s"),
975 dev->path, strerror (errno))
976 != PED_EXCEPTION_IGNORE)
977 goto error_close_dev;
978 if (!_device_probe_geometry (dev))
979 goto error_close_dev;
980 ped_device_close (dev);
984 dev->host = idlun.host_unique_id;
985 dev->did = idlun.dev_id;
987 dev->model = (char*) ped_malloc (8 + 16 + 2);
989 goto error_close_dev;
991 if (scsi_get_product_info (dev, &vendor, &product)) {
992 sprintf (dev->model, "%.8s %.16s", vendor, product);
996 strcpy (dev->model, "Generic SCSI");
999 if (!_device_probe_geometry (dev))
1000 goto error_close_dev;
1002 ped_device_close (dev);
1006 ped_device_close (dev);
1012 init_file (PedDevice* dev)
1014 struct stat dev_stat;
1016 if (!_device_stat (dev, &dev_stat))
1018 if (!ped_device_open (dev))
1021 if (S_ISBLK(dev_stat.st_mode))
1022 dev->length = _device_get_length (dev);
1024 dev->length = dev_stat.st_size / 512;
1025 if (dev->length <= 0) {
1026 ped_exception_throw (
1027 PED_EXCEPTION_ERROR,
1028 PED_EXCEPTION_CANCEL,
1029 _("The device %s has zero length, and can't possibly "
1030 "store a file system or partition table. Perhaps "
1031 "you selected the wrong device?"),
1033 goto error_close_dev;
1036 ped_device_close (dev);
1038 dev->bios_geom.cylinders = dev->length / 4 / 32;
1039 dev->bios_geom.heads = 4;
1040 dev->bios_geom.sectors = 32;
1041 dev->hw_geom = dev->bios_geom;
1042 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1043 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
1044 dev->model = strdup ("");
1049 ped_device_close (dev);
1055 init_dasd (PedDevice* dev, const char* model_name)
1057 struct stat dev_stat;
1058 struct hd_geometry geo;
1061 if (!_device_stat (dev, &dev_stat))
1064 if (!ped_device_open (dev))
1067 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1069 PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
1071 _device_set_sector_size (dev);
1072 if (!dev->sector_size)
1073 goto error_close_dev;
1075 dev->length = _device_get_length (dev);
1077 goto error_close_dev;
1079 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geo)) {
1080 dev->hw_geom.sectors = geo.sectors;
1081 dev->hw_geom.heads = geo.heads;
1082 dev->hw_geom.cylinders = dev->length
1083 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1084 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1085 dev->bios_geom = dev->hw_geom;
1087 dev->bios_geom.sectors = 12;
1088 dev->bios_geom.heads = 15;
1089 dev->bios_geom.cylinders = dev->length
1090 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1091 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1092 dev->hw_geom = dev->bios_geom;
1095 dev->model = strdup (model_name);
1097 ped_device_close (dev);
1100 ped_exception_throw ( PED_EXCEPTION_ERROR,
1101 PED_EXCEPTION_IGNORE_CANCEL,
1105 ped_device_close (dev);
1111 init_generic (PedDevice* dev, const char* model_name)
1113 struct stat dev_stat;
1114 PedExceptionOption ex_status;
1116 if (!_device_stat (dev, &dev_stat))
1119 if (!ped_device_open (dev))
1122 ped_exception_fetch_all ();
1123 if (_device_probe_geometry (dev)) {
1124 ped_exception_leave_all ();
1126 /* hack to allow use of files, for testing */
1127 ped_exception_catch ();
1128 ped_exception_leave_all ();
1130 ex_status = ped_exception_throw (
1131 PED_EXCEPTION_WARNING,
1132 PED_EXCEPTION_IGNORE_CANCEL,
1133 _("Unable to determine geometry of "
1134 "file/device %s. You should not use Parted "
1135 "unless you REALLY know what you're doing!"),
1137 switch (ex_status) {
1138 case PED_EXCEPTION_CANCEL:
1139 goto error_close_dev;
1141 case PED_EXCEPTION_UNHANDLED:
1142 ped_exception_catch ();
1143 case PED_EXCEPTION_IGNORE:
1146 PED_ASSERT (0, (void) 0);
1150 /* what should we stick in here? */
1151 dev->length = dev_stat.st_size / PED_SECTOR_SIZE_DEFAULT;
1152 dev->bios_geom.cylinders = dev->length / 4 / 32;
1153 dev->bios_geom.heads = 4;
1154 dev->bios_geom.sectors = 32;
1155 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1156 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
1159 dev->model = strdup (model_name);
1161 ped_device_close (dev);
1165 ped_device_close (dev);
1171 sdmmc_get_product_info (PedDevice* dev, char **type, char **name)
1173 *type = read_device_sysfs_file (dev, "type");
1174 *name = read_device_sysfs_file (dev, "name");
1182 init_sdmmc (PedDevice* dev)
1187 if (sdmmc_get_product_info (dev, &type, &name)) {
1188 snprintf (id, sizeof(id) - 1, "%s %s", type, name);
1192 snprintf (id, sizeof(id) - 1, "%s",
1193 _("Generic SD/MMC Storage Card"));
1195 return init_generic(dev, id);
1199 linux_new (const char* path)
1202 LinuxSpecific* arch_specific;
1204 PED_ASSERT (path != NULL, return NULL);
1206 dev = (PedDevice*) ped_malloc (sizeof (PedDevice));
1210 dev->path = strdup (path);
1212 goto error_free_dev;
1215 = (LinuxSpecific*) ped_malloc (sizeof (LinuxSpecific));
1216 if (!dev->arch_specific)
1217 goto error_free_path;
1218 arch_specific = LINUX_SPECIFIC (dev);
1219 arch_specific->dmtype = NULL;
1221 dev->open_count = 0;
1223 dev->external_mode = 0;
1225 dev->boot_dirty = 0;
1227 if (!_device_probe_type (dev))
1228 goto error_free_arch_specific;
1230 switch (dev->type) {
1231 case PED_DEVICE_IDE:
1232 if (!init_ide (dev))
1233 goto error_free_arch_specific;
1236 case PED_DEVICE_SCSI:
1237 if (!init_scsi (dev))
1238 goto error_free_arch_specific;
1241 case PED_DEVICE_DAC960:
1242 if (!init_generic (dev, _("DAC960 RAID controller")))
1243 goto error_free_arch_specific;
1246 case PED_DEVICE_SX8:
1247 if (!init_generic (dev, _("Promise SX8 SATA Device")))
1248 goto error_free_arch_specific;
1251 case PED_DEVICE_DASD:
1252 if (!init_dasd (dev, _("IBM S390 DASD drive")))
1253 goto error_free_arch_specific;
1256 case PED_DEVICE_VIODASD:
1257 if (!init_generic (dev, _("IBM iSeries Virtual DASD")))
1258 goto error_free_arch_specific;
1261 case PED_DEVICE_CPQARRAY:
1262 if (!init_generic (dev, _("Compaq Smart Array")))
1263 goto error_free_arch_specific;
1266 case PED_DEVICE_ATARAID:
1267 if (!init_generic (dev, _("ATARAID Controller")))
1268 goto error_free_arch_specific;
1271 case PED_DEVICE_I2O:
1272 if (!init_generic (dev, _("I2O Controller")))
1273 goto error_free_arch_specific;
1276 case PED_DEVICE_UBD:
1277 if (!init_generic (dev, _("User-Mode Linux UBD")))
1278 goto error_free_arch_specific;
1281 case PED_DEVICE_FILE:
1282 if (!init_file (dev))
1283 goto error_free_arch_specific;
1289 if (arch_specific->dmtype == NULL
1290 || asprintf(&type, _("Linux device-mapper (%s)"),
1291 arch_specific->dmtype) == -1)
1292 goto error_free_arch_specific;
1293 bool ok = init_generic (dev, type);
1296 goto error_free_arch_specific;
1300 case PED_DEVICE_XVD:
1301 if (!init_generic (dev, _("Xen Virtual Block Device")))
1302 goto error_free_arch_specific;
1305 case PED_DEVICE_UNKNOWN:
1306 if (!init_generic (dev, _("Unknown")))
1307 goto error_free_arch_specific;
1310 case PED_DEVICE_SDMMC:
1311 if (!init_sdmmc (dev))
1312 goto error_free_arch_specific;
1316 ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
1317 PED_EXCEPTION_CANCEL,
1318 _("ped_device_new() Unsupported device type"));
1319 goto error_free_arch_specific;
1323 error_free_arch_specific:
1324 free (dev->arch_specific);
1334 linux_destroy (PedDevice* dev)
1336 free (((LinuxSpecific*)dev->arch_specific)->dmtype);
1337 free (dev->arch_specific);
1344 linux_is_busy (PedDevice* dev)
1349 if (_partition_is_mounted_by_path (dev->path))
1352 for (i = 0; i < 32; i++) {
1355 part_name = _device_get_part_path (dev, i);
1358 status = _partition_is_mounted_by_path (part_name);
1368 /* we need to flush the master device, and all the partition devices,
1369 * because there is no coherency between the caches.
1370 * We should only flush unmounted partition devices, because:
1371 * - there is never a need to flush them (we're not doing IO there)
1372 * - flushing a device that is mounted causes unnecessary IO, and can
1373 * even screw journaling & friends up. Even cause oopsen!
1376 _flush_cache (PedDevice* dev)
1378 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1385 ioctl (arch_specific->fd, BLKFLSBUF);
1387 for (i = 1; i < 16; i++) {
1391 name = _device_get_part_path (dev, i);
1394 if (!_partition_is_mounted_by_path (name)) {
1395 fd = open (name, WR_MODE, 0);
1397 ioctl (fd, BLKFLSBUF);
1406 linux_open (PedDevice* dev)
1408 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1411 arch_specific->fd = open (dev->path, RW_MODE);
1413 if (arch_specific->fd == -1) {
1414 char* rw_error_msg = strerror (errno);
1416 arch_specific->fd = open (dev->path, RD_MODE);
1418 if (arch_specific->fd == -1) {
1419 if (ped_exception_throw (
1420 PED_EXCEPTION_ERROR,
1421 PED_EXCEPTION_RETRY_CANCEL,
1422 _("Error opening %s: %s"),
1423 dev->path, strerror (errno))
1424 != PED_EXCEPTION_RETRY) {
1430 ped_exception_throw (
1431 PED_EXCEPTION_WARNING,
1433 _("Unable to open %s read-write (%s). %s has "
1434 "been opened read-only."),
1435 dev->path, rw_error_msg, dev->path);
1448 linux_refresh_open (PedDevice* dev)
1454 linux_close (PedDevice* dev)
1456 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1460 close (arch_specific->fd);
1465 linux_refresh_close (PedDevice* dev)
1472 #if SIZEOF_OFF_T < 8
1474 static _syscall5(int,_llseek,
1476 unsigned long, offset_high,
1477 unsigned long, offset_low,
1479 unsigned int, origin)
1482 llseek (unsigned int fd, loff_t offset, unsigned int whence)
1487 retval = _llseek(fd,
1488 ((unsigned long long)offset) >> 32,
1489 ((unsigned long long)offset) & 0xffffffff,
1492 return (retval==-1 ? (loff_t) retval : result);
1495 #endif /* SIZEOF_OFF_T < 8 */
1498 _device_seek (const PedDevice* dev, PedSector sector)
1500 LinuxSpecific* arch_specific;
1502 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1503 PED_ASSERT (dev != NULL, return 0);
1504 PED_ASSERT (!dev->external_mode, return 0);
1506 arch_specific = LINUX_SPECIFIC (dev);
1508 #if SIZEOF_OFF_T < 8
1509 if (sizeof (off_t) < 8) {
1510 loff_t pos = (loff_t)(sector * dev->sector_size);
1511 return llseek (arch_specific->fd, pos, SEEK_SET) == pos;
1515 off_t pos = sector * dev->sector_size;
1516 return lseek (arch_specific->fd, pos, SEEK_SET) == pos;
1521 _read_lastoddsector (const PedDevice* dev, void* buffer)
1523 LinuxSpecific* arch_specific;
1524 struct blkdev_ioctl_param ioctl_param;
1526 PED_ASSERT(dev != NULL, return 0);
1527 PED_ASSERT(buffer != NULL, return 0);
1529 arch_specific = LINUX_SPECIFIC (dev);
1532 ioctl_param.block = 0; /* read the last sector */
1533 ioctl_param.content_length = dev->sector_size;
1534 ioctl_param.block_contents = buffer;
1536 if (ioctl(arch_specific->fd, BLKGETLASTSECT, &ioctl_param) == -1) {
1537 PedExceptionOption opt;
1538 opt = ped_exception_throw (
1539 PED_EXCEPTION_ERROR,
1540 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1541 _("%s during read on %s"),
1542 strerror (errno), dev->path);
1544 if (opt == PED_EXCEPTION_CANCEL)
1546 if (opt == PED_EXCEPTION_RETRY)
1554 linux_read (const PedDevice* dev, void* buffer, PedSector start,
1557 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1558 PedExceptionOption ex_status;
1559 void* diobuf = NULL;
1561 PED_ASSERT (dev != NULL, return 0);
1562 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1564 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1565 /* Kludge. This is necessary to read/write the last
1566 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1568 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1569 && start + count - 1 == dev->length - 1)
1570 return ped_device_read (dev, buffer, start, count - 1)
1571 && _read_lastoddsector (
1572 dev, (char *) buffer + (count-1) * 512);
1575 if (_device_seek (dev, start))
1578 ex_status = ped_exception_throw (
1579 PED_EXCEPTION_ERROR,
1580 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1581 _("%s during seek for read on %s"),
1582 strerror (errno), dev->path);
1584 switch (ex_status) {
1585 case PED_EXCEPTION_IGNORE:
1588 case PED_EXCEPTION_RETRY:
1591 case PED_EXCEPTION_UNHANDLED:
1592 ped_exception_catch ();
1593 case PED_EXCEPTION_CANCEL:
1596 PED_ASSERT (0, (void) 0);
1601 size_t read_length = count * dev->sector_size;
1602 if (posix_memalign (&diobuf, dev->sector_size, read_length) != 0)
1606 ssize_t status = read (arch_specific->fd, diobuf, read_length);
1608 memcpy(buffer, diobuf, status);
1609 if (status == (ssize_t) read_length)
1612 read_length -= status;
1613 buffer = (char *) buffer + status;
1617 ex_status = ped_exception_throw (
1618 PED_EXCEPTION_ERROR,
1619 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1620 _("%s during read on %s"),
1624 switch (ex_status) {
1625 case PED_EXCEPTION_IGNORE:
1629 case PED_EXCEPTION_RETRY:
1632 case PED_EXCEPTION_UNHANDLED:
1633 ped_exception_catch ();
1634 case PED_EXCEPTION_CANCEL:
1638 PED_ASSERT (0, (void) 0);
1649 _write_lastoddsector (PedDevice* dev, const void* buffer)
1651 LinuxSpecific* arch_specific;
1652 struct blkdev_ioctl_param ioctl_param;
1654 PED_ASSERT(dev != NULL, return 0);
1655 PED_ASSERT(buffer != NULL, return 0);
1657 arch_specific = LINUX_SPECIFIC (dev);
1660 ioctl_param.block = 0; /* write the last sector */
1661 ioctl_param.content_length = dev->sector_size;
1662 ioctl_param.block_contents = (void*) buffer;
1664 if (ioctl(arch_specific->fd, BLKSETLASTSECT, &ioctl_param) == -1) {
1665 PedExceptionOption opt;
1666 opt = ped_exception_throw (
1667 PED_EXCEPTION_ERROR,
1668 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1669 _("%s during write on %s"),
1670 strerror (errno), dev->path);
1672 if (opt == PED_EXCEPTION_CANCEL)
1674 if (opt == PED_EXCEPTION_RETRY)
1682 linux_write (PedDevice* dev, const void* buffer, PedSector start,
1685 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1686 PedExceptionOption ex_status;
1690 PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1692 if (dev->read_only) {
1693 if (ped_exception_throw (
1694 PED_EXCEPTION_ERROR,
1695 PED_EXCEPTION_IGNORE_CANCEL,
1696 _("Can't write to %s, because it is opened read-only."),
1698 != PED_EXCEPTION_IGNORE)
1704 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1705 /* Kludge. This is necessary to read/write the last
1706 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1708 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1709 && start + count - 1 == dev->length - 1)
1710 return ped_device_write (dev, buffer, start, count - 1)
1711 && _write_lastoddsector (
1712 dev, (char*) buffer + (count-1) * 512);
1715 if (_device_seek (dev, start))
1718 ex_status = ped_exception_throw (
1719 PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1720 _("%s during seek for write on %s"),
1721 strerror (errno), dev->path);
1723 switch (ex_status) {
1724 case PED_EXCEPTION_IGNORE:
1727 case PED_EXCEPTION_RETRY:
1730 case PED_EXCEPTION_UNHANDLED:
1731 ped_exception_catch ();
1732 case PED_EXCEPTION_CANCEL:
1735 PED_ASSERT (0, (void) 0);
1741 printf ("ped_device_write (\"%s\", %p, %d, %d)\n",
1742 dev->path, buffer, (int) start, (int) count);
1744 size_t write_length = count * dev->sector_size;
1746 if (posix_memalign(&diobuf, dev->sector_size, write_length) != 0)
1748 memcpy(diobuf, buffer, write_length);
1749 diobuf_start = diobuf;
1751 ssize_t status = write (arch_specific->fd, diobuf, write_length);
1752 if (status == write_length) break;
1754 write_length -= status;
1755 diobuf = (char *) diobuf + status;
1759 ex_status = ped_exception_throw (
1760 PED_EXCEPTION_ERROR,
1761 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1762 _("%s during write on %s"),
1763 strerror (errno), dev->path);
1765 switch (ex_status) {
1766 case PED_EXCEPTION_IGNORE:
1770 case PED_EXCEPTION_RETRY:
1773 case PED_EXCEPTION_UNHANDLED:
1774 ped_exception_catch ();
1775 case PED_EXCEPTION_CANCEL:
1779 PED_ASSERT (0, (void) 0);
1784 #endif /* !READ_ONLY */
1788 /* returns the number of sectors that are ok.
1791 linux_check (PedDevice* dev, void* buffer, PedSector start, PedSector count)
1793 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1798 PED_ASSERT(dev != NULL, return 0);
1800 if (!_device_seek (dev, start))
1803 if (posix_memalign(&diobuf, PED_SECTOR_SIZE_DEFAULT,
1804 count * PED_SECTOR_SIZE_DEFAULT) != 0)
1807 for (done = 0; done < count; done += status / dev->sector_size) {
1808 status = read (arch_specific->fd, diobuf,
1809 (size_t) ((count-done) * dev->sector_size));
1811 memcpy(buffer, diobuf, status);
1821 _do_fsync (PedDevice* dev)
1823 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1825 PedExceptionOption ex_status;
1828 status = fsync (arch_specific->fd);
1829 if (status >= 0) break;
1831 ex_status = ped_exception_throw (
1832 PED_EXCEPTION_ERROR,
1833 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1834 _("%s during write on %s"),
1835 strerror (errno), dev->path);
1837 switch (ex_status) {
1838 case PED_EXCEPTION_IGNORE:
1841 case PED_EXCEPTION_RETRY:
1844 case PED_EXCEPTION_UNHANDLED:
1845 ped_exception_catch ();
1846 case PED_EXCEPTION_CANCEL:
1849 PED_ASSERT (0, (void) 0);
1857 linux_sync (PedDevice* dev)
1859 PED_ASSERT (dev != NULL, return 0);
1860 PED_ASSERT (!dev->external_mode, return 0);
1864 if (!_do_fsync (dev))
1871 linux_sync_fast (PedDevice* dev)
1873 PED_ASSERT (dev != NULL, return 0);
1874 PED_ASSERT (!dev->external_mode, return 0);
1878 if (!_do_fsync (dev))
1880 /* no cache flush... */
1885 _compare_digit_state (char ch, int need_digit)
1887 return !!isdigit (ch) == need_digit;
1890 /* matches the regexp "[^0-9]+[0-9]+[^0-9]+[0-9]+$".
1891 * Motivation: accept devices looking like /dev/rd/c0d0, but
1892 * not looking like /dev/hda1 and /dev/rd/c0d0p1
1895 _match_rd_device (const char* name)
1900 /* exclude directory names from test */
1901 pos = strrchr(name, '/') ?: name;
1909 for (state = 0; state < 4; state++) {
1910 int want_digits = (state % 2 == 1);
1914 if (!_compare_digit_state (*pos, want_digits))
1917 } while (_compare_digit_state (*pos, want_digits));
1924 _probe_proc_partitions ()
1926 FILE* proc_part_file;
1927 int major, minor, size;
1929 char part_name [256];
1930 char dev_name [256];
1932 proc_part_file = fopen ("/proc/partitions", "r");
1933 if (!proc_part_file)
1936 if (fgets (buf, 256, proc_part_file) == NULL)
1939 if (fgets (buf, 256, proc_part_file) == NULL)
1942 while (fgets (buf, 512, proc_part_file)
1943 && sscanf (buf, "%d %d %d %255s", &major, &minor, &size,
1945 /* Heuristic for telling partitions and devices apart
1946 * Probably needs to be improved
1948 if (!_match_rd_device (part_name)
1949 && isdigit (part_name [strlen (part_name) - 1]))
1952 strcpy (dev_name, "/dev/");
1953 strcat (dev_name, part_name);
1954 _ped_device_probe (dev_name);
1957 fclose (proc_part_file);
1967 _skip_entry (const char *name)
1970 static struct _entry entries[] = {
1971 { ".", sizeof (".") - 1 },
1972 { "..", sizeof ("..") - 1 },
1973 { "dm-", sizeof ("dm-") - 1 },
1974 { "loop", sizeof ("loop") - 1 },
1975 { "ram", sizeof ("ram") - 1 },
1979 for (i = entries; i->name != 0; i++) {
1980 if (strncmp (name, i->name, i->len) == 0)
1991 struct dirent *dirent;
1992 char dev_name [256];
1995 if (!(blockdir = opendir ("/sys/block")))
1997 while ((dirent = readdir (blockdir))) {
1998 if (_skip_entry (dirent->d_name))
2001 if (strlen (dirent->d_name) > sizeof (dev_name) - 6)
2002 continue; /* device name too long! */
2004 strcpy (dev_name, "/dev/");
2005 strcat (dev_name, dirent->d_name);
2006 /* in /sys/block, '/'s are replaced with '!' or '.' */
2007 for (ptr = dev_name; *ptr != '\0'; ptr++) {
2008 if (*ptr == '!' || *ptr == '.')
2011 _ped_device_probe (dev_name);
2014 closedir (blockdir);
2019 _probe_standard_devices ()
2021 _ped_device_probe ("/dev/hda");
2022 _ped_device_probe ("/dev/hdb");
2023 _ped_device_probe ("/dev/hdc");
2024 _ped_device_probe ("/dev/hdd");
2025 _ped_device_probe ("/dev/hde");
2026 _ped_device_probe ("/dev/hdf");
2027 _ped_device_probe ("/dev/hdg");
2028 _ped_device_probe ("/dev/hdh");
2030 _ped_device_probe ("/dev/sda");
2031 _ped_device_probe ("/dev/sdb");
2032 _ped_device_probe ("/dev/sdc");
2033 _ped_device_probe ("/dev/sdd");
2034 _ped_device_probe ("/dev/sde");
2035 _ped_device_probe ("/dev/sdf");
2043 /* we should probe the standard devs too, even with /proc/partitions,
2044 * because /proc/partitions might return devfs stuff, and we might not
2045 * have devfs available
2047 _probe_standard_devices ();
2049 #ifdef ENABLE_DEVICE_MAPPER
2050 /* device-mapper devices aren't listed in /proc/partitions; or, if
2051 * they are, they're listed as dm-X. So, instead of relying on that,
2052 * we do our own checks.
2054 _probe_dm_devices ();
2057 /* /sys/block is more reliable and consistent; fall back to using
2058 * /proc/partitions if the former is unavailable, however.
2060 if (!_probe_sys_block ())
2061 _probe_proc_partitions ();
2065 _device_get_part_path (PedDevice* dev, int num)
2067 int path_len = strlen (dev->path);
2068 int result_len = path_len + 16;
2071 result = (char*) ped_malloc (result_len);
2075 /* Check for devfs-style /disc => /partN transformation
2076 unconditionally; the system might be using udev with devfs rules,
2077 and if not the test is harmless. */
2078 if (!strcmp (dev->path + path_len - 5, "/disc")) {
2079 /* replace /disc with /path%d */
2080 strcpy (result, dev->path);
2081 snprintf (result + path_len - 5, 16, "/part%d", num);
2082 } else if (dev->type == PED_DEVICE_DAC960
2083 || dev->type == PED_DEVICE_CPQARRAY
2084 || dev->type == PED_DEVICE_ATARAID
2085 || dev->type == PED_DEVICE_DM
2086 || isdigit (dev->path[path_len - 1]))
2087 snprintf (result, result_len, "%sp%d", dev->path, num);
2089 snprintf (result, result_len, "%s%d", dev->path, num);
2095 linux_partition_get_path (const PedPartition* part)
2097 return _device_get_part_path (part->disk->dev, part->num);
2101 _partition_get_part_dev (const PedPartition* part)
2103 struct stat dev_stat;
2104 int dev_major, dev_minor;
2106 if (!_device_stat (part->disk->dev, &dev_stat))
2108 dev_major = major (dev_stat.st_rdev);
2109 dev_minor = minor (dev_stat.st_rdev);
2110 return (dev_t)makedev (dev_major, dev_minor + part->num);
2114 _mount_table_search (const char* file_name, dev_t dev)
2116 struct stat part_stat;
2118 char part_name[512];
2122 file = fopen (file_name, "r");
2125 while (fgets (line, 512, file)) {
2126 junk = sscanf (line, "%s", part_name);
2127 if (stat (part_name, &part_stat) == 0) {
2128 if (part_stat.st_rdev == dev) {
2139 _partition_is_mounted_by_dev (dev_t dev)
2141 return _mount_table_search( "/proc/mounts", dev)
2142 || _mount_table_search( "/proc/swaps", dev)
2143 || _mount_table_search( "/etc/mtab", dev);
2147 _partition_is_mounted_by_path (const char *path)
2149 struct stat part_stat;
2150 if (stat (path, &part_stat) != 0)
2152 if (!S_ISBLK(part_stat.st_mode))
2154 return _partition_is_mounted_by_dev (part_stat.st_rdev);
2158 _partition_is_mounted (const PedPartition *part)
2161 if (!ped_partition_is_active (part))
2163 dev = _partition_get_part_dev (part);
2164 return _partition_is_mounted_by_dev (dev);
2168 linux_partition_is_busy (const PedPartition* part)
2172 PED_ASSERT (part != NULL, return 0);
2174 if (_partition_is_mounted (part))
2176 if (part->type == PED_PARTITION_EXTENDED) {
2177 for (walk = part->part_list; walk; walk = walk->next) {
2178 if (linux_partition_is_busy (walk))
2186 _blkpg_part_command (PedDevice* dev, struct blkpg_partition* part, int op)
2188 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2189 struct blkpg_ioctl_arg ioctl_arg;
2192 ioctl_arg.flags = 0;
2193 ioctl_arg.datalen = sizeof (struct blkpg_partition);
2194 ioctl_arg.data = (void*) part;
2196 return ioctl (arch_specific->fd, BLKPG, &ioctl_arg) == 0;
2200 _blkpg_add_partition (PedDisk* disk, const PedPartition *part)
2202 struct blkpg_partition linux_part;
2203 const char* vol_name;
2206 PED_ASSERT(disk != NULL, return 0);
2207 PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0,
2210 if (ped_disk_type_check_feature (disk->type,
2211 PED_DISK_TYPE_PARTITION_NAME))
2212 vol_name = ped_partition_get_name (part);
2216 dev_name = _device_get_part_path (disk->dev, part->num);
2220 memset (&linux_part, 0, sizeof (linux_part));
2221 linux_part.start = part->geom.start * disk->dev->sector_size;
2222 /* see fs/partitions/msdos.c:msdos_partition(): "leave room for LILO" */
2223 if (part->type & PED_PARTITION_EXTENDED)
2224 linux_part.length = part->geom.length == 1 ? 512 : 1024;
2226 linux_part.length = part->geom.length * disk->dev->sector_size;
2227 linux_part.pno = part->num;
2228 strncpy (linux_part.devname, dev_name, BLKPG_DEVNAMELTH);
2230 strncpy (linux_part.volname, vol_name, BLKPG_VOLNAMELTH);
2234 if (!_blkpg_part_command (disk->dev, &linux_part,
2235 BLKPG_ADD_PARTITION)) {
2236 return ped_exception_throw (
2237 PED_EXCEPTION_ERROR,
2238 PED_EXCEPTION_IGNORE_CANCEL,
2239 _("Error informing the kernel about modifications to "
2240 "partition %s -- %s. This means Linux won't know "
2241 "about any changes you made to %s until you reboot "
2242 "-- so you shouldn't mount it or use it in any way "
2243 "before rebooting."),
2247 == PED_EXCEPTION_IGNORE;
2254 _blkpg_remove_partition (PedDisk* disk, int n)
2256 struct blkpg_partition linux_part;
2258 memset (&linux_part, 0, sizeof (linux_part));
2260 return _blkpg_part_command (disk->dev, &linux_part,
2261 BLKPG_DEL_PARTITION);
2265 _disk_sync_part_table (PedDisk* disk)
2267 int largest_partnum = ped_disk_get_last_partition_num (disk);
2268 if (largest_partnum <= 0)
2272 int* rets = ped_malloc(sizeof(int) * last);
2273 int* errnums = ped_malloc(sizeof(int) * last);
2277 for (i = 1; i <= last; i++) {
2278 rets[i - 1] = _blkpg_remove_partition (disk, i);
2279 errnums[i - 1] = errno;
2282 for (i = 1; i <= last; i++) {
2283 const PedPartition *part;
2285 part = ped_disk_get_partition (disk, i);
2287 /* busy... so we won't (can't!) disturb ;) Prolly
2288 * doesn't matter anyway, because users shouldn't be
2289 * changing mounted partitions anyway...
2291 if (!rets[i - 1] && errnums[i - 1] == EBUSY)
2294 /* add the (possibly modified or new) partition */
2295 if (!_blkpg_add_partition (disk, part))
2305 #ifdef ENABLE_DEVICE_MAPPER
2307 _dm_remove_map_name(char *name)
2309 struct dm_task *task = NULL;
2312 task = dm_task_create(DM_DEVICE_REMOVE);
2316 dm_task_set_name (task, name);
2318 rc = dm_task_run(task);
2319 dm_task_update_nodes();
2320 dm_task_destroy(task);
2328 _dm_is_part (struct dm_info *this, char *name)
2330 struct dm_task* task = NULL;
2331 struct dm_info* info = alloca(sizeof *info);
2332 struct dm_deps* deps = NULL;
2336 task = dm_task_create(DM_DEVICE_DEPS);
2340 dm_task_set_name(task, name);
2341 rc = dm_task_run(task);
2348 memset(info, '\0', sizeof *info);
2349 dm_task_get_info(task, info);
2353 deps = dm_task_get_deps(task);
2358 for (i = 0; i < deps->count; i++) {
2359 unsigned int ma = major(deps->device[i]),
2360 mi = minor(deps->device[i]);
2362 if (ma == this->major && mi == this->minor)
2367 dm_task_destroy(task);
2372 _dm_remove_parts (PedDevice* dev)
2374 struct stat dev_stat;
2375 struct dm_task* task = NULL;
2376 struct dm_info* info = alloca(sizeof *info);
2377 struct dm_names* names = NULL;
2378 unsigned int next = 0;
2381 if (!_device_stat (dev, &dev_stat))
2384 task = dm_task_create(DM_DEVICE_LIST);
2388 dm_task_set_major (task, major (dev_stat.st_rdev));
2389 dm_task_set_minor (task, minor (dev_stat.st_rdev));
2391 rc = dm_task_run(task);
2395 memset(info, '\0', sizeof *info);
2396 dm_task_get_info(task, info);
2400 names = dm_task_get_names(task);
2406 names = (void *)names + next;
2408 if (_dm_is_part(info, names->name))
2409 rc += _dm_remove_map_name(names->name);
2414 dm_task_update_nodes();
2415 dm_task_destroy(task);
2422 dm_task_destroy(task);
2423 ped_exception_throw (PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE,
2424 _("parted was unable to re-read the partition "
2425 "table on %s (%s). This means Linux won't know "
2426 "anything about the modifications you made. "),
2427 dev->path, strerror (errno));
2432 _dm_add_partition (PedDisk* disk, PedPartition* part)
2434 struct stat dev_stat;
2435 struct dm_task* task = NULL;
2437 char* vol_name = NULL;
2438 char* dev_name = NULL;
2439 char* params = NULL;
2441 dev_name = _device_get_part_path (disk->dev, part->num);
2445 vol_name = strrchr (dev_name, '/');
2446 if (vol_name && *vol_name && *(++vol_name))
2447 vol_name = strdup (vol_name);
2449 vol_name = strdup (dev_name);
2453 if (!_device_stat (disk->dev, &dev_stat))
2456 if (asprintf (¶ms, "%d:%d %lld", major (dev_stat.st_rdev),
2457 minor (dev_stat.st_rdev), part->geom.start) == -1)
2463 task = dm_task_create (DM_DEVICE_CREATE);
2467 dm_task_set_name (task, vol_name);
2468 dm_task_add_target (task, 0, part->geom.length,
2470 rc = dm_task_run(task);
2472 //printf("0 %ld linear %s\n", part->geom.length, params);
2473 dm_task_update_nodes();
2474 dm_task_destroy(task);
2479 _dm_remove_map_name(vol_name);
2482 dm_task_update_nodes();
2484 dm_task_destroy (task);
2491 _dm_reread_part_table (PedDisk* disk)
2493 int largest_partnum = ped_disk_get_last_partition_num (disk);
2494 if (largest_partnum <= 0)
2498 int last = PED_MIN (largest_partnum, 16);
2502 if (!_dm_remove_parts(disk->dev))
2505 for (i = 1; i <= last; i++) {
2508 part = ped_disk_get_partition (disk, i);
2512 if (!_dm_add_partition (disk, part))
2520 _kernel_reread_part_table (PedDevice* dev)
2522 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2523 int retry_count = 5;
2526 while (ioctl (arch_specific->fd, BLKRRPART)) {
2530 ped_exception_throw (
2531 PED_EXCEPTION_WARNING,
2532 PED_EXCEPTION_IGNORE,
2533 _("The kernel was unable to re-read the partition "
2534 "table on %s (%s). This means Linux won't know "
2535 "anything about the modifications you made "
2536 "until you reboot. You should reboot your computer "
2537 "before doing anything with %s."),
2538 dev->path, strerror (errno), dev->path);
2549 static int have_blkpg = -1;
2552 if (have_blkpg != -1)
2555 kver = _get_linux_version();
2556 return have_blkpg = kver >= KERNEL_VERSION (2,4,0) ? 1 : 0;
2560 linux_disk_commit (PedDisk* disk)
2562 #ifdef ENABLE_DEVICE_MAPPER
2563 if (disk->dev->type == PED_DEVICE_DM)
2564 return _dm_reread_part_table (disk);
2566 if (disk->dev->type != PED_DEVICE_FILE) {
2567 /* The ioctl() command BLKPG_ADD_PARTITION does not notify
2568 * the devfs system; consequently, /proc/partitions will not
2569 * be up to date, and the proper links in /dev are not
2570 * created. Therefore, if using DevFS, we must get the kernel
2571 * to re-read and grok the partition table.
2573 /* Work around kernel dasd problem so we really do BLKRRPART */
2574 if (disk->dev->type != PED_DEVICE_DASD &&
2575 _have_blkpg () && !_have_devfs ()) {
2576 if (_disk_sync_part_table (disk))
2580 return _kernel_reread_part_table (disk->dev);
2586 static PedDeviceArchOps linux_dev_ops = {
2588 destroy: linux_destroy,
2589 is_busy: linux_is_busy,
2591 refresh_open: linux_refresh_open,
2593 refresh_close: linux_refresh_close,
2598 sync_fast: linux_sync_fast,
2599 probe_all: linux_probe_all
2602 PedDiskArchOps linux_disk_ops = {
2603 partition_get_path: linux_partition_get_path,
2604 partition_is_busy: linux_partition_is_busy,
2605 disk_commit: linux_disk_commit
2608 PedArchitecture ped_linux_arch = {
2609 dev_ops: &linux_dev_ops,
2610 disk_ops: &linux_disk_ops