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