]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core_compat.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / cddl / contrib / opensolaris / lib / libzfs_core / common / libzfs_core_compat.c
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21
22 /*
23  * Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
24  */
25
26 #include <sys/zfs_ioctl.h>
27 #include <zfs_ioctl_compat.h>
28 #include "libzfs_core_compat.h"
29
30 extern int zfs_ioctl_version;
31
32 int
33 lzc_compat_pre(zfs_cmd_t *zc, zfs_ioc_t *ioc, nvlist_t **source)
34 {
35         nvlist_t *nvl = NULL;
36         nvpair_t *pair, *hpair;
37         char *buf, *val;
38         zfs_ioc_t vecnum;
39         uint32_t type32;
40         int32_t cleanup_fd;
41         int error = 0;
42         int pos;
43
44         if (zfs_ioctl_version >= ZFS_IOCVER_LZC)
45                 return (0);
46
47         vecnum = *ioc;
48
49         switch (vecnum) {
50         case ZFS_IOC_CREATE:
51                 type32 = fnvlist_lookup_int32(*source, "type");
52                 zc->zc_objset_type = (uint64_t)type32;
53                 nvlist_lookup_nvlist(*source, "props", &nvl);
54                 *source = nvl;
55         break;
56         case ZFS_IOC_CLONE:
57                 buf = fnvlist_lookup_string(*source, "origin");
58                 strlcpy(zc->zc_value, buf, MAXPATHLEN);
59                 nvlist_lookup_nvlist(*source, "props", &nvl);
60                 *ioc = ZFS_IOC_CREATE;
61                 *source = nvl;
62         break;
63         case ZFS_IOC_SNAPSHOT:
64                 nvl = fnvlist_lookup_nvlist(*source, "snaps");
65                 pair = nvlist_next_nvpair(nvl, NULL);
66                 if (pair != NULL) {
67                         buf = nvpair_name(pair);
68                         pos = strcspn(buf, "@");
69                         strlcpy(zc->zc_name, buf, pos + 1);
70                         strlcpy(zc->zc_value, buf + pos + 1, MAXPATHLEN);
71                 } else
72                         error = EINVAL;
73                 /* old kernel cannot create multiple snapshots */
74                 if (!error && nvlist_next_nvpair(nvl, pair) != NULL)
75                         error = EOPNOTSUPP;
76                 nvlist_free(nvl);
77                 nvl = NULL;
78                 nvlist_lookup_nvlist(*source, "props", &nvl);
79                 *source = nvl;
80         break;
81         case ZFS_IOC_SPACE_SNAPS:
82                 buf = fnvlist_lookup_string(*source, "firstsnap");
83                 strlcpy(zc->zc_value, buf, MAXPATHLEN);
84         break;
85         case ZFS_IOC_DESTROY_SNAPS:
86                 nvl = fnvlist_lookup_nvlist(*source, "snaps");
87                 pair = nvlist_next_nvpair(nvl, NULL);
88                 if (pair != NULL) {
89                         buf = nvpair_name(pair);
90                         pos = strcspn(buf, "@");
91                         strlcpy(zc->zc_name, buf, pos + 1);
92                 } else
93                         error = EINVAL;
94                 /* old kernel cannot atomically destroy multiple snaps */
95                 if (!error && nvlist_next_nvpair(nvl, pair) != NULL)
96                         error = EOPNOTSUPP;
97                 *source = nvl;
98         break;
99         case ZFS_IOC_HOLD:
100                 nvl = fnvlist_lookup_nvlist(*source, "holds");
101                 pair = nvlist_next_nvpair(nvl, NULL);
102                 if (pair != NULL) {
103                         buf = nvpair_name(pair);
104                         pos = strcspn(buf, "@");
105                         strlcpy(zc->zc_name, buf, pos + 1);
106                         strlcpy(zc->zc_value, buf + pos + 1, MAXPATHLEN);
107                         if (nvpair_value_string(pair, &val) == 0)
108                                 strlcpy(zc->zc_string, val, MAXNAMELEN);
109                         else
110                                 error = EINVAL;
111                 } else
112                         error = EINVAL;
113                 /* old kernel cannot atomically create multiple holds */
114                 if (!error && nvlist_next_nvpair(nvl, pair) != NULL)
115                         error = EOPNOTSUPP;
116                 nvlist_free(nvl);
117                 if (nvlist_lookup_int32(*source, "cleanup_fd",
118                     &cleanup_fd) == 0)
119                         zc->zc_cleanup_fd = cleanup_fd;
120                 else
121                         zc->zc_cleanup_fd = -1;
122         break;
123         case ZFS_IOC_RELEASE:
124                 pair = nvlist_next_nvpair(*source, NULL);
125                 if (pair != NULL) {
126                         buf = nvpair_name(pair);
127                         pos = strcspn(buf, "@");
128                         strlcpy(zc->zc_name, buf, pos + 1);
129                         strlcpy(zc->zc_value, buf + pos + 1, MAXPATHLEN);
130                         if (nvpair_value_nvlist(pair, &nvl) == 0) {
131                                 hpair = nvlist_next_nvpair(nvl, NULL);
132                                 if (hpair != NULL)
133                                         strlcpy(zc->zc_string,
134                                             nvpair_name(hpair), MAXNAMELEN);
135                                 else
136                                         error = EINVAL;
137                                 if (!error && nvlist_next_nvpair(nvl,
138                                     hpair) != NULL)
139                                         error = EOPNOTSUPP;
140                         } else
141                                 error = EINVAL;
142                 } else
143                         error = EINVAL;
144                 /* old kernel cannot atomically release multiple holds */
145                 if (!error && nvlist_next_nvpair(nvl, pair) != NULL)
146                         error = EOPNOTSUPP;
147         break;
148         }
149
150         return (error);
151 }
152
153 void
154 lzc_compat_post(zfs_cmd_t *zc, const zfs_ioc_t ioc)
155 {
156         if (zfs_ioctl_version >= ZFS_IOCVER_LZC)
157                 return;
158
159         switch (ioc) {
160         case ZFS_IOC_CREATE:
161         case ZFS_IOC_CLONE:
162         case ZFS_IOC_SNAPSHOT:
163         case ZFS_IOC_SPACE_SNAPS:
164         case ZFS_IOC_DESTROY_SNAPS:
165                 zc->zc_nvlist_dst_filled = B_FALSE;
166         break;
167         }
168 }
169
170 int
171 lzc_compat_outnvl(zfs_cmd_t *zc, const zfs_ioc_t ioc, nvlist_t **outnvl)
172 {
173         nvlist_t *nvl;
174
175         if (zfs_ioctl_version >= ZFS_IOCVER_LZC)
176                 return (0);
177
178         switch (ioc) {
179         case ZFS_IOC_SPACE_SNAPS:
180                 nvl = fnvlist_alloc();
181                 fnvlist_add_uint64(nvl, "used", zc->zc_cookie);
182                 fnvlist_add_uint64(nvl, "compressed", zc->zc_objset_type);
183                 fnvlist_add_uint64(nvl, "uncompressed", zc->zc_perm_action);
184                 *outnvl = nvl;
185         break;
186         }
187
188         return (0);
189 }