2 libparted - a library for manipulating disk partitions
3 Copyright (C) 1999-2001, 2005, 2007, 2009-2011 Free Software Foundation,
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <parted/parted.h>
23 #include <parted/debug.h>
28 #include <hurd/store.h>
30 #include <sys/types.h>
35 # define _(String) dgettext (PACKAGE, String)
37 # define _(String) (String)
38 #endif /* ENABLE_NLS */
40 #include "../architecture.h"
42 #define GNU_SPECIFIC(dev) ((GNUSpecific*) (dev)->arch_specific)
44 typedef struct _GNUSpecific GNUSpecific;
51 /* Initialize a PedDevice using SOURCE. The SOURCE will NOT be destroyed;
52 the caller created it, it is the caller's responsilbility to free it
53 after it calls ped_device_destory. SOURCE is not registered in Parted's
55 PedDevice* ped_device_new_from_store (struct store *source);
58 _device_get_sector_size (PedDevice* dev)
60 GNUSpecific* arch_specific = GNU_SPECIFIC (dev);
61 size_t store_block_size = arch_specific->store->block_size;
63 return PED_SECTOR_SIZE_DEFAULT;
67 _device_get_length (PedDevice* dev)
69 GNUSpecific* arch_specific = GNU_SPECIFIC (dev);
70 size_t store_blocks = arch_specific->store->blocks;
71 size_t store_block_size = arch_specific->store->block_size;
73 return ((long long) store_blocks * store_block_size) / PED_SECTOR_SIZE_DEFAULT;
77 _device_probe_geometry (PedDevice* dev)
81 dev->length = _device_get_length (dev);
85 dev->sector_size = _device_get_sector_size (dev);
86 if (!dev->sector_size)
89 /* XXX: We have no way to get this! */
90 dev->bios_geom.sectors = 63;
91 dev->bios_geom.heads = 255;
92 cyl_size = dev->bios_geom.sectors * dev->bios_geom.heads;
93 dev->bios_geom.cylinders = dev->length / cyl_size
94 * (dev->sector_size / PED_SECTOR_SIZE_DEFAULT);
95 dev->hw_geom = dev->bios_geom;
101 init_file (PedDevice* dev)
103 PedExceptionOption ex_status;
106 if (!ped_device_open (dev)) {
107 ex_status = ped_exception_throw (
108 PED_EXCEPTION_WARNING,
109 PED_EXCEPTION_RETRY_CANCEL,
110 _("Unable to open %s."),
113 case PED_EXCEPTION_RETRY:
116 case PED_EXCEPTION_UNHANDLED:
117 ped_exception_catch ();
118 case PED_EXCEPTION_CANCEL:
126 if (!_device_probe_geometry (dev)) {
127 ex_status = ped_exception_throw (
128 PED_EXCEPTION_WARNING,
129 PED_EXCEPTION_RETRY_CANCEL,
130 _("Unable to probe store."));
132 case PED_EXCEPTION_RETRY:
135 case PED_EXCEPTION_UNHANDLED:
136 ped_exception_catch ();
137 case PED_EXCEPTION_CANCEL:
138 goto error_close_dev;
146 ped_device_close (dev);
150 ped_device_close (dev);
156 _flush_cache (PedDevice* dev)
158 GNUSpecific* arch_specific = GNU_SPECIFIC (dev);
163 /* Wait for a complete sync to finish. */
164 file_sync (arch_specific->store->source, 1, 0);
167 /* Initialize by allocating memory and filling in a few defaults, a
168 PedDevice structure. */
170 _init_device (const char *path)
173 GNUSpecific* arch_specific;
175 dev = (PedDevice*) ped_malloc (sizeof (PedDevice));
179 dev->path = strdup (path);
184 = (GNUSpecific*) ped_malloc (sizeof (GNUSpecific));
185 if (!dev->arch_specific)
186 goto error_free_path;
188 dev->type = PED_DEVICE_FILE; /* FIXME? */
191 dev->external_mode = 0;
197 error_free_arch_specific:
198 free (dev->arch_specific);
208 _kernel_reread_part_table (PedDevice* dev)
210 /* XXX: We must wait for partfs to be finished. */
214 /* Free the memory associated with a PedDevice structure. */
216 _done_device (PedDevice *dev)
218 free (dev->arch_specific);
223 /* Release all resources that libparted owns in DEV. */
225 gnu_destroy (PedDevice* dev)
227 GNUSpecific* arch_specific = GNU_SPECIFIC (dev);
229 if (arch_specific->consume)
230 store_free (arch_specific->store);
236 gnu_new (const char* path)
239 GNUSpecific* arch_specific;
240 error_t ro_err, rw_err;
243 PED_ASSERT (path != NULL);
245 dev = _init_device (path);
249 arch_specific = GNU_SPECIFIC (dev);
250 arch_specific->consume = 1;
253 /* Try read-write. */
254 if (strchr (dev->path, '/') != NULL) {
255 /* We set this to prevent having to use strchr more then once. */
258 rw_err = store_open (dev->path, 0, NULL, &arch_specific->store);
260 rw_err = store_typed_open (dev->path, 0, NULL, &arch_specific->store);
266 ro_err = store_open (dev->path, STORE_READONLY, NULL,
267 &arch_specific->store);
269 ro_err = store_typed_open (dev->path, STORE_READONLY, NULL,
270 &arch_specific->store);
274 if (ped_exception_throw (
276 PED_EXCEPTION_RETRY_CANCEL,
277 _("Error opening %s: %s"),
278 dev->path, strerror (ro_err))
279 != PED_EXCEPTION_RETRY) {
284 ped_exception_throw (
285 PED_EXCEPTION_WARNING,
287 _("Unable to open %s read-write (%s). %s has "
288 "been opened read-only."),
289 dev->path, strerror (rw_err), dev->path);
298 if (!init_file (dev)) {
307 ped_device_new_from_store (struct store *source)
310 GNUSpecific* arch_specific;
312 PED_ASSERT (source != NULL);
314 dev = _init_device (source->name ?: "(unknown)");
318 arch_specific = GNU_SPECIFIC (dev);
319 arch_specific->store = source;
320 arch_specific->consume = 0;
322 dev->read_only = source->flags & (STORE_READONLY|STORE_HARD_READONLY);
324 if (!init_file (dev)) {
333 gnu_is_busy (PedDevice* dev)
339 gnu_open (PedDevice* dev)
345 gnu_refresh_open (PedDevice* dev)
351 gnu_close (PedDevice* dev)
353 GNUSpecific* arch_specific = GNU_SPECIFIC (dev);
357 if (dev->dirty && dev->type != PED_DEVICE_FILE) {
358 if (_kernel_reread_part_table (dev))
363 if (dev->dirty && dev->boot_dirty && dev->type != PED_DEVICE_FILE) {
365 ped_exception_throw (
366 PED_EXCEPTION_WARNING,
368 _("The partition table cannot be re-read. This means "
369 "you need to reboot before mounting any "
370 "modified partitions. You also need to reinstall "
371 "your boot loader before you reboot (which may "
372 "require mounting modified partitions). It is "
373 "impossible do both things! So you'll need to "
374 "boot off a rescue disk, and reinstall your boot "
375 "loader from the rescue disk. Read section 4 of "
376 "the Parted User documentation for more "
381 if (dev->dirty && dev->type != PED_DEVICE_FILE) {
382 ped_exception_throw (
383 PED_EXCEPTION_WARNING,
384 PED_EXCEPTION_IGNORE,
385 _("The partition table on %s cannot be re-read "
386 "(%s). This means the Hurd knows nothing about any "
387 "modifications you made. You should reboot your "
388 "computer before doing anything with %s."),
389 dev->path, strerror (errno), dev->path);
392 if (dev->boot_dirty && dev->type != PED_DEVICE_FILE) {
393 ped_exception_throw (
394 PED_EXCEPTION_WARNING,
396 _("You should reinstall your boot loader before "
397 "rebooting. Read section 4 of the Parted User "
398 "documentation for more information."));
406 gnu_refresh_close (PedDevice* dev)
413 gnu_read (const PedDevice* dev, void* user_buffer, PedSector device_start,
416 GNUSpecific* arch_specific = GNU_SPECIFIC (dev);
418 PedExceptionOption ex_status;
420 size_t store_start_block;
421 /* In bytes. This can be larger than COUNT when store pages are
422 larger than PED_SECTOR_SIZE_DEFAULT. */
423 size_t store_read_length;
424 char local_buffer[PED_SECTOR_SIZE_DEFAULT];
425 void * store_read_buffer;
428 size_t device_read_length = count * PED_SECTOR_SIZE_DEFAULT;
430 start = device_start * PED_SECTOR_SIZE_DEFAULT;
431 if (PED_SECTOR_SIZE_DEFAULT != arch_specific->store->block_size) {
432 store_start_block = start / arch_specific->store->block_size;
433 store_read_length = (device_read_length
434 + arch_specific->store->block_size - 1)
435 / arch_specific->store->block_size;
437 store_start_block = device_start;
438 store_read_length = device_read_length;
442 - store_start_block * arch_specific->store->block_size;
444 if (store_read_length % arch_specific->store->block_size != 0)
445 store_read_length = store_read_length
446 + arch_specific->store->block_size
447 - store_read_length % arch_specific->store->block_size;
455 store_read_buffer = local_buffer;
456 did_read = sizeof (local_buffer);
458 err = store_read (arch_specific->store, store_start_block,
459 store_read_length - have_read,
460 &store_read_buffer, &did_read);
462 ex_status = ped_exception_throw (
464 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
465 _("%s during read on %s"),
470 case PED_EXCEPTION_IGNORE:
473 case PED_EXCEPTION_RETRY:
476 case PED_EXCEPTION_UNHANDLED:
477 ped_exception_catch ();
478 case PED_EXCEPTION_CANCEL:
483 memcpy (user_buffer + have_read - read_offset,
485 + (have_read >= read_offset
486 ? 0 : read_offset - have_read),
487 have_read + did_read > device_read_length + read_offset
488 ? device_read_length + read_offset - have_read
491 if (store_read_buffer != local_buffer)
492 vm_deallocate (mach_task_self (),
493 (long) store_read_buffer, did_read);
495 have_read += did_read;
496 store_start_block += did_read
497 / arch_specific->store->block_size;
499 if (have_read >= device_read_length)
507 gnu_write (PedDevice* dev, const void* buffer, PedSector start, PedSector count)
509 GNUSpecific* arch_specific = GNU_SPECIFIC (dev);
511 PedExceptionOption ex_status;
513 char local_buffer[PED_SECTOR_SIZE_DEFAULT];
517 /* Map a disk sector to a store sector. */
518 #define PED_TO_STORE(store, sector) (((sector) * PED_SECTOR_SIZE_DEFAULT) \
519 / (store)->block_size)
521 if (dev->read_only) {
522 if (ped_exception_throw (
524 PED_EXCEPTION_IGNORE_CANCEL,
525 _("Can't write to %s, because it is opened read-only."),
527 != PED_EXCEPTION_IGNORE)
534 printf ("ped_device_write (\"%s\", %p, %d, %d)\n",
535 dev->path, buffer, (int) start, (int) count);
539 /* If the first ``device'' block (PedSector) is not aligned on a
540 store block, then we need to fetch the old block, copy in the
541 overlaping area and finally, write the modified data out to the
543 if ((PED_SECTOR_SIZE_DEFAULT * start) % arch_specific->store->block_size
548 doggy_first_block_read:
549 /* We do not bother looping as we are only reading a
552 did_read = sizeof (local_buffer);
553 err = store_read (arch_specific->store,
554 PED_TO_STORE (arch_specific->store, start),
555 arch_specific->store->block_size, &temp,
557 if (! err && did_read != arch_specific->store->block_size)
561 ex_status = ped_exception_throw (
563 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
564 _("%s during read on %s"),
565 strerror (err), dev->path);
568 case PED_EXCEPTION_IGNORE:
571 case PED_EXCEPTION_RETRY:
572 goto doggy_first_block_read;
574 case PED_EXCEPTION_UNHANDLED:
575 ped_exception_catch ();
576 case PED_EXCEPTION_CANCEL:
581 write_offset = (start * PED_SECTOR_SIZE_DEFAULT)
582 % arch_specific->store->block_size;
583 flushing = arch_specific->store->block_size - write_offset;
584 if (flushing > count * PED_SECTOR_SIZE_DEFAULT)
585 flushing = count * PED_SECTOR_SIZE_DEFAULT;
587 memcpy (temp + write_offset, buffer, flushing);
589 doggy_first_block_write:
590 err = store_write (arch_specific->store,
591 PED_TO_STORE (arch_specific->store, start),
592 temp, arch_specific->store->block_size,
594 if (! err && did_write != arch_specific->store->block_size)
598 ex_status = ped_exception_throw (
600 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
601 _("%s during write on %s"),
602 strerror (err), dev->path);
605 case PED_EXCEPTION_IGNORE:
608 case PED_EXCEPTION_RETRY:
609 goto doggy_first_block_write;
611 case PED_EXCEPTION_UNHANDLED:
612 ped_exception_catch ();
613 case PED_EXCEPTION_CANCEL:
614 if (temp != local_buffer)
623 start += flushing / PED_SECTOR_SIZE_DEFAULT;
624 count -= flushing / PED_SECTOR_SIZE_DEFAULT;
625 buffer += write_offset;
627 if (temp != local_buffer)
628 vm_deallocate (mach_task_self (), (long) temp,
636 && count >= arch_specific->store->block_size / PED_SECTOR_SIZE_DEFAULT) {
637 err = store_write (arch_specific->store,
638 PED_TO_STORE (arch_specific->store, start),
639 buffer, count * PED_SECTOR_SIZE_DEFAULT,
643 ex_status = ped_exception_throw (
645 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
646 _("%s during write on %s"),
647 strerror (err), dev->path);
650 case PED_EXCEPTION_IGNORE:
653 case PED_EXCEPTION_RETRY:
656 case PED_EXCEPTION_UNHANDLED:
657 ped_exception_catch ();
658 case PED_EXCEPTION_CANCEL:
663 start += did_write / PED_SECTOR_SIZE_DEFAULT;
664 count -= did_write / PED_SECTOR_SIZE_DEFAULT;
671 /* We are now left with (strictly) less then a store block to write
672 to disk. Thus, we read the block, overlay the buffer and flush. */
673 PED_ASSERT (count * PED_SECTOR_SIZE_DEFAULT
674 < arch_specific->store->block_size);
676 doggy_last_block_read:
677 /* We do not bother looping as we are only reading a
680 did_read = sizeof (local_buffer);
681 err = store_read (arch_specific->store,
682 PED_TO_STORE (arch_specific->store, start),
683 arch_specific->store->block_size, &temp,
685 if (! err && did_read != arch_specific->store->block_size)
689 ex_status = ped_exception_throw (
691 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
692 _("%s during read on %s"),
693 strerror (err), dev->path);
696 case PED_EXCEPTION_IGNORE:
699 case PED_EXCEPTION_RETRY:
700 goto doggy_last_block_read;
702 case PED_EXCEPTION_UNHANDLED:
703 ped_exception_catch ();
704 case PED_EXCEPTION_CANCEL:
709 memcpy (temp, buffer, count * PED_SECTOR_SIZE_DEFAULT);
711 doggy_last_block_write:
712 err = store_write (arch_specific->store,
713 PED_TO_STORE (arch_specific->store, start),
714 temp, arch_specific->store->block_size,
716 if (! err && did_write != arch_specific->store->block_size)
720 ex_status = ped_exception_throw (
722 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
723 _("%s during write on %s"),
724 strerror (err), dev->path);
727 case PED_EXCEPTION_IGNORE:
730 case PED_EXCEPTION_RETRY:
731 goto doggy_last_block_write;
733 case PED_EXCEPTION_UNHANDLED:
734 ped_exception_catch ();
735 case PED_EXCEPTION_CANCEL:
736 if (temp != local_buffer)
737 vm_deallocate (mach_task_self (),
744 #endif /* !READ_ONLY */
748 /* TODO: returns the number of sectors that are ok.
751 gnu_check (PedDevice* dev, void* buffer, PedSector start, PedSector count)
756 PED_ASSERT (dev != NULL);
757 PED_ASSERT (!dev->external_mode);
758 PED_ASSERT (buffer != NULL);
764 gnu_sync (PedDevice* dev)
766 GNUSpecific* arch_specific;
768 PedExceptionOption ex_status;
769 static char *last_failure = NULL;
771 PED_ASSERT (dev != NULL);
772 PED_ASSERT (!dev->external_mode);
774 arch_specific = GNU_SPECIFIC (dev);
776 if (dev->read_only || ! dev->dirty)
780 err = file_sync (arch_specific->store->source, 1, 0);
781 if (! err || err == EOPNOTSUPP || err == EPERM
782 || (last_failure && strcmp (last_failure, dev->path) == 0))
785 ex_status = ped_exception_throw (
787 PED_EXCEPTION_RETRY_IGNORE_CANCEL,
788 _("%s trying to sync %s to disk"),
789 strerror (errno), dev->path);
792 case PED_EXCEPTION_IGNORE:
794 last_failure = strdup (dev->path);
797 case PED_EXCEPTION_RETRY:
800 case PED_EXCEPTION_UNHANDLED:
801 ped_exception_catch ();
802 case PED_EXCEPTION_CANCEL:
811 probe_standard_devices ()
813 _ped_device_probe ("/dev/sd0");
814 _ped_device_probe ("/dev/sd1");
815 _ped_device_probe ("/dev/sd2");
816 _ped_device_probe ("/dev/sd3");
817 _ped_device_probe ("/dev/sd4");
818 _ped_device_probe ("/dev/sd5");
820 _ped_device_probe ("/dev/hd0");
821 _ped_device_probe ("/dev/hd1");
822 _ped_device_probe ("/dev/hd2");
823 _ped_device_probe ("/dev/hd3");
824 _ped_device_probe ("/dev/hd4");
825 _ped_device_probe ("/dev/hd5");
826 _ped_device_probe ("/dev/hd6");
827 _ped_device_probe ("/dev/hd7");
835 probe_standard_devices ();
839 gnu_partition_get_path (const PedPartition* part)
841 const char* dev_path = part->disk->dev->path;
842 int result_len = strlen (dev_path) + 16;
845 result = (char*) ped_malloc (result_len);
848 snprintf (result, result_len, "%s%d", dev_path, part->num);
853 gnu_partition_is_busy (const PedPartition* part)
859 gnu_disk_commit (PedDisk* disk)
864 static PedDeviceArchOps gnu_dev_ops = {
866 destroy: gnu_destroy,
867 is_busy: gnu_is_busy,
869 refresh_open: gnu_refresh_open,
871 refresh_close: gnu_refresh_close,
877 probe_all: gnu_probe_all
880 static PedDiskArchOps gnu_disk_ops = {
881 partition_get_path: gnu_partition_get_path,
882 partition_is_busy: gnu_partition_is_busy,
883 disk_commit: gnu_disk_commit
886 PedArchitecture ped_gnu_arch = {
887 dev_ops: &gnu_dev_ops,
888 disk_ops: &gnu_disk_ops