~ubuntu-branches/ubuntu/vivid/parted/vivid

« back to all changes in this revision

Viewing changes to .pc/probe-lvs-again.patch/libparted/arch/linux.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2014-08-10 11:02:32 UTC
  • mfrom: (7.2.36 sid)
  • Revision ID: package-import@ubuntu.com-20140810110232-r36iqk36whpowvj2
Tags: 3.2-3
Probe LVM logical volumes again (closes: #757417).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* libparted - a library for manipulating disk partitions
 
2
    Copyright (C) 1999-2014 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
#include <linux/blkpg.h>
 
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 <stdlib.h>
 
30
#include <ctype.h>
 
31
#include <errno.h>
 
32
#include <fcntl.h>
 
33
#include <libgen.h>
 
34
#include <stdio.h>
 
35
#include <syscall.h>
 
36
#include <unistd.h>
 
37
#include <stdbool.h>
 
38
#include <dirent.h>
 
39
#include <sys/ioctl.h>
 
40
#include <sys/stat.h>
 
41
#include <sys/types.h>
 
42
#include <sys/utsname.h>        /* for uname() */
 
43
#include <scsi/scsi.h>
 
44
#include <assert.h>
 
45
#ifdef ENABLE_DEVICE_MAPPER
 
46
#include <libdevmapper.h>
 
47
#endif
 
48
 
 
49
#include "../architecture.h"
 
50
#include "dirname.h"
 
51
#include "xstrtol.h"
 
52
#include "xalloc.h"
 
53
 
 
54
#if ENABLE_NLS
 
55
#  include <libintl.h>
 
56
#  define _(String) dgettext (PACKAGE, String)
 
57
#else
 
58
#  define _(String) (String)
 
59
#endif /* ENABLE_NLS */
 
60
 
 
61
/* The __attribute__ feature is available in gcc versions 2.5 and later.
 
62
   The __-protected variants of the attributes 'format' and 'printf' are
 
63
   accepted by gcc versions 2.6.4 (effectively 2.7) and later.  */
 
64
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
 
65
# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
 
66
#else
 
67
# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */
 
68
#endif
 
69
 
 
70
#define STRPREFIX(a, b) (strncmp (a, b, strlen (b)) == 0)
 
71
 
 
72
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
 
73
 
 
74
#ifndef __NR__llseek
 
75
#define __NR__llseek 140
 
76
#endif
 
77
 
 
78
#ifndef SCSI_IOCTL_SEND_COMMAND
 
79
#define SCSI_IOCTL_SEND_COMMAND 1
 
80
#endif
 
81
 
 
82
/* from <linux/hdreg.h> */
 
83
#define HDIO_GETGEO             0x0301  /* get device geometry */
 
84
#define HDIO_GET_IDENTITY       0x030d  /* get IDE identification info */
 
85
 
 
86
#define RD_MODE (O_RDONLY)
 
87
#define WR_MODE (O_WRONLY)
 
88
#define RW_MODE (O_RDWR)
 
89
 
 
90
struct hd_geometry {
 
91
        unsigned char heads;
 
92
        unsigned char sectors;
 
93
        unsigned short cylinders;
 
94
        unsigned long start;
 
95
};
 
96
 
 
97
struct ata7_sectinfo {
 
98
        int valid1:1;
 
99
        int valid2:1;
 
100
        int rsv:26;
 
101
        int multiplier:4;
 
102
};
 
103
 
 
104
/* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
 
105
struct hd_driveid {
 
106
        unsigned short  config;         /* lots of obsolete bit flags */
 
107
        unsigned short  cyls;           /* "physical" cyls */
 
108
        unsigned short  reserved2;      /* reserved (word 2) */
 
109
        unsigned short  heads;          /* "physical" heads */
 
110
        unsigned short  track_bytes;    /* unformatted bytes per track */
 
111
        unsigned short  sector_bytes;   /* unformatted bytes per sector */
 
112
        unsigned short  sectors;        /* "physical" sectors per track */
 
113
        unsigned short  vendor0;        /* vendor unique */
 
114
        unsigned short  vendor1;        /* vendor unique */
 
115
        unsigned short  vendor2;        /* vendor unique */
 
116
        unsigned char   serial_no[20];  /* 0 = not_specified */
 
117
        unsigned short  buf_type;
 
118
        unsigned short  buf_size;       /* 512 byte increments;
 
119
                                                         0 = not_specified */
 
120
        unsigned short  ecc_bytes;      /* for r/w long cmds;
 
121
                                                         0 = not_specified */
 
122
        unsigned char   fw_rev[8];      /* 0 = not_specified */
 
123
        char            model[40];      /* 0 = not_specified */
 
124
        unsigned char   max_multsect;   /* 0=not_implemented */
 
125
        unsigned char   vendor3;        /* vendor unique */
 
126
        unsigned short  dword_io;       /* 0=not_implemented; 1=implemented */
 
127
        unsigned char   vendor4;        /* vendor unique */
 
128
        unsigned char   capability;     /* bits 0:DMA 1:LBA 2:IORDYsw
 
129
                                                3:IORDYsup*/
 
130
        unsigned short  reserved50;     /* reserved (word 50) */
 
131
        unsigned char   vendor5;        /* vendor unique */
 
132
        unsigned char   tPIO;           /* 0=slow, 1=medium, 2=fast */
 
133
        unsigned char   vendor6;        /* vendor unique */
 
134
        unsigned char   tDMA;           /* 0=slow, 1=medium, 2=fast */
 
135
        unsigned short  field_valid;    /* bits 0:cur_ok 1:eide_ok */
 
136
        unsigned short  cur_cyls;       /* logical cylinders */
 
137
        unsigned short  cur_heads;      /* logical heads */
 
138
        unsigned short  cur_sectors;    /* logical sectors per track */
 
139
        unsigned short  cur_capacity0;  /* logical total sectors on drive */
 
140
        unsigned short  cur_capacity1;  /*  (2 words, misaligned int)     */
 
141
        unsigned char   multsect;       /* current multiple sector count */
 
142
        unsigned char   multsect_valid; /* when (bit0==1) multsect is ok */
 
143
        unsigned int    lba_capacity;   /* total number of sectors */
 
144
        unsigned short  dma_1word;      /* single-word dma info */
 
145
        unsigned short  dma_mword;      /* multiple-word dma info */
 
146
        unsigned short  eide_pio_modes; /* bits 0:mode3 1:mode4 */
 
147
        unsigned short  eide_dma_min;   /* min mword dma cycle time (ns) */
 
148
        unsigned short  eide_dma_time;  /* recommended mword dma cycle
 
149
                                           time (ns) */
 
150
        unsigned short  eide_pio;       /* min cycle time (ns), no IORDY  */
 
151
        unsigned short  eide_pio_iordy; /* min cycle time (ns), with IORDY */
 
152
        unsigned short  words69_70[2];  /* reserved words 69-70 */
 
153
        /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
 
154
        unsigned short  words71_74[4];  /* reserved words 71-74 */
 
155
        unsigned short  queue_depth;    /*  */
 
156
        unsigned short  words76_79[4];  /* reserved words 76-79 */
 
157
        unsigned short  major_rev_num;  /*  */
 
158
        unsigned short  minor_rev_num;  /*  */
 
159
        unsigned short  command_set_1;  /* bits 0:Smart 1:Security 2:Removable
 
160
                                                3:PM */
 
161
        unsigned short  command_set_2;  /* bits 14:Smart Enabled 13:0 zero */
 
162
        unsigned short  cfsse;          /* command set-feature supported
 
163
                                           extensions */
 
164
        unsigned short  cfs_enable_1;   /* command set-feature enabled */
 
165
        unsigned short  cfs_enable_2;   /* command set-feature enabled */
 
166
        unsigned short  csf_default;    /* command set-feature default */
 
167
        unsigned short  dma_ultra;      /*  */
 
168
        unsigned short  word89;         /* reserved (word 89) */
 
169
        unsigned short  word90;         /* reserved (word 90) */
 
170
        unsigned short  CurAPMvalues;   /* current APM values */
 
171
        unsigned short  word92;         /* reserved (word 92) */
 
172
        unsigned short  hw_config;      /* hardware config */
 
173
        unsigned short  words94_105[12];/* reserved words 94-105 */
 
174
        struct ata7_sectinfo ata7_sectinfo; /* ATAPI/ATA7 physical and logical
 
175
                                               sector size */
 
176
        unsigned short  words107_116[10];/* reserved words 107-116 */
 
177
        unsigned int    logical_sectsize;/* ATAPI/ATA7 logical sector size */
 
178
        unsigned short  words119_125[7];/* reserved words 119-125 */
 
179
        unsigned short  last_lun;       /* reserved (word 126) */
 
180
        unsigned short  word127;        /* reserved (word 127) */
 
181
        unsigned short  dlf;            /* device lock function
 
182
                                         * 15:9 reserved
 
183
                                         * 8    security level 1:max 0:high
 
184
                                         * 7:6  reserved
 
185
                                         * 5    enhanced erase
 
186
                                         * 4    expire
 
187
                                         * 3    frozen
 
188
                                         * 2    locked
 
189
                                         * 1    en/disabled
 
190
                                         * 0    capability
 
191
                                         */
 
192
        unsigned short  csfo;           /* current set features options
 
193
                                         * 15:4 reserved
 
194
                                         * 3    auto reassign
 
195
                                         * 2    reverting
 
196
                                         * 1    read-look-ahead
 
197
                                         * 0    write cache
 
198
                                         */
 
199
        unsigned short  words130_155[26];/* reserved vendor words 130-155 */
 
200
        unsigned short  word156;
 
201
        unsigned short  words157_159[3]; /* reserved vendor words 157-159 */
 
202
        unsigned short  words160_255[95];/* reserved words 160-255 */
 
203
};
 
204
 
 
205
/* from <linux/fs.h> */
 
206
#define BLKRRPART  _IO(0x12,95) /* re-read partition table */
 
207
#define BLKGETSIZE _IO(0x12,96) /* return device size */
 
208
#define BLKFLSBUF  _IO(0x12,97) /* flush buffer cache */
 
209
#define BLKSSZGET  _IO(0x12,104) /* get block device sector size */
 
210
#define BLKGETLASTSECT  _IO(0x12,108) /* get last sector of block device */
 
211
#define BLKSETLASTSECT  _IO(0x12,109) /* set last sector of block device */
 
212
 
 
213
/* return device size in bytes (u64 *arg) */
 
214
#define BLKGETSIZE64 _IOR(0x12,114,size_t)
 
215
 
 
216
struct blkdev_ioctl_param {
 
217
        unsigned int block;
 
218
        size_t content_length;
 
219
        char * block_contents;
 
220
};
 
221
 
 
222
/* from <linux/major.h> */
 
223
#define IDE0_MAJOR              3
 
224
#define IDE1_MAJOR              22
 
225
#define IDE2_MAJOR              33
 
226
#define IDE3_MAJOR              34
 
227
#define IDE4_MAJOR              56
 
228
#define IDE5_MAJOR              57
 
229
#define SCSI_CDROM_MAJOR        11
 
230
#define SCSI_DISK0_MAJOR        8
 
231
#define SCSI_DISK1_MAJOR        65
 
232
#define SCSI_DISK2_MAJOR        66
 
233
#define SCSI_DISK3_MAJOR        67
 
234
#define SCSI_DISK4_MAJOR        68
 
235
#define SCSI_DISK5_MAJOR        69
 
236
#define SCSI_DISK6_MAJOR        70
 
237
#define SCSI_DISK7_MAJOR        71
 
238
#define SCSI_DISK8_MAJOR        128
 
239
#define SCSI_DISK9_MAJOR        129
 
240
#define SCSI_DISK10_MAJOR       130
 
241
#define SCSI_DISK11_MAJOR       131
 
242
#define SCSI_DISK12_MAJOR       132
 
243
#define SCSI_DISK13_MAJOR       133
 
244
#define SCSI_DISK14_MAJOR       134
 
245
#define SCSI_DISK15_MAJOR       135
 
246
#define COMPAQ_SMART2_MAJOR     72
 
247
#define COMPAQ_SMART2_MAJOR1    73
 
248
#define COMPAQ_SMART2_MAJOR2    74
 
249
#define COMPAQ_SMART2_MAJOR3    75
 
250
#define COMPAQ_SMART2_MAJOR4    76
 
251
#define COMPAQ_SMART2_MAJOR5    77
 
252
#define COMPAQ_SMART2_MAJOR6    78
 
253
#define COMPAQ_SMART2_MAJOR7    79
 
254
#define COMPAQ_SMART_MAJOR      104
 
255
#define COMPAQ_SMART_MAJOR1     105
 
256
#define COMPAQ_SMART_MAJOR2     106
 
257
#define COMPAQ_SMART_MAJOR3     107
 
258
#define COMPAQ_SMART_MAJOR4     108
 
259
#define COMPAQ_SMART_MAJOR5     109
 
260
#define COMPAQ_SMART_MAJOR6     110
 
261
#define COMPAQ_SMART_MAJOR7     111
 
262
#define DAC960_MAJOR            48
 
263
#define ATARAID_MAJOR           114
 
264
#define I2O_MAJOR1              80
 
265
#define I2O_MAJOR2              81
 
266
#define I2O_MAJOR3              82
 
267
#define I2O_MAJOR4              83
 
268
#define I2O_MAJOR5              84
 
269
#define I2O_MAJOR6              85
 
270
#define I2O_MAJOR7              86
 
271
#define I2O_MAJOR8              87
 
272
#define UBD_MAJOR               98
 
273
#define DASD_MAJOR              94
 
274
#define VIODASD_MAJOR           112
 
275
#define AOE_MAJOR               152
 
276
#define SX8_MAJOR1              160
 
277
#define SX8_MAJOR2              161
 
278
#define XVD_MAJOR               202
 
279
#define SDMMC_MAJOR             179
 
280
#define LOOP_MAJOR              7
 
281
#define MD_MAJOR                9
 
282
 
 
283
#define SCSI_BLK_MAJOR(M) (                                             \
 
284
                (M) == SCSI_DISK0_MAJOR                                 \
 
285
                || (M) == SCSI_CDROM_MAJOR                              \
 
286
                || ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR) \
 
287
                || ((M) >= SCSI_DISK8_MAJOR && (M) <= SCSI_DISK15_MAJOR))
 
288
 
 
289
/* Maximum number of partitions supported by linux. */
 
290
#define MAX_NUM_PARTS           64
 
291
 
 
292
static char* _device_get_part_path (PedDevice const *dev, int num);
 
293
static int _partition_is_mounted_by_path (const char* path);
 
294
static unsigned int _device_get_partition_range(PedDevice const* dev);
 
295
 
 
296
 
 
297
static int
 
298
_read_fd (int fd, char **buf)
 
299
{
 
300
        char* p;
 
301
        size_t size = PROC_DEVICES_BUFSIZ;
 
302
        int s, filesize = 0;
 
303
 
 
304
        *buf = malloc (size * sizeof (char));
 
305
        if (*buf == 0) {
 
306
                return -1;
 
307
        }
 
308
 
 
309
        do {
 
310
                p = &(*buf) [filesize];
 
311
                s = read (fd, p, PROC_DEVICES_BUFSIZ);
 
312
                /* exit if there is an error or EOF is reached */
 
313
                if (s <= 0)
 
314
                        break;
 
315
                filesize += s;
 
316
                size += s;
 
317
                char *new_buf = realloc (*buf, size);
 
318
                if (new_buf == NULL) {
 
319
                        int saved_errno = errno;
 
320
                        free (*buf);
 
321
                        errno = saved_errno;
 
322
                        return -1;
 
323
                }
 
324
                *buf = new_buf;
 
325
        } while (1);
 
326
 
 
327
        if (filesize == 0 && s < 0) {
 
328
                free (*buf);
 
329
                *buf = NULL;
 
330
                return -1;
 
331
        } else {
 
332
                char *new_buf = realloc (*buf, filesize + 1);
 
333
                if (new_buf == NULL) {
 
334
                        int saved_errno = errno;
 
335
                        free (*buf);
 
336
                        errno = saved_errno;
 
337
                        return -1;
 
338
                }
 
339
                *buf = new_buf;
 
340
                (*buf)[filesize] = '\0';
 
341
        }
 
342
 
 
343
        return filesize;
 
344
}
 
345
 
 
346
static int
 
347
_major_type_in_devices (int major, const char* type)
 
348
{
 
349
        int fd;
 
350
        char* buf = NULL;
 
351
        char* line;
 
352
        char* end;
 
353
        int bd = 0;
 
354
        char c;
 
355
 
 
356
        fd = open ("/proc/devices", O_RDONLY);
 
357
        if (fd < 0)
 
358
                return 0;
 
359
 
 
360
        if (_read_fd(fd, &buf) < 0) {
 
361
                close(fd);
 
362
                return 0;
 
363
        }
 
364
 
 
365
        line = buf;
 
366
        end = strchr(line, '\n');
 
367
        while (end) {
 
368
                char *name;
 
369
                int maj;
 
370
 
 
371
                c = *end;
 
372
                *end = '\0';
 
373
 
 
374
                if (!bd) {
 
375
                        if (!strncmp(line, "Block devices:", 14))
 
376
                                bd = 1;
 
377
                        goto next;
 
378
                }
 
379
 
 
380
                name = strrchr(line, ' ');
 
381
                if (!name || strcmp(name+1, type))
 
382
                        goto next;
 
383
 
 
384
                maj = strtol(line, &name, 10);
 
385
                if (maj == major) {
 
386
                        free(buf);
 
387
                        close(fd);
 
388
                        return 1;
 
389
                }
 
390
 
 
391
next:
 
392
                *end = c;
 
393
                line = end+1;
 
394
                end = strchr(line, '\n');
 
395
        }
 
396
        free(buf);
 
397
        close(fd);
 
398
        return 0;
 
399
}
 
