2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2010-2012 Semihalf.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
40 #include <sys/ioctl.h>
42 #include <sys/param.h>
43 #include <sys/stdint.h>
44 #include <sys/ucred.h>
46 #include <sys/mount.h>
48 #include <fs/nandfs/nandfs_fs.h>
49 #include <libnandfs.h>
51 #define NANDFS_IS_VALID 0x1
52 #define NANDFS_IS_OPENED 0x2
53 #define NANDFS_IS_OPENED_DEV 0x4
54 #define NANDFS_IS_ERROR 0x8
59 #define NANDFS_DEBUG(fmt, args...) do { \
60 printf("libnandfs:" fmt "\n", ##args); } while (0)
62 #define NANDFS_DEBUG(fmt, args...)
65 #define NANDFS_ASSERT_VALID(fs) assert((fs)->n_flags & NANDFS_IS_VALID)
66 #define NANDFS_ASSERT_VALID_DEV(fs) \
67 assert(((fs)->n_flags & (NANDFS_IS_VALID | NANDFS_IS_OPENED_DEV)) == \
68 (NANDFS_IS_VALID | NANDFS_IS_OPENED_DEV))
71 nandfs_iserror(struct nandfs *fs)
74 NANDFS_ASSERT_VALID(fs);
76 return (fs->n_flags & NANDFS_IS_ERROR);
80 nandfs_errmsg(struct nandfs *fs)
83 NANDFS_ASSERT_VALID(fs);
85 assert(nandfs_iserror(fs));
87 return (fs->n_errmsg);
91 nandfs_seterr(struct nandfs *fs, const char *fmt, ...)
96 vsnprintf(fs->n_errmsg, sizeof(fs->n_errmsg), fmt, ap);
98 fs->n_flags |= NANDFS_IS_ERROR;
102 nandfs_dev(struct nandfs *fs)
105 NANDFS_ASSERT_VALID(fs);
110 nandfs_init(struct nandfs *fs, const char *dir)
113 snprintf(fs->n_ioc, sizeof(fs->n_ioc), "%s/%s", dir, ".");
115 fs->n_flags = NANDFS_IS_VALID;
119 nandfs_destroy(struct nandfs *fs)
122 assert(fs->n_iocfd == -1);
124 ~(NANDFS_IS_ERROR | NANDFS_IS_VALID);
125 assert(fs->n_flags == 0);
129 nandfs_open(struct nandfs *fs)
131 struct nandfs_fsinfo fsinfo;
133 fs->n_flags |= NANDFS_IS_OPENED;
135 fs->n_iocfd = open(fs->n_ioc, O_RDONLY, S_IRUSR | S_IWUSR | S_IRGRP |
136 S_IWGRP | S_IROTH | S_IWOTH);
137 if (fs->n_iocfd == -1) {
138 nandfs_seterr(fs, "couldn't open %s: %s", fs->n_ioc,
143 if (ioctl(fs->n_iocfd, NANDFS_IOCTL_GET_FSINFO, &fsinfo) == -1) {
144 nandfs_seterr(fs, "couldn't fetch fsinfo: %s",
149 memcpy(&fs->n_fsdata, &fsinfo.fs_fsdata, sizeof(fs->n_fsdata));
150 memcpy(&fs->n_sb, &fsinfo.fs_super, sizeof(fs->n_sb));
151 snprintf(fs->n_dev, sizeof(fs->n_dev), "%s", fsinfo.fs_dev);
157 nandfs_close(struct nandfs *fs)
160 NANDFS_ASSERT_VALID(fs);
161 assert(fs->n_flags & NANDFS_IS_OPENED);
165 fs->n_flags &= ~NANDFS_IS_OPENED;
169 nandfs_get_cpstat(struct nandfs *fs, struct nandfs_cpstat *cpstat)
172 NANDFS_ASSERT_VALID(fs);
174 if (ioctl(fs->n_iocfd, NANDFS_IOCTL_GET_CPSTAT, cpstat) == -1) {
175 nandfs_seterr(fs, "ioctl NANDFS_IOCTL_GET_CPSTAT: %s",
184 nandfs_get_cpinfo(struct nandfs *fs, uint64_t cno, int mode,
185 struct nandfs_cpinfo *cpinfo, size_t nci)
187 struct nandfs_argv args;
189 NANDFS_ASSERT_VALID(fs);
191 args.nv_base = (u_long)cpinfo;
192 args.nv_nmembs = nci;
194 args.nv_flags = mode;
196 if (ioctl(fs->n_iocfd, NANDFS_IOCTL_GET_CPINFO, &args) == -1) {
197 nandfs_seterr(fs, "ioctl NANDFS_IOCTL_GET_CPINFO: %s",
202 return (args.nv_nmembs);
206 nandfs_get_cp(struct nandfs *fs, uint64_t cno, struct nandfs_cpinfo *cpinfo,
210 return (nandfs_get_cpinfo(fs, cno, NANDFS_CHECKPOINT, cpinfo, nci));
214 nandfs_get_snap(struct nandfs *fs, uint64_t cno, struct nandfs_cpinfo *cpinfo,
218 return (nandfs_get_cpinfo(fs, cno, NANDFS_SNAPSHOT, cpinfo, nci));
222 nandfs_make_snap(struct nandfs *fs, uint64_t *cno)
225 NANDFS_ASSERT_VALID(fs);
227 if (ioctl(fs->n_iocfd, NANDFS_IOCTL_MAKE_SNAP, cno) == -1) {
228 nandfs_seterr(fs, "ioctl NANDFS_IOCTL_MAKE_SNAP: %s",
237 nandfs_delete_snap(struct nandfs *fs, uint64_t cno)
240 NANDFS_ASSERT_VALID(fs);
242 if (ioctl(fs->n_iocfd, NANDFS_IOCTL_DELETE_SNAP, &cno) == -1) {
243 nandfs_seterr(fs, "ioctl NANDFS_IOCTL_DELETE_SNAP: %s",