Anonymous avatar Anonymous committed e91a781

Create string list choice. Fix some bugs. Change base.c/base.h to common.h/common.c. They might be considered finalized? (fdisk@sv.gnu.org/fdisk--main--0--patch-9)
fdisk@sv.gnu.org/fdisk--main--0--patch-9
Keywords:

Comments (0)

Files changed (5)

src/base.c

-/*
-    GNU fdisk - a clone of Linux fdisk.
-
-    Copyright (C) 2006
-    Free Software Foundation, Inc.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
-*/
-
-#include "../config.h"
-
-/*#include "command.h"*/
-/*#include "ui.h"*/
-
-#include "strlist.h"
-
-#define N_(String) String
-#if ENABLE_NLS
-#  include <libintl.h>
-#  include <locale.h>
-#  define _(String) dgettext (PACKAGE, String)
-#else
-#  define _(String) (String)
-#endif /* ENABLE_NLS */
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "base.h"
-
-
-#define SMALLBUF 128
-
-static int MEGABYTE_SECTORS (PedDevice* dev)
-{
-        return PED_MEGABYTE_SIZE / dev->sector_size;
-}
-
-struct bsdlabel {
-  unsigned int magic;
-  char unused[128];
-  unsigned int magic2;
-};
-
-typedef struct {
-	time_t	last_update;
-	time_t	predicted_time_left;
-} TimerContext;
-
-
-/* TODO: Decide if these should be moved to UICalls */
-StrList *disk_type_list;
-StrList *fs_type_list;
-
-int
-init_fs_type_str ()
-{
-	PedFileSystemType*	walk;
-
-	fs_type_list = NULL;
-
-	for (walk = ped_file_system_type_get_next (NULL); walk;
-	     walk = ped_file_system_type_get_next (walk))
-	{
-		fs_type_list = str_list_insert (fs_type_list, walk->name);
-		if (!fs_type_list)
-			return 0;
-	}
-
-	return 1;
-}
-
-int
-init_disk_type_str ()
-{
-	PedDiskType*	walk;
-
-	disk_type_list = NULL;
-
-	for (walk = ped_disk_type_get_next (NULL); walk;
-	     walk = ped_disk_type_get_next (walk))
-	{
-		disk_type_list = str_list_insert (disk_type_list, walk->name);
-		if (!disk_type_list)
-			return 0;
-	}
-
-	return 1;
-}
-
-
-static int
-_can_create_primary (const PedDisk* disk)
-{
-	int	i;
-
-	for (i = 1; i <= ped_disk_get_max_primary_partition_count (disk); i++) {
-		if (!ped_disk_get_partition (disk, i))
-			return 1;
-	}
-
-	return 0;
-}
-
-static int
-_can_create_extended (const PedDisk* disk)
-{
-	if (!_can_create_primary (disk))
-		return 0;
-	if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED))
-		return 0;
-	if (ped_disk_extended_partition (disk))
-		return 0;
-	return 1;
-}
-
-static int
-_can_create_logical (const PedDisk* disk)
-{
-	if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED))
-		return 0;
-	return ped_disk_extended_partition (disk) != 0;
-}
-
-
-/* Copied verbatim from parted upto help_on*/
-
-static int
-_partition_warn_busy (PedPartition* part)
-{
-	char* path = ped_partition_get_path (part);
-
-	if (ped_partition_is_busy (part)) {
-		ped_exception_throw (
-			PED_EXCEPTION_ERROR,
-			PED_EXCEPTION_CANCEL,
-			_("Partition %s is being used.  You must unmount it "
-			  "before you modify it with Parted."),
-			path);
-		ped_free (path);
-		return 0;
-	}
-	ped_free (path);
-	return 1;
-}
-
-static int
-_disk_warn_busy (PedDisk* disk)
-{
-	if (ped_device_is_busy (disk->dev)) {
-		if (ped_exception_throw (
-			PED_EXCEPTION_WARNING,
-			PED_EXCEPTION_IGNORE_CANCEL,
-			_("Partition(s) on %s are being used."),
-			disk->dev->path)
-				!= PED_EXCEPTION_IGNORE)
-			return 0;
-	}
-	return 1;
-}
-
-/* This function changes "sector" to "new_sector" if the new value lies
- * within the required range.
- */
-static int
-snap (PedSector* sector, PedSector new_sector, PedGeometry* range)
-{
-        PED_ASSERT (ped_geometry_test_sector_inside (range, *sector), return 0);
-        if (!ped_geometry_test_sector_inside (range, new_sector))
-                return 0;
-        *sector = new_sector;
-        return 1;
-}
-
-typedef enum {
-        MOVE_NO         = 0,
-        MOVE_STILL      = 1,
-        MOVE_UP         = 2,
-        MOVE_DOWN       = 4
-} EMoves;
-
-enum { /* Don't change these values */
-        SECT_START      =  0,
-        SECT_END        = -1
-};
-
-/* Find the prefered way to adjust the sector s inside range.
- * If a move isn't allowed or is out of range it can't be selected.
- * what contains SECT_START if the sector to adjust is a start sector
- * or SECT_END if it's an end one.
- * The prefered move is to the nearest allowed boundary of the part
- * partition (if at equal distance: to start if SECT_START or to end
- * if SECT_END).
- * The distance is returned in dist.
- */
-static EMoves
-prefer_snap (PedSector s, int what, PedGeometry* range, EMoves* allow,
-             PedPartition* part, PedSector* dist)
-{
-        PedSector up_dist = -1, down_dist = -1;
-        PedSector new_sect;
-        EMoves move;
-
-        PED_ASSERT (what == SECT_START || what == SECT_END, return 0);
-
-        if (!(*allow & (MOVE_UP | MOVE_DOWN))) {
-                *dist = 0;
-                return MOVE_STILL;
-        }
-
-        if (*allow & MOVE_UP) {
-                new_sect = part->geom.end + 1 + what;
-                if (ped_geometry_test_sector_inside (range, new_sect))
-                        up_dist = new_sect - s;
-                else
-                        *allow &= ~MOVE_UP;
-        }
-
-        if (*allow & MOVE_DOWN) {
-                new_sect = part->geom.start + what;
-                if (ped_geometry_test_sector_inside (range, new_sect))
-                        down_dist = s - new_sect;
-                else
-                        *allow &= ~MOVE_DOWN;
-        }
-
-        move = MOVE_STILL;
-        if ((*allow & MOVE_UP) && (*allow & MOVE_DOWN)) {
-                if (down_dist < up_dist || (down_dist == up_dist
-                                            && what == SECT_START) )
-                        move = MOVE_DOWN;
-                else if (up_dist < down_dist || (down_dist == up_dist
-                                                 && what == SECT_END) )
-                        move = MOVE_UP;
-                else
-                        PED_ASSERT (0, return 0);
-        } else if (*allow & MOVE_UP)
-                move = MOVE_UP;
-        else if (*allow & MOVE_DOWN)
-                move = MOVE_DOWN;
-
-        *dist = ( move == MOVE_DOWN ? down_dist :
-                ( move == MOVE_UP   ? up_dist   :
-                  0 ) );
-        return move;
-}
-
-/* Snaps a partition to nearby partition boundaries.  This is useful for
- * gobbling up small amounts of free space, and also for reinterpreting small
- * changes to a partition as non-changes (eg: perhaps the user only wanted to
- * resize the end of a partition).
- *      Note that this isn't the end of the story... this function is
- * always called before the constraint solver kicks in.  So you don't need to
- * worry too much about inadvertantly creating overlapping partitions, etc.
- */
-static void
-snap_to_boundaries (PedGeometry* new_geom, PedGeometry* old_geom,
-                    PedDisk* disk,
-                    PedGeometry* start_range, PedGeometry* end_range)
-{
-        PedPartition*   start_part;
-        PedPartition*   end_part;
-        PedSector       start = new_geom->start;
-        PedSector       end = new_geom->end;
-        PedSector       start_dist = -1, end_dist = -1;
-        EMoves          start_allow, end_allow, start_want, end_want;
-        int             adjacent;
-
-        start_want = end_want = MOVE_NO;
-        start_allow = end_allow = MOVE_STILL | MOVE_UP | MOVE_DOWN;
-
-        start_part = ped_disk_get_partition_by_sector (disk, start);
-        end_part = ped_disk_get_partition_by_sector (disk, end);
-        adjacent = (start_part->geom.end + 1 == end_part->geom.start);
-
-        /* If we can snap to old_geom, then we will... */
-        /* and this will enforce the snapped positions  */
-        if (old_geom) {
-                if (snap (&start, old_geom->start, start_range))
-                        start_allow = MOVE_STILL;
-                if (snap (&end, old_geom->end, end_range))
-                        end_allow = MOVE_STILL;
-        }
-
-        /* If start and end are on the same partition, we */
-        /* don't allow them to cross. */
-        if (start_part == end_part) {
-                start_allow &= ~MOVE_UP;
-                end_allow &= ~MOVE_DOWN;
-        }
-
-        /* Let's find our way */
-        start_want = prefer_snap (start, SECT_START, start_range, &start_allow,
-                                  start_part, &start_dist );
-        end_want = prefer_snap (end, SECT_END, end_range, &end_allow,
-                                end_part, &end_dist );
-
-        PED_ASSERT (start_dist >= 0 && end_dist >= 0, return);
-
-        /* If start and end are on adjacent partitions,    */
-        /* and if they would prefer crossing, then refrain */
-        /* the farthest to do so. */
-        if (adjacent && start_want == MOVE_UP && end_want == MOVE_DOWN) {
-                if (end_dist < start_dist) {
-                        start_allow &= ~MOVE_UP;
-                        start_want = prefer_snap (start, SECT_START,
-                                                  start_range, &start_allow,
-                                                  start_part, &start_dist );
-                        PED_ASSERT (start_dist >= 0, return);
-                } else {
-                        end_allow &= ~MOVE_DOWN;
-                        end_want = prefer_snap (end, SECT_END,
-                                                end_range, &end_allow,
-                                                end_part, &end_dist );
-                        PED_ASSERT (end_dist >= 0, return);
-                }
-        }
-
-        /* New positions */
-        start = ( start_want == MOVE_DOWN ? start_part->geom.start :
-                ( start_want == MOVE_UP ? start_part->geom.end + 1 :
-                  start ) );
-        end = ( end_want == MOVE_DOWN ? end_part->geom.start - 1 :
-              ( end_want == MOVE_UP ? end_part->geom.end :
-                end ) );
-        PED_ASSERT (ped_geometry_test_sector_inside(start_range,start), return);
-        PED_ASSERT (ped_geometry_test_sector_inside (end_range, end), return);
-        PED_ASSERT (start <= end,
-                    PED_DEBUG (0, "start = %d, end = %d\n", start, end));
-        ped_geometry_set (new_geom, start, end - start + 1);
-}
-
-/* This functions constructs a constraint from the following information:
- *      start, is_start_exact, end, is_end_exact.
- *      
- * If is_start_exact == 1, then the constraint requires start be as given in
- * "start".  Otherwise, the constraint does not set any requirements on the
- * start.
- */
-static PedConstraint*
-constraint_from_start_end (PedDevice* dev, PedGeometry* range_start,
-                           PedGeometry* range_end)
-{
-        return ped_constraint_new (ped_alignment_any, ped_alignment_any,
-                range_start, range_end, 1, dev->length);
-}
-
-static PedConstraint*
-constraint_intersect_and_destroy (PedConstraint* a, PedConstraint* b)
-{
-        PedConstraint* result = ped_constraint_intersect (a, b);
-        ped_constraint_destroy (a);
-        ped_constraint_destroy (b);
-        return result;
-}
-
-
-
-static int
-get_device(const char* prompt, PedDevice** value, const UICalls *uiquery)
-{
-	char*		dev_name = *value ? (*value)->path : NULL;
-	PedDevice*	dev;
-	if (!uiquery->getdev) {
-		if (!uiquery->getstring (prompt, &dev_name, NULL, NULL, 1))
-			return 0;
-		if (!dev_name)
-			return 0;
-		dev = ped_device_get (dev_name);
-		free (dev_name);
-		if (!dev)
-			return 0;
-	}
-	else {
-		if (!uiquery->getdev(prompt, &dev))
-			return 0;
-	}
-	*value = dev;
-	return 1;
-}
-
-static int
-get_disk (const char* prompt, PedDisk** value, const UICalls *uiquery)
-{
-	PedDevice*	dev = *value ? (*value)->dev : NULL;
-	if (!get_device(prompt, &dev, uiquery))
-		return 0;
-	if (dev != (*value)->dev) {
-		PedDisk* new_disk = ped_disk_new (dev);
-		if (!new_disk)
-			return 0;
-		*value = new_disk;
-	}
-	return 1;
-}
-
-/* These two use a different aproach, it leads to a little lack of consistency, but
- * this enables the use of a shiny interface in the UI */
-
-static int
-get_partition (const char* prompt, PedDisk* disk, PedPartition** value, UICalls *uiquery)
-{
-	PedPartition*	part;
-	int		num; 
-	char		buf[SMALLBUF];
-	if (!disk) 
-		return 0;
-	if (!uiquery->getpart) {
-		snprintf(buf,SMALLBUF,_("%s number"),prompt);
-		num = (*value) ? (*value)->num : 0;
-		if (!uiquery->getint (buf, &num)) {
-			ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
-					     _("Expecting a partition number."));
-			return 0;
-		}
-		part = ped_disk_get_partition (disk, num);
-		if (!part) {
-			ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
-					     _("Partition doesn't exist."));
-			return 0;
-		}
-		*value = part;
-	} else {
-		if (!uiquery->getpart(prompt, &disk, &part))
-			return 0;
-		*value = part;
-	}
-	return 1;
-}
-
-static int
-get_disk_type (const char* prompt, const PedDiskType** value, UICalls *uiquery)
-{
-	char*		disk_type_name;
-	PedDiskType*	disk_type;
-	int n;
-	if (!uiquery->getdisktype) {
-		if (*value) {
-			n = strlen((*value)->name);
-			disk_type_name = (char *) calloc(n,sizeof(char));
-			strncpy(disk_type_name,(*value)->name, n);
-		}
-		if (!uiquery->getstring (prompt, &disk_type_name, disk_type_list, NULL, -1))
-			return 0;
-		if (!disk_type_name) {
-			ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
-				     	_("Expecting a disk label type."));
-			return 0;
-		}
-		*value = ped_disk_type_get (disk_type_name);
-		free (disk_type_name);
-		
-	} else {
-		if (!uiquery->getdisktype(prompt, &disk_type)) return 0;
-		*value = disk_type;
-	}
-	PED_ASSERT (*value != NULL, return 0);
-	return 1;
-}
-
-
-static int
-get_part_type (const char* prompt, const PedDisk* disk, PedPartitionType* type, UICalls *uiquery)
-{
-	StrList*	opts = NULL;
-	StrList*	locopts = NULL;
-	char*		type_name;
-	int		status;
-
-	if (_can_create_primary (disk)) {
-		opts = str_list_append_unique (opts, "primary");
-		locopts = str_list_append_unique (opts, _("primary"));
-	}
-	if (_can_create_extended (disk)) {
-		opts = str_list_append_unique (opts, "extended");
-		locopts = str_list_append_unique (opts, _("extended"));
-	}
-	if (_can_create_logical (disk)) {
-		opts = str_list_append_unique (opts, "logical");
-		locopts = str_list_append_unique (opts, _("logical"));
-	}
-	if (!opts) {
-		ped_exception_throw (
-			PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
-			_("Can't create any more partitions."));
-		return 0;
-	}
-
-	status = uiquery->getstring(prompt,&type_name,opts,locopts,-1);
-	
-	str_list_destroy (opts);
-	str_list_destroy (locopts);
-	if (!status) {
-		if(type_name) free(type_name);
-		return 0;
-	}
-
-
-	if (!type_name) {
-		ped_exception_throw (
-			PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
-			_("Expecting a partition type."));
-		return 0;
-	}
-
-	if (!strcmp (type_name, "primary")
-			|| !strcmp (type_name, _("primary"))) {
-		*type = 0;
-	}
-	if (!strcmp (type_name, "extended")
-			|| !strcmp (type_name, _("extended"))) {
-		*type = PED_PARTITION_EXTENDED;
-	}
-	if (!strcmp (type_name, "logical")
-			|| !strcmp (type_name, _("logical"))) {
-		*type = PED_PARTITION_LOGICAL;
-	}
-
-	free (type_name);
-	return 1;
-}
-
-static int
-get_fs_type (const char* prompt, const PedFileSystemType **value, UICalls *uiquery)
-{
-
-
-	char*			fs_type_name;
-	PedFileSystemType*	fs_type;
-	int			n;
-	if (!uiquery->getfstype) {
-		if(*value) {
-			n = strlen((*value)->name);
-			fs_type_name = (char *) calloc(n,sizeof(char));
-			strncpy(fs_type_name,(*value)->name,n);
-		}
-		if (!uiquery->getstring(prompt,&fs_type_name,fs_type_list,NULL,-1))
-			return 0;
-		if (!fs_type_name) {
-			ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
-					     _("Expecting a file system type."));
-			return 0;
-		}
-		fs_type = ped_file_system_type_get (fs_type_name);
-		if (!fs_type) {
-			ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
-					     _("Unknown file system type \"%s\"."),
-					     fs_type_name);
-			return 0;
-		}
-		free (fs_type_name);
-		*value = fs_type;
-	}
-	else {
-		if (!uiquery->getfstype(prompt, &fs_type)) return 0;
-		*value = fs_type;
-	}
-	return 1;
-}
-
-
-
-static int
-get_sector (const char* prompt, PedDevice* dev, PedSector* value,
-			 PedGeometry** range,  int custom, UICalls *uiquery)
-{
-	char*	def_str;
-	char*	input;
-	int	valid,n;
-	/* FIXME: Check this more thoroughfully */
-
-	if (!custom && *value) {
-		if (range) {
-			*range = ped_geometry_new(dev,*value,1);
-			return *range != NULL;
-		}
-		return 1;
-	}
-
-	def_str = ped_unit_format (dev, *value);
-	if (*value) {
-		n = strlen(def_str);
-		input = (char *) calloc(n,sizeof(char));
-		strncpy(input,def_str,n);
-	}
-	if (custom || !input) {
-		uiquery->getstring(prompt,&input,NULL,NULL,1);
-	}
-
-	/* def_str might have rounded *value a little bit.  If the user picked
-	 * the default, make sure the selected sector is identical to the
-	 * default.
-	 */
-	if (input && *value && !strcmp (input, def_str)) {
-		if (range) {
-			*range = ped_geometry_new (dev, *value, 1);
-			ped_free (def_str);
-			return *range != NULL;
-		}
-
-		ped_free (def_str);
-		return 1;
-	}
-
-	ped_free (def_str);
-	if (!input) {
-		*value = 0;
-		if (range)
-			*range = NULL;
-		return 0;
-	}
-
-	valid = ped_unit_parse (input, dev, value, range);
-
-	free (input);
-	return valid;
-}
-
-static int
-ask_boolean_question(const char* prompt, UICalls *uiquery) {
-	int answer = 0;
-	uiquery->getbool(prompt,&answer);
-	return answer;
-}
-
-/* Check partition consistency */
-int
-do_check (PedDisk* disk, PedPartition* part, UICalls *uiquery)
-{
-        PedFileSystem*  fs;
-	if (!part) {
-		if (!get_partition (_("Partition"),disk, &part, uiquery))
-			goto error;
-	}
-        if (!_partition_warn_busy (part))
-                goto error;
-
-        if (!ped_disk_check (disk))
-                goto error;
-
-        fs = ped_file_system_open (&part->geom);
-        if (!fs)
-                goto error;
-        if (!ped_file_system_check (fs, uiquery->timer))
-                goto error_close_fs;
-        ped_file_system_close (fs);
-        return 1;
-error_close_fs:
-        ped_file_system_close (fs);
-error:
-        return 0;
-}
-
-/* Copy a partition.
-   The parameters specify the destination partition.
-   The source partition is get using a callback function prompt.
-   Writes partition table to disk */
-/* If warn is set to 1, warns the user TODO: get rid of warn */
-int
-do_cp (PedDisk* dst_disk, PedPartition* dst, int warn, UICalls *uiquery)
-{
-        PedDisk*                src_disk;
-        PedDevice*              src_device;
-        PedPartition*           src = NULL;
-        PedFileSystem*          src_fs;
-        PedFileSystem*          dst_fs;
-        PedFileSystemType*      dst_fs_type;
-	if (warn)
-		if (!ask_boolean_question 
-		(_("WARNING: This writes all data to disk automatically, continue?"),uiquery)) 
-			return 1;
-
-        if (!dst_disk)
-                goto error;
-
-        src_disk = dst_disk;
-	if (get_disk (_("Source device"), &src_disk, uiquery))
-		goto error_destroy_disk;
-        
-
-        if (!get_partition (_("Source partition"),src_disk, &src, uiquery))
-                goto error_destroy_disk;
-        if (src->type == PED_PARTITION_EXTENDED) {
-                ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
-                        _("Can't copy an extended partition."));
-                goto error_destroy_disk;
-        }
-        if (!_partition_warn_busy (src))
-                goto error_destroy_disk;
-	if (!dst) {
-		if (!get_partition (_("Destination partition"),dst_disk, &dst, uiquery))
-			goto error_destroy_disk;
-	}
-        if (!_partition_warn_busy (dst))
-                goto error_destroy_disk;
-
-/* do the copy */
-        src_fs = ped_file_system_open (&src->geom);
-        if (!src_fs)
-                goto error_destroy_disk;
-        dst_fs = ped_file_system_copy (src_fs, &dst->geom, uiquery->timer);
-        if (!dst_fs)
-                goto error_close_src_fs;
-        dst_fs_type = dst_fs->type;     /* may be different to src_fs->type */
-        ped_file_system_close (src_fs);
-        ped_file_system_close (dst_fs);
-
-/* update the partition table, close disks */
-        if (!ped_partition_set_system (dst, dst_fs_type))
-                goto error_destroy_disk;
-        if (!ped_disk_commit (dst_disk)) {
-		//if (uiquery->need_commit) uiquery->need_commit = -1;
-                goto error_destroy_disk;
-	}
-	uiquery->need_commit = 0;
-        if (src_disk != dst_disk)
-                ped_disk_destroy (src_disk);
-        /*ped_disk_destroy (dst_disk);*/
-        return 1;
-
-error_close_src_fs:
-        ped_file_system_close (src_fs);
-error_destroy_disk:
-        if (src_disk && src_disk != dst_disk)
-                ped_disk_destroy (src_disk);
-        /*ped_disk_destroy (dst_disk);*/
-error:
-        return 0;
-}
-
-/* Create a new partition table. Takes dev and disk as parameters,
-   in addition it takes a label type, if NULL, queries... */
-
-int
-do_mklabel (PedDevice* dev, PedDisk** disk, const PedDiskType* type, UICalls *uiquery)
-{
-
-        ped_exception_fetch_all ();
-
-        if (!*disk) ped_exception_catch ();
-        ped_exception_leave_all ();
-
-        if (*disk) {
-                if (!_disk_warn_busy (*disk)) {
-                        ped_disk_destroy (*disk);
-                        goto error;
-                }
-                ped_disk_destroy (*disk);
-        }
-	if (!type) {
-        	if (!get_disk_type (_("New disk label type"), &type, uiquery))
-                	goto error;
-	}
-
-        *disk = ped_disk_new_fresh (dev, type);
-        if (!*disk)
-                goto error;
-	
-        /*if (!ped_disk_commit (*disk))
-                goto error;*/
-	uiquery->need_commit = 1;
-        return 1;
-
-error:
-        return 0;
-}
-
-/* Create a filesystem. Takes filesystem type as an optional parameter */
-/* If warn is set to 1, warns the user TODO: get rid of warn */
-int
-do_mkfs (PedDisk* disk, PedPartition* part, const PedFileSystemType* type, int warn, UICalls *uiquery)
-{
-
-        PedFileSystem*          fs;
-	if (warn) {
-		if (!ask_boolean_question 
-		(_("WARNING: This writes all data to disk automatically, continue?"),uiquery)) 
-			return 1;
-	}
-
-        if (!disk)
-                goto error;
-	if (!part) {
-		if (!get_partition (_("Partition"),disk, &part, uiquery))
-			goto error;
-	}
-        if (!_partition_warn_busy (part))
-                goto error;
-	if (!type) {
-        	if (!get_fs_type (_("File system"), &type, uiquery))
-	                goto error;
-	}
-
-
-        fs = ped_file_system_create (&part->geom, type, uiquery->timer);
-        if (!fs)
-                goto error;
-        ped_file_system_close (fs);
-
-        if (!ped_partition_set_system (part, type))
-                goto error;
-        if (ped_partition_is_flag_available (part, PED_PARTITION_LBA))
-                ped_partition_set_flag (part, PED_PARTITION_LBA, 1);
-        if (!ped_disk_commit (disk)) {
-		//if (uiquery->need_commit) uiquery->need_commit = -1;
-                goto error;
-	}
-	uiquery->need_commit = 0;
-        return 1;
-
-
-error:
-        return 0;
-}
-
-/* The parameter custom is 1, then the user is asked about the start and end sector *
- * If the parameter newpart is not NULL, it is set to the newly created partition */
-int
-do_mkpart (PedDisk* disk, PedSector start, PedSector end, int custom, PedPartitionType part_type,
-	const PedFileSystemType* fs_type, PedPartition **newpart, UICalls *uiquery)
-{
-	PedGeometry		*range_start = NULL, *range_end = NULL;
-        PedPartition*            part;
-        /*PedSector                start = 0, end = 0;*/
-        PedConstraint*           user_constraint;
-        PedConstraint*           dev_constraint;
-        PedConstraint*           final_constraint;
-        char*                    peek_word;
-        char*                    part_name = NULL;
-        char                     *start_usr = NULL, *end_usr = NULL;
-        char                     *start_sol = NULL, *end_sol = NULL;
-        
-        if (!disk)
-                goto error;
-
-        if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) {
-		if (part_type && part_type != PED_PARTITION_NORMAL)
-			goto error;
-                part_type = PED_PARTITION_NORMAL;
-        } else if (!part_type) {
-                if (!get_part_type (_("Partition type"), disk, &part_type, uiquery))
-                        goto error;
-        }
-
-                
-        /*peek_word = command_line_peek_word ();*/
-        if (part_type == PED_PARTITION_EXTENDED) {
-            /*|| (peek_word && isdigit (peek_word[0]))) {*/
-                fs_type = NULL;
-        } else if (!fs_type) {
-                if (!get_fs_type (_("File system type?"), &fs_type, uiquery))
-                        goto error;
-        }
-        /*if (peek_word)
-                ped_free (peek_word);*/
-
-        if (ped_disk_type_check_feature (disk->type,
-                                         PED_DISK_TYPE_PARTITION_NAME)) 
-                uiquery->getstring(_("Partition name"), &part_name, NULL, NULL, 1); 
-
-        if (!get_sector (_("Start?"), disk->dev, &start, &range_start, custom, uiquery))
-                goto error;
-        if (!get_sector (_("End?"), disk->dev, &end, &range_end, custom, uiquery))
-                goto error;
-        
-        /* processing starts here */
-        part = ped_partition_new (disk, part_type, fs_type, start, end);
-        if (!part)
-                goto error;
-
-        snap_to_boundaries (&part->geom, NULL, disk, range_start, range_end);
-
-        /* create constraints */
-        user_constraint = constraint_from_start_end (disk->dev, range_start,
-                        range_end);
-        PED_ASSERT (user_constraint != NULL, return 0);
-
-        dev_constraint = ped_device_get_constraint (disk->dev);
-        PED_ASSERT (dev_constraint != NULL, return 0);
-
-        final_constraint = ped_constraint_intersect (user_constraint,
-                        dev_constraint);
-        if (!final_constraint)
-                goto error_destroy_simple_constraints;
-
-        /* subject to partition constraint */
-        ped_exception_fetch_all();
-        if (!ped_disk_add_partition (disk, part, final_constraint)) {
-                ped_exception_leave_all();
-               
-                if (ped_disk_add_partition (disk, part,
-                                        ped_constraint_any (disk->dev))) {
-                        start_usr = ped_unit_format (disk->dev, start);
-                        end_usr   = ped_unit_format (disk->dev, end);
-                        start_sol = ped_unit_format (disk->dev, part->geom.start);
-                        end_sol   = ped_unit_format (disk->dev, part->geom.end);
-
-                        switch (ped_exception_throw (
-                                PED_EXCEPTION_WARNING,
-                                PED_EXCEPTION_YES_NO,
-                                _("You requested a partition from %s to %s.\n"
-                                  "The closest location we can manage is "
-                                  "%s to %s.  "
-                                  "Is this still acceptable to you?"),
-                                start_usr, end_usr, start_sol, end_sol))
-                        {
-                                case PED_EXCEPTION_YES:
-                                        /* all is well in this state */
-                                        break;
-                                case PED_EXCEPTION_NO:
-                                case PED_EXCEPTION_UNHANDLED:
-                                default:
-                                        /* undo partition addition */
-                                        goto error_remove_part;
-                        }
-                } else {
-                        goto error_remove_part;
-                }
-        }
-        ped_exception_catch();
-
-        /* set minor attributes */
-        if (part_name)
-                PED_ASSERT (ped_partition_set_name (part, part_name), return 0);
-        if (!ped_partition_set_system (part, fs_type))
-                goto error;
-        if (ped_partition_is_flag_available (part, PED_PARTITION_LBA))
-                ped_partition_set_flag (part, PED_PARTITION_LBA, 1);
-        
-        /*if (!ped_disk_commit (disk))
-                goto error;*/
-	uiquery->need_commit = 1;
-        
-        /* clean up */
-        ped_constraint_destroy (final_constraint);
-        ped_constraint_destroy (user_constraint);
-        ped_constraint_destroy (dev_constraint);
-
-        
-        if (range_start != NULL)
-                ped_geometry_destroy (range_start);
-        if (range_end != NULL)
-                ped_geometry_destroy (range_end);
-        
-        if (start_usr != NULL)
-                ped_free (start_usr);
-        if (end_usr != NULL)
-                ped_free (end_usr);
-        if (start_sol != NULL)
-                ped_free (start_sol);
-        if (end_sol != NULL)
-                ped_free (end_sol);
-	if (newpart) *newpart = part;
-        return 1;
-
-error_remove_part:
-        ped_disk_remove_partition (disk, part);
-error_destroy_all_constraints:
-        ped_constraint_destroy (final_constraint);
-error_destroy_simple_constraints:
-        ped_constraint_destroy (user_constraint);
-        ped_constraint_destroy (dev_constraint);
-error_destroy_part:
-        ped_partition_destroy (part);
-error:
-        if (range_start != NULL)
-                ped_geometry_destroy (range_start);
-        if (range_end != NULL)
-                ped_geometry_destroy (range_end);
-
-        if (start_usr != NULL)
-                ped_free (start_usr);
-        if (end_usr != NULL)
-                ped_free (end_usr);
-        if (start_sol != NULL)
-                ped_free (start_sol);
-        if (end_sol != NULL)
-                ped_free (end_sol);
-
-        return 0;
-}
-/* TODO: get rid of warn */
-int
-do_mkpartfs (PedDisk* disk, PedSector start, PedSector end, int custom, PedPartitionType part_type,
-	const PedFileSystemType* fs_type, PedPartition **newpart, int warn, UICalls *uiquery)
-{
-
-        PedPartition*            part;
-
-        
-        if (!disk)
-                return 0;
-
-	if (warn) {
-		if (!ask_boolean_question 
-		(_("WARNING: This writes all data to disk automatically, continue?"),uiquery)) 
-			return 1;
-	}
-
-        if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) {
-		if (part_type && part_type != PED_PARTITION_NORMAL)
-			return 0;
-                part_type = PED_PARTITION_NORMAL;
-        } else if (!part_type) {
-                if (!get_part_type (_("Partition type"), disk, &part_type, uiquery))
-                        return 0;
-        }
-
-        if (part_type == PED_PARTITION_EXTENDED) {
-                ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
-                        _("An extended partition cannot hold a file system."));
-                return 0;
-        }
-
-        if (!fs_type) {
-                if (!get_fs_type (_("File system type?"), &fs_type, uiquery))
-                        return 0;
-        }
-	if (!do_mkpart(disk,start,end,custom,part_type,fs_type,&part,uiquery))
-		return 0;
-	if (!do_mkfs(disk,part,fs_type,0,uiquery))
-		return 0;
-	if (newpart) *newpart = part;
-	return 1;
-
-
-}
-
-/* TODO: get rid of warn */
-static int
-do_move (PedDisk *disk, PedPartition *part, PedSector start, PedSector end, int custom, int warn, UICalls *uiquery)
-{
-       
-        PedFileSystem*  fs;
-        PedFileSystem*  fs_copy;
-        PedConstraint*  constraint;
-        /*PedSector       start = 0, end = 0;*/
-        PedGeometry     *range_start = NULL, *range_end = NULL;
-        PedGeometry     old_geom, new_geom;
-
-
-        if (!disk)
-                goto error;
-
-	if (warn) {
-		if (!ask_boolean_question 
-		(_("WARNING: This writes all data to disk automatically, continue?"),uiquery)) 
-			return 1;
-	}
-
-	if (!part)
-        	if (!get_partition (_("Partition"), disk, &part, uiquery))
-                	goto error;
-        if (!_partition_warn_busy (part))
-                goto error;
-        if (part->type == PED_PARTITION_EXTENDED) {
-                ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
-                        _("Can't move an extended partition."));
-                goto error;
-        }
-        old_geom = part->geom;
-        fs = ped_file_system_open (&old_geom);
-        if (!fs)
-                goto error;
-
-        /* get new target */
-        if (!get_sector (_("Start?"), disk->dev, &start, &range_start, custom, uiquery))
-                goto error_close_fs;
-        end = start + old_geom.length - 1;
-        if (!get_sector (_("End?"), disk->dev, &end, &range_end, custom, uiquery))
-                goto error_close_fs;
-
-        /* set / test on "disk" */
-        if (!ped_geometry_init (&new_geom, disk->dev, start, end - start + 1))
-                goto error_close_fs;
-        snap_to_boundaries (&new_geom, NULL, disk, range_start, range_end);
-
-        constraint = constraint_intersect_and_destroy (
-                        ped_file_system_get_copy_constraint (fs, disk->dev),
-                        constraint_from_start_end (disk->dev, range_start, range_end));
-        if (!ped_disk_set_partition_geom (disk, part, constraint,
-                                          new_geom.start, new_geom.end))
-                goto error_destroy_constraint;
-        ped_constraint_destroy (constraint);
-        if (ped_geometry_test_overlap (&old_geom, &part->geom)) {
-                ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
-                        _("Can't move a partition onto itself.  Try using resize, perhaps?"));
-                goto error_close_fs;
-        }
-
-        /* do the move */
-        fs_copy = ped_file_system_copy (fs, &part->geom, uiquery->timer);
-        if (!fs_copy)
-                goto error_close_fs;
-        ped_file_system_close (fs_copy);
-        ped_file_system_close (fs);
-        if (!ped_disk_commit (disk)) {
-		//if (uiquery->need_commit) uiquery->need_commit = -1;
-                goto error;
-	}
-	uiquery->need_commit = 0;
-        if (range_start != NULL)
-                ped_geometry_destroy (range_start);
-        if (range_end != NULL)
-                ped_geometry_destroy (range_end);
-        return 1;
-
-error_destroy_constraint:
-        ped_constraint_destroy (constraint);
-error_close_fs:
-        ped_file_system_close (fs);
-error:
-        if (range_start != NULL)
-                ped_geometry_destroy (range_start);
-        if (range_end != NULL)
-                ped_geometry_destroy (range_end);
-        return 0;
-}
-
-static int
-do_name (PedDisk* disk, PedPartition* part, char *name, UICalls *uiquery)
-{
-	const char *temp;
-	int n;
-        if (!disk)
-                goto error;
-	if (!part) 
-        	if (!get_partition (_("Partition number?"), disk, &part, uiquery))
-                	goto error;
-	if (!name) {
-		temp = ped_partition_get_name(part);
-		n = strlen(temp);
-		name = (char *) calloc(n,sizeof(char));
-		strncpy(name,temp,n);
-        	if (!uiquery->getstring(_("Partition name"), &name, NULL, NULL, 0))
-			goto error;
-	}
-
-        if (!name)
-                goto error;
-        if (!ped_partition_set_name (part, name))
-                goto error_free_name;
-        free (name);
-
-        /*if (!ped_disk_commit (disk))
-                goto error_destroy_disk;*/
-	uiquery->need_commit = 1;
-        return 1;
-
-error_free_name:
-        free (name);
-error:
-        return 0;
-}
-
-
-
-static PedPartitionType
-_disk_get_part_type_for_sector (PedDisk* disk, PedSector sector)
-{
-        PedPartition*   extended;
-
-        extended = ped_disk_extended_partition (disk);
-        if (!extended
-            || !ped_geometry_test_sector_inside (&extended->geom, sector))
-                return 0;
-
-        return PED_PARTITION_LOGICAL;
-}
-
-/* This function checks if "part" contains a file system, and returs
- *      0 if either no file system was found, or the user declined to add it.
- *      1 if a file system was found, and the user chose to add it.
- *      -1 if the user chose to cancel the entire search.
- */
-static int
-_rescue_add_partition (PedPartition* part, UICalls *uiquery)
-{
-        const PedFileSystemType*        fs_type;
-        PedGeometry*                    probed;
-        PedExceptionOption              ex_opt;
-        PedConstraint*                  constraint;
-        char*                           found_start;
-        char*                           found_end;
-
-        fs_type = ped_file_system_probe (&part->geom);
-        if (!fs_type)
-                return 0;
-        probed = ped_file_system_probe_specific (fs_type, &part->geom);
-        if (!probed)
-                return 0;
-
-        if (!ped_geometry_test_inside (&part->geom, probed)) {
-                ped_geometry_destroy (probed);
-                return 0;
-        }
-
-        constraint = ped_constraint_exact (probed);
-        if (!ped_disk_set_partition_geom (part->disk, part, constraint,
-                                          probed->start, probed->end)) {
-                ped_constraint_destroy (constraint);
-                return 0;
-        }
-        ped_constraint_destroy (constraint);
-
-        found_start = ped_unit_format (probed->dev, probed->start);
-        found_end = ped_unit_format (probed->dev, probed->end);
-        ex_opt = ped_exception_throw (
-                PED_EXCEPTION_INFORMATION,
-                PED_EXCEPTION_YES_NO_CANCEL,
-                _("A %s %s partition was found at %s -> %s.  "
-                  "Do you want to add it to the partition table?"),
-                fs_type->name, ped_partition_type_get_name (part->type),
-                found_start, found_end);
-        ped_geometry_destroy (probed);
-        ped_free (found_start);
-        ped_free (found_end);
-
-        switch (ex_opt) {
-                case PED_EXCEPTION_CANCEL: return -1;
-                case PED_EXCEPTION_NO: return 0;
-        }
-
-        ped_partition_set_system (part, fs_type);
-        ped_disk_commit (part->disk);
-	uiquery->need_commit = 0;
-        return 1;
-}
-
-/* hack: we only iterate through the start, since most (all) fs's have their
- * superblocks at the start.  We'll need to change this if we generalize
- * for RAID, or something...
- */
-static int
-_rescue_pass (PedDisk* disk, PedGeometry* start_range, PedGeometry* end_range, UICalls *uiquery)
-{
-        PedSector               start;
-        PedGeometry             start_geom_exact;
-        PedGeometry             entire_dev;
-        PedConstraint           constraint;
-        PedPartition*           part;
-        PedPartitionType        part_type;
-
-        part_type = _disk_get_part_type_for_sector (
-                        disk, (start_range->start + end_range->end) / 2);
-
-        ped_geometry_init (&entire_dev, disk->dev, 0, disk->dev->length);
-
-        ped_timer_reset (uiquery->timer);
-        ped_timer_set_state_name (uiquery->timer, _("searching for file systems"));
-        for (start = start_range->start; start <= start_range->end; start++) {
-                ped_timer_update (uiquery->timer, 1.0 * (start - start_range->start)
-                                         / start_range->length);
-
-                ped_geometry_init (&start_geom_exact, disk->dev, start, 1);
-                ped_constraint_init (
-                        &constraint, ped_alignment_any, ped_alignment_any,
-                        &start_geom_exact, &entire_dev,
-                        1, disk->dev->length);
-                part = ped_partition_new (disk, part_type, NULL, start,
-                                end_range->end);
-                if (!part) {
-                        ped_constraint_done (&constraint);
-                        continue;
-                }
-
-                ped_exception_fetch_all ();
-                if (ped_disk_add_partition (disk, part, &constraint)) {
-                        ped_exception_leave_all ();
-                        switch (_rescue_add_partition (part, uiquery)) {
-                        case 1:
-                                ped_constraint_done (&constraint);
-                                return 1;
-
-                        case 0:
-                                ped_disk_remove_partition (disk, part);
-                                break;
-
-                        case -1:
-                                goto error_remove_partition;
-                        }
-                } else {
-                        ped_exception_leave_all ();
-                }
-                ped_partition_destroy (part);
-                ped_constraint_done (&constraint);
-        }
-        ped_timer_update (uiquery->timer, 1.0);
-
-        return 1;
-
-error_remove_partition:
-        ped_disk_remove_partition (disk, part);
-error_partition_destroy:
-        ped_partition_destroy (part);
-error_constraint_done:
-        ped_constraint_done (&constraint);
-error:
-        return 0;
-}
-
-int
-do_rescue (PedDisk* disk, PedSector start, PedSector end, int custom, int warn, UICalls *uiquery)
-{
-
-        PedSector               fuzz;
-        PedGeometry             probe_start_region;
-        PedGeometry             probe_end_region;
-
-
-        if (!disk)
-                goto error;
-	if (warn)
-		if (!ask_boolean_question 
-		(_("WARNING: This writes all data to disk automatically, continue?"),uiquery)) 
-			return 1;
-
-        if (!get_sector (_("Start"), disk->dev, &start, NULL, custom, uiquery))
-                goto error;
-        if (!get_sector (_("End"), disk->dev, &end, NULL, custom, uiquery))
-                goto error;
-
-        fuzz = PED_MAX (PED_MIN ((end - start) / 10, MEGABYTE_SECTORS(disk->dev)),
-                        MEGABYTE_SECTORS(disk->dev) * 16);
-
-        ped_geometry_init (&probe_start_region, disk->dev,
-                           PED_MAX(start - fuzz, 0),
-                           PED_MIN(2 * fuzz, (disk->dev)->length - (start - fuzz)));
-        ped_geometry_init (&probe_end_region, disk->dev,
-                           PED_MAX(end - fuzz, 0),
-                           PED_MIN(2 * fuzz, (disk->dev)->length - (end - fuzz)));
-
-        if (!_rescue_pass (disk, &probe_start_region, &probe_end_region, uiquery))
-                goto error;
-
-
-        return 1;
-
-
-error:
-        return 0;
-}
-
-int
-do_resize (PedDisk *disk, PedPartition *part, PedSector start, PedSector end, 
-						int custom, int warn, UICalls *uiquery)
-{
-
-        PedFileSystem           *fs;
-        PedConstraint           *constraint;
-        PedGeometry             *range_start = NULL, *range_end = NULL;
-        PedGeometry             new_geom;
-
-
-        if (!disk)
-                goto error;
-	if (warn)
-		if (!ask_boolean_question 
-		(_("WARNING: This writes all data to disk automatically, continue?"),uiquery)) 
-			return 1;
-	if (!part) 
-        	if (!get_partition (_("Partition"), disk, &part, uiquery))
-                	goto error;
-        if (part->type != PED_PARTITION_EXTENDED) {
-                if (!_partition_warn_busy (part))
-                        goto error;
-        }
-
-        start = part->geom.start;
-        end = part->geom.end;
-        if (!get_sector (_("Start"), disk->dev, &start, &range_start, custom, uiquery))
-                goto error;
-        if (!get_sector (_("End"), disk->dev, &end, &range_end, custom, uiquery))
-                goto error;
-
-        if (!ped_geometry_init (&new_geom, disk->dev, start, end - start + 1))
-                goto error;
-        snap_to_boundaries (&new_geom, &part->geom, disk,
-                            range_start, range_end);
-
-        if (part->type == PED_PARTITION_EXTENDED) {
-                constraint = constraint_from_start_end (disk->dev,
-                                range_start, range_end);
-                if (!ped_disk_set_partition_geom (disk, part, constraint,
-                                                  new_geom.start, new_geom.end))
-                        goto error_destroy_constraint;
-                ped_partition_set_system (part, NULL);
-        } else {
-                fs = ped_file_system_open (&part->geom);
-                if (!fs)
-                        goto error;
-                constraint = constraint_intersect_and_destroy (
-                                ped_file_system_get_resize_constraint (fs),
-                                constraint_from_start_end (
-                                        disk->dev, range_start, range_end));
-                if (!ped_disk_set_partition_geom (disk, part, constraint,
-                                                  new_geom.start, new_geom.end))
-                        goto error_close_fs;
-                if (!ped_file_system_resize (fs, &part->geom, uiquery->timer))
-                        goto error_close_fs;
-                /* may have changed... eg fat16 -> fat32 */
-                ped_partition_set_system (part, fs->type);
-                ped_file_system_close (fs);
-        }
-
-        ped_disk_commit (disk);
-	uiquery->need_commit = 0;
-        ped_constraint_destroy (constraint);
-        if (range_start != NULL)
-                ped_geometry_destroy (range_start);
-        if (range_end != NULL)
-                ped_geometry_destroy (range_end);
-        return 1;
-
-error_close_fs:
-        ped_file_system_close (fs);
-error_destroy_constraint:
-        ped_constraint_destroy (constraint);
-error:
-        if (range_start != NULL)
-                ped_geometry_destroy (range_start);
-        if (range_end != NULL)
-                ped_geometry_destroy (range_end);
-        return 0;
-}
-
-int
-do_rm (PedDisk* disk, PedPartition* part, UICalls *uiquery)
-{
-       
-
-  
-        if (!disk)
-                goto error;
-	if (!part) 
-        	if (!get_partition (_("Partition"), disk, &part, uiquery))
-                	goto error;
-        if (!_partition_warn_busy (part))
-                goto error;
-
-        ped_disk_delete_partition (disk, part);
-        uiquery->need_commit = 1;
-        return 1;
-
-
-error:
-        return 0;
-}
-