400
 
 
401
static int
 
402
_is_ide_major (int major)
 
403
{
 
404
        switch (major) {
 
405
                case IDE0_MAJOR:
 
406
                case IDE1_MAJOR:
 
407
                case IDE2_MAJOR:
 
408
                case IDE3_MAJOR:
 
409
                case IDE4_MAJOR:
 
410
                case IDE5_MAJOR:
 
411
                        return 1;
 
412
 
 
413
                default:
 
414
                        return 0;
 
415
        }
 
416
}
 
417
 
 
418
static int
 
419
_is_cpqarray_major (int major)
 
420
{
 
421
        return ((COMPAQ_SMART2_MAJOR <= major && major <= COMPAQ_SMART2_MAJOR7)
 
422
             || (COMPAQ_SMART_MAJOR <= major && major <= COMPAQ_SMART_MAJOR7));
 
423
}
 
424
 
 
425
static int
 
426
_is_i2o_major (int major)
 
427
{
 
428
        return (I2O_MAJOR1 <= major && major <= I2O_MAJOR8);
 
429
}
 
430
 
 
431
static int
 
432
_is_sx8_major (int major)
 
433
{
 
434
        return (SX8_MAJOR1 <= major && major <= SX8_MAJOR2);
 
435
}
 
436
 
 
437
static int
 
438
_is_virtblk_major (int major)
 
439
{
 
440
        return _major_type_in_devices (major, "virtblk");
 
441
}
 
442
 
 
443
#ifdef ENABLE_DEVICE_MAPPER
 
444
static int
 
445
_dm_task_run_wait (struct dm_task *task, uint32_t cookie)
 
446
{
 
447
        int rc = 0;
 
448
 
 
449
        rc = dm_task_run (task);
 
450
        dm_udev_wait (cookie);
 
451
 
 
452
        return rc;
 
453
}
 
454
 
 
455
static int
 
456
_is_dm_major (int major)
 
457
{
 
458
        return _major_type_in_devices (major, "device-mapper");
 
459
}
 
460
 
 
461
static int
 
462
_dm_maptype (PedDevice *dev)
 
463
{
 
464
        LinuxSpecific*  arch_specific = LINUX_SPECIFIC (dev);
 
465
        struct dm_task *dmt;
 
466
        uint64_t start, length;
 
467
        char *target_type = NULL;
 
468
        char *params;
 
469
        int r = -1;
 
470
        const char* dev_dir = getenv ("DM_DEV_DIR");
 
471
 
 
472
        if (dev_dir && *dev_dir && !dm_set_dev_dir(dev_dir))
 
473
                return r;
 
474
 
 
475
        if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
 
476
                return r;
 
477
 
 
478
        if (!dm_task_set_major_minor(dmt, arch_specific->major,
 
479
                                     arch_specific->minor, 0))
 
480
                goto bad;
 
481
 
 
482
        dm_task_no_open_count(dmt);
 
483
 
 
484
        if (!dm_task_run(dmt))
 
485
                goto bad;
 
486
 
 
487
        dm_get_next_target(dmt, NULL, &start, &length, &target_type, &params);
 
488
 
 
489
        arch_specific->dmtype = strdup(target_type ? target_type : "NO-TARGET");
 
490
        if (arch_specific->dmtype == NULL)
 
491
                goto bad;
 
492
        r = 0;
 
493
bad:
 
494
        dm_task_destroy(dmt);
 
495
        return r;
 
496
}
 
497
 
 
498
/* Return nonzero if device-mapper device, DEVPATH, is part of a dmraid
 
499
   array.  Use the heuristic of checking for the string "DMRAID-" at the
 
500
   start of its UUID.  */
 
501
static int
 
502
_is_dmraid_device (const char *devpath)
 
503
{
 
504
        int rc = 0;
 
505
 
 
506
        char const *dm_name = strrchr (devpath, '/');
 
507
        char const *dm_basename = dm_name && *(++dm_name) ? dm_name : devpath;
 
508
        struct dm_task *task = dm_task_create (DM_DEVICE_DEPS);
 
509
        if (!task)
 
510
                return 0;
 
511
 
 
512
        dm_task_set_name (task, dm_basename);
 
513
        if (!dm_task_run (task))
 
514
                goto err;
 
515
 
 
516
        const char *dmraid_uuid = dm_task_get_uuid (task);
 
517
        if (STRPREFIX (dmraid_uuid, "DMRAID-"))
 
518
                rc = 1;
 
519
 
 
520
err:
 
521
        dm_task_destroy (task);
 
522
        return rc;
 
523
}
 
524
 
 
525
/* We consider a dm device that is a linear mapping with a  *
 
526
 * single target that also is a dm device to be a partition */
 
527
 
 
528
static int
 
529
_dm_is_part (const char *path)
 
530
{
 
531
        int rc = 0;
 
532
        struct dm_task *task = dm_task_create (DM_DEVICE_DEPS);
 
533
        if (!task)
 
534
                return 0;
 
535
 
 
536
        dm_task_set_name(task, path);
 
537
        if (!dm_task_run(task))
 
538
                goto err;
 
539
 
 
540
        struct dm_info *info = alloca (sizeof *info);
 
541
        memset(info, '\0', sizeof *info);
 
542
        dm_task_get_info (task, info);
 
543
        if (!info->exists)
 
544
                goto err;
 
545
 
 
546
        struct dm_deps *deps = dm_task_get_deps (task);
 
547
        if (!deps)
 
548
                goto err;
 
549
 
 
550
        if (deps->count != 1)
 
551
                goto err;
 
552
        if (!_is_dm_major (major (deps->device[0])))
 
553
                goto err;
 
554
        dm_task_destroy (task);
 
555
        if (!(task = dm_task_create (DM_DEVICE_TABLE)))
 
556
                return 0;
 
557
        dm_task_set_name (task, path);
 
558
        if (!dm_task_run (task))
 
559
                goto err;
 
560
 
 
561
        char *target_type = NULL;
 
562
        char *params = NULL;
 
563
        uint64_t start, length;
 
564
 
 
565
        dm_get_next_target (task, NULL, &start, &length, &target_type, &params);
 
566
        if (strcmp (target_type, "linear"))
 
567
                goto err;
 
568
        rc = 1;
 
569
 
 
570
err:
 
571
        dm_task_destroy(task);
 
572
        return rc;
 
573
}
 
574
 
 
575
static int
 
576
_probe_dm_devices ()
 
577
{
 
578
       DIR*            mapper_dir;
 
579
       struct dirent*  dent;
 
580
       char            buf [512];      /* readdir(3) claims d_name[256] */
 
581
       struct stat     st;
 
582
 
 
583
       mapper_dir = opendir ("/dev/mapper");
 
584
       if (!mapper_dir)
 
585
               return 0;
 
586
 
 
587
       /* Search the /dev/mapper directory for devices w/ the same major
 
588
        * number that was returned from _probe_lvm_major().
 
589
        */
 
590
       while ((dent = readdir (mapper_dir))) {
 
591
               if (strcmp (dent->d_name, ".")  == 0 ||
 
592
                   strcmp (dent->d_name, "..") == 0)
 
593
                       continue;
 
594
 
 
595
               snprintf (buf, sizeof (buf), "/dev/mapper/%s", dent->d_name);
 
596
 
 
597
               if (stat (buf, &st) != 0)
 
598
                       continue;
 
599
 
 
600
               if (_is_dm_major(major(st.st_rdev)) && _is_dmraid_device (buf)
 
601
                   && !_dm_is_part(buf))
 
602
                       _ped_device_probe (buf);
 
603
       }
 
604
       closedir (mapper_dir);
 
605
 
 
606
       return 1;
 
607
}
 
608
#endif
 
609
 
 
610
static int
 
611
_device_stat (PedDevice* dev, struct stat * dev_stat)
 
612
{
 
613
        PED_ASSERT (dev != NULL);
 
614
        PED_ASSERT (!dev->external_mode);
 
615
 
 
616
        while (1) {
 
617
                if (!stat (dev->path, dev_stat)) {
 
618
                        return 1;
 
619
                } else {
 
620
                        if (ped_exception_throw (
 
621
                                PED_EXCEPTION_ERROR,
 
622
                                PED_EXCEPTION_RETRY_CANCEL,
 
623
                                _("Could not stat device %s - %s."),
 
624
                                dev->path,
 
625
                                strerror (errno))
 
626
                                        != PED_EXCEPTION_RETRY)
 
627
                                return 0;
 
628
                }
 
629
        }
 
630
}
 
631
 
 
632
static int
 
633
_device_probe_type (PedDevice* dev)
 
634
{
 
635
        struct stat             dev_stat;
 
636
        int                     dev_major;
 
637
        int                     dev_minor;
 
638
        LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
 
639
 
 
640
        if (!_device_stat (dev, &dev_stat))
 
641
                return 0;
 
642
 
 
643
        if (!S_ISBLK(dev_stat.st_mode)) {
 
644
                dev->type = PED_DEVICE_FILE;
 
645
                return 1;
 
646
        }
 
647
 
 
648
        arch_specific->major = dev_major = major (dev_stat.st_rdev);
 
649
        arch_specific->minor = dev_minor = minor (dev_stat.st_rdev);
 
650
 
 
651
        if (SCSI_BLK_MAJOR (dev_major) && (dev_minor % 0x10 == 0)) {
 
652
                dev->type = PED_DEVICE_SCSI;
 
653
        } else if (_is_ide_major (dev_major) && (dev_minor % 0x40 == 0)) {
 
654
                dev->type = PED_DEVICE_IDE;
 
655
        } else if (dev_major == DAC960_MAJOR && (dev_minor % 0x8 == 0)) {
 
656
                dev->type = PED_DEVICE_DAC960;
 
657
        } else if (dev_major == ATARAID_MAJOR && (dev_minor % 0x10 == 0)) {
 
658
                dev->type = PED_DEVICE_ATARAID;
 
659
        } else if (dev_major == AOE_MAJOR && (dev_minor % 0x10 == 0)) {
 
660
                dev->type = PED_DEVICE_AOE;
 
661
        } else if (dev_major == DASD_MAJOR && (dev_minor % 0x4 == 0)) {
 
662
                dev->type = PED_DEVICE_DASD;
 
663
        } else if (dev_major == VIODASD_MAJOR && (dev_minor % 0x8 == 0)) {
 
664
                dev->type = PED_DEVICE_VIODASD;
 
665
        } else if (_is_sx8_major(dev_major) && (dev_minor % 0x20 == 0)) {
 
666
                dev->type = PED_DEVICE_SX8;
 
667
        } else if (_is_i2o_major (dev_major) && (dev_minor % 0x10 == 0)) {
 
668
                dev->type = PED_DEVICE_I2O;
 
669
        } else if (_is_cpqarray_major (dev_major) && (dev_minor % 0x10 == 0)) {
 
670
                dev->type = PED_DEVICE_CPQARRAY;
 
671
        } else if (dev_major == UBD_MAJOR && (dev_minor % 0x10 == 0)) {
 
672
                dev->type = PED_DEVICE_UBD;
 
673
#ifdef ENABLE_DEVICE_MAPPER
 
674
        } else if (_is_dm_major(dev_major)) {
 
675
                dev->type = PED_DEVICE_DM;
 
676
                if (_dm_maptype(dev)) {
 
677
                        ped_exception_throw (
 
678
                                PED_EXCEPTION_BUG,
 
679
                                PED_EXCEPTION_CANCEL,
 
680
                                _("Unable to determine the dm type of %s."),
 
681
                                dev->path);
 
682
                }
 
683
#endif
 
684
        } else if (dev_major == XVD_MAJOR && (dev_minor % 0x10 == 0)) {
 
685
                dev->type = PED_DEVICE_XVD;
 
686
        } else if (dev_major == SDMMC_MAJOR && (dev_minor % 0x08 == 0)) {
 
687
                dev->type = PED_DEVICE_SDMMC;
 
688
        } else if (_is_virtblk_major(dev_major)) {
 
689
                dev->type = PED_DEVICE_VIRTBLK;
 
690
        } else if (dev_major == LOOP_MAJOR) {
 
691
                dev->type = PED_DEVICE_LOOP;
 
692
        } else if (dev_major == MD_MAJOR) {
 
693
                dev->type = PED_DEVICE_MD;
 
694
        } else {
 
695
                dev->type = PED_DEVICE_UNKNOWN;
 
696
        }
 
697
 
 
698
        return 1;
 
699
}
 
700
 
 
701
static int
 
702
_get_linux_version ()
 
703
{
 
704
        static int kver = -1;
 
705
 
 
706
        struct utsname uts;
 
707
        int major = 0;
 
708
        int minor = 0;
 
709
        int teeny = 0;
 
710
 
 
711
        if (kver != -1)
 
712
                return kver;
 
713
 
 
714
        if (uname (&uts))
 
715
                return kver = 0;
 
716
        int n = sscanf (uts.release, "%u.%u.%u", &major, &minor, &teeny);
 
717
        assert (n == 2 || n == 3);
 
718
        return kver = KERNEL_VERSION (major, minor, teeny);
 
719
}
 
720
 
 
721
#if USE_BLKID
 
722
static void
 
723
get_blkid_topology (LinuxSpecific *arch_specific)
 
724
{
 
725
        arch_specific->probe = blkid_new_probe ();
 
726
        if (!arch_specific->probe)
 
727
                return;
 
728
 
 
729
        if (blkid_probe_set_device(arch_specific->probe,
 
730
                                   arch_specific->fd, 0, 0))
 
731
                return;
 
732
 
 
733
        arch_specific->topology =
 
734
                blkid_probe_get_topology(arch_specific->probe);
 
735
}
 
736
#endif
 
737
 
 
738
static void
 
739
_device_set_sector_size (PedDevice* dev)
 
740
{
 
741
        LinuxSpecific*  arch_specific = LINUX_SPECIFIC (dev);
 
742
        int sector_size;
 
743
 
 
744
        dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
 
745
        dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
 
746
 
 
747
        PED_ASSERT (dev->open_count);
 
748
 
 
749
        if (_get_linux_version() < KERNEL_VERSION (2,3,0)) {
 
750
                dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
 
751
                return;
 
752
        }
 
753
 
 
754
        if (ioctl (arch_specific->fd, BLKSSZGET, &sector_size)) {
 
755
                ped_exception_throw (
 
756
                        PED_EXCEPTION_WARNING,
 
757
                        PED_EXCEPTION_OK,
 
758
                        _("Could not determine sector size for %s: %s.\n"
 
759
                          "Using the default sector size (%lld)."),
 
760
                        dev->path, strerror (errno), PED_SECTOR_SIZE_DEFAULT);
 
761
        } else {
 
762
                dev->sector_size = (long long)sector_size;
 
763
                dev->phys_sector_size = dev->sector_size;
 
764
        }
 
765
 
 
766
#if USE_BLKID
 
767
        get_blkid_topology(arch_specific);
 
768
        if (!arch_specific->topology) {
 
769
                dev->phys_sector_size = 0;
 
770
        } else {
 
771
                dev->phys_sector_size =
 
772
                        blkid_topology_get_physical_sector_size(
 
773
                                arch_specific->topology);
 
774
        }
 
775
        if (dev->phys_sector_size == 0) {
 
776
                ped_exception_throw (
 
777
                        PED_EXCEPTION_WARNING,
 
778
                        PED_EXCEPTION_OK,
 
779
                        _("Could not determine physical sector size for %s.\n"
 
780
                          "Using the logical sector size (%lld)."),
 
781
                        dev->path, dev->sector_size);
 
782
                dev->phys_sector_size = dev->sector_size;
 
783
        }
 
784
#endif
 
785
 
 
786
#if defined __s390__ || defined __s390x__
 
787
        /* Return PED_SECTOR_SIZE_DEFAULT for DASDs. */
 
788
        if (dev->type == PED_DEVICE_DASD) {
 
789
                arch_specific->real_sector_size = dev->sector_size;
 
790
                dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
 
791
        }
 
792
#endif
 
793
}
 
794
 
 
795
static int
 
796
_kernel_has_blkgetsize64(void)
 
797
{
 
798
        int version = _get_linux_version();
 
799
 
 
800
        if (version >= KERNEL_VERSION (2,5,4)) return 1;
 
801
        if (version <  KERNEL_VERSION (2,5,0) &&
 
802
            version >= KERNEL_VERSION (2,4,18)) return 1;
 
803
        return 0;
 
804
}
 
805
 
 
806
/* TODO: do a binary search if BLKGETSIZE doesn't work?! */
 
