xref: /onnv-gate/usr/src/lib/libzfs_jni/common/libzfs_jni_dataset.c (revision 5582:c4c30e76a747)
1789Sahrens /*
2789Sahrens  * CDDL HEADER START
3789Sahrens  *
4789Sahrens  * The contents of this file are subject to the terms of the
51643Stalley  * Common Development and Distribution License (the "License").
61643Stalley  * You may not use this file except in compliance with the License.
7789Sahrens  *
8789Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9789Sahrens  * or http://www.opensolaris.org/os/licensing.
10789Sahrens  * See the License for the specific language governing permissions
11789Sahrens  * and limitations under the License.
12789Sahrens  *
13789Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
14789Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15789Sahrens  * If applicable, add the following below this CDDL HEADER, with the
16789Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
17789Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
18789Sahrens  *
19789Sahrens  * CDDL HEADER END
20789Sahrens  */
211643Stalley 
22789Sahrens /*
235094Slling  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24789Sahrens  * Use is subject to license terms.
25789Sahrens  */
26789Sahrens 
27789Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
28789Sahrens 
291206Stalley #include "libzfs_jni_util.h"
30789Sahrens #include "libzfs_jni_dataset.h"
31789Sahrens #include "libzfs_jni_property.h"
321206Stalley #include "libzfs_jni_pool.h"
33789Sahrens #include <strings.h>
34789Sahrens 
35789Sahrens #define	REGEX_ZFS_NAME "^((([^/]*)(/.+)?)[/@])?([^/]+)/*"
36789Sahrens #define	REGEX_ZFS_NAME_NGROUPS	6
37789Sahrens #define	REGEX_ZFS_NAME_POOL_GROUP 3
38789Sahrens #define	REGEX_ZFS_NAME_PARENT_GROUP 2
39789Sahrens #define	REGEX_ZFS_NAME_BASE_GROUP 5
40789Sahrens 
41789Sahrens /*
42789Sahrens  * Types
43789Sahrens  */
44789Sahrens 
45789Sahrens typedef struct DatasetBean {
46789Sahrens 	zjni_Object_t super;
47789Sahrens 
48789Sahrens 	jmethodID method_setPoolName;
49789Sahrens 	jmethodID method_setParentName;
50789Sahrens 	jmethodID method_setBaseName;
51789Sahrens 	jmethodID method_setProperties;
52789Sahrens 	jmethodID method_addProperty;
53789Sahrens } DatasetBean_t;
54789Sahrens 
55789Sahrens typedef struct FileSystemBean {
56789Sahrens 	DatasetBean_t super;
57789Sahrens } FileSystemBean_t;
58789Sahrens 
59789Sahrens typedef struct PoolBean {
60789Sahrens 	FileSystemBean_t super;
611206Stalley 	PoolStatsBean_t interface_PoolStats;
62789Sahrens } PoolBean_t;
63789Sahrens 
64789Sahrens typedef struct VolumeBean {
65789Sahrens 	DatasetBean_t super;
66789Sahrens } VolumeBean_t;
67789Sahrens 
68789Sahrens typedef struct SnapshotBean {
69789Sahrens 	DatasetBean_t super;
70789Sahrens } SnapshotBean_t;
71789Sahrens 
72789Sahrens typedef struct FileSystemSnapshotBean {
73789Sahrens 	DatasetBean_t super;
74789Sahrens } FileSystemSnapshotBean_t;
75789Sahrens 
76789Sahrens typedef struct VolumeSnapshotBean {
77789Sahrens 	DatasetBean_t super;
78789Sahrens } VolumeSnapshotBean_t;
79789Sahrens 
80789Sahrens /*
81789Sahrens  * Function prototypes
82789Sahrens  */
83789Sahrens 
84789Sahrens static void new_DatasetBean(JNIEnv *, DatasetBean_t *);
85789Sahrens static void new_PoolBean(JNIEnv *, PoolBean_t *);
86789Sahrens static void new_FileSystemBean(JNIEnv *, FileSystemBean_t *);
87789Sahrens static void new_VolumeBean(JNIEnv *, VolumeBean_t *);
88789Sahrens static void new_SnapshotBean(JNIEnv *, SnapshotBean_t *);
89789Sahrens static void new_FileSystemSnapshotBean(JNIEnv *, FileSystemSnapshotBean_t *);
90789Sahrens static void new_VolumeSnapshotBean(JNIEnv *, VolumeSnapshotBean_t *);
911643Stalley static int set_name_in_DatasetBean(JNIEnv *, char *, DatasetBean_t *);
92789Sahrens static int populate_DatasetBean(JNIEnv *, zfs_handle_t *, DatasetBean_t *);
931643Stalley static int populate_PoolBean(
941643Stalley     JNIEnv *, zpool_handle_t *, zfs_handle_t *, PoolBean_t *);
95789Sahrens static int populate_FileSystemBean(
96789Sahrens     JNIEnv *, zfs_handle_t *, FileSystemBean_t *);
97789Sahrens static int populate_VolumeBean(
98789Sahrens     JNIEnv *, zfs_handle_t *, VolumeBean_t *);
99789Sahrens static int populate_SnapshotBean(JNIEnv *, zfs_handle_t *, SnapshotBean_t *);
100789Sahrens static int populate_FileSystemSnapshotBean(
101789Sahrens     JNIEnv *, zfs_handle_t *, FileSystemSnapshotBean_t *);
102789Sahrens static int populate_VolumeSnapshotBean(
103789Sahrens     JNIEnv *, zfs_handle_t *, VolumeSnapshotBean_t *);
1041643Stalley static jobject create_PoolBean(JNIEnv *, zpool_handle_t *, zfs_handle_t *);
105789Sahrens static jobject create_FileSystemBean(JNIEnv *, zfs_handle_t *);
106789Sahrens static jobject create_VolumeBean(JNIEnv *, zfs_handle_t *);
107789Sahrens static jobject create_FileSystemSnapshotBean(JNIEnv *, zfs_handle_t *);
108789Sahrens static jobject create_VolumeSnapshotBean(JNIEnv *, zfs_handle_t *);
109789Sahrens static jobject create_DatasetBean(JNIEnv *, zfs_handle_t *);
110789Sahrens static int is_fs_snapshot(zfs_handle_t *);
1111643Stalley static int is_pool_name(const char *);
112789Sahrens 
113789Sahrens /*
114789Sahrens  * Static functions
115789Sahrens  */
116789Sahrens 
117789Sahrens /* Create a DatasetBean */
118789Sahrens static void
new_DatasetBean(JNIEnv * env,DatasetBean_t * bean)119789Sahrens new_DatasetBean(JNIEnv *env, DatasetBean_t *bean)
120789Sahrens {
121789Sahrens 	zjni_Object_t *object = (zjni_Object_t *)bean;
122789Sahrens 
123789Sahrens 	if (object->object == NULL) {
124789Sahrens 		object->class =
125789Sahrens 		    (*env)->FindClass(env, ZFSJNI_PACKAGE_DATA "DatasetBean");
126789Sahrens 
127789Sahrens 		object->constructor =
128789Sahrens 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
129789Sahrens 
130789Sahrens 		object->object =
131789Sahrens 		    (*env)->NewObject(env, object->class, object->constructor);
132789Sahrens 	}
133789Sahrens 
134789Sahrens 	bean->method_setPoolName = (*env)->GetMethodID(
135789Sahrens 	    env, object->class, "setPoolName", "(Ljava/lang/String;)V");
136789Sahrens 
137789Sahrens 	bean->method_setParentName = (*env)->GetMethodID(
138789Sahrens 	    env, object->class, "setParentName", "(Ljava/lang/String;)V");
139789Sahrens 
140789Sahrens 	bean->method_setBaseName = (*env)->GetMethodID(
141789Sahrens 	    env, object->class, "setBaseName", "(Ljava/lang/String;)V");
142789Sahrens 
143789Sahrens 	bean->method_setProperties = (*env)->GetMethodID(
144789Sahrens 	    env, object->class, "setProperties",
145789Sahrens 	    "([L" ZFSJNI_PACKAGE_DATA "Property;)V");
146789Sahrens 
147789Sahrens 	bean->method_addProperty = (*env)->GetMethodID(
148789Sahrens 	    env, object->class, "addProperty",
149789Sahrens 	    "(L" ZFSJNI_PACKAGE_DATA "Property;)V");
150789Sahrens }
151789Sahrens 
152789Sahrens /* Create a PoolBean */
153789Sahrens static void
new_PoolBean(JNIEnv * env,PoolBean_t * bean)154789Sahrens new_PoolBean(JNIEnv *env, PoolBean_t *bean)
155789Sahrens {
156789Sahrens 	zjni_Object_t *object = (zjni_Object_t *)bean;
157789Sahrens 
158789Sahrens 	if (object->object == NULL) {
159789Sahrens 
160789Sahrens 		object->class =
161789Sahrens 		    (*env)->FindClass(env, ZFSJNI_PACKAGE_DATA "PoolBean");
162789Sahrens 
163789Sahrens 		object->constructor =
164789Sahrens 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
165789Sahrens 
166789Sahrens 		object->object =
167789Sahrens 		    (*env)->NewObject(env, object->class, object->constructor);
168789Sahrens 	}
169789Sahrens 
170789Sahrens 	new_FileSystemBean(env, (FileSystemBean_t *)bean);
1711206Stalley 	new_PoolStats(env, &(bean->interface_PoolStats), object);
172789Sahrens }
173789Sahrens 
174789Sahrens /* Create a FileSystemBean */
175789Sahrens static void
new_FileSystemBean(JNIEnv * env,FileSystemBean_t * bean)176789Sahrens new_FileSystemBean(JNIEnv *env, FileSystemBean_t *bean)
177789Sahrens {
178789Sahrens 	zjni_Object_t *object = (zjni_Object_t *)bean;
179789Sahrens 
180789Sahrens 	if (object->object == NULL) {
181789Sahrens 		object->class =
182789Sahrens 		    (*env)->FindClass(env,
1835094Slling 		    ZFSJNI_PACKAGE_DATA "FileSystemBean");
184789Sahrens 
185789Sahrens 		object->constructor =
186789Sahrens 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
187789Sahrens 
188789Sahrens 		object->object =
189789Sahrens 		    (*env)->NewObject(env, object->class, object->constructor);
190789Sahrens 	}
191789Sahrens 
192789Sahrens 	new_DatasetBean(env, (DatasetBean_t *)bean);
193789Sahrens }
194789Sahrens 
195789Sahrens /* Create a VolumeBean */
196789Sahrens static void
new_VolumeBean(JNIEnv * env,VolumeBean_t * bean)197789Sahrens new_VolumeBean(JNIEnv *env, VolumeBean_t *bean)
198789Sahrens {
199789Sahrens 	zjni_Object_t *object = (zjni_Object_t *)bean;
200789Sahrens 
201789Sahrens 	if (object->object == NULL) {
202789Sahrens 		object->class =
203789Sahrens 		    (*env)->FindClass(env,
2045094Slling 		    ZFSJNI_PACKAGE_DATA "VolumeBean");
205789Sahrens 
206789Sahrens 		object->constructor =
207789Sahrens 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
208789Sahrens 
209789Sahrens 		object->object =
210789Sahrens 		    (*env)->NewObject(env, object->class, object->constructor);
211789Sahrens 	}
212789Sahrens 
213789Sahrens 	new_DatasetBean(env, (DatasetBean_t *)bean);
214789Sahrens }
215789Sahrens 
216789Sahrens /* Create a SnapshotBean */
217789Sahrens static void
new_SnapshotBean(JNIEnv * env,SnapshotBean_t * bean)218789Sahrens new_SnapshotBean(JNIEnv *env, SnapshotBean_t *bean)
219789Sahrens {
220789Sahrens 	zjni_Object_t *object = (zjni_Object_t *)bean;
221789Sahrens 
222789Sahrens 	if (object->object == NULL) {
223789Sahrens 		object->class =
224789Sahrens 		    (*env)->FindClass(env,
2255094Slling 		    ZFSJNI_PACKAGE_DATA "SnapshotBean");
226789Sahrens 
227789Sahrens 		object->constructor =
228789Sahrens 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
229789Sahrens 
230789Sahrens 		object->object =
231789Sahrens 		    (*env)->NewObject(env, object->class, object->constructor);
232789Sahrens 	}
233789Sahrens 
234789Sahrens 	new_DatasetBean(env, (DatasetBean_t *)bean);
235789Sahrens }
236789Sahrens 
237789Sahrens /* Create a FileSystemSnapshotBean */
238789Sahrens static void
new_FileSystemSnapshotBean(JNIEnv * env,FileSystemSnapshotBean_t * bean)239789Sahrens new_FileSystemSnapshotBean(JNIEnv *env, FileSystemSnapshotBean_t *bean)
240789Sahrens {
241789Sahrens 	zjni_Object_t *object = (zjni_Object_t *)bean;
242789Sahrens 
243789Sahrens 	if (object->object == NULL) {
244789Sahrens 		object->class =
245789Sahrens 		    (*env)->FindClass(env,
2465094Slling 		    ZFSJNI_PACKAGE_DATA "FileSystemSnapshotBean");
247789Sahrens 
248789Sahrens 		object->constructor =
249789Sahrens 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
250789Sahrens 
251789Sahrens 		object->object =
252789Sahrens 		    (*env)->NewObject(env, object->class, object->constructor);
253789Sahrens 	}
254789Sahrens 
255789Sahrens 	new_SnapshotBean(env, (SnapshotBean_t *)bean);
256789Sahrens }
257789Sahrens 
258789Sahrens /* Create a VolumeSnapshotBean */
259789Sahrens static void
new_VolumeSnapshotBean(JNIEnv * env,VolumeSnapshotBean_t * bean)260789Sahrens new_VolumeSnapshotBean(JNIEnv *env, VolumeSnapshotBean_t *bean)
261789Sahrens {
262789Sahrens 	zjni_Object_t *object = (zjni_Object_t *)bean;
263789Sahrens 
264789Sahrens 	if (object->object == NULL) {
265789Sahrens 		object->class =
266789Sahrens 		    (*env)->FindClass(env,
2675094Slling 		    ZFSJNI_PACKAGE_DATA "VolumeSnapshotBean");
268789Sahrens 
269789Sahrens 		object->constructor =
270789Sahrens 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
271789Sahrens 
272789Sahrens 		object->object =
273789Sahrens 		    (*env)->NewObject(env, object->class, object->constructor);
274789Sahrens 	}
275789Sahrens 
276789Sahrens 	new_SnapshotBean(env, (SnapshotBean_t *)bean);
277789Sahrens }
278789Sahrens 
279789Sahrens static int
set_name_in_DatasetBean(JNIEnv * env,char * name,DatasetBean_t * bean)2801643Stalley set_name_in_DatasetBean(JNIEnv *env, char *name, DatasetBean_t *bean)
281789Sahrens {
282789Sahrens 	jstring poolUTF;
283789Sahrens 	jstring parentUTF;
284789Sahrens 	jstring baseUTF;
285789Sahrens 	zjni_Object_t *object = (zjni_Object_t *)bean;
286789Sahrens 
287789Sahrens 	/*
288789Sahrens 	 * zhp->zfs_name has the format
289789Sahrens 	 * <pool>[[/<container...>]/<dataset>[@<snapshot>]]
290789Sahrens 	 */
291789Sahrens 
292789Sahrens 	regex_t re;
293789Sahrens 	regmatch_t matches[REGEX_ZFS_NAME_NGROUPS];
294789Sahrens 
295789Sahrens 	if (regcomp(&re, REGEX_ZFS_NAME, REG_EXTENDED) != 0 ||
296789Sahrens 	    regexec(&re, name, REGEX_ZFS_NAME_NGROUPS, matches, 0) != 0) {
297789Sahrens 		regfree(&re);
298789Sahrens 		zjni_throw_exception(env, "invalid name: %s", name);
299789Sahrens 		return (-1);
300789Sahrens 	}
301789Sahrens 
302789Sahrens 	regfree(&re);
303789Sahrens 
304789Sahrens 	/* Set names */
305789Sahrens 	poolUTF = zjni_get_matched_string(
306789Sahrens 	    env, name, matches + REGEX_ZFS_NAME_POOL_GROUP);
307789Sahrens 	parentUTF = zjni_get_matched_string(
308789Sahrens 	    env, name, matches + REGEX_ZFS_NAME_PARENT_GROUP);
309789Sahrens 	baseUTF = zjni_get_matched_string(
310789Sahrens 	    env, name, matches + REGEX_ZFS_NAME_BASE_GROUP);
311789Sahrens 
312789Sahrens 	if (poolUTF == NULL) {
313789Sahrens 		poolUTF = baseUTF;
314789Sahrens 	}
315789Sahrens 
316789Sahrens 	(*env)->CallVoidMethod(
317789Sahrens 	    env, object->object, bean->method_setPoolName, poolUTF);
318789Sahrens 	(*env)->CallVoidMethod(
319789Sahrens 	    env, object->object, bean->method_setBaseName, baseUTF);
320789Sahrens 
321789Sahrens 	if (parentUTF != NULL) {
322789Sahrens 		(*env)->CallVoidMethod(
323789Sahrens 		    env, object->object, bean->method_setParentName, parentUTF);
324789Sahrens 	}
325789Sahrens 
3261643Stalley 	return (0);
3271643Stalley }
3281643Stalley 
3291643Stalley static int
populate_DatasetBean(JNIEnv * env,zfs_handle_t * zhp,DatasetBean_t * bean)3301643Stalley populate_DatasetBean(JNIEnv *env, zfs_handle_t *zhp, DatasetBean_t *bean)
3311643Stalley {
3321643Stalley 	jobjectArray properties;
3331643Stalley 	zjni_Object_t *object = (zjni_Object_t *)bean;
3341643Stalley 
3351643Stalley 	int result = set_name_in_DatasetBean(
3361643Stalley 	    env, (char *)zfs_get_name(zhp), bean);
3371643Stalley 	if (result != 0) {
3381643Stalley 		/* Must not call any more Java methods to preserve exception */
3391643Stalley 		return (-1);
3401643Stalley 	}
3411643Stalley 
342789Sahrens 	properties = zjni_get_Dataset_properties(env, zhp);
343789Sahrens 	if (properties == NULL) {
344789Sahrens 		/* Must not call any more Java methods to preserve exception */
345789Sahrens 		return (-1);
346789Sahrens 	}
347789Sahrens 
348789Sahrens 	(*env)->CallVoidMethod(
349789Sahrens 	    env, object->object, bean->method_setProperties, properties);
350789Sahrens 
351789Sahrens 	return (0);
352789Sahrens }
353789Sahrens 
354789Sahrens static int
populate_PoolBean(JNIEnv * env,zpool_handle_t * zphp,zfs_handle_t * zhp,PoolBean_t * bean)3551643Stalley populate_PoolBean(JNIEnv *env, zpool_handle_t *zphp, zfs_handle_t *zhp,
3561643Stalley     PoolBean_t *bean)
357789Sahrens {
3581206Stalley 	int result = 0;
3591643Stalley 	zjni_Object_t *object = (zjni_Object_t *)bean;
3601643Stalley 	PoolStatsBean_t *pool_stats = &(bean->interface_PoolStats);
3611643Stalley 	DeviceStatsBean_t *dev_stats = (DeviceStatsBean_t *)pool_stats;
3621643Stalley 	nvlist_t *devices = zjni_get_root_vdev(zphp);
3631100Stalley 
3641643Stalley 	if (devices == NULL ||
3651643Stalley 	    populate_DeviceStatsBean(env, devices, dev_stats, object)) {
3661206Stalley 		result = -1;
3671206Stalley 	} else {
3681643Stalley 		char *msgid;
3691206Stalley 
3701643Stalley 		/* Override value set in populate_DeviceStatsBean */
3711643Stalley 		(*env)->CallVoidMethod(env, object->object,
3721643Stalley 		    dev_stats->method_setSize,
3735094Slling 		    zpool_get_prop_int(zphp, ZPOOL_PROP_SIZE, NULL));
3741206Stalley 
3751643Stalley 		(*env)->CallVoidMethod(env, object->object,
3761643Stalley 		    pool_stats->method_setPoolState,
3771643Stalley 		    zjni_pool_state_to_obj(
3785094Slling 		    env, zpool_get_state(zphp)));
3791206Stalley 
3801643Stalley 		(*env)->CallVoidMethod(env, object->object,
3811643Stalley 		    pool_stats->method_setPoolStatus,
3821643Stalley 		    zjni_pool_status_to_obj(env,
3835094Slling 		    zpool_get_status(zphp, &msgid)));
3841206Stalley 
385*5582Scristian 		(*env)->CallVoidMethod(env, object->object,
386*5582Scristian 		    pool_stats->method_setPoolVersion,
387*5582Scristian 		    zpool_get_prop_int(zphp, ZPOOL_PROP_VERSION, NULL));
388*5582Scristian 
3891643Stalley 		/*
3901643Stalley 		 * If a root file system does not exist for this pool, the pool
3911643Stalley 		 * is likely faulted, so just set its name in the Java object.
3921643Stalley 		 * Otherwise, populate all fields of the Java object.
3931643Stalley 		 */
3941643Stalley 		if (zhp == NULL) {
3955094Slling 			result = set_name_in_DatasetBean(env,
3965094Slling 			    (char *)zpool_get_name(zphp),
3975094Slling 			    (DatasetBean_t *)bean);
3981643Stalley 		} else {
3995094Slling 			result = populate_FileSystemBean(
4005094Slling 			    env, zhp, (FileSystemBean_t *)bean);
4011206Stalley 		}
4021100Stalley 	}
4031100Stalley 
4041206Stalley 	return (result != 0);
405789Sahrens }
406789Sahrens 
407789Sahrens static int
populate_FileSystemBean(JNIEnv * env,zfs_handle_t * zhp,FileSystemBean_t * bean)408789Sahrens populate_FileSystemBean(JNIEnv *env, zfs_handle_t *zhp, FileSystemBean_t *bean)
409789Sahrens {
410789Sahrens 	return (populate_DatasetBean(env, zhp, (DatasetBean_t *)bean));
411789Sahrens }
412789Sahrens 
413789Sahrens static int
populate_VolumeBean(JNIEnv * env,zfs_handle_t * zhp,VolumeBean_t * bean)414789Sahrens populate_VolumeBean(JNIEnv *env, zfs_handle_t *zhp, VolumeBean_t *bean)
415789Sahrens {
416789Sahrens 	return (populate_DatasetBean(env, zhp, (DatasetBean_t *)bean));
417789Sahrens }
418789Sahrens 
419789Sahrens static int
populate_SnapshotBean(JNIEnv * env,zfs_handle_t * zhp,SnapshotBean_t * bean)420789Sahrens populate_SnapshotBean(JNIEnv *env, zfs_handle_t *zhp, SnapshotBean_t *bean)
421789Sahrens {
422789Sahrens 	return (populate_DatasetBean(env, zhp, (DatasetBean_t *)bean));
423789Sahrens }
424789Sahrens 
425789Sahrens static int
populate_FileSystemSnapshotBean(JNIEnv * env,zfs_handle_t * zhp,FileSystemSnapshotBean_t * bean)426789Sahrens populate_FileSystemSnapshotBean(JNIEnv *env, zfs_handle_t *zhp,
427789Sahrens     FileSystemSnapshotBean_t *bean)
428789Sahrens {
429789Sahrens 	return (populate_SnapshotBean(env, zhp, (SnapshotBean_t *)bean));
430789Sahrens }
431789Sahrens 
432789Sahrens static int
populate_VolumeSnapshotBean(JNIEnv * env,zfs_handle_t * zhp,VolumeSnapshotBean_t * bean)433789Sahrens populate_VolumeSnapshotBean(JNIEnv *env, zfs_handle_t *zhp,
434789Sahrens     VolumeSnapshotBean_t *bean)
435789Sahrens {
436789Sahrens 	return (populate_SnapshotBean(env, zhp, (SnapshotBean_t *)bean));
437789Sahrens }
438789Sahrens 
439789Sahrens static jobject
create_PoolBean(JNIEnv * env,zpool_handle_t * zphp,zfs_handle_t * zhp)4401643Stalley create_PoolBean(JNIEnv *env, zpool_handle_t *zphp, zfs_handle_t *zhp)
441789Sahrens {
442789Sahrens 	int result;
443789Sahrens 	PoolBean_t bean_obj = {0};
444789Sahrens 	PoolBean_t *bean = &bean_obj;
445789Sahrens 
446789Sahrens 	/* Construct PoolBean */
447789Sahrens 	new_PoolBean(env, bean);
448789Sahrens 
4491643Stalley 	result = populate_PoolBean(env, zphp, zhp, bean);
450789Sahrens 	if (result) {
451789Sahrens 		/* Must not call any more Java methods to preserve exception */
452789Sahrens 		return (NULL);
453789Sahrens 	}
454789Sahrens 
455789Sahrens 	return (((zjni_Object_t *)bean)->object);
456789Sahrens }
457789Sahrens 
458789Sahrens static jobject
create_FileSystemBean(JNIEnv * env,zfs_handle_t * zhp)459789Sahrens create_FileSystemBean(JNIEnv *env, zfs_handle_t *zhp)
460789Sahrens {
461789Sahrens 	int result;
462789Sahrens 	FileSystemBean_t bean_obj = {0};
463789Sahrens 	FileSystemBean_t *bean = &bean_obj;
464789Sahrens 
465789Sahrens 	/* Construct FileSystemBean */
466789Sahrens 	new_FileSystemBean(env, bean);
467789Sahrens 
468789Sahrens 	result = populate_FileSystemBean(env, zhp, bean);
469789Sahrens 	if (result) {
470789Sahrens 		/* Must not call any more Java methods to preserve exception */
471789Sahrens 		return (NULL);
472789Sahrens 	}
473789Sahrens 
474789Sahrens 	return (((zjni_Object_t *)bean)->object);
475789Sahrens }
476789Sahrens 
477789Sahrens static jobject
create_VolumeBean(JNIEnv * env,zfs_handle_t * zhp)478789Sahrens create_VolumeBean(JNIEnv *env, zfs_handle_t *zhp)
479789Sahrens {
480789Sahrens 	int result;
481789Sahrens 	VolumeBean_t bean_obj = {0};
482789Sahrens 	VolumeBean_t *bean = &bean_obj;
483789Sahrens 
484789Sahrens 	/* Construct VolumeBean */
485789Sahrens 	new_VolumeBean(env, bean);
486789Sahrens 
487789Sahrens 	result = populate_VolumeBean(env, zhp, bean);
488789Sahrens 	if (result) {
489789Sahrens 		/* Must not call any more Java methods to preserve exception */
490789Sahrens 		return (NULL);
491789Sahrens 	}
492789Sahrens 
493789Sahrens 	return (((zjni_Object_t *)bean)->object);
494789Sahrens }
495789Sahrens 
496789Sahrens static jobject
create_FileSystemSnapshotBean(JNIEnv * env,zfs_handle_t * zhp)497789Sahrens create_FileSystemSnapshotBean(JNIEnv *env, zfs_handle_t *zhp)
498789Sahrens {
499789Sahrens 	int result;
500789Sahrens 	FileSystemSnapshotBean_t bean_obj = {0};
501789Sahrens 	FileSystemSnapshotBean_t *bean = &bean_obj;
502789Sahrens 
503789Sahrens 	/* Construct FileSystemSnapshotBean */
504789Sahrens 	new_FileSystemSnapshotBean(env, bean);
505789Sahrens 
506789Sahrens 	result = populate_FileSystemSnapshotBean(env, zhp, bean);
507789Sahrens 	if (result) {
508789Sahrens 		/* Must not call any more Java methods to preserve exception */
509789Sahrens 		return (NULL);
510789Sahrens 	}
511789Sahrens 
512789Sahrens 	return (((zjni_Object_t *)bean)->object);
513789Sahrens }
514789Sahrens 
515789Sahrens static jobject
create_VolumeSnapshotBean(JNIEnv * env,zfs_handle_t * zhp)516789Sahrens create_VolumeSnapshotBean(JNIEnv *env, zfs_handle_t *zhp)
517789Sahrens {
518789Sahrens 	int result;
519789Sahrens 	VolumeSnapshotBean_t bean_obj = {0};
520789Sahrens 	VolumeSnapshotBean_t *bean = &bean_obj;
521789Sahrens 
522789Sahrens 	/* Construct VolumeSnapshotBean */
523789Sahrens 	new_VolumeSnapshotBean(env, bean);
524789Sahrens 
525789Sahrens 	result = populate_VolumeSnapshotBean(env, zhp, bean);
526789Sahrens 	if (result) {
527789Sahrens 		/* Must not call any more Java methods to preserve exception */
528789Sahrens 		return (NULL);
529789Sahrens 	}
530789Sahrens 
531789Sahrens 	return (((zjni_Object_t *)bean)->object);
532789Sahrens }
533789Sahrens 
534789Sahrens static jobject
create_DatasetBean(JNIEnv * env,zfs_handle_t * zhp)535789Sahrens create_DatasetBean(JNIEnv *env, zfs_handle_t *zhp)
536789Sahrens {
537789Sahrens 	jobject object = NULL;
538789Sahrens 
539789Sahrens 	switch (zfs_get_type(zhp)) {
540789Sahrens 	case ZFS_TYPE_FILESYSTEM:
5411643Stalley 		object = create_FileSystemBean(env, zhp);
542789Sahrens 		break;
543789Sahrens 
544789Sahrens 	case ZFS_TYPE_VOLUME:
545789Sahrens 		object = create_VolumeBean(env, zhp);
546789Sahrens 		break;
547789Sahrens 
548789Sahrens 	case ZFS_TYPE_SNAPSHOT:
549789Sahrens 		object = is_fs_snapshot(zhp) ?
550789Sahrens 		    create_FileSystemSnapshotBean(env, zhp) :
551789Sahrens 		    create_VolumeSnapshotBean(env, zhp);
552789Sahrens 		break;
553789Sahrens 	}
554789Sahrens 
555789Sahrens 	return (object);
556789Sahrens }
557789Sahrens 
558789Sahrens /*
559789Sahrens  * Determines whether the given snapshot is a snapshot of a file
560789Sahrens  * system or of a volume.
561789Sahrens  *
562789Sahrens  * Returns:
563789Sahrens  *
564789Sahrens  *	0 if it is a volume snapshot
565789Sahrens  *	1 if it is a file system snapshot
566789Sahrens  *	-1 on error
567789Sahrens  */
568789Sahrens static int
is_fs_snapshot(zfs_handle_t * zhp)569789Sahrens is_fs_snapshot(zfs_handle_t *zhp)
570789Sahrens {
571789Sahrens 	char parent[ZFS_MAXNAMELEN];
572789Sahrens 	zfs_handle_t *parent_zhp;
573789Sahrens 	int isfs;
574789Sahrens 
575789Sahrens 	if (zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) {
576789Sahrens 		return (-1);
577789Sahrens 	}
578789Sahrens 
579789Sahrens 	zjni_get_dataset_from_snapshot(
580789Sahrens 	    zfs_get_name(zhp), parent, sizeof (parent));
581789Sahrens 
5825094Slling 	parent_zhp = zfs_open(g_zfs, parent, ZFS_TYPE_DATASET);
583789Sahrens 	if (parent_zhp == NULL) {
584789Sahrens 		return (-1);
585789Sahrens 	}
586789Sahrens 
587789Sahrens 	isfs = zfs_get_type(parent_zhp) == ZFS_TYPE_FILESYSTEM;
588789Sahrens 	zfs_close(parent_zhp);
589789Sahrens 
590789Sahrens 	return (isfs);
591789Sahrens }
592789Sahrens 
593789Sahrens static int
is_pool_name(const char * name)5941643Stalley is_pool_name(const char *name)
595789Sahrens {
5963061Stomee 	return (strchr(name, '/') == NULL && strchr(name, '@') == NULL);
597789Sahrens }
598789Sahrens 
599789Sahrens /*
600789Sahrens  * Package-private functions
601789Sahrens  */
602789Sahrens 
603789Sahrens /*
6041643Stalley  * Callback function for zpool_iter().  Creates a Pool and adds it to
6051643Stalley  * the given zjni_ArrayList.
6061643Stalley  */
6071643Stalley int
zjni_create_add_Pool(zpool_handle_t * zphp,void * data)6081643Stalley zjni_create_add_Pool(zpool_handle_t *zphp, void *data)
6091643Stalley {
6101643Stalley 	JNIEnv *env = ((zjni_ArrayCallbackData_t *)data)->env;
6111643Stalley 	zjni_Collection_t *list = ((zjni_ArrayCallbackData_t *)data)->list;
6121643Stalley 
6131643Stalley 	/* Get root fs for this pool -- may be NULL if pool is faulted */
6142082Seschrock 	zfs_handle_t *zhp = zfs_open(g_zfs, zpool_get_name(zphp),
6152082Seschrock 	    ZFS_TYPE_FILESYSTEM);
6161643Stalley 
6171643Stalley 	jobject bean = create_PoolBean(env, zphp, zhp);
6181643Stalley 
6195094Slling 	if (zhp != NULL)
6205094Slling 		zfs_close(zhp);
6211643Stalley 
6221643Stalley 	zpool_close(zphp);
6231643Stalley 
6241643Stalley 	if (bean == NULL) {
6251643Stalley 		/* Must not call any more Java methods to preserve exception */
6261643Stalley 		return (-1);
6271643Stalley 	}
6281643Stalley 
6291643Stalley 	/* Add pool to zjni_ArrayList */
6301643Stalley 	(*env)->CallBooleanMethod(env, ((zjni_Object_t *)list)->object,
6311643Stalley 	    ((zjni_Collection_t *)list)->method_add, bean);
6321643Stalley 
6331643Stalley 	return (0);
6341643Stalley }
6351643Stalley 
6361643Stalley /*
637789Sahrens  * Callback function for zfs_iter_children().  Creates the appropriate
638789Sahrens  * Dataset and adds it to the given zjni_ArrayList.  Per the contract
639789Sahrens  * with zfs_iter_children(), calls zfs_close() on the given
640789Sahrens  * zfs_handle_t.
641789Sahrens  */
642789Sahrens int
zjni_create_add_Dataset(zfs_handle_t * zhp,void * data)643789Sahrens zjni_create_add_Dataset(zfs_handle_t *zhp, void *data)
644789Sahrens {
645789Sahrens 	JNIEnv *env = ((zjni_ArrayCallbackData_t *)data)->env;
646789Sahrens 	zjni_Collection_t *list = ((zjni_ArrayCallbackData_t *)data)->list;
647789Sahrens 	zfs_type_t typemask =
648789Sahrens 	    ((zjni_DatasetArrayCallbackData_t *)data)->typemask;
649789Sahrens 
650789Sahrens 	/* Only add allowed types */
651789Sahrens 	if (zfs_get_type(zhp) & typemask) {
652789Sahrens 
653789Sahrens 		jobject bean = create_DatasetBean(env, zhp);
654789Sahrens 		zfs_close(zhp);
655789Sahrens 
656789Sahrens 		if (bean == NULL) {
657789Sahrens 			/*
658789Sahrens 			 * Must not call any more Java methods to preserve
659789Sahrens 			 * exception
660789Sahrens 			 */
661789Sahrens 			return (-1);
662789Sahrens 		}
663789Sahrens 
6641643Stalley 		/* Add Dataset to zjni_ArrayList */
665789Sahrens 		(*env)->CallBooleanMethod(env, ((zjni_Object_t *)list)->object,
666789Sahrens 		    ((zjni_Collection_t *)list)->method_add, bean);
6673265Sahrens 	} else {
6683265Sahrens 		zfs_close(zhp);
669789Sahrens 	}
670789Sahrens 
671789Sahrens 	return (0);
672789Sahrens }
673789Sahrens 
674789Sahrens jobjectArray
zjni_get_Datasets_below(JNIEnv * env,jstring parentUTF,zfs_type_t parent_typemask,zfs_type_t child_typemask,char * arrayClass)675789Sahrens zjni_get_Datasets_below(JNIEnv *env, jstring parentUTF,
676789Sahrens     zfs_type_t parent_typemask, zfs_type_t child_typemask, char *arrayClass)
677789Sahrens {
678789Sahrens 	jobjectArray array = NULL;
6791643Stalley 
6801643Stalley 	if (parentUTF != NULL) {
6811643Stalley 		zfs_handle_t *zhp;
6821643Stalley 		int error = 1;
6831643Stalley 		const char *name =
6841643Stalley 		    (*env)->GetStringUTFChars(env, parentUTF, NULL);
685789Sahrens 
6861643Stalley 		/* Create an array list to hold the children */
6871643Stalley 		zjni_DatasetSet_t list_obj = {0};
6881643Stalley 		zjni_DatasetSet_t *list = &list_obj;
6891643Stalley 		zjni_new_DatasetSet(env, list);
6901643Stalley 
6911643Stalley 		/* Retrieve parent dataset */
6922082Seschrock 		zhp = zfs_open(g_zfs, name, parent_typemask);
6931643Stalley 
6941643Stalley 		if (zhp != NULL) {
6951643Stalley 			zjni_DatasetArrayCallbackData_t data = {0};
6961643Stalley 			data.data.env = env;
6971643Stalley 			data.data.list = (zjni_Collection_t *)list;
6981643Stalley 			data.typemask = child_typemask;
699789Sahrens 
7001643Stalley 			(void) zfs_iter_children(zhp, zjni_create_add_Dataset,
7011643Stalley 			    &data);
7021643Stalley 
7031643Stalley 			zfs_close(zhp);
7041643Stalley 
7051643Stalley 			if ((*env)->ExceptionOccurred(env) == NULL) {
7061643Stalley 				error = 0;
7071643Stalley 			}
7081643Stalley 		} else
709789Sahrens 
7101643Stalley 		/* Parent is not a dataset -- see if it's a faulted pool */
7111643Stalley 		if ((parent_typemask & ZFS_TYPE_FILESYSTEM) &&
7121643Stalley 		    is_pool_name(name)) {
7132082Seschrock 			zpool_handle_t *zphp = zpool_open_canfail(g_zfs, name);
714789Sahrens 
7151643Stalley 			if (zphp != NULL) {
7161643Stalley 				/* A faulted pool has no datasets */
7171643Stalley 				error = 0;
7181643Stalley 				zpool_close(zphp);
7191643Stalley 			}
7201643Stalley 		}
721789Sahrens 
7221643Stalley 		(*env)->ReleaseStringUTFChars(env, parentUTF, name);
7231643Stalley 
7241643Stalley 		if (!error) {
7251206Stalley 			array = zjni_Collection_to_array(
7261206Stalley 			    env, (zjni_Collection_t *)list, arrayClass);
7271206Stalley 		}
728789Sahrens 	}
729789Sahrens 
730789Sahrens 	return (array);
731789Sahrens }
732789Sahrens 
733789Sahrens jobjectArray
zjni_get_Datasets_dependents(JNIEnv * env,jobjectArray paths)734789Sahrens zjni_get_Datasets_dependents(JNIEnv *env, jobjectArray paths)
735789Sahrens {
736789Sahrens 	jint i;
737789Sahrens 	jint npaths;
738789Sahrens 	zjni_DatasetArrayCallbackData_t data = {0};
739789Sahrens 	jobjectArray array = NULL;
740789Sahrens 
741789Sahrens 	/* Create a list to hold the children */
742789Sahrens 	zjni_DatasetSet_t list_obj = {0};
743789Sahrens 	zjni_DatasetSet_t *list = &list_obj;
744789Sahrens 	zjni_new_DatasetSet(env, list);
745789Sahrens 
746789Sahrens 	data.data.env = env;
747789Sahrens 	data.data.list = (zjni_Collection_t *)list;
7485094Slling 	data.typemask = ZFS_TYPE_DATASET;
749789Sahrens 
750789Sahrens 	npaths = (*env)->GetArrayLength(env, paths);
751789Sahrens 	for (i = 0; i < npaths; i++) {
752789Sahrens 
753789Sahrens 		jstring pathUTF = (jstring)
754789Sahrens 		    ((*env)->GetObjectArrayElement(env, paths, i));
755789Sahrens 
7561643Stalley 		if (pathUTF != NULL) {
7571643Stalley 			const char *path =
7581643Stalley 			    (*env)->GetStringUTFChars(env, pathUTF, NULL);
7591643Stalley 
7605094Slling 			zfs_handle_t *zhp = zfs_open(g_zfs, path,
7615094Slling 			    ZFS_TYPE_DATASET);
7621643Stalley 			if (zhp != NULL) {
7631643Stalley 				/* Add all dependents of this Dataset to list */
7642474Seschrock 				(void) zfs_iter_dependents(zhp, B_FALSE,
7651643Stalley 				    zjni_create_add_Dataset, &data);
7661643Stalley 
7671643Stalley 				/* Add this Dataset to list (and close zhp) */
7681643Stalley 				(void) zjni_create_add_Dataset(zhp, &data);
7693265Sahrens 			} else if (is_pool_name(path)) {
7703265Sahrens 				/*
7713265Sahrens 				 * Path is not a dataset -
7723265Sahrens 				 * see if it's a faulted pool
7733265Sahrens 				 */
7742082Seschrock 				zpool_handle_t *zphp = zpool_open_canfail(g_zfs,
7752082Seschrock 				    path);
7761643Stalley 
7771643Stalley 				if (zphp != NULL) {
7781643Stalley 					/*
7791643Stalley 					 * Add this Pool to list (and
7801643Stalley 					 * close zphp)
7811643Stalley 					 */
7821643Stalley 					(void) zjni_create_add_Pool(zphp,
7831643Stalley 					    &data.data);
7841643Stalley 				}
7851643Stalley 			}
7861643Stalley 
7871643Stalley 			(*env)->ReleaseStringUTFChars(env, pathUTF, path);
788789Sahrens 		}
789789Sahrens 	}
790789Sahrens 
791789Sahrens 	if ((*env)->ExceptionOccurred(env) == NULL) {
792789Sahrens 		array = zjni_Collection_to_array(env, (zjni_Collection_t *)list,
793789Sahrens 		    ZFSJNI_PACKAGE_DATA "Dataset");
794789Sahrens 	}
795789Sahrens 
796789Sahrens 	return (array);
797789Sahrens }
798789Sahrens 
799789Sahrens /*
800789Sahrens  * Gets a Dataset of the given name and type, or NULL if no such
801789Sahrens  * Dataset exists.
802789Sahrens  */
803789Sahrens jobject
zjni_get_Dataset(JNIEnv * env,jstring nameUTF,zfs_type_t typemask)804789Sahrens zjni_get_Dataset(JNIEnv *env, jstring nameUTF, zfs_type_t typemask)
805789Sahrens {
806789Sahrens 	jobject device = NULL;
8071643Stalley 	const char *name = (*env)->GetStringUTFChars(env, nameUTF, NULL);
8082082Seschrock 	zfs_handle_t *zhp = zfs_open(g_zfs, name, typemask);
8091643Stalley 
8101643Stalley 	if ((typemask & ZFS_TYPE_FILESYSTEM) && is_pool_name(name)) {
8112082Seschrock 		zpool_handle_t *zphp = zpool_open_canfail(g_zfs, name);
8121643Stalley 
8131643Stalley 		if (zphp != NULL) {
8141643Stalley 			device = create_PoolBean(env, zphp, zhp);
8151643Stalley 			zpool_close(zphp);
8161643Stalley 		}
8171643Stalley 	} else if (zhp != NULL) {
8181643Stalley 		/* Creates a Dataset object of the appropriate class */
8191643Stalley 		device = create_DatasetBean(env, zhp);
8201643Stalley 	}
8211643Stalley 
8221206Stalley 	if (zhp != NULL) {
823789Sahrens 		zfs_close(zhp);
824789Sahrens 	}
825789Sahrens 
8261643Stalley 	(*env)->ReleaseStringUTFChars(env, nameUTF, name);
8271643Stalley 
828789Sahrens 	return (device);
829789Sahrens }
830