summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2011-10-25 07:31:13 +0000
committerpjd <pjd@FreeBSD.org>2011-10-25 07:31:13 +0000
commit38c5d5e6a3b5f85d473b1c513e7210a63b577191 (patch)
tree58c2e38696c21593555b9e0778f141716b9d1859 /sbin
parentac82c708e32f7268c12562100d4b721a5b0f7a5a (diff)
downloadFreeBSD-src-38c5d5e6a3b5f85d473b1c513e7210a63b577191.zip
FreeBSD-src-38c5d5e6a3b5f85d473b1c513e7210a63b577191.tar.gz
Simplify eli_backup_create() and eli_backup_restore() functions.
As a side-effect it is now possible to backup unsupported (newer) GELI metadata versions. MFC after: 3 days
Diffstat (limited to 'sbin')
-rw-r--r--sbin/geom/class/eli/geom_eli.c115
1 files changed, 28 insertions, 87 deletions
diff --git a/sbin/geom/class/eli/geom_eli.c b/sbin/geom/class/eli/geom_eli.c
index 03c1073..975afda 100644
--- a/sbin/geom/class/eli/geom_eli.c
+++ b/sbin/geom/class/eli/geom_eli.c
@@ -1295,66 +1295,53 @@ eli_kill(struct gctl_req *req)
static int
eli_backup_create(struct gctl_req *req, const char *prov, const char *file)
{
- struct g_eli_metadata md;
unsigned char *sector;
ssize_t secsize;
- off_t mediasize;
- int filefd, provfd, ret;
+ int error, filefd, ret;
ret = -1;
- provfd = filefd = -1;
+ filefd = -1;
sector = NULL;
secsize = 0;
- provfd = g_open(prov, 0);
- if (provfd == -1) {
- gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno));
- goto out;
- }
- filefd = open(file, O_WRONLY | O_TRUNC | O_CREAT, 0600);
- if (filefd == -1) {
- gctl_error(req, "Cannot open %s: %s.", file, strerror(errno));
- goto out;
- }
-
- mediasize = g_mediasize(provfd);
- secsize = g_sectorsize(provfd);
- if (mediasize == -1 || secsize == -1) {
+ secsize = g_get_sectorsize(prov);
+ if (secsize == 0) {
gctl_error(req, "Cannot get informations about %s: %s.", prov,
strerror(errno));
goto out;
}
-
sector = malloc(secsize);
if (sector == NULL) {
gctl_error(req, "Cannot allocate memory.");
goto out;
}
-
/* Read metadata from the provider. */
- if (pread(provfd, sector, secsize, mediasize - secsize) != secsize) {
- gctl_error(req, "Cannot read metadata: %s.", strerror(errno));
+ error = g_metadata_read(prov, sector, secsize, G_ELI_MAGIC);
+ if (error != 0) {
+ gctl_error(req, "Unable to read metadata from %s: %s.", prov,
+ strerror(error));
goto out;
}
- /* Check if this is geli provider. */
- if (eli_metadata_decode(sector, &md) != 0) {
- gctl_error(req, "MD5 hash mismatch: not a geli provider?");
+
+ filefd = open(file, O_WRONLY | O_TRUNC | O_CREAT, 0600);
+ if (filefd == -1) {
+ gctl_error(req, "Unable to open %s: %s.", file,
+ strerror(errno));
goto out;
}
/* Write metadata to the destination file. */
if (write(filefd, sector, secsize) != secsize) {
- gctl_error(req, "Cannot write to %s: %s.", file,
+ gctl_error(req, "Unable to write to %s: %s.", file,
strerror(errno));
+ (void)close(filefd);
+ (void)unlink(file);
goto out;
}
(void)fsync(filefd);
+ (void)close(filefd);
/* Success. */
ret = 0;
out:
- if (provfd >= 0)
- (void)g_close(provfd);
- if (filefd >= 0)
- (void)close(filefd);
if (sector != NULL) {
bzero(sector, secsize);
free(sector);
@@ -1384,10 +1371,8 @@ eli_restore(struct gctl_req *req)
{
struct g_eli_metadata md;
const char *file, *prov;
- unsigned char *sector;
- ssize_t secsize;
off_t mediasize;
- int nargs, filefd, provfd;
+ int nargs;
nargs = gctl_get_int(req, "nargs");
if (nargs != 2) {
@@ -1397,72 +1382,28 @@ eli_restore(struct gctl_req *req)
file = gctl_get_ascii(req, "arg0");
prov = gctl_get_ascii(req, "arg1");
- provfd = filefd = -1;
- sector = NULL;
- secsize = 0;
-
- filefd = open(file, O_RDONLY);
- if (filefd == -1) {
- gctl_error(req, "Cannot open %s: %s.", file, strerror(errno));
- goto out;
- }
- provfd = g_open(prov, 1);
- if (provfd == -1) {
- gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno));
- goto out;
- }
-
- mediasize = g_mediasize(provfd);
- secsize = g_sectorsize(provfd);
- if (mediasize == -1 || secsize == -1) {
- gctl_error(req, "Cannot get informations about %s: %s.", prov,
- strerror(errno));
- goto out;
- }
-
- sector = malloc(secsize);
- if (sector == NULL) {
- gctl_error(req, "Cannot allocate memory.");
- goto out;
- }
-
/* Read metadata from the backup file. */
- if (read(filefd, sector, secsize) != secsize) {
- gctl_error(req, "Cannot read from %s: %s.", file,
+ if (eli_metadata_read(req, file, &md) == -1)
+ return;
+ /* Obtain provider's mediasize. */
+ mediasize = g_get_mediasize(prov);
+ if (mediasize == 0) {
+ gctl_error(req, "Cannot get informations about %s: %s.", prov,
strerror(errno));
- goto out;
- }
- /* Check if this file contains geli metadata. */
- if (eli_metadata_decode(sector, &md) != 0) {
- gctl_error(req, "MD5 hash mismatch: not a geli backup file?");
- goto out;
+ return;
}
/* Check if the provider size has changed since we did the backup. */
if (md.md_provsize != (uint64_t)mediasize) {
if (gctl_get_int(req, "force")) {
md.md_provsize = mediasize;
- eli_metadata_encode(&md, sector);
} else {
gctl_error(req, "Provider size mismatch: "
"wrong backup file?");
- goto out;
+ return;
}
}
- /* Write metadata from the provider. */
- if (pwrite(provfd, sector, secsize, mediasize - secsize) != secsize) {
- gctl_error(req, "Cannot write metadata: %s.", strerror(errno));
- goto out;
- }
- (void)g_flush(provfd);
-out:
- if (provfd >= 0)
- (void)g_close(provfd);
- if (filefd >= 0)
- (void)close(filefd);
- if (sector != NULL) {
- bzero(sector, secsize);
- free(sector);
- }
+ /* Write metadata to the provider. */
+ (void)eli_metadata_store(req, prov, &md);
}
static void
OpenPOWER on IntegriCloud