1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cgpt.h"
#include <string.h>
#include "cgptlib_internal.h"
#include "cgpt_params.h"
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->driveName, &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;
}
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");
return CGPT_FAILED;
}
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;
}
index = params->partition - 1;
entry = GetEntry(&drive.gpt, PRIMARY, index);
} else {
// find next empty partition
for (index = 0; index < max_part; index++) {
entry = GetEntry(&drive.gpt, PRIMARY, index);
if (IsZero(&entry->type)) {
params->partition = index + 1;
break;
}
}
if (index >= max_part) {
Error("no unused partitions available\n");
goto bad;
}
}
// New partitions must specify type, begin, and size.
if (IsZero(&entry->type)) {
if (!params->set_begin || !params->set_size || !params->set_type) {
Error("-t, -b, and -s options are required for new partitions\n");
goto bad;
}
if (IsZero(¶ms->type_guid)) {
Error("New partitions must have a type other than \"unused\"\n");
goto bad;
}
if (!params->set_unique)
uuid_generate((uint8_t *)&entry->unique);
}
if (params->set_begin)
entry->starting_lba = params->begin;
if (params->set_size)
entry->ending_lba = params->begin + params->size - 1;
if (params->set_type)
memcpy(&entry->type, ¶ms->type_guid, sizeof(Guid));
if (params->set_unique)
memcpy(&entry->unique, ¶ms->unique_guid, sizeof(Guid));
if (params->label) {
if (CGPT_OK != UTF8ToUTF16((uint8_t *)params->label, entry->name,
sizeof(entry->name) / sizeof(entry->name[0]))) {
Error("The label cannot be converted to UTF16.\n");
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);
}
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:
(void) DriveClose(&drive, 0);
return CGPT_FAILED;
}
|