summaryrefslogtreecommitdiff
path: root/cgpt/cgpt_add.c
diff options
context:
space:
mode:
Diffstat (limited to 'cgpt/cgpt_add.c')
-rw-r--r--cgpt/cgpt_add.c188
1 files changed, 172 insertions, 16 deletions
diff --git a/cgpt/cgpt_add.c b/cgpt/cgpt_add.c
index f989fe4d..5a3aeec7 100644
--- a/cgpt/cgpt_add.c
+++ b/cgpt/cgpt_add.c
@@ -9,8 +9,27 @@
#include "cgptlib_internal.h"
#include "cgpt_params.h"
-int cgpt_add(CgptAddParams *params) {
+// This is an internal helper function which assumes no NULL args are passed.
+// It sets the given attribute values for a single entry at the given index.
+static void set_entry_attributes(struct drive drive,
+ GptEntry *entry,
+ uint32_t index,
+ CgptAddParams *params) {
+ if (params->set_raw) {
+ entry->attrs.fields.gpt_att = params->raw_value;
+ } else {
+ if (params->set_successful)
+ SetSuccessful(&drive.gpt, PRIMARY, index, params->successful);
+ if (params->set_tries)
+ SetTries(&drive.gpt, PRIMARY, index, params->tries);
+ if (params->set_priority)
+ SetPriority(&drive.gpt, PRIMARY, index, params->priority);
+ }
+}
+// Set the attributes such as is_successful, num_tries_left, priority, etc.
+// from the given values in params.
+int cgpt_set_attributes(CgptAddParams *params) {
struct drive drive;
int gpt_retval;
@@ -20,20 +39,164 @@ int cgpt_add(CgptAddParams *params) {
if (params == NULL)
return CGPT_FAILED;
- if (CGPT_OK != DriveOpen(params->driveName, &drive))
+ if (CGPT_OK != DriveOpen(params->drive_name, &drive))
return CGPT_FAILED;
if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
Error("GptSanityCheck() returned %d: %s\n",
gpt_retval, GptError(gpt_retval));
- return CGPT_FAILED;
+ goto bad;
}
if (((drive.gpt.valid_headers & MASK_BOTH) != MASK_BOTH) ||
((drive.gpt.valid_entries & MASK_BOTH) != MASK_BOTH)) {
Error("one of the GPT header/entries is invalid.\n"
"please run 'cgpt repair' before adding anything.\n");
+ goto bad;
+ }
+
+ if (params->partition == 0) {
+ Error("invalid partition number: %d\n", params->partition);
+ goto bad;
+ }
+
+ uint32_t max_part = GetNumberOfEntries(&drive.gpt);
+ if (params->partition > max_part) {
+ Error("invalid partition number: %d\n", params->partition);
+ goto bad;
+ }
+
+ index = params->partition - 1;
+ entry = GetEntry(&drive.gpt, PRIMARY, index);
+
+ set_entry_attributes(drive, entry, index, params);
+
+ RepairEntries(&drive.gpt, MASK_PRIMARY);
+ RepairHeader(&drive.gpt, MASK_PRIMARY);
+
+ drive.gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
+ GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2);
+ UpdateCrc(&drive.gpt);
+
+ // Write it all out.
+ return DriveClose(&drive, 1);
+
+bad:
+ DriveClose(&drive, 0);
+ return CGPT_FAILED;
+}
+
+// This method gets the partition details such as the attributes, the
+// guids of the partitions, etc. Input is the partition number or the
+// unique id of the partition. Output is populated in the respective
+// fields of params.
+int cgpt_get_partition_details(CgptAddParams *params) {
+ struct drive drive;
+
+ int gpt_retval;
+ GptEntry *entry;
+ uint32_t index;
+ int result = CGPT_FAILED;
+
+ if (params == NULL)
+ return result;
+
+ if (CGPT_OK != DriveOpen(params->drive_name, &drive)) {
+ Error("Unable to open drive: %s\n", params->drive_name);
+ return result;
+ }
+
+ if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
+ Error("GptSanityCheck() returned %d: %s\n",
+ gpt_retval, GptError(gpt_retval));
+ goto bad;
+ }
+
+ if (((drive.gpt.valid_headers & MASK_BOTH) != MASK_BOTH) ||
+ ((drive.gpt.valid_entries & MASK_BOTH) != MASK_BOTH)) {
+ Error("one of the GPT header/entries is invalid.\n"
+ "please run 'cgpt repair' before adding anything.\n");
+ goto bad;
+ }
+
+ uint32_t max_part = GetNumberOfEntries(&drive.gpt);
+
+ if (params->partition) {
+ if (params->partition > max_part) {
+ Error("invalid partition number: %d\n", params->partition);
+ goto bad;
+ }
+
+ // A valid partition number has been specified, so get the entry directly.
+ index = params->partition - 1;
+ entry = GetEntry(&drive.gpt, PRIMARY, index);
+ } else {
+ // Partition number is not specified, try looking up by the unique id.
+ if (!params->set_unique) {
+ Error("either partition or unique_id must be specified\n");
+ goto bad;
+ }
+
+ // A unique id is specified. find the entry that matches it.
+ for (index = 0; index < max_part; index++) {
+ entry = GetEntry(&drive.gpt, PRIMARY, index);
+ if (GuidEqual(&entry->unique, &params->unique_guid)) {
+ params->partition = index + 1;
+ break;
+ }
+ }
+
+ if (index >= max_part) {
+ Error("no partitions with the given unique id available\n");
+ goto bad;
+ }
+ }
+
+ // At this point, irrespective of whether a partition number is specified
+ // or a unique id is specified, we have valid non-null values for all these:
+ // index, entry, params->partition.
+
+ params->begin = entry->starting_lba;
+ params->size = entry->ending_lba - entry->starting_lba + 1;
+ memcpy(&params->type_guid, &entry->type, sizeof(Guid));
+ memcpy(&params->unique_guid, &entry->unique, sizeof(Guid));
+
+ params->raw_value = entry->attrs.fields.gpt_att;
+ params->successful = GetSuccessful(&drive.gpt, PRIMARY, index);
+ params->tries = GetTries(&drive.gpt, PRIMARY, index);
+ params->priority = GetPriority(&drive.gpt, PRIMARY, index);
+ result = CGPT_OK;
+
+bad:
+ DriveClose(&drive, 0);
+ return result;
+}
+
+
+int cgpt_add(CgptAddParams *params) {
+ struct drive drive;
+
+ int gpt_retval;
+ GptEntry *entry;
+ uint32_t index;
+
+ if (params == NULL)
+ return CGPT_FAILED;
+
+ if (CGPT_OK != DriveOpen(params->drive_name, &drive))
return CGPT_FAILED;
+
+ if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
+ Error("GptSanityCheck() returned %d: %s\n",
+ gpt_retval, GptError(gpt_retval));
+ goto bad;
+ }
+
+ if (((drive.gpt.valid_headers & MASK_BOTH) != MASK_BOTH) ||
+ ((drive.gpt.valid_entries & MASK_BOTH) != MASK_BOTH)) {
+ Error("one of the GPT header/entries is invalid.\n"
+ "please run 'cgpt repair' before adding anything.\n");
+ goto bad;
}
uint32_t max_part = GetNumberOfEntries(&drive.gpt);
@@ -45,7 +208,7 @@ int cgpt_add(CgptAddParams *params) {
index = params->partition - 1;
entry = GetEntry(&drive.gpt, PRIMARY, index);
} else {
- // find next empty partition
+ // Find next empty partition.
for (index = 0; index < max_part; index++) {
entry = GetEntry(&drive.gpt, PRIMARY, index);
if (IsZero(&entry->type)) {
@@ -88,16 +251,8 @@ int cgpt_add(CgptAddParams *params) {
goto bad;
}
}
- if (params->set_raw) {
- entry->attrs.fields.gpt_att = params->raw_value;
- } else {
- if (params->set_successful)
- SetSuccessful(&drive.gpt, PRIMARY, index, params->successful);
- if (params->set_tries)
- SetTries(&drive.gpt, PRIMARY, index, params->tries);
- if (params->set_priority)
- SetPriority(&drive.gpt, PRIMARY, index, params->priority);
- }
+
+ set_entry_attributes(drive, entry, index, params);
RepairEntries(&drive.gpt, MASK_PRIMARY);
RepairHeader(&drive.gpt, MASK_PRIMARY);
@@ -106,10 +261,11 @@ int cgpt_add(CgptAddParams *params) {
GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2);
UpdateCrc(&drive.gpt);
- // Write it all out
+ // Write it all out.
return DriveClose(&drive, 1);
bad:
- (void) DriveClose(&drive, 0);
+ DriveClose(&drive, 0);
return CGPT_FAILED;
}
+