807
static PedSector
 
808
_device_get_length (PedDevice* dev)
 
809
{
 
810
        unsigned long           size;
 
811
        LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
 
812
        uint64_t bytes=0;
 
813
        const char*             test_str;
 
814
        PedSector               test_size;
 
815
 
 
816
 
 
817
        PED_ASSERT (dev->open_count > 0);
 
818
        PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
 
819
 
 
820
        test_str = getenv ("PARTED_TEST_DEVICE_LENGTH");
 
821
        if (test_str
 
822
            && xstrtoll (test_str, NULL, 10, &test_size, NULL) == LONGINT_OK)
 
823
                return test_size;
 
824
 
 
825
        if (_kernel_has_blkgetsize64()) {
 
826
                if (ioctl(arch_specific->fd, BLKGETSIZE64, &bytes) == 0) {
 
827
                        return bytes / dev->sector_size;
 
828
                }
 
829
        }
 
830
 
 
831
        if (ioctl (arch_specific->fd, BLKGETSIZE, &size)) {
 
832
                ped_exception_throw (
 
833
                        PED_EXCEPTION_BUG,
 
834
                        PED_EXCEPTION_CANCEL,
 
835
                        _("Unable to determine the size of %s (%s)."),
 
836
                        dev->path,
 
837
                        strerror (errno));
 
838
                return 0;
 
839
        }
 
840
 
 
841
        return size;
 
842
}
 
843
 
 
844
static int
 
845
_device_probe_geometry (PedDevice* dev)
 
846
{
 
847
        LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
 
848
        struct stat             dev_stat;
 
849
        struct hd_geometry      geometry;
 
850
 
 
851
        if (!_device_stat (dev, &dev_stat))
 
852
                return 0;
 
853
        PED_ASSERT (S_ISBLK (dev_stat.st_mode));
 
854
 
 
855
        _device_set_sector_size (dev);
 
856
 
 
857
        dev->length = _device_get_length (dev);
 
858
        if (!dev->length)
 
859
                return 0;
 
860
 
 
861
        /* The GETGEO ioctl is no longer useful (as of linux 2.6.x).  We could
 
862
         * still use it in 2.4.x, but this is contentious.  Perhaps we should
 
863
         * move to EDD. */
 
864
        dev->bios_geom.sectors = 63;
 
865
        dev->bios_geom.heads = 255;
 
866
        dev->bios_geom.cylinders
 
867
                = dev->length / (63 * 255);
 
868
 
 
869
        /* FIXME: what should we put here?  (TODO: discuss on linux-kernel) */
 
870
        if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geometry)
 
871
                        && geometry.sectors && geometry.heads) {
 
872
                dev->hw_geom.sectors = geometry.sectors;
 
873
                dev->hw_geom.heads = geometry.heads;
 
874
                dev->hw_geom.cylinders
 
875
                        = dev->length / (dev->hw_geom.heads
 
876
                                         * dev->hw_geom.sectors);
 
877
        } else {
 
878
                dev->hw_geom = dev->bios_geom;
 
879
        }
 
880
 
 
881
        return 1;
 
882
}
 
883
 
 
884
static char*
 
885
strip_name(char* str)
 
886
{
 
887
        int     i;
 
888
        int     end = 0;
 
889
 
 
890
        for (i = 0; str[i] != 0; i++) {
 
891
                if (!isspace (str[i])
 
892
                    || (isspace (str[i]) && !isspace (str[i+1]) && str[i+1])) {
 
893
                        str [end] = str[i];
 
894
                        end++;
 
895
                }
 
896
        }
 
897
        str[end] = 0;
 
898
        return strdup (str);
 
899
}
 
900
 
 
901
static int
 
902
init_ide (PedDevice* dev)
 
903
{
 
904
        LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
 
905
        struct stat             dev_stat;
 
906
        struct hd_driveid       hdi;
 
907
        PedExceptionOption      ex_status;
 
908
        char                    hdi_buf[41];
 
909
        int                     sector_multiplier = 0;
 
910
 
 
911
        if (!_device_stat (dev, &dev_stat))
 
912
                goto error;
 
913
 
 
914
        if (!ped_device_open (dev))
 
915
                goto error;
 
916
 
 
917
        if (ioctl (arch_specific->fd, HDIO_GET_IDENTITY, &hdi)) {
 
918
                ex_status = ped_exception_throw (
 
919
                                PED_EXCEPTION_WARNING,
 
920
                                PED_EXCEPTION_IGNORE_CANCEL,
 
921
                                _("Could not get identity of device %s - %s"),
 
922
                                dev->path, strerror (errno));
 
923
                switch (ex_status) {
 
924
                        case PED_EXCEPTION_CANCEL:
 
925
                                goto error_close_dev;
 
926
 
 
927
                        case PED_EXCEPTION_UNHANDLED:
 
928
                                ped_exception_catch ();
 
929
                        case PED_EXCEPTION_IGNORE:
 
930
                                dev->model = strdup(_("Generic IDE"));
 
931
                                break;
 
932
                        default:
 
933
                                PED_ASSERT (0);
 
934
                                break;
 
935
                }
 
936
        } else {
 
937
                /* hdi.model is not guaranteed to be NULL terminated */
 
938
                memcpy (hdi_buf, hdi.model, 40);
 
939
                hdi_buf[40] = '\0';
 
940
                dev->model = strip_name (hdi_buf);
 
941
 
 
942
                if (!hdi.ata7_sectinfo.valid1 && hdi.ata7_sectinfo.valid2)
 
943
                        sector_multiplier = hdi.ata7_sectinfo.multiplier;
 
944
                else
 
945
                        sector_multiplier = 1;
 
946
 
 
947
                if (sector_multiplier != 1) {
 
948
                        ex_status = ped_exception_throw (
 
949
                                PED_EXCEPTION_WARNING,
 
950
                                PED_EXCEPTION_IGNORE_CANCEL,
 
951
                                _("Device %s has multiple (%d) logical sectors "
 
952
                                  "per physical sector.\n"
 
953
                                  "GNU Parted supports this EXPERIMENTALLY for "
 
954
                                  "some special disk label/file system "
 
955
                                  "combinations, e.g. GPT and ext2/3.\n"
 
956
                                  "Please consult the web site for up-to-date "
 
957
                                  "information."),
 
958
                                dev->path, sector_multiplier);
 
959
 
 
960
                        switch (ex_status) {
 
961
                                case PED_EXCEPTION_CANCEL:
 
962
                                        goto error_close_dev;
 
963
 
 
964
                                case PED_EXCEPTION_UNHANDLED:
 
965
                                        ped_exception_catch ();
 
966
                                case PED_EXCEPTION_IGNORE:
 
967
                                        break;
 
968
                                default:
 
969
                                        PED_ASSERT (0);
 
970
                                        break;
 
971
                        }
 
972
                }
 
973
 
 
974
                /* XXX sector_size has not been set yet! */
 
975
                /* dev->phys_sector_size = dev->sector_size
 
976
                   * sector_multiplier;*/
 
977
                dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
 
978
        }
 
979
 
 
980
        if (!_device_probe_geometry (dev))
 
981
                goto error_close_dev;
 
982
 
 
983
        ped_device_close (dev);
 
984
        return 1;
 
985
 
 
986
error_close_dev:
 
987
        ped_device_close (dev);
 
988
error:
 
989
        return 0;
 
990
}
 
991
 
 
992
/* This function reads the /sys entry named "file" for device "dev". */
 
993
static char *
 
994
read_device_sysfs_file (PedDevice *dev, const char *file)
 
995
{
 
996
        FILE *f;
 
997
        char name_buf[128];
 
998
        char buf[256];
 
999
 
 
1000
        snprintf (name_buf, 127, "/sys/block/%s/device/%s",
 
1001
                  last_component (dev->path), file);
 
1002
 
 
1003
        if ((f = fopen (name_buf, "r")) == NULL)
 
1004
                return NULL;
 
1005
 
 
1006
        if (fgets (buf, 255, f) == NULL) {
 
1007
                fclose (f);
 
1008
                return NULL;
 
1009
        }
 
1010
 
 
1011
        fclose (f);
 
1012
        return strip_name (buf);
 
1013
}
 
1014
 
 
1015
/* This function sends a query to a SCSI device for vendor and product
 
1016
 * information.  It uses the deprecated SCSI_IOCTL_SEND_COMMAND to
 
1017
 * issue this query.
 
1018
 */
 
1019
static int
 
1020
scsi_query_product_info (PedDevice* dev, char **vendor, char **product)
 
1021
{
 
1022
        /* The following are defined by the SCSI-2 specification. */
 
1023
        typedef struct _scsi_inquiry_cmd
 
1024
        {
 
1025
                uint8_t op;
 
1026
                uint8_t lun;          /* bits 5-7 denote the LUN */
 
1027
                uint8_t page_code;
 
1028
                uint8_t reserved;
 
1029
                uint8_t alloc_length;
 
1030
                uint8_t control;
 
1031
        } __attribute__((packed)) scsi_inquiry_cmd_t;
 
1032
 
 
1033
        typedef struct _scsi_inquiry_data
 
1034
        {
 
1035
                uint8_t peripheral_info;
 
1036
                uint8_t device_info;
 
1037
                uint8_t version_info;
 
1038
                uint8_t _field1;
 
1039
                uint8_t additional_length;
 
1040
                uint8_t _reserved1;
 
1041
                uint8_t _reserved2;
 
1042
                uint8_t _field2;
 
1043
                uint8_t vendor_id[8];
 
1044
                uint8_t product_id[16];
 
1045
                uint8_t product_revision[4];
 
1046
                uint8_t vendor_specific[20];
 
1047
                uint8_t _reserved3[40];
 
1048
        } __attribute__((packed)) scsi_inquiry_data_t;
 
1049
 
 
1050
        struct scsi_arg
 
1051
        {
 
1052
                unsigned int inlen;
 
1053
                unsigned int outlen;
 
1054
 
 
1055
                union arg_data
 
1056
                {
 
1057
                        scsi_inquiry_data_t out;
 
1058
                        scsi_inquiry_cmd_t  in;
 
1059
                } data;
 
1060
        } arg;
 
1061
 
 
1062
        LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
 
1063
        char    buf[32];
 
1064
 
 
1065
        *vendor = NULL;
 
1066
        *product = NULL;
 
1067
 
 
1068
        memset (&arg, 0x00, sizeof(struct scsi_arg));
 
1069
        arg.inlen  = 0;
 
1070
        arg.outlen = sizeof(scsi_inquiry_data_t);
 
1071
        arg.data.in.op  = INQUIRY;
 
1072
        arg.data.in.lun = dev->host << 5;
 
1073
        arg.data.in.alloc_length = sizeof(scsi_inquiry_data_t);
 
1074
        arg.data.in.page_code = 0;
 
1075
        arg.data.in.reserved = 0;
 
1076
        arg.data.in.control = 0;
 
1077
 
 
1078
        if (ioctl (arch_specific->fd, SCSI_IOCTL_SEND_COMMAND, &arg) < 0)
 
1079
                return 0;
 
1080
 
 
1081
        memcpy (buf, arg.data.out.vendor_id, 8);
 
1082
        buf[8] = '\0';
 
1083
        *vendor = strip_name (buf);
 
1084
 
 
1085
        memcpy (buf, arg.data.out.product_id, 16);
 
1086
        buf[16] = '\0';
 
1087
        *product = strip_name (buf);
 
1088
 
 
1089
        return 1;
 
1090
}
 
1091
 
 
1092
/* This function provides the vendor and product name for a SCSI device.
 
1093
 * It supports both the modern /sys interface and direct queries
 
1094
 * via the deprecated ioctl, SCSI_IOCTL_SEND_COMMAND.
 
1095
 */
 
1096
static int
 
1097
scsi_get_product_info (PedDevice* dev, char **vendor, char **product)
 
1098
{
 
1099
        *vendor = read_device_sysfs_file (dev, "vendor");
 
1100
        *product = read_device_sysfs_file (dev, "model");
 
1101
        if (*vendor && *product)
 
1102
                return 1;
 
1103
 
 
1104
        return scsi_query_product_info (dev, vendor, product);
 
1105
}
 
1106
 
 
1107
static int
 
1108
init_scsi (PedDevice* dev)
 
1109
{
 
1110
        struct scsi_idlun
 
1111
        {
 
1112
                uint32_t dev_id;
 
1113
                uint32_t host_unique_id;
 
1114
        } idlun;
 
1115
 
 
1116
        LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
 
1117
        char* vendor;
 
1118
        char* product;
 
1119
 
 
1120
        if (!ped_device_open (dev))
 
1121
                goto error;
 
1122
 
 
1123
        if (ioctl (arch_specific->fd, SCSI_IOCTL_GET_IDLUN, &idlun) < 0) {
 
1124
                dev->host = 0;
 
1125
                dev->did = 0;
 
1126
                if (ped_exception_throw (
 
1127
                        PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
 
1128
                        _("Error initialising SCSI device %s - %s"),
 
1129
                        dev->path, strerror (errno))
 
1130
                                != PED_EXCEPTION_IGNORE)
 
1131
                        goto error_close_dev;
 
1132
                if (!_device_probe_geometry (dev))
 
1133
                        goto error_close_dev;
 
1134
                ped_device_close (dev);
 
1135
                return 1;
 
1136
        }
 
1137
 
 
1138
        dev->host = idlun.host_unique_id;
 
1139
        dev->did  = idlun.dev_id;
 
1140
 
 
1141
        dev->model = (char*) ped_malloc (8 + 16 + 2);
 
1142
        if (!dev->model)
 
1143
                goto error_close_dev;
 
1144
 
 
1145
        if (scsi_get_product_info (dev, &vendor, &product)) {
 
1146
                sprintf (dev->model, "%.8s %.16s", vendor, product);
 
1147
                free (vendor);
 
1148
                free (product);
 
1149
        } else {
 
1150
                strcpy (dev->model, "Generic SCSI");
 
1151
        }
 
1152
 
 
1153
        if (!_device_probe_geometry (dev))
 
1154
                goto error_close_dev;
 
1155
 
 
1156
        ped_device_close (dev);
 
1157
        return 1;
 
1158
 
 
1159
error_close_dev:
 
1160
        ped_device_close (dev);
 
1161
error:
 
1162
        return 0;
 
1163
}
 
1164
 
 
1165
static int
 
1166
init_file (PedDevice* dev)
 
1167
{
 
1168
        struct stat     dev_stat;
 
1169
 
 
1170
        if (!_device_stat (dev, &dev_stat))
 
1171
                goto error;
 
1172
        if (!ped_device_open (dev))
 
1173
                goto error;
 
1174
 
 
1175
        dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
 
1176
        char *p = getenv ("PARTED_SECTOR_SIZE");
 
1177
        if (p) {
 
1178
                int s = atoi (p);
 
1179
                if (0 < s && s % 512 == 0)
 
1180
                        dev->sector_size = s;
 
1181
        }
 
1182
        dev->phys_sector_size = dev->sector_size;
 
1183
 
 
1184
        if (S_ISBLK(dev_stat.st_mode))
 
1185
                dev->length = _device_get_length (dev);
 
1186
        else
 
1187
                dev->length = dev_stat.st_size / dev->sector_size;
 
1188
        if (dev->length <= 0) {
 
1189
                ped_exception_throw (
 
1190
                        PED_EXCEPTION_ERROR,
 
1191
                        PED_EXCEPTION_CANCEL,
 
1192
                        _("The device %s is so small that it cannot possibly "
 
1193
                          "store a file system or partition table.  Perhaps "
 
1194
                          "you selected the wrong device?"),
 
1195
                        dev->path);
 
1196
                goto error_close_dev;
 
1197
        }
 
1198
 
 
1199
        ped_device_close (dev);
 
1200
 
 
1201
        dev->bios_geom.cylinders = dev->length / 4 / 32;
 
1202
        dev->bios_geom.heads = 4;
 
1203
        dev->bios_geom.sectors = 32;
 
1204
        dev->hw_geom = dev->bios_geom;
 
1205
        dev->model = strdup ("");
 
1206
 
 
1207
        return 1;
 
1208
 
 
1209
error_close_dev:
 
1210
        ped_device_close (dev);
 
1211
error:
 
1212
        return 0;
 
1213
}
 
1214
 
 
1215
#if defined __s390__ || defined __s390x__
 
1216
static int
 
1217
init_dasd (PedDevice* dev, const char* model_name)
 
