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

« back to all changes in this revision

Viewing changes to .pc/skip-floppy.patch/libparted/arch/linux.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2014-07-21 10:23:16 UTC
  • mfrom: (7.2.32 sid)
  • Revision ID: package-import@ubuntu.com-20140721102316-jsyv3yzmbo8vlde5
Tags: 3.1-3
Upload to unstable.

Show diffs side-by-side

added added

removed removed

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