write_ia64_disk.c revision 121921
1105816Sphk/*
2121921Smarcel * Copyright (c) 2003 Marcel Moolenaar
3121921Smarcel * All rights reserved.
4121921Smarcel *
5121921Smarcel * Redistribution and use in source and binary forms, with or without
6121921Smarcel * modification, are permitted provided that the following conditions
7121921Smarcel * are met:
8121921Smarcel *
9121921Smarcel * 1. Redistributions of source code must retain the above copyright
10121921Smarcel *    notice, this list of conditions and the following disclaimer.
11121921Smarcel * 2. Redistributions in binary form must reproduce the above copyright
12121921Smarcel *    notice, this list of conditions and the following disclaimer in the
13121921Smarcel *    documentation and/or other materials provided with the distribution.
14121921Smarcel *
15121921Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16121921Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17121921Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18121921Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19121921Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20121921Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21121921Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22121921Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23121921Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24121921Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25121921Smarcel *
26121921Smarcel * CRC32 code derived from work by Gary S. Brown.
27105816Sphk */
28105816Sphk
29105816Sphk#include <sys/cdefs.h>
30105816Sphk__FBSDID("$FreeBSD: head/lib/libdisk/write_ia64_disk.c 121921 2003-11-03 03:18:34Z marcel $");
31105816Sphk
32105816Sphk#include <sys/types.h>
33105816Sphk#include <sys/disklabel.h>
34105816Sphk#include <sys/diskmbr.h>
35121921Smarcel#include <sys/gpt.h>
36121921Smarcel#include <sys/stat.h>
37121921Smarcel
38121921Smarcel#include <errno.h>
39121921Smarcel#include <fcntl.h>
40105816Sphk#include <paths.h>
41121921Smarcel#include <stddef.h>
42121921Smarcel#include <stdio.h>
43121921Smarcel#include <stdlib.h>
44121921Smarcel#include <string.h>
45121921Smarcel#include <unistd.h>
46121921Smarcel#include <uuid.h>
47121921Smarcel
48105816Sphk#include "libdisk.h"
49105816Sphk
50121921Smarcelstatic uuid_t _efi = GPT_ENT_TYPE_EFI;
51121921Smarcelstatic uuid_t _fbsd = GPT_ENT_TYPE_FREEBSD;
52121921Smarcelstatic uuid_t _swap = GPT_ENT_TYPE_FREEBSD_SWAP;
53121921Smarcelstatic uuid_t _ufs = GPT_ENT_TYPE_FREEBSD_UFS;
54121921Smarcel
55121921Smarcelstatic uint32_t crc32_tab[] = {
56121921Smarcel	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
57121921Smarcel	0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
58121921Smarcel	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
59121921Smarcel	0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
60121921Smarcel	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
61121921Smarcel	0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
62121921Smarcel	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
63121921Smarcel	0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
64121921Smarcel	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
65121921Smarcel	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
66121921Smarcel	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
67121921Smarcel	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
68121921Smarcel	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
69121921Smarcel	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
70121921Smarcel	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
71121921Smarcel	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
72121921Smarcel	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
73121921Smarcel	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
74121921Smarcel	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
75121921Smarcel	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
76121921Smarcel	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
77121921Smarcel	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
78121921Smarcel	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
79121921Smarcel	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
80121921Smarcel	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
81121921Smarcel	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
82121921Smarcel	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
83121921Smarcel	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
84121921Smarcel	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
85121921Smarcel	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
86121921Smarcel	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
87121921Smarcel	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
88121921Smarcel	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
89121921Smarcel	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
90121921Smarcel	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
91121921Smarcel	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
92121921Smarcel	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
93121921Smarcel	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
94121921Smarcel	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
95121921Smarcel	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
96121921Smarcel	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
97121921Smarcel	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
98121921Smarcel	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
99121921Smarcel};
100121921Smarcel
101121921Smarceluint32_t
102121921Smarcelcrc32(const void *buf, size_t size)
103121921Smarcel{
104121921Smarcel	const uint8_t *p;
105121921Smarcel	uint32_t crc;
106121921Smarcel
107121921Smarcel	p = buf;
108121921Smarcel	crc = ~0U;
109121921Smarcel
110121921Smarcel	while (size--)
111121921Smarcel		crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
112121921Smarcel
113121921Smarcel	return (crc ^ ~0U);
114121921Smarcel}
115121921Smarcel
116121921Smarcelstatic int
117121921Smarcelwrite_pmbr(int fd, const struct disk *disk)
118121921Smarcel{
119121921Smarcel	struct dos_partition dp;
120121921Smarcel	char *buffer;
121121921Smarcel	u_long nsects;
122121921Smarcel	int error;
123121921Smarcel
124121921Smarcel	nsects = disk->media_size / disk->sector_size;
125121921Smarcel	buffer = calloc(disk->sector_size, 1);
126121921Smarcel	if (buffer == NULL)
127121921Smarcel		return (ENOMEM);
128121921Smarcel	buffer[DOSMAGICOFFSET] = DOSMAGIC & 0xff;
129121921Smarcel	buffer[DOSMAGICOFFSET + 1] = DOSMAGIC >> 8;
130121921Smarcel
131121921Smarcel	dp.dp_flag = 0;
132121921Smarcel	dp.dp_shd = dp.dp_ssect = dp.dp_scyl = 0xff;
133121921Smarcel	dp.dp_typ = DOSPTYP_PMBR;
134121921Smarcel	dp.dp_ehd = dp.dp_esect = dp.dp_ecyl = 0xff;
135121921Smarcel	dp.dp_start = 1;
136121921Smarcel	dp.dp_size = (nsects > 0xffffffffu) ? ~0u : nsects;
137121921Smarcel	memcpy(buffer + DOSPARTOFF, &dp, DOSPARTSIZE);
138121921Smarcel
139121921Smarcel	if (lseek(fd, 0L, SEEK_SET) != 0L ||
140121921Smarcel	    write(fd, buffer, disk->sector_size) != disk->sector_size)
141121921Smarcel		error = (errno) ? errno : EAGAIN;
142121921Smarcel
143121921Smarcel	free(buffer);
144121921Smarcel	return (error);
145121921Smarcel}
146121921Smarcel
147121921Smarcelstatic int
148121921Smarcelread_gpt(int fd, const struct disk *disk, struct gpt_hdr *hdr,
149121921Smarcel    struct gpt_ent *tbl)
150121921Smarcel{
151121921Smarcel	char *buffer;
152121921Smarcel	off_t off;
153121921Smarcel	size_t nsects, sz;
154121921Smarcel	int error, i;
155121921Smarcel
156121921Smarcel	nsects = disk->gpt_size * sizeof(struct gpt_ent) / disk->sector_size;
157121921Smarcel	nsects++;
158121921Smarcel	sz = nsects * disk->sector_size;
159121921Smarcel	buffer = malloc(sz);
160121921Smarcel	if (buffer == NULL)
161121921Smarcel		return (ENOMEM);
162121921Smarcel
163121921Smarcel	if (lseek(fd, disk->sector_size, SEEK_SET) != disk->sector_size ||
164121921Smarcel	    read(fd, buffer, disk->sector_size) != disk->sector_size) {
165121921Smarcel		error = (errno) ? errno : EAGAIN;
166121921Smarcel		goto bail;
167121921Smarcel	}
168121921Smarcel	if (memcmp(buffer, GPT_HDR_SIG, sizeof(hdr->hdr_sig)) != 0) {
169121921Smarcel		/*
170121921Smarcel		 * No GPT on disk. Create one out of thin air.
171121921Smarcel		 */
172121921Smarcel		bzero(&hdr[0], sizeof(struct gpt_hdr));
173121921Smarcel		memcpy(hdr[0].hdr_sig, GPT_HDR_SIG, sizeof(hdr[0].hdr_sig));
174121921Smarcel		hdr[0].hdr_revision = GPT_HDR_REVISION;
175121921Smarcel		hdr[0].hdr_size = offsetof(struct gpt_hdr, padding);
176121921Smarcel		hdr[0].hdr_lba_self = 1;
177121921Smarcel		hdr[0].hdr_lba_alt = disk->media_size / disk->sector_size - 1L;
178121921Smarcel		hdr[0].hdr_lba_start = disk->lba_start;
179121921Smarcel		hdr[0].hdr_lba_end = disk->lba_end;
180121921Smarcel		uuid_create(&hdr[0].hdr_uuid, NULL);
181121921Smarcel		hdr[0].hdr_lba_table = 2;
182121921Smarcel		hdr[0].hdr_entries = disk->gpt_size;
183121921Smarcel		hdr[0].hdr_entsz = sizeof(struct gpt_ent);
184121921Smarcel		hdr[1] = hdr[0];
185121921Smarcel		hdr[1].hdr_lba_self = hdr[0].hdr_lba_alt;
186121921Smarcel		hdr[1].hdr_lba_alt = hdr[0].hdr_lba_self;
187121921Smarcel		hdr[1].hdr_lba_table = disk->lba_end + 1;
188121921Smarcel
189121921Smarcel		for (i = 0; i < disk->gpt_size; i++) {
190121921Smarcel			bzero(&tbl[i], sizeof(struct gpt_ent));
191121921Smarcel			uuid_create(&tbl[i].ent_uuid, NULL);
192121921Smarcel		}
193121921Smarcel
194121921Smarcel		error = 0;
195121921Smarcel		goto bail;
196121921Smarcel	}
197121921Smarcel
198121921Smarcel	/*
199121921Smarcel	 * We have a GPT on disk. Read it.
200121921Smarcel	 */
201121921Smarcel	memcpy(&hdr[0], buffer, sizeof(struct gpt_hdr));
202121921Smarcel	off = hdr->hdr_lba_table * disk->sector_size;
203121921Smarcel	if (lseek(fd, off, SEEK_SET) != off ||
204121921Smarcel	    read(fd, buffer, sz) != sz) {
205121921Smarcel		error = (errno) ? errno : EAGAIN;
206121921Smarcel		goto bail;
207121921Smarcel	}
208121921Smarcel	memcpy(tbl, buffer, sizeof(struct gpt_ent) * disk->gpt_size);
209121921Smarcel	off = hdr->hdr_lba_alt * disk->sector_size;
210121921Smarcel	if (lseek(fd, off, SEEK_SET) != off ||
211121921Smarcel	    read(fd, buffer, disk->sector_size) != disk->sector_size) {
212121921Smarcel		error = (errno) ? errno : EAGAIN;
213121921Smarcel		goto bail;
214121921Smarcel	}
215121921Smarcel	memcpy(&hdr[1], buffer, sizeof(struct gpt_hdr));
216121921Smarcel	error = 0;
217121921Smarcel
218121921Smarcelbail:
219121921Smarcel	free(buffer);
220121921Smarcel	return (error);
221121921Smarcel}
222121921Smarcel
223121921Smarcelstatic int
224121921Smarcelupdate_gpt(int fd, const struct disk *disk, struct gpt_hdr *hdr,
225121921Smarcel    struct gpt_ent *tbl)
226121921Smarcel{
227121921Smarcel	char *buffer;
228121921Smarcel	struct chunk *c;
229121921Smarcel	off_t off;
230121921Smarcel	size_t bufsz;
231121921Smarcel	int error, idx;
232121921Smarcel
233121921Smarcel	idx = 0;
234121921Smarcel	for (c = disk->chunks->part; c != NULL; c = c->next) {
235121921Smarcel		if (!(c->flags & CHUNK_HAS_INDEX)) {
236121921Smarcel			while (idx < disk->gpt_size &&
237121921Smarcel			    !uuid_is_nil(&tbl[idx].ent_type, NULL))
238121921Smarcel				idx++;
239121921Smarcel			if (idx == disk->gpt_size)
240121921Smarcel				return (ENOSPC);
241121921Smarcel
242121921Smarcel			switch (c->type) {
243121921Smarcel			case freebsd:
244121921Smarcel				tbl[idx].ent_type = _fbsd;
245121921Smarcel				break;
246121921Smarcel			case efi:
247121921Smarcel				tbl[idx].ent_type = _efi;
248121921Smarcel				break;
249121921Smarcel			case part:
250121921Smarcel				switch (c->subtype) {
251121921Smarcel				case FS_SWAP:
252121921Smarcel					tbl[idx].ent_type = _swap;
253121921Smarcel					break;
254121921Smarcel				case FS_BSDFFS:
255121921Smarcel					tbl[idx].ent_type = _ufs;
256121921Smarcel					break;
257121921Smarcel				default:
258121921Smarcel					return (EINVAL);
259121921Smarcel				}
260121921Smarcel				break;
261121921Smarcel			default:
262121921Smarcel				return (EINVAL);
263121921Smarcel			}
264121921Smarcel		} else
265121921Smarcel			idx = CHUNK_FTOI(c->flags);
266121921Smarcel
267121921Smarcel		tbl[idx].ent_lba_start = c->offset / disk->sector_size;
268121921Smarcel		tbl[idx].ent_lba_end = c->end / disk->sector_size;
269121921Smarcel 	}
270121921Smarcel
271121921Smarcel	hdr[0].hdr_crc_table = crc32(tbl,
272121921Smarcel	    disk->gpt_size * sizeof(struct gpt_ent));
273121921Smarcel	hdr[0].hdr_crc_self = 0;
274121921Smarcel	hdr[0].hdr_crc_self = crc32(&hdr[0], hdr[0].hdr_size);
275121921Smarcel
276121921Smarcel	hdr[1].hdr_crc_table = hdr[0].hdr_crc_table;
277121921Smarcel	hdr[1].hdr_crc_self = 0;
278121921Smarcel	hdr[1].hdr_crc_self = crc32(&hdr[1], hdr[1].hdr_size);
279121921Smarcel
280121921Smarcel	/*
281121921Smarcel	 * Write the new GPT back to the disk.
282121921Smarcel	 */
283121921Smarcel	bufsz = disk->gpt_size * sizeof(struct gpt_ent);
284121921Smarcel	if (bufsz == 0 || bufsz % disk->sector_size)
285121921Smarcel		bufsz += disk->sector_size;
286121921Smarcel	bufsz = (bufsz / disk->sector_size) * disk->sector_size;
287121921Smarcel	buffer = calloc(1, bufsz);
288121921Smarcel
289121921Smarcel	memcpy(buffer, &hdr[0], sizeof(struct gpt_hdr));
290121921Smarcel	off = hdr[0].hdr_lba_self * disk->sector_size;
291121921Smarcel	if (lseek(fd, off, SEEK_SET) != off ||
292121921Smarcel	    write(fd, buffer, disk->sector_size) != disk->sector_size) {
293121921Smarcel		error = (errno) ? errno : EAGAIN;
294121921Smarcel		goto bail;
295121921Smarcel	}
296121921Smarcel	memcpy(buffer, &hdr[1], sizeof(struct gpt_hdr));
297121921Smarcel	off = hdr[1].hdr_lba_self * disk->sector_size;
298121921Smarcel	if (lseek(fd, off, SEEK_SET) != off ||
299121921Smarcel	    write(fd, buffer, disk->sector_size) != disk->sector_size) {
300121921Smarcel		error = (errno) ? errno : EAGAIN;
301121921Smarcel		goto bail;
302121921Smarcel	}
303121921Smarcel	memcpy(buffer, tbl, disk->gpt_size * sizeof(struct gpt_ent));
304121921Smarcel	off = hdr[0].hdr_lba_table * disk->sector_size;
305121921Smarcel	if (lseek(fd, off, SEEK_SET) != off ||
306121921Smarcel	    write(fd, buffer, bufsz) != bufsz) {
307121921Smarcel		error = (errno) ? errno : EAGAIN;
308121921Smarcel		goto bail;
309121921Smarcel	}
310121921Smarcel	off = hdr[1].hdr_lba_table * disk->sector_size;
311121921Smarcel	if (lseek(fd, off, SEEK_SET) != off ||
312121921Smarcel	    write(fd, buffer, bufsz) != bufsz) {
313121921Smarcel		error = (errno) ? errno : EAGAIN;
314121921Smarcel		goto bail;
315121921Smarcel	}
316121921Smarcel	error = 0;
317121921Smarcel
318121921Smarcelbail:
319121921Smarcel	free(buffer);
320121921Smarcel	return (error);
321121921Smarcel}
322121921Smarcel
323105816Sphkint
324121921SmarcelWrite_Disk(const struct disk *disk)
325105816Sphk{
326121921Smarcel	char devname[64];
327121921Smarcel	struct gpt_hdr *hdr;
328121921Smarcel	struct gpt_ent *tbl;
329121921Smarcel	int error, fd;
330121921Smarcel
331121921Smarcel	hdr = malloc(sizeof(struct gpt_hdr) * 2);
332121921Smarcel	if (hdr == NULL)
333121921Smarcel		return (ENOMEM);
334121921Smarcel	tbl = malloc(sizeof(struct gpt_ent) * disk->gpt_size);
335121921Smarcel	if (tbl == NULL) {
336121921Smarcel		free(hdr);
337121921Smarcel		return (ENOMEM);
338121921Smarcel	}
339121921Smarcel
340121921Smarcel	snprintf(devname, sizeof(devname), "%s%s", _PATH_DEV, disk->name);
341121921Smarcel	fd = open(devname, O_RDWR);
342121921Smarcel	if (fd == -1) {
343121921Smarcel		free(tbl);
344121921Smarcel		free(hdr);
345121921Smarcel		return (errno);
346121921Smarcel	}
347121921Smarcel
348121921Smarcel	/*
349121921Smarcel	 * We can always write the PMBR, because we reject disks that do not
350121921Smarcel	 * have a PMBR and are not virgin.
351121921Smarcel	 */
352121921Smarcel	error = write_pmbr(fd, disk);
353121921Smarcel	if (error)
354121921Smarcel		goto bail;
355121921Smarcel
356121921Smarcel	/*
357121921Smarcel	 * Read the existing GPT from disk or otherwise create one out of
358121921Smarcel	 * thin air. This way we can preserve the UUIDs and the entry names
359121921Smarcel	 * when updating it.
360121921Smarcel	 */
361121921Smarcel	error = read_gpt(fd, disk, hdr, tbl);
362121921Smarcel	if (error)
363121921Smarcel		goto bail;
364121921Smarcel
365121921Smarcel	/*
366121921Smarcel	 * Update and write the in-memory copy of the GPT.
367121921Smarcel	 */
368121921Smarcel	error = update_gpt(fd, disk, hdr, tbl);
369121921Smarcel	if (error)
370121921Smarcel		goto bail;
371121921Smarcel
372106741Smarcel	return (0);
373121921Smarcel
374121921Smarcelbail:
375121921Smarcel	close(fd);
376121921Smarcel	free(tbl);
377121921Smarcel	free(hdr);
378121921Smarcel	return (error);
379105816Sphk}
380