1218
{
 
1219
        struct stat             dev_stat;
 
1220
        struct hd_geometry      geo;
 
1221
        dasd_information_t dasd_info;
 
1222
 
 
1223
        if (!_device_stat (dev, &dev_stat))
 
1224
                goto error;
 
1225
 
 
1226
        if (!ped_device_open (dev))
 
1227
                goto error;
 
1228
 
 
1229
        LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
 
1230
 
 
1231
        PED_ASSERT (S_ISBLK (dev_stat.st_mode));
 
1232
 
 
1233
        _device_set_sector_size (dev);
 
1234
        if (!dev->sector_size)
 
1235
                goto error_close_dev;
 
1236
 
 
1237
        dev->length = _device_get_length (dev);
 
1238
        if (!dev->length)
 
1239
                goto error_close_dev;
 
1240
 
 
1241
        if (!ioctl (arch_specific->fd, HDIO_GETGEO, &geo)) {
 
1242
                dev->hw_geom.sectors = geo.sectors;
 
1243
                dev->hw_geom.heads = geo.heads;
 
1244
                dev->hw_geom.cylinders = dev->length
 
1245
                        / (dev->hw_geom.heads * dev->hw_geom.sectors)
 
1246
                        / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
 
1247
                dev->bios_geom = dev->hw_geom;
 
1248
        } else {
 
1249
                dev->bios_geom.sectors = 12;
 
1250
                dev->bios_geom.heads = 15;
 
1251
                dev->bios_geom.cylinders = dev->length
 
1252
                        / (dev->hw_geom.heads * dev->hw_geom.sectors)
 
1253
                        / (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
 
1254
                dev->hw_geom = dev->bios_geom;
 
1255
        }
 
1256
 
 
1257
        if (!ioctl(arch_specific->fd, BIODASDINFO, &dasd_info)) {
 
1258
                arch_specific->devno = dasd_info.devno;
 
1259
        } else {
 
1260
                arch_specific->devno = arch_specific->major * 256 +
 
1261
                                       arch_specific->minor;
 
1262
        }
 
1263
 
 
1264
        dev->model = strdup (model_name);
 
1265
 
 
1266
        ped_device_close (dev);
 
1267
        return 1;
 
1268
 
 
1269
error_close_dev:
 
1270
        ped_device_close (dev);
 
1271
error:
 
1272
        return 0;
 
1273
}
 
1274
#endif
 
1275
 
 
1276
static int
 
1277
init_generic (PedDevice* dev, const char* model_name)
 
1278
{
 
1279
        struct stat             dev_stat;
 
1280
        PedExceptionOption      ex_status;
 
1281
 
 
1282
        if (!_device_stat (dev, &dev_stat))
 
1283
                goto error;
 
1284
 
 
1285
        if (!ped_device_open (dev))
 
1286
                goto error;
 
1287
 
 
1288
        ped_exception_fetch_all ();
 
1289
        if (_device_probe_geometry (dev)) {
 
1290
                ped_exception_leave_all ();
 
1291
        } else {
 
1292
                if (!_device_get_length (dev)) {
 
1293
                        ped_exception_catch ();
 
1294
                        ped_exception_leave_all ();
 
1295
                        goto error_close_dev;
 
1296
                }
 
1297
 
 
1298
                /* hack to allow use of files, for testing */
 
1299
                ped_exception_catch ();
 
1300
                ped_exception_leave_all ();
 
1301
 
 
1302
                ex_status = ped_exception_throw (
 
1303
                                PED_EXCEPTION_WARNING,
 
1304
                                PED_EXCEPTION_IGNORE_CANCEL,
 
1305
                                _("Unable to determine geometry of "
 
1306
                                "file/device %s.  You should not use Parted "
 
1307
                                "unless you REALLY know what you're doing!"),
 
1308
                                dev->path);
 
1309
                switch (ex_status) {
 
1310
                        case PED_EXCEPTION_CANCEL:
 
1311
                                goto error_close_dev;
 
1312
 
 
1313
                        case PED_EXCEPTION_UNHANDLED:
 
1314
                                ped_exception_catch ();
 
1315
                        case PED_EXCEPTION_IGNORE:
 
1316
                                break;
 
1317
                        default:
 
1318
                                PED_ASSERT (0);
 
1319
                                break;
 
1320
                }
 
1321
 
 
1322
                /* what should we stick in here? */
 
1323
                dev->length = dev_stat.st_size / PED_SECTOR_SIZE_DEFAULT;
 
1324
                dev->bios_geom.cylinders = dev->length / 4 / 32;
 
1325
                dev->bios_geom.heads = 4;
 
1326
                dev->bios_geom.sectors = 32;
 
1327
                dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
 
1328
                dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
 
1329
        }
 
1330
 
 
1331
        dev->model = strdup (model_name);
 
1332
 
 
1333
        ped_device_close (dev);
 
1334
        return 1;
 
1335
 
 
1336
error_close_dev:
 
1337
        ped_device_close (dev);
 
1338
error:
 
1339
        return 0;
 
1340
}
 
1341
 
 
1342
static int
 
1343
sdmmc_get_product_info (PedDevice* dev, char **type, char **name)
 
1344
{
 
1345
        *type = read_device_sysfs_file (dev, "type");
 
1346
        *name = read_device_sysfs_file (dev, "name");
 
1347
        if (*type && *name)
 
1348
                return 1;
 
1349
 
 
1350
        return 0;
 
1351
}
 
1352
 
 
1353
static int
 
1354
init_sdmmc (PedDevice* dev)
 
1355
{
 
1356
        char id[128];
 
1357
        char *type, *name;
 
1358
 
 
1359
        if (sdmmc_get_product_info (dev, &type, &name)) {
 
1360
                snprintf (id, sizeof(id) - 1, "%s %s", type, name);
 
1361
                free (type);
 
1362
                free (name);
 
1363
        } else {
 
1364
                snprintf (id, sizeof(id) - 1, "%s",
 
1365
                          _("Generic SD/MMC Storage Card"));
 
1366
        }
 
1367
        return init_generic(dev, id);
 
1368
}
 
1369
 
 
1370
static PedDevice*
 
1371
linux_new (const char* path)
 
1372
{
 
1373
        PedDevice*      dev;
 
1374
        LinuxSpecific*  arch_specific;
 
1375
 
 
1376
        PED_ASSERT (path != NULL);
 
1377
 
 
1378
        dev = (PedDevice*) ped_malloc (sizeof (PedDevice));
 
1379
        if (!dev)
 
1380
                goto error;
 
1381
 
 
1382
        dev->path = strdup (path);
 
1383
        if (!dev->path)
 
1384
                goto error_free_dev;
 
1385
 
 
1386
        dev->arch_specific
 
1387
                = (LinuxSpecific*) ped_malloc (sizeof (LinuxSpecific));
 
1388
        if (!dev->arch_specific)
 
1389
                goto error_free_path;
 
1390
        arch_specific = LINUX_SPECIFIC (dev);
 
1391
        arch_specific->dmtype = NULL;
 
1392
#if USE_BLKID
 
1393
        arch_specific->probe = NULL;
 
1394
        arch_specific->topology = NULL;
 
1395
#endif
 
1396
 
 
1397
        dev->open_count = 0;
 
1398
        dev->read_only = 0;
 
1399
        dev->external_mode = 0;
 
1400
        dev->dirty = 0;
 
1401
        dev->boot_dirty = 0;
 
1402
 
 
1403
#ifdef ENABLE_DEVICE_MAPPER
 
1404
        dm_udev_set_sync_support(1);
 
1405
#endif
 
1406
 
 
1407
        if (!_device_probe_type (dev))
 
1408
                goto error_free_arch_specific;
 
1409
 
 
1410
        switch (dev->type) {
 
1411
        case PED_DEVICE_IDE:
 
1412
                if (!init_ide (dev))
 
1413
                        goto error_free_arch_specific;
 
1414
                break;
 
1415
 
 
1416
        case PED_DEVICE_SCSI:
 
1417
                if (!init_scsi (dev))
 
1418
                        goto error_free_arch_specific;
 
1419
                break;
 
1420
 
 
1421
        case PED_DEVICE_DAC960:
 
1422
                if (!init_generic (dev, _("DAC960 RAID controller")))
 
1423
                        goto error_free_arch_specific;
 
1424
                break;
 
1425
 
 
1426
        case PED_DEVICE_SX8:
 
1427
                if (!init_generic (dev, _("Promise SX8 SATA Device")))
 
1428
                        goto error_free_arch_specific;
 
1429
                break;
 
1430
 
 
1431
        case PED_DEVICE_AOE:
 
1432
                if (!init_generic (dev, _("ATA over Ethernet Device")))
 
1433
                    goto error_free_arch_specific;
 
1434
                break;
 
1435
 
 
1436
#if defined __s390__ || defined __s390x__
 
1437
        case PED_DEVICE_DASD:
 
1438
                if (!init_dasd (dev, _("IBM S390 DASD drive")))
 
1439
                        goto error_free_arch_specific;
 
1440
                break;
 
1441
#endif
 
1442
 
 
1443
        case PED_DEVICE_VIODASD:
 
1444
                if (!init_generic (dev, _("IBM iSeries Virtual DASD")))
 
1445
                        goto error_free_arch_specific;
 
1446
                break;
 
1447
 
 
1448
        case PED_DEVICE_CPQARRAY:
 
1449
                if (!init_generic (dev, _("Compaq Smart Array")))
 
1450
                        goto error_free_arch_specific;
 
1451
                break;
 
1452
 
 
1453
        case PED_DEVICE_ATARAID:
 
1454
                if (!init_generic (dev, _("ATARAID Controller")))
 
1455
                        goto error_free_arch_specific;
 
1456
                break;
 
1457
 
 
1458
        case PED_DEVICE_I2O:
 
1459
                if (!init_generic (dev, _("I2O Controller")))
 
1460
                        goto error_free_arch_specific;
 
1461
                break;
 
1462
 
 
1463
        case PED_DEVICE_UBD:
 
1464
                if (!init_generic (dev, _("User-Mode Linux UBD")))
 
1465
                        goto error_free_arch_specific;
 
1466
                break;
 
1467
 
 
1468
        case PED_DEVICE_FILE:
 
1469
                if (!init_file (dev))
 
1470
                        goto error_free_arch_specific;
 
1471
                break;
 
1472
 
 
1473
        case PED_DEVICE_LOOP:
 
1474
                if (!init_generic (dev, _("Loopback device")))
 
1475
                        goto error_free_arch_specific;
 
1476
                break;
 
1477
 
 
1478
        case PED_DEVICE_DM:
 
1479
                {
 
1480
                  char* type;
 
1481
                  if (arch_specific->dmtype == NULL
 
1482
                      || asprintf(&type, _("Linux device-mapper (%s)"),
 
1483
                                  arch_specific->dmtype) == -1)
 
1484
                        goto error_free_arch_specific;
 
1485
                  bool ok = init_generic (dev, type);
 
1486
                  free (type);
 
1487
                  if (!ok)
 
1488
                    goto error_free_arch_specific;
 
1489
                  break;
 
1490
                }
 
1491
 
 
1492
        case PED_DEVICE_XVD:
 
1493
                if (!init_generic (dev, _("Xen Virtual Block Device")))
 
1494
                        goto error_free_arch_specific;
 
1495
                break;
 
1496
 
 
1497
        case PED_DEVICE_UNKNOWN:
 
1498
                if (!init_generic (dev, _("Unknown")))
 
1499
                        goto error_free_arch_specific;
 
1500
                break;
 
1501
 
 
1502
        case PED_DEVICE_SDMMC:
 
1503
                if (!init_sdmmc (dev))
 
1504
                        goto error_free_arch_specific;
 
1505
                break;
 
1506
        case PED_DEVICE_VIRTBLK:
 
1507
                if (!init_generic(dev, _("Virtio Block Device")))
 
1508
                        goto error_free_arch_specific;
 
1509
                break;
 
1510
 
 
1511
        case PED_DEVICE_MD:
 
1512
                if (!init_generic(dev, _("Linux Software RAID Array")))
 
1513
                        goto error_free_arch_specific;
 
1514
                break;
 
1515
 
 
1516
        default:
 
1517
                ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
 
1518
                                PED_EXCEPTION_CANCEL,
 
1519
                                _("ped_device_new()  Unsupported device type"));
 
1520
                goto error_free_arch_specific;
 
1521
        }
 
1522
        return dev;
 
1523
 
 
1524
error_free_arch_specific:
 
1525
        free (dev->arch_specific);
 
1526
error_free_path:
 
1527
        free (dev->path);
 
1528
error_free_dev:
 
1529
        free (dev);
 
1530
error:
 
1531
        return NULL;
 
1532
}
 
1533
 
 
1534
static void
 
1535
linux_destroy (PedDevice* dev)
 
1536
{
 
1537
        LinuxSpecific *arch_specific = LINUX_SPECIFIC(dev);
 
1538
        void *p = arch_specific->dmtype;
 
1539
 
 
1540
#if USE_BLKID
 
1541
        if (arch_specific->probe)
 
1542
                blkid_free_probe(arch_specific->probe);
 
1543
#endif
 
1544
        free (p);
 
1545
        free (dev->arch_specific);
 
1546
        free (dev->path);
 
1547
        free (dev->model);
 
1548
        free (dev);
 
1549
}
 
1550
 
 
1551
static int
 
1552
linux_is_busy (PedDevice* dev)
 
1553
{
 
1554
        int     i;
 
1555
        char*   part_name;
 
1556
 
 
1557
        if (_partition_is_mounted_by_path (dev->path))
 
1558
                return 1;
 
1559
 
 
1560
        for (i = 0; i < 32; i++) {
 
1561
                int status;
 
1562
 
 
1563
                part_name = _device_get_part_path (dev, i);
 
1564
                if (!part_name)
 
1565
                        return 1;
 
1566
                status = _partition_is_mounted_by_path (part_name);
 
1567
                free (part_name);
 
1568
 
 
1569
                if (status)
 
1570
                        return 1;
 
1571
        }
 
1572
 
 
1573
        return 0;
 
1574
}
 
1575
 
 
1576
/* we need to flush the master device, and all the partition devices,
 
1577
 * because there is no coherency between the caches.
 
1578
 * We should only flush unmounted partition devices, because:
 
1579
 *  - there is never a need to flush them (we're not doing IO there)
 
1580
 *  - flushing a device that is mounted causes unnecessary IO, and can
 
1581
 * even screw journaling & friends up.  Even cause oopsen!
 
1582
 */
 
1583
static void
 
1584
_flush_cache (PedDevice* dev)
 
1585
{
 
1586
        LinuxSpecific*  arch_specific = LINUX_SPECIFIC (dev);
 
1587
        int             i;
 
1588
        int             lpn = _device_get_partition_range(dev);
 
1589
 
 
1590
        if (dev->read_only)
 
1591
                return;
 
1592
        dev->dirty = 0;
 
1593
 
 
1594
        ioctl (arch_specific->fd, BLKFLSBUF);
 
1595
 
 
1596
        for (i = 1; i < lpn; i++) {
 
1597
                char*           name;
 
1598
                int             fd;
 
1599
 
 
1600
                name = _device_get_part_path (dev, i);
 
1601
                if (!name)
 
1602
                        break;
 
1603
                if (!_partition_is_mounted_by_path (name)) {
 
1604
                        fd = open (name, WR_MODE, 0);
 
1605
                        if (fd > 0) {
 
1606
                                ioctl (fd, BLKFLSBUF);
 
1607
retry:
 
1608
                                if (fsync (fd) < 0 || close (fd) < 0)
 
1609
                                        if (ped_exception_throw (
 
1610
                                                PED_EXCEPTION_WARNING,
 
1611
                                                PED_EXCEPTION_RETRY +
 
1612
                                                        PED_EXCEPTION_IGNORE,
 
1613
                                                _("Error fsyncing/closing %s: %s"),
 
1614
                                                name, strerror (errno))
 
1615
                                                        == PED_EXCEPTION_RETRY)
 
1616
                                                goto retry;
 
1617
                        }
 
1618
                }
 
1619
                free (name);
 
1620
        }
 
1621
}
 
1622
 
 
1623
static int
 
1624
linux_open (PedDevice* dev)
 
1625
{
 
1626
        LinuxSpecific*  arch_specific = LINUX_SPECIFIC (dev);
 
1627
 
 
1628
retry:
 
1629
        arch_specific->fd = open (dev->path, RW_MODE);
 
1630
 
 
1631
        if (arch_specific->fd == -1) {
 
1632
                char*   rw_error_msg = strerror (errno);
 
1633
 
 
1634
                arch_specific->fd = open (dev->path, RD_MODE);
 
1635
 
 
1636
                if (arch_specific->fd == -1) {
 
1637
                        if (ped_exception_throw (
 
1638
                                PED_EXCEPTION_ERROR,
 
1639
                                PED_EXCEPTION_RETRY_CANCEL,
 
1640
                                _("Error opening %s: %s"),
 
1641
                                dev->path, strerror (errno))
 
1642
                                        != PED_EXCEPTION_RETRY) {
 
1643
                                return 0;
 
1644
                        } else {
 
1645
                                goto retry;
 
1646
                        }
 
1647
                } else {
 
1648
                        ped_exception_throw (
 
1649
                                PED_EXCEPTION_WARNING,
 
1650
                                PED_EXCEPTION_OK,
 
1651
                                _("Unable to open %s read-write (%s).  %s has "
 
1652
                                  "been opened read-only."),
 
1653
                                dev->path, rw_error_msg, dev->path);
 
1654
                        dev->read_only = 1;
 
1655
                }
 
1656
        } else {
 
1657
                dev->read_only = 0;
 
1658
        }
 
1659
 
 
1660
        _flush_cache (dev);
 
1661
 
 
1662
        return 1;
 
1663
}
 
1664
 
 
1665
static int
 
