author | Jim Dunham <James.Dunham@Sun.COM> |
Tue, 09 Mar 2010 15:50:06 -0500 | |
changeset 11876 | 5fce03ad05c6 |
parent 11807 | 73a3c0d27389 |
child 12296 | 7cf402a7f374 |
permissions | -rw-r--r-- |
789 | 1 |
/* |
2 |
* CDDL HEADER START |
|
3 |
* |
|
4 |
* The contents of this file are subject to the terms of the |
|
1544 | 5 |
* Common Development and Distribution License (the "License"). |
6 |
* You may not use this file except in compliance with the License. |
|
789 | 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 |
/* |
|
11422
42768837421d
PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents:
11022
diff
changeset
|
22 |
* Copyright 2010 Sun Microsystems, Inc. All rights reserved. |
789 | 23 |
* Use is subject to license terms. |
24 |
*/ |
|
25 |
||
26 |
/* |
|
27 |
* Internal utility routines for the ZFS library. |
|
28 |
*/ |
|
29 |
||
30 |
#include <errno.h> |
|
31 |
#include <fcntl.h> |
|
32 |
#include <libintl.h> |
|
33 |
#include <stdarg.h> |
|
34 |
#include <stdio.h> |
|
35 |
#include <stdlib.h> |
|
36 |
#include <strings.h> |
|
37 |
#include <unistd.h> |
|
5094 | 38 |
#include <ctype.h> |
39 |
#include <math.h> |
|
789 | 40 |
#include <sys/mnttab.h> |
3635 | 41 |
#include <sys/mntent.h> |
42 |
#include <sys/types.h> |
|
789 | 43 |
|
44 |
#include <libzfs.h> |
|
45 |
||
46 |
#include "libzfs_impl.h" |
|
4787 | 47 |
#include "zfs_prop.h" |
789 | 48 |
|
2082 | 49 |
int |
50 |
libzfs_errno(libzfs_handle_t *hdl) |
|
51 |
{ |
|
52 |
return (hdl->libzfs_error); |
|
53 |
} |
|
789 | 54 |
|
2082 | 55 |
const char * |
56 |
libzfs_error_action(libzfs_handle_t *hdl) |
|
57 |
{ |
|
58 |
return (hdl->libzfs_action); |
|
59 |
} |
|
60 |
||
61 |
const char * |
|
62 |
libzfs_error_description(libzfs_handle_t *hdl) |
|
63 |
{ |
|
64 |
if (hdl->libzfs_desc[0] != '\0') |
|
65 |
return (hdl->libzfs_desc); |
|
789 | 66 |
|
2082 | 67 |
switch (hdl->libzfs_error) { |
68 |
case EZFS_NOMEM: |
|
69 |
return (dgettext(TEXT_DOMAIN, "out of memory")); |
|
70 |
case EZFS_BADPROP: |
|
71 |
return (dgettext(TEXT_DOMAIN, "invalid property value")); |
|
72 |
case EZFS_PROPREADONLY: |
|
73 |
return (dgettext(TEXT_DOMAIN, "read only property")); |
|
74 |
case EZFS_PROPTYPE: |
|
75 |
return (dgettext(TEXT_DOMAIN, "property doesn't apply to " |
|
76 |
"datasets of this type")); |
|
77 |
case EZFS_PROPNONINHERIT: |
|
78 |
return (dgettext(TEXT_DOMAIN, "property cannot be inherited")); |
|
79 |
case EZFS_PROPSPACE: |
|
80 |
return (dgettext(TEXT_DOMAIN, "invalid quota or reservation")); |
|
81 |
case EZFS_BADTYPE: |
|
82 |
return (dgettext(TEXT_DOMAIN, "operation not applicable to " |
|
83 |
"datasets of this type")); |
|
84 |
case EZFS_BUSY: |
|
85 |
return (dgettext(TEXT_DOMAIN, "pool or dataset is busy")); |
|
86 |
case EZFS_EXISTS: |
|
87 |
return (dgettext(TEXT_DOMAIN, "pool or dataset exists")); |
|
88 |
case EZFS_NOENT: |
|
89 |
return (dgettext(TEXT_DOMAIN, "no such pool or dataset")); |
|
90 |
case EZFS_BADSTREAM: |
|
91 |
return (dgettext(TEXT_DOMAIN, "invalid backup stream")); |
|
92 |
case EZFS_DSREADONLY: |
|
93 |
return (dgettext(TEXT_DOMAIN, "dataset is read only")); |
|
94 |
case EZFS_VOLTOOBIG: |
|
95 |
return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for " |
|
96 |
"this system")); |
|
97 |
case EZFS_INVALIDNAME: |
|
98 |
return (dgettext(TEXT_DOMAIN, "invalid name")); |
|
99 |
case EZFS_BADRESTORE: |
|
100 |
return (dgettext(TEXT_DOMAIN, "unable to restore to " |
|
101 |
"destination")); |
|
102 |
case EZFS_BADBACKUP: |
|
103 |
return (dgettext(TEXT_DOMAIN, "backup failed")); |
|
104 |
case EZFS_BADTARGET: |
|
105 |
return (dgettext(TEXT_DOMAIN, "invalid target vdev")); |
|
106 |
case EZFS_NODEVICE: |
|
107 |
return (dgettext(TEXT_DOMAIN, "no such device in pool")); |
|
108 |
case EZFS_BADDEV: |
|
109 |
return (dgettext(TEXT_DOMAIN, "invalid device")); |
|
110 |
case EZFS_NOREPLICAS: |
|
111 |
return (dgettext(TEXT_DOMAIN, "no valid replicas")); |
|
112 |
case EZFS_RESILVERING: |
|
113 |
return (dgettext(TEXT_DOMAIN, "currently resilvering")); |
|
114 |
case EZFS_BADVERSION: |
|
115 |
return (dgettext(TEXT_DOMAIN, "unsupported version")); |
|
116 |
case EZFS_POOLUNAVAIL: |
|
117 |
return (dgettext(TEXT_DOMAIN, "pool is unavailable")); |
|
118 |
case EZFS_DEVOVERFLOW: |
|
119 |
return (dgettext(TEXT_DOMAIN, "too many devices in one vdev")); |
|
120 |
case EZFS_BADPATH: |
|
121 |
return (dgettext(TEXT_DOMAIN, "must be an absolute path")); |
|
122 |
case EZFS_CROSSTARGET: |
|
123 |
return (dgettext(TEXT_DOMAIN, "operation crosses datasets or " |
|
124 |
"pools")); |
|
125 |
case EZFS_ZONED: |
|
126 |
return (dgettext(TEXT_DOMAIN, "dataset in use by local zone")); |
|
127 |
case EZFS_MOUNTFAILED: |
|
128 |
return (dgettext(TEXT_DOMAIN, "mount failed")); |
|
129 |
case EZFS_UMOUNTFAILED: |
|
130 |
return (dgettext(TEXT_DOMAIN, "umount failed")); |
|
3126 | 131 |
case EZFS_UNSHARENFSFAILED: |
2082 | 132 |
return (dgettext(TEXT_DOMAIN, "unshare(1M) failed")); |
3126 | 133 |
case EZFS_SHARENFSFAILED: |
2082 | 134 |
return (dgettext(TEXT_DOMAIN, "share(1M) failed")); |
5331 | 135 |
case EZFS_UNSHARESMBFAILED: |
136 |
return (dgettext(TEXT_DOMAIN, "smb remove share failed")); |
|
137 |
case EZFS_SHARESMBFAILED: |
|
138 |
return (dgettext(TEXT_DOMAIN, "smb add share failed")); |
|
2082 | 139 |
case EZFS_PERM: |
140 |
return (dgettext(TEXT_DOMAIN, "permission denied")); |
|
141 |
case EZFS_NOSPC: |
|
142 |
return (dgettext(TEXT_DOMAIN, "out of space")); |
|
11807
73a3c0d27389
6911541 'zfs mount' coredump
Sam Falkner <Sam.Falkner@Sun.COM>
parents:
11422
diff
changeset
|
143 |
case EZFS_FAULT: |
73a3c0d27389
6911541 'zfs mount' coredump
Sam Falkner <Sam.Falkner@Sun.COM>
parents:
11422
diff
changeset
|
144 |
return (dgettext(TEXT_DOMAIN, "bad address")); |
2082 | 145 |
case EZFS_IO: |
146 |
return (dgettext(TEXT_DOMAIN, "I/O error")); |
|
147 |
case EZFS_INTR: |
|
148 |
return (dgettext(TEXT_DOMAIN, "signal received")); |
|
149 |
case EZFS_ISSPARE: |
|
150 |
return (dgettext(TEXT_DOMAIN, "device is reserved as a hot " |
|
151 |
"spare")); |
|
152 |
case EZFS_INVALCONFIG: |
|
153 |
return (dgettext(TEXT_DOMAIN, "invalid vdev configuration")); |
|
2474
c001ad7e0c25
6368751 libzfs interface for mount/umounting all the file systems for a given pool
eschrock
parents:
2082
diff
changeset
|
154 |
case EZFS_RECURSIVE: |
c001ad7e0c25
6368751 libzfs interface for mount/umounting all the file systems for a given pool
eschrock
parents:
2082
diff
changeset
|
155 |
return (dgettext(TEXT_DOMAIN, "recursive dataset dependency")); |
2926 | 156 |
case EZFS_NOHISTORY: |
157 |
return (dgettext(TEXT_DOMAIN, "no history available")); |
|
3912 | 158 |
case EZFS_POOLPROPS: |
159 |
return (dgettext(TEXT_DOMAIN, "failed to retrieve " |
|
160 |
"pool properties")); |
|
161 |
case EZFS_POOL_NOTSUP: |
|
162 |
return (dgettext(TEXT_DOMAIN, "operation not supported " |
|
163 |
"on this type of pool")); |
|
164 |
case EZFS_POOL_INVALARG: |
|
165 |
return (dgettext(TEXT_DOMAIN, "invalid argument for " |
|
166 |
"this pool operation")); |
|
3978
2dd668007b7a
6533813 recursive snapshotting resulted in a bad stack overflow
mmusante
parents:
3912
diff
changeset
|
167 |
case EZFS_NAMETOOLONG: |
2dd668007b7a
6533813 recursive snapshotting resulted in a bad stack overflow
mmusante
parents:
3912
diff
changeset
|
168 |
return (dgettext(TEXT_DOMAIN, "dataset name is too long")); |
4276
c42d49ffb16f
6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents:
4180
diff
changeset
|
169 |
case EZFS_OPENFAILED: |
c42d49ffb16f
6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents:
4180
diff
changeset
|
170 |
return (dgettext(TEXT_DOMAIN, "open failed")); |
c42d49ffb16f
6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents:
4180
diff
changeset
|
171 |
case EZFS_NOCAP: |
c42d49ffb16f
6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents:
4180
diff
changeset
|
172 |
return (dgettext(TEXT_DOMAIN, |
c42d49ffb16f
6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents:
4180
diff
changeset
|
173 |
"disk capacity information could not be retrieved")); |
c42d49ffb16f
6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents:
4180
diff
changeset
|
174 |
case EZFS_LABELFAILED: |
c42d49ffb16f
6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents:
4180
diff
changeset
|
175 |
return (dgettext(TEXT_DOMAIN, "write of label failed")); |
4543 | 176 |
case EZFS_BADWHO: |
177 |
return (dgettext(TEXT_DOMAIN, "invalid user/group")); |
|
178 |
case EZFS_BADPERM: |
|
179 |
return (dgettext(TEXT_DOMAIN, "invalid permission")); |
|
180 |
case EZFS_BADPERMSET: |
|
181 |
return (dgettext(TEXT_DOMAIN, "invalid permission set name")); |
|
182 |
case EZFS_NODELEGATION: |
|
183 |
return (dgettext(TEXT_DOMAIN, "delegated administration is " |
|
184 |
"disabled on pool")); |
|
185 |
case EZFS_PERMRDONLY: |
|
186 |
return (dgettext(TEXT_DOMAIN, "snapshot permissions cannot be" |
|
187 |
" modified")); |
|
5363 | 188 |
case EZFS_BADCACHE: |
189 |
return (dgettext(TEXT_DOMAIN, "invalid or missing cache file")); |
|
5450 | 190 |
case EZFS_ISL2CACHE: |
191 |
return (dgettext(TEXT_DOMAIN, "device is in use as a cache")); |
|
6423 | 192 |
case EZFS_VDEVNOTSUP: |
193 |
return (dgettext(TEXT_DOMAIN, "vdev specification is not " |
|
194 |
"supported")); |
|
7042
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
195 |
case EZFS_NOTSUP: |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
196 |
return (dgettext(TEXT_DOMAIN, "operation not supported " |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
197 |
"on this dataset")); |
7214
04c540040a32
6721908 A hot spare "in use" in an exported zpool, is stolen when a disk fails in an imported pool.
lling
parents:
7042
diff
changeset
|
198 |
case EZFS_ACTIVE_SPARE: |
04c540040a32
6721908 A hot spare "in use" in an exported zpool, is stolen when a disk fails in an imported pool.
lling
parents:
7042
diff
changeset
|
199 |
return (dgettext(TEXT_DOMAIN, "pool has active shared spare " |
04c540040a32
6721908 A hot spare "in use" in an exported zpool, is stolen when a disk fails in an imported pool.
lling
parents:
7042
diff
changeset
|
200 |
"device")); |
9701
cc5b64682e64
6803605 should be able to offline log devices
George Wilson <George.Wilson@Sun.COM>
parents:
9396
diff
changeset
|
201 |
case EZFS_UNPLAYED_LOGS: |
cc5b64682e64
6803605 should be able to offline log devices
George Wilson <George.Wilson@Sun.COM>
parents:
9396
diff
changeset
|
202 |
return (dgettext(TEXT_DOMAIN, "log device has unplayed intent " |
cc5b64682e64
6803605 should be able to offline log devices
George Wilson <George.Wilson@Sun.COM>
parents:
9396
diff
changeset
|
203 |
"logs")); |
10242
c40d075fbca6
PSARC/2009/297 zfs snapshot holds
Chris Kirby <chris.kirby@sun.com>
parents:
9701
diff
changeset
|
204 |
case EZFS_REFTAG_RELE: |
c40d075fbca6
PSARC/2009/297 zfs snapshot holds
Chris Kirby <chris.kirby@sun.com>
parents:
9701
diff
changeset
|
205 |
return (dgettext(TEXT_DOMAIN, "no such tag on this dataset")); |
c40d075fbca6
PSARC/2009/297 zfs snapshot holds
Chris Kirby <chris.kirby@sun.com>
parents:
9701
diff
changeset
|
206 |
case EZFS_REFTAG_HOLD: |
c40d075fbca6
PSARC/2009/297 zfs snapshot holds
Chris Kirby <chris.kirby@sun.com>
parents:
9701
diff
changeset
|
207 |
return (dgettext(TEXT_DOMAIN, "tag already exists on this " |
c40d075fbca6
PSARC/2009/297 zfs snapshot holds
Chris Kirby <chris.kirby@sun.com>
parents:
9701
diff
changeset
|
208 |
"dataset")); |
10342
108f0058f837
6833815 scheduled snapshots deleted per snapshot policy can lead to replication failures
Chris Kirby <chris.kirby@sun.com>
parents:
10242
diff
changeset
|
209 |
case EZFS_TAGTOOLONG: |
108f0058f837
6833815 scheduled snapshots deleted per snapshot policy can lead to replication failures
Chris Kirby <chris.kirby@sun.com>
parents:
10242
diff
changeset
|
210 |
return (dgettext(TEXT_DOMAIN, "tag too long")); |
11007
216d8396182e
PSARC/2009/557 ZFS send dedup
Lori Alt <Lori.Alt@Sun.COM>
parents:
10817
diff
changeset
|
211 |
case EZFS_PIPEFAILED: |
216d8396182e
PSARC/2009/557 ZFS send dedup
Lori Alt <Lori.Alt@Sun.COM>
parents:
10817
diff
changeset
|
212 |
return (dgettext(TEXT_DOMAIN, "pipe create failed")); |
216d8396182e
PSARC/2009/557 ZFS send dedup
Lori Alt <Lori.Alt@Sun.COM>
parents:
10817
diff
changeset
|
213 |
case EZFS_THREADCREATEFAILED: |
216d8396182e
PSARC/2009/557 ZFS send dedup
Lori Alt <Lori.Alt@Sun.COM>
parents:
10817
diff
changeset
|
214 |
return (dgettext(TEXT_DOMAIN, "thread create failed")); |
11422
42768837421d
PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents:
11022
diff
changeset
|
215 |
case EZFS_POSTSPLIT_ONLINE: |
42768837421d
PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents:
11022
diff
changeset
|
216 |
return (dgettext(TEXT_DOMAIN, "disk was split from this pool " |
42768837421d
PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents:
11022
diff
changeset
|
217 |
"into a new one")); |
2082 | 218 |
case EZFS_UNKNOWN: |
219 |
return (dgettext(TEXT_DOMAIN, "unknown error")); |
|
220 |
default: |
|
2500
12e683f74751
6455228 zpool_mount_datasets() should take an additional flag
eschrock
parents:
2474
diff
changeset
|
221 |
assert(hdl->libzfs_error == 0); |
12e683f74751
6455228 zpool_mount_datasets() should take an additional flag
eschrock
parents:
2474
diff
changeset
|
222 |
return (dgettext(TEXT_DOMAIN, "no error")); |
2082 | 223 |
} |
224 |
} |
|
225 |
||
226 |
/*PRINTFLIKE2*/ |
|
789 | 227 |
void |
2082 | 228 |
zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...) |
789 | 229 |
{ |
230 |
va_list ap; |
|
231 |
||
232 |
va_start(ap, fmt); |
|
233 |
||
2082 | 234 |
(void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc), |
235 |
fmt, ap); |
|
236 |
hdl->libzfs_desc_active = 1; |
|
789 | 237 |
|
238 |
va_end(ap); |
|
239 |
} |
|
240 |
||
2082 | 241 |
static void |
242 |
zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap) |
|
243 |
{ |
|
244 |
(void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action), |
|
245 |
fmt, ap); |
|
246 |
hdl->libzfs_error = error; |
|
247 |
||
248 |
if (hdl->libzfs_desc_active) |
|
249 |
hdl->libzfs_desc_active = 0; |
|
250 |
else |
|
251 |
hdl->libzfs_desc[0] = '\0'; |
|
252 |
||
253 |
if (hdl->libzfs_printerr) { |
|
254 |
if (error == EZFS_UNKNOWN) { |
|
255 |
(void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal " |
|
256 |
"error: %s\n"), libzfs_error_description(hdl)); |
|
257 |
abort(); |
|
258 |
} |
|
259 |
||
260 |
(void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action, |
|
3912 | 261 |
libzfs_error_description(hdl)); |
2082 | 262 |
if (error == EZFS_NOMEM) |
263 |
exit(1); |
|
264 |
} |
|
265 |
} |
|
266 |
||
3237
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
267 |
int |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
268 |
zfs_error(libzfs_handle_t *hdl, int error, const char *msg) |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
269 |
{ |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
270 |
return (zfs_error_fmt(hdl, error, "%s", msg)); |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
271 |
} |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
272 |
|
2082 | 273 |
/*PRINTFLIKE3*/ |
274 |
int |
|
3237
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
275 |
zfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) |
2082 | 276 |
{ |
277 |
va_list ap; |
|
278 |
||
279 |
va_start(ap, fmt); |
|
280 |
||
281 |
zfs_verror(hdl, error, fmt, ap); |
|
282 |
||
283 |
va_end(ap); |
|
284 |
||
285 |
return (-1); |
|
286 |
} |
|
287 |
||
288 |
static int |
|
289 |
zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt, |
|
290 |
va_list ap) |
|
291 |
{ |
|
292 |
switch (error) { |
|
293 |
case EPERM: |
|
294 |
case EACCES: |
|
295 |
zfs_verror(hdl, EZFS_PERM, fmt, ap); |
|
296 |
return (-1); |
|
297 |
||
4543 | 298 |
case ECANCELED: |
299 |
zfs_verror(hdl, EZFS_NODELEGATION, fmt, ap); |
|
300 |
return (-1); |
|
301 |
||
2082 | 302 |
case EIO: |
303 |
zfs_verror(hdl, EZFS_IO, fmt, ap); |
|
304 |
return (-1); |
|
305 |
||
11807
73a3c0d27389
6911541 'zfs mount' coredump
Sam Falkner <Sam.Falkner@Sun.COM>
parents:
11422
diff
changeset
|
306 |
case EFAULT: |
73a3c0d27389
6911541 'zfs mount' coredump
Sam Falkner <Sam.Falkner@Sun.COM>
parents:
11422
diff
changeset
|
307 |
zfs_verror(hdl, EZFS_FAULT, fmt, ap); |
73a3c0d27389
6911541 'zfs mount' coredump
Sam Falkner <Sam.Falkner@Sun.COM>
parents:
11422
diff
changeset
|
308 |
return (-1); |
73a3c0d27389
6911541 'zfs mount' coredump
Sam Falkner <Sam.Falkner@Sun.COM>
parents:
11422
diff
changeset
|
309 |
|
2082 | 310 |
case EINTR: |
311 |
zfs_verror(hdl, EZFS_INTR, fmt, ap); |
|
312 |
return (-1); |
|
313 |
} |
|
314 |
||
315 |
return (0); |
|
316 |
} |
|
317 |
||
3237
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
318 |
int |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
319 |
zfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg) |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
320 |
{ |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
321 |
return (zfs_standard_error_fmt(hdl, error, "%s", msg)); |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
322 |
} |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
323 |
|
2082 | 324 |
/*PRINTFLIKE3*/ |
325 |
int |
|
3237
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
326 |
zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) |
789 | 327 |
{ |
328 |
va_list ap; |
|
329 |
||
330 |
va_start(ap, fmt); |
|
331 |
||
2082 | 332 |
if (zfs_common_error(hdl, error, fmt, ap) != 0) { |
333 |
va_end(ap); |
|
334 |
return (-1); |
|
335 |
} |
|
336 |
||
337 |
switch (error) { |
|
338 |
case ENXIO: |
|
5807
8b40dde8cc40
6609780 zpool dump core when trying to destroy pool
ck153898
parents:
5450
diff
changeset
|
339 |
case ENODEV: |
2082 | 340 |
zfs_verror(hdl, EZFS_IO, fmt, ap); |
341 |
break; |
|
342 |
||
343 |
case ENOENT: |
|
344 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
345 |
"dataset does not exist")); |
|
346 |
zfs_verror(hdl, EZFS_NOENT, fmt, ap); |
|
347 |
break; |
|
348 |
||
349 |
case ENOSPC: |
|
350 |
case EDQUOT: |
|
351 |
zfs_verror(hdl, EZFS_NOSPC, fmt, ap); |
|
352 |
return (-1); |
|
353 |
||
354 |
case EEXIST: |
|
355 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
356 |
"dataset already exists")); |
|
357 |
zfs_verror(hdl, EZFS_EXISTS, fmt, ap); |
|
358 |
break; |
|
359 |
||
360 |
case EBUSY: |
|
361 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
362 |
"dataset is busy")); |
|
363 |
zfs_verror(hdl, EZFS_BUSY, fmt, ap); |
|
364 |
break; |
|
4543 | 365 |
case EROFS: |
366 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
367 |
"snapshot permissions cannot be modified")); |
|
368 |
zfs_verror(hdl, EZFS_PERMRDONLY, fmt, ap); |
|
369 |
break; |
|
3978
2dd668007b7a
6533813 recursive snapshotting resulted in a bad stack overflow
mmusante
parents:
3912
diff
changeset
|
370 |
case ENAMETOOLONG: |
2dd668007b7a
6533813 recursive snapshotting resulted in a bad stack overflow
mmusante
parents:
3912
diff
changeset
|
371 |
zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap); |
2dd668007b7a
6533813 recursive snapshotting resulted in a bad stack overflow
mmusante
parents:
3912
diff
changeset
|
372 |
break; |
5860
4e1dc300d1d7
6580259 onnv ZFS panic with zfs_purgedir in zfs_dir.c
ck153898
parents:
5807
diff
changeset
|
373 |
case ENOTSUP: |
4e1dc300d1d7
6580259 onnv ZFS panic with zfs_purgedir in zfs_dir.c
ck153898
parents:
5807
diff
changeset
|
374 |
zfs_verror(hdl, EZFS_BADVERSION, fmt, ap); |
4e1dc300d1d7
6580259 onnv ZFS panic with zfs_purgedir in zfs_dir.c
ck153898
parents:
5807
diff
changeset
|
375 |
break; |
9234
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
376 |
case EAGAIN: |
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
377 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
378 |
"pool I/O is currently suspended")); |
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
379 |
zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap); |
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
380 |
break; |
2082 | 381 |
default: |
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
382 |
zfs_error_aux(hdl, strerror(error)); |
2082 | 383 |
zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); |
384 |
break; |
|
789 | 385 |
} |
386 |
||
387 |
va_end(ap); |
|
2082 | 388 |
return (-1); |
789 | 389 |
} |
390 |
||
3237
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
391 |
int |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
392 |
zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg) |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
393 |
{ |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
394 |
return (zpool_standard_error_fmt(hdl, error, "%s", msg)); |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
395 |
} |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
396 |
|
2082 | 397 |
/*PRINTFLIKE3*/ |
398 |
int |
|
3237
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
399 |
zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) |
789 | 400 |
{ |
2082 | 401 |
va_list ap; |
402 |
||
403 |
va_start(ap, fmt); |
|
404 |
||
405 |
if (zfs_common_error(hdl, error, fmt, ap) != 0) { |
|
406 |
va_end(ap); |
|
407 |
return (-1); |
|
408 |
} |
|
409 |
||
410 |
switch (error) { |
|
411 |
case ENODEV: |
|
412 |
zfs_verror(hdl, EZFS_NODEVICE, fmt, ap); |
|
413 |
break; |
|
414 |
||
415 |
case ENOENT: |
|
3912 | 416 |
zfs_error_aux(hdl, |
417 |
dgettext(TEXT_DOMAIN, "no such pool or dataset")); |
|
2082 | 418 |
zfs_verror(hdl, EZFS_NOENT, fmt, ap); |
419 |
break; |
|
420 |
||
421 |
case EEXIST: |
|
422 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
423 |
"pool already exists")); |
|
424 |
zfs_verror(hdl, EZFS_EXISTS, fmt, ap); |
|
425 |
break; |
|
426 |
||
427 |
case EBUSY: |
|
428 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy")); |
|
7341
938f611658fc
6736545 cut and paste error in zpool_standard_error_fmt() trashes error
Eric Schrock <Eric.Schrock@Sun.COM>
parents:
7214
diff
changeset
|
429 |
zfs_verror(hdl, EZFS_BUSY, fmt, ap); |
2082 | 430 |
break; |
431 |
||
432 |
case ENXIO: |
|
433 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
434 |
"one or more devices is currently unavailable")); |
|
435 |
zfs_verror(hdl, EZFS_BADDEV, fmt, ap); |
|
436 |
break; |
|
437 |
||
438 |
case ENAMETOOLONG: |
|
439 |
zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap); |
|
440 |
break; |
|
441 |
||
3912 | 442 |
case ENOTSUP: |
443 |
zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap); |
|
444 |
break; |
|
445 |
||
446 |
case EINVAL: |
|
447 |
zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap); |
|
448 |
break; |
|
449 |
||
4543 | 450 |
case ENOSPC: |
451 |
case EDQUOT: |
|
452 |
zfs_verror(hdl, EZFS_NOSPC, fmt, ap); |
|
453 |
return (-1); |
|
9234
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
454 |
case EAGAIN: |
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
455 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
456 |
"pool I/O is currently suspended")); |
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
457 |
zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap); |
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
458 |
break; |
4543 | 459 |
|
2082 | 460 |
default: |
461 |
zfs_error_aux(hdl, strerror(error)); |
|
462 |
zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); |
|
463 |
} |
|
464 |
||
465 |
va_end(ap); |
|
466 |
return (-1); |
|
789 | 467 |
} |
468 |
||
469 |
/* |
|
470 |
* Display an out of memory error message and abort the current program. |
|
471 |
*/ |
|
2082 | 472 |
int |
473 |
no_memory(libzfs_handle_t *hdl) |
|
789 | 474 |
{ |
2082 | 475 |
return (zfs_error(hdl, EZFS_NOMEM, "internal error")); |
789 | 476 |
} |
477 |
||
478 |
/* |
|
479 |
* A safe form of malloc() which will die if the allocation fails. |
|
480 |
*/ |
|
481 |
void * |
|
2082 | 482 |
zfs_alloc(libzfs_handle_t *hdl, size_t size) |
789 | 483 |
{ |
484 |
void *data; |
|
485 |
||
486 |
if ((data = calloc(1, size)) == NULL) |
|
2082 | 487 |
(void) no_memory(hdl); |
789 | 488 |
|
489 |
return (data); |
|
490 |
} |
|
491 |
||
492 |
/* |
|
2676 | 493 |
* A safe form of realloc(), which also zeroes newly allocated space. |
494 |
*/ |
|
495 |
void * |
|
496 |
zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize) |
|
497 |
{ |
|
498 |
void *ret; |
|
499 |
||
500 |
if ((ret = realloc(ptr, newsize)) == NULL) { |
|
501 |
(void) no_memory(hdl); |
|
502 |
return (NULL); |
|
503 |
} |
|
504 |
||
505 |
bzero((char *)ret + oldsize, (newsize - oldsize)); |
|
506 |
return (ret); |
|
507 |
} |
|
508 |
||
509 |
/* |
|
789 | 510 |
* A safe form of strdup() which will die if the allocation fails. |
511 |
*/ |
|
512 |
char * |
|
2082 | 513 |
zfs_strdup(libzfs_handle_t *hdl, const char *str) |
789 | 514 |
{ |
515 |
char *ret; |
|
516 |
||
517 |
if ((ret = strdup(str)) == NULL) |
|
2082 | 518 |
(void) no_memory(hdl); |
789 | 519 |
|
520 |
return (ret); |
|
521 |
} |
|
522 |
||
523 |
/* |
|
524 |
* Convert a number to an appropriately human-readable output. |
|
525 |
*/ |
|
526 |
void |
|
527 |
zfs_nicenum(uint64_t num, char *buf, size_t buflen) |
|
528 |
{ |
|
529 |
uint64_t n = num; |
|
530 |
int index = 0; |
|
531 |
char u; |
|
532 |
||
533 |
while (n >= 1024) { |
|
1162 | 534 |
n /= 1024; |
789 | 535 |
index++; |
536 |
} |
|
537 |
||
538 |
u = " KMGTPE"[index]; |
|
539 |
||
1162 | 540 |
if (index == 0) { |
789 | 541 |
(void) snprintf(buf, buflen, "%llu", n); |
1162 | 542 |
} else if ((num & ((1ULL << 10 * index) - 1)) == 0) { |
543 |
/* |
|
544 |
* If this is an even multiple of the base, always display |
|
545 |
* without any decimal precision. |
|
546 |
*/ |
|
789 | 547 |
(void) snprintf(buf, buflen, "%llu%c", n, u); |
1162 | 548 |
} else { |
549 |
/* |
|
550 |
* We want to choose a precision that reflects the best choice |
|
551 |
* for fitting in 5 characters. This can get rather tricky when |
|
552 |
* we have numbers that are very close to an order of magnitude. |
|
553 |
* For example, when displaying 10239 (which is really 9.999K), |
|
554 |
* we want only a single place of precision for 10.0K. We could |
|
555 |
* develop some complex heuristics for this, but it's much |
|
556 |
* easier just to try each combination in turn. |
|
557 |
*/ |
|
558 |
int i; |
|
559 |
for (i = 2; i >= 0; i--) { |
|
4451 | 560 |
if (snprintf(buf, buflen, "%.*f%c", i, |
561 |
(double)num / (1ULL << 10 * index), u) <= 5) |
|
1162 | 562 |
break; |
563 |
} |
|
564 |
} |
|
789 | 565 |
} |
2082 | 566 |
|
567 |
void |
|
568 |
libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr) |
|
569 |
{ |
|
570 |
hdl->libzfs_printerr = printerr; |
|
571 |
} |
|
572 |
||
573 |
libzfs_handle_t * |
|
574 |
libzfs_init(void) |
|
575 |
{ |
|
576 |
libzfs_handle_t *hdl; |
|
577 |
||
578 |
if ((hdl = calloc(sizeof (libzfs_handle_t), 1)) == NULL) { |
|
579 |
return (NULL); |
|
580 |
} |
|
581 |
||
2500
12e683f74751
6455228 zpool_mount_datasets() should take an additional flag
eschrock
parents:
2474
diff
changeset
|
582 |
if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) { |
2082 | 583 |
free(hdl); |
584 |
return (NULL); |
|
585 |
} |
|
586 |
||
587 |
if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) { |
|
588 |
(void) close(hdl->libzfs_fd); |
|
589 |
free(hdl); |
|
590 |
return (NULL); |
|
591 |
} |
|
592 |
||
593 |
hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "r"); |
|
594 |
||
4787 | 595 |
zfs_prop_init(); |
5094 | 596 |
zpool_prop_init(); |
8811
f8deccf701cf
6790687 libzfs mnttab caching ignores external changes
Eric Taylor <Eric.Taylor@Sun.COM>
parents:
8343
diff
changeset
|
597 |
libzfs_mnttab_init(hdl); |
4787 | 598 |
|
2082 | 599 |
return (hdl); |
600 |
} |
|
601 |
||
602 |
void |
|
603 |
libzfs_fini(libzfs_handle_t *hdl) |
|
604 |
{ |
|
605 |
(void) close(hdl->libzfs_fd); |
|
606 |
if (hdl->libzfs_mnttab) |
|
607 |
(void) fclose(hdl->libzfs_mnttab); |
|
608 |
if (hdl->libzfs_sharetab) |
|
609 |
(void) fclose(hdl->libzfs_sharetab); |
|
4180
30b15f0bd3c9
6491973 sharemgr: zfs set sharenfs=on is slow with lots of zfs filesystems
dougm
parents:
3978
diff
changeset
|
610 |
zfs_uninit_libshare(hdl); |
4543 | 611 |
if (hdl->libzfs_log_str) |
612 |
(void) free(hdl->libzfs_log_str); |
|
6865 | 613 |
zpool_free_handles(hdl); |
10817
7dfde45252f0
6889826 ZFS retire agent should be able to repair pools
Eric Schrock <Eric.Schrock@Sun.COM>
parents:
10588
diff
changeset
|
614 |
libzfs_fru_clear(hdl, B_TRUE); |
2082 | 615 |
namespace_clear(hdl); |
8811
f8deccf701cf
6790687 libzfs mnttab caching ignores external changes
Eric Taylor <Eric.Taylor@Sun.COM>
parents:
8343
diff
changeset
|
616 |
libzfs_mnttab_fini(hdl); |
2082 | 617 |
free(hdl); |
618 |
} |
|
619 |
||
620 |
libzfs_handle_t * |
|
621 |
zpool_get_handle(zpool_handle_t *zhp) |
|
622 |
{ |
|
623 |
return (zhp->zpool_hdl); |
|
624 |
} |
|
625 |
||
626 |
libzfs_handle_t * |
|
627 |
zfs_get_handle(zfs_handle_t *zhp) |
|
628 |
{ |
|
629 |
return (zhp->zfs_hdl); |
|
630 |
} |
|
2676 | 631 |
|
7538
18c2451107fd
PSARC 2008/469 Excluding snapshot info from 'zfs list'
Rich Morris <Richard.Morris@Sun.COM>
parents:
7390
diff
changeset
|
632 |
zpool_handle_t * |
18c2451107fd
PSARC 2008/469 Excluding snapshot info from 'zfs list'
Rich Morris <Richard.Morris@Sun.COM>
parents:
7390
diff
changeset
|
633 |
zfs_get_pool_handle(const zfs_handle_t *zhp) |
18c2451107fd
PSARC 2008/469 Excluding snapshot info from 'zfs list'
Rich Morris <Richard.Morris@Sun.COM>
parents:
7390
diff
changeset
|
634 |
{ |
18c2451107fd
PSARC 2008/469 Excluding snapshot info from 'zfs list'
Rich Morris <Richard.Morris@Sun.COM>
parents:
7390
diff
changeset
|
635 |
return (zhp->zpool_hdl); |
18c2451107fd
PSARC 2008/469 Excluding snapshot info from 'zfs list'
Rich Morris <Richard.Morris@Sun.COM>
parents:
7390
diff
changeset
|
636 |
} |
18c2451107fd
PSARC 2008/469 Excluding snapshot info from 'zfs list'
Rich Morris <Richard.Morris@Sun.COM>
parents:
7390
diff
changeset
|
637 |
|
2676 | 638 |
/* |
3635 | 639 |
* Given a name, determine whether or not it's a valid path |
640 |
* (starts with '/' or "./"). If so, walk the mnttab trying |
|
641 |
* to match the device number. If not, treat the path as an |
|
642 |
* fs/vol/snap name. |
|
643 |
*/ |
|
644 |
zfs_handle_t * |
|
645 |
zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype) |
|
646 |
{ |
|
647 |
struct stat64 statbuf; |
|
648 |
struct extmnttab entry; |
|
649 |
int ret; |
|
650 |
||
651 |
if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) { |
|
652 |
/* |
|
653 |
* It's not a valid path, assume it's a name of type 'argtype'. |
|
654 |
*/ |
|
655 |
return (zfs_open(hdl, path, argtype)); |
|
656 |
} |
|
657 |
||
658 |
if (stat64(path, &statbuf) != 0) { |
|
659 |
(void) fprintf(stderr, "%s: %s\n", path, strerror(errno)); |
|
660 |
return (NULL); |
|
661 |
} |
|
662 |
||
663 |
rewind(hdl->libzfs_mnttab); |
|
664 |
while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) { |
|
665 |
if (makedevice(entry.mnt_major, entry.mnt_minor) == |
|
666 |
statbuf.st_dev) { |
|
667 |
break; |
|
668 |
} |
|
669 |
} |
|
670 |
if (ret != 0) { |
|
671 |
return (NULL); |
|
672 |
} |
|
673 |
||
674 |
if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) { |
|
675 |
(void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"), |
|
676 |
path); |
|
677 |
return (NULL); |
|
678 |
} |
|
679 |
||
680 |
return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM)); |
|
681 |
} |
|
682 |
||
683 |
/* |
|
2676 | 684 |
* Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from |
685 |
* an ioctl(). |
|
686 |
*/ |
|
687 |
int |
|
688 |
zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len) |
|
689 |
{ |
|
690 |
if (len == 0) |
|
10407
34e10c4af053
6875779 zfs user accounting callbacks can be simplified
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
10342
diff
changeset
|
691 |
len = 4*1024; |
2676 | 692 |
zc->zc_nvlist_dst_size = len; |
693 |
if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t) |
|
694 |
zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == NULL) |
|
695 |
return (-1); |
|
696 |
||
697 |
return (0); |
|
698 |
} |
|
699 |
||
700 |
/* |
|
701 |
* Called when an ioctl() which returns an nvlist fails with ENOMEM. This will |
|
702 |
* expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was |
|
703 |
* filled in by the kernel to indicate the actual required size. |
|
704 |
*/ |
|
705 |
int |
|
706 |
zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc) |
|
707 |
{ |
|
708 |
free((void *)(uintptr_t)zc->zc_nvlist_dst); |
|
709 |
if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t) |
|
710 |
zfs_alloc(hdl, zc->zc_nvlist_dst_size)) |
|
711 |
== NULL) |
|
712 |
return (-1); |
|
713 |
||
714 |
return (0); |
|
715 |
} |
|
716 |
||
717 |
/* |
|
2885 | 718 |
* Called to free the src and dst nvlists stored in the command structure. |
2676 | 719 |
*/ |
720 |
void |
|
721 |
zcmd_free_nvlists(zfs_cmd_t *zc) |
|
722 |
{ |
|
5094 | 723 |
free((void *)(uintptr_t)zc->zc_nvlist_conf); |
2676 | 724 |
free((void *)(uintptr_t)zc->zc_nvlist_src); |
725 |
free((void *)(uintptr_t)zc->zc_nvlist_dst); |
|
726 |
} |
|
727 |
||
5094 | 728 |
static int |
729 |
zcmd_write_nvlist_com(libzfs_handle_t *hdl, uint64_t *outnv, uint64_t *outlen, |
|
730 |
nvlist_t *nvl) |
|
2676 | 731 |
{ |
732 |
char *packed; |
|
733 |
size_t len; |
|
734 |
||
735 |
verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0); |
|
736 |
||
737 |
if ((packed = zfs_alloc(hdl, len)) == NULL) |
|
738 |
return (-1); |
|
739 |
||
740 |
verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); |
|
741 |
||
5094 | 742 |
*outnv = (uint64_t)(uintptr_t)packed; |
743 |
*outlen = len; |
|
744 |
||
745 |
return (0); |
|
746 |
} |
|
2676 | 747 |
|
5094 | 748 |
int |
749 |
zcmd_write_conf_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl) |
|
750 |
{ |
|
751 |
return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_conf, |
|
752 |
&zc->zc_nvlist_conf_size, nvl)); |
|
753 |
} |
|
754 |
||
755 |
int |
|
756 |
zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl) |
|
757 |
{ |
|
758 |
return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_src, |
|
759 |
&zc->zc_nvlist_src_size, nvl)); |
|
2676 | 760 |
} |
761 |
||
762 |
/* |
|
763 |
* Unpacks an nvlist from the ZFS ioctl command structure. |
|
764 |
*/ |
|
765 |
int |
|
766 |
zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp) |
|
767 |
{ |
|
768 |
if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst, |
|
769 |
zc->zc_nvlist_dst_size, nvlp, 0) != 0) |
|
770 |
return (no_memory(hdl)); |
|
771 |
||
772 |
return (0); |
|
773 |
} |
|
3912 | 774 |
|
5094 | 775 |
int |
776 |
zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc) |
|
777 |
{ |
|
778 |
int error; |
|
779 |
||
780 |
zc->zc_history = (uint64_t)(uintptr_t)hdl->libzfs_log_str; |
|
781 |
error = ioctl(hdl->libzfs_fd, request, zc); |
|
782 |
if (hdl->libzfs_log_str) { |
|
783 |
free(hdl->libzfs_log_str); |
|
784 |
hdl->libzfs_log_str = NULL; |
|
785 |
} |
|
786 |
zc->zc_history = 0; |
|
787 |
||
788 |
return (error); |
|
789 |
} |
|
790 |
||
791 |
/* |
|
792 |
* ================================================================ |
|
793 |
* API shared by zfs and zpool property management |
|
794 |
* ================================================================ |
|
795 |
*/ |
|
796 |
||
3912 | 797 |
static void |
5094 | 798 |
zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type) |
3912 | 799 |
{ |
5094 | 800 |
zprop_list_t *pl = cbp->cb_proplist; |
3912 | 801 |
int i; |
802 |
char *title; |
|
803 |
size_t len; |
|
804 |
||
805 |
cbp->cb_first = B_FALSE; |
|
806 |
if (cbp->cb_scripted) |
|
807 |
return; |
|
808 |
||
809 |
/* |
|
810 |
* Start with the length of the column headers. |
|
811 |
*/ |
|
812 |
cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME")); |
|
813 |
cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN, |
|
814 |
"PROPERTY")); |
|
815 |
cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN, |
|
816 |
"VALUE")); |
|
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
817 |
cbp->cb_colwidths[GET_COL_RECVD] = strlen(dgettext(TEXT_DOMAIN, |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
818 |
"RECEIVED")); |
3912 | 819 |
cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN, |
820 |
"SOURCE")); |
|
821 |
||
8269
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
822 |
/* first property is always NAME */ |
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
823 |
assert(cbp->cb_proplist->pl_prop == |
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
824 |
((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : ZFS_PROP_NAME)); |
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
825 |
|
3912 | 826 |
/* |
827 |
* Go through and calculate the widths for each column. For the |
|
828 |
* 'source' column, we kludge it up by taking the worst-case scenario of |
|
829 |
* inheriting from the longest name. This is acceptable because in the |
|
830 |
* majority of cases 'SOURCE' is the last column displayed, and we don't |
|
831 |
* use the width anyway. Note that the 'VALUE' column can be oversized, |
|
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
832 |
* if the name of the property is much longer than any values we find. |
3912 | 833 |
*/ |
834 |
for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { |
|
835 |
/* |
|
836 |
* 'PROPERTY' column |
|
837 |
*/ |
|
5094 | 838 |
if (pl->pl_prop != ZPROP_INVAL) { |
839 |
const char *propname = (type == ZFS_TYPE_POOL) ? |
|
840 |
zpool_prop_to_name(pl->pl_prop) : |
|
841 |
zfs_prop_to_name(pl->pl_prop); |
|
842 |
||
843 |
len = strlen(propname); |
|
3912 | 844 |
if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) |
845 |
cbp->cb_colwidths[GET_COL_PROPERTY] = len; |
|
846 |
} else { |
|
847 |
len = strlen(pl->pl_user_prop); |
|
848 |
if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) |
|
849 |
cbp->cb_colwidths[GET_COL_PROPERTY] = len; |
|
850 |
} |
|
851 |
||
852 |
/* |
|
8269
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
853 |
* 'VALUE' column. The first property is always the 'name' |
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
854 |
* property that was tacked on either by /sbin/zfs's |
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
855 |
* zfs_do_get() or when calling zprop_expand_list(), so we |
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
856 |
* ignore its width. If the user specified the name property |
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
857 |
* to display, then it will be later in the list in any case. |
3912 | 858 |
*/ |
8269
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
859 |
if (pl != cbp->cb_proplist && |
3912 | 860 |
pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE]) |
861 |
cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width; |
|
862 |
||
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
863 |
/* 'RECEIVED' column. */ |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
864 |
if (pl != cbp->cb_proplist && |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
865 |
pl->pl_recvd_width > cbp->cb_colwidths[GET_COL_RECVD]) |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
866 |
cbp->cb_colwidths[GET_COL_RECVD] = pl->pl_recvd_width; |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
867 |
|
3912 | 868 |
/* |
869 |
* 'NAME' and 'SOURCE' columns |
|
870 |
*/ |
|
5094 | 871 |
if (pl->pl_prop == (type == ZFS_TYPE_POOL ? ZPOOL_PROP_NAME : |
872 |
ZFS_PROP_NAME) && |
|
3912 | 873 |
pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) { |
874 |
cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width; |
|
875 |
cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width + |
|
876 |
strlen(dgettext(TEXT_DOMAIN, "inherited from")); |
|
877 |
} |
|
878 |
} |
|
879 |
||
880 |
/* |
|
881 |
* Now go through and print the headers. |
|
882 |
*/ |
|
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
883 |
for (i = 0; i < ZFS_GET_NCOLS; i++) { |
3912 | 884 |
switch (cbp->cb_columns[i]) { |
885 |
case GET_COL_NAME: |
|
886 |
title = dgettext(TEXT_DOMAIN, "NAME"); |
|
887 |
break; |
|
888 |
case GET_COL_PROPERTY: |
|
889 |
title = dgettext(TEXT_DOMAIN, "PROPERTY"); |
|
890 |
break; |
|
891 |
case GET_COL_VALUE: |
|
892 |
title = dgettext(TEXT_DOMAIN, "VALUE"); |
|
893 |
break; |
|
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
894 |
case GET_COL_RECVD: |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
895 |
title = dgettext(TEXT_DOMAIN, "RECEIVED"); |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
896 |
break; |
3912 | 897 |
case GET_COL_SOURCE: |
898 |
title = dgettext(TEXT_DOMAIN, "SOURCE"); |
|
899 |
break; |
|
900 |
default: |
|
901 |
title = NULL; |
|
902 |
} |
|
903 |
||
904 |
if (title != NULL) { |
|
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
905 |
if (i == (ZFS_GET_NCOLS - 1) || |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
906 |
cbp->cb_columns[i + 1] == GET_COL_NONE) |
3912 | 907 |
(void) printf("%s", title); |
908 |
else |
|
909 |
(void) printf("%-*s ", |
|
910 |
cbp->cb_colwidths[cbp->cb_columns[i]], |
|
911 |
title); |
|
912 |
} |
|
913 |
} |
|
914 |
(void) printf("\n"); |
|
915 |
} |
|
916 |
||
917 |
/* |
|
918 |
* Display a single line of output, according to the settings in the callback |
|
919 |
* structure. |
|
920 |
*/ |
|
921 |
void |
|
5094 | 922 |
zprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp, |
923 |
const char *propname, const char *value, zprop_source_t sourcetype, |
|
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
924 |
const char *source, const char *recvd_value) |
3912 | 925 |
{ |
926 |
int i; |
|
927 |
const char *str; |
|
928 |
char buf[128]; |
|
929 |
||
930 |
/* |
|
931 |
* Ignore those source types that the user has chosen to ignore. |
|
932 |
*/ |
|
933 |
if ((sourcetype & cbp->cb_sources) == 0) |
|
934 |
return; |
|
935 |
||
936 |
if (cbp->cb_first) |
|
5094 | 937 |
zprop_print_headers(cbp, cbp->cb_type); |
3912 | 938 |
|
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
939 |
for (i = 0; i < ZFS_GET_NCOLS; i++) { |
3912 | 940 |
switch (cbp->cb_columns[i]) { |
941 |
case GET_COL_NAME: |
|
942 |
str = name; |
|
943 |
break; |
|
944 |
||
945 |
case GET_COL_PROPERTY: |
|
946 |
str = propname; |
|
947 |
break; |
|
948 |
||
949 |
case GET_COL_VALUE: |
|
950 |
str = value; |
|
951 |
break; |
|
952 |
||
953 |
case GET_COL_SOURCE: |
|
954 |
switch (sourcetype) { |
|
5094 | 955 |
case ZPROP_SRC_NONE: |
3912 | 956 |
str = "-"; |
957 |
break; |
|
958 |
||
5094 | 959 |
case ZPROP_SRC_DEFAULT: |
3912 | 960 |
str = "default"; |
961 |
break; |
|
962 |
||
5094 | 963 |
case ZPROP_SRC_LOCAL: |
3912 | 964 |
str = "local"; |
965 |
break; |
|
966 |
||
5094 | 967 |
case ZPROP_SRC_TEMPORARY: |
3912 | 968 |
str = "temporary"; |
969 |
break; |
|
970 |
||
5094 | 971 |
case ZPROP_SRC_INHERITED: |
3912 | 972 |
(void) snprintf(buf, sizeof (buf), |
973 |
"inherited from %s", source); |
|
974 |
str = buf; |
|
975 |
break; |
|
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
976 |
case ZPROP_SRC_RECEIVED: |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
977 |
str = "received"; |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
978 |
break; |
3912 | 979 |
} |
980 |
break; |
|
981 |
||
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
982 |
case GET_COL_RECVD: |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
983 |
str = (recvd_value == NULL ? "-" : recvd_value); |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
984 |
break; |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
985 |
|
3912 | 986 |
default: |
987 |
continue; |
|
988 |
} |
|
989 |
||
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
990 |
if (cbp->cb_columns[i + 1] == GET_COL_NONE) |
3912 | 991 |
(void) printf("%s", str); |
992 |
else if (cbp->cb_scripted) |
|
993 |
(void) printf("%s\t", str); |
|
994 |
else |
|
995 |
(void) printf("%-*s ", |
|
996 |
cbp->cb_colwidths[cbp->cb_columns[i]], |
|
997 |
str); |
|
998 |
} |
|
999 |
||
1000 |
(void) printf("\n"); |
|
1001 |
} |
|
4543 | 1002 |
|
5094 | 1003 |
/* |
1004 |
* Given a numeric suffix, convert the value into a number of bits that the |
|
1005 |
* resulting value must be shifted. |
|
1006 |
*/ |
|
1007 |
static int |
|
1008 |
str2shift(libzfs_handle_t *hdl, const char *buf) |
|
1009 |
{ |
|
1010 |
const char *ends = "BKMGTPEZ"; |
|
1011 |
int i; |
|
1012 |
||
1013 |
if (buf[0] == '\0') |
|
1014 |
return (0); |
|
1015 |
for (i = 0; i < strlen(ends); i++) { |
|
1016 |
if (toupper(buf[0]) == ends[i]) |
|
1017 |
break; |
|
1018 |
} |
|
1019 |
if (i == strlen(ends)) { |
|
1020 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1021 |
"invalid numeric suffix '%s'"), buf); |
|
1022 |
return (-1); |
|
1023 |
} |
|
1024 |
||
1025 |
/* |
|
1026 |
* We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't |
|
1027 |
* allow 'BB' - that's just weird. |
|
1028 |
*/ |
|
1029 |
if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && |
|
1030 |
toupper(buf[0]) != 'B')) |
|
1031 |
return (10*i); |
|
1032 |
||
1033 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1034 |
"invalid numeric suffix '%s'"), buf); |
|
1035 |
return (-1); |
|
1036 |
} |
|
1037 |
||
1038 |
/* |
|
1039 |
* Convert a string of the form '100G' into a real number. Used when setting |
|
1040 |
* properties or creating a volume. 'buf' is used to place an extended error |
|
1041 |
* message for the caller to use. |
|
1042 |
*/ |
|
4543 | 1043 |
int |
5094 | 1044 |
zfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num) |
1045 |
{ |
|
1046 |
char *end; |
|
1047 |
int shift; |
|
1048 |
||
1049 |
*num = 0; |
|
1050 |
||
1051 |
/* Check to see if this looks like a number. */ |
|
1052 |
if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { |
|
1053 |
if (hdl) |
|
1054 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1055 |
"bad numeric value '%s'"), value); |
|
1056 |
return (-1); |
|
1057 |
} |
|
1058 |
||
10817
7dfde45252f0
6889826 ZFS retire agent should be able to repair pools
Eric Schrock <Eric.Schrock@Sun.COM>
parents:
10588
diff
changeset
|
1059 |
/* Rely on strtoull() to process the numeric portion. */ |
5094 | 1060 |
errno = 0; |
8343
655db2375fed
6739553 libzfs_status msgid table is out of sync
Eric Schrock <Eric.Schrock@Sun.COM>
parents:
8269
diff
changeset
|
1061 |
*num = strtoull(value, &end, 10); |
5094 | 1062 |
|
1063 |
/* |
|
1064 |
* Check for ERANGE, which indicates that the value is too large to fit |
|
1065 |
* in a 64-bit value. |
|
1066 |
*/ |
|
1067 |
if (errno == ERANGE) { |
|
1068 |
if (hdl) |
|
1069 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1070 |
"numeric value is too large")); |
|
1071 |
return (-1); |
|
1072 |
} |
|
1073 |
||
1074 |
/* |
|
1075 |
* If we have a decimal value, then do the computation with floating |
|
1076 |
* point arithmetic. Otherwise, use standard arithmetic. |
|
1077 |
*/ |
|
1078 |
if (*end == '.') { |
|
1079 |
double fval = strtod(value, &end); |
|
1080 |
||
1081 |
if ((shift = str2shift(hdl, end)) == -1) |
|
1082 |
return (-1); |
|
1083 |
||
1084 |
fval *= pow(2, shift); |
|
1085 |
||
1086 |
if (fval > UINT64_MAX) { |
|
1087 |
if (hdl) |
|
1088 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1089 |
"numeric value is too large")); |
|
1090 |
return (-1); |
|
1091 |
} |
|
1092 |
||
1093 |
*num = (uint64_t)fval; |
|
1094 |
} else { |
|
1095 |
if ((shift = str2shift(hdl, end)) == -1) |
|
1096 |
return (-1); |
|
1097 |
||
1098 |
/* Check for overflow */ |
|
1099 |
if (shift >= 64 || (*num << shift) >> shift != *num) { |
|
1100 |
if (hdl) |
|
1101 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1102 |
"numeric value is too large")); |
|
1103 |
return (-1); |
|
1104 |
} |
|
1105 |
||
1106 |
*num <<= shift; |
|
1107 |
} |
|
1108 |
||
1109 |
return (0); |
|
1110 |
} |
|
1111 |
||
1112 |
/* |
|
1113 |
* Given a propname=value nvpair to set, parse any numeric properties |
|
1114 |
* (index, boolean, etc) if they are specified as strings and add the |
|
1115 |
* resulting nvpair to the returned nvlist. |
|
1116 |
* |
|
1117 |
* At the DSL layer, all properties are either 64-bit numbers or strings. |
|
1118 |
* We want the user to be able to ignore this fact and specify properties |
|
1119 |
* as native values (numbers, for example) or as strings (to simplify |
|
1120 |
* command line utilities). This also handles converting index types |
|
1121 |
* (compression, checksum, etc) from strings to their on-disk index. |
|
1122 |
*/ |
|
1123 |
int |
|
1124 |
zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop, |
|
1125 |
zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp, |
|
1126 |
const char *errbuf) |
|
4543 | 1127 |
{ |
5094 | 1128 |
data_type_t datatype = nvpair_type(elem); |
1129 |
zprop_type_t proptype; |
|
1130 |
const char *propname; |
|
1131 |
char *value; |
|
1132 |
boolean_t isnone = B_FALSE; |
|
1133 |
||
1134 |
if (type == ZFS_TYPE_POOL) { |
|
1135 |
proptype = zpool_prop_get_type(prop); |
|
1136 |
propname = zpool_prop_to_name(prop); |
|
1137 |
} else { |
|
1138 |
proptype = zfs_prop_get_type(prop); |
|
1139 |
propname = zfs_prop_to_name(prop); |
|
1140 |
} |
|
1141 |
||
1142 |
/* |
|
1143 |
* Convert any properties to the internal DSL value types. |
|
1144 |
*/ |
|
1145 |
*svalp = NULL; |
|
1146 |
*ivalp = 0; |
|
1147 |
||
1148 |
switch (proptype) { |
|
1149 |
case PROP_TYPE_STRING: |
|
1150 |
if (datatype != DATA_TYPE_STRING) { |
|
1151 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1152 |
"'%s' must be a string"), nvpair_name(elem)); |
|
1153 |
goto error; |
|
1154 |
} |
|
1155 |
(void) nvpair_value_string(elem, svalp); |
|
1156 |
if (strlen(*svalp) >= ZFS_MAXPROPLEN) { |
|
1157 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1158 |
"'%s' is too long"), nvpair_name(elem)); |
|
1159 |
goto error; |
|
1160 |
} |
|
1161 |
break; |
|
1162 |
||
1163 |
case PROP_TYPE_NUMBER: |
|
1164 |
if (datatype == DATA_TYPE_STRING) { |
|
1165 |
(void) nvpair_value_string(elem, &value); |
|
1166 |
if (strcmp(value, "none") == 0) { |
|
1167 |
isnone = B_TRUE; |
|
1168 |
} else if (zfs_nicestrtonum(hdl, value, ivalp) |
|
1169 |
!= 0) { |
|
1170 |
goto error; |
|
1171 |
} |
|
1172 |
} else if (datatype == DATA_TYPE_UINT64) { |
|
1173 |
(void) nvpair_value_uint64(elem, ivalp); |
|
1174 |
} else { |
|
1175 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1176 |
"'%s' must be a number"), nvpair_name(elem)); |
|
1177 |
goto error; |
|
1178 |
} |
|
1179 |
||
1180 |
/* |
|
1181 |
* Quota special: force 'none' and don't allow 0. |
|
1182 |
*/ |
|
5378
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5363
diff
changeset
|
1183 |
if ((type & ZFS_TYPE_DATASET) && *ivalp == 0 && !isnone && |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5363
diff
changeset
|
1184 |
(prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA)) { |
5094 | 1185 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
5378
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5363
diff
changeset
|
1186 |
"use 'none' to disable quota/refquota")); |
5094 | 1187 |
goto error; |
1188 |
} |
|
1189 |
break; |
|
1190 |
||
1191 |
case PROP_TYPE_INDEX: |
|
5378
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5363
diff
changeset
|
1192 |
if (datatype != DATA_TYPE_STRING) { |
5094 | 1193 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
1194 |
"'%s' must be a string"), nvpair_name(elem)); |
|
1195 |
goto error; |
|
1196 |
} |
|
1197 |
||
5378
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5363
diff
changeset
|
1198 |
(void) nvpair_value_string(elem, &value); |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5363
diff
changeset
|
1199 |
|
5094 | 1200 |
if (zprop_string_to_index(prop, value, ivalp, type) != 0) { |
1201 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1202 |
"'%s' must be one of '%s'"), propname, |
|
1203 |
zprop_values(prop, type)); |
|
1204 |
goto error; |
|
1205 |
} |
|
1206 |
break; |
|
1207 |
||
1208 |
default: |
|
1209 |
abort(); |
|
1210 |
} |
|
4543 | 1211 |
|
5094 | 1212 |
/* |
1213 |
* Add the result to our return set of properties. |
|
1214 |
*/ |
|
1215 |
if (*svalp != NULL) { |
|
1216 |
if (nvlist_add_string(ret, propname, *svalp) != 0) { |
|
1217 |
(void) no_memory(hdl); |
|
1218 |
return (-1); |
|
1219 |
} |
|
1220 |
} else { |
|
1221 |
if (nvlist_add_uint64(ret, propname, *ivalp) != 0) { |
|
1222 |
(void) no_memory(hdl); |
|
1223 |
return (-1); |
|
1224 |
} |
|
1225 |
} |
|
1226 |
||
1227 |
return (0); |
|
1228 |
error: |
|
1229 |
(void) zfs_error(hdl, EZFS_BADPROP, errbuf); |
|
1230 |
return (-1); |
|
1231 |
} |
|
1232 |
||
7390
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1233 |
static int |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1234 |
addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp, |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1235 |
zfs_type_t type) |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1236 |
{ |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1237 |
int prop; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1238 |
zprop_list_t *entry; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1239 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1240 |
prop = zprop_name_to_prop(propname, type); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1241 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1242 |
if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type)) |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1243 |
prop = ZPROP_INVAL; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1244 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1245 |
/* |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1246 |
* When no property table entry can be found, return failure if |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1247 |
* this is a pool property or if this isn't a user-defined |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1248 |
* dataset property, |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1249 |
*/ |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1250 |
if (prop == ZPROP_INVAL && (type == ZFS_TYPE_POOL || |
9396
f41cf682d0d3
PSARC/2009/204 ZFS user/group quotas & space accounting
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
9234
diff
changeset
|
1251 |
(!zfs_prop_user(propname) && !zfs_prop_userquota(propname)))) { |
7390
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1252 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1253 |
"invalid property '%s'"), propname); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1254 |
return (zfs_error(hdl, EZFS_BADPROP, |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1255 |
dgettext(TEXT_DOMAIN, "bad property list"))); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1256 |
} |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1257 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1258 |
if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL) |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1259 |
return (-1); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1260 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1261 |
entry->pl_prop = prop; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1262 |
if (prop == ZPROP_INVAL) { |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1263 |
if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) == NULL) { |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1264 |
free(entry); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1265 |
return (-1); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1266 |
} |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1267 |
entry->pl_width = strlen(propname); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1268 |
} else { |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1269 |
entry->pl_width = zprop_width(prop, &entry->pl_fixed, |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1270 |
type); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1271 |
} |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1272 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1273 |
*listp = entry; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1274 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1275 |
return (0); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1276 |
} |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1277 |
|
5094 | 1278 |
/* |
1279 |
* Given a comma-separated list of properties, construct a property list |
|
1280 |
* containing both user-defined and native properties. This function will |
|
1281 |
* return a NULL list if 'all' is specified, which can later be expanded |
|
1282 |
* by zprop_expand_list(). |
|
1283 |
*/ |
|
1284 |
int |
|
1285 |
zprop_get_list(libzfs_handle_t *hdl, char *props, zprop_list_t **listp, |
|
1286 |
zfs_type_t type) |
|
1287 |
{ |
|
1288 |
*listp = NULL; |
|
1289 |
||
1290 |
/* |
|
1291 |
* If 'all' is specified, return a NULL list. |
|
1292 |
*/ |
|
1293 |
if (strcmp(props, "all") == 0) |
|
1294 |
return (0); |
|
1295 |
||
1296 |
/* |
|
1297 |
* If no props were specified, return an error. |
|
1298 |
*/ |
|
1299 |
if (props[0] == '\0') { |
|
1300 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1301 |
"no properties specified")); |
|
1302 |
return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN, |
|
1303 |
"bad property list"))); |
|
4543 | 1304 |
} |
5094 | 1305 |
|
1306 |
/* |
|
1307 |
* It would be nice to use getsubopt() here, but the inclusion of column |
|
1308 |
* aliases makes this more effort than it's worth. |
|
1309 |
*/ |
|
7390
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1310 |
while (*props != '\0') { |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1311 |
size_t len; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1312 |
char *p; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1313 |
char c; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1314 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1315 |
if ((p = strchr(props, ',')) == NULL) { |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1316 |
len = strlen(props); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1317 |
p = props + len; |
5094 | 1318 |
} else { |
7390
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1319 |
len = p - props; |
5094 | 1320 |
} |
1321 |
||
1322 |
/* |
|
1323 |
* Check for empty options. |
|
1324 |
*/ |
|
1325 |
if (len == 0) { |
|
1326 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1327 |
"empty property name")); |
|
1328 |
return (zfs_error(hdl, EZFS_BADPROP, |
|
1329 |
dgettext(TEXT_DOMAIN, "bad property list"))); |
|
1330 |
} |
|
1331 |
||
1332 |
/* |
|
1333 |
* Check all regular property names. |
|
1334 |
*/ |
|
7390
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1335 |
c = props[len]; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1336 |
props[len] = '\0'; |
5094 | 1337 |
|
7390
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1338 |
if (strcmp(props, "space") == 0) { |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1339 |
static char *spaceprops[] = { |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1340 |
"name", "avail", "used", "usedbysnapshots", |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1341 |
"usedbydataset", "usedbyrefreservation", |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1342 |
"usedbychildren", NULL |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1343 |
}; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1344 |
int i; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1345 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1346 |
for (i = 0; spaceprops[i]; i++) { |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1347 |
if (addlist(hdl, spaceprops[i], listp, type)) |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1348 |
return (-1); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1349 |
listp = &(*listp)->pl_next; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1350 |
} |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1351 |
} else { |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1352 |
if (addlist(hdl, props, listp, type)) |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1353 |
return (-1); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1354 |
listp = &(*listp)->pl_next; |
5094 | 1355 |
} |
1356 |
||
7390
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1357 |
props = p; |
5094 | 1358 |
if (c == ',') |
7390
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1359 |
props++; |
5094 | 1360 |
} |
1361 |
||
1362 |
return (0); |
|
1363 |
} |
|
1364 |
||
1365 |
void |
|
1366 |
zprop_free_list(zprop_list_t *pl) |
|
1367 |
{ |
|
1368 |
zprop_list_t *next; |
|
4543 | 1369 |
|
5094 | 1370 |
while (pl != NULL) { |
1371 |
next = pl->pl_next; |
|
1372 |
free(pl->pl_user_prop); |
|
1373 |
free(pl); |
|
1374 |
pl = next; |
|
1375 |
} |
|
1376 |
} |
|
1377 |
||
1378 |
typedef struct expand_data { |
|
1379 |
zprop_list_t **last; |
|
1380 |
libzfs_handle_t *hdl; |
|
1381 |
zfs_type_t type; |
|
1382 |
} expand_data_t; |
|
1383 |
||
1384 |
int |
|
1385 |
zprop_expand_list_cb(int prop, void *cb) |
|
1386 |
{ |
|
1387 |
zprop_list_t *entry; |
|
1388 |
expand_data_t *edp = cb; |
|
1389 |
||
1390 |
if ((entry = zfs_alloc(edp->hdl, sizeof (zprop_list_t))) == NULL) |
|
1391 |
return (ZPROP_INVAL); |
|
1392 |
||
1393 |
entry->pl_prop = prop; |
|
1394 |
entry->pl_width = zprop_width(prop, &entry->pl_fixed, edp->type); |
|
1395 |
entry->pl_all = B_TRUE; |
|
1396 |
||
1397 |
*(edp->last) = entry; |
|
1398 |
edp->last = &entry->pl_next; |
|
1399 |
||
1400 |
return (ZPROP_CONT); |
|
4543 | 1401 |
} |
5094 | 1402 |
|
1403 |
int |
|
1404 |
zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, zfs_type_t type) |
|
1405 |
{ |
|
1406 |
zprop_list_t *entry; |
|
1407 |
zprop_list_t **last; |
|
1408 |
expand_data_t exp; |
|
1409 |
||
1410 |
if (*plp == NULL) { |
|
1411 |
/* |
|
1412 |
* If this is the very first time we've been called for an 'all' |
|
1413 |
* specification, expand the list to include all native |
|
1414 |
* properties. |
|
1415 |
*/ |
|
1416 |
last = plp; |
|
1417 |
||
1418 |
exp.last = last; |
|
1419 |
exp.hdl = hdl; |
|
1420 |
exp.type = type; |
|
1421 |
||
1422 |
if (zprop_iter_common(zprop_expand_list_cb, &exp, B_FALSE, |
|
1423 |
B_FALSE, type) == ZPROP_INVAL) |
|
1424 |
return (-1); |
|
1425 |
||
1426 |
/* |
|
1427 |
* Add 'name' to the beginning of the list, which is handled |
|
1428 |
* specially. |
|
1429 |
*/ |
|
1430 |
if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL) |
|
1431 |
return (-1); |
|
1432 |
||
1433 |
entry->pl_prop = (type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : |
|
1434 |
ZFS_PROP_NAME; |
|
1435 |
entry->pl_width = zprop_width(entry->pl_prop, |
|
1436 |
&entry->pl_fixed, type); |
|
1437 |
entry->pl_all = B_TRUE; |
|
1438 |
entry->pl_next = *plp; |
|
1439 |
*plp = entry; |
|
1440 |
} |
|
1441 |
return (0); |
|
1442 |
} |
|
1443 |
||
1444 |
int |
|
1445 |
zprop_iter(zprop_func func, void *cb, boolean_t show_all, boolean_t ordered, |
|
1446 |
zfs_type_t type) |
|
1447 |
{ |
|
1448 |
return (zprop_iter_common(func, cb, show_all, ordered, type)); |
|
1449 |
} |