summaryrefslogtreecommitdiffstats
path: root/usr.sbin/vnconfig/vnconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/vnconfig/vnconfig.c')
-rw-r--r--usr.sbin/vnconfig/vnconfig.c104
1 files changed, 96 insertions, 8 deletions
diff --git a/usr.sbin/vnconfig/vnconfig.c b/usr.sbin/vnconfig/vnconfig.c
index ce1f7ea..c9f6e5e 100644
--- a/usr.sbin/vnconfig/vnconfig.c
+++ b/usr.sbin/vnconfig/vnconfig.c
@@ -51,6 +51,7 @@ static const char rcsid[] =
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
+#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/param.h>
@@ -64,6 +65,7 @@ static const char rcsid[] =
#define MAXVNDISK 16
#define LINESIZE 1024
+#define ZBUFSIZE 32768
struct vndisk {
char *dev;
@@ -84,6 +86,8 @@ struct vndisk {
#define VN_IGNORE 0x80
#define VN_SET 0x100
#define VN_RESET 0x200
+#define VN_TRUNCATE 0x400
+#define VN_ZERO 0x800
int nvndisks;
@@ -111,9 +115,10 @@ main(argc, argv)
int flags = 0;
int size = 0;
char *autolabel = NULL;
+ char *s;
configfile = _PATH_VNTAB;
- while ((i = getopt(argc, argv, "acdef:gr:s:S:L:uv")) != -1)
+ while ((i = getopt(argc, argv, "acdef:gr:s:S:TZL:uv")) != -1)
switch (i) {
/* all -- use config file */
@@ -151,15 +156,19 @@ main(argc, argv)
/* reset options */
case 'r':
- if (what_opt(optarg,&resetopt))
- errx(1, "invalid options '%s'", optarg);
+ for (s = strtok(optarg, ","); s; s = strtok(NULL, ",")) {
+ if (what_opt(s, &resetopt))
+ errx(1, "invalid options '%s'", s);
+ }
flags |= VN_RESET;
break;
/* set options */
case 's':
- if (what_opt(optarg,&setopt))
- errx(1, "invalid options '%s'", optarg);
+ for (s = strtok(optarg, ","); s; s = strtok(NULL, ",")) {
+ if (what_opt(s, &setopt))
+ errx(1, "invalid options '%s'", s);
+ }
flags |= VN_SET;
break;
@@ -178,6 +187,14 @@ main(argc, argv)
size = getsize(optarg);
break;
+ case 'T':
+ flags |= VN_TRUNCATE;
+ break;
+
+ case 'Z':
+ flags |= VN_ZERO;
+ break;
+
case 'L':
autolabel = optarg;
break;
@@ -192,13 +209,13 @@ main(argc, argv)
if (flags == 0)
flags = VN_CONFIG;
- if (all)
+ if (all) {
readconfig(flags);
- else {
+ } else {
if (argc < optind + 1)
usage();
vndisks[0].dev = argv[optind++];
- vndisks[0].file = argv[optind++];
+ vndisks[0].file = argv[optind++]; /* may be NULL */
vndisks[0].flags = flags;
vndisks[0].size = size;
vndisks[0].autolabel = autolabel;
@@ -217,6 +234,7 @@ what_opt(str,p)
char *str;
u_long *p;
{
+ if (!strcmp(str,"reserve")) { *p |= VN_RESERVE; return 0; }
if (!strcmp(str,"labels")) { *p |= VN_LABELS; return 0; }
if (!strcmp(str,"follow")) { *p |= VN_FOLLOW; return 0; }
if (!strcmp(str,"debug")) { *p |= VN_DEBUG; return 0; }
@@ -237,6 +255,7 @@ config(vnp)
char *rdev;
FILE *f;
u_long l;
+ int pgsize = getpagesize();
rv = 0;
@@ -254,6 +273,47 @@ config(vnp)
if (flags & VN_IGNORE)
return(0);
+ /*
+ * When a regular file has been specified, do any requested setup
+ * of the file. Truncation (also creates the file if necessary),
+ * sizing, and zeroing.
+ */
+
+ if (file && vnp->size != 0 && (flags & VN_CONFIG)) {
+ int fd;
+ struct stat st;
+
+ if (flags & VN_TRUNCATE)
+ fd = open(file, O_RDWR|O_CREAT|O_TRUNC);
+ else
+ fd = open(file, O_RDWR);
+ if (fd >= 0 && fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
+ if (st.st_size < (off_t)vnp->size * pgsize)
+ ftruncate(fd, (off_t)vnp->size * pgsize);
+ if (vnp->size != 0)
+ st.st_size = (off_t)vnp->size * pgsize;
+
+ if (flags & VN_ZERO) {
+ char *buf = malloc(ZBUFSIZE);
+ bzero(buf, ZBUFSIZE);
+ while (st.st_size > 0) {
+ int n = (st.st_size > ZBUFSIZE) ?
+ ZBUFSIZE : (int)st.st_size;
+ if (write(fd, buf, n) != n) {
+ ftruncate(fd, 0);
+ printf("Unable to ZERO file %s\n", file);
+ return(0);
+ }
+ st.st_size -= (off_t)n;
+ }
+ }
+ close(fd);
+ } else {
+ printf("Unable to open file %s\n", file);
+ return(0);
+ }
+ }
+
rdev = rawdevice(dev);
f = fopen(rdev, "rw");
if (f == NULL) {
@@ -294,6 +354,34 @@ config(vnp)
printf("%s: cleared\n", dev);
}
/*
+ * Set specified options
+ */
+ if (flags & VN_SET) {
+ l = setopt;
+ if (global)
+ rv = ioctl(fileno(f), VNIOCGSET, &l);
+ else
+ rv = ioctl(fileno(f), VNIOCUSET, &l);
+ if (rv) {
+ warn("VNIO[GU]SET");
+ } else if (verbose)
+ printf("%s: flags now=%08x\n",dev,l);
+ }
+ /*
+ * Reset specified options
+ */
+ if (flags & VN_RESET) {
+ l = resetopt;
+ if (global)
+ rv = ioctl(fileno(f), VNIOCGCLEAR, &l);
+ else
+ rv = ioctl(fileno(f), VNIOCUCLEAR, &l);
+ if (rv) {
+ warn("VNIO[GU]CLEAR");
+ } else if (verbose)
+ printf("%s: flags now=%08x\n",dev,l);
+ }
+ /*
* Configure the device
*/
if (flags & VN_CONFIG) {
OpenPOWER on IntegriCloud