1666
linux_refresh_open (PedDevice* dev)
 
1667
{
 
1668
        return 1;
 
1669
}
 
1670
 
 
1671
static int
 
1672
linux_close (PedDevice* dev)
 
1673
{
 
1674
        LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
 
1675
 
 
1676
        if (dev->dirty)
 
1677
                _flush_cache (dev);
 
1678
retry:
 
1679
        if (fsync (arch_specific->fd) < 0 || close (arch_specific->fd) < 0)
 
1680
                if (ped_exception_throw (
 
1681
                        PED_EXCEPTION_WARNING,
 
1682
                        PED_EXCEPTION_RETRY + PED_EXCEPTION_IGNORE,
 
1683
                        _("Error fsyncing/closing %s: %s"),
 
1684
                        dev->path, strerror (errno))
 
1685
                                == PED_EXCEPTION_RETRY)
 
1686
                        goto retry;
 
1687
        return 1;
 
1688
}
 
1689
 
 
1690
static int
 
1691
linux_refresh_close (PedDevice* dev)
 
1692
{
 
1693
        if (dev->dirty)
 
1694
                _flush_cache (dev);
 
1695
        return 1;
 
1696
}
 
1697
 
 
1698
#if SIZEOF_OFF_T < 8
 
1699
 
 
1700
static _syscall5(int,_llseek,
 
1701
                 unsigned int, fd,
 
1702
                 unsigned long, offset_high,
 
1703
                 unsigned long, offset_low,
 
1704
                 loff_t*, result,
 
1705
                 unsigned int, origin)
 
1706
 
 
1707
loff_t
 
1708
llseek (unsigned int fd, loff_t offset, unsigned int whence)
 
1709
{
 
1710
        loff_t result;
 
1711
        int retval;
 
1712
 
 
1713
        retval = _llseek(fd,
 
1714
                         ((unsigned long long)offset) >> 32,
 
1715
                         ((unsigned long long)offset) & 0xffffffff,
 
1716
                         &result,
 
1717
                         whence);
 
1718
        return (retval==-1 ? (loff_t) retval : result);
 
1719
}
 
1720
 
 
1721
#endif /* SIZEOF_OFF_T < 8 */
 
1722
 
 
1723
static int
 
1724
_device_seek (const PedDevice* dev, PedSector sector)
 
1725
{
 
1726
        LinuxSpecific*  arch_specific;
 
1727
 
 
1728
        PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
 
1729
        PED_ASSERT (dev != NULL);
 
1730
        PED_ASSERT (!dev->external_mode);
 
1731
 
 
1732
        arch_specific = LINUX_SPECIFIC (dev);
 
1733
 
 
1734
#if SIZEOF_OFF_T < 8
 
1735
        if (sizeof (off_t) < 8) {
 
1736
                loff_t  pos = (loff_t)(sector * dev->sector_size);
 
1737
                return llseek (arch_specific->fd, pos, SEEK_SET) == pos;
 
1738
        } else
 
1739
#endif
 
1740
        {
 
1741
                off_t   pos = sector * dev->sector_size;
 
1742
                return lseek (arch_specific->fd, pos, SEEK_SET) == pos;
 
1743
        }
 
1744
}
 
1745
 
 
1746
static int
 
1747
_read_lastoddsector (const PedDevice* dev, void* buffer)
 
1748
{
 
1749
        LinuxSpecific*                  arch_specific;
 
1750
        struct blkdev_ioctl_param       ioctl_param;
 
1751
 
 
1752
        PED_ASSERT(dev != NULL);
 
1753
        PED_ASSERT(buffer != NULL);
 
1754
 
 
1755
        arch_specific = LINUX_SPECIFIC (dev);
 
1756
 
 
1757
retry:
 
1758
        ioctl_param.block = 0; /* read the last sector */
 
1759
        ioctl_param.content_length = dev->sector_size;
 
1760
        ioctl_param.block_contents = buffer;
 
1761
 
 
1762
        if (ioctl(arch_specific->fd, BLKGETLASTSECT, &ioctl_param) == -1) {
 
1763
                PedExceptionOption      opt;
 
1764
                opt = ped_exception_throw (
 
1765
                        PED_EXCEPTION_ERROR,
 
1766
                        PED_EXCEPTION_RETRY_IGNORE_CANCEL,
 
1767
                        _("%s during read on %s"),
 
1768
                        strerror (errno), dev->path);
 
1769
 
 
1770
                if (opt == PED_EXCEPTION_CANCEL)
 
1771
                        return 0;
 
1772
                if (opt == PED_EXCEPTION_RETRY)
 
1773
                        goto retry;
 
1774
        }
 
1775
 
 
1776
        return 1;
 
1777
}
 
1778
 
 
1779
static int
 
1780
linux_read (const PedDevice* dev, void* buffer, PedSector start,
 
1781
            PedSector count)
 
1782
{
 
1783
        LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
 
1784
        PedExceptionOption      ex_status;
 
1785
        void*                   diobuf = NULL;
 
1786
 
 
1787
        PED_ASSERT (dev != NULL);
 
1788
        PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
 
1789
 
 
1790
        if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
 
1791
                /* Kludge.  This is necessary to read/write the last
 
1792
                   block of an odd-sized disk, until Linux 2.5.x kernel fixes.
 
1793
                */
 
1794
                if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
 
1795
                    && start + count - 1 == dev->length - 1)
 
1796
                        return ped_device_read (dev, buffer, start, count - 1)
 
1797
                                && _read_lastoddsector (
 
1798
                                        dev, (char *) buffer + (count-1) * 512);
 
1799
        }
 
1800
        while (1) {
 
1801
                if (_device_seek (dev, start))
 
1802
                        break;
 
1803
 
 
1804
                ex_status = ped_exception_throw (
 
1805
                        PED_EXCEPTION_ERROR,
 
1806
                        PED_EXCEPTION_RETRY_IGNORE_CANCEL,
 
1807
                        _("%s during seek for read on %s"),
 
1808
                        strerror (errno), dev->path);
 
1809
 
 
1810
                switch (ex_status) {
 
1811
                        case PED_EXCEPTION_IGNORE:
 
1812
                                return 1;
 
1813
 
 
1814
                        case PED_EXCEPTION_RETRY:
 
1815
                                break;
 
1816
 
 
1817
                        case PED_EXCEPTION_UNHANDLED:
 
1818
                                ped_exception_catch ();
 
1819
                        case PED_EXCEPTION_CANCEL:
 
1820
                                return 0;
 
1821
                        default:
 
1822
                                PED_ASSERT (0);
 
1823
                                break;
 
1824
                }
 
1825
        }
 
1826
 
 
1827
        size_t read_length = count * dev->sector_size;
 
1828
        if (posix_memalign (&diobuf, dev->sector_size, read_length) != 0)
 
1829
                return 0;
 
1830
 
 
1831
        while (1) {
 
1832
                ssize_t status = read (arch_specific->fd, diobuf, read_length);
 
1833
                if (status > 0)
 
1834
                        memcpy(buffer, diobuf, status);
 
1835
                if (status == (ssize_t) read_length)
 
1836
                        break;
 
1837
                if (status > 0) {
 
1838
                        read_length -= status;
 
1839
                        buffer = (char *) buffer + status;
 
1840
                        continue;
 
1841
                }
 
1842
 
 
1843
                ex_status = ped_exception_throw (
 
1844
                        PED_EXCEPTION_ERROR,
 
1845
                        PED_EXCEPTION_RETRY_IGNORE_CANCEL,
 
1846
                        (status == 0
 
1847
                         ? _("%0.0send of file while reading %s")
 
1848
                         : _("%s during read on %s")),
 
1849
                        strerror (errno),
 
1850
                        dev->path);
 
1851
 
 
1852
                switch (ex_status) {
 
1853
                        case PED_EXCEPTION_IGNORE:
 
1854
                                free(diobuf);
 
1855
                                return 1;
 
1856
 
 
1857
                        case PED_EXCEPTION_RETRY:
 
1858
                                break;
 
1859
 
 
1860
                        case PED_EXCEPTION_UNHANDLED:
 
1861
                                ped_exception_catch ();
 
1862
                        case PED_EXCEPTION_CANCEL:
 
1863
                                free(diobuf);
 
1864
                                return 0;
 
1865
                        default:
 
1866
                                PED_ASSERT (0);
 
1867
                                break;
 
1868
                }
 
1869
        }
 
1870
 
 
1871
        free (diobuf);
 
1872
 
 
1873
        return 1;
 
1874
}
 
1875
 
 
1876
static int
 
1877
_write_lastoddsector (PedDevice* dev, const void* buffer)
 
1878
{
 
1879
        LinuxSpecific*                  arch_specific;
 
1880
        struct blkdev_ioctl_param       ioctl_param;
 
1881
 
 
1882
        PED_ASSERT(dev != NULL);
 
1883
        PED_ASSERT(buffer != NULL);
 
1884
 
 
1885
        arch_specific = LINUX_SPECIFIC (dev);
 
1886
 
 
1887
retry:
 
1888
        ioctl_param.block = 0; /* write the last sector */
 
1889
        ioctl_param.content_length = dev->sector_size;
 
1890
        ioctl_param.block_contents = (void*) buffer;
 
1891
 
 
1892
        if (ioctl(arch_specific->fd, BLKSETLASTSECT, &ioctl_param) == -1) {
 
1893
                PedExceptionOption      opt;
 
1894
                opt = ped_exception_throw (
 
1895
                        PED_EXCEPTION_ERROR,
 
1896
                        PED_EXCEPTION_RETRY_IGNORE_CANCEL,
 
1897
                        _("%s during write on %s"),
 
1898
                        strerror (errno), dev->path);
 
1899
 
 
1900
                if (opt == PED_EXCEPTION_CANCEL)
 
1901
                        return 0;
 
1902
                if (opt == PED_EXCEPTION_RETRY)
 
1903
                        goto retry;
 
1904
        }
 
1905
 
 
1906
        return 1;
 
1907
}
 
1908
 
 
1909
static int
 
1910
linux_write (PedDevice* dev, const void* buffer, PedSector start,
 
1911
             PedSector count)
 
1912
{
 
1913
        LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
 
1914
        PedExceptionOption      ex_status;
 
1915
        void*                   diobuf;
 
1916
        void*                   diobuf_start;
 
1917
 
 
1918
        PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
 
1919
 
 
1920
        if (dev->read_only) {
 
1921
                if (ped_exception_throw (
 
1922
                        PED_EXCEPTION_ERROR,
 
1923
                        PED_EXCEPTION_IGNORE_CANCEL,
 
1924
                        _("Can't write to %s, because it is opened read-only."),
 
1925
                        dev->path)
 
1926
                                != PED_EXCEPTION_IGNORE)
 
1927
                        return 0;
 
1928
                else
 
1929
                        return 1;
 
1930
        }
 
1931
 
 
1932
        if (_get_linux_version() < KERNEL_VERSION (2,6,0)) {
 
1933
                /* Kludge.  This is necessary to read/write the last
 
1934
                   block of an odd-sized disk, until Linux 2.5.x kernel fixes.
 
1935
                */
 
1936
                if (dev->type != PED_DEVICE_FILE && (dev->length & 1)
 
1937
                    && start + count - 1 == dev->length - 1)
 
1938
                        return ped_device_write (dev, buffer, start, count - 1)
 
1939
                                && _write_lastoddsector (
 
1940
                                        dev, ((char*) buffer
 
1941
                                              + (count-1) * dev->sector_size));
 
1942
        }
 
1943
        while (1) {
 
1944
                if (_device_seek (dev, start))
 
1945
                        break;
 
1946
 
 
1947
                ex_status = ped_exception_throw (
 
1948
                        PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_IGNORE_CANCEL,
 
1949
                        _("%s during seek for write on %s"),
 
1950
                        strerror (errno), dev->path);
 
1951
 
 
1952
                switch (ex_status) {
 
1953
                        case PED_EXCEPTION_IGNORE:
 
1954
                                return 1;
 
1955
 
 
1956
                        case PED_EXCEPTION_RETRY:
 
1957
                                break;
 
1958
 
 
1959
                        case PED_EXCEPTION_UNHANDLED:
 
1960
                                ped_exception_catch ();
 
1961
                        case PED_EXCEPTION_CANCEL:
 
1962
                                return 0;
 
1963
                        default:
 
1964
                                PED_ASSERT (0);
 
1965
                                break;
 
1966
                }
 
1967
        }
 
1968
 
 
1969
#ifdef READ_ONLY
 
1970
        printf ("ped_device_write (\"%s\", %p, %d, %d)\n",
 
1971
                dev->path, buffer, (int) start, (int) count);
 
1972
#else
 
1973
        size_t write_length = count * dev->sector_size;
 
1974
        dev->dirty = 1;
 
1975
        if (posix_memalign(&diobuf, dev->sector_size, write_length) != 0)
 
1976
                return 0;
 
1977
        memcpy(diobuf, buffer, write_length);
 
1978
        diobuf_start = diobuf;
 
1979
        while (1) {
 
1980
                ssize_t status = write (arch_specific->fd, diobuf, write_length);
 
1981
                if (status == write_length) break;
 
1982
                if (status > 0) {
 
1983
                        write_length -= status;
 
1984
                        diobuf = (char *) diobuf + status;
 
1985
                        continue;
 
1986
                }
 
1987
 
 
1988
                ex_status = ped_exception_throw (
 
1989
                        PED_EXCEPTION_ERROR,
 
1990
                        PED_EXCEPTION_RETRY_IGNORE_CANCEL,
 
1991
                        _("%s during write on %s"),
 
1992
                        strerror (errno), dev->path);
 
1993
 
 
1994
                switch (ex_status) {
 
1995
                        case PED_EXCEPTION_IGNORE:
 
1996
                                free(diobuf_start);
 
1997
                                return 1;
 
1998
 
 
1999
                        case PED_EXCEPTION_RETRY:
 
2000
                                break;
 
2001
 
 
2002
                        case PED_EXCEPTION_UNHANDLED:
 
2003
                                ped_exception_catch ();
 
2004
                        case PED_EXCEPTION_CANCEL:
 
2005
                                free(diobuf_start);
 
2006
                                return 0;
 
2007
                        default:
 
2008
                                PED_ASSERT (0);
 
2009
                                break;
 
2010
                }
 
2011
        }
 
2012
        free(diobuf_start);
 
2013
#endif /* !READ_ONLY */
 
2014
        return 1;
 
2015
}
 
2016
 
 
2017
/* returns the number of sectors that are ok.
 
2018
 */
 
2019
static PedSector
 
2020
linux_check (PedDevice* dev, void* buffer, PedSector start, PedSector count)
 
2021
{
 
2022
        LinuxSpecific*  arch_specific = LINUX_SPECIFIC (dev);
 
2023
        PedSector       done = 0;
 
2024
        int             status;
 
2025
        void*           diobuf;
 
2026
 
 
2027
        PED_ASSERT(dev != NULL);
 
2028
 
 
2029
        if (!_device_seek (dev, start))
 
2030
                return 0;
 
2031
 
 
2032
        if (posix_memalign(&diobuf, PED_SECTOR_SIZE_DEFAULT,
 
2033
                           count * PED_SECTOR_SIZE_DEFAULT) != 0)
 
2034
                return 0;
 
2035
 
 
2036
        for (done = 0; done < count; done += status / dev->sector_size) {
 
2037
                status = read (arch_specific->fd, diobuf,
 
2038
                               (size_t) ((count-done) * dev->sector_size));
 
2039
                if (status > 0)
 
2040
                        memcpy(buffer, diobuf, status);
 
2041
                if (status < 0)
 
2042
                        break;
 
2043
        }
 
2044
        free(diobuf);
 
2045
 
 
2046
        return done;
 
2047
}
 
2048
 
 
2049
static int
 
2050
_do_fsync (PedDevice* dev)
 
2051
{
 
2052
        LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
 
2053
        int                     status;
 
2054
        PedExceptionOption      ex_status;
 
2055
 
 
2056
        while (1) {
 
2057
                status = fsync (arch_specific->fd);
 
2058
                if (status >= 0) break;
 
2059
 
 
2060
                ex_status = ped_exception_throw (
 
2061
                        PED_EXCEPTION_ERROR,
 
2062
                        PED_EXCEPTION_RETRY_IGNORE_CANCEL,
 
2063
                        _("%s during write on %s"),
 
2064
                        strerror (errno), dev->path);
 
2065
 
 
2066
                switch (ex_status) {
 
2067
                        case PED_EXCEPTION_IGNORE:
 
2068
                                return 1;
 
2069
 
 
2070
                        case PED_EXCEPTION_RETRY:
 
2071
                                break;
 
2072
 
 
2073
                        case PED_EXCEPTION_UNHANDLED:
 
2074
                                ped_exception_catch ();
 
2075
                        case PED_EXCEPTION_CANCEL:
 
2076
                                return 0;
 
2077
                        default:
 
2078
                                PED_ASSERT (0);
 
2079
                                break;
 
2080
                }
 
2081
        }
 
2082
        return 1;
 
2083
}
 
2084
 
 
2085
static int
 
2086
linux_sync (PedDevice* dev)
 
