Anonymous avatar Anonymous committed 8b9b85f

Hm, I forgot the src dir, I wasn't commiting anything (fdisk@sv.gnu.org/fdisk--main--0--patch-3)
fdisk@sv.gnu.org/fdisk--main--0--patch-3
Keywords:

Comments (0)

Files changed (4)

+/*
+    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"
+
+
+struct bsdlabel {
+  unsigned int magic;
+  char unused[128];
+  unsigned int magic2;
+};
+
+typedef struct {
+	time_t	last_update;
+	time_t	predicted_time_left;
+} TimerContext;
+
+
+
+/* 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->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;
+	*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; 
+	if (!disk) 
+		return 0;
+	if (!uiquery->getpart) {
+		num = (*value) ? (*value)->num : 0;
+		if (!uiquery->getint (prompt, &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;
+	if (!uiquery->getdisktype) {
+		if (*value) 
+			strcpy(disk_type_name,(*value)->name);
+		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;
+
+	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;
+	}
+
+	uiquery->getstring(prompt,&type_name,opts,locopts,-1);
+	
+	str_list_destroy (opts);
+	str_list_destroy (locopts);
+
+	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;
+	if (!uiquery->getfstype) {
+		if(*value) {
+			strcpy(fs_type_name,(*value)->name);
+		}
+		if (!uiquery->getstring(prompt,&fs_type_name,fs_type_list,fs_type_list,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
+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, PedTimer* timer, 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, 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 */
+int
+do_cp (PedDisk* dst_disk, PedPartition* dst, PedTimer* timer, UICalls *uiquery)
+{
+        PedDisk*                src_disk;
+        PedDevice*              src_device;
+        PedPartition*           src = NULL;
+        PedFileSystem*          src_fs;
+        PedFileSystem*          dst_fs;
+        PedFileSystemType*      dst_fs_type;
+	
+	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, 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))
+                goto error_destroy_disk;
+        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;
+        return 1;
+
+error:
+        return 0;
+}
+
+/* Create a filesystem. Takes filesystem type as an optional parameter */
+static int
+do_mkfs (PedDisk* disk, PedPartition* part, const PedFileSystemType* type,
+				PedTimer* timer, UICalls *uiquery)
+{
+
+        PedFileSystem*          fs;
+
+	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, 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))
+                goto error;
+        return 1;
+
+
+error:
+        return 0;
+}
+
+/* The parameter custom is 1, then the user is asked about the start and end sector */
+static int
+do_mkpart (PedDisk* disk, PedSector start, PedSector end, int custom, PedPartitionType part_type,
+		const PedFileSystemType* fs_type, PedTimer* timer, 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 (!get_part_type (_("Partition type"), disk, &part_type, uiquery))
+                        goto error;
+        }
+
+        if (ped_disk_type_check_feature (disk->type,
+                                         PED_DISK_TYPE_PARTITION_NAME)) 
+                uiquery->getstring(_("Partition name"), &part_name, NULL, NULL, 1); 
+                
+        /*peek_word = command_line_peek_word ();*/
+        if (part_type == PED_PARTITION_EXTENDED) {
+            /*|| (peek_word && isdigit (peek_word[0]))) {*/
+                fs_type = NULL;
+        } else {
+                if (!command_line_get_fs_type (_("File system type?"),
+                                               &fs_type))
+                        goto error;
+        }
+        /*if (peek_word)
+                ped_free (peek_word);*/
+
+        if (!get_sector (_("Start?"), disk->dev, &start, &range_start, custom))
+                goto error;
+        if (!get_sector (_("End?"), disk->dev, &end, &range_end, custom))
+                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 (*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 (*dev))) {
+                        start_usr = ped_unit_format (*dev, start);
+                        end_usr   = ped_unit_format (*dev, end);
+                        start_sol = ped_unit_format (*dev, part->geom.start);
+                        end_sol   = ped_unit_format (*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;
+        
+        /* clean up */
+        ped_constraint_destroy (final_constraint);
+        ped_constraint_destroy (user_constraint);
+        ped_constraint_destroy (dev_constraint);
+
+        ped_disk_destroy (disk);
+        
+        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 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;
+}
+
+/*
+    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 */
+	/* 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*);
+	/* 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**);
+};
+
+extern int do_check (PedDisk*, PedPartition*, PedTimer*, UICalls *);
+extern int do_cp (PedDisk*, PedPartition*, PedTimer*, UICalls *);
+
+
+#endif
+/*
+    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
+*/
+
+#define NCH 1
+
+#include "../config.h"
+#include "command.h"
+/*#include "ui.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>
+
+#ifdef SLCURSES
+  #include <slcurses.h>
+#else
+#if NCH
+  #include <ncurses.h>
+#else
+  #include <curses.h>
+#endif
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#ifdef ENABLE_MTRACE
+#include <mcheck.h>
+#endif
+
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+
+/* Set the default device, if not set
+   Should respect the platform for which cfdisk is compiled */
+#ifndef DEFAULT_DEVICE
+#define DEFAULT_DEVICE "/dev/hda"
+#define ALTERNATE_DEVICE "/dev/sda"
+#endif
+/*
+    GNU fdisk - a clone of Linux fdisk.
+    This file originally from GNU Parted.
+
+    Copyright (C) 1999, 2000, 2001, 2002, 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 STRLIST_H_INCLUDED
+#define STRLIST_H_INCLUDED
+
+#include <wchar.h>
+
+typedef struct _StrList StrList;
+struct _StrList {
+	StrList*	next;
+	const wchar_t*	str;
+};
+
+extern char* language;
+extern char* gettext_charset;
+extern char* term_charset;
+
+extern StrList* str_list_create (const char* first, ...);
+extern StrList* str_list_create_unique (const char* first, ...);
+extern void str_list_destroy (StrList* list);
+extern void str_list_destroy_node (StrList* list);
+
+extern StrList* str_list_duplicate (const StrList* list);
+extern StrList* str_list_duplicate_node (const StrList* list);
+extern StrList* str_list_insert (StrList* list, const char* str);
+extern StrList* str_list_append (StrList* list, const char* str);
+extern StrList* str_list_append_unique (StrList* list, const char* str);
+extern StrList* str_list_join (StrList* a, StrList* b);
+extern char* str_list_convert (const StrList* list);
+extern char* str_list_convert_node (const StrList* list);
+
+extern void str_list_print (const StrList* list);
+extern void str_list_print_wrap (const StrList* list, int line_length,
+				 int offset, int indent);
+extern int str_list_match_any (const StrList* list, const char* str);
+extern int str_list_match_node (const StrList* list, const char* str);
+extern StrList* str_list_match (const StrList* list, const char* str);
+
+extern int str_list_length (const StrList* list);
+
+#endif /* STRLIST_H_INCLUDED */
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.