]> localhost Git - hfdisk.git/commitdiff
Simplied user input, and provided more meaningful defaults.
authorMichael McMaster <michael@codesrc.com>
Thu, 29 May 2014 02:03:35 +0000 (12:03 +1000)
committerMichael McMaster <michael@codesrc.com>
Thu, 29 May 2014 02:03:35 +0000 (12:03 +1000)
dump.c
hfdisk.8
hfdisk.c
hfdisk.h
io.c
io.h
partition_map.c
partition_map.h

diff --git a/dump.c b/dump.c
index 7e9560f2d8c4b68f0753cb87adf51d5ea5561c4b..933107b2d48c325977f3ca2d0db92b4cd09a8081 100644 (file)
--- a/dump.c
+++ b/dump.c
@@ -36,6 +36,7 @@
 #include <errno.h>
 #include <fcntl.h>
 
+#include "hfdisk.h"
 #include "io.h"
 #include "errors.h"
 #include "partition_map.h"
 //
 // Types
 //
-typedef struct names {
-    char *abbr;
-    char *full;
-} NAMES;
 
 
 //
 // Global Constants
 //
-NAMES plist[] = {
-    {"Drvr", "Apple_Driver"},
-    {"Dr43", "Apple_Driver43"},
-    {"Free", "Apple_Free"},
-    {" HFS", "Apple_HFS"},
-    {" MFS", "Apple_MFS"},
-    {"PDOS", "Apple_PRODOS"},
-    {"junk", "Apple_Scratch"},
-    {"unix", "Apple_UNIX_SVR2"},
-    {" map", "Apple_partition_map"},
-    {0,        0}
-};
 
 const char * kStringEmpty      = "";
 const char * kStringNot                = " not";
index 01eaa8114fda04ef3b00eb523f91188680ae9f1f..0c9cb547be6081a2faff423afaeefe0a6fd0dab9 100644 (file)
--- a/hfdisk.8
+++ b/hfdisk.8
@@ -1,15 +1,15 @@
-.TH PDISK 8 "20 December 1996" "MkLinux DR2" "Linux Programmer's Manual"
+.TH HFDISK 8 "20 December 1996" "MkLinux DR2" "Linux Programmer's Manual"
 .SH NAME
-pdisk \- Apple partition table editor for Linux
+hfdisk \- Apple partition table editor
 .SH SYNOPSIS
-.B pdisk
+.B hfdisk
 .B "[\-h|\--help] [\-v|\--version] [\-l|\--list [name ...]]"
 .br
-.B pdisk
+.B hfdisk
 .B "[\-r|\--readonly]"
 device ...
 .SH DESCRIPTION
-.B pdisk
+.B hfdisk
 is a menu driven program which partitions disks using the standard Apple
 disk partitioning scheme described in "Inside Macintosh: Devices".
 It does not support the intel/dos partitioning scheme supported by 
@@ -52,12 +52,12 @@ is the partition described by the second entry in the partiton map on /dev/sda.
 .TP
 .B \-v | \--version
 Prints version number of the
-.B pdisk
+.B hfdisk
 program.
 .TP
 .B \-h | \--help
 Prints a rather lame set of help messages for the
-.B pdisk
+.B hfdisk
 program.
 .TP
 .B \-l | \--list
@@ -77,13 +77,13 @@ Otherwise, lists the partition tables for the specified
 .TP
 .B \-r | \--readonly
 Prevents
-.B pdisk
+.B hfdisk
 from writing to the device.
 .SH "Editing Partition Tables"
 An argument which is simply the name of a
 .I device
 indicates that
-.B pdisk
+.B hfdisk
 should edit the partition table of that device.
 
 The current top level editing commands are:
@@ -129,12 +129,8 @@ The
 .B c
 (create new partition) command is the only one with complicated arguments.
 The first argument is the base address (in blocks) of the partition.
-Besides a raw number, you can also specify a partition number followed
-by the letter 'p' to indicate that the first block of the new partition should
-be the same as the first block of that existing free  space partition.
 The second argument is the length of the partition in blocks.
-This can be a raw number or can be a partition number followed by the
-letter 'p' to use the size of that partition or can be a number followed
+This can be a raw number or can be a number followed
 by 'k', 'm', or 'g' to indicate the size in kilobytes, megabytes, or gigabytes
 respectively.
 (These are powers of 1024, of course, not powers of 1000.)