2087
{
 
2088
        PED_ASSERT (dev != NULL);
 
2089
        PED_ASSERT (!dev->external_mode);
 
2090
 
 
2091
        if (dev->read_only)
 
2092
                return 1;
 
2093
        if (!_do_fsync (dev))
 
2094
                return 0;
 
2095
        _flush_cache (dev);
 
2096
        return 1;
 
2097
}
 
2098
 
 
2099
static int
 
2100
linux_sync_fast (PedDevice* dev)
 
2101
{
 
2102
        PED_ASSERT (dev != NULL);
 
2103
        PED_ASSERT (!dev->external_mode);
 
2104
 
 
2105
        if (dev->read_only)
 
2106
                return 1;
 
2107
        if (!_do_fsync (dev))
 
2108
                return 0;
 
2109
        /* no cache flush... */
 
2110
        return 1;
 
2111
}
 
2112
 
 
2113
static inline int
 
2114
_compare_digit_state (char ch, int need_digit)
 
2115
{
 
2116
        return !!isdigit (ch) == need_digit;
 
2117
}
 
2118
 
 
2119
/* matches the regexp "[^0-9]+[0-9]+[^0-9]+[0-9]+$".
 
2120
 * Motivation: accept devices looking like /dev/rd/c0d0, but
 
2121
 * not looking like /dev/hda1 and /dev/rd/c0d0p1
 
2122
 */
 
2123
static int _GL_ATTRIBUTE_PURE
 
2124
_match_rd_device (const char* name)
 
2125
{
 
2126
        const char* pos;
 
2127
        int state;
 
2128
 
 
2129
        /* exclude directory names from test */
 
2130
        pos = strrchr(name, '/') ?: name;
 
2131
 
 
2132
        /* states:
 
2133
         *      0       non-digits
 
2134
         *      1       digits
 
2135
         *      2       non-digits
 
2136
         *      3       digits
 
2137
         */
 
2138
        for (state = 0; state < 4; state++) {
 
2139
                int want_digits = (state % 2 == 1);
 
2140
                do {
 
2141
                        if (!*pos)
 
2142
                                return 0;
 
2143
                        if (!_compare_digit_state (*pos, want_digits))
 
2144
                                return 0;
 
2145
                        pos++;
 
2146
                } while (_compare_digit_state (*pos, want_digits));
 
2147
        }
 
2148
 
 
2149
        return *pos == 0;
 
2150
}
 
2151
 
 
2152
static int
 
2153
_probe_proc_partitions ()
 
2154
{
 
2155
        FILE*           proc_part_file;
 
2156
        int             major, minor, size;
 
2157
        char            buf [512];
 
2158
        char            part_name [256];
 
2159
        char            dev_name [256];
 
2160
        int ok = 0;
 
2161
 
 
2162
        proc_part_file = fopen ("/proc/partitions", "r");
 
2163
        if (!proc_part_file)
 
2164
                return 0;
 
2165
 
 
2166
        if (fgets (buf, 256, proc_part_file) == NULL)
 
2167
                goto done;
 
2168
 
 
2169
        if (fgets (buf, 256, proc_part_file) == NULL)
 
2170
                goto done;
 
2171
 
 
2172
        while (fgets (buf, 512, proc_part_file)
 
2173
               && sscanf (buf, "%d %d %d %255s", &major, &minor, &size,
 
2174
                          part_name) == 4) {
 
2175
                /* Heuristic for telling partitions and devices apart
 
2176
                 * Probably needs to be improved
 
2177
                 */
 
2178
                if (!_match_rd_device (part_name)
 
2179
                    && isdigit (part_name [strlen (part_name) - 1]))
 
2180
                        continue;
 
2181
 
 
2182
                strcpy (dev_name, "/dev/");
 
2183
                strcat (dev_name, part_name);
 
2184
                _ped_device_probe (dev_name);
 
2185
        }
 
2186
 
 
2187
        ok = 1;
 
2188
 done:
 
2189
        fclose (proc_part_file);
 
2190
        return ok;
 
2191
}
 
2192
 
 
2193
struct _entry {
 
2194
        const char *name;
 
2195
        size_t len;
 
2196
};
 
2197
 
 
2198
static int _GL_ATTRIBUTE_PURE
 
2199
_skip_entry (const char *name)
 
2200
{
 
2201
        struct _entry *i;
 
2202
        static struct _entry entries[] = {
 
2203
                { ".",          sizeof (".") - 1        },
 
2204
                { "..",         sizeof ("..") - 1       },
 
2205
                { "dm-",        sizeof ("dm-") - 1      },
 
2206
                { "loop",       sizeof ("loop") - 1     },
 
2207
                { "ram",        sizeof ("ram") - 1      },
 
2208
                { "fd",         sizeof ("fd") - 1       },
 
2209
                { 0, 0 },
 
2210
        };
 
2211
 
 
2212
        for (i = entries; i->name != 0; i++) {
 
2213
                if (strncmp (name, i->name, i->len) == 0)
 
2214
                        return 1;
 
2215
        }
 
2216
 
 
2217
        return 0;
 
2218
}
 
2219
 
 
2220
static int
 
2221
_probe_sys_block ()
 
2222
{
 
2223
        DIR *blockdir;
 
2224
        struct dirent *dirent;
 
2225
        char dev_name [256];
 
2226
        char *ptr;
 
2227
 
 
2228
        if (!(blockdir = opendir ("/sys/block")))
 
2229
                return 0;
 
2230
        while ((dirent = readdir (blockdir))) {
 
2231
                if (_skip_entry (dirent->d_name))
 
2232
                        continue;
 
2233
 
 
2234
                if (strlen (dirent->d_name) > sizeof (dev_name) - 6)
 
2235
                        continue; /* device name too long! */
 
2236
 
 
2237
                strcpy (dev_name, "/dev/");
 
2238
                strcat (dev_name, dirent->d_name);
 
2239
                /* in /sys/block, '/'s are replaced with '!' or '.' */
 
2240
                for (ptr = dev_name; *ptr != '\0'; ptr++) {
 
2241
                        if (*ptr == '!' || *ptr == '.')
 
2242
                                *ptr = '/';
 
2243
                }
 
2244
                _ped_device_probe (dev_name);
 
2245
        }
 
2246
 
 
2247
        closedir (blockdir);
 
2248
        return 1;
 
2249
}
 
2250
 
 
2251
static int
 
2252
_probe_standard_devices ()
 
2253
{
 
2254
        _ped_device_probe ("/dev/hda");
 
2255
        _ped_device_probe ("/dev/hdb");
 
2256
        _ped_device_probe ("/dev/hdc");
 
2257
        _ped_device_probe ("/dev/hdd");
 
2258
        _ped_device_probe ("/dev/hde");
 
2259
        _ped_device_probe ("/dev/hdf");
 
2260
        _ped_device_probe ("/dev/hdg");
 
2261
        _ped_device_probe ("/dev/hdh");
 
2262
 
 
2263
        _ped_device_probe ("/dev/sda");
 
2264
        _ped_device_probe ("/dev/sdb");
 
2265
        _ped_device_probe ("/dev/sdc");
 
2266
        _ped_device_probe ("/dev/sdd");
 
2267
        _ped_device_probe ("/dev/sde");
 
2268
        _ped_device_probe ("/dev/sdf");
 
2269
 
 
2270
        return 1;
 
2271
}
 
2272
 
 
2273
static void
 
2274
linux_probe_all ()
 
2275
{
 
2276
        /* we should probe the standard devs too, even with /proc/partitions,
 
2277
         * because /proc/partitions might return devfs stuff, and we might not
 
2278
         * have devfs available
 
2279
         */
 
2280
        _probe_standard_devices ();
 
2281
 
 
2282
#ifdef ENABLE_DEVICE_MAPPER
 
2283
        /* device-mapper devices aren't listed in /proc/partitions; or, if
 
2284
         * they are, they're listed as dm-X.  So, instead of relying on that,
 
2285
         * we do our own checks.
 
2286
         */
 
2287
        _probe_dm_devices ();
 
2288
#endif
 
2289
 
 
2290
        /* /sys/block is more reliable and consistent; fall back to using
 
2291
         * /proc/partitions if the former is unavailable, however.
 
2292
         */
 
2293
        if (!_probe_sys_block ())
 
2294
                _probe_proc_partitions ();
 
2295
}
 
2296
 
 
2297
static char * _GL_ATTRIBUTE_FORMAT ((__printf__, 1, 2))
 
2298
zasprintf (const char *format, ...)
 
2299
{
 
2300
  va_list args;
 
2301
  char *resultp;
 
2302
  va_start (args, format);
 
2303
  int r = vasprintf (&resultp, format, args);
 
2304
  va_end (args);
 
2305
  return r < 0 ? NULL : resultp;
 
2306
}
 
2307
 
 
2308
static char *
 
2309
dm_canonical_path (PedDevice const *dev)
 
2310
{
 
2311
        LinuxSpecific const *arch_specific = LINUX_SPECIFIC (dev);
 
2312
 
 
2313
        /* Get map name from devicemapper */
 
2314
        struct dm_task *task = dm_task_create (DM_DEVICE_INFO);
 
2315
        if (!task)
 
2316
                goto err;
 
2317
        if (!dm_task_set_major_minor (task, arch_specific->major,
 
2318
                                      arch_specific->minor, 0))
 
2319
                goto err;
 
2320
        if (!dm_task_run(task))
 
2321
                goto err;
 
2322
        char *dev_name = zasprintf ("/dev/mapper/%s", dm_task_get_name (task));
 
2323
        if (dev_name == NULL)
 
2324
                goto err;
 
2325
        dm_task_destroy (task);
 
2326
        return dev_name;
 
2327
err:
 
2328
        return NULL;
 
2329
}
 
2330
 
 
2331
static char*
 
2332
_device_get_part_path (PedDevice const *dev, int num)
 
2333
{
 
2334
        char *devpath = (dev->type == PED_DEVICE_DM
 
2335
                         ? dm_canonical_path (dev) : dev->path);
 
2336
        size_t path_len = strlen (devpath);
 
2337
        char *result;
 
2338
        /* Check for devfs-style /disc => /partN transformation
 
2339
           unconditionally; the system might be using udev with devfs rules,
 
2340
           and if not the test is harmless. */
 
2341
        if (5 < path_len && !strcmp (devpath + path_len - 5, "/disc")) {
 
2342
                /* replace /disc with /part%d */
 
2343
                result = zasprintf ("%.*s/part%d",
 
2344
                                    (int) (path_len - 5), devpath, num);
 
2345
        } else {
 
2346
                char const *p = (dev->type == PED_DEVICE_DAC960
 
2347
                                 || dev->type == PED_DEVICE_CPQARRAY
 
2348
                                 || dev->type == PED_DEVICE_ATARAID
 
2349
                                 || isdigit (devpath[path_len - 1])
 
2350
                                 ? "p" : "");
 
2351
                result = zasprintf ("%s%s%d", devpath, p, num);
 
2352
        }
 
2353
        if (dev->type == PED_DEVICE_DM)
 
2354
                free (devpath);
 
2355
        return result;
 
2356
}
 
2357
 
 
2358
static char*
 
2359
linux_partition_get_path (const PedPartition* part)
 
2360
{
 
2361
        /* loop label means use the whole disk */
 
2362
        if (strcmp (part->disk->type->name, "loop") == 0)
 
2363
                return xstrdup (part->disk->dev->path);
 
2364
        return _device_get_part_path (part->disk->dev, part->num);
 
2365
}
 
2366
 
 
2367
static int
 
2368
_mount_table_search (const char* file_name, dev_t dev)
 
2369
{
 
2370
        struct stat part_stat;
 
2371
        char line[512];
 
2372
        char part_name[512];
 
2373
        FILE* file;
 
2374
 
 
2375
        file = fopen (file_name, "r");
 
2376
        if (!file)
 
2377
                return 0;
 
2378
        while (fgets (line, 512, file)) {
 
2379
                if (sscanf (line, "%s", part_name) == 1
 
2380
                    && stat (part_name, &part_stat) == 0) {
 
2381
                        if (part_stat.st_rdev == dev) {
 
2382
                                fclose (file);
 
2383
                                return 1;
 
2384
                        }
 
2385
                }
 
2386
        }
 
2387
        fclose (file);
 
2388
        return 0;
 
2389
}
 
2390
 
 
2391
static int
 
2392
_partition_is_mounted_by_dev (dev_t dev)
 
2393
{
 
2394
        return  _mount_table_search( "/proc/mounts", dev)
 
2395
                || _mount_table_search( "/proc/swaps", dev)
 
2396
                || _mount_table_search( "/etc/mtab", dev);
 
2397
}
 
2398
 
 
2399
static int
 
2400
_partition_is_mounted_by_path (const char *path)
 
2401
{
 
2402
        struct stat part_stat;
 
2403
        if (stat (path, &part_stat) != 0)
 
2404
                return 0;
 
2405
        if (!S_ISBLK(part_stat.st_mode))
 
2406
                return 0;
 
2407
        return _partition_is_mounted_by_dev (part_stat.st_rdev);
 
2408
}
 
2409
 
 
2410
/* If partition PART is mounted, or if we encounter an out-of-memory error
 
2411
   while trying to determine its status, return 1.  Otherwise, return 0.  */
 
2412
static int
 
2413
_partition_is_mounted (const PedPartition *part)
 
2414
{
 
2415
        if (!ped_partition_is_active (part))
 
2416
                return 0;
 
2417
        char *part_name = _device_get_part_path (part->disk->dev, part->num);
 
2418
        if (!part_name)
 
2419
                return 1;
 
2420
        int status = _partition_is_mounted_by_path (part_name);
 
2421
        free (part_name);
 
2422
        return !!status;
 
2423
}
 
2424
 
 
2425
static int
 
2426
linux_partition_is_busy (const PedPartition* part)
 
2427
{
 
2428
        PedPartition*   walk;
 
2429
 
 
2430
        PED_ASSERT (part != NULL);
 
2431
 
 
2432
        if (strcmp (part->disk->type->name, "loop") == 0)
 
2433
                return linux_is_busy (part->disk->dev);
 
2434
        if (_partition_is_mounted (part))
 
2435
                return 1;
 
2436
        if (part->type == PED_PARTITION_EXTENDED) {
 
2437
                for (walk = part->part_list; walk; walk = walk->next) {
 
2438
                        if (linux_partition_is_busy (walk))
 
2439
                                return 1;
 
2440
                }
 
2441
        }
 
2442
        return 0;
 
2443
}
 
2444
 
 
2445
static int
 
2446
_blkpg_part_command (PedDevice* dev, struct blkpg_partition* part, int op)
 
2447
{
 
2448
        LinuxSpecific*          arch_specific = LINUX_SPECIFIC (dev);
 
2449
        struct blkpg_ioctl_arg  ioctl_arg;
 
2450
 
 
2451
        ioctl_arg.op = op;
 
2452
        ioctl_arg.flags = 0;
 
2453
        ioctl_arg.datalen = sizeof (struct blkpg_partition);
 
2454
        ioctl_arg.data = (void*) part;
 
2455
 
 
2456
        return ioctl (arch_specific->fd, BLKPG, &ioctl_arg) == 0;
 
2457
}
 
2458
 
 
2459
static int
 
2460
_blkpg_add_partition (PedDisk* disk, const PedPartition *part)
 
2461
{
 
2462
        struct blkpg_partition  linux_part;
 
2463
        const char*             vol_name;
 
2464
        char*                   dev_name;
 
2465
 
 
2466
        PED_ASSERT(disk != NULL);
 
2467
        PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
 
2468
 
 
2469
        if (ped_disk_type_check_feature (disk->type,
 
2470
                                         PED_DISK_TYPE_PARTITION_NAME))
 
2471
                vol_name = ped_partition_get_name (part);
 
2472
        else
 
2473
                vol_name = NULL;
 
2474
 
 
2475
        dev_name = _device_get_part_path (disk->dev, part->num);
 
2476
        if (!dev_name)
 
2477
                return 0;
 
2478
 
 
2479
        memset (&linux_part, 0, sizeof (linux_part));
 
2480
        linux_part.start = part->geom.start * disk->dev->sector_size;
 
2481
        /* see fs/partitions/msdos.c:msdos_partition(): "leave room for LILO" */
 
2482
        if (part->type & PED_PARTITION_EXTENDED) {
 
2483
                linux_part.length = 1;
 
2484
                if (disk->dev->sector_size == 512) {
 
2485
                        if (linux_part.length == 1)
 
2486
                                linux_part.length = 2;
 
2487
                        PedPartition *walk;
 
2488
                        /* if the second sector is claimed by a logical partition,
 
2489
                           then there's just no room for lilo, so don't try to use it */
 
2490
                        for (walk = part->part_list; walk; walk = walk->next) {
 
2491
                                if (walk->geom.start == part->geom.start+1)
 
2492
                                        linux_part.length = 1;
 
2493
                        }
 
2494
                }
 
2495
                linux_part.length *= disk->dev->sector_size;
 
2496
        }
 
2497
        else {
 
2498
                linux_part.length = part->geom.length * disk->dev->sector_size;
 
2499
        }
 
2500
        linux_part.pno = part->num;
 
2501
        strncpy (linux_part.devname, dev_name, BLKPG_DEVNAMELTH);
 
2502
        if (vol_name)
 
2503
                strncpy (linux_part.volname, vol_name, BLKPG_VOLNAMELTH);
 
2504
 
 
2505
        free (dev_name);
 
2506
 
 
2507
        if (!_blkpg_part_command (disk->dev, &linux_part,
 
2508
                                  BLKPG_ADD_PARTITION)) {
 
2509
                return 0;
 
2510
        }
 
2511
 
 
2512
        return 1;
 
2513
}
 
