~youscribe/parted/3.1

« back to all changes in this revision

Viewing changes to libparted/arch/beos.c

  • Committer: Guilhem Lettron
  • Date: 2012-10-22 14:37:59 UTC
  • Revision ID: guilhem+ubuntu@lettron.fr-20121022143759-m403kecgz13sknvp
3.1 from tarball

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    libparted - a library for manipulating disk partitions
 
3
    Copyright (C) 2006-2007, 2009-2012 Free Software Foundation, Inc.
 
4
 
 
5
    This program is free software; you can redistribute it and/or modify
 
6
    it under the terms of the GNU General Public License as published by
 
7
    the Free Software Foundation; either version 3 of the License, or
 
8
    (at your option) any later version.
 
9
 
 
10
    This program is distributed in the hope that it will be useful,
 
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
    GNU General Public License for more details.
 
14
 
 
15
    You should have received a copy of the GNU General Public License
 
16
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
*/
 
18
 
 
19
#include <config.h>
 
20
 
 
21
#include <parted/parted.h>
 
22
#include <parted/debug.h>
 
23
 
 
24
/* POSIX headers */
 
25
#include <sys/stat.h>
 
26
#include <dirent.h>
 
27
#include <limits.h>
 
28
#include <unistd.h>
 
29
#include <fcntl.h>
 
30
#include <errno.h>
 
31
 
 
32
/* BeOS APIs */
 
33
#include <drivers/Drivers.h>
 
34
 
 
35
/* ZETA R1+ APIs */
 
36
#if B_ZETA_VERSION >= B_ZETA_VERSION_1_0_0
 
37
#  include <device/ata_info.h>
 
38
#endif
 
39
 
 
40
#if ENABLE_NLS
 
41
#  include <libintl.h>
 
42
#  define _(String) dgettext (PACKAGE, String)
 
43
#else
 
44
#  define _(String) (String)
 
45
#endif /* ENABLE_NLS */
 
46
 
 
47
#include "../architecture.h"
 
48
 
 
49
#define BEOS_SPECIFIC(dev)      ((BEOSSpecific*) (dev)->arch_specific)
 
50
 
 
51
typedef struct _BEOSSpecific    BEOSSpecific;
 
52
 
 
53
struct _BEOSSpecific {
 
54
        int     fd;
 
55
};
 
56
 
 
57
static void
 
58
_scan_for_disks(const char* path)
 
59
{
 
60
        char subdir[PATH_MAX];
 
61
        dirent_t* entp;
 
62
        size_t pos;
 
63
        DIR* dirp;
 
64
 
 
65
        if ((dirp=opendir(path)) != NULL)
 
66
        {
 
67
                /* Build first part of path */
 
68
                strcpy(subdir, path);
 
69
                strcat(subdir, "/");
 
70
                pos = strlen(subdir);
 
71
 
 
72
                /* Check all directory entries.. */
 
73
                while((entp=readdir(dirp)) != NULL)
 
74
                {
 
75
                        /* If they start with '.' just skip */
 
76
                        if (entp->d_name[0] == '.')
 
77
                                continue;
 
78
 
 
79
                        strcpy(subdir+pos, entp->d_name);
 
80
 
 
81
                        /* /dev/disk/.../raw are the complete disks
 
82
                                we're interested in */
 
83
                        if (strcmp(entp->d_name, "raw") == 0)
 
84
                                _ped_device_probe(subdir);
 
85
                        else    /* If not 'raw', it most often will
 
86
                                                be another subdir */
 
87
                                _scan_for_disks(subdir);
 
88
                }
 
89
 
 
90
                closedir(dirp);
 
91
        }
 
92
}
 
93
 
 
94
static void
 
95
_flush_cache(PedDevice* dev)
 
96
{
 
97
        int fd;
 
98
        if ((fd=open(dev->path, O_RDONLY)) < 0)
 
99
        {
 
100
                ioctl(fd, B_FLUSH_DRIVE_CACHE);
 
101
                close(fd);
 
102
        }
 
103
}
 
