diff -u --recursive --new-file parted-1.7.1/include/parted/device.h parted-1.7.1-my/include/parted/device.h --- parted-1.7.1/include/parted/device.h 2006-05-25 19:28:43.000000000 +0200 +++ parted-1.7.1-my/include/parted/device.h 2006-10-17 21:27:10.000000000 +0200 @@ -77,6 +77,8 @@ int open_count; /**< the number of times this device has been opened with ped_device_open(). */ int read_only; + int test_mode; //zanac + void* operation; //zanac int external_mode; int dirty; int boot_dirty; @@ -119,6 +121,7 @@ extern int ped_device_open (PedDevice* dev); extern int ped_device_close (PedDevice* dev); extern void ped_device_destroy (PedDevice* dev); +extern int ped_device_test_mode (PedDevice* dev, int test_mode); //zanac extern int ped_device_begin_external_access (PedDevice* dev); extern int ped_device_end_external_access (PedDevice* dev); diff -u --recursive --new-file parted-1.7.1/include/parted/disk.h parted-1.7.1-my/include/parted/disk.h --- parted-1.7.1/include/parted/disk.h 2006-05-25 19:28:43.000000000 +0200 +++ parted-1.7.1-my/include/parted/disk.h 2006-10-17 21:18:13.000000000 +0200 @@ -37,6 +37,7 @@ #include #include #include +#include /** * Partition types @@ -138,6 +139,8 @@ struct _PedDisk { PedDevice* dev; /**< the device where the partition table lies */ + PedDisk* disk; /**< "parent" disk used for + apply/undo. */ //zanac const PedDiskType* type; /**< type of disk label */ const int* block_sizes; /**< block sizes supported by this label */ @@ -234,6 +237,8 @@ extern int ped_disk_commit (PedDisk* disk); extern int ped_disk_commit_to_dev (PedDisk* disk); extern int ped_disk_commit_to_os (PedDisk* disk); +extern PedDisk *ped_disk_commit_test_disk (PedDisk **disk); //zanac + extern int ped_disk_check (PedDisk* disk); extern void ped_disk_print (PedDisk* disk); diff -u --recursive --new-file parted-1.7.1/include/parted/Makefile.am parted-1.7.1-my/include/parted/Makefile.am --- parted-1.7.1/include/parted/Makefile.am 2006-05-25 19:28:43.000000000 +0200 +++ parted-1.7.1-my/include/parted/Makefile.am 2006-10-17 19:03:20.000000000 +0200 @@ -5,6 +5,7 @@ debug.h \ device.h \ disk.h \ + operation.h \ exception.h \ filesys.h \ geom.h \ diff -u --recursive --new-file parted-1.7.1/include/parted/Makefile.in parted-1.7.1-my/include/parted/Makefile.in --- parted-1.7.1/include/parted/Makefile.in 2006-05-27 11:50:03.000000000 +0200 +++ parted-1.7.1-my/include/parted/Makefile.in 2006-10-17 19:03:36.000000000 +0200 @@ -192,6 +192,7 @@ debug.h \ device.h \ disk.h \ + operation.h \ exception.h \ filesys.h \ geom.h \ diff -u --recursive --new-file parted-1.7.1/include/parted/operation.h parted-1.7.1-my/include/parted/operation.h --- parted-1.7.1/include/parted/operation.h 1970-01-01 01:00:00.000000000 +0100 +++ parted-1.7.1-my/include/parted/operation.h 2006-10-28 12:42:13.000000000 +0200 @@ -0,0 +1,81 @@ +/* + libparted - a library for manipulating disk partitions + Copyright (C) 1999, 2000, 2001, 2002 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 +*/ + +/** + * \addtogroup PedOperation + * @{ + */ + +/** \file operation.h */ +#include + +#ifndef PED_OPERATION_H_INCLUDED +#define PED_OPERATION_H_INCLUDED + + + +typedef struct _PedOperation PedOperation; +typedef struct _PedOperationRM PedOperationRM; +typedef struct _PedOperationMKPART PedOperationMKPART; + +/** + * Operation types + */ +typedef enum { + PED_OPERATION_MKPART = 1, + PED_OPERATION_RM = 2 +} PedOperationType; + + +/** + * PedOperation structure represents an operation to by committed + */ +struct _PedOperation { + PedOperation* prev; + PedOperation* next; + PedOperationType type; + void* operation; +}; + +struct _PedOperationRM { + int num; /**< the partition number: In Linux, this is the + same as the minor number. No assumption + should be made about "num" and "type" + - different disk labels have different rules. */ +}; + +struct _PedOperationMKPART { + PedOperationType oper_type; + int part_type; + const PedFileSystemType* fs_type; + PedSector start; + PedSector end; + PedGeometry* range_start; + PedGeometry* range_end; + char* part_name; +}; + + +/** @} */ + + +#endif /* PED_OPERATION_H_INCLUDED */ + +/** @} */ + diff -u --recursive --new-file parted-1.7.1/libparted/device.c parted-1.7.1-my/libparted/device.c --- parted-1.7.1/libparted/device.c 2006-05-25 19:29:06.000000000 +0200 +++ parted-1.7.1-my/libparted/device.c 2006-10-28 13:12:47.000000000 +0200 @@ -195,6 +195,9 @@ if (!walk) return NULL; _device_register (walk); + + walk->test_mode = 0; + return walk; } @@ -271,6 +274,20 @@ return ped_architecture->dev_ops->close (dev); } +//zanac +int +ped_device_test_mode (PedDevice* dev, int test_mode) +{ + PED_ASSERT (dev != NULL, return 0); + PED_ASSERT ((test_mode == 0) || (test_mode == 1), return 0); + + dev->test_mode = test_mode; + + return 1; +} + + + /** * Begins external access mode. External access mode allows you to * safely do IO on the device. If a PedDevice is open, then you should diff -u --recursive --new-file parted-1.7.1/libparted/disk.c parted-1.7.1-my/libparted/disk.c --- parted-1.7.1/libparted/disk.c 2006-05-25 19:29:06.000000000 +0200 +++ parted-1.7.1-my/libparted/disk.c 2006-10-17 21:25:06.000000000 +0200 @@ -190,6 +190,22 @@ if (!type->ops->read (disk)) goto error_destroy_disk; disk->needs_clobber = 0; + disk->disk = NULL; //zanac + + if (dev->test_mode) { //zanac + PedDisk *clone_disk; + + clone_disk = ped_disk_duplicate (disk); + if (!clone_disk) + goto error_destroy_disk; + + clone_disk->disk = disk; + + ped_device_close(dev); + + return clone_disk; + } + ped_device_close (dev); return disk; @@ -433,6 +449,27 @@ return 0; } +//zanac +PedDisk * +ped_disk_commit_test_disk (PedDisk **disk) +{ + PedDisk *clone_disk; + clone_disk = ped_disk_duplicate(*disk); + + if (!clone_disk) + goto error; + + clone_disk->disk = *disk; + *disk = clone_disk; + + return clone_disk; + +error: + return 0; +} + + + /** * Write the changes made to the in-memory description * of a partition table to the device. @@ -486,6 +523,8 @@ int ped_disk_commit (PedDisk* disk) { + if (disk->dev->test_mode) return 1; //zanac + if (!ped_disk_commit_to_dev (disk)) return 0; return ped_disk_commit_to_os (disk); diff -u --recursive --new-file parted-1.7.1/libparted/filesys.c parted-1.7.1-my/libparted/filesys.c --- parted-1.7.1/libparted/filesys.c 2006-05-25 19:29:06.000000000 +0200 +++ parted-1.7.1-my/libparted/filesys.c 2006-10-14 16:47:46.000000000 +0200 @@ -297,6 +297,10 @@ PedFileSystemType* fs_type = NULL; PED_ASSERT (geom != NULL, return 0); + PED_ASSERT (geom->dev != NULL, return 0); + + if (geom->dev->test_mode) + return 1; if (!ped_device_open (geom->dev)) goto error; @@ -440,6 +444,7 @@ PED_ASSERT (geom != NULL, return NULL); PED_ASSERT (type != NULL, return NULL); + PED_ASSERT (geom->dev != NULL, return NULL); if (!type->ops->create) { ped_exception_throw (PED_EXCEPTION_NO_FEATURE, @@ -476,6 +481,10 @@ { PedDevice* dev = fs->geom->dev; + if (fs->geom->dev->test_mode) + ped_device_close (dev); + return 1; + PED_ASSERT (fs != NULL, goto error_close_dev); if (!fs->type->ops->close (fs)) diff -u --recursive --new-file parted-1.7.1/parted/parted.c parted-1.7.1-my/parted/parted.c --- parted-1.7.1/parted/parted.c 2006-05-25 19:28:42.000000000 +0200 +++ parted-1.7.1-my/parted/parted.c 2006-10-28 13:13:36.000000000 +0200 @@ -34,6 +34,7 @@ #include #include +#include "../include/parted/operation.h" #include #include @@ -48,6 +49,8 @@ #ifdef HAVE_GETOPT_H #include +PedDisk* disk; + /* minimum amount of free space to leave, or maximum amount to gobble up */ #define MIN_FREESPACE (1000 * 2) /* 1000k */ @@ -126,6 +129,96 @@ static void _done (PedDevice* dev); +//zanac +int +ped_device_add_operation_mkpart (PedDevice* dev, + PedPartitionType part_type, + const PedFileSystemType *fs_type, + PedSector start, + PedSector end, + PedGeometry *range_start, + PedGeometry *range_end, + char *part_name) +{ + PedOperationMKPART *operationMKPART; + operationMKPART = malloc(sizeof (PedOperationMKPART)); + if (!operationMKPART) + goto error; + + PedOperation* new_operation; + new_operation = malloc(sizeof (PedOperation)); + if (!new_operation) + goto error; + + operationMKPART->part_type = part_type; + operationMKPART->fs_type = fs_type; + operationMKPART->start = start; + operationMKPART->end = end; + operationMKPART->range_start = range_start; + operationMKPART->range_end = range_end; + operationMKPART->part_name = part_name; + new_operation->operation = operationMKPART; + new_operation->prev = NULL; + new_operation->next = NULL; + new_operation->type = PED_OPERATION_MKPART; + + if (dev->operation == NULL) { + dev->operation = new_operation; + } + else { + PedOperation *operation = dev->operation; + PedOperation *last_operation = dev->operation; + while ((operation = operation->next)) + last_operation = operation; + new_operation->prev = last_operation; + last_operation->next = new_operation; + } + + return 1; + +error: + return 0; +} + +int +ped_device_add_operation_rm (PedDevice* dev, + int num) +{ + PedOperationRM *operationRM; + operationRM = malloc(sizeof (PedOperationRM)); + if (!operationRM) + goto error; + + PedOperation* new_operation; + new_operation = malloc(sizeof (PedOperation)); + if (!new_operation) + goto error; + + operationRM->num = num; + new_operation->operation = operationRM; + new_operation->prev = NULL; + new_operation->next = NULL; + new_operation->type = PED_OPERATION_RM; + + if (dev->operation == NULL) { + dev->operation = new_operation; + } + else { + PedOperation *operation = dev->operation; + PedOperation *last_operation = dev->operation; + while ((operation = operation->next)) + last_operation = operation; + new_operation->prev = last_operation; + last_operation->next = new_operation; + } + + return 1; + +error: + return 0; +} + + static void _timer_handler (PedTimer* timer, void* context) { @@ -598,10 +691,12 @@ if (!command_line_get_fs_type (_("File system?"), &type)) goto error_destroy_disk; - fs = ped_file_system_create (&part->geom, type, timer); - if (!fs) - goto error_destroy_disk; - ped_file_system_close (fs); + if (!(*dev)->test_mode) { + fs = ped_file_system_create (&part->geom, type, timer); + if (!fs) + goto error_destroy_disk; + ped_file_system_close (fs); + } if (!ped_partition_set_system (part, type)) goto error_destroy_disk; @@ -618,61 +713,66 @@ return 0; } + static int -do_mkpart (PedDevice** dev) +do_true_mkpart (PedDevice** dev, + PedPartitionType part_type, + const PedFileSystemType *fs_type, + PedSector start, + PedSector end, + PedGeometry *range_start, + PedGeometry *range_end, + char *part_name) { - PedDisk* disk; PedPartition* part; - PedPartitionType part_type; + /*PedPartitionType part_type; const PedFileSystemType* fs_type = ped_file_system_type_get ("ext2"); PedSector start = 0, end = 0; - PedGeometry *range_start = NULL, *range_end = NULL; + PedGeometry *range_start = NULL, *range_end = NULL;*/ PedConstraint* user_constraint; PedConstraint* dev_constraint; PedConstraint* final_constraint; char* peek_word; - char* part_name = NULL; + //char* part_name = NULL; char *start_usr = NULL, *end_usr = NULL; char *start_sol = NULL, *end_sol = NULL; - disk = ped_disk_new (*dev); - if (!disk) - goto error; - - if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) { - part_type = PED_PARTITION_NORMAL; - } else { - if (!command_line_get_part_type (_("Partition type?"), - disk, &part_type)) - goto error_destroy_disk; - } - - if (ped_disk_type_check_feature (disk->type, - PED_DISK_TYPE_PARTITION_NAME)) - part_name = command_line_get_word (_("Partition name?"), - "", 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_destroy_disk; + if ((*dev)->test_mode) { + if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) { + part_type = PED_PARTITION_NORMAL; + } else { + if (!command_line_get_part_type (_("Partition type?"), + disk, &part_type)) + goto error; + } + + if (ped_disk_type_check_feature (disk->type, + PED_DISK_TYPE_PARTITION_NAME)) + part_name = command_line_get_word (_("Partition name?"), + "", 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 (!command_line_get_sector (_("Start?"), *dev, &start, &range_start)) + goto error; + if (!command_line_get_sector (_("End?"), *dev, &end, &range_end)) + goto error; } - if (peek_word) - ped_free (peek_word); - - if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start)) - goto error_destroy_disk; - if (!command_line_get_sector (_("End?"), *dev, &end, &range_end)) - goto error_destroy_disk; /* processing starts here */ part = ped_partition_new (disk, part_type, fs_type, start, end); if (!part) - goto error_destroy_disk; + goto error; snap_to_boundaries (&part->geom, NULL, disk, range_start, range_end); @@ -729,24 +829,24 @@ if (part_name) PED_ASSERT (ped_partition_set_name (part, part_name), return 0); if (!ped_partition_set_system (part, fs_type)) - goto error_destroy_disk; + 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_destroy_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 (!(*dev)->test_mode) { + 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); @@ -757,6 +857,16 @@ if (end_sol != NULL) ped_free (end_sol); + disk = ped_disk_commit_test_disk(&disk); + if (!disk) + goto error; + + if ((*dev)->test_mode) { + ped_device_add_operation_mkpart (*dev, part_type, + fs_type, start, end, range_start, range_end, + part_name); + } + return 1; error_remove_part: @@ -768,8 +878,8 @@ ped_constraint_destroy (dev_constraint); error_destroy_part: ped_partition_destroy (part); -error_destroy_disk: - ped_disk_destroy (disk); +/*error_destroy_disk: + ped_disk_destroy (disk);*/ error: if (range_start != NULL) ped_geometry_destroy (range_start); @@ -788,6 +898,29 @@ return 0; } + +static int +do_mkpart (PedDevice** dev) +{ + PedPartition* part; + PedPartitionType part_type; + const PedFileSystemType* fs_type = ped_file_system_type_get ("ext2"); + PedSector start = 0, end = 0; + PedGeometry *range_start = NULL, *range_end = NULL; + 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; + + do_true_mkpart (dev, part_type, fs_type, start, end, + range_start, range_end, part_name); + + return 0; +} + static int do_mkpartfs (PedDevice** dev) { @@ -1183,7 +1316,6 @@ static int do_print (PedDevice** dev) { - PedDisk* disk; PedPartition* part; Table* table; StrList* row; @@ -1200,10 +1332,6 @@ char* tmp; wchar_t* table_rendered; - disk = ped_disk_new (*dev); - if (!disk) - goto error; - peek_word = command_line_peek_word (); if (peek_word) { has_num_arg = isdigit (peek_word[0]); @@ -1368,12 +1496,9 @@ ped_free (table_rendered); table_destroy (table); - ped_disk_destroy (disk); return 1; -error_destroy_disk: - ped_disk_destroy (disk); error: return 0; } @@ -1651,27 +1776,135 @@ } static int -do_rm (PedDevice** dev) +do_undo (PedDevice** dev) +{ + PedOperation *operation = (*dev)->operation; + if (operation == NULL) { + printf("Cannot undo... of course! ;)\n"); + goto error; + } + + PedDisk *old_disk = disk->disk; + ped_disk_destroy(disk); + disk = old_disk; + + old_disk = disk->disk; + ped_disk_destroy(disk); + disk = old_disk; + + disk = ped_disk_commit_test_disk(&disk); + + if (operation->next == NULL) { + printf("No other undo available!\n"); + free(operation); + (*dev)->operation = NULL; + } else { + operation = (*dev)->operation; + PedOperation *last_operation = (*dev)->operation; + while ((operation = operation->next)) + last_operation = operation; + + operation = last_operation->prev; + operation->next = NULL; + free(last_operation); + } + + return 1; + +error: + return 0; +} + +static int +do_true_rm (PedDevice** dev, int num) { - PedDisk* disk; PedPartition* part = NULL; - disk = ped_disk_new (*dev); - if (!disk) - goto error; + part = ped_disk_get_partition (disk, num); + if (!part) + goto error; + + ped_disk_delete_partition (disk, part); + ped_disk_commit (disk); + disk = ped_disk_commit_test_disk(&disk); + + if ((*dev)->test_mode) { + ped_device_add_operation_rm (*dev, num); + } + + return 1; + +error: + return 0; +} + +static int +do_apply (PedDevice** dev) +{ + PedOperation *operation = (*dev)->operation; + if (operation == NULL) { + printf("Cannot apply... of course! ;)\n"); + goto error; + } + + /*Destroy all disk used to save intermediate state*/ + while (disk->disk != NULL) { + PedDisk *old_disk = disk->disk; + ped_disk_destroy(disk); + disk = old_disk; + } + + + /*make a new backup of disk*/ + disk = ped_disk_commit_test_disk(&disk); + ped_device_test_mode(*dev, 0); //test mode off: now committing! + + + /*Do all operation saved!*/ + do { + if (operation->type == PED_OPERATION_RM) { + PedOperationRM *operationRM = operation->operation; + do_true_rm(dev, operationRM->num); + } + if (operation->type == PED_OPERATION_MKPART) { + PedOperationMKPART *operationMKPART = operation->operation; + do_true_mkpart(dev, + operationMKPART->part_type, + operationMKPART->fs_type, + operationMKPART->start, + operationMKPART->end, + operationMKPART->range_start, + operationMKPART->range_end, + operationMKPART->part_name); + } + } while ((operation = operation->next)); + + ped_device_test_mode(*dev, 1); //test mode on + + /*Warning: memory leak, we don't really empty the list of operation! FIX*/ + //FIX mast create an API like "ped_operation_free(dev)"; + (*dev)->operation = NULL; + + return 1; + +error: + return 0; +} + +static int +do_rm (PedDevice** dev) +{ + PedPartition* part = NULL; if (!command_line_get_partition (_("Partition number?"), disk, &part)) - goto error_destroy_disk; + goto error; if (!_partition_warn_busy (part)) - goto error_destroy_disk; + goto error; + + do_true_rm(dev, part->num); - ped_disk_delete_partition (disk, part); - ped_disk_commit (disk); - ped_disk_destroy (disk); return 1; -error_destroy_disk: - ped_disk_destroy (disk); error: return 0; } @@ -2073,6 +2306,30 @@ "copy of GNU Parted\n"), NULL), 1)); +command_register (commands, command_create ( + str_list_create_unique ("undo", _("undo"), NULL), + do_undo, + str_list_create ( +_("undo displays the current undo " +"of GNU Parted and copyright information"), +NULL), + str_list_create ( +_("undo displays copyright and version information corressponding to this " +"copy of GNU Parted\n"), +NULL), 1)); + +command_register (commands, command_create ( + str_list_create_unique ("apply", _("apply"), NULL), + do_apply, + str_list_create ( +_("apply displays the current apply " +"of GNU Parted and copyright information"), +NULL), + str_list_create ( +_("apply displays copyright and version information corressponding to this " +"copy of GNU Parted\n"), +NULL), 1)); + } static void @@ -2146,6 +2403,8 @@ dev = ped_device_get ((*argv_ptr) [0]); if (!dev) return NULL; + /*printf("test mode by Zanac\n");*/ + ped_device_test_mode(dev, 1); (*argc_ptr)--; (*argv_ptr)++; } else { @@ -2235,6 +2494,7 @@ main (int argc, char** argv) { PedDevice* dev; + int status; #ifdef HAVE_GETUID @@ -2248,11 +2508,23 @@ if (!dev) return 1; + //zanac + dev->operation = NULL; + disk = ped_disk_new (dev); + if (!disk) + return 1; + if (argc || opt_script_mode) status = non_interactive_mode (&dev, commands, argc, argv); else status = interactive_mode (&dev, commands); + + PedDisk *orig_disk; + orig_disk = disk->disk; + ped_disk_destroy(disk); + ped_disk_destroy(orig_disk); + _done (dev); return !status;