Expand PMF_FN_* macros.
[netbsd-mini2440.git] / usr.sbin / fssconfig / fssconfig.c
blobcb3f69e5a334e4eccb8571d7e5ca95b256b427a4
1 /* $NetBSD: fssconfig.c,v 1.5 2005/04/17 16:28:26 hannken Exp $ */
3 /*-
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Juergen Hannken-Illjes.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/param.h>
33 #include <sys/ioctl.h>
34 #include <sys/mount.h>
35 #include <sys/stat.h>
37 #include <err.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <time.h>
43 #include <unistd.h>
44 #include <util.h>
46 #include <dev/fssvar.h>
48 int vflag = 0;
49 int xflag = 0;
51 void config(int, char **);
52 void unconfig(int, char **);
53 void list(int, char **);
54 void usage(void);
56 int
57 main(int argc, char **argv)
59 int ch;
60 void (*action)(int, char **);
62 action = config;
64 while ((ch = getopt(argc, argv, "cluvx")) != -1) {
65 switch (ch) {
66 case 'c':
67 action = config;
68 break;
69 case 'l':
70 action = list;
71 break;
72 case 'u':
73 action = unconfig;
74 break;
75 case 'v':
76 vflag++;
77 break;
78 case 'x':
79 xflag++;
80 break;
81 default:
82 case '?':
83 usage();
84 /* NOTREACHED */
88 argc -= optind;
89 argv += optind;
91 (*action)(argc, argv);
93 exit(0);
96 void
97 config(int argc, char **argv)
99 int fd, isreg, istmp, ispersistent;
100 char full[64], path[MAXPATHLEN];
101 off_t bssize;
102 dev_t mountdev;
103 struct stat sbuf;
104 struct statvfs fsbuf;
105 struct fss_set fss;
107 if (argc < 3)
108 usage();
110 istmp = ispersistent = 0;
112 fss.fss_mount = argv[1];
113 fss.fss_bstore = argv[2];
115 if (statvfs(argv[1], &fsbuf) != 0 || stat(argv[1], &sbuf) != 0)
116 err(1, "stat %s", argv[1]);
117 mountdev = sbuf.st_dev;
118 if (stat(argv[2], &sbuf) == 0 &&
119 S_ISREG(sbuf.st_mode) &&
120 sbuf.st_dev == mountdev) {
121 if ((sbuf.st_flags & SF_SNAPSHOT) == 0)
122 errx(1, "%s: exists and is not a snapshot", argv[2]);
123 if (argc != 3)
124 usage();
125 isreg = ispersistent = 1;
127 goto configure;
130 if (argc > 5)
131 usage();
133 if (argc > 3)
134 fss.fss_csize = strsuftoll("cluster size", argv[3], 0, INT_MAX);
135 else
136 fss.fss_csize = 0;
137 if (argc > 4)
138 bssize = strsuftoll("bs size", argv[4], 0, LLONG_MAX);
139 else
140 bssize = (off_t)fsbuf.f_blocks*fsbuf.f_frsize;
143 * Create the backing store. If it is a directory, create a temporary
144 * file and set the unlink flag.
146 if ((fd = open(fss.fss_bstore, O_CREAT|O_TRUNC|O_WRONLY, 0600)) < 0) {
147 if (errno != EISDIR)
148 err(1, "create: %s", fss.fss_bstore);
149 snprintf(path, sizeof(path), "%s/XXXXXXXXXX", fss.fss_bstore);
150 if ((fd = mkstemp(path)) < 0)
151 err(1, "mkstemp: %s", path);
152 fss.fss_bstore = path;
153 istmp = 1;
155 if (fstat(fd, &sbuf) < 0)
156 err(1, "stat: %s", fss.fss_bstore);
157 if (!ispersistent && sbuf.st_dev == mountdev)
158 ispersistent = 1;
159 isreg = S_ISREG(sbuf.st_mode);
160 if (!ispersistent && isreg && ftruncate(fd, bssize) < 0)
161 err(1, "truncate %s", fss.fss_bstore);
162 close(fd);
164 configure:
165 if ((fd = opendisk(argv[0], O_RDWR, full, sizeof(full), 0)) < 0) {
166 if (istmp)
167 unlink(fss.fss_bstore);
168 err(1, "open: %s", argv[0]);
171 if (ioctl(fd, FSSIOCSET, &fss) < 0) {
172 if (istmp)
173 unlink(fss.fss_bstore);
174 err(1, "%s: FSSIOCSET", full);
177 if ((xflag || istmp) && isreg && unlink(fss.fss_bstore) < 0)
178 err(1, "unlink: %s", fss.fss_bstore);
180 if (vflag)
181 list(1, argv);
184 void
185 unconfig(int argc, char **argv)
187 int fd;
188 char full[64];
190 if (argc != 1)
191 usage();
193 if (vflag)
194 list(1, argv);
196 if ((fd = opendisk(argv[0], O_RDWR, full, sizeof(full), 0)) < 0)
197 err(1, "open: %s", argv[0]);
199 if (ioctl(fd, FSSIOCCLR) < 0)
200 err(1, "%s: FSSIOCCLR", full);
203 void
204 list(int argc, char **argv)
206 int n, fd, flags;
207 char *dev, path[64], full[64];
208 char clbuf[5], bsbuf[5], tmbuf[64];
209 time_t t;
210 struct fss_get fsg;
212 if (argc > 1)
213 usage();
215 if (argc > 0)
216 dev = argv[0];
217 else
218 dev = path;
220 for (n = 0; ; n++) {
221 if (argc == 0)
222 snprintf(path, sizeof(path), "fss%d", n);
223 if ((fd = opendisk(dev, O_RDONLY, full, sizeof(full), 0)) < 0) {
224 if (argc == 0 && (errno == ENOENT || errno == ENXIO))
225 break;
226 err(1, "open: %s", dev);
229 if (ioctl(fd, FSSIOFGET, &flags) < 0)
230 flags = 0;
232 if (ioctl(fd, FSSIOCGET, &fsg) < 0) {
233 if (errno == ENXIO)
234 printf("%s: not in use\n", dev);
235 else
236 err(1, "%s: FSSIOCGET", full);
237 } else if (vflag) {
238 humanize_number(clbuf, sizeof(clbuf),
239 (int64_t)fsg.fsg_csize,
240 "", HN_AUTOSCALE, HN_B|HN_NOSPACE);
242 humanize_number(bsbuf, sizeof(bsbuf),
243 (int64_t)fsg.fsg_bs_size*fsg.fsg_csize,
244 "", HN_AUTOSCALE, HN_B|HN_NOSPACE);
246 t = fsg.fsg_time.tv_sec;
247 strftime(tmbuf, sizeof(tmbuf), "%F %T", localtime(&t));
249 printf("%s: %s, taken %s", dev, fsg.fsg_mount, tmbuf);
250 if ((flags & FSS_UNCONFIG_ON_CLOSE) != 0)
251 printf(", unconfig on close");
252 if (fsg.fsg_csize == 0)
253 printf(", file system internal\n");
254 else
255 printf(", %"PRId64" cluster of %s, %s backup\n",
256 fsg.fsg_mount_size, clbuf, bsbuf);
257 } else
258 printf("%s: %s\n", dev, fsg.fsg_mount);
260 close(fd);
262 if (argc > 0)
263 break;
267 void
268 usage(void)
270 fprintf(stderr, "%s",
271 "usage: fssconfig [-cxv] device path backup [cluster [size]]\n"
272 " fssconfig -u [-v] device\n"
273 " fssconfig -l [-v] [device]\n");
274 exit(1);