src/base.h

-/*
-    GNU fdisk - a clone of Linux fdisk.
-
-    Copyright (C) 2006
-    Free Software Foundation, Inc.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
-*/
-
-
-
-#ifndef BASE_H_INCLUDED
-#define BASE_H_INCLUDED
-
-#include <parted/parted.h>
-#include "strlist.h"
-
-typedef struct _UICalls UICalls;
-struct _UICalls {
-	/* The first parameter specifies the prompt text */
-	/* All functions should return 1 on success, 0 otherwise */
-	/* getstring: 	The second parameter is the string that is read.                 *
-	 * The two StrLists specify thevalid strings, the second contains the localized. *
-	 * The integer specified how to treat multiwords, TODO: explain                  */
-	int (*getstring)(const char*, char**, const StrList*, const StrList*, int);
-	int (*getint)(const char*, int*);
-	int (*getbool)(const char*, int*);
-	int (*getdev)(const char*, PedDevice**);
-	/* getpart, if the disk is NULL, it should be specified. This won't actually be used */
-	int (*getpart)(const char*, PedDisk**, PedPartition**);
-	int (*getdisktype)(const char*, PedDiskType**);
-	int (*getfstype)(const char*, PedFileSystemType**);
-	PedTimer* timer;
-	int need_commit;
-};
-
-extern int do_check (PedDisk*, PedPartition*, UICalls *);
-extern int do_cp (PedDisk*, PedPartition*, int warn, UICalls *);
-extern int do_mklabel (PedDevice*, PedDisk**, const PedDiskType*, UICalls *);
-extern int do_mkfs (PedDisk*, PedPartition*, const PedFileSystemType*, int warn, UICalls *);
-extern int do_mkpart (PedDisk*, PedSector start, PedSector end, int custom, PedPartitionType,
-	const PedFileSystemType*, PedPartition **newpart, UICalls *);
-extern int do_mkpartfs (PedDisk*, PedSector start, PedSector end, int custom, PedPartitionType,
-	const PedFileSystemType*, PedPartition **newpart, int warn, UICalls *);
-
-
-#endif
 #define NCH 1
 
 #include "../config.h"