@@ -170,7 +166,7 @@ In order to use the new partition map you must reboot.
 .SH BUGS
 Some people believe there should really be just one disk partitioning utility.
 .br
-.B pdisk
+.B hfdisk
 should be able to create HFS partitions that work.
 .br
 Even more help should be available during user input.
index 9b0aba0596f7f32a330fe135dfab56103d68884e..ec58652ea3dad9da071ae7572231a507d6ee38e0 100644 (file)
--- a/hfdisk.c
+++ b/hfdisk.c
@@ -33,6 +33,7 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
+#include <inttypes.h>
 
 #include <sys/ioctl.h>
 
@@ -65,6 +66,19 @@ enum getopt_values {
     kListOption = 1001
 };
 
+const NAMES plist[] = {
+       {"Drvr", "Apple_Driver"},
+       {"Dr43", "Apple_Driver43"},
+       {"Free", "Apple_Free"},
+       {" HFS", "Apple_HFS"},
+       {" MFS", "Apple_MFS"},
+       {"PDOS", "Apple_PRODOS"},
+       {"junk", "Apple_Scratch"},
+       {"unix", "Apple_UNIX_SVR2"},
+       {" map", "Apple_partition_map"},
+       {0, 0}
+};
+
 
 //
 // Global Variables
@@ -90,8 +104,7 @@ void do_reorder(partition_map_header *map);
 void do_write_partition_map(partition_map_header *map);
 void edit(char *name);
 int get_base_argument(long *number, partition_map_header *map);
-int get_command_line(int *argc, char ***argv);
-int get_size_argument(long *number, partition_map_header *map);
+int get_size_argument(uint32_t base, long *number, partition_map_header *map);
 int get_options(int argc, char **argv);
 void print_notes();
 
@@ -270,7 +283,6 @@ edit(char *name)
            break;
        case 'Q':
        case 'q':
-           flush_to_newline(1);
            goto finis;
            break;
        case 'I':
@@ -304,7 +316,6 @@ edit(char *name)
            if (!dflag) {
                goto do_error;
            } else if (do_expert(map)) {
-               flush_to_newline(0);
                goto finis;
            }
            break;
@@ -345,7 +356,7 @@ do_create_partition(partition_map_header *map, int get_type)
     if (get_base_argument(&base, map) == 0) {
        return;
     }
