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 <stdio.h>
32#include <string.h>
33#include <dlfcn.h>
34#include <errno.h>
35#include <mntent.h>
36
37#include "sun_nio_fs_LinuxNativeDispatcher.h"
38
39typedef size_t fgetxattr_func(int fd, const char* name, void* value, size_t size);
40typedef int fsetxattr_func(int fd, const char* name, void* value, size_t size, int flags);
41typedef int fremovexattr_func(int fd, const char* name);
42typedef int flistxattr_func(int fd, char* list, size_t size);
43
44fgetxattr_func* my_fgetxattr_func = NULL;
45fsetxattr_func* my_fsetxattr_func = NULL;
46fremovexattr_func* my_fremovexattr_func = NULL;
47flistxattr_func* my_flistxattr_func = NULL;
48
49static jfieldID entry_name;
50static jfieldID entry_dir;
51static jfieldID entry_fstype;
52static jfieldID entry_options;
53
54static void throwUnixException(JNIEnv* env, int errnum) {
55 jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
56 "(I)V", errnum);
57 if (x != NULL) {
58 (*env)->Throw(env, x);
59 }
60}
61
62JNIEXPORT void JNICALL
63Java_sun_nio_fs_LinuxNativeDispatcher_init(JNIEnv *env, jclass clazz)
64{
65 my_fgetxattr_func = (fgetxattr_func*)dlsym(RTLD_DEFAULT, "fgetxattr");
66 my_fsetxattr_func = (fsetxattr_func*)dlsym(RTLD_DEFAULT, "fsetxattr");
67 my_fremovexattr_func = (fremovexattr_func*)dlsym(RTLD_DEFAULT, "fremovexattr");
68 my_flistxattr_func = (flistxattr_func*)dlsym(RTLD_DEFAULT, "flistxattr");
69
70 clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry");
71 CHECK_NULL(clazz);
72 entry_name = (*env)->GetFieldID(env, clazz, "name", "[B");
73 CHECK_NULL(entry_name);
74 entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B");
75 CHECK_NULL(entry_dir);
76 entry_fstype = (*env)->GetFieldID(env, clazz, "fstype", "[B");
77 CHECK_NULL(entry_fstype);
78 entry_options = (*env)->GetFieldID(env, clazz, "opts", "[B");
79 CHECK_NULL(entry_options);
80}
81
82JNIEXPORT jint JNICALL
83Java_sun_nio_fs_LinuxNativeDispatcher_fgetxattr0(JNIEnv* env, jclass clazz,
84 jint fd, jlong nameAddress, jlong valueAddress, jint valueLen)
85{
86 size_t res = -1;
87 const char* name = jlong_to_ptr(nameAddress);
88 void* value = jlong_to_ptr(valueAddress);
89
90 if (my_fgetxattr_func == NULL) {
91 errno = ENOTSUP;
92 } else {
93 /* EINTR not documented */
94 res = (*my_fgetxattr_func)(fd, name, value, valueLen);
95 }
96 if (res == (size_t)-1)
97 throwUnixException(env, errno);
98 return (jint)res;
99}
100
101JNIEXPORT void JNICALL
102Java_sun_nio_fs_LinuxNativeDispatcher_fsetxattr0(JNIEnv* env, jclass clazz,
103 jint fd, jlong nameAddress, jlong valueAddress, jint valueLen)
104{
105 int res = -1;
106 const char* name = jlong_to_ptr(nameAddress);
107 void* value = jlong_to_ptr(valueAddress);
108
109 if (my_fsetxattr_func == NULL) {
110 errno = ENOTSUP;
111 } else {
112 /* EINTR not documented */
113 res = (*my_fsetxattr_func)(fd, name, value, valueLen, 0);
114 }
115 if (res == -1)
116 throwUnixException(env, errno);
117}
118
119JNIEXPORT void JNICALL
120Java_sun_nio_fs_LinuxNativeDispatcher_fremovexattr0(JNIEnv* env, jclass clazz,
121 jint fd, jlong nameAddress)
122{
123 int res = -1;
124 const char* name = jlong_to_ptr(nameAddress);
125
126 if (my_fremovexattr_func == NULL) {
127 errno = ENOTSUP;
128 } else {
129 /* EINTR not documented */
130 res = (*my_fremovexattr_func)(fd, name);
131 }
132 if (res == -1)
133 throwUnixException(env, errno);
134}
135
136JNIEXPORT jint JNICALL
137Java_sun_nio_fs_LinuxNativeDispatcher_flistxattr(JNIEnv* env, jclass clazz,
138 jint fd, jlong listAddress, jint size)
139{
140 size_t res = -1;
141 char* list = jlong_to_ptr(listAddress);
142
143 if (my_flistxattr_func == NULL) {
144 errno = ENOTSUP;
145 } else {
146 /* EINTR not documented */
147 res = (*my_flistxattr_func)(fd, list, (size_t)size);
148 }
149 if (res == (size_t)-1)
150 throwUnixException(env, errno);
151 return (jint)res;
152}
153
154JNIEXPORT jlong JNICALL
155Java_sun_nio_fs_LinuxNativeDispatcher_setmntent0(JNIEnv* env, jclass this, jlong pathAddress,
156 jlong modeAddress)
157{
158 FILE* fp = NULL;
159 const char* path = (const char*)jlong_to_ptr(pathAddress);
160 const char* mode = (const char*)jlong_to_ptr(modeAddress);
161
162 do {
163 fp = setmntent(path, mode);
164 } while (fp == NULL && errno == EINTR);
165 if (fp == NULL) {
166 throwUnixException(env, errno);
167 }
168 return ptr_to_jlong(fp);
169}
170
171JNIEXPORT jint JNICALL
172Java_sun_nio_fs_LinuxNativeDispatcher_getmntent(JNIEnv* env, jclass this,
173 jlong value, jobject entry)
174{
175 struct mntent ent;
176 char buf[1024];
177 int buflen = sizeof(buf);
178 struct mntent* m;
179 FILE* fp = jlong_to_ptr(value);
180 jsize len;
181 jbyteArray bytes;
182 char* name;
183 char* dir;
184 char* fstype;
185 char* options;
186
187 m = getmntent_r(fp, &ent, (char*)&buf, buflen);
188 if (m == NULL)
189 return -1;
190 name = m->mnt_fsname;
191 dir = m->mnt_dir;
192 fstype = m->mnt_type;
193 options = m->mnt_opts;
194
195 len = strlen(name);
196 bytes = (*env)->NewByteArray(env, len);
197 if (bytes == NULL)
198 return -1;
199 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)name);
200 (*env)->SetObjectField(env, entry, entry_name, bytes);
201
202 len = strlen(dir);
203 bytes = (*env)->NewByteArray(env, len);
204 if (bytes == NULL)
205 return -1;
206 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)dir);
207 (*env)->SetObjectField(env, entry, entry_dir, bytes);
208
209 len = strlen(fstype);
210 bytes = (*env)->NewByteArray(env, len);
211 if (bytes == NULL)
212 return -1;
213 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)fstype);
214 (*env)->SetObjectField(env, entry, entry_fstype, bytes);
215
216 len = strlen(options);
217 bytes = (*env)->NewByteArray(env, len);
218 if (bytes == NULL)
219 return -1;
220 (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)options);
221 (*env)->SetObjectField(env, entry, entry_options, bytes);
222
223 return 0;
224}
225
226JNIEXPORT void JNICALL
227Java_sun_nio_fs_LinuxNativeDispatcher_endmntent(JNIEnv* env, jclass this, jlong stream)
228{
229 FILE* fp = jlong_to_ptr(stream);
230 /* FIXME - man page doesn't explain how errors are returned */
231 endmntent(fp);
232}
233