104
 
 
105
#if B_ZETA_VERSION >= B_ZETA_VERSION_1_0_0
 
106
static int
 
107
_device_init_ata(PedDevice* dev)
 
108
{
 
109
        ata_device_infoblock ide_info;
 
110
        int maxlen, len, idx, fd;
 
111
        char buf[256];
 
112
 
 
113
        /* Try and get information about device from ATA(PI) driver */
 
114
        if ((fd=open(dev->path, O_RDONLY)) < 0)
 
115
                goto ata_error;
 
116
 
 
117
        if (ioctl(fd, B_ATA_GET_DEVICE_INFO, &ide_info, sizeof(ide_info)) < 0)
 
118
                goto ata_error_close;
 
119
 
 
120
        close(fd);
 
121
 
 
122
        /* Copy 'logical' dimensions */
 
123
        dev->bios_geom.cylinders = ide_info.cylinders;
 
124
        dev->bios_geom.heads = ide_info.heads;
 
125
        dev->bios_geom.sectors = ide_info.sectors;
 
126
 
 
127
        /* Copy used dimensions */
 
128
        dev->hw_geom.cylinders = ide_info.current_cylinders;
 
129
        dev->hw_geom.heads = ide_info.current_heads;
 
130
        dev->hw_geom.sectors = ide_info.current_sectors;
 
131
 
 
132
        /* Copy total number of sectors */
 
133
        if (ide_info._48_bit_addresses_supported)
 
134
                dev->length = ide_info.LBA48_total_sectors;
 
135
        else if (ide_info.LBA_supported)
 
136
                dev->length = ide_info.LBA_total_sectors;
 
137
        else
 
138
                dev->length = ide_info.cylinders *
 
139
                                ide_info.heads *
 
140
                                ide_info.sectors;
 
141
 
 
142
        dev->sector_size =
 
143
        dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
 
144
 
 
145
        /* Use sensible model */
 
146
        maxlen=sizeof(ide_info.model_number);
 
147
        strncpy(buf, ide_info.model_number, maxlen);
 
148
        buf[maxlen] = '\0';
 
149
 
 
150
        for (len=-1, idx=maxlen-1; idx > 0 && len < 0; idx--)
 
151
                if (buf[idx] > 0x20)
 
152
                        len = idx;
 
153
 
 
154
        buf[(len == -1) ? 0 : len+1] = '\0';
 
155
 
 
156
        dev->model = strdup(buf);
 
157
 
 
158
        return PED_DEVICE_IDE;
 
159
 
 
160
ata_error_close:
 
161
        close(fd);
 
162
 
 
163
ata_error:
 
164
        return 0;
 
165
}
 
166
#endif
 
167
 
 
168
static int
 
169
_device_init_generic_blkdev(PedDevice* dev)
 
170
{
 
171
        device_geometry bios, os;
 
172
        int got_bios_info = 0;
 
173
        int fd;
 
174
 
 
175
        /* Try and get information about device from ATA(PI) driver */
 
176
        if ((fd=open(dev->path, O_RDONLY)) < 0)
 
177
                goto blkdev_error;
 
178
 
 
179
        /* B_GET_GEOMETRY is mandatory */
 
180
        if (ioctl(fd, B_GET_GEOMETRY, &os, sizeof(os)) < 0)
 
181
                goto blkdev_error_close;
 
182
 
 
183
        /* B_GET_BIOS_GEOMETRY is optional */
 
184
        if (!ioctl(fd, B_GET_BIOS_GEOMETRY, &bios, sizeof(bios)))
 
185
                got_bios_info = 1;
 
186
 
 
187
        close(fd);
 
188
 
 
189
        dev->hw_geom.cylinders = os.cylinder_count;
 
190
        dev->hw_geom.heads = os.head_count;
 
191
        dev->hw_geom.sectors = os.sectors_per_track;
 
192
 
 
193
        dev->sector_size =
 
194
        dev->phys_sector_size = os.bytes_per_sector;
 
195
 
 
196
        if (got_bios_info)
 
197
        {
 
198
                dev->bios_geom.cylinders = bios.cylinder_count;
 
199
                dev->bios_geom.heads = bios.head_count;
 
200
                dev->bios_geom.sectors = bios.sectors_per_track;
 
201
        }
 
202
        else
 
203
                dev->bios_geom = dev->hw_geom;
 
204
 
 
205
        dev->model = strdup("");
 
206
 
 
207
        return PED_DEVICE_IDE;
 
208
 
 
209
blkdev_error_close:
 
210
        close(fd);
 
211
 
 
212
blkdev_error:
 
213
        return 0;
 
214
}
 