-    if (get_size_argument(&length, map) == 0) {
+    if (get_size_argument(base, &length, map) == 0) {
        return;
     }
 
@@ -356,17 +367,27 @@ do_create_partition(partition_map_header *map, int get_type)
     if (get_type == 0) {
        add_partition_to_map(name, kUnixType, base, length, map);
 
-    } else if (get_string_argument("Type of partition: ", &type_name, 1) == 0) {
-       bad_input("Bad type");
-       return;
     } else {
-       if (strncmp(type_name, kFreeType, DPISTRLEN) == 0) {
-           bad_input("Can't create a partition with the Free type");
-           return;
-       }
-       if (strncmp(type_name, kMapType, DPISTRLEN) == 0) {
-           bad_input("Can't create a partition with the Map type");
-           return;
+       while (1) {
+           if (get_string_argument("Type of partition (L for known types): ", &type_name, 1) == 0) {
+             bad_input("Bad type");
+             return;
+            } else if (strncmp(type_name, kFreeType, DPISTRLEN) == 0) {
+                   bad_input("Can't create a partition with the Free type");
+           } else if (strncmp(type_name, kMapType, DPISTRLEN) == 0) {
+                   bad_input("Can't create a partition with the Map type");
+           } else if (strncmp(type_name, "L", DPISTRLEN) == 0) {
+               int i = 0;
+               while (plist[i].full) {
+                   printf("%s\n", plist[i].full);
+                   ++i;
+               }
+               printf("\n");
+           }
+               else
+               {
+                       break;
+               }
        }
        add_partition_to_map(name, type_name, base, length, map);
     }
@@ -400,62 +421,47 @@ do_create_bootstrap_partition(partition_map_header *map)
 int
 get_base_argument(long *number, partition_map_header *map)
 {
-    partition_map * entry;
-    int c;
     int result = 0;
 
-    if (get_number_argument("First block: ", number, kDefault) == 0) {
+    uint32_t defaultFirstBlock = find_free_space(map);
+    char prompt[32];
+    sprintf(prompt, "First block [%"PRIu32"]: ", defaultFirstBlock);
+    if (get_number_argument(prompt, number, defaultFirstBlock) == 0) {
        bad_input("Bad block number");
     } else {
        result = 1;
-       c = getch();
-
-       if (c == 'p' || c == 'P') {
-           entry = find_entry_by_disk_address(*number, map);
-           if (entry == NULL) {
-               bad_input("Bad partition number");
-               result = 0;
-           } else {
-               *number = entry->data->dpme_pblock_start;
-           }
-       } else if (c > 0) {
-           ungetch(c);
-       }
     }
     return result;
 }
 
 
 int
-get_size_argument(long *number, partition_map_header *map)
+get_size_argument(uint32_t base, long *number, partition_map_header *map)
 {
-    partition_map * entry;
-    int c;
     int result = 0;
-    long multiple;
 
-    if (get_number_argument("Length (in blocks, kB (k), MB (M) or GB (G)): ", number, kDefault) == 0) {
+    uint32_t defaultSize = 20480; // 10MB
+
+    // Work out how much free-space is available.
+    partition_map* part = find_entry_by_sector(base, map);
+    if (part)
+    {
+       size_t partEnd =
+           part->data->dpme_pblock_start +
+           part->data->dpme_pblocks;
+       defaultSize = partEnd - base;
+    }
+
+    char prompt[80];
+    sprintf(
+       prompt,
+       "Length (in blocks, kB (k), MB (M) or GB (G)) [%"PRIu32"]: ",
+       defaultSize);
+
+    if (get_number_argument(prompt, number, defaultSize) == 0) {
        bad_input("Bad length");
     } else {
        result = 1;
-       multiple = get_multiplier(PBLOCK_SIZE);
-       if (multiple != 1) {
-           *number *= multiple;
-       } else {
-           c = getch();
-
-           if (c == 'p' || c == 'P') {
-               entry = find_entry_by_disk_address(*number, map);
-               if (entry == NULL) {
-                   bad_input("Bad partition number");
-                   result = 0;
-               } else {
-                   *number = entry->data->dpme_pblocks;
-               }
-           } else if (c > 0) {
-               ungetch(c);
-           }
-       }
     }
     return result;
 }
@@ -536,7 +542,7 @@ do_write_partition_map(partition_map_header *map)
     printf("the map causes all data on that partition to be LOST FOREVER. \n");
     printf("Make sure you have a backup of any data on such partitions you \n");
     printf("want to keep before answering 'yes' to the question below! \n\n");
-    if (get_okay("Write partition map? [n/y]: ", 0) != 1) {
+    if (get_okay("Write partition map? [N/y]: ") != 1) {
        return;
     }
 
@@ -579,7 +585,6 @@ do_expert(partition_map_header *map)
            break;
        case 'X':
        case 'x':
-           flush_to_newline(1);
            goto finis;
            break;
        case 'Q':
index b1f9e3b333b801bf10b4f69048f33c450afcbf9f..633eaf6b568a37e567a387c1aa6ccd3fc9f99437 100644 (file)
--- a/hfdisk.h
+++ b/hfdisk.h
 //
 // Types
 //
+typedef struct names {
+       char *abbr;
+       char *full;
+} NAMES;
 
 
 //
 // Global Constants
 //
+extern const NAMES plist[];
 
 
 //
diff --git a/io.c b/io.c
index 62970303ada5b02caa6ebdec33a4a41e44100ef1..4a3a81ad39501cd639ccf80f9d64852518f67049 100644 (file)
--- a/io.c
+++ b/io.c
@@ -60,324 +60,127 @@ const long kDefault = -1;
 //
 // Global Variables
 //
-short unget_buf[UNGET_MAX_COUNT+1];
-int unget_count;
 
 
 //
 // Forward declarations
 //
-long get_number(int first_char);
-char* get_string(int eos);
 
 
 //
 // Routines
 //
-int
-getch()
-{
-    if (unget_count > 0) {
-       return (unget_buf[--unget_count]);
-    } else {
-       return (getc(stdin));
-    }
-}
-
-
-void
-ungetch(int c)
-{
-    // In practice there is never more than one character in
-    // the unget_buf, but what's a little overkill among friends?
-
-    if (unget_count < UNGET_MAX_COUNT) {
-       unget_buf[unget_count++] = c;
-    } else {
-       fatal(-1, "Programmer error in ungetch().");
-    }
-}
-
-       
-void
-flush_to_newline(int keep_newline)
-{
-    int                c;
-
-    for (;;) {
-       c = getch();
-
-       if (c <= 0) {
-           break;
-       } else if (c == '\n') {
-           if (keep_newline) {
-               ungetch(c);
-           }
-           break;
-       } else {
-           // skip
-       }
-    }
-    return;
-}
 
 
 int
-get_okay(char *prompt, int default_value)
+get_okay(char *prompt)
 {
-    int                c;
-
-    flush_to_newline(0);
-    printf("%s", prompt);
-
-    for (;;) {
-       c = getch();
-
-       if (c <= 0) {
-           break;
-       } else if (c == ' ' || c == '\t') {
-           // skip blanks and tabs
-       } else if (c == '\n') {
-           ungetch(c);
-           return default_value;
-       } else if (c == 'y' || c == 'Y') {
-           return 1;
-       } else if (c == 'n' || c == 'N') {
-           return 0;
-       } else {
-           flush_to_newline(0);
-           printf("%s", prompt);
+    int result = 0;
+    char* string = NULL;
+    if (get_string_argument(prompt, &string, 1))
+    {
+       if (string[0] == 'Y' || string[0] == 'y')
+       {
+           result = 1;
        }
     }
-    return -1;
+    free(string);
+    return result;
 }
 
        
 int
 get_command(char *prompt, int promptBeforeGet, int *command)
 {
-    int                c;
-
-    if (promptBeforeGet) {
-       printf("%s", prompt);
-    }  
-    for (;;) {
-       c = getch();
-
-       if (c <= 0) {
-           break;
-       } else if (c == ' ' || c == '\t') {
-           // skip blanks and tabs
-       } else if (c == '\n') {
-           printf("%s", prompt);
-       } else {
-           *command = c;
-           return 1;
-       }
+    int result = 0;
+    char* string = NULL;
+    if (get_string_argument(prompt, &string, 1))
+    {
+       *command = string[0];
+       result = 1;
     }
-    return 0;
+    free(string);
+    return result;
+
 }
 
        
 int
 get_number_argument(char *prompt, long *number, long default_value)
 {
-    int c;
     int result = 0;
 
-    for (;;) {
-       c = getch();
+    char* buf = NULL;
+    size_t buflen = 0;
+    char multiplier;
+    int matched;
 
-       if (c <= 0) {
+    while (result == 0) {
+       printf("%s", prompt);
+
+       if (getline(&buf, &buflen, stdin) == -1)
+       {
+           // EOF
            break;
-       } else if (c == ' ' || c == '\t') {
-           // skip blanks and tabs
-       } else if (c == '\n') {
-           if (default_value < 0) {
-               printf("%s", prompt);
-           } else {
-               ungetch(c);
-               *number = default_value;
-               result = 1;
-               break;
-           }
-       } else if ('0' <= c && c <= '9') {
-           *number = get_number(c);
+       }
+       else if ((default_value > 0) && (strncmp(buf, "\n", 1) == 0))
+       {
+           *number = default_value;
            result = 1;
            break;
-       } else {
-           ungetch(c);
-           *number = 0;
-           break;
+       }
+       else if ((matched = sscanf(buf, "%ld%c", number, &multiplier)) >= 1)
+       {
+           result = 1;
+           if (matched == 2) {
+               if (multiplier == 'g' || multiplier == 'G') {
+                   *number *= (1024*1024*1024 / PBLOCK_SIZE);
+               } else if (multiplier == 'm' || multiplier == 'M') {
+                   *number *= (1024*1024 / PBLOCK_SIZE);
+               } else if (multiplier == 'k' || multiplier == 'K') {
+                   *number *= (1024 / PBLOCK_SIZE);
+               } else if (multiplier != '\n') {
+                   result = 0;
+               }
+           }
        }
     }
+    free(buf);
     return result;
 }
 
 
-long
-get_number(int first_char)
-{
-    register int c;
-    int base;
-    int digit;
-    int ret_value;
-
-    if (first_char != '0') {
-       c = first_char;
-       base = 10;
-       digit = BAD_DIGIT;
-    } else if ((c=getch()) == 'x' || c == 'X') {
-       c = getch();
-       base = 16;
-       digit = BAD_DIGIT;
-    } else {
-       c = first_char;
-       base = 8;
-       digit = 0;
-    }
-    ret_value = 0;
-    for (ret_value = 0; ; c = getch()) {
-       if (c >= '0' && c <= '9') {
-           digit = c - '0';
-       } else if (c >='A' && c <= 'F') {
-           digit = 10 + (c - 'A');
-       } else if (c >='a' && c <= 'f') {
-           digit = 10 + (c - 'a');
-       } else {
-           digit = BAD_DIGIT;
-       }
-       if (digit >= base) {
-           break;
-       }
-       ret_value = ret_value * base + digit;
-    }
-    ungetch(c);
-    return(ret_value);
-}
-
-       
 int
 get_string_argument(char *prompt, char **string, int reprompt)
 {
-    int c;
     int result = 0;
+    size_t buflen = 0;
 
-    for (;;) {
-       c = getch();
+    while (result == 0) {
+       printf("%s", prompt);
 
-       if (c <= 0) {
-           break;
-       } else if (c == ' ' || c == '\t') {
-           // skip blanks and tabs
-       } else if (c == '\n') {
-           if (reprompt) {
-               printf("%s", prompt);
-           } else {
-               ungetch(c);
-               *string = NULL;
-               break;
-           }
-       } else if (c == '"' || c == '\'') {
-           *string = get_string(c);
-           result = 1;
-           break;
-       } else if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
-               || (c == '-' || c == '/')) {
-           ungetch(c);
-           *string = get_string(' ');
-           result = 1;
-           break;
-       } else {
-           ungetch(c);
-           *string = NULL;
+       if (getline(string, &buflen, stdin) == -1)
+       {
+           // EOF
            break;
        }
-    }
-    return result;
-}
-
-
-char *
-get_string(int eos)
-{
-    int c;
-    char *s;
-    char *ret_value;
-    char *limit;
-    int length;
-
-    ret_value = (char *) malloc(STRING_CHUNK);
-    if (ret_value == NULL) {
-       error(errno, "can't allocate memory for string buffer");
-       return NULL;
-    }
-    length = STRING_CHUNK;
-    limit = ret_value + length;
-
-    c = getch();
-    for (s = ret_value; ; c = getch()) {
-       if (s >= limit) {
-           // expand string
-           limit = (char *) malloc(length+STRING_CHUNK);
-           if (limit == NULL) {
-               error(errno, "can't allocate memory for string buffer");
-               ret_value[length-1] = 0;
-               break;
-           }
-           strncpy(limit, ret_value, length);
-           free(ret_value);
-           s = limit + (s - ret_value);
-           ret_value = limit;
-           length += STRING_CHUNK;
-           limit = ret_value + length;
-       }
-       if (c <= 0 || c == eos || (eos == ' ' && c == '\t')) {
-           *s++ = 0;
+       else if ((strncmp(*string, "\n", 1) == 0) && !reprompt)
+       {
+           result = 0;
            break;
-       } else if (c == '\n') {
-           *s++ = 0;
-           ungetch(c);
-           break;
-       } else {
-           *s++ = c;
        }
-    }
-    return(ret_value);
-}
-
-
-long
-get_multiplier(long divisor)
-{
-    int c;
-    int result;
-
-    c = getch();
-
-    if (c <= 0 || divisor <= 0) {
-       result = 0;
-    } else if (c == 'g' || c == 'G') {
-       result = 1024*1024*1024;
-    } else if (c == 'm' || c == 'M') {
-       result = 1024*1024;
-    } else if (c == 'k' || c == 'K') {
-       result = 1024;
-    } else {
-       ungetch(c);
-       result = 1;
-    }
-    if (result > 1) {
-       if (result >= divisor) {
-           result /= divisor;
-       } else {
+       else
+       {
+           size_t len = strnlen(*string, buflen);
+           if ((*string)[len - 1] == '\n') {
+               (*string)[len - 1] = '\0';
+           }
            result = 1;
        }
     }
     return result;
 }
 
-
 int
 number_of_digits(unsigned long value)
 {
@@ -404,7 +207,6 @@ bad_input(char *fmt, ...)
     vfprintf(stderr, fmt, ap);
     va_end(ap);
     fprintf(stderr, "\n");
-    flush_to_newline(1);
 }
 
 
diff --git a/io.h b/io.h
index 9561b344f092e28f26d6a9000eb02414d43f3ec8..dce3e3716f5438c9cd465d3559fce122b837abf6 100644 (file)
--- a/io.h
+++ b/io.h
@@ -53,15 +53,11 @@ extern const long kDefault;
 //
 void bad_input(char *fmt, ...);
 int close_device(int fildes);
-void flush_to_newline(int keep_newline);
 int get_command(char *prompt, int promptBeforeGet, int *command);
-long get_multiplier(long divisor);
 int get_number_argument(char *prompt, long *number, long default_value);
-int get_okay(char *prompt, int default_value);
+int get_okay(char *prompt);
 int get_string_argument(char *prompt, char **string, int reprompt);
-int getch();
 int number_of_digits(unsigned long value);
 int open_device(const char *path, int oflag);
 int read_block(int fd, unsigned long num, char *buf, int quiet);
-void ungetch(int c);
 int write_block(int fd, unsigned long num, char *buf);
index d191df9156b5b8e5ab600fc71cc526a05223ff49..67033862c28f41f385b08e7af873a3b6a1993255 100644 (file)
@@ -365,7 +365,7 @@ init_partition_map(char *name, partition_map_header* oldmap)
 
     if (oldmap != NULL) {
        printf("map already exists\n");
-       if (get_okay("do you want to reinit? [n/y]: ", 0) != 1) {
+       if (get_okay("do you want to reinit? [N/y]: ") != 1) {
            return oldmap;
        }
     }
@@ -414,9 +414,9 @@ create_partition_map(char *name)
     map->maximum_in_map = -1;
 
     number = compute_device_size(fd);
-    printf("size of 'device' is %lu blocks: ", number);
-    flush_to_newline(0);
-    get_number_argument("what should be the size? ", (long *)&number, number);
+    char prompt[64];
+    sprintf(prompt, "Device block size [%lu]: ", number);
+    get_number_argument(prompt, (long *)&number, number);
     if (number < 4) {
        number = 4;
     }
@@ -678,7 +678,6 @@ compute_device_size(int fd)
        if (valid != 0) {
            x = x + 1;
        }
-       // printf("size in blocks = %d\n", x);
        free(data);
     }
 
@@ -1002,3 +1001,38 @@ resize_map(long new_size, partition_map_header *map)
     delete_partition_from_map(entry);
     add_partition_to_map("Apple", kMapType, 1, new_size, map);
 }
+
+uint32_t
+find_free_space(partition_map_header *map)
+{
+    partition_map * cur;
+    uint32_t result = -1;
+
+    // find a block that starts includes base and length
+    cur = map->base_order;
+    while (cur != NULL) {
+       if (strncmp(cur->data->dpme_type, kFreeType, DPISTRLEN) == 0) {
+           result = cur->data->dpme_pblock_start;
+           break;
+       } else {
+           cur = cur->next_by_base;
+       }
+    }
+    return result;
+}
+
+partition_map*
+find_entry_by_sector(uint32_t lba, partition_map_header *map)
+{
+    partition_map* cur = map->base_order;
+    while (cur != NULL) {
+       if ((cur->data->dpme_pblock_start <= lba) &&
+           (lba < cur->data->dpme_pblock_start + cur->data->dpme_pblocks)) {
+           break;
+       } else {
+           cur = cur->next_by_base;
+       }
+    }
+    return cur;
+}
+
index abf6d131cbb1f6cc51dcbc83cf07749c6ce40360..05e43c22f2d80e7262284d7c31153843aafd3333 100644 (file)
@@ -75,10 +75,12 @@ int add_partition_to_map(const char *name, const char *dptype, uint32_t base, ui
 void close_partition_map(partition_map_header *map);
 void delete_partition_from_map(partition_map *entry);
 partition_map* find_entry_by_disk_address(long index, partition_map_header *map);
+partition_map* find_entry_by_sector(uint32_t lba, partition_map_header *map);
 partition_map_header* init_partition_map(char *name, partition_map_header* oldmap);
 void move_entry_in_map(long old_index, long index, partition_map_header *map);
 partition_map_header* open_partition_map(char *name, int *valid_file);
 void resize_map(long new_size, partition_map_header *map);
 void write_partition_map(partition_map_header *map);
+uint32_t find_free_space(partition_map_header *map);
 
 #endif