1 /* 2 * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "jni.h" 27 #include "jni_util.h" 28 #include "jvm.h" 29 #include "jlong.h" 30 31 #include <sys/param.h> 32 #include <sys/mount.h> 33 #ifdef ST_RDONLY 34 #define statfs statvfs 35 #define getfsstat getvfsstat 36 #define f_flags f_flag 37 #define ISREADONLY ST_RDONLY 38 #else 39 #define ISREADONLY MNT_RDONLY 40 #endif 41 42 #include <stdlib.h> 43 #include <string.h> 44 45 static jfieldID entry_name; 46 static jfieldID entry_dir; 47 static jfieldID entry_fstype; 48 static jfieldID entry_options; 49 50 struct fsstat_iter { 51 struct statfs *buf; 52 int pos; 53 int nentries; 54 }; 55 56 #include "sun_nio_fs_BsdNativeDispatcher.h" 57 58 static void throwUnixException(JNIEnv* env, int errnum) { 59 jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException", 60 "(I)V", errnum); 61 if (x != NULL) { 62 (*env)->Throw(env, x); 63 } 64 } 65 66 /** 67 * Initialize jfieldIDs 68 */ 69 JNIEXPORT void JNICALL 70 Java_sun_nio_fs_BsdNativeDispatcher_initIDs(JNIEnv* env, jclass this) 71 { 72 jclass clazz; 73 74 clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry"); 75 CHECK_NULL(clazz); 76 entry_name = (*env)->GetFieldID(env, clazz, "name", "[B"); 77 CHECK_NULL(entry_name); 78 entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B"); 79 CHECK_NULL(entry_dir); 80 entry_fstype = (*env)->GetFieldID(env, clazz, "fstype", "[B"); 81 CHECK_NULL(entry_fstype); 82 entry_options = (*env)->GetFieldID(env, clazz, "opts", "[B"); 83 CHECK_NULL(entry_options); 84 } 85 86 JNIEXPORT jlong JNICALL 87 Java_sun_nio_fs_BsdNativeDispatcher_getfsstat(JNIEnv* env, jclass this) 88 { 89 int nentries; 90 size_t bufsize; 91 struct fsstat_iter *iter = malloc(sizeof(*iter)); 92 93 if (iter == NULL) { 94 JNU_ThrowOutOfMemoryError(env, "native heap"); 95 return 0; 96 } 97 98 iter->pos = 0; 99 iter->nentries = 0; 100 iter->buf = NULL; 101 102 nentries = getfsstat(NULL, 0, MNT_NOWAIT); 103 104 if (nentries <= 0) { 105 free(iter); 106 throwUnixException(env, errno); 107 return 0; 108 } 109 110 // It's possible that a new filesystem gets mounted between 111 // the first getfsstat and the second so loop until consistant 112 113 while (nentries != iter->nentries) { 114 if (iter->buf != NULL) 115 free(iter->buf); 116 117 bufsize = nentries * sizeof(struct statfs); 118 iter->nentries = nentries; 119 120 iter->buf = malloc(bufsize); 121 if (iter->buf == NULL) { 122 free(iter); 123 JNU_ThrowOutOfMemoryError(env, "native heap"); 124 return 0; 125 } 126 127 nentries = getfsstat(iter->buf, bufsize, MNT_WAIT); 128 if (nentries <= 0) { 129 free(iter->buf); 130 free(iter); 131 throwUnixException(env, errno); 132 return 0; 133 } 134 } 135 136 return (jlong)iter; 137 } 138 139 JNIEXPORT jint JNICALL 140 Java_sun_nio_fs_BsdNativeDispatcher_fsstatEntry(JNIEnv* env, jclass this, 141 jlong value, jobject entry) 142 { 143 struct fsstat_iter *iter = jlong_to_ptr(value); 144 jsize len; 145 jbyteArray bytes; 146 char* name; 147 char* dir; 148 char* fstype; 149 char* options; 150 dev_t dev; 151 152 if (iter == NULL || iter->pos >= iter->nentries) 153 return -1; 154 155 name = iter->buf[iter->pos].f_mntfromname; 156 dir = iter->buf[iter->pos].f_mntonname; 157 fstype = iter->buf[iter->pos].f_fstypename; 158 if (iter->buf[iter->pos].f_flags & ISREADONLY) 159 options="ro"; 160 else 161 options=""; 162 163 iter->pos++; 164 165 len = strlen(name); 166 bytes = (*env)->NewByteArray(env, len); 167 if (bytes == NULL) 168 return -1; 169 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)name); 170 (*env)->SetObjectField(env, entry, entry_name, bytes); 171 172 len = strlen(dir); 173 bytes = (*env)->NewByteArray(env, len); 174 if (bytes == NULL) 175 return -1; 176 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)dir); 177 (*env)->SetObjectField(env, entry, entry_dir, bytes); 178 179 len = strlen(fstype); 180 bytes = (*env)->NewByteArray(env, len); 181 if (bytes == NULL) 182 return -1; 183 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)fstype); 184 (*env)->SetObjectField(env, entry, entry_fstype, bytes); 185 186 len = strlen(options); 187 bytes = (*env)->NewByteArray(env, len); 188 if (bytes == NULL) 189 return -1; 190 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)options); 191 (*env)->SetObjectField(env, entry, entry_options, bytes); 192 193 return 0; 194 } 195 196 JNIEXPORT void JNICALL 197 Java_sun_nio_fs_BsdNativeDispatcher_endfsstat(JNIEnv* env, jclass this, jlong value) 198 { 199 struct fsstat_iter *iter = jlong_to_ptr(value); 200 201 if (iter != NULL) { 202 free(iter->buf); 203 free(iter); 204 } 205 }