215
 
 
216
static int
 
217
_device_init_blkdev(PedDevice* dev)
 
218
{
 
219
        int type;
 
220
 
 
221
#if B_ZETA_VERSION >= B_ZETA_VERSION_1_0_0
 
222
        if (!(type=_device_init_ata(dev)))
 
223
#endif
 
224
        type = _device_init_generic_blkdev(dev);
 
225
 
 
226
        return type;
 
227
}
 
228
 
 
229
static int
 
230
_device_init_file(PedDevice* dev, struct stat* dev_statp)
 
231
{
 
232
        if (!dev_statp->st_size)
 
233
                return 0;
 
234
 
 
235
        dev->sector_size =
 
236
        dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT;
 
237
 
 
238
        dev->length = dev_statp->st_size / PED_SECTOR_SIZE_DEFAULT;
 
239
 
 
240
        dev->bios_geom.cylinders = dev->length / (4 * 32);
 
241
        dev->bios_geom.heads = 4;
 
242
        dev->bios_geom.sectors = 32;
 
243
        dev->hw_geom = dev->bios_geom;
 
244
 
 
245
        dev->model = strdup(_("Disk Image"));
 
246
 
 
247
        return PED_DEVICE_FILE;
 
248
}
 
249
 
 
250
static int
 
251
_device_init(PedDevice* dev)
 
252
{
 
253
        struct stat dev_stat;
 
254
        int type = 0;
 
255
 
 
256
        /* Check if we're a regular file */
 
257
        if (stat(dev->path, &dev_stat) < 0)
 
258
                goto done;
 
259
 
 
260
        if (S_ISBLK(dev_stat.st_mode) || S_ISCHR(dev_stat.st_mode))
 
261
                type = _device_init_blkdev(dev);
 
262
        else if (S_ISREG(dev_stat.st_mode))
 
263
                type = _device_init_file(dev,&dev_stat);
 
264
 
 
265
done:
 
266
        return type;
 
267
}
 
268
 
 
269
 
 
270
static PedDevice*
 
271
beos_new (const char* path)
 
272
{
 
273
        struct stat stat_info;
 
274
        PedDevice* dev;
 
275
 
 
276
        PED_ASSERT(path != NULL);
 
277
 
 
278
        dev = (PedDevice*) ped_malloc (sizeof (PedDevice));
 
279
        if (!dev)
 
280
                goto error;
 
281
 
 
282
        dev->path = strdup(path);
 
283
        if (!dev->path)
 
284
                goto error_free_dev;
 
285
 
 
286
        dev->arch_specific
 
287
                = (BEOSSpecific*) ped_malloc(sizeof(BEOSSpecific));
 
288
        if (dev->arch_specific == NULL)
 
289
                goto error_free_path;
 
290
 
 
291
        dev->open_count = 0;
 
292
        dev->read_only = 0;
 
293
        dev->external_mode = 0;
 
294
        dev->dirty = 0;
 
295
        dev->boot_dirty = 0;
 
296
 
 
297
        if ((dev->type=_device_init(dev)) <= 0)
 
298
                goto error_free_arch_specific;
 
299
 
 
300
        /* All OK! */
 
301
        return dev;
 
302
 
 
303
error_free_arch_specific:
 
304
        free (dev->arch_specific);
 
305
 
 
306
error_free_path:
 
307
        free (dev->path);
 
308
 
 
309
error_free_dev:
 
310
        free (dev);
 
311
 
 
312
error:
 
313
        return NULL;
 
314
}
 
