1 /* $NetBSD: snapshot.c,v 1.3 2006/10/26 20:02:30 hannken Exp $ */
4 * Copyright (c) 2005 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>
37 #include <dev/fssvar.h>
49 * Create a snapshot of the file system currently mounted on the first argument
50 * using the second argument as backing store and return an open file
51 * descriptor for the snapshot. If the second argument is NULL, use the first
52 * as backing store. If the third argument is not NULL, it gets the time the
53 * snapshot was created. If the fourth argument is not NULL, it gets the
54 * snapshot device path.
57 snap_open(char *mountpoint
, char *backup
, time_t *snap_date
, char **snap_dev
)
59 int i
, fd
, israw
, fsinternal
, dounlink
, flags
;
60 char path
[MAXPATHLEN
], fss_dev
[14];
70 fss
.fss_mount
= mountpoint
;
71 fss
.fss_bstore
= backup
? backup
: fss
.fss_mount
;
74 if (stat(fss
.fss_mount
, &sb
) < 0)
79 * Prepare the backing store. `backup' is either a raw device,
80 * a file or a directory. If it is a file, it must not exist.
83 if (stat(fss
.fss_bstore
, &sb
) == 0) {
84 if (S_ISDIR(sb
.st_mode
)) {
85 snprintf(path
, sizeof(path
),
86 "%s/XXXXXXXXXX", fss
.fss_bstore
);
88 fss
.fss_bstore
= path
;
90 } else if (S_ISCHR(sb
.st_mode
)) {
91 fd
= open(fss
.fss_bstore
, O_RDWR
);
96 fd
= open(fss
.fss_bstore
, O_CREAT
|O_EXCL
|O_WRONLY
, 0600);
102 if (fstat(fd
, &sb
) < 0)
104 fsinternal
= (!israw
&& sb
.st_dev
== mountdev
);
107 * If the backing store is a plain file and the snapshot
108 * is not file system internal, truncate to file system
111 if (!israw
&& !fsinternal
) {
112 if (statvfs(fss
.fss_bstore
, &fsb
) < 0)
114 if (ftruncate(fd
, (off_t
)fsb
.f_frsize
*fsb
.f_bavail
) < 0)
122 * Create the snapshot on the first free snapshot device.
125 snprintf(fss_dev
, sizeof(fss_dev
), "/dev/rfss%d", i
);
126 if ((fd
= open(fss_dev
, O_RDWR
, 0)) < 0)
129 if (ioctl(fd
, FSSIOFGET
, &flags
) < 0)
132 if (ioctl(fd
, FSSIOCSET
, &fss
) < 0) {
140 if (snap_dev
!= NULL
) {
141 *snap_dev
= strdup(fss_dev
);
142 if (*snap_dev
== NULL
) {
143 ioctl(fd
, FSSIOCCLR
);
148 flags
|= FSS_UNCONFIG_ON_CLOSE
;
149 if (ioctl(fd
, FSSIOCGET
, &fsg
) < 0 ||
150 ioctl(fd
, FSSIOFSET
, &flags
) < 0 ||
151 (!israw
&& unlink(fss
.fss_bstore
) < 0)) {
152 ioctl(fd
, FSSIOCCLR
);
156 if (snap_date
!= NULL
)
157 *snap_date
= fsg
.fsg_time
.tv_sec
;
163 unlink(fss
.fss_bstore
);