-#include "base.h"
+#include "common.h"
 /*#include "command.h"*/
 /*#include "ui.h"*/
 
 #define UP_KEY 1
 #define DOWN_KEY 2
 
-#define MENU_TITLE 1  /* Leave one row for menu title */
-#define MENU_LIST 2  /* Display a fullscreen list */
-#define MENU_ANYKEY 4
-#define MENU_BUTTON 8
 
+enum _MenuOptions {
+	MENU_DEFAULT = 0,
+	MENU_TITLE = 1,  /* Leave one row for menu title */
+	MENU_LIST = 2,   /* Unimplemented */
+	MENU_ANYKEY = 4,
+	MENU_BUTTON = 8,
+	MENU_LEAVE_WARNING = 16 /* Don't clear the warning line */
+};
+
+typedef enum _MenuOptions MenuOptions;
+
+#define TINYBUF 16	/* NOTE: Changing this may lead to segfaults. Double-check. */
 #define SMALLBUF 128
 
 
+
 struct MenuItem {
 	char key;
 	char *name;
 	char *desc; 
 };
-/*int curses_ready = 0;*/
+
+
+PedDevice *dev;
+PedDisk *disk;
+char *devname;
+char *info_size;
+char *info_sectorsize;
+char *info_model;
+char *info_heads;
+char *info_cylinders;
+char *info_sectors;
+char *info_cylsize;
 
 
 static void
 	return x;
 }
 
