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"
49 # define _(String) dgettext (PACKAGE, String)
51 # define _(String) (String)
52 #endif /* ENABLE_NLS */
54 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
57 #define __NR__llseek 140
60 #ifndef SCSI_IOCTL_SEND_COMMAND
61 #define SCSI_IOCTL_SEND_COMMAND 1
64 /* from <linux/hdreg.h> */
65 #define HDIO_GETGEO 0x0301 /* get device geometry */
66 #define HDIO_GET_IDENTITY 0x030d /* get IDE identification info */
68 #if defined(O_DIRECT) && !(defined(__s390__) || defined(__s390x__))
69 #define RD_MODE (O_RDONLY | O_DIRECT)
70 #define WR_MODE (O_WRONLY | O_DIRECT)
71 #define RW_MODE (O_RDWR | O_DIRECT)
73 #define RD_MODE (O_RDONLY)
74 #define WR_MODE (O_WRONLY)
75 #define RW_MODE (O_RDWR)
78 #if defined(__s390__) || defined(__s390x__)
79 # include <parted/fdasd.h>
82 #define LINUX_SPECIFIC(dev) ((LinuxSpecific*) (dev)->arch_specific)
84 typedef struct _LinuxSpecific LinuxSpecific;
86 struct _LinuxSpecific {
88 char* dmtype; /**< device map target type */
89 #if defined(__s390__) || defined(__s390x__)
90 unsigned int real_sector_size;
91 /* IBM internal dasd structure (i guess ;), required. */
92 struct fdasd_anchor *anchor;
98 unsigned char sectors;
99 unsigned short cylinders;
103 struct ata7_sectinfo {
110 /* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
112 unsigned short config; /* lots of obsolete bit flags */
113 unsigned short cyls; /* "physical" cyls */
114 unsigned short reserved2; /* reserved (word 2) */
115 unsigned short heads; /* "physical" heads */
116 unsigned short track_bytes; /* unformatted bytes per track */
117 unsigned short sector_bytes; /* unformatted bytes per sector */
118 unsigned short sectors; /* "physical" sectors per track */
119 unsigned short vendor0; /* vendor unique */
120 unsigned short vendor1; /* vendor unique */
121 unsigned short vendor2; /* vendor unique */
122 unsigned char serial_no[20]; /* 0 = not_specified */
123 unsigned short buf_type;
124 unsigned short buf_size; /* 512 byte increments;
126 unsigned short ecc_bytes; /* for r/w long cmds;
128 unsigned char fw_rev[8]; /* 0 = not_specified */
129 char model[40]; /* 0 = not_specified */
130 unsigned char max_multsect; /* 0=not_implemented */
131 unsigned char vendor3; /* vendor unique */
132 unsigned short dword_io; /* 0=not_implemented; 1=implemented */
133 unsigned char vendor4; /* vendor unique */
134 unsigned char capability; /* bits 0:DMA 1:LBA 2:IORDYsw
136 unsigned short reserved50; /* reserved (word 50) */
137 unsigned char vendor5; /* vendor unique */
138 unsigned char tPIO; /* 0=slow, 1=medium, 2=fast */
139 unsigned char vendor6; /* vendor unique */
140 unsigned char tDMA; /* 0=slow, 1=medium, 2=fast */
141 unsigned short field_valid; /* bits 0:cur_ok 1:eide_ok */
142 unsigned short cur_cyls; /* logical cylinders */
143 unsigned short cur_heads; /* logical heads */
144 unsigned short cur_sectors; /* logical sectors per track */
145 unsigned short cur_capacity0; /* logical total sectors on drive */
146 unsigned short cur_capacity1; /* (2 words, misaligned int) */
147 unsigned char multsect; /* current multiple sector count */
148 unsigned char multsect_valid; /* when (bit0==1) multsect is ok */
149 unsigned int lba_capacity; /* total number of sectors */
150 unsigned short dma_1word; /* single-word dma info */
151 unsigned short dma_mword; /* multiple-word dma info */
152 unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */
153 unsigned short eide_dma_min; /* min mword dma cycle time (ns) */
154 unsigned short eide_dma_time; /* recommended mword dma cycle
156 unsigned short eide_pio; /* min cycle time (ns), no IORDY */
157 unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */
158 unsigned short words69_70[2]; /* reserved words 69-70 */
159 /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
160 unsigned short words71_74[4]; /* reserved words 71-74 */
161 unsigned short queue_depth; /* */
162 unsigned short words76_79[4]; /* reserved words 76-79 */
163 unsigned short major_rev_num; /* */
164 unsigned short minor_rev_num; /* */
165 unsigned short command_set_1; /* bits 0:Smart 1:Security 2:Removable
167 unsigned short command_set_2; /* bits 14:Smart Enabled 13:0 zero */
168 unsigned short cfsse; /* command set-feature supported
170 unsigned short cfs_enable_1; /* command set-feature enabled */
171 unsigned short cfs_enable_2; /* command set-feature enabled */
172 unsigned short csf_default; /* command set-feature default */
173 unsigned short dma_ultra; /* */
174 unsigned short word89; /* reserved (word 89) */
175 unsigned short word90; /* reserved (word 90) */
176 unsigned short CurAPMvalues; /* current APM values */
177 unsigned short word92; /* reserved (word 92) */
178 unsigned short hw_config; /* hardware config */
179 unsigned short words94_105[12];/* reserved words 94-105 */
180 struct ata7_sectinfo ata7_sectinfo; /* ATAPI/ATA7 physical and logical
182 unsigned short words107_116[10];/* reserved words 107-116 */
183 unsigned int logical_sectsize;/* ATAPI/ATA7 logical sector size */
184 unsigned short words119_125[7];/* reserved words 119-125 */
185 unsigned short last_lun; /* reserved (word 126) */
186 unsigned short word127; /* reserved (word 127) */
187 unsigned short dlf; /* device lock function
189 * 8 security level 1:max 0:high
198 unsigned short csfo; /* current set features options
205 unsigned short words130_155[26];/* reserved vendor words 130-155 */
206 unsigned short word156;
207 unsigned short words157_159[3]; /* reserved vendor words 157-159 */
208 unsigned short words160_255[95];/* reserved words 160-255 */
211 /* from <linux/fs.h> */
212 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
213 #define BLKGETSIZE _IO(0x12,96) /* return device size */
214 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
215 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
216 #define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
217 #define BLKSETLASTSECT _IO(0x12,109) /* set last sector of block device */
219 /* return device size in bytes (u64 *arg) */
220 #define BLKGETSIZE64 _IOR(0x12,114,size_t)
222 struct blkdev_ioctl_param {
224 size_t content_length;
225 char * block_contents;
228 /* from <linux/major.h> */
230 #define IDE1_MAJOR 22
231 #define IDE2_MAJOR 33
232 #define IDE3_MAJOR 34
233 #define IDE4_MAJOR 56
234 #define IDE5_MAJOR 57
235 #define SCSI_CDROM_MAJOR 11
236 #define SCSI_DISK0_MAJOR 8
237 #define SCSI_DISK1_MAJOR 65
238 #define SCSI_DISK2_MAJOR 66
239 #define SCSI_DISK3_MAJOR 67
240 #define SCSI_DISK4_MAJOR 68
241 #define SCSI_DISK5_MAJOR 69
242 #define SCSI_DISK6_MAJOR 70
243 #define SCSI_DISK7_MAJOR 71
244 #define COMPAQ_SMART2_MAJOR 72
245 #define COMPAQ_SMART2_MAJOR1 73
246 #define COMPAQ_SMART2_MAJOR2 74
247 #define COMPAQ_SMART2_MAJOR3 75
248 #define COMPAQ_SMART2_MAJOR4 76
249 #define COMPAQ_SMART2_MAJOR5 77
250 #define COMPAQ_SMART2_MAJOR6 78
251 #define COMPAQ_SMART2_MAJOR7 79
252 #define COMPAQ_SMART_MAJOR 104
253 #define COMPAQ_SMART_MAJOR1 105
254 #define COMPAQ_SMART_MAJOR2 106
255 #define COMPAQ_SMART_MAJOR3 107
256 #define COMPAQ_SMART_MAJOR4 108
257 #define COMPAQ_SMART_MAJOR5 109
258 #define COMPAQ_SMART_MAJOR6 110
259 #define COMPAQ_SMART_MAJOR7 111
260 #define DAC960_MAJOR 48
261 #define ATARAID_MAJOR 114
262 #define I2O_MAJOR1 80
263 #define I2O_MAJOR2 81
264 #define I2O_MAJOR3 82
265 #define I2O_MAJOR4 83
266 #define I2O_MAJOR5 84
267 #define I2O_MAJOR6 85
268 #define I2O_MAJOR7 86
269 #define I2O_MAJOR8 87
271 #define DASD_MAJOR 94
272 #define VIODASD_MAJOR 112
273 #define SX8_MAJOR1 160
274 #define SX8_MAJOR2 161
275 #define XVD_MAJOR 202
276 #define SDMMC_MAJOR 179
278 #define SCSI_BLK_MAJOR(M) ( \
279 (M) == SCSI_DISK0_MAJOR \
280 || (M) == SCSI_CDROM_MAJOR \
281 || ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
283 /* Maximum number of partitions supported by linux. */
284 #define MAX_NUM_PARTS 64
286 static char* _device_get_part_path (PedDevice* dev, int num);
287 static int _partition_is_mounted_by_path (const char* path);
290 _is_ide_major (int major)
307 _is_cpqarray_major (int major)
309 return ((COMPAQ_SMART2_MAJOR <= major && major <= COMPAQ_SMART2_MAJOR7)
310 || (COMPAQ_SMART_MAJOR <= major && major <= COMPAQ_SMART_MAJOR7));
314 _is_i2o_major (int major)
316 return (I2O_MAJOR1 <= major && major <= I2O_MAJOR8);
320 _is_sx8_major (int major)
322 return (SX8_MAJOR1 <= major && major <= SX8_MAJOR2);
325 #ifdef ENABLE_DEVICE_MAPPER
327 _dm_maptype (PedDevice *dev)
329 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
332 uint64_t start, length;
333 char *target_type = NULL;
336 const char* dev_dir = getenv ("DM_DEV_DIR");
338 if (dev_dir && *dev_dir && !dm_set_dev_dir(dev_dir))
341 if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
344 if (!dm_task_set_name(dmt, dev->path))
347 dm_task_no_open_count(dmt);
349 if (!dm_task_run(dmt))
352 next = dm_get_next_target(dmt, NULL, &start, &length,
353 &target_type, ¶ms);
355 arch_specific->dmtype = strdup(target_type ? target_type : "NO-TARGET");
356 if (arch_specific->dmtype == NULL)
360 dm_task_destroy(dmt);
365 readFD (int fd, char **buf)
368 size_t size = PROC_DEVICES_BUFSIZ;
371 *buf = malloc (size * sizeof (char));
377 p = &(*buf) [filesize];
378 s = read (fd, p, PROC_DEVICES_BUFSIZ);
379 /* exit if there is an error or EOF is reached */
384 *buf = realloc (*buf, size);
387 if (filesize == 0 && s < 0) {
392 /* there is always some excess memory left unused */
393 *buf = realloc (*buf, filesize+1);
394 (*buf)[filesize] = '\0';
401 _is_dm_major (int major)
410 fd = open ("/proc/devices", O_RDONLY);
414 if (readFD(fd, &buf) < 0) {
420 end = strchr(line, '\n');
429 if (!strncmp(line, "Block devices:", 14))
434 name = strrchr(line, ' ');
435 if (!name || strcmp(name+1, "device-mapper"))
438 maj = strtol(line, &name, 10);
448 end = strchr(line, '\n');
460 char buf [512]; /* readdir(3) claims d_name[256] */
463 mapper_dir = opendir ("/dev/mapper");
467 /* Search the /dev/mapper directory for devices w/ the same major
468 * number that was returned from _probe_lvm_major().
470 while ((dent = readdir (mapper_dir))) {
471 if (strcmp (dent->d_name, ".") == 0 ||
472 strcmp (dent->d_name, "..") == 0)
475 snprintf (buf, sizeof (buf), "/dev/mapper/%s", dent->d_name);
477 if (stat (buf, &st) != 0)
480 if (_is_dm_major(major(st.st_rdev)))
481 _ped_device_probe (buf);
483 closedir (mapper_dir);
490 _device_stat (PedDevice* dev, struct stat * dev_stat)
492 PED_ASSERT (dev != NULL, return 0);
493 PED_ASSERT (!dev->external_mode, return 0);
496 if (!stat (dev->path, dev_stat)) {
499 if (ped_exception_throw (
501 PED_EXCEPTION_RETRY_CANCEL,
502 _("Could not stat device %s - %s."),
505 != PED_EXCEPTION_RETRY)
512 _device_probe_type (PedDevice* dev)
514 struct stat dev_stat;
518 if (!_device_stat (dev, &dev_stat))
521 if (!S_ISBLK(dev_stat.st_mode)) {
522 dev->type = PED_DEVICE_FILE;
526 dev_major = major (dev_stat.st_rdev);
527 dev_minor = minor (dev_stat.st_rdev);
529 if (SCSI_BLK_MAJOR (dev_major) && (dev_minor % 0x10 == 0)) {
530 dev->type = PED_DEVICE_SCSI;
531 } else if (_is_ide_major (dev_major) && (dev_minor % 0x40 == 0)) {
532 dev->type = PED_DEVICE_IDE;
533 } else if (dev_major == DAC960_MAJOR && (dev_minor % 0x8 == 0)) {
534 dev->type = PED_DEVICE_DAC960;
535 } else if (dev_major == ATARAID_MAJOR && (dev_minor % 0x10 == 0)) {
536 dev->type = PED_DEVICE_ATARAID;
537 } else if (dev_major == DASD_MAJOR && (dev_minor % 0x4 == 0)) {
538 dev->type = PED_DEVICE_DASD;
539 } else if (dev_major == VIODASD_MAJOR && (dev_minor % 0x8 == 0)) {
540 dev->type = PED_DEVICE_VIODASD;
541 } else if (_is_sx8_major(dev_major) && (dev_minor % 0x20 == 0)) {
542 dev->type = PED_DEVICE_SX8;
543 } else if (_is_i2o_major (dev_major) && (dev_minor % 0x10 == 0)) {
544 dev->type = PED_DEVICE_I2O;
545 } else if (_is_cpqarray_major (dev_major) && (dev_minor % 0x10 == 0)) {
546 dev->type = PED_DEVICE_CPQARRAY;
547 } else if (dev_major == UBD_MAJOR && (dev_minor % 0x10 == 0)) {
548 dev->type = PED_DEVICE_UBD;
549 #ifdef ENABLE_DEVICE_MAPPER
550 } else if (_is_dm_major(dev_major)) {
551 dev->type = PED_DEVICE_DM;
552 if (_dm_maptype(dev)) {
553 ped_exception_throw (
555 PED_EXCEPTION_CANCEL,
556 _("Unable to determine the dm type of %s."),
560 } else if (dev_major == XVD_MAJOR && (dev_minor % 0x10 == 0)) {
561 dev->type = PED_DEVICE_XVD;
562 } else if (dev_major == SDMMC_MAJOR && (dev_minor % 0x08 == 0)) {
563 dev->type = PED_DEVICE_SDMMC;
565 dev->type = PED_DEVICE_UNKNOWN;
572 _get_linux_version ()
574 static int kver = -1;
586 if (sscanf (uts.release, "%u.%u.%u", &major, &minor, &teeny) != 3)
589 return kver = KERNEL_VERSION (major, minor, teeny);
595 static int have_devfs = -1;
598 if (have_devfs != -1)
601 /* the presence of /dev/.devfsd implies that DevFS is active */
602 if (stat("/dev/.devfsd", &sb) < 0)
603 return have_devfs = 0;
605 return have_devfs = S_ISCHR(sb.st_mode) ? 1 : 0;
609 _device_set_sector_size (PedDevice* dev)
611 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
614 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
615 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
617 PED_ASSERT (dev->open_count, return);
619 if (_get_linux_version() < KERNEL_VERSION (2,3,0)) {
620 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
624 if (ioctl (arch_specific->fd, BLKSSZGET, §or_size)) {
625 ped_exception_throw (
626 PED_EXCEPTION_WARNING,
628 _("Could not determine sector size for %s: %s.\n"
629 "Using the default sector size (%lld)."),
630 dev->path, strerror (errno), PED_SECTOR_SIZE_DEFAULT);
632 dev->sector_size = (long long)sector_size;
635 /* Return PED_SECTOR_SIZE_DEFAULT for DASDs. */
636 if (dev->type == PED_DEVICE_DASD) {
637 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
640 if (dev->sector_size != PED_SECTOR_SIZE_DEFAULT) {
641 ped_exception_throw (
642 PED_EXCEPTION_WARNING,
644 _("Device %s has a logical sector size of %lld. Not "
645 "all parts of GNU Parted support this at the moment, "
646 "and the working code is HIGHLY EXPERIMENTAL.\n"),
647 dev->path, dev->sector_size);
652 _kernel_has_blkgetsize64(void)
654 int version = _get_linux_version();
656 if (version >= KERNEL_VERSION (2,5,4)) return 1;
657 if (version < KERNEL_VERSION (2,5,0) &&
658 version >= KERNEL_VERSION (2,4,18)) return 1;
662 /* TODO: do a binary search if BLKGETSIZE doesn't work?! */
664 _device_get_length (PedDevice* dev)
667 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
671 PED_ASSERT (dev->open_count > 0, return 0);
672 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
674 if (_kernel_has_blkgetsize64()) {
675 if (ioctl(arch_specific->fd, BLKGETSIZE64, &bytes) == 0) {
676 return bytes / dev->sector_size;
680 if (ioctl (arch_specific->fd, BLKGETSIZE, &size)) {
681 ped_exception_throw (
683 PED_EXCEPTION_CANCEL,
684 _("Unable to determine the size of %s (%s)."),
694 _device_probe_geometry (PedDevice* dev)
696 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
697 struct stat dev_stat;
698 struct hd_geometry geometry;
700 if (!_device_stat (dev, &dev_stat))
702 PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
704 _device_set_sector_size (dev);
706 dev->length = _device_get_length (dev);
710 /* The GETGEO ioctl is no longer useful (as of linux 2.6.x). We could
711 * still use it in 2.4.x, but this is contentious. Perhaps we should
713 dev->bios_geom.sectors = 63;
714 dev->bios_geom.heads = 255;
715 dev->bios_geom.cylinders
716 = dev->length / (63 * 255);
718 /* FIXME: what should we put here? (TODO: discuss on linux-kernel) */
719 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geometry)
720 && geometry.sectors && geometry.heads) {
721 dev->hw_geom.sectors = geometry.sectors;
722 dev->hw_geom.heads = geometry.heads;
723 dev->hw_geom.cylinders
724 = dev->length / (dev->hw_geom.heads
725 * dev->hw_geom.sectors);
727 dev->hw_geom = dev->bios_geom;
734 strip_name(char* str)
739 for (i = 0; str[i] != 0; i++) {
740 if (!isspace (str[i])
741 || (isspace (str[i]) && !isspace (str[i+1]) && str[i+1])) {
751 init_ide (PedDevice* dev)
753 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
754 struct stat dev_stat;
756 struct hd_driveid hdi;
757 PedExceptionOption ex_status;
759 int sector_multiplier = 0;
761 if (!_device_stat (dev, &dev_stat))
764 dev_major = major (dev_stat.st_rdev);
766 if (!ped_device_open (dev))
769 if (ioctl (arch_specific->fd, HDIO_GET_IDENTITY, &hdi)) {
770 ex_status = ped_exception_throw (
771 PED_EXCEPTION_WARNING,
772 PED_EXCEPTION_IGNORE_CANCEL,
773 _("Could not get identity of device %s - %s"),
774 dev->path, strerror (errno));
776 case PED_EXCEPTION_CANCEL:
777 goto error_close_dev;
779 case PED_EXCEPTION_UNHANDLED:
780 ped_exception_catch ();
781 case PED_EXCEPTION_IGNORE:
782 dev->model = strdup(_("Generic IDE"));
785 PED_ASSERT (0, (void) 0);
789 /* hdi.model is not guaranteed to be NULL terminated */
790 memcpy (hdi_buf, hdi.model, 40);
792 dev->model = strip_name (hdi_buf);
794 if (!hdi.ata7_sectinfo.valid1 && hdi.ata7_sectinfo.valid2)
795 sector_multiplier = hdi.ata7_sectinfo.multiplier;
797 sector_multiplier = 1;
799 if (sector_multiplier != 1) {
800 ex_status = ped_exception_throw (
801 PED_EXCEPTION_WARNING,
802 PED_EXCEPTION_IGNORE_CANCEL,
803 _("Device %s has multiple (%d) logical sectors "
804 "per physical sector.\n"
805 "GNU Parted supports this EXPERIMENTALLY for "
806 "some special disk label/file system "
807 "combinations, e.g. GPT and ext2/3.\n"
808 "Please consult the web site for up-to-date "
810 dev->path, sector_multiplier);
813 case PED_EXCEPTION_CANCEL:
814 goto error_close_dev;
816 case PED_EXCEPTION_UNHANDLED:
817 ped_exception_catch ();
818 case PED_EXCEPTION_IGNORE:
821 PED_ASSERT (0, (void) 0);
826 /* XXX sector_size has not been set yet! */
827 /* dev->phys_sector_size = dev->sector_size
828 * sector_multiplier;*/
829 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
832 if (!_device_probe_geometry (dev))
833 goto error_close_dev;
835 ped_device_close (dev);
839 ped_device_close (dev);
844 /* This function reads the /sys entry named "file" for device "dev". */
846 read_device_sysfs_file (PedDevice *dev, const char *file)
852 snprintf (name_buf, 127, "/sys/block/%s/device/%s",
853 last_component (dev->path), file);
855 if ((f = fopen (name_buf, "r")) == NULL)
858 if (fgets (buf, 255, f) == NULL)
862 return strip_name (buf);
865 /* This function sends a query to a SCSI device for vendor and product
866 * information. It uses the deprecated SCSI_IOCTL_SEND_COMMAND to
870 scsi_query_product_info (PedDevice* dev, char **vendor, char **product)
872 /* The following are defined by the SCSI-2 specification. */
873 typedef struct _scsi_inquiry_cmd
876 uint8_t lun; /* bits 5-7 denote the LUN */
879 uint8_t alloc_length;
881 } __attribute__((packed)) scsi_inquiry_cmd_t;
883 typedef struct _scsi_inquiry_data
885 uint8_t peripheral_info;
887 uint8_t version_info;
889 uint8_t additional_length;
893 uint8_t vendor_id[8];
894 uint8_t product_id[16];
895 uint8_t product_revision[4];
896 uint8_t vendor_specific[20];
897 uint8_t _reserved3[40];
898 } __attribute__((packed)) scsi_inquiry_data_t;
907 scsi_inquiry_data_t out;
908 scsi_inquiry_cmd_t in;
912 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
918 memset (&arg, 0x00, sizeof(struct scsi_arg));
920 arg.outlen = sizeof(scsi_inquiry_data_t);
921 arg.data.in.op = INQUIRY;
922 arg.data.in.lun = dev->host << 5;
923 arg.data.in.alloc_length = sizeof(scsi_inquiry_data_t);
924 arg.data.in.page_code = 0;
925 arg.data.in.reserved = 0;
926 arg.data.in.control = 0;
928 if (ioctl (arch_specific->fd, SCSI_IOCTL_SEND_COMMAND, &arg) < 0)
931 memcpy (buf, arg.data.out.vendor_id, 8);
933 *vendor = strip_name (buf);
935 memcpy (buf, arg.data.out.product_id, 16);
937 *product = strip_name (buf);
942 /* This function provides the vendor and product name for a SCSI device.
943 * It supports both the modern /sys interface and direct queries
944 * via the deprecated ioctl, SCSI_IOCTL_SEND_COMMAND.
947 scsi_get_product_info (PedDevice* dev, char **vendor, char **product)
949 *vendor = read_device_sysfs_file (dev, "vendor");
950 *product = read_device_sysfs_file (dev, "model");
951 if (*vendor && *product)
954 return scsi_query_product_info (dev, vendor, product);
958 init_scsi (PedDevice* dev)
963 uint32_t host_unique_id;
966 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
970 if (!ped_device_open (dev))
973 if (ioctl (arch_specific->fd, SCSI_IOCTL_GET_IDLUN, &idlun) < 0) {
976 if (ped_exception_throw (
977 PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
978 _("Error initialising SCSI device %s - %s"),
979 dev->path, strerror (errno))
980 != PED_EXCEPTION_IGNORE)
981 goto error_close_dev;
982 if (!_device_probe_geometry (dev))
983 goto error_close_dev;
984 ped_device_close (dev);
988 dev->host = idlun.host_unique_id;
989 dev->did = idlun.dev_id;
991 dev->model = (char*) ped_malloc (8 + 16 + 2);
993 goto error_close_dev;
995 if (scsi_get_product_info (dev, &vendor, &product)) {
996 sprintf (dev->model, "%.8s %.16s", vendor, product);
1000 strcpy (dev->model, "Generic SCSI");
1003 if (!_device_probe_geometry (dev))
1004 goto error_close_dev;
1006 ped_device_close (dev);
1010 ped_device_close (dev);
1016 init_file (PedDevice* dev)
1018 struct stat dev_stat;
1020 if (!_device_stat (dev, &dev_stat))
1022 if (!ped_device_open (dev))
1025 if (S_ISBLK(dev_stat.st_mode))
1026 dev->length = _device_get_length (dev);
1028 dev->length = dev_stat.st_size / 512;
1029 if (dev->length <= 0) {
1030 ped_exception_throw (
1031 PED_EXCEPTION_ERROR,
1032 PED_EXCEPTION_CANCEL,
1033 _("The device %s has zero length, and can't possibly "
1034 "store a file system or partition table. Perhaps "
1035 "you selected the wrong device?"),
1037 goto error_close_dev;
1040 ped_device_close (dev);
1042 dev->bios_geom.cylinders = dev->length / 4 / 32;
1043 dev->bios_geom.heads = 4;
1044 dev->bios_geom.sectors = 32;
1045 dev->hw_geom = dev->bios_geom;
1046 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1047 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
1048 dev->model = strdup ("");
1053 ped_device_close (dev);
1059 init_dasd (PedDevice* dev, const char* model_name)
1061 struct stat dev_stat;
1062 struct hd_geometry geo;
1065 if (!_device_stat (dev, &dev_stat))
1068 if (!ped_device_open (dev))
1071 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1073 PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
1075 _device_set_sector_size (dev);
1076 if (!dev->sector_size)
1077 goto error_close_dev;
1079 dev->length = _device_get_length (dev);
1081 goto error_close_dev;
1083 if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geo)) {
1084 dev->hw_geom.sectors = geo.sectors;
1085 dev->hw_geom.heads = geo.heads;
1086 dev->hw_geom.cylinders = dev->length
1087 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1088 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1089 dev->bios_geom = dev->hw_geom;
1091 dev->bios_geom.sectors = 12;
1092 dev->bios_geom.heads = 15;
1093 dev->bios_geom.cylinders = dev->length
1094 / (dev->hw_geom.heads * dev->hw_geom.sectors)
1095 / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1096 dev->hw_geom = dev->bios_geom;
1099 dev->model = strdup (model_name);
1101 ped_device_close (dev);
1104 ped_exception_throw ( PED_EXCEPTION_ERROR,
1105 PED_EXCEPTION_IGNORE_CANCEL,
1109 ped_device_close (dev);
1115 init_generic (PedDevice* dev, const char* model_name)
1117 struct stat dev_stat;
1118 PedExceptionOption ex_status;
1120 if (!_device_stat (dev, &dev_stat))
1123 if (!ped_device_open (dev))
1126 ped_exception_fetch_all ();
1127 if (_device_probe_geometry (dev)) {
1128 ped_exception_leave_all ();
1130 /* hack to allow use of files, for testing */
1131 ped_exception_catch ();
1132 ped_exception_leave_all ();
1134 ex_status = ped_exception_throw (
1135 PED_EXCEPTION_WARNING,
1136 PED_EXCEPTION_IGNORE_CANCEL,
1137 _("Unable to determine geometry of "
1138 "file/device %s. You should not use Parted "
1139 "unless you REALLY know what you're doing!"),
1141 switch (ex_status) {
1142 case PED_EXCEPTION_CANCEL:
1143 goto error_close_dev;
1145 case PED_EXCEPTION_UNHANDLED:
1146 ped_exception_catch ();
1147 case PED_EXCEPTION_IGNORE:
1150 PED_ASSERT (0, (void) 0);
1154 /* what should we stick in here? */
1155 dev->length = dev_stat.st_size / PED_SECTOR_SIZE_DEFAULT;
1156 dev->bios_geom.cylinders = dev->length / 4 / 32;
1157 dev->bios_geom.heads = 4;
1158 dev->bios_geom.sectors = 32;
1159 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1160 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
1163 dev->model = strdup (model_name);
1165 ped_device_close (dev);
1169 ped_device_close (dev);
1175 sdmmc_get_product_info (PedDevice* dev, char **type, char **name)
1177 *type = read_device_sysfs_file (dev, "type");
1178 *name = read_device_sysfs_file (dev, "name");
1186 init_sdmmc (PedDevice* dev)
1191 if (sdmmc_get_product_info (dev, &type, &name)) {
1192 snprintf (id, sizeof(id) - 1, "%s %s", type, name);
1196 snprintf (id, sizeof(id) - 1, "%s",
1197 _("Generic SD/MMC Storage Card"));
1199 return init_generic(dev, id);
1203 linux_new (const char* path)
1206 LinuxSpecific* arch_specific;
1208 PED_ASSERT (path != NULL, return NULL);
1210 dev = (PedDevice*) ped_malloc (sizeof (PedDevice));
1214 dev->path = strdup (path);
1216 goto error_free_dev;
1219 = (LinuxSpecific*) ped_malloc (sizeof (LinuxSpecific));
1220 if (!dev->arch_specific)
1221 goto error_free_path;
1222 arch_specific = LINUX_SPECIFIC (dev);
1223 arch_specific->dmtype = NULL;
1225 dev->open_count = 0;
1227 dev->external_mode = 0;
1229 dev->boot_dirty = 0;
1231 if (!_device_probe_type (dev))
1232 goto error_free_arch_specific;
1234 switch (dev->type) {
1235 case PED_DEVICE_IDE:
1236 if (!init_ide (dev))
1237 goto error_free_arch_specific;
1240 case PED_DEVICE_SCSI:
1241 if (!init_scsi (dev))
1242 goto error_free_arch_specific;
1245 case PED_DEVICE_DAC960:
1246 if (!init_generic (dev, _("DAC960 RAID controller")))
1247 goto error_free_arch_specific;
1250 case PED_DEVICE_SX8:
1251 if (!init_generic (dev, _("Promise SX8 SATA Device")))
1252 goto error_free_arch_specific;
1255 case PED_DEVICE_DASD:
1256 if (!init_dasd (dev, _("IBM S390 DASD drive")))
1257 goto error_free_arch_specific;
1260 case PED_DEVICE_VIODASD:
1261 if (!init_generic (dev, _("IBM iSeries Virtual DASD")))
1262 goto error_free_arch_specific;
1265 case PED_DEVICE_CPQARRAY:
1266 if (!init_generic (dev, _("Compaq Smart Array")))
1267 goto error_free_arch_specific;
1270 case PED_DEVICE_ATARAID:
1271 if (!init_generic (dev, _("ATARAID Controller")))
1272 goto error_free_arch_specific;
1275 case PED_DEVICE_I2O:
1276 if (!init_generic (dev, _("I2O Controller")))
1277 goto error_free_arch_specific;
1280 case PED_DEVICE_UBD:
1281 if (!init_generic (dev, _("User-Mode Linux UBD")))
1282 goto error_free_arch_specific;
1285 case PED_DEVICE_FILE:
1286 if (!init_file (dev))
1287 goto error_free_arch_specific;
1293 if (arch_specific->dmtype == NULL
1294 || asprintf(&type, _("Linux device-mapper (%s)"),
1295 arch_specific->dmtype) == -1)
1296 goto error_free_arch_specific;
1297 bool ok = init_generic (dev, type);
1300 goto error_free_arch_specific;
1304 case PED_DEVICE_XVD:
1305 if (!init_generic (dev, _("Xen Virtual Block Device")))
1306 goto error_free_arch_specific;
1309 case PED_DEVICE_UNKNOWN:
1310 if (!init_generic (dev, _("Unknown")))
1311 goto error_free_arch_specific;
1314 case PED_DEVICE_SDMMC:
1315 if (!init_sdmmc (dev))
1316 goto error_free_arch_specific;
1320 ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
1321 PED_EXCEPTION_CANCEL,
1322 _("ped_device_new() Unsupported device type"));
1323 goto error_free_arch_specific;
1327 error_free_arch_specific:
1328 free (dev->arch_specific);
1338 linux_destroy (PedDevice* dev)
1340 free (((LinuxSpecific*)dev->arch_specific)->dmtype);
1341 free (dev->arch_specific);
1348 linux_is_busy (PedDevice* dev)
1353 if (_partition_is_mounted_by_path (dev->path))
1356 for (i = 0; i < 32; i++) {
1359 part_name = _device_get_part_path (dev, i);
1362 status = _partition_is_mounted_by_path (part_name);
1372 /* we need to flush the master device, and all the partition devices,
1373 * because there is no coherency between the caches.
1374 * We should only flush unmounted partition devices, because:
1375 * - there is never a need to flush them (we're not doing IO there)
1376 * - flushing a device that is mounted causes unnecessary IO, and can
1377 * even screw journaling & friends up. Even cause oopsen!
1380 _flush_cache (PedDevice* dev)
1382 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1389 ioctl (arch_specific->fd, BLKFLSBUF);
1391 for (i = 1; i < 16; i++) {
1395 name = _device_get_part_path (dev, i);
1398 if (!_partition_is_mounted_by_path (name)) {
1399 fd = open (name, WR_MODE, 0);
1401 ioctl (fd, BLKFLSBUF);
1410 linux_open (PedDevice* dev)
1412 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1415 arch_specific->fd = open (dev->path, RW_MODE);
1417 if (arch_specific->fd == -1) {
1418 char* rw_error_msg = strerror (errno);
1420 arch_specific->fd = open (dev->path, RD_MODE);
1422 if (arch_specific->fd == -1) {
1423 if (ped_exception_throw (
1424 PED_EXCEPTION_ERROR,
1425 PED_EXCEPTION_RETRY_CANCEL,
1426 _("Error opening %s: %s"),
1427 dev->path, strerror (errno))
1428 != PED_EXCEPTION_RETRY) {
1434 ped_exception_throw (
1435 PED_EXCEPTION_WARNING,
1437 _("Unable to open %s read-write (%s). %s has "
1438 "been opened read-only."),
1439 dev->path, rw_error_msg, dev->path);
1452 linux_refresh_open (PedDevice* dev)
1458 linux_close (PedDevice* dev)
1460 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1464 close (arch_specific->fd);
1469 linux_refresh_close (PedDevice* dev)
1476 #if SIZEOF_OFF_T < 8
1478 static _syscall5(int,_llseek,
1480 unsigned long, offset_high,
1481 unsigned long, offset_low,
1483 unsigned int, origin)
1486 llseek (unsigned int fd, loff_t offset, unsigned int whence)
1491 retval = _llseek(fd,
1492 ((unsigned long long)offset) >> 32,
1493 ((unsigned long long)offset) & 0xffffffff,
1496 return (retval==-1 ? (loff_t) retval : result);
1499 #endif /* SIZEOF_OFF_T < 8 */
1502 _device_seek (const PedDevice* dev, PedSector sector)
1504 LinuxSpecific* arch_specific;
1506 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1507 PED_ASSERT (dev != NULL, return 0);
1508 PED_ASSERT (!dev->external_mode, return 0);
1510 arch_specific = LINUX_SPECIFIC (dev);
1512 #if SIZEOF_OFF_T < 8
1513 if (sizeof (off_t) < 8) {
1514 loff_t pos = (loff_t)(sector * dev->sector_size);
1515 return llseek (arch_specific->fd, pos, SEEK_SET) == pos;
1519 off_t pos = sector * dev->sector_size;
1520 return lseek (arch_specific->fd, pos, SEEK_SET) == pos;
1525 _read_lastoddsector (const PedDevice* dev, void* buffer)
1527 LinuxSpecific* arch_specific;
1528 struct blkdev_ioctl_param ioctl_param;
1530 PED_ASSERT(dev != NULL, return 0);
1531 PED_ASSERT(buffer != NULL, return 0);
1533 arch_specific = LINUX_SPECIFIC (dev);
1536 ioctl_param.block = 0; /* read the last sector */
1537 ioctl_param.content_length = dev->sector_size;
1538 ioctl_param.block_contents = buffer;
1540 if (ioctl(arch_specific->fd, BLKGETLASTSECT, &ioctl_param) == -1) {
1541 PedExceptionOption opt;
1542 opt = ped_exception_throw (
1543 PED_EXCEPTION_ERROR,
1544 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1545 _("%s during read on %s"),
1546 strerror (errno), dev->path);
1548 if (opt == PED_EXCEPTION_CANCEL)
1550 if (opt == PED_EXCEPTION_RETRY)
1558 linux_read (const PedDevice* dev, void* buffer, PedSector start,
1561 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1562 PedExceptionOption ex_status;
1563 void* diobuf = NULL;
1565 PED_ASSERT (dev != NULL, return 0);
1566 PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1568 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1569 /* Kludge. This is necessary to read/write the last
1570 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1572 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1573 && start + count - 1 == dev->length - 1)
1574 return ped_device_read (dev, buffer, start, count - 1)
1575 && _read_lastoddsector (
1576 dev, (char *) buffer + (count-1) * 512);
1579 if (_device_seek (dev, start))
1582 ex_status = ped_exception_throw (
1583 PED_EXCEPTION_ERROR,
1584 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1585 _("%s during seek for read on %s"),
1586 strerror (errno), dev->path);
1588 switch (ex_status) {
1589 case PED_EXCEPTION_IGNORE:
1592 case PED_EXCEPTION_RETRY:
1595 case PED_EXCEPTION_UNHANDLED:
1596 ped_exception_catch ();
1597 case PED_EXCEPTION_CANCEL:
1600 PED_ASSERT (0, (void) 0);
1605 size_t read_length = count * dev->sector_size;
1606 if (posix_memalign (&diobuf, dev->sector_size, read_length) != 0)
1610 ssize_t status = read (arch_specific->fd, diobuf, read_length);
1612 memcpy(buffer, diobuf, status);
1613 if (status == (ssize_t) read_length)
1616 read_length -= status;
1617 buffer = (char *) buffer + status;
1621 ex_status = ped_exception_throw (
1622 PED_EXCEPTION_ERROR,
1623 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1624 _("%s during read on %s"),
1628 switch (ex_status) {
1629 case PED_EXCEPTION_IGNORE:
1633 case PED_EXCEPTION_RETRY:
1636 case PED_EXCEPTION_UNHANDLED:
1637 ped_exception_catch ();
1638 case PED_EXCEPTION_CANCEL:
1642 PED_ASSERT (0, (void) 0);
1653 _write_lastoddsector (PedDevice* dev, const void* buffer)
1655 LinuxSpecific* arch_specific;
1656 struct blkdev_ioctl_param ioctl_param;
1658 PED_ASSERT(dev != NULL, return 0);
1659 PED_ASSERT(buffer != NULL, return 0);
1661 arch_specific = LINUX_SPECIFIC (dev);
1664 ioctl_param.block = 0; /* write the last sector */
1665 ioctl_param.content_length = dev->sector_size;
1666 ioctl_param.block_contents = (void*) buffer;
1668 if (ioctl(arch_specific->fd, BLKSETLASTSECT, &ioctl_param) == -1) {
1669 PedExceptionOption opt;
1670 opt = ped_exception_throw (
1671 PED_EXCEPTION_ERROR,
1672 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1673 _("%s during write on %s"),
1674 strerror (errno), dev->path);
1676 if (opt == PED_EXCEPTION_CANCEL)
1678 if (opt == PED_EXCEPTION_RETRY)
1686 linux_write (PedDevice* dev, const void* buffer, PedSector start,
1689 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1690 PedExceptionOption ex_status;
1694 PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1696 if (dev->read_only) {
1697 if (ped_exception_throw (
1698 PED_EXCEPTION_ERROR,
1699 PED_EXCEPTION_IGNORE_CANCEL,
1700 _("Can't write to %s, because it is opened read-only."),
1702 != PED_EXCEPTION_IGNORE)
1708 if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1709 /* Kludge. This is necessary to read/write the last
1710 block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1712 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1713 && start + count - 1 == dev->length - 1)
1714 return ped_device_write (dev, buffer, start, count - 1)
1715 && _write_lastoddsector (
1716 dev, (char*) buffer + (count-1) * 512);
1719 if (_device_seek (dev, start))
1722 ex_status = ped_exception_throw (
1723 PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1724 _("%s during seek for 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);
1745 printf ("ped_device_write (\"%s\", %p, %d, %d)\n",
1746 dev->path, buffer, (int) start, (int) count);
1748 size_t write_length = count * dev->sector_size;
1750 if (posix_memalign(&diobuf, dev->sector_size, write_length) != 0)
1752 memcpy(diobuf, buffer, write_length);
1753 diobuf_start = diobuf;
1755 ssize_t status = write (arch_specific->fd, diobuf, write_length);
1756 if (status == write_length) break;
1758 write_length -= status;
1759 diobuf = (char *) diobuf + status;
1763 ex_status = ped_exception_throw (
1764 PED_EXCEPTION_ERROR,
1765 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1766 _("%s during write on %s"),
1767 strerror (errno), dev->path);
1769 switch (ex_status) {
1770 case PED_EXCEPTION_IGNORE:
1774 case PED_EXCEPTION_RETRY:
1777 case PED_EXCEPTION_UNHANDLED:
1778 ped_exception_catch ();
1779 case PED_EXCEPTION_CANCEL:
1783 PED_ASSERT (0, (void) 0);
1788 #endif /* !READ_ONLY */
1792 /* returns the number of sectors that are ok.
1795 linux_check (PedDevice* dev, void* buffer, PedSector start, PedSector count)
1797 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1802 PED_ASSERT(dev != NULL, return 0);
1804 if (!_device_seek (dev, start))
1807 if (posix_memalign(&diobuf, PED_SECTOR_SIZE_DEFAULT,
1808 count * PED_SECTOR_SIZE_DEFAULT) != 0)
1811 for (done = 0; done < count; done += status / dev->sector_size) {
1812 status = read (arch_specific->fd, diobuf,
1813 (size_t) ((count-done) * dev->sector_size));
1815 memcpy(buffer, diobuf, status);
1825 _do_fsync (PedDevice* dev)
1827 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1829 PedExceptionOption ex_status;
1832 status = fsync (arch_specific->fd);
1833 if (status >= 0) break;
1835 ex_status = ped_exception_throw (
1836 PED_EXCEPTION_ERROR,
1837 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1838 _("%s during write on %s"),
1839 strerror (errno), dev->path);
1841 switch (ex_status) {
1842 case PED_EXCEPTION_IGNORE:
1845 case PED_EXCEPTION_RETRY:
1848 case PED_EXCEPTION_UNHANDLED:
1849 ped_exception_catch ();
1850 case PED_EXCEPTION_CANCEL:
1853 PED_ASSERT (0, (void) 0);
1861 linux_sync (PedDevice* dev)
1863 PED_ASSERT (dev != NULL, return 0);
1864 PED_ASSERT (!dev->external_mode, return 0);
1868 if (!_do_fsync (dev))
1875 linux_sync_fast (PedDevice* dev)
1877 PED_ASSERT (dev != NULL, return 0);
1878 PED_ASSERT (!dev->external_mode, return 0);
1882 if (!_do_fsync (dev))
1884 /* no cache flush... */
1889 _compare_digit_state (char ch, int need_digit)
1891 return !!isdigit (ch) == need_digit;
1894 /* matches the regexp "[^0-9]+[0-9]+[^0-9]+[0-9]+$".
1895 * Motivation: accept devices looking like /dev/rd/c0d0, but
1896 * not looking like /dev/hda1 and /dev/rd/c0d0p1
1899 _match_rd_device (const char* name)
1904 /* exclude directory names from test */
1905 pos = strrchr(name, '/') ?: name;
1913 for (state = 0; state < 4; state++) {
1914 int want_digits = (state % 2 == 1);
1918 if (!_compare_digit_state (*pos, want_digits))
1921 } while (_compare_digit_state (*pos, want_digits));
1928 _probe_proc_partitions ()
1930 FILE* proc_part_file;
1931 int major, minor, size;
1933 char part_name [256];
1934 char dev_name [256];
1936 proc_part_file = fopen ("/proc/partitions", "r");
1937 if (!proc_part_file)
1940 if (fgets (buf, 256, proc_part_file) == NULL)
1943 if (fgets (buf, 256, proc_part_file) == NULL)
1946 while (fgets (buf, 512, proc_part_file)
1947 && sscanf (buf, "%d %d %d %255s", &major, &minor, &size,
1949 /* Heuristic for telling partitions and devices apart
1950 * Probably needs to be improved
1952 if (!_match_rd_device (part_name)
1953 && isdigit (part_name [strlen (part_name) - 1]))
1956 strcpy (dev_name, "/dev/");
1957 strcat (dev_name, part_name);
1958 _ped_device_probe (dev_name);
1961 fclose (proc_part_file);
1971 _skip_entry (const char *name)
1974 static struct _entry entries[] = {
1975 { ".", sizeof (".") - 1 },
1976 { "..", sizeof ("..") - 1 },
1977 { "dm-", sizeof ("dm-") - 1 },
1978 { "loop", sizeof ("loop") - 1 },
1979 { "ram", sizeof ("ram") - 1 },
1983 for (i = entries; i->name != 0; i++) {
1984 if (strncmp (name, i->name, i->len) == 0)
1995 struct dirent *dirent;
1996 char dev_name [256];
1999 if (!(blockdir = opendir ("/sys/block")))
2001 while ((dirent = readdir (blockdir))) {
2002 if (_skip_entry (dirent->d_name))
2005 if (strlen (dirent->d_name) > sizeof (dev_name) - 6)
2006 continue; /* device name too long! */
2008 strcpy (dev_name, "/dev/");
2009 strcat (dev_name, dirent->d_name);
2010 /* in /sys/block, '/'s are replaced with '!' or '.' */
2011 for (ptr = dev_name; *ptr != '\0'; ptr++) {
2012 if (*ptr == '!' || *ptr == '.')
2015 _ped_device_probe (dev_name);
2018 closedir (blockdir);
2023 _probe_standard_devices ()
2025 _ped_device_probe ("/dev/hda");
2026 _ped_device_probe ("/dev/hdb");
2027 _ped_device_probe ("/dev/hdc");
2028 _ped_device_probe ("/dev/hdd");
2029 _ped_device_probe ("/dev/hde");
2030 _ped_device_probe ("/dev/hdf");
2031 _ped_device_probe ("/dev/hdg");
2032 _ped_device_probe ("/dev/hdh");
2034 _ped_device_probe ("/dev/sda");
2035 _ped_device_probe ("/dev/sdb");
2036 _ped_device_probe ("/dev/sdc");
2037 _ped_device_probe ("/dev/sdd");
2038 _ped_device_probe ("/dev/sde");
2039 _ped_device_probe ("/dev/sdf");
2047 /* we should probe the standard devs too, even with /proc/partitions,
2048 * because /proc/partitions might return devfs stuff, and we might not
2049 * have devfs available
2051 _probe_standard_devices ();
2053 #ifdef ENABLE_DEVICE_MAPPER
2054 /* device-mapper devices aren't listed in /proc/partitions; or, if
2055 * they are, they're listed as dm-X. So, instead of relying on that,
2056 * we do our own checks.
2058 _probe_dm_devices ();
2061 /* /sys/block is more reliable and consistent; fall back to using
2062 * /proc/partitions if the former is unavailable, however.
2064 if (!_probe_sys_block ())
2065 _probe_proc_partitions ();
2069 _device_get_part_path (PedDevice* dev, int num)
2071 int path_len = strlen (dev->path);
2072 int result_len = path_len + 16;
2075 result = (char*) ped_malloc (result_len);
2079 /* Check for devfs-style /disc => /partN transformation
2080 unconditionally; the system might be using udev with devfs rules,
2081 and if not the test is harmless. */
2082 if (!strcmp (dev->path + path_len - 5, "/disc")) {
2083 /* replace /disc with /path%d */
2084 strcpy (result, dev->path);
2085 snprintf (result + path_len - 5, 16, "/part%d", num);
2086 } else if (dev->type == PED_DEVICE_DAC960
2087 || dev->type == PED_DEVICE_CPQARRAY
2088 || dev->type == PED_DEVICE_ATARAID
2089 || dev->type == PED_DEVICE_DM
2090 || isdigit (dev->path[path_len - 1]))
2091 snprintf (result, result_len, "%sp%d", dev->path, num);
2093 snprintf (result, result_len, "%s%d", dev->path, num);
2099 linux_partition_get_path (const PedPartition* part)
2101 return _device_get_part_path (part->disk->dev, part->num);
2105 _partition_get_part_dev (const PedPartition* part)
2107 struct stat dev_stat;
2108 int dev_major, dev_minor;
2110 if (!_device_stat (part->disk->dev, &dev_stat))
2112 dev_major = major (dev_stat.st_rdev);
2113 dev_minor = minor (dev_stat.st_rdev);
2114 return (dev_t)makedev (dev_major, dev_minor + part->num);
2118 _mount_table_search (const char* file_name, dev_t dev)
2120 struct stat part_stat;
2122 char part_name[512];
2126 file = fopen (file_name, "r");
2129 while (fgets (line, 512, file)) {
2130 junk = sscanf (line, "%s", part_name);
2131 if (stat (part_name, &part_stat) == 0) {
2132 if (part_stat.st_rdev == dev) {
2143 _partition_is_mounted_by_dev (dev_t dev)
2145 return _mount_table_search( "/proc/mounts", dev)
2146 || _mount_table_search( "/proc/swaps", dev)
2147 || _mount_table_search( "/etc/mtab", dev);
2151 _partition_is_mounted_by_path (const char *path)
2153 struct stat part_stat;
2154 if (stat (path, &part_stat) != 0)
2156 if (!S_ISBLK(part_stat.st_mode))
2158 return _partition_is_mounted_by_dev (part_stat.st_rdev);
2162 _partition_is_mounted (const PedPartition *part)
2165 if (!ped_partition_is_active (part))
2167 dev = _partition_get_part_dev (part);
2168 return _partition_is_mounted_by_dev (dev);
2172 linux_partition_is_busy (const PedPartition* part)
2176 PED_ASSERT (part != NULL, return 0);
2178 if (_partition_is_mounted (part))
2180 if (part->type == PED_PARTITION_EXTENDED) {
2181 for (walk = part->part_list; walk; walk = walk->next) {
2182 if (linux_partition_is_busy (walk))
2190 _blkpg_part_command (PedDevice* dev, struct blkpg_partition* part, int op)
2192 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2193 struct blkpg_ioctl_arg ioctl_arg;
2196 ioctl_arg.flags = 0;
2197 ioctl_arg.datalen = sizeof (struct blkpg_partition);
2198 ioctl_arg.data = (void*) part;
2200 return ioctl (arch_specific->fd, BLKPG, &ioctl_arg) == 0;
2204 _blkpg_add_partition (PedDisk* disk, const PedPartition *part)
2206 struct blkpg_partition linux_part;
2207 const char* vol_name;
2210 PED_ASSERT(disk != NULL, return 0);
2211 PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0,
2214 if (ped_disk_type_check_feature (disk->type,
2215 PED_DISK_TYPE_PARTITION_NAME))
2216 vol_name = ped_partition_get_name (part);
2220 dev_name = _device_get_part_path (disk->dev, part->num);
2224 memset (&linux_part, 0, sizeof (linux_part));
2225 linux_part.start = part->geom.start * disk->dev->sector_size;
2226 /* see fs/partitions/msdos.c:msdos_partition(): "leave room for LILO" */
2227 if (part->type & PED_PARTITION_EXTENDED)
2228 linux_part.length = part->geom.length == 1 ? 512 : 1024;
2230 linux_part.length = part->geom.length * disk->dev->sector_size;
2231 linux_part.pno = part->num;
2232 strncpy (linux_part.devname, dev_name, BLKPG_DEVNAMELTH);
2234 strncpy (linux_part.volname, vol_name, BLKPG_VOLNAMELTH);
2238 if (!_blkpg_part_command (disk->dev, &linux_part,
2239 BLKPG_ADD_PARTITION)) {
2240 return ped_exception_throw (
2241 PED_EXCEPTION_ERROR,
2242 PED_EXCEPTION_IGNORE_CANCEL,
2243 _("Error informing the kernel about modifications to "
2244 "partition %s -- %s. This means Linux won't know "
2245 "about any changes you made to %s until you reboot "
2246 "-- so you shouldn't mount it or use it in any way "
2247 "before rebooting."),
2251 == PED_EXCEPTION_IGNORE;
2258 _blkpg_remove_partition (PedDisk* disk, int n)
2260 struct blkpg_partition linux_part;
2262 memset (&linux_part, 0, sizeof (linux_part));
2264 return _blkpg_part_command (disk->dev, &linux_part,
2265 BLKPG_DEL_PARTITION);
2269 * The number of partitions that a device can have depends on the kernel.
2270 * If we don't find this value in /sys/block/DEV/range, we will use our own
2274 _device_get_partition_range(PedDevice* dev)
2281 r = snprintf(path, sizeof(path), "/sys/block/%s/range",
2282 last_component(dev->path));
2283 if(r < 0 || r >= sizeof(path))
2284 return MAX_NUM_PARTS;
2286 fp = fopen(path, "r");
2288 return MAX_NUM_PARTS;
2290 ok = fscanf(fp, "%d", &range) == 1;
2293 /* (range <= 0) is none sense.*/
2294 return ok && range > 0 ? range : MAX_NUM_PARTS;
2298 * Sync the partition table in two step process:
2299 * 1. Remove all of the partitions from the kernel's tables, but do not attempt
2300 * removal of any partition for which the corresponding ioctl call fails.
2301 * 2. Add all the partitions that we hold in disk.
2303 * To achieve this two step process we must calculate the minimum number of
2304 * maximum possible partitions between what linux supports and what the label
2305 * type supports. EX:
2307 * number=MIN(max_parts_supported_in_linux,max_parts_supported_in_msdos_tables)
2310 _disk_sync_part_table (PedDisk* disk)
2312 PED_ASSERT(disk != NULL, return 0);
2313 PED_ASSERT(disk->dev != NULL, return 0);
2316 /* lpn = largest partition number. */
2317 if(ped_disk_get_max_supported_partition_count(disk, &lpn))
2318 lpn = PED_MIN(lpn, _device_get_partition_range(disk->dev));
2320 lpn = _device_get_partition_range(disk->dev);
2322 /* Its not possible to support largest_partnum < 0.
2323 * largest_partnum == 0 would mean does not support partitions.
2328 int *rets = ped_malloc(sizeof(int) * lpn);
2329 int *errnums = ped_malloc(sizeof(int) * lpn);
2333 for (i = 1; i <= lpn; i++) {
2334 rets[i - 1] = _blkpg_remove_partition (disk, i);
2335 errnums[i - 1] = errno;
2338 for (i = 1; i <= lpn; i++) {
2339 const PedPartition *part = ped_disk_get_partition (disk, i);
2341 /* busy... so we won't (can't!) disturb ;) Prolly
2342 * doesn't matter anyway, because users shouldn't be
2343 * changing mounted partitions anyway...
2345 if (!rets[i - 1] && errnums[i - 1] == EBUSY)
2348 /* add the (possibly modified or new) partition */
2349 if (!_blkpg_add_partition (disk, part))
2359 #ifdef ENABLE_DEVICE_MAPPER
2361 _dm_remove_map_name(char *name)
2363 struct dm_task *task = NULL;
2366 task = dm_task_create(DM_DEVICE_REMOVE);
2370 dm_task_set_name (task, name);
2372 rc = dm_task_run(task);
2373 dm_task_update_nodes();
2374 dm_task_destroy(task);
2382 _dm_is_part (struct dm_info *this, char *name)
2384 struct dm_task* task = NULL;
2385 struct dm_info* info = alloca(sizeof *info);
2386 struct dm_deps* deps = NULL;
2390 task = dm_task_create(DM_DEVICE_DEPS);
2394 dm_task_set_name(task, name);
2395 rc = dm_task_run(task);
2402 memset(info, '\0', sizeof *info);
2403 dm_task_get_info(task, info);
2407 deps = dm_task_get_deps(task);
2412 for (i = 0; i < deps->count; i++) {
2413 unsigned int ma = major(deps->device[i]),
2414 mi = minor(deps->device[i]);
2416 if (ma == this->major && mi == this->minor)
2421 dm_task_destroy(task);
2426 _dm_remove_parts (PedDevice* dev)
2428 struct stat dev_stat;
2429 struct dm_task* task = NULL;
2430 struct dm_info* info = alloca(sizeof *info);
2431 struct dm_names* names = NULL;
2432 unsigned int next = 0;
2435 if (!_device_stat (dev, &dev_stat))
2438 task = dm_task_create(DM_DEVICE_LIST);
2442 dm_task_set_major (task, major (dev_stat.st_rdev));
2443 dm_task_set_minor (task, minor (dev_stat.st_rdev));
2445 rc = dm_task_run(task);
2449 memset(info, '\0', sizeof *info);
2450 dm_task_get_info(task, info);
2454 names = dm_task_get_names(task);
2460 names = (void *)names + next;
2462 if (_dm_is_part(info, names->name))
2463 rc += _dm_remove_map_name(names->name);
2468 dm_task_update_nodes();
2469 dm_task_destroy(task);
2476 dm_task_destroy(task);
2477 ped_exception_throw (PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE,
2478 _("parted was unable to re-read the partition "
2479 "table on %s (%s). This means Linux won't know "
2480 "anything about the modifications you made. "),
2481 dev->path, strerror (errno));
2486 _dm_add_partition (PedDisk* disk, PedPartition* part)
2488 struct stat dev_stat;
2489 struct dm_task* task = NULL;
2491 char* vol_name = NULL;
2492 char* dev_name = NULL;
2493 char* params = NULL;
2495 dev_name = _device_get_part_path (disk->dev, part->num);
2499 vol_name = strrchr (dev_name, '/');
2500 if (vol_name && *vol_name && *(++vol_name))
2501 vol_name = strdup (vol_name);
2503 vol_name = strdup (dev_name);
2507 if (!_device_stat (disk->dev, &dev_stat))
2510 if (asprintf (¶ms, "%d:%d %lld", major (dev_stat.st_rdev),
2511 minor (dev_stat.st_rdev), part->geom.start) == -1)
2517 task = dm_task_create (DM_DEVICE_CREATE);
2521 dm_task_set_name (task, vol_name);
2522 dm_task_add_target (task, 0, part->geom.length,
2524 rc = dm_task_run(task);
2526 //printf("0 %ld linear %s\n", part->geom.length, params);
2527 dm_task_update_nodes();
2528 dm_task_destroy(task);
2533 _dm_remove_map_name(vol_name);
2536 dm_task_update_nodes();
2538 dm_task_destroy (task);
2545 _dm_reread_part_table (PedDisk* disk)
2547 int largest_partnum = ped_disk_get_last_partition_num (disk);
2548 if (largest_partnum <= 0)
2552 int last = PED_MIN (largest_partnum, 16);
2556 if (!_dm_remove_parts(disk->dev))
2559 for (i = 1; i <= last; i++) {
2562 part = ped_disk_get_partition (disk, i);
2566 if (!_dm_add_partition (disk, part))
2574 _kernel_reread_part_table (PedDevice* dev)
2576 LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
2577 int retry_count = 5;
2580 while (ioctl (arch_specific->fd, BLKRRPART)) {
2584 ped_exception_throw (
2585 PED_EXCEPTION_WARNING,
2586 PED_EXCEPTION_IGNORE,
2587 _("The kernel was unable to re-read the partition "
2588 "table on %s (%s). This means Linux won't know "
2589 "anything about the modifications you made "
2590 "until you reboot. You should reboot your computer "
2591 "before doing anything with %s."),
2592 dev->path, strerror (errno), dev->path);
2603 static int have_blkpg = -1;
2606 if (have_blkpg != -1)
2609 kver = _get_linux_version();
2610 return have_blkpg = kver >= KERNEL_VERSION (2,4,0) ? 1 : 0;
2614 linux_disk_commit (PedDisk* disk)
2616 #ifdef ENABLE_DEVICE_MAPPER
2617 if (disk->dev->type == PED_DEVICE_DM)
2618 return _dm_reread_part_table (disk);
2620 if (disk->dev->type != PED_DEVICE_FILE) {
2621 /* The ioctl() command BLKPG_ADD_PARTITION does not notify
2622 * the devfs system; consequently, /proc/partitions will not
2623 * be up to date, and the proper links in /dev are not
2624 * created. Therefore, if using DevFS, we must get the kernel
2625 * to re-read and grok the partition table.
2627 /* Work around kernel dasd problem so we really do BLKRRPART */
2628 if (disk->dev->type != PED_DEVICE_DASD &&
2629 _have_blkpg () && !_have_devfs ()) {
2630 if (_disk_sync_part_table (disk))
2634 return _kernel_reread_part_table (disk->dev);
2640 static PedDeviceArchOps linux_dev_ops = {
2642 destroy: linux_destroy,
2643 is_busy: linux_is_busy,
2645 refresh_open: linux_refresh_open,
2647 refresh_close: linux_refresh_close,
2652 sync_fast: linux_sync_fast,
2653 probe_all: linux_probe_all
2656 PedDiskArchOps linux_disk_ops = {
2657 partition_get_path: linux_partition_get_path,
2658 partition_is_busy: linux_partition_is_busy,
2659 disk_commit: linux_disk_commit
2662 PedArchitecture ped_linux_arch = {
2663 dev_ops: &linux_dev_ops,
2664 disk_ops: &linux_disk_ops