1 /* $NetBSD: fssconfig.c,v 1.5 2005/04/17 16:28:26 hannken Exp $ */
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
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
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>
46 #include <dev/fssvar.h>
51 void config(int, char **);
52 void unconfig(int, char **);
53 void list(int, char **);
57 main(int argc
, char **argv
)
60 void (*action
)(int, char **);
64 while ((ch
= getopt(argc
, argv
, "cluvx")) != -1) {
91 (*action
)(argc
, argv
);
97 config(int argc
, char **argv
)
99 int fd
, isreg
, istmp
, ispersistent
;
100 char full
[64], path
[MAXPATHLEN
];
104 struct statvfs fsbuf
;
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]);
125 isreg
= ispersistent
= 1;
134 fss
.fss_csize
= strsuftoll("cluster size", argv
[3], 0, INT_MAX
);
138 bssize
= strsuftoll("bs size", argv
[4], 0, LLONG_MAX
);
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) {
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
;
155 if (fstat(fd
, &sbuf
) < 0)
156 err(1, "stat: %s", fss
.fss_bstore
);
157 if (!ispersistent
&& sbuf
.st_dev
== mountdev
)
159 isreg
= S_ISREG(sbuf
.st_mode
);
160 if (!ispersistent
&& isreg
&& ftruncate(fd
, bssize
) < 0)
161 err(1, "truncate %s", fss
.fss_bstore
);
165 if ((fd
= opendisk(argv
[0], O_RDWR
, full
, sizeof(full
), 0)) < 0) {
167 unlink(fss
.fss_bstore
);
168 err(1, "open: %s", argv
[0]);
171 if (ioctl(fd
, FSSIOCSET
, &fss
) < 0) {
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
);
185 unconfig(int argc
, char **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
);
204 list(int argc
, char **argv
)
207 char *dev
, path
[64], full
[64];
208 char clbuf
[5], bsbuf
[5], tmbuf
[64];
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
))
226 err(1, "open: %s", dev
);
229 if (ioctl(fd
, FSSIOFGET
, &flags
) < 0)
232 if (ioctl(fd
, FSSIOCGET
, &fsg
) < 0) {
234 printf("%s: not in use\n", dev
);
236 err(1, "%s: FSSIOCGET", full
);
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");
255 printf(", %"PRId64
" cluster of %s, %s backup\n",
256 fsg
.fsg_mount_size
, clbuf
, bsbuf
);
258 printf("%s: %s\n", dev
, fsg
.fsg_mount
);
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");