+
+
 static void
-clear_status(int sub) {
-	move(LINES-1-(sub==0),0);
+clear_lines(int start, int end) {
+	int y = start;
+	do {
+		move (y,0);
+		clrtoeol();
+	} while(y++ < end);
+}
+/* Define these as macros */
+#define clear_status(warn) clear_lines(LINES - 1 - ((warn) != 0),0)
+#define clear_menu() clear_lines(LINES - 2 - MENUSIZE, LINES - 1);
+
+/*static void
+clear_status(int warn_line) {
+	move(LINES-1-warn_line,0);
 	clrtoeol();
-}
+}*/
 
 
 
 void
-set_status(const char *status, int sub) {
-	clear_status(sub);
+set_status(const char *status, int warn_line) {
+	clear_status(warn_line);
 	/*attron(A_REVERSE);*/
-	move(LINES-1-(sub==0),0);
-	mvaddstr(LINES-1-(sub==0), get_center(status) ,status);
+	move(LINES-1-warn_line,0);
+	mvaddstr(LINES-1-warn_line, get_center(status) ,status);
 	/*attroff(A_REVERSE);*/
 }
 
 void
-print_warning(const char *status, int sub) {
-	set_status(status,sub);
+print_warning(const char *status, int status_line) {
+	set_status(status,!status_line);
 	putchar(BELL);
 }
 
 	mvaddstr(LINES - 2 - MENUSIZE, MENUDIV, title);	
 }
 
+/* TODO: Improve this. */
+void
+display_message (const char *msg) {
+	int y = 0, x = 0, i,n = strlen(msg);
+	move(y,x);
+	clrtoeol();
+	for (i = 0; i < n; i++) {
+		mvaddch(y,x,msg[i]);
+		if (++x >= COLS) {
+			move(++y,x=0);
+			clrtoeol();
+		}	
+	}
+	while (y++ < LINES-4-MENUSIZE) {
+		move (y,0);
+		clrtoeol();
+	}
+}
+
 /* Menu drawing function */
 void
-menu_draw (struct MenuItem *items, int item_len, int type, const char *keys, int selected) {
-	int i, y = LINES - 2 - MENUSIZE + (type & MENU_TITLE ? 1 : 0), x = MENUDIV;
-	int item_size = item_len + (type & MENU_BUTTON ? 2 : 0);
+menu_draw (struct MenuItem *items, int item_len, MenuOptions opts, const char *keys, int selected) {
+	int i, y = LINES - 2 - MENUSIZE + (opts & MENU_TITLE ? 1 : 0), x = MENUDIV;
+	int item_size = item_len + (opts & MENU_BUTTON ? 2 : 0);
 	const char *desc;
 	move(y,0);
 	clrtoeol();
 			name_len = strlen(name);
 			/* Enclose the text if the type is a button. If it is too long, cut. */
 			if (name_len >= item_len) {
-				snprintf(buf,item_size+1, (type & MENU_BUTTON) ? "[%s]" : "%s" , name);
-				if (type & MENU_BUTTON) {
+				snprintf(buf,item_size+1, (opts & MENU_BUTTON) ? "[%s]" : "%s" , name);
+				if (opts & MENU_BUTTON) {
 					buf[item_size-1] = ']';
 					buf[item_size] = '\0';
 				}
 			}
 			else {
-				snprintf(buf,item_size+1, (type & MENU_BUTTON) ? "[%*s%s%*s]" : "%*s%s%*s" ,
+				snprintf(buf,item_size+1, (opts & MENU_BUTTON) ? "[%*s%s%*s]" : "%*s%s%*s" ,
 				(item_len - name_len)/2, "", name, (item_len - name_len + 1)/2 , "");
 			}
 	
 		move(y,0);
 		clrtoeol();
 	}
-	move(LINES-2,0);
-	clrtoeol();
+	if (!(opts & MENU_LEAVE_WARNING)) {
+		move(LINES-2,0);
+		clrtoeol();
+	}
 	move(LINES-1,0);
 	clrtoeol();
 	/* If the selected item exits, print its description */
 	if (selected < i) {
 		desc = _(items[selected].desc);
-		set_status(desc,1);
+		set_status(desc,0);
 	}
-	refresh;
+	refresh();
 }
 
 
 /* Menu display function. The selected parameter specifies the item that is selected by
  * default and the keys string includes the keys that should be accepted by the interface. */
 static int
-do_menu (struct MenuItem *items, int item_len, int type, const char *keys, int selected) {
+do_menu (struct MenuItem *items, int item_len, MenuOptions opts, const char *keys, int selected) {
 	int i, key = 0, count = 0, redraw = 1;
 	
 	/* Count the items and make sure that the selected item is available */
 	for (count = 0; items[count].name; count++);
 	if (selected >= count)
 		selected = 0;
+	while (!strchr(keys,tolower(items[selected].key))) {
+		selected = (selected + 1) % count;
+	}
 	while (!key) {
 		if (redraw) {
-			menu_draw (items, item_len, type, keys, selected);
+			menu_draw (items, item_len, opts, keys, selected);
+			opts &= ~MENU_LEAVE_WARNING; /* Clear the warning next time */
 			redraw = 0;
 		}
 		key = getch();
 			key = items[selected].key;
 		}
 		/* If the pressed key is in the list of accepted keys, print a warning */
-		if(!(type & MENU_ANYKEY) && !strchr(keys,tolower(key))) {
+		if(!(opts & MENU_ANYKEY) && !strchr(keys,tolower(key))) {
 			key = 0;
 			print_warning(_("Invalid key"),0);
 		}
 	return key;
 }
 
+/* String list choice */
+static void
+strlist_draw (const char *prompt, const StrList *strlist, const StrList* selected) {
+	char buf[SMALLBUF]; /* FIXME: Not needed */
+	char *temp;
+	int n,x,y = INFOSIZE;
+	const StrList *current;
+
+	move(y++,0); clrtoeol();
+	move(y,0); clrtoeol(); mvaddstr(y++,5,prompt);
+	/* FIXME: Using buf here not needed. This appears another time in source. */
+	mvaddch(y,0,' ');//' 'buf[0] = ' ';
+	for (x = 1; x < COLS-1; x++) {
+		mvaddch(y,x,'-'); //buf[i] = '-';
+        }
+	mvaddch(y++,x,' ');
+	//if (i < SMALLBUF) buf[i++] = ' ';
+	//if (i < SMALLBUF) buf[i] = '\0';
+	//mvaddstr(y++,0,buf);
+	move(y++,0); clrtoeol();
+	
+	n = COLS-LINES-MENUSIZE;
+	
+	for (current = strlist; current && y < n; current = current->next, y++) {
+		if (current == selected)
+			attron(A_STANDOUT);
+		move(y,0); clrtoeol();
+		temp = str_list_convert_node(current);
+		mvaddstr(y,7,temp);
+		if (temp) free(temp);
+		if (current == selected)
+			attroff(A_STANDOUT);
+	} 
+}
+
+void plist_draw (PedDisk *cdisk, PedPartition *selected);
+
+static const StrList*
+do_strlist (const char *prompt, const StrList *strlist) {
+	const StrList *selected = strlist, *temp;
+	int redraw = 1, key = 0, done = 0;
+	while (!done) {
+		if (redraw) {
+			strlist_draw(prompt, strlist, selected);
+			clear_menu();
+			redraw = 0;
+		}
+		refresh();
+		key = getch();
+		if (key == ESC) {
+			key = getch();
+			if (key == '[' || key == 'O') {
+			key = getch();
+				if (key == 'B') { /* That's down arrow */
+					if (!selected->next)
+						print_warning(_("No more choices"),0);
+					else {
+						selected = selected->next;
+						redraw = 1;
+					}
+				}
+				else if (key == 'A') { /* That's up arrow */
+					if (strlist == selected)
+						print_warning(_("No more choices"),0);
+					else {
+					/* FIXME: Edit strlist and make this faster */
+					/* Users should not use the up arrow much anyway */
+						temp = strlist;
+						while (temp && temp->next != selected)
+							temp = temp->next;
+						/* This should never happen */
+						if (temp->next != selected)
+							print_warning(_("Bug in the program. "
+							                "The programmer is an idiot."),0);
+						else {
+							selected = temp;
+							redraw = 1;
+						}
+					}
+				}
+				else
+					print_warning(_("Invalid key"),0);
+			}
+			else
+				print_warning(_("Invalid key"),0);
+		}
+		else if (key == CR) {
+			done = 1;
+		}
+		else 
+			print_warning(_("Invalid key"),0);
+	}
+	if (disk) plist_draw(disk,NULL);
+	return selected;
+}
+
+
 static int
 read_char (const char* prompt, char **value) {
 	char buf[SMALLBUF];
 	addstr(buf);
 	getyx(stdscr,y,x);
 	n = MIN(n,COLS-x);
+	refresh();
 	while(!done) {
 		key = getch();
 		if (key == ESC) {
 
 static int
 getstring (const char* prompt, char **value, const StrList* words, const StrList* locwords, int mword) {
-	/* TODO: Write this. For now ignores valid words. Make a list choice? */
-	return read_char(prompt,value);
+	/* TODO: Implement multiword, etc. */
+	const StrList *selected;
+	if (words || locwords) {
+		if(locwords)
+			selected = do_strlist(prompt,locwords);
+		else
+			selected = do_strlist(prompt,words);
+		if (*value) free(*value);
+		*value = str_list_convert_node(selected);
+		return (*value != NULL);
+	}
+	else return read_char(prompt,value);
 }
 
+
+
+static PedExceptionOption
+exception_handler (PedException* ex) {
+	static struct MenuItem ex_choices[] = {
+		{ 'f', N_("Fix"), "" },
+		{ 'y', N_("Yes"), "" },
+		{ 'n', N_("No"), "" },
+		{ 'o', N_("OK"), "" },
+		{ 'r', N_("Retry"), "" },
+		{ 'i', N_("Ignore"), "" },
+		{ 'c', N_("Cancel"), "" },
+		{ 0, NULL, NULL }
+	};
+	/* Adding new elements to ex_key may lead to segfaults. Double check. */
+	static const struct { char key; PedExceptionOption option; }  ex_keys [] = {
+		{ 'f', PED_EXCEPTION_FIX },
+		{ 'y', PED_EXCEPTION_YES },
+		{ 'n', PED_EXCEPTION_NO },
+		{ 'o', PED_EXCEPTION_OK },
+		{ 'r', PED_EXCEPTION_RETRY },
+		{ 'i', PED_EXCEPTION_IGNORE },
+		{ 'c', PED_EXCEPTION_CANCEL },
+		{ 0, 0 }
+	};
+	char keys[TINYBUF];
+	int res,i,k = 0;
+	for (i = 0; ex_keys[i].key; i++)
+		if (ex->options & ex_keys[i].option) {
+#if 0
+			if (k >= TINYBUF) break; /* NOTE: This is not needed now, but have in mind */
+#endif
+			keys[k++] = ex_keys[i].key;
+		}
+#if 0
+	if (k < TINYBUF)
+#endif
+	keys[k] = '\0';
+	display_message(ex->message);
+	res = do_menu(ex_choices, 8, MENU_BUTTON, keys, 0);
+	for (i = 0; ex_keys[i].key; i++)
+		if (ex_keys[i].key == res)
+			return ex_keys[i].option;
+	return PED_EXCEPTION_UNHANDLED;
+}
+
+typedef struct {
+	time_t	last_update;
+	time_t	predicted_time_left;
+} TimerContext;
+
+static TimerContext timer_context;
+
+static void
+_timer_handler (PedTimer* timer, void* context) {
+	char buf[SMALLBUF];
+	TimerContext*	tcontext = (TimerContext*) context;
+	int		draw;
+
+
+	if (tcontext->last_update != timer->now && timer->now > timer->start) {
+		tcontext->predicted_time_left = timer->predicted_end - timer->now;
+		tcontext->last_update = timer->now;
+		draw = 1;
+	} else {
+		draw = 0;
+	}
+
+        if (draw) {
+		if(timer->state_name)
+			snprintf(buf,SMALLBUF,_("We are now %s."), timer->state_name);
+		else
+			snprintf(buf,SMALLBUF,_("An operation is now taking place."));
+		set_status(buf,0);
+		snprintf(buf,SMALLBUF,_("Progress: %3.1f%%   Time left: %4.2d:%.2d"),
+		         100.0 * timer->frac,
+		         tcontext->predicted_time_left / 60,
+		         tcontext->predicted_time_left % 60); 
+		set_status(buf,1);
+        }
+
+}
+
+
 static void
 init_calls() {
 	uiquery.getbool = getbool;
 	uiquery.getstring = getstring;
 	uiquery.need_commit = 0;
+	uiquery.timer = ped_timer_new (_timer_handler, &timer_context);
+	ped_exception_set_handler(exception_handler);
+	init_fs_type_str ();
+	init_disk_type_str ();
 }
 
+
 /* Define column positions. The first three will be fixed. */
 #define col_name 3
 #define col_flags 12
 #define col_fs 35
 
 /* Partition list drawing function */
+/* TODO: Make scrollable */
 void
 plist_draw (PedDisk *cdisk, PedPartition *selected) {
 	PedPartition *part;
 	char buf[SMALLBUF];
 	int col_label = ((float)53/(80-col_fs))*(COLS-col_fs);
 	int col_size = ((float)66/(80-col_fs))*(COLS-col_fs);
-	int i,x,y = INFOSIZE;
+	int n,i,x,y = INFOSIZE;
 	
 	move(y++,0); clrtoeol();
 	/* Display header */
 	if (i < SMALLBUF) buf[i++] = ' ';
 	if (i < SMALLBUF) buf[i] = '\0';
 	mvaddstr(y++,0,buf);
-	for (part = ped_disk_next_partition (cdisk, NULL); part;
+
+	n = LINES-2-MENUSIZE;
+	for (part = ped_disk_next_partition (cdisk, NULL); part && y < n;
 	     part = ped_disk_next_partition (cdisk, part)) {
-		if (part->type & PED_PARTITION_METADATA) continue;
-		int free = 0;
+		if (part->type & PED_PARTITION_METADATA) continue; /* We skip METADATA partitions */
+		int free = part->type & PED_PARTITION_FREESPACE;
+
 		if (part == selected) attron(A_STANDOUT);
+
 		snprintf(buf, SMALLBUF, "%*d%*s", col_name+4,part->num, col_flags-col_name-4, "");
 		mvaddstr(y,0,buf);
+		/* ped_partition_get_flag(part, PED_PARTITION_BOOT) throws an exception when ran on a
+		   free space */
+		snprintf(buf, SMALLBUF, "%-*s", col_type-col_flags,
+		         (!free && ped_partition_get_flag(part, PED_PARTITION_BOOT) ? N_("Bootable") : ""));
+		mvaddstr(y,col_flags,buf);
 
-		snprintf(buf, SMALLBUF, "%-*s", col_type-col_flags,
-		         (ped_partition_get_flag(part, PED_PARTITION_BOOT) ? N_("Bootable") : ""));
-		mvaddstr(y,col_flags,buf);
 		if (part->type & PED_PARTITION_EXTENDED)
 			temp = N_("Extended");
 		else if (part->type & PED_PARTITION_LOGICAL)
 			temp = N_("Logical");
-		else if (part->type & PED_PARTITION_FREESPACE) {
-			free = 1;
+		else if (free) {
 			temp = N_("None"); /* FIXME: Make this like Linux cfdisk */
 		}
+		else temp = N_("Primary");
 
-		else temp = N_("Primary");
 		snprintf(buf, SMALLBUF, "%-*s", col_fs-col_type, temp);
 		mvaddstr(y,col_type,buf);
+
 		temp = "";
 		if(part->fs_type)
 			temp = part->fs_type->name;
+		if (free)
+			temp = _("Free space");
 		snprintf(buf, SMALLBUF, "%-*s", col_label-col_fs, temp);
 
 		mvaddstr(y,col_fs,buf);
 		if (!temp) temp = "";
 		snprintf(buf, SMALLBUF, "%-*s", col_size-col_label, temp);
 		mvaddstr(y,col_label,buf);
+
+		/* Display the size of the disk right-aligned. */
 		snprintf(buf, SMALLBUF, "%*s ", COLS-col_size-1,
 		         ped_unit_format (part->disk->dev, part->geom.length));
 		mvaddstr(y++,col_size,buf);
+
 		if (part == selected) attroff(A_STANDOUT);
 	}
+	while (y < n) {
+		move(y++,0); clrtoeol();
+	}
+	refresh();
 }
 
 static struct MenuItem part_menu[] = {
 };
 
 
-
+/* Get previous non-METADATA partition. Needed for menu navigation */
 /* FIXME: This is *ugly*. Fix it. Can be fixed with a expand/collapse
           list of logical partitions. At least it works. */
 static PedPartition *
 disk_get_prev_nmd_partition(PedDisk *cdisk, PedPartition *part) {
 	PedPartition *temp_a, *temp_b;
+	/* temp_a will iterate through partitions that are not METADATA, while
+	   temp_b will iterate through all partitions. When temp_b reaches our partition,
+	   temp_a is the partition we are looking for. */
 	temp_a = NULL;
-	/*do {
-		temp_a = ped_disk_next_partition(cdisk,temp_a);
-	} while (temp_a || temp_a->type & PED_PARTITION_METADATA);*/
 	temp_b = temp_a;
 	do {
 		if (ped_disk_next_partition(cdisk,temp_b) == part)
 }
 
 const char keys_ext[] = { 'd','u','w','q','p','h',UP_KEY,DOWN_KEY, '\0' };
-const char keys_free[] = { 'n','r','u','w','q','p','h',UP_KEY,DOWN_KEY, '\0' };
+const char keys_free[] = { 'n','s','u','w','q','p','h',UP_KEY,DOWN_KEY, '\0' };
 const char keys_part[] = { 'b','f','c','a','y','r','o','d','t','u','w','q','p','h',UP_KEY,DOWN_KEY, '\0' };
 /*bfcayrodtuwqph*/
 
 	const char* keys;
 	PedPartition *selected = NULL;
 	PedPartition *temp,*memp;
+	MenuOptions menu_opts = MENU_DEFAULT;
 	do {
 		selected = ped_disk_next_partition(cdisk,selected);
 	} while (selected && selected->type & PED_PARTITION_METADATA);
 			keys = keys_free;
 		else keys = keys_part;
 		
-		key = do_menu(part_menu, 8, MENU_BUTTON, keys, 0);
+		key = do_menu(part_menu, 8, MENU_BUTTON | menu_opts, keys, 0);
+		menu_opts &= ~MENU_LEAVE_WARNING;
 		if (key == UP_KEY) {
 
 			temp = disk_get_prev_nmd_partition(cdisk,selected);
 				selected = temp;
 				redraw = 1;
 			}
-			/* FIXME: Make the menu drawing clear these more carefully. */
-			else print_warning(N_("No more partitions"),1);
+			
+			else {
+				menu_opts |= MENU_LEAVE_WARNING;
+				print_warning(N_("No more partitions"),0);
+			}
 			key = 0;
 		}
 		if (key == DOWN_KEY) {
 				selected = temp;
 				redraw = 1;
 			}
-			else print_warning(N_("No more partitions"),1);
+			else {
+				menu_opts |= MENU_LEAVE_WARNING;
+				print_warning(N_("No more partitions"),0);
+			}
 			key = 0;
 		}
 		if (key == ESC || key == 'q') {
 				getbool(N_("Partition table has changed, are you sure you want to quit?"),
 				        &key);
 			}
+			else if (key == ESC) {
+				key = 0;
+				getbool(N_("Are you sure you want to quit?"), &key);
+			}
+		}
+		if (key == 'n') {
 		}
 		refresh();
 	}
 }
 
 
-PedDevice *dev;
-PedDisk *disk;
-char *devname;
-char *info_size;
-char *info_sectorsize;
-char *info_model;
-char *info_heads;
-char *info_cylinders;
-char *info_sectors;
-char *info_cylsize;
+
+
+
 static void
-
-
 show_info() {
 	int y;
 	char buf[SMALLBUF];
 		}
 		else do_quit(0,NULL);
 	}
+	ped_exception_fetch_all ();
 	disk = ped_disk_new(dev);
+	
 	if (!disk) {
+		ped_exception_catch();
+		ped_exception_leave_all();
 		menu_title(_("Cannot find a partition table on the disk"));
 		if ('c' == do_menu(custom_label, 8, MENU_BUTTON | MENU_TITLE, "cq", 0)) {
 			if (!do_mklabel (dev, &disk, NULL, &uiquery))
 				do_quit(1,_("Creation of partition table failed"));
 		}
 		else do_quit (0,NULL);
+	} else {
+		ped_exception_leave_all();
 	}
 	ped_unit_set_default(PED_UNIT_MEGABYTE);
 
 	/*curses_ready = 1;*/
 	initscr();
 	//start_color();
+	cbreak();
 	noecho();
 	nonl();
+	
 	init_calls();
 	init_disk();
 	int test = 0;
+/*
+    GNU fdisk - a clone of Linux fdisk.
+
+    Copyright (C) 2006
+    Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+*/
+
+#include "../config.h"
+
+/*#include "command.h"*/
+/*#include "ui.h"*/
+
+#include "strlist.h"
+
+#define N_(String) String
+#if ENABLE_NLS
+#  include <libintl.h>
+#  include <locale.h>
+#  define _(String) dgettext (PACKAGE, String)
+#else
+#  define _(String) (String)
+#endif /* ENABLE_NLS */
+
+#include <parted/parted.h>
+#include <parted/debug.h>
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "common.h"
+
+
+#define SMALLBUF 128
+
+static int MEGABYTE_SECTORS (PedDevice* dev)
+{
+        return PED_MEGABYTE_SIZE / dev->sector_size;
+}
+
+struct bsdlabel {
+  unsigned int magic;
+  char unused[128];
+  unsigned int magic2;
+};
+
+
+/* TODO: Decide if these should be moved to UICalls */
+StrList *disk_type_list;
+StrList *fs_type_list;
+
+int
+init_fs_type_str ()
+{
+	PedFileSystemType*	walk;
+
+	fs_type_list = NULL;
+
+	for (walk = ped_file_system_type_get_next (NULL); walk;
+	     walk = ped_file_system_type_get_next (walk))
+	{
+		fs_type_list = str_list_insert (fs_type_list, walk->name);
+		if (!fs_type_list)
+			return 0;
+	}
+
+	return 1;
+}
+
+int
+init_disk_type_str ()
+{
+	PedDiskType*	walk;
+
+	disk_type_list = NULL;
+
+	for (walk = ped_disk_type_get_next (NULL); walk;
+	     walk = ped_disk_type_get_next (walk))
+	{
+		disk_type_list = str_list_insert (disk_type_list, walk->name);
+		if (!disk_type_list)
+			return 0;
+	}
+
+	return 1;
+}
+
+
+static int
+_can_create_primary (const PedDisk* disk)
+{
+	int	i;
+
+	for (i = 1; i <= ped_disk_get_max_primary_partition_count (disk); i++) {
+		if (!ped_disk_get_partition (disk, i))
+			return 1;
+	}
+
+	return 0;
+}
+
+static int
+_can_create_extended (const PedDisk* disk)
+{
+	if (!_can_create_primary (disk))
+		return 0;
+	if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED))
+		return 0;
+	if (ped_disk_extended_partition (disk))
+		return 0;
+	return 1;
+}
+
+static int
+_can_create_logical (const PedDisk* disk)
+{
+	if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED))
+		return 0;
+	return ped_disk_extended_partition (disk) != 0;
+}
+
+
+/* Copied verbatim from parted upto help_on*/
+
+static int
+_partition_warn_busy (PedPartition* part)
+{
+	char* path = ped_partition_get_path (part);
+
+	if (ped_partition_is_busy (part)) {
+		ped_exception_throw (
+			PED_EXCEPTION_ERROR,
+			PED_EXCEPTION_CANCEL,
+			_("Partition %s is being used.  You must unmount it "
+			  "before you modify it with Parted."),
+			path);
+		ped_free (path);
+		return 0;
+	}
+	ped_free (path);
+	return 1;
+}
+
+static int
+_disk_warn_busy (PedDisk* disk)
+{
+	if (ped_device_is_busy (disk->dev)) {
+		if (ped_exception_throw (
+			PED_EXCEPTION_WARNING,
+			PED_EXCEPTION_IGNORE_CANCEL,
+			_("Partition(s) on %s are being used."),
+			disk->dev->path)
+				!= PED_EXCEPTION_IGNORE)
+			return 0;
+	}
+	return 1;
+}
+
+/* This function changes "sector" to "new_sector" if the new value lies
+ * within the required range.
+ */
+static int
+snap (PedSector* sector, PedSector new_sector, PedGeometry* range)
+{
+        PED_ASSERT (ped_geometry_test_sector_inside (range, *sector), return 0);
+        if (!ped_geometry_test_sector_inside (range, new_sector))
+                return 0;
+        *sector = new_sector;
+        return 1;
+}
+
+typedef enum {
+        MOVE_NO         = 0,
+        MOVE_STILL      = 1,
+        MOVE_UP         = 2,
+        MOVE_DOWN       = 4
+} EMoves;
+
+enum { /* Don't change these values */
+        SECT_START      =  0,
+        SECT_END        = -1
+};
+
+/* Find the prefered way to adjust the sector s inside range.
+ * If a move isn't allowed or is out of range it can't be selected.
+ * what contains SECT_START if the sector to adjust is a start sector
+ * or SECT_END if it's an end one.
+ * The prefered move is to the nearest allowed boundary of the part
+ * partition (if at equal distance: to start if SECT_START or to end
+ * if SECT_END).
+ * The distance is returned in dist.
+ */
+static EMoves
+prefer_snap (PedSector s, int what, PedGeometry* range, EMoves* allow,
+             PedPartition* part, PedSector* dist)
+{
+        PedSector up_dist = -1, down_dist = -1;
+        PedSector new_sect;
+        EMoves move;