subr.c revision 129470
1129470Spjd/*-
2129470Spjd * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3129470Spjd * All rights reserved.
4129470Spjd *
5129470Spjd * Redistribution and use in source and binary forms, with or without
6129470Spjd * modification, are permitted provided that the following conditions
7129470Spjd * are met:
8129470Spjd * 1. Redistributions of source code must retain the above copyright
9129470Spjd *    notice, this list of conditions and the following disclaimer.
10129470Spjd * 2. Redistributions in binary form must reproduce the above copyright
11129470Spjd *    notice, this list of conditions and the following disclaimer in the
12129470Spjd *    documentation and/or other materials provided with the distribution.
13129470Spjd *
14129470Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15129470Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16129470Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17129470Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18129470Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19129470Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20129470Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21129470Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22129470Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23129470Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24129470Spjd * SUCH DAMAGE.
25129470Spjd */
26129470Spjd
27129470Spjd#include <sys/cdefs.h>
28129470Spjd__FBSDID("$FreeBSD: head/sbin/geom/misc/subr.c 129470 2004-05-20 10:09:56Z pjd $");
29129470Spjd
30129470Spjd#include <sys/param.h>
31129470Spjd#include <sys/disk.h>
32129470Spjd#include <sys/endian.h>
33129470Spjd#include <sys/uio.h>
34129470Spjd#include <errno.h>
35129470Spjd#include <fcntl.h>
36129470Spjd#include <paths.h>
37129470Spjd#include <stdio.h>
38129470Spjd#include <stdlib.h>
39129470Spjd#include <stdarg.h>
40129470Spjd#include <string.h>
41129470Spjd#include <strings.h>
42129470Spjd#include <unistd.h>
43129470Spjd#include <assert.h>
44129470Spjd#include <libgeom.h>
45129470Spjd
46129470Spjd#include "misc/subr.h"
47129470Spjd
48129470Spjd
49129470Spjdstruct std_metadata {
50129470Spjd	char		md_magic[16];
51129470Spjd	uint32_t	md_version;
52129470Spjd};
53129470Spjd
54129470Spjdstatic void
55129470Spjdstd_metadata_decode(const u_char *data, struct std_metadata *md)
56129470Spjd{
57129470Spjd
58129470Spjd        bcopy(data, md->md_magic, sizeof(md->md_magic));
59129470Spjd        md->md_version = le32dec(data + 16);
60129470Spjd}
61129470Spjd
62129470Spjdstatic void
63129470Spjdpathgen(const char *name, char *path, size_t size)
64129470Spjd{
65129470Spjd
66129470Spjd	if (strncmp(name, _PATH_DEV, strlen(_PATH_DEV)) != 0)
67129470Spjd		snprintf(path, size, "%s%s", _PATH_DEV, name);
68129470Spjd	else
69129470Spjd		strlcpy(path, name, size);
70129470Spjd}
71129470Spjd
72129470Spjdint
73129470Spjdg_metadata_store(const char *name, u_char *md, size_t size)
74129470Spjd{
75129470Spjd	char path[MAXPATHLEN];
76129470Spjd	unsigned sectorsize;
77129470Spjd	off_t mediasize;
78129470Spjd	u_char *sector;
79129470Spjd	int error, fd;
80129470Spjd
81129470Spjd	pathgen(name, path, sizeof(path));
82129470Spjd	sector = NULL;
83129470Spjd	error = 0;
84129470Spjd
85129470Spjd	fd = open(path, O_WRONLY);
86129470Spjd	if (fd == -1)
87129470Spjd		return (errno);
88129470Spjd	if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) < 0) {
89129470Spjd		error = errno;
90129470Spjd		goto out;
91129470Spjd	}
92129470Spjd	if (ioctl(fd, DIOCGSECTORSIZE, &sectorsize) < 0) {
93129470Spjd		error = errno;
94129470Spjd		goto out;
95129470Spjd	}
96129470Spjd	assert(sectorsize >= size);
97129470Spjd	sector = malloc(sectorsize);
98129470Spjd	if (sector == NULL) {
99129470Spjd		error = ENOMEM;
100129470Spjd		goto out;
101129470Spjd	}
102129470Spjd	bcopy(md, sector, size);
103129470Spjd	if (pwrite(fd, sector, sectorsize, mediasize - sectorsize) !=
104129470Spjd	    (ssize_t)sectorsize) {
105129470Spjd		error = errno;
106129470Spjd		goto out;
107129470Spjd	}
108129470Spjdout:
109129470Spjd	if (sector != NULL)
110129470Spjd		free(sector);
111129470Spjd	close(fd);
112129470Spjd	return (error);
113129470Spjd}
114129470Spjd
115129470Spjdint
116129470Spjdg_metadata_clear(const char *name, const char *magic)
117129470Spjd{
118129470Spjd	struct std_metadata md;
119129470Spjd	char path[MAXPATHLEN];
120129470Spjd	unsigned sectorsize;
121129470Spjd	off_t mediasize;
122129470Spjd	u_char *sector;
123129470Spjd	int error, fd;
124129470Spjd
125129470Spjd	pathgen(name, path, sizeof(path));
126129470Spjd	sector = NULL;
127129470Spjd	error = 0;
128129470Spjd
129129470Spjd	fd = open(path, O_RDWR);
130129470Spjd	if (fd == -1)
131129470Spjd		return (errno);
132129470Spjd	if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) < 0) {
133129470Spjd		error = errno;
134129470Spjd		goto out;
135129470Spjd	}
136129470Spjd	if (ioctl(fd, DIOCGSECTORSIZE, &sectorsize) < 0) {
137129470Spjd		error = errno;
138129470Spjd		goto out;
139129470Spjd	}
140129470Spjd	sector = malloc(sectorsize);
141129470Spjd	if (sector == NULL) {
142129470Spjd		error = ENOMEM;
143129470Spjd		goto out;
144129470Spjd	}
145129470Spjd	if (magic != NULL) {
146129470Spjd		if (pread(fd, sector, sectorsize, mediasize - sectorsize) !=
147129470Spjd		    (ssize_t)sectorsize) {
148129470Spjd			error = errno;
149129470Spjd			goto out;
150129470Spjd		}
151129470Spjd		std_metadata_decode(sector, &md);
152129470Spjd		if (strcmp(md.md_magic, magic) != 0) {
153129470Spjd			error = EINVAL;
154129470Spjd			goto out;
155129470Spjd		}
156129470Spjd	}
157129470Spjd	bzero(sector, sectorsize);
158129470Spjd	if (pwrite(fd, sector, sectorsize, mediasize - sectorsize) !=
159129470Spjd	    (ssize_t)sectorsize) {
160129470Spjd		error = errno;
161129470Spjd		goto out;
162129470Spjd	}
163129470Spjdout:
164129470Spjd	if (sector != NULL)
165129470Spjd		free(sector);
166129470Spjd	close(fd);
167129470Spjd	return (error);
168129470Spjd}
169129470Spjd
170129470Spjd/*
171129470Spjd * Set an error message, if one does not already exist.
172129470Spjd */
173129470Spjdvoid
174129470Spjdgctl_error(struct gctl_req *req, const char *error, ...)
175129470Spjd{
176129470Spjd	va_list ap;
177129470Spjd
178129470Spjd	if (req->error != NULL)
179129470Spjd		return;
180129470Spjd	va_start(ap, error);
181129470Spjd	vasprintf(&req->error, error, ap);
182129470Spjd	va_end(ap);
183129470Spjd}
184129470Spjd
185129470Spjdvoid *
186129470Spjdgctl_get_param(struct gctl_req *req, const char *param, int *len)
187129470Spjd{
188129470Spjd	unsigned i;
189129470Spjd	void *p;
190129470Spjd	struct gctl_req_arg *ap;
191129470Spjd
192129470Spjd	for (i = 0; i < req->narg; i++) {
193129470Spjd		ap = &req->arg[i];
194129470Spjd		if (strcmp(param, ap->name))
195129470Spjd			continue;
196129470Spjd		if (!(ap->flag & GCTL_PARAM_RD))
197129470Spjd			continue;
198129470Spjd		p = ap->value;
199129470Spjd		if (len != NULL)
200129470Spjd			*len = ap->len;
201129470Spjd		return (p);
202129470Spjd	}
203129470Spjd	return (NULL);
204129470Spjd}
205129470Spjd
206129470Spjdchar const *
207129470Spjdgctl_get_asciiparam(struct gctl_req *req, const char *param)
208129470Spjd{
209129470Spjd	unsigned i;
210129470Spjd	char const *p;
211129470Spjd	struct gctl_req_arg *ap;
212129470Spjd
213129470Spjd	for (i = 0; i < req->narg; i++) {
214129470Spjd		ap = &req->arg[i];
215129470Spjd		if (strcmp(param, ap->name))
216129470Spjd			continue;
217129470Spjd		if (!(ap->flag & GCTL_PARAM_RD))
218129470Spjd			continue;
219129470Spjd		p = ap->value;
220129470Spjd		if (ap->len < 1) {
221129470Spjd			gctl_error(req, "No length argument (%s)", param);
222129470Spjd			return (NULL);
223129470Spjd		}
224129470Spjd		if (p[ap->len - 1] != '\0') {
225129470Spjd			gctl_error(req, "Unterminated argument (%s)", param);
226129470Spjd			return (NULL);
227129470Spjd		}
228129470Spjd		return (p);
229129470Spjd	}
230129470Spjd	return (NULL);
231129470Spjd}
232129470Spjd
233129470Spjdvoid *
234129470Spjdgctl_get_paraml(struct gctl_req *req, const char *param, int len)
235129470Spjd{
236129470Spjd	int i;
237129470Spjd	void *p;
238129470Spjd
239129470Spjd	p = gctl_get_param(req, param, &i);
240129470Spjd	if (p == NULL)
241129470Spjd		gctl_error(req, "Missing %s argument", param);
242129470Spjd	else if (i != len) {
243129470Spjd		p = NULL;
244129470Spjd		gctl_error(req, "Wrong length %s argument", param);
245129470Spjd	}
246129470Spjd	return (p);
247129470Spjd}
248