1 /* 2 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2013 SAP SE. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 #include <stdlib.h> 28 #include <errno.h> 29 #include <sys/types.h> 30 #include <sys/mntctl.h> 31 32 #include "jni.h" 33 #include "jni_util.h" 34 35 #include "sun_nio_fs_AixNativeDispatcher.h" 36 37 static jfieldID entry_name; 38 static jfieldID entry_dir; 39 static jfieldID entry_fstype; 40 static jfieldID entry_options; 41 42 static jclass entry_cls; 43 44 /** 45 * Call this to throw an internal UnixException when a system/library 46 * call fails 47 */ 48 static void throwUnixException(JNIEnv* env, int errnum) { 49 jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException", 50 "(I)V", errnum); 51 if (x != NULL) { 52 (*env)->Throw(env, x); 53 } 54 } 55 56 /** 57 * Initialization 58 */ 59 JNIEXPORT void JNICALL 60 Java_sun_nio_fs_AixNativeDispatcher_init(JNIEnv* env, jclass this) 61 { 62 jclass clazz; 63 64 clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry"); 65 CHECK_NULL(clazz); 66 entry_name = (*env)->GetFieldID(env, clazz, "name", "[B"); 67 CHECK_NULL(entry_name); 68 entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B"); 69 CHECK_NULL(entry_dir); 70 entry_fstype = (*env)->GetFieldID(env, clazz, "fstype", "[B"); 71 CHECK_NULL(entry_fstype); 72 entry_options = (*env)->GetFieldID(env, clazz, "opts", "[B"); 73 CHECK_NULL(entry_options); 74 entry_cls = (*env)->NewGlobalRef(env, clazz); 75 if (entry_cls == NULL) { 76 JNU_ThrowOutOfMemoryError(env, NULL); 77 return; 78 } 79 } 80 81 /** 82 * Special implementation of getextmntent (see SolarisNativeDispatcher.c) 83 * that returns all entries at once. 84 */ 85 JNIEXPORT jobjectArray JNICALL 86 Java_sun_nio_fs_AixNativeDispatcher_getmntctl(JNIEnv* env, jclass this) 87 { 88 int must_free_buf = 0; 89 char stack_buf[1024]; 90 char* buffer = stack_buf; 91 size_t buffer_size = 1024; 92 int num_entries; 93 int i; 94 jobjectArray ret; 95 struct vmount * vm; 96 97 for (i = 0; i < 5; i++) { 98 num_entries = mntctl(MCTL_QUERY, buffer_size, buffer); 99 if (num_entries != 0) { 100 break; 101 } 102 if (must_free_buf) { 103 free(buffer); 104 } 105 buffer_size *= 8; 106 buffer = malloc(buffer_size); 107 must_free_buf = 1; 108 } 109 /* Treat zero entries like errors. */ 110 if (num_entries <= 0) { 111 if (must_free_buf) { 112 free(buffer); 113 } 114 throwUnixException(env, errno); 115 return NULL; 116 } 117 ret = (*env)->NewObjectArray(env, num_entries, entry_cls, NULL); 118 if (ret == NULL) { 119 if (must_free_buf) { 120 free(buffer); 121 } 122 return NULL; 123 } 124 vm = (struct vmount*)buffer; 125 for (i = 0; i < num_entries; i++) { 126 jsize len; 127 jbyteArray bytes; 128 const char* fstype; 129 /* We set all relevant attributes so there is no need to call constructor. */ 130 jobject entry = (*env)->AllocObject(env, entry_cls); 131 if (entry == NULL) { 132 if (must_free_buf) { 133 free(buffer); 134 } 135 return NULL; 136 } 137 (*env)->SetObjectArrayElement(env, ret, i, entry); 138 139 /* vm->vmt_data[...].vmt_size is 32 bit aligned and also includes NULL byte. */ 140 /* Since we only need the characters, it is necessary to check string size manually. */ 141 len = strlen((char*)vm + vm->vmt_data[VMT_OBJECT].vmt_off); 142 bytes = (*env)->NewByteArray(env, len); 143 if (bytes == NULL) { 144 if (must_free_buf) { 145 free(buffer); 146 } 147 return NULL; 148 } 149 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)((char *)vm + vm->vmt_data[VMT_OBJECT].vmt_off)); 150 (*env)->SetObjectField(env, entry, entry_name, bytes); 151 152 len = strlen((char*)vm + vm->vmt_data[VMT_STUB].vmt_off); 153 bytes = (*env)->NewByteArray(env, len); 154 if (bytes == NULL) { 155 if (must_free_buf) { 156 free(buffer); 157 } 158 return NULL; 159 } 160 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)((char *)vm + vm->vmt_data[VMT_STUB].vmt_off)); 161 (*env)->SetObjectField(env, entry, entry_dir, bytes); 162 163 switch (vm->vmt_gfstype) { 164 case MNT_J2: 165 fstype = "jfs2"; 166 break; 167 case MNT_NAMEFS: 168 fstype = "namefs"; 169 break; 170 case MNT_NFS: 171 fstype = "nfs"; 172 break; 173 case MNT_JFS: 174 fstype = "jfs"; 175 break; 176 case MNT_CDROM: 177 fstype = "cdrom"; 178 break; 179 case MNT_PROCFS: 180 fstype = "procfs"; 181 break; 182 case MNT_NFS3: 183 fstype = "nfs3"; 184 break; 185 case MNT_AUTOFS: 186 fstype = "autofs"; 187 break; 188 case MNT_UDF: 189 fstype = "udfs"; 190 break; 191 case MNT_NFS4: 192 fstype = "nfs4"; 193 break; 194 case MNT_CIFS: 195 fstype = "smbfs"; 196 break; 197 default: 198 fstype = "unknown"; 199 } 200 len = strlen(fstype); 201 bytes = (*env)->NewByteArray(env, len); 202 if (bytes == NULL) { 203 if (must_free_buf) { 204 free(buffer); 205 } 206 return NULL; 207 } 208 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)fstype); 209 (*env)->SetObjectField(env, entry, entry_fstype, bytes); 210 211 len = strlen((char*)vm + vm->vmt_data[VMT_ARGS].vmt_off); 212 bytes = (*env)->NewByteArray(env, len); 213 if (bytes == NULL) { 214 if (must_free_buf) { 215 free(buffer); 216 } 217 return NULL; 218 } 219 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)((char *)vm + vm->vmt_data[VMT_ARGS].vmt_off)); 220 (*env)->SetObjectField(env, entry, entry_options, bytes); 221 222 /* goto the next vmount structure: */ 223 vm = (struct vmount *)((char *)vm + vm->vmt_length); 224 } 225 226 if (must_free_buf) { 227 free(buffer); 228 } 229 return ret; 230 }