1 /* 2 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. 3 * Copyright 2013 SAP AG. 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 jint JNICALL 60 Java_sun_nio_fs_AixNativeDispatcher_init(JNIEnv* env, jclass this) 61 { 62 jint flags = 0; 63 jclass clazz; 64 65 clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry"); 66 if (clazz == NULL) { 67 return 0; 68 } 69 entry_name = (*env)->GetFieldID(env, clazz, "name", "[B"); 70 entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B"); 71 entry_fstype = (*env)->GetFieldID(env, clazz, "fstype", "[B"); 72 entry_options = (*env)->GetFieldID(env, clazz, "opts", "[B"); 73 entry_cls = (*env)->NewGlobalRef(env, clazz); 74 75 return 0; 76 } 77 78 /** 79 * Special implementation of getextmntent (see SolarisNativeDispatcher.c) 80 * that returns all entries at once. 81 */ 82 JNIEXPORT jobjectArray JNICALL 83 Java_sun_nio_fs_AixNativeDispatcher_getmntctl(JNIEnv* env, jclass this) 84 { 85 int must_free_buf = 0; 86 char stack_buf[1024]; 87 char* buffer = stack_buf; 88 size_t buffer_size = 1024; 89 int num_entries; 90 int i; 91 jobjectArray ret; 92 struct vmount * vm; 93 94 for (i = 0; i < 5; i++) { 95 num_entries = mntctl(MCTL_QUERY, buffer_size, buffer); 96 if (num_entries != 0) { 97 break; 98 } 99 if (must_free_buf) { 100 free(buffer); 101 } 102 buffer_size *= 8; 103 buffer = malloc(buffer_size); 104 must_free_buf = 1; 105 } 106 /* Treat zero entries like errors. */ 107 if (num_entries <= 0) { 108 if (must_free_buf) { 109 free(buffer); 110 } 111 throwUnixException(env, errno); 112 return NULL; 113 } 114 ret = (*env)->NewObjectArray(env, num_entries, entry_cls, NULL); 115 if (ret == NULL) { 116 if (must_free_buf) { 117 free(buffer); 118 } 119 return NULL; 120 } 121 vm = (struct vmount*)buffer; 122 for (i = 0; i < num_entries; i++) { 123 jsize len; 124 jbyteArray bytes; 125 const char* fstype; 126 /* We set all relevant attributes so there is no need to call constructor. */ 127 jobject entry = (*env)->AllocObject(env, entry_cls); 128 if (entry == NULL) { 129 if (must_free_buf) { 130 free(buffer); 131 } 132 return NULL; 133 } 134 (*env)->SetObjectArrayElement(env, ret, i, entry); 135 136 /* vm->vmt_data[...].vmt_size is 32 bit aligned and also includes NULL byte. */ 137 /* Since we only need the characters, it is necessary to check string size manually. */ 138 len = strlen((char*)vm + vm->vmt_data[VMT_OBJECT].vmt_off); 139 bytes = (*env)->NewByteArray(env, len); 140 if (bytes == NULL) { 141 if (must_free_buf) { 142 free(buffer); 143 } 144 return NULL; 145 } 146 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)((char *)vm + vm->vmt_data[VMT_OBJECT].vmt_off)); 147 (*env)->SetObjectField(env, entry, entry_name, bytes); 148 149 len = strlen((char*)vm + vm->vmt_data[VMT_STUB].vmt_off); 150 bytes = (*env)->NewByteArray(env, len); 151 if (bytes == NULL) { 152 if (must_free_buf) { 153 free(buffer); 154 } 155 return NULL; 156 } 157 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)((char *)vm + vm->vmt_data[VMT_STUB].vmt_off)); 158 (*env)->SetObjectField(env, entry, entry_dir, bytes); 159 160 switch (vm->vmt_gfstype) { 161 case MNT_J2: 162 fstype = "jfs2"; 163 break; 164 case MNT_NAMEFS: 165 fstype = "namefs"; 166 break; 167 case MNT_NFS: 168 fstype = "nfs"; 169 break; 170 case MNT_JFS: 171 fstype = "jfs"; 172 break; 173 case MNT_CDROM: 174 fstype = "cdrom"; 175 break; 176 case MNT_PROCFS: 177 fstype = "procfs"; 178 break; 179 case MNT_NFS3: 180 fstype = "nfs3"; 181 break; 182 case MNT_AUTOFS: 183 fstype = "autofs"; 184 break; 185 case MNT_UDF: 186 fstype = "udfs"; 187 break; 188 case MNT_NFS4: 189 fstype = "nfs4"; 190 break; 191 case MNT_CIFS: 192 fstype = "smbfs"; 193 break; 194 default: 195 fstype = "unknown"; 196 } 197 len = strlen(fstype); 198 bytes = (*env)->NewByteArray(env, len); 199 if (bytes == NULL) { 200 if (must_free_buf) { 201 free(buffer); 202 } 203 return NULL; 204 } 205 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)fstype); 206 (*env)->SetObjectField(env, entry, entry_fstype, bytes); 207 208 len = strlen((char*)vm + vm->vmt_data[VMT_ARGS].vmt_off); 209 bytes = (*env)->NewByteArray(env, len); 210 if (bytes == NULL) { 211 if (must_free_buf) { 212 free(buffer); 213 } 214 return NULL; 215 } 216 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)((char *)vm + vm->vmt_data[VMT_ARGS].vmt_off)); 217 (*env)->SetObjectField(env, entry, entry_options, bytes); 218 219 /* goto the next vmount structure: */ 220 vm = (struct vmount *)((char *)vm + vm->vmt_length); 221 } 222 223 if (must_free_buf) { 224 free(buffer); 225 } 226 return ret; 227 }