315
 
 
316
static void
 
317
beos_destroy (PedDevice* dev)
 
318
{
 
319
        free (dev->arch_specific);
 
320
        free (dev->path);
 
321
        free (dev->model);
 
322
        free (dev);
 
323
}
 
324
 
 
325
static int
 
326
beos_is_busy (PedDevice* dev)
 
327
{
 
328
        return 1;
 
329
}
 
330
 
 
331
static int
 
332
beos_open (PedDevice* dev)
 
333
{
 
334
        BEOSSpecific* arch_specific = BEOS_SPECIFIC(dev);
 
335
 
 
336
retry:
 
337
        arch_specific->fd = open(dev->path, O_RDWR);
 
338
        if (arch_specific->fd == -1) {
 
339
                char* rw_error_msg = strerror(errno);
 
340
 
 
341
                arch_specific->fd = open (dev->path, O_RDONLY);
 
342
                if (arch_specific->fd == -1) {
 
343
                        if (ped_exception_throw (
 
344
                                        PED_EXCEPTION_ERROR,
 
345
                                        PED_EXCEPTION_RETRY_CANCEL,
 
346
                                        _("Error opening %s: %s"),
 
347
                                        dev->path, strerror (errno))
 
348
                                        != PED_EXCEPTION_RETRY) {
 
349
                                                return 0;
 
350
                                        } else {
 
351
                                                goto retry;
 
352
                                        }
 
353
                } else {
 
354
                        ped_exception_throw (
 
355
                                PED_EXCEPTION_WARNING,
 
356
                                PED_EXCEPTION_OK,
 
357
                                _("Unable to open %s read-write (%s).  %s has "
 
358
                                        "been opened read-only."),
 
359
                                dev->path, rw_error_msg, dev->path);
 
360
                        dev->read_only = 1;
 
361
                }
 
362
        } else {
 
363
                dev->read_only = 0;
 
364
        }
 
365
 
 
366
        _flush_cache (dev);
 
367
 
 
368
        return 1;
 
369
}
 
370
 
 
371
static int
 
372
beos_refresh_open (PedDevice* dev)
 
373
{
 
374
        return 1;
 
375
}
 
376
 
 
377
static int
 
378
beos_close (PedDevice* dev)
 
379
{
 
380
        BEOSSpecific* arch_specific = BEOS_SPECIFIC(dev);
 
381
 
 
382
        if (dev->dirty)
 
383
                _flush_cache (dev);
 
384
 
 
385
        close (arch_specific->fd);
 
386
 
 
387
        return 1;
 
388
}
 
389
 
 
390
static int
 
391
beos_refresh_close (PedDevice* dev)
 
392
{
 
393
        if (dev->dirty)
 
394
                _flush_cache (dev);
 
395
 
 
396
        return 1;
 
397
}
 
398
 
 
399
static int
 
400
beos_read (const PedDevice* dev, void* buffer, PedSector start, PedSector count)
 
