OSDN Git Service

linux: add wait time and retries to kernel partition reread
[android-x86/external-parted.git] / libparted / arch / linux.c
1 /* libparted - a library for manipulating disk partitions
2     Copyright (C) 1999-2010 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>.
16 */
17
18 #define PROC_DEVICES_BUFSIZ 16384
19
20 #include <config.h>
21 #include <arch/linux.h>
22
23 #include <parted/parted.h>
24 #include <parted/debug.h>
25 #if defined __s390__ || defined __s390x__
26 #include <parted/fdasd.h>
27 #endif
28
29 #include <ctype.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <libgen.h>
33 #include <stdio.h>
34 #include <syscall.h>
35 #include <unistd.h>
36 #include <stdbool.h>
37 #include <dirent.h>
38 #include <sys/ioctl.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <sys/utsname.h>        /* for uname() */
42 #include <scsi/scsi.h>
43 #ifdef ENABLE_DEVICE_MAPPER
44 #include <libdevmapper.h>
45 #endif
46
47 #include "../architecture.h"
48 #include "dirname.h"
49
50 #if ENABLE_NLS
51 #  include <libintl.h>
52 #  define _(String) dgettext (PACKAGE, String)
53 #else
54 #  define _(String) (String)
55 #endif /* ENABLE_NLS */
56
57 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
58
59 #ifndef __NR__llseek
60 #define __NR__llseek 140
61 #endif
62
63 #ifndef SCSI_IOCTL_SEND_COMMAND
64 #define SCSI_IOCTL_SEND_COMMAND 1
65 #endif
66
67 /* from <linux/hdreg.h> */
68 #define HDIO_GETGEO             0x0301  /* get device geometry */
69 #define HDIO_GET_IDENTITY       0x030d  /* get IDE identification info */
70
71 #define RD_MODE (O_RDONLY)
72 #define WR_MODE (O_WRONLY)
73 #define RW_MODE (O_RDWR)
74
75 struct hd_geometry {
76         unsigned char heads;
77         unsigned char sectors;
78         unsigned short cylinders;
79         unsigned long start;
80 };
81
82 struct ata7_sectinfo {
83         int valid1:1;
84         int valid2:1;
85         int rsv:26;
86         int multiplier:4;
87 };
88
89 /* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
90 struct hd_driveid {
91         unsigned short  config;         /* lots of obsolete bit flags */
92         unsigned short  cyls;           /* "physical" cyls */
93         unsigned short  reserved2;      /* reserved (word 2) */
94         unsigned short  heads;          /* "physical" heads */
95         unsigned short  track_bytes;    /* unformatted bytes per track */
96         unsigned short  sector_bytes;   /* unformatted bytes per sector */
97         unsigned short  sectors;        /* "physical" sectors per track */
98         unsigned short  vendor0;        /* vendor unique */
99         unsigned short  vendor1;        /* vendor unique */
100         unsigned short  vendor2;        /* vendor unique */
101         unsigned char   serial_no[20];  /* 0 = not_specified */
102         unsigned short  buf_type;
103         unsigned short  buf_size;       /* 512 byte increments;
104                                                          0 = not_specified */
105         unsigned short  ecc_bytes;      /* for r/w long cmds;
106                                                          0 = not_specified */
107         unsigned char   fw_rev[8];      /* 0 = not_specified */
108         char            model[40];      /* 0 = not_specified */
109         unsigned char   max_multsect;   /* 0=not_implemented */
110         unsigned char   vendor3;        /* vendor unique */
111         unsigned short  dword_io;       /* 0=not_implemented; 1=implemented */
112         unsigned char   vendor4;        /* vendor unique */
113         unsigned char   capability;     /* bits 0:DMA 1:LBA 2:IORDYsw
114                                                 3:IORDYsup*/
115         unsigned short  reserved50;     /* reserved (word 50) */
116         unsigned char   vendor5;        /* vendor unique */
117         unsigned char   tPIO;           /* 0=slow, 1=medium, 2=fast */
118         unsigned char   vendor6;        /* vendor unique */
119         unsigned char   tDMA;           /* 0=slow, 1=medium, 2=fast */
120         unsigned short  field_valid;    /* bits 0:cur_ok 1:eide_ok */
121         unsigned short  cur_cyls;       /* logical cylinders */
122         unsigned short  cur_heads;      /* logical heads */
123         unsigned short  cur_sectors;    /* logical sectors per track */
124         unsigned short  cur_capacity0;  /* logical total sectors on drive */
125         unsigned short  cur_capacity1;  /*  (2 words, misaligned int)     */
126         unsigned char   multsect;       /* current multiple sector count */
127         unsigned char   multsect_valid; /* when (bit0==1) multsect is ok */
128         unsigned int    lba_capacity;   /* total number of sectors */
129         unsigned short  dma_1word;      /* single-word dma info */
130         unsigned short  dma_mword;      /* multiple-word dma info */
131         unsigned short  eide_pio_modes; /* bits 0:mode3 1:mode4 */
132         unsigned short  eide_dma_min;   /* min mword dma cycle time (ns) */
133         unsigned short  eide_dma_time;  /* recommended mword dma cycle
134                                            time (ns) */
135         unsigned short  eide_pio;       /* min cycle time (ns), no IORDY  */
136         unsigned short  eide_pio_iordy; /* min cycle time (ns), with IORDY */
137         unsigned short  words69_70[2];  /* reserved words 69-70 */
138         /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
139         unsigned short  words71_74[4];  /* reserved words 71-74 */
140         unsigned short  queue_depth;    /*  */
141         unsigned short  words76_79[4];  /* reserved words 76-79 */
142         unsigned short  major_rev_num;  /*  */
143         unsigned short  minor_rev_num;  /*  */
144         unsigned short  command_set_1;  /* bits 0:Smart 1:Security 2:Removable
145                                                 3:PM */
146         unsigned short  command_set_2;  /* bits 14:Smart Enabled 13:0 zero */
147         unsigned short  cfsse;          /* command set-feature supported
148                                            extensions */
149         unsigned short  cfs_enable_1;   /* command set-feature enabled */
150         unsigned short  cfs_enable_2;   /* command set-feature enabled */
151         unsigned short  csf_default;    /* command set-feature default */
152         unsigned short  dma_ultra;      /*  */
153         unsigned short  word89;         /* reserved (word 89) */
154         unsigned short  word90;         /* reserved (word 90) */
155         unsigned short  CurAPMvalues;   /* current APM values */
156         unsigned short  word92;         /* reserved (word 92) */
157         unsigned short  hw_config;      /* hardware config */
158         unsigned short  words94_105[12];/* reserved words 94-105 */
159         struct ata7_sectinfo ata7_sectinfo; /* ATAPI/ATA7 physical and logical
160                                                sector size */
161         unsigned short  words107_116[10];/* reserved words 107-116 */
162         unsigned int    logical_sectsize;/* ATAPI/ATA7 logical sector size */
163         unsigned short  words119_125[7];/* reserved words 119-125 */
164         unsigned short  last_lun;       /* reserved (word 126) */
165         unsigned short  word127;        /* reserved (word 127) */
166         unsigned short  dlf;            /* device lock function
167                                          * 15:9 reserved
168                                          * 8    security level 1:max 0:high
169                                          * 7:6  reserved
170                                          * 5    enhanced erase
171                                          * 4    expire
172                                          * 3    frozen
173                                          * 2    locked
174                                          * 1    en/disabled
175                                          * 0    capability
176                                          */
177         unsigned short  csfo;           /* current set features options
178                                          * 15:4 reserved
179                                          * 3    auto reassign
180                                          * 2    reverting
181                                          * 1    read-look-ahead
182                                          * 0    write cache
183                                          */
184         unsigned short  words130_155[26];/* reserved vendor words 130-155 */
185         unsigned short  word156;
186         unsigned short  words157_159[3]; /* reserved vendor words 157-159 */
187         unsigned short  words160_255[95];/* reserved words 160-255 */
188 };
189
190 /* from <linux/fs.h> */
191 #define BLKRRPART  _IO(0x12,95) /* re-read partition table */
192 #define BLKGETSIZE _IO(0x12,96) /* return device size */
193 #define BLKFLSBUF  _IO(0x12,97) /* flush buffer cache */
194 #define BLKSSZGET  _IO(0x12,104) /* get block device sector size */
195 #define BLKGETLASTSECT  _IO(0x12,108) /* get last sector of block device */
196 #define BLKSETLASTSECT  _IO(0x12,109) /* set last sector of block device */
197
198 /* return device size in bytes (u64 *arg) */
199 #define BLKGETSIZE64 _IOR(0x12,114,size_t)
200
201 struct blkdev_ioctl_param {
202         unsigned int block;
203         size_t content_length;
204         char * block_contents;
205 };
206
207 /* from <linux/major.h> */
208 #define IDE0_MAJOR              3
209 #define IDE1_MAJOR              22
210 #define IDE2_MAJOR              33
211 #define IDE3_MAJOR              34
212 #define IDE4_MAJOR              56
213 #define IDE5_MAJOR              57
214 #define SCSI_CDROM_MAJOR        11
215 #define SCSI_DISK0_MAJOR        8
216 #define SCSI_DISK1_MAJOR        65
217 #define SCSI_DISK2_MAJOR        66
218 #define SCSI_DISK3_MAJOR        67
219 #define SCSI_DISK4_MAJOR        68
220 #define SCSI_DISK5_MAJOR        69
221 #define SCSI_DISK6_MAJOR        70
222 #define SCSI_DISK7_MAJOR        71
223 #define COMPAQ_SMART2_MAJOR     72
224 #define COMPAQ_SMART2_MAJOR1    73
225 #define COMPAQ_SMART2_MAJOR2    74
226 #define COMPAQ_SMART2_MAJOR3    75
227 #define COMPAQ_SMART2_MAJOR4    76
228 #define COMPAQ_SMART2_MAJOR5    77
229 #define COMPAQ_SMART2_MAJOR6    78
230 #define COMPAQ_SMART2_MAJOR7    79
231 #define COMPAQ_SMART_MAJOR      104
232 #define COMPAQ_SMART_MAJOR1     105
233 #define COMPAQ_SMART_MAJOR2     106
234 #define COMPAQ_SMART_MAJOR3     107
235 #define COMPAQ_SMART_MAJOR4     108
236 #define COMPAQ_SMART_MAJOR5     109
237 #define COMPAQ_SMART_MAJOR6     110
238 #define COMPAQ_SMART_MAJOR7     111
239 #define DAC960_MAJOR            48
240 #define ATARAID_MAJOR           114
241 #define I2O_MAJOR1              80
242 #define I2O_MAJOR2              81
243 #define I2O_MAJOR3              82
244 #define I2O_MAJOR4              83
245 #define I2O_MAJOR5              84
246 #define I2O_MAJOR6              85
247 #define I2O_MAJOR7              86
248 #define I2O_MAJOR8              87
249 #define UBD_MAJOR               98
250 #define DASD_MAJOR              94
251 #define VIODASD_MAJOR           112
252 #define SX8_MAJOR1              160
253 #define SX8_MAJOR2              161
254 #define XVD_MAJOR               202
255 #define SDMMC_MAJOR             179
256 #define LOOP_MAJOR              7
257
258 #define SCSI_BLK_MAJOR(M) (                                             \
259                 (M) == SCSI_DISK0_MAJOR                                 \
260                 || (M) == SCSI_CDROM_MAJOR                              \
261                 || ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
262
263 /* Maximum number of partitions supported by linux. */
264 #define MAX_NUM_PARTS           64
265
266 static char* _device_get_part_path (PedDevice* dev, int num);
267 static int _partition_is_mounted_by_path (const char* path);
268
269 static int
270 _read_fd (int fd, char **buf)
271 {
272         char* p;
273         size_t size = PROC_DEVICES_BUFSIZ;
274         int s, filesize = 0;
275
276         *buf = malloc (size * sizeof (char));
277         if (*buf == 0) {
278                 return -1;
279         }
280
281         do {
282                 p = &(*buf) [filesize];
283                 s = read (fd, p, PROC_DEVICES_BUFSIZ);
284                 /* exit if there is an error or EOF is reached */
285                 if (s <= 0)
286                         break;
287                 filesize += s;
288                 size += s;
289                 char *new_buf = realloc (*buf, size);
290                 if (new_buf == NULL) {
291                         int saved_errno = errno;
292                         free (*buf);
293                         errno = saved_errno;
294                         return -1;
295                 }
296                 *buf = new_buf;
297         } while (1);
298
299         if (filesize == 0 && s < 0) {
300                 free (*buf);
301                 *buf = NULL;
302                 return -1;
303         } else {
304                 char *new_buf = realloc (*buf, filesize + 1);
305                 if (new_buf == NULL) {
306                         int saved_errno = errno;
307                         free (*buf);
308                         errno = saved_errno;
309                         return -1;
310                 }
311                 *buf = new_buf;
312                 (*buf)[filesize] = '\0';
313         }
314
315         return filesize;
316 }
317
318 static int
319 _major_type_in_devices (int major, const char* type)
320 {
321         int fd;
322         char* buf = NULL;
323         char* line;
324         char* end;
325         int bd = 0;
326         char c;
327
328         fd = open ("/proc/devices", O_RDONLY);
329         if (fd < 0)
330                 return 0;
331
332         if (_read_fd(fd, &buf) < 0) {
333                 close(fd);
334                 return 0;
335         }
336
337         line = buf;
338         end = strchr(line, '\n');
339         while (end) {
340                 char *name;
341                 int maj;
342
343                 c = *end;
344                 *end = '\0';
345
346                 if (!bd) {
347                         if (!strncmp(line, "Block devices:", 14))
348                                 bd = 1;
349                         goto next;
350                 }
351
352                 name = strrchr(line, ' ');
353                 if (!name || strcmp(name+1, type))
354                         goto next;
355
356                 maj = strtol(line, &name, 10);
357                 if (maj == major) {
358                         free(buf);
359                         close(fd);
360                         return 1;
361                 }
362
363 next:
364                 *end = c;
365                 line = end+1;
366                 end = strchr(line, '\n');
367         }
368         free(buf);
369         close(fd);
370         return 0;
371 }
372
373 static int
374 _is_ide_major (int major)
375 {
376         switch (major) {
377                 case IDE0_MAJOR:
378                 case IDE1_MAJOR:
379                 case IDE2_MAJOR:
380                 case IDE3_MAJOR:
381                 case IDE4_MAJOR:
382                 case IDE5_MAJOR:
383                         return 1;
384
385                 default:
386                         return 0;
387         }
388 }
389
390 static int
391 _is_cpqarray_major (int major)
392 {
393         return ((COMPAQ_SMART2_MAJOR <= major && major <= COMPAQ_SMART2_MAJOR7)
394              || (COMPAQ_SMART_MAJOR <= major && major <= COMPAQ_SMART_MAJOR7));
395 }
396
397 static int
398 _is_i2o_major (int major)
399 {
400         return (I2O_MAJOR1 <= major && major <= I2O_MAJOR8);
401 }
402
403 static int
404 _is_sx8_major (int major)
405 {
406         return (SX8_MAJOR1 <= major && major <= SX8_MAJOR2);
407 }
408
409 static int
410 _is_virtblk_major (int major)
411 {
412         return _major_type_in_devices (major, "virtblk");
413 }
414
415 #ifdef ENABLE_DEVICE_MAPPER
416 static int
417 _is_dm_major (int major)
418 {
419         return _major_type_in_devices (major, "device-mapper");
420 }
421
422 static int
423 _dm_maptype (PedDevice *dev)
424 {
425         LinuxSpecific*  arch_specific = LINUX_SPECIFIC (dev);
426         struct dm_task *dmt;
427         uint64_t start, length;
428         char *target_type = NULL;
429         char *params;
430         int r = -1;
431         const char* dev_dir = getenv ("DM_DEV_DIR");
432
433         if (dev_dir && *dev_dir && !dm_set_dev_dir(dev_dir))
434                 return r;
435
436         if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
437                 return r;
438
439         if (!dm_task_set_major_minor(dmt, arch_specific->major,
440                                      arch_specific->minor, 0))
441                 goto bad;
442
443         dm_task_no_open_count(dmt);
444
445         if (!dm_task_run(dmt))
446                 goto bad;
447
448         dm_get_next_target(dmt, NULL, &start, &length, &target_type, &params);
449
450         arch_specific->dmtype = strdup(target_type ? target_type : "NO-TARGET");
451         if (arch_specific->dmtype == NULL)
452                 goto bad;
453         r = 0;
454 bad:
455         dm_task_destroy(dmt);
456         return r;
457 }
458
459
460 static int
461 _probe_dm_devices ()
462 {
463        DIR*            mapper_dir;
464        struct dirent*  dent;
465        char            buf [512];      /* readdir(3) claims d_name[256] */
466        struct stat     st;
467
468        mapper_dir = opendir ("/dev/mapper");
469        if (!mapper_dir)
470                return 0;
471
472        /* Search the /dev/mapper directory for devices w/ the same major
473         * number that was returned from _probe_lvm_major().
474         */
475        while ((dent = readdir (mapper_dir))) {
476                if (strcmp (dent->d_name, ".")  == 0 ||
477                    strcmp (dent->d_name, "..") == 0)
478                        continue;
479
480                snprintf (buf, sizeof (buf), "/dev/mapper/%s", dent->d_name);
481
482                if (stat (buf, &st) != 0)
483                        continue;
484
485                if (_is_dm_major(major(st.st_rdev)))
486                        _ped_device_probe (buf);
487        }
488        closedir (mapper_dir);
489
490        return 1;
491 }
492 #endif
493
494 static int
495 _device_stat (PedDevice* dev, struct stat * dev_stat)
496 {
497         PED_ASSERT (dev != NULL, return 0);
498         PED_ASSERT (!dev->external_mode, return 0);
499
500         while (1) {
501                 if (!stat (dev->path, dev_stat)) {
502                         return 1;
503                 } else {
504                         if (ped_exception_throw (
505                                 PED_EXCEPTION_ERROR,
506                                 PED_EXCEPTION_RETRY_CANCEL,
507                                 _("Could not stat device %s - %s."),
508                                 dev->path,
509                                 strerror (errno))
510                                         != PED_EXCEPTION_RETRY)
511                                 return 0;
512                 }
513         }
514 }
515
516 static int
517 _device_probe_type (PedDevice* dev)
518 {
519         struct stat             dev_stat;
520         int                     dev_major;
521         int                     dev_minor;
522         LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
523
524         if (!_device_stat (dev, &dev_stat))
525                 return 0;
526
527         if (!S_ISBLK(dev_stat.st_mode)) {
528                 dev->type = PED_DEVICE_FILE;
529                 return 1;
530         }
531
532         arch_specific->major = dev_major = major (dev_stat.st_rdev);
533         arch_specific->minor = dev_minor = minor (dev_stat.st_rdev);
534
535         if (SCSI_BLK_MAJOR (dev_major) && (dev_minor % 0x10 == 0)) {
536                 dev->type = PED_DEVICE_SCSI;
537         } else if (_is_ide_major (dev_major) && (dev_minor % 0x40 == 0)) {
538                 dev->type = PED_DEVICE_IDE;
539         } else if (dev_major == DAC960_MAJOR && (dev_minor % 0x8 == 0)) {
540                 dev->type = PED_DEVICE_DAC960;
541         } else if (dev_major == ATARAID_MAJOR && (dev_minor % 0x10 == 0)) {
542                 dev->type = PED_DEVICE_ATARAID;
543         } else if (dev_major == DASD_MAJOR && (dev_minor % 0x4 == 0)) {
544                 dev->type = PED_DEVICE_DASD;
545         } else if (dev_major == VIODASD_MAJOR && (dev_minor % 0x8 == 0)) {
546                 dev->type = PED_DEVICE_VIODASD;
547         } else if (_is_sx8_major(dev_major) && (dev_minor % 0x20 == 0)) {
548                 dev->type = PED_DEVICE_SX8;
549         } else if (_is_i2o_major (dev_major) && (dev_minor % 0x10 == 0)) {
550                 dev->type = PED_DEVICE_I2O;
551         } else if (_is_cpqarray_major (dev_major) && (dev_minor % 0x10 == 0)) {
552                 dev->type = PED_DEVICE_CPQARRAY;
553         } else if (dev_major == UBD_MAJOR && (dev_minor % 0x10 == 0)) {
554                 dev->type = PED_DEVICE_UBD;
555 #ifdef ENABLE_DEVICE_MAPPER
556         } else if (_is_dm_major(dev_major)) {
557                 dev->type = PED_DEVICE_DM;
558                 if (_dm_maptype(dev)) {
559                         ped_exception_throw (
560                                 PED_EXCEPTION_BUG,
561                                 PED_EXCEPTION_CANCEL,
562                                 _("Unable to determine the dm type of %s."),
563                                 dev->path);
564                 }
565 #endif
566         } else if (dev_major == XVD_MAJOR && (dev_minor % 0x10 == 0)) {
567                 dev->type = PED_DEVICE_XVD;
568         } else if (dev_major == SDMMC_MAJOR && (dev_minor % 0x08 == 0)) {
569                 dev->type = PED_DEVICE_SDMMC;
570         } else if (_is_virtblk_major(dev_major)) {
571                 dev->type = PED_DEVICE_VIRTBLK;
572         } else if (dev_major == LOOP_MAJOR) {
573                 dev->type = PED_DEVICE_FILE;
574         } else {
575                 dev->type = PED_DEVICE_UNKNOWN;
576         }
577
578         return 1;
579 }
580
581 static int
582 _get_linux_version ()
583 {
584         static int kver = -1;
585
586         struct utsname uts;
587         int major;
588         int minor;
589         int teeny;
590
591         if (kver != -1)
592                 return kver;
593
594         if (uname (&uts))
595                 return kver = 0;
596         if (sscanf (uts.release, "%u.%u.%u", &major, &minor, &teeny) != 3)
597                 return kver = 0;
598
599         return kver = KERNEL_VERSION (major, minor, teeny);
600 }
601
602 static int
603 _have_kern26 ()
604 {
605         static int have_kern26 = -1;
606         int kver;
607
608         if (have_kern26 != -1)
609                 return have_kern26;
610
611         kver = _get_linux_version();
612         return have_kern26 = kver >= KERNEL_VERSION (2,6,0) ? 1 : 0;
613 }
614
615 #if USE_BLKID
616 static void
617 get_blkid_topology (LinuxSpecific *arch_specific)
618 {
619         arch_specific->probe = blkid_new_probe ();
620         if (!arch_specific->probe)
621                 return;
622
623         if (blkid_probe_set_device(arch_specific->probe,
624                                    arch_specific->fd, 0, 0))
625                 return;
626
627         arch_specific->topology =
628                 blkid_probe_get_topology(arch_specific->probe);
629 }
630 #endif
631
632 static void
633 _device_set_sector_size (PedDevice* dev)
634 {
635         LinuxSpecific*  arch_specific = LINUX_SPECIFIC (dev);
636         int sector_size;
637
638         dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
639         dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
640
641         PED_ASSERT (dev->open_count, return);
642
643         if (_get_linux_version() < KERNEL_VERSION (2,3,0)) {
644                 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
645                 return;
646         }
647
648         if (ioctl (arch_specific->fd, BLKSSZGET, &sector_size)) {
649                 ped_exception_throw (
650                         PED_EXCEPTION_WARNING,
651                         PED_EXCEPTION_OK,
652                         _("Could not determine sector size for %s: %s.\n"
653                           "Using the default sector size (%lld)."),
654                         dev->path, strerror (errno), PED_SECTOR_SIZE_DEFAULT);
655         } else {
656                 dev->sector_size = (long long)sector_size;
657                 dev->phys_sector_size = dev->sector_size;
658         }
659
660 #if USE_BLKID
661         get_blkid_topology(arch_specific);
662         if (!arch_specific->topology) {
663                 dev->phys_sector_size = 0;
664         } else {
665                 dev->phys_sector_size =
666                         blkid_topology_get_physical_sector_size(
667                                 arch_specific->topology);
668         }
669         if (dev->phys_sector_size == 0) {
670                 ped_exception_throw (
671                         PED_EXCEPTION_WARNING,
672                         PED_EXCEPTION_OK,
673                         _("Could not determine physical sector size for %s.\n"
674                           "Using the logical sector size (%lld)."),
675                         dev->path, dev->sector_size);
676                 dev->phys_sector_size = dev->sector_size;
677         }
678 #endif
679
680 #if defined __s390__ || defined __s390x__
681         /* Return PED_SECTOR_SIZE_DEFAULT for DASDs. */
682         if (dev->type == PED_DEVICE_DASD) {
683                 arch_specific->real_sector_size = dev->sector_size;
684                 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
685         }
686 #endif
687
688         if (dev->sector_size != PED_SECTOR_SIZE_DEFAULT) {
689                 ped_exception_throw (
690                         PED_EXCEPTION_WARNING,
691                         PED_EXCEPTION_OK,
692                         _("Device %s has a logical sector size of %lld.  Not "
693                           "all parts of GNU Parted support this at the moment, "
694                           "and the working code is HIGHLY EXPERIMENTAL.\n"),
695                         dev->path, dev->sector_size);
696         }
697 }
698
699 static int
700 _kernel_has_blkgetsize64(void)
701 {
702         int version = _get_linux_version();
703
704         if (version >= KERNEL_VERSION (2,5,4)) return 1;
705         if (version <  KERNEL_VERSION (2,5,0) &&
706             version >= KERNEL_VERSION (2,4,18)) return 1;
707         return 0;
708 }
709
710 /* TODO: do a binary search if BLKGETSIZE doesn't work?! */
711 static PedSector
712 _device_get_length (PedDevice* dev)
713 {
714         unsigned long           size;
715         LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
716         uint64_t bytes=0;
717
718
719         PED_ASSERT (dev->open_count > 0, return 0);
720         PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
721
722         if (_kernel_has_blkgetsize64()) {
723                 if (ioctl(arch_specific->fd, BLKGETSIZE64, &bytes) == 0) {
724                         return bytes / dev->sector_size;
725                 }
726         }
727
728         if (ioctl (arch_specific->fd, BLKGETSIZE, &size)) {
729                 ped_exception_throw (
730                         PED_EXCEPTION_BUG,
731                         PED_EXCEPTION_CANCEL,
732                         _("Unable to determine the size of %s (%s)."),
733                         dev->path,
734                         strerror (errno));
735                 return 0;
736         }
737
738         return size;
739 }
740
741 static int
742 _device_probe_geometry (PedDevice* dev)
743 {
744         LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
745         struct stat             dev_stat;
746         struct hd_geometry      geometry;
747
748         if (!_device_stat (dev, &dev_stat))
749                 return 0;
750         PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
751
752         _device_set_sector_size (dev);
753
754         dev->length = _device_get_length (dev);
755         if (!dev->length)
756                 return 0;
757
758         /* The GETGEO ioctl is no longer useful (as of linux 2.6.x).  We could
759          * still use it in 2.4.x, but this is contentious.  Perhaps we should
760          * move to EDD. */
761         dev->bios_geom.sectors = 63;
762         dev->bios_geom.heads = 255;
763         dev->bios_geom.cylinders
764                 = dev->length / (63 * 255);
765
766         /* FIXME: what should we put here?  (TODO: discuss on linux-kernel) */
767         if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geometry)
768                         && geometry.sectors && geometry.heads) {
769                 dev->hw_geom.sectors = geometry.sectors;
770                 dev->hw_geom.heads = geometry.heads;
771                 dev->hw_geom.cylinders
772                         = dev->length / (dev->hw_geom.heads
773                                          * dev->hw_geom.sectors);
774         } else {
775                 dev->hw_geom = dev->bios_geom;
776         }
777
778         return 1;
779 }
780
781 static char*
782 strip_name(char* str)
783 {
784         int     i;
785         int     end = 0;
786
787         for (i = 0; str[i] != 0; i++) {
788                 if (!isspace (str[i])
789                     || (isspace (str[i]) && !isspace (str[i+1]) && str[i+1])) {
790                         str [end] = str[i];
791                         end++;
792                 }
793         }
794         str[end] = 0;
795         return strdup (str);
796 }
797
798 static int
799 init_ide (PedDevice* dev)
800 {
801         LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
802         struct stat             dev_stat;
803         struct hd_driveid       hdi;
804         PedExceptionOption      ex_status;
805         char                    hdi_buf[41];
806         int                     sector_multiplier = 0;
807
808         if (!_device_stat (dev, &dev_stat))
809                 goto error;
810
811         if (!ped_device_open (dev))
812                 goto error;
813
814         if (ioctl (arch_specific->fd, HDIO_GET_IDENTITY, &hdi)) {
815                 ex_status = ped_exception_throw (
816                                 PED_EXCEPTION_WARNING,
817                                 PED_EXCEPTION_IGNORE_CANCEL,
818                                 _("Could not get identity of device %s - %s"),
819                                 dev->path, strerror (errno));
820                 switch (ex_status) {
821                         case PED_EXCEPTION_CANCEL:
822                                 goto error_close_dev;
823
824                         case PED_EXCEPTION_UNHANDLED:
825                                 ped_exception_catch ();
826                         case PED_EXCEPTION_IGNORE:
827                                 dev->model = strdup(_("Generic IDE"));
828                                 break;
829                         default:
830                                 PED_ASSERT (0, (void) 0);
831                                 break;
832                 }
833         } else {
834                 /* hdi.model is not guaranteed to be NULL terminated */
835                 memcpy (hdi_buf, hdi.model, 40);
836                 hdi_buf[40] = '\0';
837                 dev->model = strip_name (hdi_buf);
838
839                 if (!hdi.ata7_sectinfo.valid1 && hdi.ata7_sectinfo.valid2)
840                         sector_multiplier = hdi.ata7_sectinfo.multiplier;
841                 else
842                         sector_multiplier = 1;
843
844                 if (sector_multiplier != 1) {
845                         ex_status = ped_exception_throw (
846                                 PED_EXCEPTION_WARNING,
847                                 PED_EXCEPTION_IGNORE_CANCEL,
848                                 _("Device %s has multiple (%d) logical sectors "
849                                   "per physical sector.\n"
850                                   "GNU Parted supports this EXPERIMENTALLY for "
851                                   "some special disk label/file system "
852                                   "combinations, e.g. GPT and ext2/3.\n"
853                                   "Please consult the web site for up-to-date "
854                                   "information."),
855                                 dev->path, sector_multiplier);
856
857                         switch (ex_status) {
858                                 case PED_EXCEPTION_CANCEL:
859                                         goto error_close_dev;
860
861                                 case PED_EXCEPTION_UNHANDLED:
862                                         ped_exception_catch ();
863                                 case PED_EXCEPTION_IGNORE:
864                                         break;
865                                 default:
866                                         PED_ASSERT (0, (void) 0);
867                                         break;
868                         }
869                 }
870
871                 /* XXX sector_size has not been set yet! */
872                 /* dev->phys_sector_size = dev->sector_size
873                    * sector_multiplier;*/
874                 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
875         }
876
877         if (!_device_probe_geometry (dev))
878                 goto error_close_dev;
879
880         ped_device_close (dev);
881         return 1;
882
883 error_close_dev:
884         ped_device_close (dev);
885 error:
886         return 0;
887 }
888
889 /* This function reads the /sys entry named "file" for device "dev". */
890 static char *
891 read_device_sysfs_file (PedDevice *dev, const char *file)
892 {
893         FILE *f;
894         char name_buf[128];
895         char buf[256];
896
897         snprintf (name_buf, 127, "/sys/block/%s/device/%s",
898                   last_component (dev->path), file);
899
900         if ((f = fopen (name_buf, "r")) == NULL)
901                 return NULL;
902
903         if (fgets (buf, 255, f) == NULL)
904                 return NULL;
905
906         fclose (f);
907         return strip_name (buf);
908 }
909
910 /* This function sends a query to a SCSI device for vendor and product
911  * information.  It uses the deprecated SCSI_IOCTL_SEND_COMMAND to
912  * issue this query.
913  */
914 static int
915 scsi_query_product_info (PedDevice* dev, char **vendor, char **product)
916 {
917         /* The following are defined by the SCSI-2 specification. */
918         typedef struct _scsi_inquiry_cmd
919         {
920                 uint8_t op;
921                 uint8_t lun;          /* bits 5-7 denote the LUN */
922                 uint8_t page_code;
923                 uint8_t reserved;
924                 uint8_t alloc_length;
925                 uint8_t control;
926         } __attribute__((packed)) scsi_inquiry_cmd_t;
927
928         typedef struct _scsi_inquiry_data
929         {
930                 uint8_t peripheral_info;
931                 uint8_t device_info;
932                 uint8_t version_info;
933                 uint8_t _field1;
934                 uint8_t additional_length;
935                 uint8_t _reserved1;
936                 uint8_t _reserved2;
937                 uint8_t _field2;
938                 uint8_t vendor_id[8];
939                 uint8_t product_id[16];
940                 uint8_t product_revision[4];
941                 uint8_t vendor_specific[20];
942                 uint8_t _reserved3[40];
943         } __attribute__((packed)) scsi_inquiry_data_t;
944
945         struct scsi_arg
946         {
947                 unsigned int inlen;
948                 unsigned int outlen;
949
950                 union arg_data
951                 {
952                         scsi_inquiry_data_t out;
953                         scsi_inquiry_cmd_t  in;
954                 } data;
955         } arg;
956
957         LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
958         char    buf[32];
959
960         *vendor = NULL;
961         *product = NULL;
962
963         memset (&arg, 0x00, sizeof(struct scsi_arg));
964         arg.inlen  = 0;
965         arg.outlen = sizeof(scsi_inquiry_data_t);
966         arg.data.in.op  = INQUIRY;
967         arg.data.in.lun = dev->host << 5;
968         arg.data.in.alloc_length = sizeof(scsi_inquiry_data_t);
969         arg.data.in.page_code = 0;
970         arg.data.in.reserved = 0;
971         arg.data.in.control = 0;
972
973         if (ioctl (arch_specific->fd, SCSI_IOCTL_SEND_COMMAND, &arg) < 0)
974                 return 0;
975
976         memcpy (buf, arg.data.out.vendor_id, 8);
977         buf[8] = '\0';
978         *vendor = strip_name (buf);
979
980         memcpy (buf, arg.data.out.product_id, 16);
981         buf[16] = '\0';
982         *product = strip_name (buf);
983
984         return 1;
985 }
986
987 /* This function provides the vendor and product name for a SCSI device.
988  * It supports both the modern /sys interface and direct queries
989  * via the deprecated ioctl, SCSI_IOCTL_SEND_COMMAND.
990  */
991 static int
992 scsi_get_product_info (PedDevice* dev, char **vendor, char **product)
993 {
994         *vendor = read_device_sysfs_file (dev, "vendor");
995         *product = read_device_sysfs_file (dev, "model");
996         if (*vendor && *product)
997                 return 1;
998
999         return scsi_query_product_info (dev, vendor, product);
1000 }
1001
1002 static int
1003 init_scsi (PedDevice* dev)
1004 {
1005         struct scsi_idlun
1006         {
1007                 uint32_t dev_id;
1008                 uint32_t host_unique_id;
1009         } idlun;
1010
1011         LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1012         char* vendor;
1013         char* product;
1014
1015         if (!ped_device_open (dev))
1016                 goto error;
1017
1018         if (ioctl (arch_specific->fd, SCSI_IOCTL_GET_IDLUN, &idlun) < 0) {
1019                 dev->host = 0;
1020                 dev->did = 0;
1021                 if (ped_exception_throw (
1022                         PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
1023                         _("Error initialising SCSI device %s - %s"),
1024                         dev->path, strerror (errno))
1025                                 != PED_EXCEPTION_IGNORE)
1026                         goto error_close_dev;
1027                 if (!_device_probe_geometry (dev))
1028                         goto error_close_dev;
1029                 ped_device_close (dev);
1030                 return 1;
1031         }
1032
1033         dev->host = idlun.host_unique_id;
1034         dev->did  = idlun.dev_id;
1035
1036         dev->model = (char*) ped_malloc (8 + 16 + 2);
1037         if (!dev->model)
1038                 goto error_close_dev;
1039
1040         if (scsi_get_product_info (dev, &vendor, &product)) {
1041                 sprintf (dev->model, "%.8s %.16s", vendor, product);
1042                 free (vendor);
1043                 free (product);
1044         } else {
1045                 strcpy (dev->model, "Generic SCSI");
1046         }
1047
1048         if (!_device_probe_geometry (dev))
1049                 goto error_close_dev;
1050
1051         ped_device_close (dev);
1052         return 1;
1053
1054 error_close_dev:
1055         ped_device_close (dev);
1056 error:
1057         return 0;
1058 }
1059
1060 static int
1061 init_file (PedDevice* dev)
1062 {
1063         struct stat     dev_stat;
1064
1065         if (!_device_stat (dev, &dev_stat))
1066                 goto error;
1067         if (!ped_device_open (dev))
1068                 goto error;
1069
1070         dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1071         char *p = getenv ("PARTED_SECTOR_SIZE");
1072         if (p) {
1073                 int s = atoi (p);
1074                 if (0 < s && s % 512 == 0)
1075                         dev->sector_size = s;
1076         }
1077         dev->phys_sector_size = dev->sector_size;
1078
1079         if (S_ISBLK(dev_stat.st_mode))
1080                 dev->length = _device_get_length (dev);
1081         else
1082                 dev->length = dev_stat.st_size / dev->sector_size;
1083         if (dev->length <= 0) {
1084                 ped_exception_throw (
1085                         PED_EXCEPTION_ERROR,
1086                         PED_EXCEPTION_CANCEL,
1087                         _("The device %s has zero length, and can't possibly "
1088                           "store a file system or partition table.  Perhaps "
1089                           "you selected the wrong device?"),
1090                         dev->path);
1091                 goto error_close_dev;
1092         }
1093
1094         ped_device_close (dev);
1095
1096         dev->bios_geom.cylinders = dev->length / 4 / 32;
1097         dev->bios_geom.heads = 4;
1098         dev->bios_geom.sectors = 32;
1099         dev->hw_geom = dev->bios_geom;
1100         dev->model = strdup ("");
1101
1102         return 1;
1103
1104 error_close_dev:
1105         ped_device_close (dev);
1106 error:
1107         return 0;
1108 }
1109
1110 #if defined __s390__ || defined __s390x__
1111 static int
1112 init_dasd (PedDevice* dev, const char* model_name)
1113 {
1114         struct stat             dev_stat;
1115         struct hd_geometry      geo;
1116         dasd_information_t dasd_info;
1117
1118         if (!_device_stat (dev, &dev_stat))
1119                 goto error;
1120
1121         if (!ped_device_open (dev))
1122                 goto error;
1123
1124         LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
1125
1126         PED_ASSERT (S_ISBLK (dev_stat.st_mode), return 0);
1127
1128         _device_set_sector_size (dev);
1129         if (!dev->sector_size)
1130                 goto error_close_dev;
1131
1132         dev->length = _device_get_length (dev);
1133         if (!dev->length)
1134                 goto error_close_dev;
1135
1136         if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geo)) {
1137                 dev->hw_geom.sectors = geo.sectors;
1138                 dev->hw_geom.heads = geo.heads;
1139                 dev->hw_geom.cylinders = dev->length
1140                         / (dev->hw_geom.heads * dev->hw_geom.sectors)
1141                         / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1142                 dev->bios_geom = dev->hw_geom;
1143         } else {
1144                 dev->bios_geom.sectors = 12;
1145                 dev->bios_geom.heads = 15;
1146                 dev->bios_geom.cylinders = dev->length
1147                         / (dev->hw_geom.heads * dev->hw_geom.sectors)
1148                         / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
1149                 dev->hw_geom = dev->bios_geom;
1150         }
1151
1152         if (!ioctl(arch_specific->fd, BIODASDINFO, &dasd_info)) {
1153                 arch_specific->devno = dasd_info.devno;
1154         } else {
1155                 arch_specific->devno = arch_specific->major * 256 +
1156                                        arch_specific->minor;
1157         }
1158
1159         dev->model = strdup (model_name);
1160
1161         ped_device_close (dev);
1162         return 1;
1163
1164 error_close_dev:
1165         ped_device_close (dev);
1166 error:
1167         return 0;
1168 }
1169 #endif
1170
1171 static int
1172 init_generic (PedDevice* dev, const char* model_name)
1173 {
1174         struct stat             dev_stat;
1175         PedExceptionOption      ex_status;
1176
1177         if (!_device_stat (dev, &dev_stat))
1178                 goto error;
1179
1180         if (!ped_device_open (dev))
1181                 goto error;
1182
1183         ped_exception_fetch_all ();
1184         if (_device_probe_geometry (dev)) {
1185                 ped_exception_leave_all ();
1186         } else {
1187                 /* hack to allow use of files, for testing */
1188                 ped_exception_catch ();
1189                 ped_exception_leave_all ();
1190
1191                 ex_status = ped_exception_throw (
1192                                 PED_EXCEPTION_WARNING,
1193                                 PED_EXCEPTION_IGNORE_CANCEL,
1194                                 _("Unable to determine geometry of "
1195                                 "file/device %s.  You should not use Parted "
1196                                 "unless you REALLY know what you're doing!"),
1197                                 dev->path);
1198                 switch (ex_status) {
1199                         case PED_EXCEPTION_CANCEL:
1200                                 goto error_close_dev;
1201
1202                         case PED_EXCEPTION_UNHANDLED:
1203                                 ped_exception_catch ();
1204                         case PED_EXCEPTION_IGNORE:
1205                                 break;
1206                         default:
1207                                 PED_ASSERT (0, (void) 0);
1208                                 break;
1209                 }
1210
1211                 /* what should we stick in here? */
1212                 dev->length = dev_stat.st_size / PED_SECTOR_SIZE_DEFAULT;
1213                 dev->bios_geom.cylinders = dev->length / 4 / 32;
1214                 dev->bios_geom.heads = 4;
1215                 dev->bios_geom.sectors = 32;
1216                 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
1217                 dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
1218         }
1219
1220         dev->model = strdup (model_name);
1221
1222         ped_device_close (dev);
1223         return 1;
1224
1225 error_close_dev:
1226         ped_device_close (dev);
1227 error:
1228         return 0;
1229 }
1230
1231 static int
1232 sdmmc_get_product_info (PedDevice* dev, char **type, char **name)
1233 {
1234         *type = read_device_sysfs_file (dev, "type");
1235         *name = read_device_sysfs_file (dev, "name");
1236         if (*type && *name)
1237                 return 1;
1238
1239         return 0;
1240 }
1241
1242 static int
1243 init_sdmmc (PedDevice* dev)
1244 {
1245         char id[128];
1246         char *type, *name;
1247
1248         if (sdmmc_get_product_info (dev, &type, &name)) {
1249                 snprintf (id, sizeof(id) - 1, "%s %s", type, name);
1250                 free (type);
1251                 free (name);
1252         } else {
1253                 snprintf (id, sizeof(id) - 1, "%s",
1254                           _("Generic SD/MMC Storage Card"));
1255         }
1256         return init_generic(dev, id);
1257 }
1258
1259 static PedDevice*
1260 linux_new (const char* path)
1261 {
1262         PedDevice*      dev;
1263         LinuxSpecific*  arch_specific;
1264
1265         PED_ASSERT (path != NULL, return NULL);
1266
1267         dev = (PedDevice*) ped_malloc (sizeof (PedDevice));
1268         if (!dev)
1269                 goto error;
1270
1271         dev->path = strdup (path);
1272         if (!dev->path)
1273                 goto error_free_dev;
1274
1275         dev->arch_specific
1276                 = (LinuxSpecific*) ped_malloc (sizeof (LinuxSpecific));
1277         if (!dev->arch_specific)
1278                 goto error_free_path;
1279         arch_specific = LINUX_SPECIFIC (dev);
1280         arch_specific->dmtype = NULL;
1281 #if USE_BLKID
1282         arch_specific->probe = NULL;
1283         arch_specific->topology = NULL;
1284 #endif
1285
1286         dev->open_count = 0;
1287         dev->read_only = 0;
1288         dev->external_mode = 0;
1289         dev->dirty = 0;
1290         dev->boot_dirty = 0;
1291
1292         if (!_device_probe_type (dev))
1293                 goto error_free_arch_specific;
1294
1295         switch (dev->type) {
1296         case PED_DEVICE_IDE:
1297                 if (!init_ide (dev))
1298                         goto error_free_arch_specific;
1299                 break;
1300
1301         case PED_DEVICE_SCSI:
1302                 if (!init_scsi (dev))
1303                         goto error_free_arch_specific;
1304                 break;
1305
1306         case PED_DEVICE_DAC960:
1307                 if (!init_generic (dev, _("DAC960 RAID controller")))
1308                         goto error_free_arch_specific;
1309                 break;
1310
1311         case PED_DEVICE_SX8:
1312                 if (!init_generic (dev, _("Promise SX8 SATA Device")))
1313                         goto error_free_arch_specific;
1314                 break;
1315
1316 #if defined __s390__ || defined __s390x__
1317         case PED_DEVICE_DASD:
1318                 if (!init_dasd (dev, _("IBM S390 DASD drive")))
1319                         goto error_free_arch_specific;
1320                 break;
1321 #endif
1322
1323         case PED_DEVICE_VIODASD:
1324                 if (!init_generic (dev, _("IBM iSeries Virtual DASD")))
1325                         goto error_free_arch_specific;
1326                 break;
1327
1328         case PED_DEVICE_CPQARRAY:
1329                 if (!init_generic (dev, _("Compaq Smart Array")))
1330                         goto error_free_arch_specific;
1331                 break;
1332
1333         case PED_DEVICE_ATARAID:
1334                 if (!init_generic (dev, _("ATARAID Controller")))
1335                         goto error_free_arch_specific;
1336                 break;
1337
1338         case PED_DEVICE_I2O:
1339                 if (!init_generic (dev, _("I2O Controller")))
1340                         goto error_free_arch_specific;
1341                 break;
1342
1343         case PED_DEVICE_UBD:
1344                 if (!init_generic (dev, _("User-Mode Linux UBD")))
1345                         goto error_free_arch_specific;
1346                 break;
1347
1348         case PED_DEVICE_FILE:
1349                 if (!init_file (dev))
1350                         goto error_free_arch_specific;
1351                 break;
1352
1353         case PED_DEVICE_DM:
1354                 {
1355                   char* type;
1356                   if (arch_specific->dmtype == NULL
1357                       || asprintf(&type, _("Linux device-mapper (%s)"),
1358                                   arch_specific->dmtype) == -1)
1359                         goto error_free_arch_specific;
1360                   bool ok = init_generic (dev, type);
1361                   free (type);
1362                   if (!ok)
1363                     goto error_free_arch_specific;
1364                   break;
1365                 }
1366
1367         case PED_DEVICE_XVD:
1368                 if (!init_generic (dev, _("Xen Virtual Block Device")))
1369                         goto error_free_arch_specific;
1370                 break;
1371
1372         case PED_DEVICE_UNKNOWN:
1373                 if (!init_generic (dev, _("Unknown")))
1374                         goto error_free_arch_specific;
1375                 break;
1376
1377         case PED_DEVICE_SDMMC:
1378                 if (!init_sdmmc (dev))
1379                         goto error_free_arch_specific;
1380                 break;
1381         case PED_DEVICE_VIRTBLK:
1382                 if (!init_generic(dev, _("Virtio Block Device")))
1383                         goto error_free_arch_specific;
1384                 break;
1385
1386         default:
1387                 ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
1388                                 PED_EXCEPTION_CANCEL,
1389                                 _("ped_device_new()  Unsupported device type"));
1390                 goto error_free_arch_specific;
1391         }
1392         return dev;
1393
1394 error_free_arch_specific:
1395         free (dev->arch_specific);
1396 error_free_path:
1397         free (dev->path);
1398 error_free_dev:
1399         free (dev);
1400 error:
1401         return NULL;
1402 }
1403
1404 static void
1405 linux_destroy (PedDevice* dev)
1406 {
1407         LinuxSpecific *arch_specific = LINUX_SPECIFIC(dev);
1408         void *p = arch_specific->dmtype;
1409
1410 #if USE_BLKID
1411         if (arch_specific->probe)
1412                 blkid_free_probe(arch_specific->probe);
1413 #endif
1414         free (p);
1415         free (dev->arch_specific);
1416         free (dev->path);
1417         free (dev->model);
1418         free (dev);
1419 }
1420
1421 static int
1422 linux_is_busy (PedDevice* dev)
1423 {
1424         int     i;
1425         char*   part_name;
1426
1427         if (_partition_is_mounted_by_path (dev->path))
1428                 return 1;
1429
1430         for (i = 0; i < 32; i++) {
1431                 int status;
1432
1433                 part_name = _device_get_part_path (dev, i);
1434                 if (!part_name)
1435                         return 1;
1436                 status = _partition_is_mounted_by_path (part_name);
1437                 free (part_name);
1438
1439                 if (status)
1440                         return 1;
1441         }
1442
1443         return 0;
1444 }
1445
1446 /* we need to flush the master device, and with kernel < 2.6 all the partition
1447  * devices, because there is no coherency between the caches with old kernels.
1448  * We should only flush unmounted partition devices, because:
1449  *  - there is never a need to flush them (we're not doing IO there)
1450  *  - flushing a device that is mounted causes unnecessary IO, and can
1451  * even screw journaling & friends up.  Even cause oopsen!
1452  */
1453 static void
1454 _flush_cache (PedDevice* dev)
1455 {
1456         LinuxSpecific*  arch_specific = LINUX_SPECIFIC (dev);
1457         int             i;
1458
1459         if (dev->read_only)
1460                 return;
1461         dev->dirty = 0;
1462
1463         ioctl (arch_specific->fd, BLKFLSBUF);
1464
1465         /* With linux-2.6.0 and newer, we're done.  */
1466         if (_have_kern26())
1467                 return;
1468
1469         for (i = 1; i < 16; i++) {
1470                 char*           name;
1471                 int             fd;
1472
1473                 name = _device_get_part_path (dev, i);
1474                 if (!name)
1475                         break;
1476                 if (!_partition_is_mounted_by_path (name)) {
1477                         fd = open (name, WR_MODE, 0);
1478                         if (fd > 0) {
1479                                 ioctl (fd, BLKFLSBUF);
1480 retry:
1481                                 if (fsync (fd) < 0 || close (fd) < 0)
1482                                         if (ped_exception_throw (
1483                                                 PED_EXCEPTION_WARNING,
1484                                                 PED_EXCEPTION_RETRY +
1485                                                         PED_EXCEPTION_IGNORE,
1486                                                 _("Error fsyncing/closing %s: %s"),
1487                                                 name, strerror (errno))
1488                                                         == PED_EXCEPTION_RETRY)
1489                                                 goto retry;
1490                         }
1491                 }
1492                 free (name);
1493         }
1494 }
1495
1496 static int
1497 linux_open (PedDevice* dev)
1498 {
1499         LinuxSpecific*  arch_specific = LINUX_SPECIFIC (dev);
1500
1501 retry:
1502         arch_specific->fd = open (dev->path, RW_MODE);
1503
1504         if (arch_specific->fd == -1) {
1505                 char*   rw_error_msg = strerror (errno);
1506
1507                 arch_specific->fd = open (dev->path, RD_MODE);
1508
1509                 if (arch_specific->fd == -1) {
1510                         if (ped_exception_throw (
1511                                 PED_EXCEPTION_ERROR,
1512                                 PED_EXCEPTION_RETRY_CANCEL,
1513                                 _("Error opening %s: %s"),
1514                                 dev->path, strerror (errno))
1515                                         != PED_EXCEPTION_RETRY) {
1516                                 return 0;
1517                         } else {
1518                                 goto retry;
1519                         }
1520                 } else {
1521                         ped_exception_throw (
1522                                 PED_EXCEPTION_WARNING,
1523                                 PED_EXCEPTION_OK,
1524                                 _("Unable to open %s read-write (%s).  %s has "
1525                                   "been opened read-only."),
1526                                 dev->path, rw_error_msg, dev->path);
1527                         dev->read_only = 1;
1528                 }
1529         } else {
1530                 dev->read_only = 0;
1531         }
1532
1533         /* With kernels < 2.6 flush cache for cache coherence issues */
1534         if (!_have_kern26())
1535                 _flush_cache (dev);
1536
1537         return 1;
1538 }
1539
1540 static int
1541 linux_refresh_open (PedDevice* dev)
1542 {
1543         return 1;
1544 }
1545
1546 static int
1547 linux_close (PedDevice* dev)
1548 {
1549         LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
1550
1551         if (dev->dirty)
1552                 _flush_cache (dev);
1553 retry:
1554         if (fsync (arch_specific->fd) < 0 || close (arch_specific->fd) < 0)
1555                 if (ped_exception_throw (
1556                         PED_EXCEPTION_WARNING,
1557                         PED_EXCEPTION_RETRY + PED_EXCEPTION_IGNORE,
1558                         _("Error fsyncing/closing %s: %s"),
1559                         dev->path, strerror (errno))
1560                                 == PED_EXCEPTION_RETRY)
1561                         goto retry;
1562         return 1;
1563 }
1564
1565 static int
1566 linux_refresh_close (PedDevice* dev)
1567 {
1568         if (dev->dirty)
1569                 _flush_cache (dev);
1570         return 1;
1571 }
1572
1573 #if SIZEOF_OFF_T < 8
1574
1575 static _syscall5(int,_llseek,
1576                  unsigned int, fd,
1577                  unsigned long, offset_high,
1578                  unsigned long, offset_low,
1579                  loff_t*, result,
1580                  unsigned int, origin)
1581
1582 loff_t
1583 llseek (unsigned int fd, loff_t offset, unsigned int whence)
1584 {
1585         loff_t result;
1586         int retval;
1587
1588         retval = _llseek(fd,
1589                          ((unsigned long long)offset) >> 32,
1590                          ((unsigned long long)offset) & 0xffffffff,
1591                          &result,
1592                          whence);
1593         return (retval==-1 ? (loff_t) retval : result);
1594 }
1595
1596 #endif /* SIZEOF_OFF_T < 8 */
1597
1598 static int
1599 _device_seek (const PedDevice* dev, PedSector sector)
1600 {
1601         LinuxSpecific*  arch_specific;
1602
1603         PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1604         PED_ASSERT (dev != NULL, return 0);
1605         PED_ASSERT (!dev->external_mode, return 0);
1606
1607         arch_specific = LINUX_SPECIFIC (dev);
1608
1609 #if SIZEOF_OFF_T < 8
1610         if (sizeof (off_t) < 8) {
1611                 loff_t  pos = (loff_t)(sector * dev->sector_size);
1612                 return llseek (arch_specific->fd, pos, SEEK_SET) == pos;
1613         } else
1614 #endif
1615         {
1616                 off_t   pos = sector * dev->sector_size;
1617                 return lseek (arch_specific->fd, pos, SEEK_SET) == pos;
1618         }
1619 }
1620
1621 static int
1622 _read_lastoddsector (const PedDevice* dev, void* buffer)
1623 {
1624         LinuxSpecific*                  arch_specific;
1625         struct blkdev_ioctl_param       ioctl_param;
1626
1627         PED_ASSERT(dev != NULL, return 0);
1628         PED_ASSERT(buffer != NULL, return 0);
1629
1630         arch_specific = LINUX_SPECIFIC (dev);
1631
1632 retry:
1633         ioctl_param.block = 0; /* read the last sector */
1634         ioctl_param.content_length = dev->sector_size;
1635         ioctl_param.block_contents = buffer;
1636
1637         if (ioctl(arch_specific->fd, BLKGETLASTSECT, &ioctl_param) == -1) {
1638                 PedExceptionOption      opt;
1639                 opt = ped_exception_throw (
1640                         PED_EXCEPTION_ERROR,
1641                         PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1642                         _("%s during read on %s"),
1643                         strerror (errno), dev->path);
1644
1645                 if (opt == PED_EXCEPTION_CANCEL)
1646                         return 0;
1647                 if (opt == PED_EXCEPTION_RETRY)
1648                         goto retry;
1649         }
1650
1651         return 1;
1652 }
1653
1654 static int
1655 linux_read (const PedDevice* dev, void* buffer, PedSector start,
1656             PedSector count)
1657 {
1658         LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
1659         PedExceptionOption      ex_status;
1660         void*                   diobuf = NULL;
1661
1662         PED_ASSERT (dev != NULL, return 0);
1663         PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1664
1665         if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1666                 /* Kludge.  This is necessary to read/write the last
1667                    block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1668                 */
1669                 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1670                     && start + count - 1 == dev->length - 1)
1671                         return ped_device_read (dev, buffer, start, count - 1)
1672                                 && _read_lastoddsector (
1673                                         dev, (char *) buffer + (count-1) * 512);
1674         }
1675         while (1) {
1676                 if (_device_seek (dev, start))
1677                         break;
1678
1679                 ex_status = ped_exception_throw (
1680                         PED_EXCEPTION_ERROR,
1681                         PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1682                         _("%s during seek for read on %s"),
1683                         strerror (errno), dev->path);
1684
1685                 switch (ex_status) {
1686                         case PED_EXCEPTION_IGNORE:
1687                                 return 1;
1688
1689                         case PED_EXCEPTION_RETRY:
1690                                 break;
1691
1692                         case PED_EXCEPTION_UNHANDLED:
1693                                 ped_exception_catch ();
1694                         case PED_EXCEPTION_CANCEL:
1695                                 return 0;
1696                         default:
1697                                 PED_ASSERT (0, (void) 0);
1698                                 break;
1699                 }
1700         }
1701
1702         size_t read_length = count * dev->sector_size;
1703         if (posix_memalign (&diobuf, dev->sector_size, read_length) != 0)
1704                 return 0;
1705
1706         while (1) {
1707                 ssize_t status = read (arch_specific->fd, diobuf, read_length);
1708                 if (status > 0)
1709                         memcpy(buffer, diobuf, status);
1710                 if (status == (ssize_t) read_length)
1711                         break;
1712                 if (status > 0) {
1713                         read_length -= status;
1714                         buffer = (char *) buffer + status;
1715                         continue;
1716                 }
1717
1718                 ex_status = ped_exception_throw (
1719                         PED_EXCEPTION_ERROR,
1720                         PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1721                         (status == 0
1722                          ? _("end of file while reading %s")
1723                          : _("%s during read on %s")),
1724                         strerror (errno),
1725                         dev->path);
1726
1727                 switch (ex_status) {
1728                         case PED_EXCEPTION_IGNORE:
1729                                 free(diobuf);
1730                                 return 1;
1731
1732                         case PED_EXCEPTION_RETRY:
1733                                 break;
1734
1735                         case PED_EXCEPTION_UNHANDLED:
1736                                 ped_exception_catch ();
1737                         case PED_EXCEPTION_CANCEL:
1738                                 free(diobuf);
1739                                 return 0;
1740                         default:
1741                                 PED_ASSERT (0, (void) 0);
1742                                 break;
1743                 }
1744         }
1745
1746         free (diobuf);
1747
1748         return 1;
1749 }
1750
1751 static int
1752 _write_lastoddsector (PedDevice* dev, const void* buffer)
1753 {
1754         LinuxSpecific*                  arch_specific;
1755         struct blkdev_ioctl_param       ioctl_param;
1756
1757         PED_ASSERT(dev != NULL, return 0);
1758         PED_ASSERT(buffer != NULL, return 0);
1759
1760         arch_specific = LINUX_SPECIFIC (dev);
1761
1762 retry:
1763         ioctl_param.block = 0; /* write the last sector */
1764         ioctl_param.content_length = dev->sector_size;
1765         ioctl_param.block_contents = (void*) buffer;
1766
1767         if (ioctl(arch_specific->fd, BLKSETLASTSECT, &ioctl_param) == -1) {
1768                 PedExceptionOption      opt;
1769                 opt = ped_exception_throw (
1770                         PED_EXCEPTION_ERROR,
1771                         PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1772                         _("%s during write on %s"),
1773                         strerror (errno), dev->path);
1774
1775                 if (opt == PED_EXCEPTION_CANCEL)
1776                         return 0;
1777                 if (opt == PED_EXCEPTION_RETRY)
1778                         goto retry;
1779         }
1780
1781         return 1;
1782 }
1783
1784 static int
1785 linux_write (PedDevice* dev, const void* buffer, PedSector start,
1786              PedSector count)
1787 {
1788         LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
1789         PedExceptionOption      ex_status;
1790         void*                   diobuf;
1791         void*                   diobuf_start;
1792
1793         PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
1794
1795         if (dev->read_only) {
1796                 if (ped_exception_throw (
1797                         PED_EXCEPTION_ERROR,
1798                         PED_EXCEPTION_IGNORE_CANCEL,
1799                         _("Can't write to %s, because it is opened read-only."),
1800                         dev->path)
1801                                 != PED_EXCEPTION_IGNORE)
1802                         return 0;
1803                 else
1804                         return 1;
1805         }
1806
1807         if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
1808                 /* Kludge.  This is necessary to read/write the last
1809                    block of an odd-sized disk, until Linux 2.5.x kernel fixes.
1810                 */
1811                 if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
1812                     && start + count - 1 == dev->length - 1)
1813                         return ped_device_write (dev, buffer, start, count - 1)
1814                                 && _write_lastoddsector (
1815                                         dev, ((char*) buffer
1816                                               + (count-1) * dev->sector_size));
1817         }
1818         while (1) {
1819                 if (_device_seek (dev, start))
1820                         break;
1821
1822                 ex_status = ped_exception_throw (
1823                         PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1824                         _("%s during seek for write on %s"),
1825                         strerror (errno), dev->path);
1826
1827                 switch (ex_status) {
1828                         case PED_EXCEPTION_IGNORE:
1829                                 return 1;
1830
1831                         case PED_EXCEPTION_RETRY:
1832                                 break;
1833
1834                         case PED_EXCEPTION_UNHANDLED:
1835                                 ped_exception_catch ();
1836                         case PED_EXCEPTION_CANCEL:
1837                                 return 0;
1838                         default:
1839                                 PED_ASSERT (0, (void) 0);
1840                                 break;
1841                 }
1842         }
1843
1844 #ifdef READ_ONLY
1845         printf ("ped_device_write (\"%s\", %p, %d, %d)\n",
1846                 dev->path, buffer, (int) start, (int) count);
1847 #else
1848         size_t write_length = count * dev->sector_size;
1849         dev->dirty = 1;
1850         if (posix_memalign(&diobuf, dev->sector_size, write_length) != 0)
1851                 return 0;
1852         memcpy(diobuf, buffer, write_length);
1853         diobuf_start = diobuf;
1854         while (1) {
1855                 ssize_t status = write (arch_specific->fd, diobuf, write_length);
1856                 if (status == write_length) break;
1857                 if (status > 0) {
1858                         write_length -= status;
1859                         diobuf = (char *) diobuf + status;
1860                         continue;
1861                 }
1862
1863                 ex_status = ped_exception_throw (
1864                         PED_EXCEPTION_ERROR,
1865                         PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1866                         _("%s during write on %s"),
1867                         strerror (errno), dev->path);
1868
1869                 switch (ex_status) {
1870                         case PED_EXCEPTION_IGNORE:
1871                                 free(diobuf_start);
1872                                 return 1;
1873
1874                         case PED_EXCEPTION_RETRY:
1875                                 break;
1876
1877                         case PED_EXCEPTION_UNHANDLED:
1878                                 ped_exception_catch ();
1879                         case PED_EXCEPTION_CANCEL:
1880                                 free(diobuf_start);
1881                                 return 0;
1882                         default:
1883                                 PED_ASSERT (0, (void) 0);
1884                                 break;
1885                 }
1886         }
1887         free(diobuf_start);
1888 #endif /* !READ_ONLY */
1889         return 1;
1890 }
1891
1892 /* returns the number of sectors that are ok.
1893  */
1894 static PedSector
1895 linux_check (PedDevice* dev, void* buffer, PedSector start, PedSector count)
1896 {
1897         LinuxSpecific*  arch_specific = LINUX_SPECIFIC (dev);
1898         PedSector       done = 0;
1899         int             status;
1900         void*           diobuf;
1901
1902         PED_ASSERT(dev != NULL, return 0);
1903
1904         if (!_device_seek (dev, start))
1905                 return 0;
1906
1907         if (posix_memalign(&diobuf, PED_SECTOR_SIZE_DEFAULT,
1908                            count * PED_SECTOR_SIZE_DEFAULT) != 0)
1909                 return 0;
1910
1911         for (done = 0; done < count; done += status / dev->sector_size) {
1912                 status = read (arch_specific->fd, diobuf,
1913                                (size_t) ((count-done) * dev->sector_size));
1914                 if (status > 0)
1915                         memcpy(buffer, diobuf, status);
1916                 if (status < 0)
1917                         break;
1918         }
1919         free(diobuf);
1920
1921         return done;
1922 }
1923
1924 static int
1925 _do_fsync (PedDevice* dev)
1926 {
1927         LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
1928         int                     status;
1929         PedExceptionOption      ex_status;
1930
1931         while (1) {
1932                 status = fsync (arch_specific->fd);
1933                 if (status >= 0) break;
1934
1935                 ex_status = ped_exception_throw (
1936                         PED_EXCEPTION_ERROR,
1937                         PED_EXCEPTION_RETRY_IGNORE_CANCEL,
1938                         _("%s during write on %s"),
1939                         strerror (errno), dev->path);
1940
1941                 switch (ex_status) {
1942                         case PED_EXCEPTION_IGNORE:
1943                                 return 1;
1944
1945                         case PED_EXCEPTION_RETRY:
1946                                 break;
1947
1948                         case PED_EXCEPTION_UNHANDLED:
1949                                 ped_exception_catch ();
1950                         case PED_EXCEPTION_CANCEL:
1951                                 return 0;
1952                         default:
1953                                 PED_ASSERT (0, (void) 0);
1954                                 break;
1955                 }
1956         }
1957         return 1;
1958 }
1959
1960 static int
1961 linux_sync (PedDevice* dev)
1962 {
1963         PED_ASSERT (dev != NULL, return 0);
1964         PED_ASSERT (!dev->external_mode, return 0);
1965
1966         if (dev->read_only)
1967                 return 1;
1968         if (!_do_fsync (dev))
1969                 return 0;
1970         _flush_cache (dev);
1971         return 1;
1972 }
1973
1974 static int
1975 linux_sync_fast (PedDevice* dev)
1976 {
1977         PED_ASSERT (dev != NULL, return 0);
1978         PED_ASSERT (!dev->external_mode, return 0);
1979
1980         if (dev->read_only)
1981                 return 1;
1982         if (!_do_fsync (dev))
1983                 return 0;
1984         /* no cache flush... */
1985         return 1;
1986 }
1987
1988 static inline int
1989 _compare_digit_state (char ch, int need_digit)
1990 {
1991         return !!isdigit (ch) == need_digit;
1992 }
1993
1994 /* matches the regexp "[^0-9]+[0-9]+[^0-9]+[0-9]+$".
1995  * Motivation: accept devices looking like /dev/rd/c0d0, but
1996  * not looking like /dev/hda1 and /dev/rd/c0d0p1
1997  */
1998 static int
1999 _match_rd_device (const char* name)
2000 {
2001         const char* pos;
2002         int state;
2003
2004         /* exclude directory names from test */
2005         pos = strrchr(name, '/') ?: name;
2006
2007         /* states:
2008          *      0       non-digits
2009          *      1       digits
2010          *      2       non-digits
2011          *      3       digits
2012          */
2013         for (state = 0; state < 4; state++) {
2014                 int want_digits = (state % 2 == 1);
2015                 do {
2016                         if (!*pos)
2017                                 return 0;
2018                         if (!_compare_digit_state (*pos, want_digits))
2019                                 return 0;
2020                         pos++;
2021                 } while (_compare_digit_state (*pos, want_digits));
2022         }
2023
2024         return *pos == 0;
2025 }
2026
2027 static int
2028 _probe_proc_partitions ()
2029 {
2030         FILE*           proc_part_file;
2031         int             major, minor, size;
2032         char            buf [512];
2033         char            part_name [256];
2034         char            dev_name [256];
2035
2036         proc_part_file = fopen ("/proc/partitions", "r");
2037         if (!proc_part_file)
2038                 return 0;
2039
2040         if (fgets (buf, 256, proc_part_file) == NULL)
2041                 return 0;
2042
2043         if (fgets (buf, 256, proc_part_file) == NULL)
2044                 return 0;
2045
2046         while (fgets (buf, 512, proc_part_file)
2047                && sscanf (buf, "%d %d %d %255s", &major, &minor, &size,
2048                           part_name) == 4) {
2049                 /* Heuristic for telling partitions and devices apart
2050                  * Probably needs to be improved
2051                  */
2052                 if (!_match_rd_device (part_name)
2053                     && isdigit (part_name [strlen (part_name) - 1]))
2054                         continue;
2055
2056                 strcpy (dev_name, "/dev/");
2057                 strcat (dev_name, part_name);
2058                 _ped_device_probe (dev_name);
2059         }
2060
2061         fclose (proc_part_file);
2062         return 1;
2063 }
2064
2065 struct _entry {
2066         const char *name;
2067         size_t len;
2068 };
2069
2070 static int
2071 _skip_entry (const char *name)
2072 {
2073         struct _entry *i;
2074         static struct _entry entries[] = {
2075                 { ".",          sizeof (".") - 1        },
2076                 { "..",         sizeof ("..") - 1       },
2077                 { "dm-",        sizeof ("dm-") - 1      },
2078                 { "loop",       sizeof ("loop") - 1     },
2079                 { "ram",        sizeof ("ram") - 1      },
2080                 { 0, 0 },
2081         };
2082
2083         for (i = entries; i->name != 0; i++) {
2084                 if (strncmp (name, i->name, i->len) == 0)
2085                         return 1;
2086         }
2087
2088         return 0;
2089 }
2090
2091 static int
2092 _probe_sys_block ()
2093 {
2094         DIR *blockdir;
2095         struct dirent *dirent;
2096         char dev_name [256];
2097         char *ptr;
2098
2099         if (!(blockdir = opendir ("/sys/block")))
2100                 return 0;
2101         while ((dirent = readdir (blockdir))) {
2102                 if (_skip_entry (dirent->d_name))
2103                         continue;
2104
2105                 if (strlen (dirent->d_name) > sizeof (dev_name) - 6)
2106                         continue; /* device name too long! */
2107
2108                 strcpy (dev_name, "/dev/");
2109                 strcat (dev_name, dirent->d_name);
2110                 /* in /sys/block, '/'s are replaced with '!' or '.' */
2111                 for (ptr = dev_name; *ptr != '\0'; ptr++) {
2112                         if (*ptr == '!' || *ptr == '.')
2113                                 *ptr = '/';
2114                 }
2115                 _ped_device_probe (dev_name);
2116         }
2117
2118         closedir (blockdir);
2119         return 1;
2120 }
2121
2122 static int
2123 _probe_standard_devices ()
2124 {
2125         _ped_device_probe ("/dev/hda");
2126         _ped_device_probe ("/dev/hdb");
2127         _ped_device_probe ("/dev/hdc");
2128         _ped_device_probe ("/dev/hdd");
2129         _ped_device_probe ("/dev/hde");
2130         _ped_device_probe ("/dev/hdf");
2131         _ped_device_probe ("/dev/hdg");
2132         _ped_device_probe ("/dev/hdh");
2133
2134         _ped_device_probe ("/dev/sda");
2135         _ped_device_probe ("/dev/sdb");
2136         _ped_device_probe ("/dev/sdc");
2137         _ped_device_probe ("/dev/sdd");
2138         _ped_device_probe ("/dev/sde");
2139         _ped_device_probe ("/dev/sdf");
2140
2141         return 1;
2142 }
2143
2144 static void
2145 linux_probe_all ()
2146 {
2147         /* we should probe the standard devs too, even with /proc/partitions,
2148          * because /proc/partitions might return devfs stuff, and we might not
2149          * have devfs available
2150          */
2151         _probe_standard_devices ();
2152
2153 #ifdef ENABLE_DEVICE_MAPPER
2154         /* device-mapper devices aren't listed in /proc/partitions; or, if
2155          * they are, they're listed as dm-X.  So, instead of relying on that,
2156          * we do our own checks.
2157          */
2158         _probe_dm_devices ();
2159 #endif
2160
2161         /* /sys/block is more reliable and consistent; fall back to using
2162          * /proc/partitions if the former is unavailable, however.
2163          */
2164         if (!_probe_sys_block ())
2165                 _probe_proc_partitions ();
2166 }
2167
2168 static char*
2169 _device_get_part_path (PedDevice* dev, int num)
2170 {
2171         int             path_len = strlen (dev->path);
2172         int             result_len = path_len + 16;
2173         char*           result;
2174
2175         result = (char*) ped_malloc (result_len);
2176         if (!result)
2177                 return NULL;
2178
2179         /* Check for devfs-style /disc => /partN transformation
2180            unconditionally; the system might be using udev with devfs rules,
2181            and if not the test is harmless. */
2182         if (!strcmp (dev->path + path_len - 5, "/disc")) {
2183                 /* replace /disc with /path%d */
2184                 strcpy (result, dev->path);
2185                 snprintf (result + path_len - 5, 16, "/part%d", num);
2186         } else if (dev->type == PED_DEVICE_DAC960
2187                         || dev->type == PED_DEVICE_CPQARRAY
2188                         || dev->type == PED_DEVICE_ATARAID
2189                         || dev->type == PED_DEVICE_DM
2190                         || isdigit (dev->path[path_len - 1]))
2191                 snprintf (result, result_len, "%sp%d", dev->path, num);
2192         else
2193                 snprintf (result, result_len, "%s%d", dev->path, num);
2194
2195         return result;
2196 }
2197
2198 static char*
2199 linux_partition_get_path (const PedPartition* part)
2200 {
2201         return _device_get_part_path (part->disk->dev, part->num);
2202 }
2203
2204 static dev_t
2205 _partition_get_part_dev (const PedPartition* part)
2206 {
2207         struct stat dev_stat;
2208         int dev_major, dev_minor;
2209
2210         if (stat (part->disk->dev->path, &dev_stat))
2211                 return (dev_t)0;
2212         dev_major = major (dev_stat.st_rdev);
2213         dev_minor = minor (dev_stat.st_rdev);
2214         return (dev_t)makedev (dev_major, dev_minor + part->num);
2215 }
2216
2217 static int
2218 _mount_table_search (const char* file_name, dev_t dev)
2219 {
2220         struct stat part_stat;
2221         char line[512];
2222         char part_name[512];
2223         FILE* file;
2224
2225         file = fopen (file_name, "r");
2226         if (!file)
2227                 return 0;
2228         while (fgets (line, 512, file)) {
2229                 if (sscanf (line, "%s", part_name) == 1
2230                     && stat (part_name, &part_stat) == 0) {
2231                         if (part_stat.st_rdev == dev) {
2232                                 fclose (file);
2233                                 return 1;
2234                         }
2235                 }
2236         }
2237         fclose (file);
2238         return 0;
2239 }
2240
2241 static int
2242 _partition_is_mounted_by_dev (dev_t dev)
2243 {
2244         return  _mount_table_search( "/proc/mounts", dev)
2245                 || _mount_table_search( "/proc/swaps", dev)
2246                 || _mount_table_search( "/etc/mtab", dev);
2247 }
2248
2249 static int
2250 _partition_is_mounted_by_path (const char *path)
2251 {
2252         struct stat part_stat;
2253         if (stat (path, &part_stat) != 0)
2254                 return 0;
2255         if (!S_ISBLK(part_stat.st_mode))
2256                 return 0;
2257         return _partition_is_mounted_by_dev (part_stat.st_rdev);
2258 }
2259
2260 static int
2261 _partition_is_mounted (const PedPartition *part)
2262 {
2263         dev_t dev;
2264         if (!ped_partition_is_active (part))
2265                 return 0;
2266         dev = _partition_get_part_dev (part);
2267         if (!dev)
2268                 return 0;
2269         return _partition_is_mounted_by_dev (dev);
2270 }
2271
2272 static int
2273 _has_partitions (const PedDisk* disk)
2274 {
2275         PED_ASSERT(disk != NULL, return 0);
2276
2277         /* Some devices can't be partitioned. */
2278         if (!strcmp (disk->type->name, "loop"))
2279                 return 0;
2280
2281         return 1;
2282 }
2283
2284 static int
2285 linux_partition_is_busy (const PedPartition* part)
2286 {
2287         PedPartition*   walk;
2288
2289         PED_ASSERT (part != NULL, return 0);
2290
2291         if (_partition_is_mounted (part))
2292                 return 1;
2293         if (part->type == PED_PARTITION_EXTENDED) {
2294                 for (walk = part->part_list; walk; walk = walk->next) {
2295                         if (linux_partition_is_busy (walk))
2296                                 return 1;
2297                 }
2298         }
2299         return 0;
2300 }
2301
2302 #ifdef ENABLE_DEVICE_MAPPER
2303 static int
2304 _dm_remove_map_name(char *name)
2305 {
2306         struct dm_task  *task = NULL;
2307         int             rc;
2308
2309         task = dm_task_create(DM_DEVICE_REMOVE);
2310         if (!task)
2311                 return 1;
2312
2313         dm_task_set_name (task, name);
2314
2315         rc = dm_task_run(task);
2316         dm_task_update_nodes();
2317         dm_task_destroy(task);
2318         if (rc < 0)
2319                 return 1;
2320
2321         return 0;
2322 }
2323
2324 static int
2325 _dm_is_part (struct dm_info *this, char *name)
2326 {
2327         struct dm_task* task = NULL;
2328         struct dm_info* info = alloca(sizeof *info);
2329         struct dm_deps* deps = NULL;
2330         int             rc = 0;
2331         unsigned int    i;
2332
2333         task = dm_task_create(DM_DEVICE_DEPS);
2334         if (!task)
2335                 return 0;
2336
2337         dm_task_set_name(task, name);
2338         rc = dm_task_run(task);
2339         if (rc < 0) {
2340                 rc = 0;
2341                 goto err;
2342         }
2343         rc = 0;
2344
2345         memset(info, '\0', sizeof *info);
2346         dm_task_get_info(task, info);
2347         if (!info->exists)
2348                 goto err;
2349
2350         deps = dm_task_get_deps(task);
2351         if (!deps)
2352                 goto err;
2353
2354         rc = 0;
2355         for (i = 0; i < deps->count; i++) {
2356                 unsigned int ma = major(deps->device[i]),
2357                              mi = minor(deps->device[i]);
2358
2359                 if (ma == this->major && mi == this->minor)
2360                         rc = 1;
2361         }
2362
2363 err:
2364         dm_task_destroy(task);
2365         return rc;
2366 }
2367
2368 static int
2369 _dm_remove_parts (PedDevice* dev)
2370 {
2371         struct dm_task*         task = NULL;
2372         struct dm_info*         info = alloca(sizeof *info);
2373         struct dm_names*        names = NULL;
2374         unsigned int            next = 0;
2375         int                     rc;
2376         LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
2377
2378         task = dm_task_create(DM_DEVICE_LIST);
2379         if (!task)
2380                 goto err;
2381
2382         if (!dm_task_set_major_minor (task, arch_specific->major,
2383                                       arch_specific->minor, 0))
2384                 goto err;
2385
2386         rc = dm_task_run(task);
2387         if (rc < 0)
2388                 goto err;
2389
2390         memset(info, '\0', sizeof *info);
2391         dm_task_get_info(task, info);
2392         if (!info->exists)
2393                 goto err;
2394
2395         names = dm_task_get_names(task);
2396         if (!names)
2397                 goto err;
2398
2399         rc = 0;
2400         do {
2401                 names = (void *) ((char *) names + next);
2402
2403                 if (_dm_is_part(info, names->name))
2404                         rc += _dm_remove_map_name(names->name);
2405
2406                 next = names->next;
2407         } while (next);
2408
2409         dm_task_update_nodes();
2410         dm_task_destroy(task);
2411         task = NULL;
2412
2413         if (!rc)
2414                 return 1;
2415 err:
2416         if (task)
2417                 dm_task_destroy(task);
2418         ped_exception_throw (PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE,
2419                 _("parted was unable to re-read the partition "
2420                   "table on %s (%s).  This means Linux won't know "
2421                   "anything about the modifications you made. "),
2422                 dev->path, strerror (errno));
2423         return 0;
2424 }
2425
2426 static int
2427 _dm_add_partition (PedDisk* disk, PedPartition* part)
2428 {
2429         int             rc;
2430         char*           vol_name = NULL;
2431         const char*     dev_name = NULL;
2432         char*           params = NULL;
2433         LinuxSpecific*  arch_specific = LINUX_SPECIFIC (disk->dev);
2434
2435         if (!_has_partitions(disk))
2436                 return 0;
2437
2438         /* Get map name from devicemapper */
2439         struct dm_task *task = dm_task_create (DM_DEVICE_INFO);
2440         if (!task)
2441                 goto err;
2442
2443         if (!dm_task_set_major_minor (task, arch_specific->major,
2444                                       arch_specific->minor, 0))
2445                 goto err;
2446
2447         rc = dm_task_run(task);
2448         if (rc < 0)
2449                 goto err;
2450
2451         dev_name = dm_task_get_name (task);
2452
2453         if (asprintf (&vol_name, "%sp%d", dev_name, part->num) == -1)
2454                 goto err;
2455
2456         /* Caution: dm_task_destroy frees dev_name.  */
2457         dm_task_destroy (task);
2458         task = NULL;
2459
2460         if (asprintf (&params, "%d:%d %lld", arch_specific->major,
2461                       arch_specific->minor, part->geom.start) == -1)
2462                 goto err;
2463
2464         task = dm_task_create (DM_DEVICE_CREATE);
2465         if (!task)
2466                 goto err;
2467
2468         dm_task_set_name (task, vol_name);
2469         dm_task_add_target (task, 0, part->geom.length,
2470                 "linear", params);
2471         rc = dm_task_run (task);
2472         if (rc >= 0) {
2473                 //printf("0 %ld linear %s\n", part->geom.length, params);
2474                 dm_task_update_nodes();
2475                 dm_task_destroy(task);
2476                 free(params);
2477                 free(vol_name);
2478                 return 1;
2479         } else {
2480                 _dm_remove_map_name(vol_name);
2481         }
2482 err:
2483         dm_task_update_nodes();
2484         if (task)
2485                 dm_task_destroy (task);
2486         free (params);
2487         free (vol_name);
2488         return 0;
2489 }
2490
2491 static int
2492 _dm_reread_part_table (PedDisk* disk)
2493 {
2494         int largest_partnum = ped_disk_get_last_partition_num (disk);
2495         if (largest_partnum <= 0)
2496           return 1;
2497
2498         int     rc = 1;
2499         int     last = PED_MIN (largest_partnum, 16);
2500         int     i;
2501
2502         sync();
2503         if (!_dm_remove_parts(disk->dev))
2504                 rc = 0;
2505
2506         for (i = 1; i <= last; i++) {
2507                 PedPartition*      part;
2508
2509                 part = ped_disk_get_partition (disk, i);
2510                 if (!part)
2511                         continue;
2512
2513                 if (!_dm_add_partition (disk, part))
2514                         rc = 0;
2515         }
2516         return rc;
2517 }
2518 #endif
2519
2520 static int
2521 _kernel_reread_part_table (PedDevice* dev)
2522 {
2523         LinuxSpecific*  arch_specific = LINUX_SPECIFIC (dev);
2524         int             retry_count = 9;
2525
2526         sync();
2527         while (ioctl (arch_specific->fd, BLKRRPART)) {
2528                 retry_count--;
2529                 sync();
2530                 if (retry_count == 3)
2531                         sleep(1); /* Pause to allow system to settle */
2532
2533                 if (!retry_count) {
2534                         ped_exception_throw (
2535                                 PED_EXCEPTION_WARNING,
2536                                 PED_EXCEPTION_IGNORE,
2537                         _("WARNING: the kernel failed to re-read the partition "
2538                           "table on %s (%s).  As a result, it may not "
2539                           "reflect all of your changes until after reboot."),
2540                                 dev->path, strerror (errno));
2541                         return 0;
2542                 }
2543         }
2544
2545         return 1;
2546 }
2547
2548 static int
2549 linux_disk_commit (PedDisk* disk)
2550 {
2551        if (!_has_partitions (disk))
2552                return 1;
2553
2554 #ifdef ENABLE_DEVICE_MAPPER
2555         if (disk->dev->type == PED_DEVICE_DM)
2556                 return _dm_reread_part_table (disk);
2557 #endif
2558         if (disk->dev->type != PED_DEVICE_FILE) {
2559                 return _kernel_reread_part_table (disk->dev);
2560         }
2561
2562         return 1;
2563 }
2564
2565 #if USE_BLKID
2566 PedAlignment*
2567 linux_get_minimum_alignment(const PedDevice *dev)
2568 {
2569         blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
2570         if (!tp)
2571                 return NULL;
2572
2573         if (blkid_topology_get_minimum_io_size(tp) == 0)
2574                 return ped_alignment_new(
2575                         blkid_topology_get_alignment_offset(tp) /
2576                                 dev->sector_size,
2577                         dev->phys_sector_size / dev->sector_size);
2578
2579         return ped_alignment_new(
2580                 blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2581                 blkid_topology_get_minimum_io_size(tp) / dev->sector_size);
2582 }
2583
2584 PedAlignment*
2585 linux_get_optimum_alignment(const PedDevice *dev)
2586 {
2587         blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
2588         if (!tp)
2589                 return NULL;
2590
2591         /* If optimal_io_size is 0 _and_ alignment_offset is 0 _and_
2592            minimum_io_size is a power of 2 then go with the device.c default */
2593         unsigned long minimum_io_size = blkid_topology_get_minimum_io_size(tp);
2594         if (blkid_topology_get_optimal_io_size(tp) == 0 &&
2595             blkid_topology_get_alignment_offset(tp) == 0 &&
2596             (minimum_io_size & (minimum_io_size - 1)) == 0)
2597                 return NULL;
2598
2599         /* If optimal_io_size is 0 and we don't meet the other criteria
2600            for using the device.c default, return the minimum alignment. */
2601         if (blkid_topology_get_optimal_io_size(tp) == 0)
2602                 return linux_get_minimum_alignment(dev);
2603
2604         return ped_alignment_new(
2605                 blkid_topology_get_alignment_offset(tp) / dev->sector_size,
2606                 blkid_topology_get_optimal_io_size(tp) / dev->sector_size);
2607 }
2608 #endif
2609
2610 static PedDeviceArchOps linux_dev_ops = {
2611         _new:           linux_new,
2612         destroy:        linux_destroy,
2613         is_busy:        linux_is_busy,
2614         open:           linux_open,
2615         refresh_open:   linux_refresh_open,
2616         close:          linux_close,
2617         refresh_close:  linux_refresh_close,
2618         read:           linux_read,
2619         write:          linux_write,
2620         check:          linux_check,
2621         sync:           linux_sync,
2622         sync_fast:      linux_sync_fast,
2623         probe_all:      linux_probe_all,
2624 #if USE_BLKID
2625         get_minimum_alignment:  linux_get_minimum_alignment,
2626         get_optimum_alignment:  linux_get_optimum_alignment,
2627 #endif
2628 };
2629
2630 PedDiskArchOps linux_disk_ops =  {
2631         partition_get_path:     linux_partition_get_path,
2632         partition_is_busy:      linux_partition_is_busy,
2633         disk_commit:            linux_disk_commit
2634 };
2635
2636 PedArchitecture ped_linux_arch = {
2637         dev_ops:        &linux_dev_ops,
2638         disk_ops:       &linux_disk_ops
2639 };