2514
 
 
2515
static int
 
2516
_blkpg_remove_partition (PedDisk* disk, int n)
 
2517
{
 
2518
        struct blkpg_partition  linux_part;
 
2519
 
 
2520
        memset (&linux_part, 0, sizeof (linux_part));
 
2521
        linux_part.pno = n;
 
2522
        return _blkpg_part_command (disk->dev, &linux_part,
 
2523
                                    BLKPG_DEL_PARTITION);
 
2524
}
 
2525
 
 
2526
#ifdef BLKPG_RESIZE_PARTITION
 
2527
static int _blkpg_resize_partition (PedDisk* disk, const PedPartition *part)
 
2528
{
 
2529
        struct blkpg_partition  linux_part;
 
2530
        char*                   dev_name;
 
2531
 
 
2532
        PED_ASSERT(disk != NULL);
 
2533
        PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
 
2534
 
 
2535
        dev_name = _device_get_part_path (disk->dev, part->num);
 
2536
        if (!dev_name)
 
2537
                return 0;
 
2538
        memset (&linux_part, 0, sizeof (linux_part));
 
2539
        linux_part.start = part->geom.start * disk->dev->sector_size;
 
2540
        /* see fs/partitions/msdos.c:msdos_partition(): "leave room for LILO" */
 
2541
        if (part->type & PED_PARTITION_EXTENDED) {
 
2542
                if (disk->dev->sector_size == 512) {
 
2543
                        linux_part.length = 2;
 
2544
                        PedPartition *walk;
 
2545
                        /* if the second sector is claimed by a logical partition,
 
2546
                           then there's just no room for lilo, so don't try to use it */
 
2547
                        for (walk = part->part_list; walk; walk = walk->next) {
 
2548
                                if (walk->geom.start == part->geom.start+1)
 
2549
                                        linux_part.length = 1;
 
2550
                        }
 
2551
                } else linux_part.length = 1;
 
2552
        }
 
2553
        else
 
2554
                linux_part.length = part->geom.length * disk->dev->sector_size;
 
2555
        linux_part.pno = part->num;
 
2556
        strncpy (linux_part.devname, dev_name, BLKPG_DEVNAMELTH);
 
2557
 
 
2558
        free (dev_name);
 
2559
 
 
2560
        if (!_blkpg_part_command (disk->dev, &linux_part,
 
2561
                                  BLKPG_RESIZE_PARTITION)) {
 
2562
                return ped_exception_throw (
 
2563
                        PED_EXCEPTION_ERROR,
 
2564
                        PED_EXCEPTION_IGNORE_CANCEL,
 
2565
                        _("Error informing the kernel about modifications to "
 
2566
                          "partition %s -- %s.  This means Linux won't know "
 
2567
                          "about any changes you made to %s until you reboot "
 
2568
                          "-- so you shouldn't mount it or use it in any way "
 
2569
                          "before rebooting."),
 
2570
                        linux_part.devname,
 
2571
                        strerror (errno),
 
2572
                        linux_part.devname)
 
2573
                                == PED_EXCEPTION_IGNORE;
 
2574
        }
 
2575
 
 
2576
        return 1;
 
2577
}
 
2578
#endif
 
2579
 
 
2580
/* Read the integer from /sys/block/DEV_BASE/ENTRY and set *VAL
 
2581
   to that value, where DEV_BASE is the last component of DEV->path.
 
2582
   Upon success, return true.  Otherwise, return false. */
 
2583
static bool
 
2584
_sysfs_int_entry_from_dev(PedDevice const* dev, const char *entry, int *val)
 
2585
{
 
2586
        char        path[128];
 
2587
        int r = snprintf(path, sizeof(path), "/sys/block/%s/%s",
 
2588
                         last_component(dev->path), entry);
 
2589
        if (r < 0 || r >= sizeof(path))
 
2590
                return false;
 
2591
 
 
2592
        FILE *fp = fopen(path, "r");
 
2593
        if (!fp)
 
2594
                return false;
 
2595
 
 
2596
        bool ok = fscanf(fp, "%d", val) == 1;
 
2597
        fclose(fp);
 
2598
 
 
2599
        return ok;
 
2600
}
 
2601
 
 
2602
/* Read the unsigned long long from /sys/block/DEV_BASE/PART_BASE/ENTRY
 
2603
   and set *VAL to that value, where DEV_BASE is the last component of path to
 
2604
   block device corresponding to PART and PART_BASE is the sysfs name of PART.
 
2605
   Upon success, return true. Otherwise, return false. */
 
2606
static bool
 
2607
_sysfs_ull_entry_from_part(PedPartition const* part, const char *entry,
 
2608
                           unsigned long long *val)
 
2609
{
 
2610
        char path[128];
 
2611
        char *part_name = _device_get_part_path (part->disk->dev, part->num);
 
2612
        if (!part_name)
 
2613
                return false;
 
2614
 
 
2615
        int r = snprintf(path, sizeof(path), "/sys/block/%s/%s/%s",
 
2616
                last_component(part->disk->dev->path),
 
2617
                last_component(part_name), entry);
 
2618
        free(part_name);
 
2619
        if (r < 0 || r >= sizeof(path))
 
2620
                return false;
 
2621
 
 
2622
        FILE *fp = fopen(path, "r");
 
2623
        if (!fp)
 
2624
                return false;
 
2625
 
 
2626
        bool ok = fscanf(fp, "%llu", val) == 1;
 
2627
        fclose(fp);
 
2628
 
 
2629
        return ok;
 
2630
}
 
2631
 
 
2632
 
 
2633
/* Get the starting sector and length of a partition PART within a block device
 
2634
   Use blkpg if available, then check sysfs and then use HDIO_GETGEO and
 
2635
   BLKGETSIZE64 ioctls as fallback.  Upon success, return true.  Otherwise,
 
2636
   return false. */
 
2637
static bool
 
2638
_kernel_get_partition_start_and_length(PedPartition const *part,
 
2639
                                       unsigned long long *start,
 
2640
                                       unsigned long long *length)
 
2641
{
 
2642
        PED_ASSERT(part);
 
2643
        PED_ASSERT(start);
 
2644
        PED_ASSERT(length);
 
2645
 
 
2646
        char *dev_name = _device_get_part_path (part->disk->dev, part->num);
 
2647
        if (!dev_name)
 
2648
                return false;
 
2649
 
 
2650
        int ok = _sysfs_ull_entry_from_part (part, "start", start);
 
2651
        if (!ok) {
 
2652
                struct hd_geometry geom;
 
2653
                int dev_fd = open (dev_name, O_RDONLY);
 
2654
                if (dev_fd != -1 && ioctl (dev_fd, HDIO_GETGEO, &geom)) {
 
2655
                        *start = geom.start;
 
2656
                        ok = true;
 
2657
                } else {
 
2658
                        if (dev_fd != -1)
 
2659
                                close(dev_fd);
 
2660
                        free (dev_name);
 
2661
                        return false;
 
2662
                }
 
2663
        }
 
2664
        *start = (*start * 512) / part->disk->dev->sector_size;
 
2665
        ok = _sysfs_ull_entry_from_part (part, "size", length);
 
2666
 
 
2667
        int fd;
 
2668
        if (!ok) {
 
2669
                fd = open (dev_name, O_RDONLY);
 
2670
                if (fd != -1 && ioctl (fd, BLKGETSIZE64, length))
 
2671
                        ok = true;
 
2672
        } else {
 
2673
                fd = -1;
 
2674
                *length *= 512;
 
2675
        }
 
2676
        *length /= part->disk->dev->sector_size;
 
2677
        if (fd != -1)
 
2678
                close (fd);
 
2679
 
 
2680
        if (!ok)
 
2681
                ped_exception_throw (
 
2682
                        PED_EXCEPTION_BUG,
 
2683
                        PED_EXCEPTION_CANCEL,
 
2684
                        _("Unable to determine the start and length of %s."),
 
2685
                        dev_name);
 
2686
        free (dev_name);
 
2687
        return ok;
 
2688
}
 
2689
 
 
2690
 
 
2691
/*
 
2692
 * The number of partitions that a device can have depends on the kernel.
 
2693
 * If we don't find this value in /sys/block/DEV/ext_range, we will use our own
 
2694
 * value.
 
2695
 */
 
2696
static unsigned int
 
2697
_device_get_partition_range(PedDevice const* dev)
 
2698
{
 
2699
        int range;
 
2700
        if (dev->type == PED_DEVICE_DM)
 
2701
                return MAX_NUM_PARTS;
 
2702
        bool ok = _sysfs_int_entry_from_dev(dev, "ext_range", &range);
 
2703
 
 
2704
        if (!ok)
 
2705
                return MAX_NUM_PARTS;
 
2706
        /* both 0 and 1 mean no partitions */
 
2707
        return range > 1 ? range : 0;
 
2708
}
 
2709
 
 
2710
#ifdef ENABLE_DEVICE_MAPPER
 
2711
static int
 
2712
_dm_remove_partition(PedDisk* disk, int partno)
 
2713
{
 
2714
        int             rc = 0;
 
2715
        uint32_t        cookie = 0;
 
2716
        char            *part_name = _device_get_part_path (disk->dev, partno);
 
2717
 
 
2718
        int fd = open (part_name, O_RDONLY | O_EXCL);
 
2719
        if (fd == -1) {
 
2720
                if (errno == ENOENT)
 
2721
                        errno = ENXIO; /* nothing to remove, device already doesn't exist */
 
2722
                goto err;
 
2723
        }
 
2724
        close (fd);
 
2725
        struct dm_task *task = dm_task_create(DM_DEVICE_REMOVE);
 
2726
        if (!task)
 
2727
                goto err;
 
2728
        dm_task_set_name (task, part_name);
 
2729
        if (!dm_task_set_cookie (task, &cookie, 0))
 
2730
                goto err;
 
2731
        rc = _dm_task_run_wait (task, cookie);
 
2732
        dm_task_update_nodes();
 
2733
        dm_task_destroy(task);
 
2734
err:
 
2735
        free (part_name);
 
2736
        return rc;
 
2737
}
 
2738
 
 
2739
static bool
 
2740
_dm_get_partition_start_and_length(PedPartition const *part,
 
2741
                                   unsigned long long *start,
 
2742
                                   unsigned long long *length)
 
2743
{
 
2744
        struct dm_task* task = NULL;
 
2745
        int             rc = 0;
 
2746
 
 
2747
        if (!(task = dm_task_create(DM_DEVICE_TABLE)))
 
2748
                return 0;
 
2749
        char *path = _device_get_part_path (part->disk->dev, part->num);
 
2750
        PED_ASSERT(path);
 
2751
        /* libdevmapper likes to complain on stderr instead of quietly
 
2752
           returning ENOENT or ENXIO, so try to stat first */
 
2753
        struct stat st;
 
2754
        if (stat(path, &st))
 
2755
                goto err;
 
2756
        dm_task_set_name(task, path);
 
2757
        if (!dm_task_run(task))
 
2758
                goto err;
 
2759
 
 
2760
        int major, minor;
 
2761
        char *params;
 
2762
        char *target_type;
 
2763
        dm_get_next_target(task, NULL, (uint64_t *)start, (uint64_t *)length, &target_type, &params);
 
2764
        if (sscanf (params, "%d:%d %Ld", &major, &minor, start) != 3)
 
2765
                goto err;
 
2766
        rc = 1;
 
2767
err:
 
2768
        free (path);
 
2769
        dm_task_destroy(task);
 
2770
        return rc;
 
2771
}
 
2772
 
 
2773
 
 
2774
static int
 
2775
_dm_add_partition (PedDisk* disk, const PedPartition* part)
 
2776
{
 
2777
        LinuxSpecific*  arch_specific = LINUX_SPECIFIC (disk->dev);
 
2778
        char*           params = NULL;
 
2779
        char*           vol_name = NULL;
 
2780
        const char*     dev_name = NULL;
 
2781
        char*           vol_uuid = NULL;
 
2782
        const char*     dev_uuid = NULL;
 
2783
        uint32_t        cookie = 0;
 
2784
 
 
2785
        /* Get map name from devicemapper */
 
2786
        struct dm_task *task = dm_task_create (DM_DEVICE_INFO);
 
2787
        if (!task)
 
2788
                goto err;
 
2789
 
 
2790
        if (!dm_task_set_major_minor (task, arch_specific->major,
 
2791
                                      arch_specific->minor, 0))
 
2792
                goto err;
 
2793
 
 
2794
        if (!dm_task_run(task))
 
2795
                goto err;
 
2796
 
 
2797
        dev_name = dm_task_get_name (task);
 
2798
        size_t name_len = strlen (dev_name);
 
2799
        vol_name = zasprintf ("%s%s%d",
 
2800
                              dev_name,
 
2801
                              isdigit (dev_name[name_len - 1]) ? "p" : "",
 
2802
                              part->num);
 
2803
        if (vol_name == NULL)
 
2804
                goto err;
 
2805
 
 
2806
        dev_uuid = dm_task_get_uuid (task);
 
2807
        if (dev_uuid && (strlen(dev_uuid) > 0)
 
2808
             && !(vol_uuid = zasprintf ("part%d-%s", part->num, dev_uuid)))
 
2809
            goto err;
 
2810
 
 
2811
        /* Caution: dm_task_destroy frees dev_name.  */
 
2812
        dm_task_destroy (task);
 
2813
        task = NULL;
 
2814
        if ( ! (params = zasprintf ("%d:%d %lld", arch_specific->major,
 
2815
                                    arch_specific->minor, part->geom.start)))
 
2816
                goto err;
 
2817
 
 
2818
        task = dm_task_create (DM_DEVICE_CREATE);
 
2819
        if (!task)
 
2820
                goto err;
 
2821
 
 
2822
        dm_task_set_name (task, vol_name);
 
2823
        if (vol_uuid)
 
2824
                dm_task_set_uuid (task, vol_uuid);
 
2825
        dm_task_add_target (task, 0, part->geom.length,
 
2826
                "linear", params);
 
2827
        if (!dm_task_set_cookie (task, &cookie, 0))
 
2828
                goto err;
 
2829
        if (_dm_task_run_wait (task, cookie)) {
 
2830
                dm_task_update_nodes ();
 
2831
                dm_task_destroy (task);
 
2832
                free (params);
 
2833
                free (vol_uuid);
 
2834
                free (vol_name);
 
2835
                return 1;
 
2836
        } else {
 
2837
                _dm_remove_partition (disk, part->num);
 
2838
        }
 
2839
err:
 
2840
        dm_task_update_nodes();
 
2841
        if (task)
 
2842
                dm_task_destroy (task);
 
2843
        free (params);
 
2844
        free (vol_uuid);
 
2845
        free (vol_name);
 
2846
        return 0;
 
2847
}
 
2848
 
 
2849
static int
 
2850
_dm_resize_partition (PedDisk* disk, const PedPartition* part)
 
2851
{
 
2852
        LinuxSpecific*  arch_specific = LINUX_SPECIFIC (disk->dev);
 
2853
        char*           params = NULL;
 
2854
        char*           vol_name = NULL;
 
2855
        const char*     dev_name = NULL;
 
2856
        uint32_t        cookie = 0;
 
2857
 
 
2858
        /* Get map name from devicemapper */
 
2859
        struct dm_task *task = dm_task_create (DM_DEVICE_INFO);
 
2860
        if (!task)
 
2861
                goto err;
 
2862
 
 
2863
        if (!dm_task_set_major_minor (task, arch_specific->major,
 
2864
                                      arch_specific->minor, 0))
 
2865
                goto err;
 
2866
 
 
2867
        if (!dm_task_run(task))
 
2868
                goto err;
 
2869
 
 
2870
        dev_name = dm_task_get_name (task);
 
2871
        size_t name_len = strlen (dev_name);
 
2872
        vol_name = zasprintf ("%s%s%d",
 
2873
                              dev_name,
 
2874
                              isdigit (dev_name[name_len - 1]) ? "p" : "",
 
2875
                              part->num);
 
2876
        if (vol_name == NULL)
 
2877
                goto err;
 
2878
 
 
2879
        /* Caution: dm_task_destroy frees dev_name.  */
 
2880
        dm_task_destroy (task);
 
2881
        task = NULL;
 
2882
        if ( ! (params = zasprintf ("%d:%d %lld", arch_specific->major,
 
2883
                                    arch_specific->minor, part->geom.start)))
 
2884
                goto err;
 
2885
 
 
2886
        task = dm_task_create (DM_DEVICE_RELOAD);
 
2887
        if (!task)
 
2888
                goto err;
 
2889
 
 
2890
        dm_task_set_name (task, vol_name);
 
2891
        dm_task_add_target (task, 0, part->geom.length,
 
2892
                "linear", params);
 
2893
        if (!dm_task_set_cookie (task, &cookie, 0))
 
2894
                goto err;
 
2895
        if (dm_task_run (task)) {
 
2896
                dm_task_destroy (task);
 
2897
                task = dm_task_create (DM_DEVICE_RESUME);
 
2898
                if (!task)
 
2899
                        goto err;
 
2900
                dm_task_set_name (task, vol_name);
 
2901
                if (!dm_task_set_cookie (task, &cookie, 0))
 
2902
                        goto err;
 
2903
                if (dm_task_run (task)) {
 
2904
                        free (params);
 
2905
                        free (vol_name);
 
2906
                        return 1;
 
2907
                }
 
2908
        }
 
2909
err:
 
2910
        dm_task_update_nodes();
 
2911
        if (task)
 
2912
                dm_task_destroy (task);
 
2913
        free (params);
 
2914
        free (vol_name);
 
2915
        return 0;
 
2916
}
 