401
{
 
402
        BEOSSpecific* arch_specific = BEOS_SPECIFIC(dev);
 
403
        int status;
 
404
        PedExceptionOption ex_status;
 
405
        size_t read_length = count * dev->sector_size;
 
406
 
 
407
        PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
 
408
 
 
409
        /* First, try to seek */
 
410
        while(1)
 
411
        {
 
412
                if (lseek(arch_specific->fd, start * dev->sector_size, SEEK_SET)
 
413
                        == start * dev->sector_size)
 
414
                        break;
 
415
 
 
416
                ex_status = ped_exception_throw (
 
417
                        PED_EXCEPTION_ERROR,
 
418
                        PED_EXCEPTION_RETRY_IGNORE_CANCEL,
 
419
                        _("%s during seek for read on %s"),
 
420
                        strerror (errno), dev->path);
 
421
 
 
422
                switch (ex_status)
 
423
                {
 
424
                        case PED_EXCEPTION_IGNORE:
 
425
                                return 1;
 
426
                        case PED_EXCEPTION_RETRY:
 
427
                                break /* out of switch */;
 
428
                        case PED_EXCEPTION_UNHANDLED:
 
429
                                ped_exception_catch ();
 
430
                        case PED_EXCEPTION_CANCEL:
 
431
                                return 0;
 
432
                }
 
433
        }
 
434
 
 
435
        /* If we seeked ok, now is the time to read */
 
436
        while (1)
 
437
        {
 
438
                status = read(arch_specific->fd, buffer, read_length);
 
439
                if (status == count * dev->sector_size)
 
440
                        break;
 
441
 
 
442
                if (status > 0)
 
443
                {
 
444
                        read_length -= status;
 
445
                        buffer += status;
 
446
                        continue;
 
447
                }
 
448
 
 
449
                ex_status = ped_exception_throw (
 
450
                        PED_EXCEPTION_ERROR,
 
451
                        PED_EXCEPTION_RETRY_IGNORE_CANCEL,
 
452
                        _("%s during read on %s"),
 
453
                        strerror (errno),
 
454
                        dev->path);
 
455
 
 
456
                switch (ex_status)
 
457
                {
 
458
                        case PED_EXCEPTION_IGNORE:
 
459
                                return 1;
 
460
                        case PED_EXCEPTION_RETRY:
 
461
                                break;
 
462
                        case PED_EXCEPTION_UNHANDLED:
 
463
                                ped_exception_catch ();
 
464
                        case PED_EXCEPTION_CANCEL:
 
465
                                return 0;
 
466
                }
 
467
        }
 
468
 
 
469
        return 1;
 
470
}
 
471
 
 
472
static int
 
473
beos_write (PedDevice* dev, const void* buffer, PedSector start,
 
474
        PedSector count)
 
475
{
 
476
        BEOSSpecific* arch_specific = BEOS_SPECIFIC(dev);
 
477
        int                     status;
 
478
        PedExceptionOption      ex_status;
 
479
        size_t                  write_length = count * dev->sector_size;
 
480
 
 
481
        PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
 
482
 
 
483
        if (dev->read_only)
 
484
        {
 
485
                if (ped_exception_throw (
 
486
                        PED_EXCEPTION_ERROR,
 
487
                        PED_EXCEPTION_IGNORE_CANCEL,
 
488
                        _("Can't write to %s, because it is opened read-only."),
 
489
                        dev->path)
 
490
                        != PED_EXCEPTION_IGNORE)
 
491
                        return 0;
 
492
                else
 
493
                        return 1;
 
494
        }
 
495
 
 
496
        while(1)
 
497
        {
 
498
                if (lseek(arch_specific->fd,start * dev->sector_size,SEEK_SET)
 
499
                        == start * dev->sector_size)
 
500
                        break;
 
501
 
 
502
                ex_status = ped_exception_throw (
 
503
                        PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_IGNORE_CANCEL,
 
504
                        _("%s during seek for write on %s"),
 
505
                        strerror (errno), dev->path);
 
506
 
 
507
                switch (ex_status)
 
508
                {
 
509
                        case PED_EXCEPTION_IGNORE:
 
510
                                return 1;
 
511
                        case PED_EXCEPTION_RETRY:
 
512
                                break;
 
513
                        case PED_EXCEPTION_UNHANDLED:
 
514
                                ped_exception_catch ();
 
515
                        case PED_EXCEPTION_CANCEL:
 
516
                                return 0;
 
517
                }
 
518
        }
 
519
 
 
520
#ifdef READ_ONLY
 
521
        printf ("ped_device_write (\"%s\", %p, %d, %d)\n",
 
522
                dev->path, buffer, (int) start, (int) count);
 
523
#else
 
524
        dev->dirty = 1;
 
525
        while(1)
 
526
        {
 
527
                status = write (arch_specific->fd, buffer, write_length);
 
528
                if (status == count * dev->sector_size)
 
529
                        break;
 
530
 
 
531
                if (status > 0)
 
532
                {
 
533
                        write_length -= status;
 
534
                        buffer += status;
 
535
                        continue;
 
536
                }
 
537
 
 
538
                ex_status = ped_exception_throw (
 
539
                        PED_EXCEPTION_ERROR,
 
540
                        PED_EXCEPTION_RETRY_IGNORE_CANCEL,
 
541
                        _("%s during write on %s"),
 
542
                        strerror (errno), dev->path);
 
543
 
 
544
                switch (ex_status)
 
545
                {
 
546
                        case PED_EXCEPTION_IGNORE:
 
547
                                return 1;
 
548
                        case PED_EXCEPTION_RETRY:
 
549
                                break;
 
550
                        case PED_EXCEPTION_UNHANDLED:
 
551
                                ped_exception_catch ();
 
552
                        case PED_EXCEPTION_CANCEL:
 
553
                                return 0;
 
554
                }
 
555
        }
 
556
#endif /* !READ_ONLY */
 
557
 
 
558
        return 1;
 
559
}
 
560
 
 
561
static PedSector
 
562
beos_check (PedDevice* dev, void* buffer, PedSector start, PedSector count)
 
563
{
 
564
        BEOSSpecific*   arch_specific = BEOS_SPECIFIC(dev);
 
565
        PedSector               done = 0;
 
566
        int                             status;
 
567
 
 
568
        PED_ASSERT(dev != NULL);
 
569
 
 
570
        if (lseek(arch_specific->fd, start * dev->sector_size, SEEK_SET)
 
571
                != start * dev->sector_size)
 
572
                return 0;
 
573
 
 
574
        for (done = 0; done < count; done += status / dev->sector_size)
 
575
        {
 
576
                status = read (arch_specific->fd, buffer,
 
577
                               (size_t) ((count-done) * dev->sector_size));
 
578
                if (status < 0)
 
579
                        break;
 
580
        }
 
581
 
 
582
        return done;
 
583
}
 
584
 
 
585
static int
 
586
beos_sync (PedDevice* dev)
 
587
{
 
588
        return 1;
 
589
}
 
590
 
 
591
static int
 
592
beos_sync_fast (PedDevice* dev)
 
593
{
 
594
        return 1;
 
595
}
 
596
 
 
597
/* Probe for all available disks */
 
598
static void
 
599
beos_probe_all ()
 
600
{
 
601
        /* For BeOS/ZETA/Haiku, all disks are published under /dev/disk */
 
602
        _scan_for_disks("/dev/disk");
 
603
}
 
604
 
 
605
static char*
 
606
beos_partition_get_path (const PedPartition* part)
 
607
{
 
608
        return NULL;
 
609
}
 
610
 
 
611
static int
 
612
beos_partition_is_busy (const PedPartition* part)
 
613
{
 
614
        return 0;
 
615
}
 
616
 
 
617
static int
 
618
beos_disk_commit (PedDisk* disk)
 
619
{
 
620
        return 0;
 
621
}
 
622
 
 
623
static PedDeviceArchOps beos_dev_ops = {
 
624
        _new:           beos_new,
 
625
        destroy:        beos_destroy,
 
626
        is_busy:        beos_is_busy,
 
627
        open:           beos_open,
 
628
        refresh_open:   beos_refresh_open,
 
629
        close:          beos_close,
 
630
        refresh_close:  beos_refresh_close,
 
631
        read:           beos_read,
 
632
        write:          beos_write,
 
633
        check:          beos_check,
 
634
        sync:           beos_sync,
 
635
        sync_fast:      beos_sync_fast,
 
636
        probe_all:      beos_probe_all
 
637
};
 
638
 
 
639
static PedDiskArchOps beos_disk_ops =  {
 
640
        partition_get_path:     beos_partition_get_path,
 
641
        partition_is_busy:      beos_partition_is_busy,
 
642
        disk_commit:            beos_disk_commit
 
643
};
 
644
 
 
645
PedArchitecture ped_beos_arch = {
 
646
        dev_ops:        &beos_dev_ops,
 
647
        disk_ops:       &beos_disk_ops
 
648
};