2917
 
 
2918
#endif
 
2919
 
 
2920
/*
 
2921
 * Sync the partition table in two step process:
 
2922
 * 1. Remove all of the partitions from the kernel's tables, but do not attempt
 
2923
 *    removal of any partition for which the corresponding ioctl call fails.
 
2924
 * 2. Add all the partitions that we hold in disk, throwing a warning
 
2925
 *    if we cannot because step 1 failed to remove it and it is not being
 
2926
 *    added back with the same start and length.
 
2927
 *
 
2928
 * To achieve this two step process we must calculate the minimum number of
 
2929
 * maximum possible partitions between what linux supports and what the label
 
2930
 * type supports. EX:
 
2931
 *
 
2932
 * number=MIN(max_parts_supported_in_linux,max_parts_supported_in_msdos_tables)
 
2933
 */
 
2934
static int
 
2935
_disk_sync_part_table (PedDisk* disk)
 
2936
{
 
2937
        PED_ASSERT(disk != NULL);
 
2938
        PED_ASSERT(disk->dev != NULL);
 
2939
        int lpn, lpn2;
 
2940
        unsigned int part_range = _device_get_partition_range(disk->dev);
 
2941
        int (*add_partition)(PedDisk* disk, const PedPartition *part);
 
2942
        int (*resize_partition)(PedDisk* disk, const PedPartition *part);
 
2943
        int (*remove_partition)(PedDisk* disk, int partno);
 
2944
        bool (*get_partition_start_and_length)(PedPartition const *part,
 
2945
                                               unsigned long long *start,
 
2946
                                               unsigned long long *length);
 
2947
 
 
2948
 
 
2949
        if (disk->dev->type == PED_DEVICE_DM) {
 
2950
                add_partition = _dm_add_partition;
 
2951
                remove_partition = _dm_remove_partition;
 
2952
                resize_partition = _dm_resize_partition;
 
2953
                get_partition_start_and_length = _dm_get_partition_start_and_length;
 
2954
        } else {
 
2955
                add_partition = _blkpg_add_partition;
 
2956
                remove_partition = _blkpg_remove_partition;
 
2957
#ifdef BLKPG_RESIZE_PARTITION
 
2958
                resize_partition = _blkpg_resize_partition;
 
2959
#else
 
2960
                resize_partition = NULL;
 
2961
#endif
 
2962
                get_partition_start_and_length = _kernel_get_partition_start_and_length;
 
2963
        }
 
2964
 
 
2965
        /* lpn = largest partition number.
 
2966
         * for remove pass, use greater of device or label limit */
 
2967
        if (ped_disk_get_max_supported_partition_count(disk, &lpn))
 
2968
                lpn = PED_MAX(lpn, part_range);
 
2969
        else
 
2970
                lpn = part_range;
 
2971
        /* for add pass, use lesser of device or label limit */
 
2972
        if (ped_disk_get_max_supported_partition_count(disk, &lpn2))
 
2973
                lpn2 = PED_MIN(lpn2, part_range);
 
2974
        else
 
2975
                lpn2 = part_range;
 
2976
        /* Its not possible to support largest_partnum < 0.
 
2977
         * largest_partnum == 0 would mean does not support partitions.
 
2978
         * */
 
2979
        if (lpn < 1)
 
2980
                return 0;
 
2981
        int ret = 0;
 
2982
        int *ok = calloc (lpn, sizeof *ok);
 
2983
        if (!ok)
 
2984
                return 0;
 
2985
        int *errnums = ped_malloc(sizeof(int) * lpn);
 
2986
        if (!errnums)
 
2987
                goto cleanup;
 
2988
 
 
2989
        int i;
 
2990
        /* remove old partitions first */
 
2991
        for (i = 1; i <= lpn; i++) {
 
2992
                PedPartition *part = ped_disk_get_partition (disk, i);
 
2993
                if (part) {
 
2994
                        unsigned long long length;
 
2995
                        unsigned long long start;
 
2996
                        /* get start and length of existing partition */
 
2997
                        if (get_partition_start_and_length(part,
 
2998
                                                           &start, &length)
 
2999
                            && start == part->geom.start
 
3000
                            && (length == part->geom.length
 
3001
                                || (resize_partition && part->num < lpn2)))
 
3002
                        {
 
3003
                                /* partition is unchanged, or will be resized so nothing to do */
 
3004
                                ok[i - 1] = 1;
 
3005
                                continue;
 
3006
                        }
 
3007
                }
 
3008
                /* Attempt to remove the partition, retrying for
 
3009
                   up to max_sleep_seconds upon any failure due to EBUSY. */
 
3010
                unsigned int sleep_microseconds = 10000;
 
3011
                unsigned int max_sleep_seconds = 1;
 
3012
                unsigned int n_sleep = (max_sleep_seconds
 
3013
                                        * 1000000 / sleep_microseconds);
 
3014
                do {
 
3015
                        ok[i - 1] = remove_partition (disk, i);
 
3016
                        errnums[i - 1] = errno;
 
3017
                        if (ok[i - 1] || errnums[i - 1] != EBUSY)
 
3018
                                break;
 
3019
                        usleep (sleep_microseconds);
 
3020
                } while (n_sleep--);
 
3021
                if (!ok[i - 1] && errnums[i - 1] == ENXIO)
 
3022
                        ok[i - 1] = 1; /* it already doesn't exist */
 
3023
        }
 
3024
        lpn = lpn2;
 
3025
        /* don't actually add partitions for loop */
 
3026
        if (strcmp (disk->type->name, "loop") == 0)
 
3027
                lpn = 0;
 
3028
        for (i = 1; i <= lpn; i++) {
 
3029
                PedPartition *part = ped_disk_get_partition (disk, i);
 
3030
                if (!part)
 
3031
                        continue;
 
3032
                unsigned long long length;
 
3033
                unsigned long long start;
 
3034
                /* get start and length of existing partition */
 
3035
                if (get_partition_start_and_length(part,
 
3036
                                                   &start, &length)
 
3037
                    && start == part->geom.start)
 
3038
                {
 
3039
                        if (length == part->geom.length) {
 
3040
                                ok[i - 1] = 1;
 
3041
                                /* partition is unchanged, so nothing to do */
 
3042
                                continue;
 
3043
                        }
 
3044
                        if (resize_partition
 
3045
                            && start == part->geom.start)
 
3046
                        {
 
3047
                                /* try to resize */
 
3048
                                if (resize_partition (disk, part)) {
 
3049
                                        ok[i - 1] = 1;
 
3050
                                        continue;
 
3051
                                }
 
3052
                        }
 
3053
                }
 
3054
                /* add the (possibly modified or new) partition */
 
3055
                if (!add_partition (disk, part)) {
 
3056
                        ok[i - 1] = 0;
 
3057
                        errnums[i - 1] = errno;
 
3058
                }
 
3059
        }
 
3060
 
 
3061
        char *bad_part_list = NULL;
 
3062
        /* now warn about any errors */
 
3063
        for (i = 1; i <= lpn; i++) {
 
3064
                if (ok[i - 1] || errnums[i - 1] == ENXIO)
 
3065
                        continue;
 
3066
                if (bad_part_list == NULL) {
 
3067
                        bad_part_list = malloc (lpn * 5);
 
3068
                        if (!bad_part_list)
 
3069
                                goto cleanup;
 
3070
                        bad_part_list[0] = 0;
 
3071
                }
 
3072
                sprintf (bad_part_list + strlen (bad_part_list), "%d, ", i);
 
3073
        }
 
3074
        if (bad_part_list == NULL)
 
3075
                ret = 1;
 
3076
        else {
 
3077
                bad_part_list[strlen (bad_part_list) - 2] = 0;
 
3078
                if (ped_exception_throw (
 
3079
                        PED_EXCEPTION_ERROR,
 
3080
                        PED_EXCEPTION_IGNORE_CANCEL,
 
3081
                        _("Partition(s) %s on %s have been written, but we have "
 
3082
                          "been unable to inform the kernel of the change, "
 
3083
                          "probably because it/they are in use.  As a result, "
 
3084
                          "the old partition(s) will remain in use.  You "
 
3085
                          "should reboot now before making further changes."),
 
3086
                        bad_part_list, disk->dev->path) == PED_EXCEPTION_IGNORE)
 
3087
                        ret = 1;
 
3088
                free (bad_part_list);
 
3089
        }
 
3090
 cleanup:
 
3091
        free (errnums);
 
3092
        free (ok);
 
3093
        return ret;
 
3094
}
 
3095
 
 
3096
static int
 
3097
_have_blkpg ()
 
3098
{
 
3099
        static int have_blkpg = -1;
 
3100
        int kver;
 
3101
 
 
3102
        if (have_blkpg != -1)
 
3103
                return have_blkpg;
 
3104
 
 
3105
        kver = _get_linux_version();
 
3106
        return have_blkpg = kver >= KERNEL_VERSION (2,4,0) ? 1 : 0;
 
3107
}
 
3108
 
 
3109
static int
 
3110
_chrooted ()
 
3111
{
 
3112
        static int cached = -1;
 
3113
        struct stat root, init_root;
 
3114
 
 
3115
        if (cached != -1)
 
3116
                return cached;
 
3117
 
 
3118
        if (stat ("/", &root) || stat ("/proc/1/root", &init_root))
 
3119
                /* We can't tell, but are unlikely to be able to tell in the
 
3120
                 * future either.
 
3121
                 */
 
3122
                cached = 0;
 
3123
        else if (root.st_dev == init_root.st_dev &&
 
3124
                 root.st_ino == init_root.st_ino)
 
3125
                /* / has the same dev/ino as /sbin/init's root, so we're not
 
3126
                 * in a chroot.
 
3127
                 */
 
3128
                cached = 0;
 
3129
        else
 
3130
                /* We must be in a chroot. */
 
3131
                cached = 1;
 
3132
 
 
3133
        return cached;
 
3134
}
 
3135
 
 
3136
/* Return nonzero upon success, 0 if something fails.  */
 
3137
static int
 
3138
linux_disk_commit (PedDisk* disk)
 
3139
{
 
3140
        int ret = 1;
 
3141
 
 
3142
        /* Modern versions of udev may notice the write activity on
 
3143
         * partition devices caused by _flush_cache, and may decide to
 
3144
         * synthesise some change events as a result. These may in turn run
 
3145
         * programs that open partition devices, which will race with us
 
3146
         * trying to remove those devices. To avoid this, we need to wait
 
3147
         * until udevd has finished processing its event queue.
 
3148
         * TODO: for upstream submission, this should check whether udevadm
 
3149
         * exists on $PATH.
 
3150
         */
 
3151
        if (!_chrooted () && system ("udevadm settle") != 0) {
 
3152
                /* ignore failures */
 
3153
        }
 
3154
 
 
3155
        if (disk->dev->type != PED_DEVICE_FILE) {
 
3156
 
 
3157
                /* We now require BLKPG support.  If this assertion fails,
 
3158
                   please write to the mailing list describing your system.
 
3159
                   Assuming it's never triggered, ...
 
3160
                   FIXME: remove this assertion in 2012.  */
 
3161
                assert (_have_blkpg ());
 
3162
 
 
3163
                if (!_disk_sync_part_table (disk))
 
3164
                        ret = 0;
 
3165
        }
 
3166
 
 
3167
        /* Now we wait for udevd to finish creating device nodes based on
 
3168
         * the above activity, so that callers can reliably use them.
 
3169
         * TODO: for upstream submission, this should check whether udevadm
 
3170
         * exists on $PATH.
 
3171
         */
 
3172
        if (!_chrooted () && system ("udevadm settle") != 0) {
 
3173
                /* ignore failures */
 
3174
        }
 
3175
 
 
3176
        return ret;
 
3177
}
 
3178
 
 
3179
#if USE_BLKID
 
3180
static PedAlignment*
 
3181
linux_get_minimum_alignment(const PedDevice *dev)
 
3182
{
 
3183
        blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
 
3184
        if (!tp)
 
3185
                return NULL;
 
3186
 
 
3187
        if (blkid_topology_get_minimum_io_size(tp) == 0)
 
3188
                return ped_alignment_new(
 
3189
                        blkid_topology_get_alignment_offset(tp) /
 
3190
                                dev->sector_size,
 
3191
                        dev->phys_sector_size / dev->sector_size);
 
3192
 
 
3193
        return ped_alignment_new(
 
3194
                blkid_topology_get_alignment_offset(tp) / dev->sector_size,
 
3195
                blkid_topology_get_minimum_io_size(tp) / dev->sector_size);
 
3196
}
 
3197
 
 
3198
static PedAlignment*
 
3199
linux_get_optimum_alignment(const PedDevice *dev)
 
3200
{
 
3201
        blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
 
3202
        if (!tp)
 
3203
                return NULL;
 
3204
 
 
3205
        /* When PED_DEFAULT_ALIGNMENT is divisible by the *_io_size or
 
3206
           there are no *_io_size values, use the PED_DEFAULT_ALIGNMENT
 
3207
           If one or the other will not divide evenly, fall through to
 
3208
           previous logic. */
 
3209
        unsigned long optimal_io = blkid_topology_get_optimal_io_size(tp);
 
3210
        unsigned long minimum_io = blkid_topology_get_minimum_io_size(tp);
 
3211
        if (
 
3212
            (!optimal_io && !minimum_io)
 
3213
            || (optimal_io && PED_DEFAULT_ALIGNMENT % optimal_io == 0
 
3214
                && minimum_io && PED_DEFAULT_ALIGNMENT % minimum_io == 0)
 
3215
            || (!minimum_io && optimal_io
 
3216
                && PED_DEFAULT_ALIGNMENT % optimal_io == 0)
 
3217
            || (!optimal_io && minimum_io
 
3218
                && PED_DEFAULT_ALIGNMENT % minimum_io == 0)
 
3219
           ) {
 
3220
            /* DASD needs to use minimum alignment */
 
3221
            if (dev->type == PED_DEVICE_DASD)
 
3222
                return linux_get_minimum_alignment(dev);
 
3223
 
 
3224
            return ped_alignment_new(
 
3225
                    blkid_topology_get_alignment_offset(tp) / dev->sector_size,
 
3226
                    PED_DEFAULT_ALIGNMENT / dev->sector_size);
 
3227
        }
 
3228
 
 
3229
        /* If optimal_io_size is 0 and we don't meet the other criteria
 
3230
           for using the device.c default, return the minimum alignment. */
 
3231
        if (blkid_topology_get_optimal_io_size(tp) == 0)
 
3232
                return linux_get_minimum_alignment(dev);
 
3233
 
 
3234
        return ped_alignment_new(
 
3235
                blkid_topology_get_alignment_offset(tp) / dev->sector_size,
 
3236
                blkid_topology_get_optimal_io_size(tp) / dev->sector_size);
 
3237
}
 
3238
#endif
 
3239
 
 
3240
static PedDeviceArchOps linux_dev_ops = {
 
3241
        _new:           linux_new,
 
3242
        destroy:        linux_destroy,
 
3243
        is_busy:        linux_is_busy,
 
3244
        open:           linux_open,
 
3245
        refresh_open:   linux_refresh_open,
 
3246
        close:          linux_close,
 
3247
        refresh_close:  linux_refresh_close,
 
3248
        read:           linux_read,
 
3249
        write:          linux_write,
 
3250
        check:          linux_check,
 
3251
        sync:           linux_sync,
 
3252
        sync_fast:      linux_sync_fast,
 
3253
        probe_all:      linux_probe_all,
 
3254
#if USE_BLKID
 
3255
        get_minimum_alignment:  linux_get_minimum_alignment,
 
3256
        get_optimum_alignment:  linux_get_optimum_alignment,
 
3257
#endif
 
3258
};
 
3259
 
 
3260
PedDiskArchOps linux_disk_ops =  {
 
3261
        partition_get_path:     linux_partition_get_path,
 
3262
        partition_is_busy:      linux_partition_is_busy,
 
3263
        disk_commit:            linux_disk_commit
 
3264
};
 
3265
 
 
3266
PedArchitecture ped_linux_arch = {
 
3267
        dev_ops:        &linux_dev_ops,
 
3268
        disk_ops:       &linux_disk_ops
 
3269
};