1 /*
2  * Copyright (c) 2008, 2013, 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 package sun.nio.fs;
27 
28 import java.security.AccessController;
29 import java.security.PrivilegedAction;
30 
31 /**
32  * Unix system and library calls.
33  */
34 
35 class UnixNativeDispatcher {
UnixNativeDispatcher()36     protected UnixNativeDispatcher() { }
37 
38     // returns a NativeBuffer containing the given path
copyToNativeBuffer(UnixPath path)39     private static NativeBuffer copyToNativeBuffer(UnixPath path) {
40         byte[] cstr = path.getByteArrayForSysCalls();
41         int size = cstr.length + 1;
42         NativeBuffer buffer = NativeBuffers.getNativeBufferFromCache(size);
43         if (buffer == null) {
44             buffer = NativeBuffers.allocNativeBuffer(size);
45         } else {
46             // buffer already contains the path
47             if (buffer.owner() == path)
48                 return buffer;
49         }
50         NativeBuffers.copyCStringToNativeBuffer(cstr, buffer);
51         buffer.setOwner(path);
52         return buffer;
53     }
54 
55     /**
56      * char *getcwd(char *buf, size_t size);
57      */
getcwd()58     static native byte[] getcwd();
59 
60     /**
61      * int dup(int filedes)
62      */
dup(int filedes)63     static native int dup(int filedes) throws UnixException;
64 
65     /**
66      * int open(const char* path, int oflag, mode_t mode)
67      */
open(UnixPath path, int flags, int mode)68     static int open(UnixPath path, int flags, int mode) throws UnixException {
69         NativeBuffer buffer = copyToNativeBuffer(path);
70         try {
71             return open0(buffer.address(), flags, mode);
72         } finally {
73             buffer.release();
74         }
75     }
open0(long pathAddress, int flags, int mode)76     private static native int open0(long pathAddress, int flags, int mode)
77         throws UnixException;
78 
79     /**
80      * int openat(int dfd, const char* path, int oflag, mode_t mode)
81      */
openat(int dfd, byte[] path, int flags, int mode)82     static int openat(int dfd, byte[] path, int flags, int mode) throws UnixException {
83         NativeBuffer buffer = NativeBuffers.asNativeBuffer(path);
84         try {
85             return openat0(dfd, buffer.address(), flags, mode);
86         } finally {
87             buffer.release();
88         }
89     }
openat0(int dfd, long pathAddress, int flags, int mode)90     private static native int openat0(int dfd, long pathAddress, int flags, int mode)
91         throws UnixException;
92 
93     /**
94      * close(int filedes)
95      */
close(int fd)96     static native void close(int fd);
97 
98     /**
99      * FILE* fopen(const char *filename, const char* mode);
100      */
fopen(UnixPath filename, String mode)101     static long fopen(UnixPath filename, String mode) throws UnixException {
102         NativeBuffer pathBuffer = copyToNativeBuffer(filename);
103         NativeBuffer modeBuffer = NativeBuffers.asNativeBuffer(Util.toBytes(mode));
104         try {
105             return fopen0(pathBuffer.address(), modeBuffer.address());
106         } finally {
107             modeBuffer.release();
108             pathBuffer.release();
109         }
110     }
fopen0(long pathAddress, long modeAddress)111     private static native long fopen0(long pathAddress, long modeAddress)
112         throws UnixException;
113 
114     /**
115      * fclose(FILE* stream)
116      */
fclose(long stream)117     static native void fclose(long stream) throws UnixException;
118 
119     /**
120      * link(const char* existing, const char* new)
121      */
link(UnixPath existing, UnixPath newfile)122     static void link(UnixPath existing, UnixPath newfile) throws UnixException {
123         NativeBuffer existingBuffer = copyToNativeBuffer(existing);
124         NativeBuffer newBuffer = copyToNativeBuffer(newfile);
125         try {
126             link0(existingBuffer.address(), newBuffer.address());
127         } finally {
128             newBuffer.release();
129             existingBuffer.release();
130         }
131     }
link0(long existingAddress, long newAddress)132     private static native void link0(long existingAddress, long newAddress)
133         throws UnixException;
134 
135     /**
136      * unlink(const char* path)
137      */
unlink(UnixPath path)138     static void unlink(UnixPath path) throws UnixException {
139         NativeBuffer buffer = copyToNativeBuffer(path);
140         try {
141             unlink0(buffer.address());
142         } finally {
143             buffer.release();
144         }
145     }
unlink0(long pathAddress)146     private static native void unlink0(long pathAddress) throws UnixException;
147 
148     /**
149      * unlinkat(int dfd, const char* path, int flag)
150      */
unlinkat(int dfd, byte[] path, int flag)151     static void unlinkat(int dfd, byte[] path, int flag) throws UnixException {
152         NativeBuffer buffer = NativeBuffers.asNativeBuffer(path);
153         try {
154             unlinkat0(dfd, buffer.address(), flag);
155         } finally {
156             buffer.release();
157         }
158     }
unlinkat0(int dfd, long pathAddress, int flag)159     private static native void unlinkat0(int dfd, long pathAddress, int flag)
160         throws UnixException;
161 
162     /**
163      * mknod(const char* path, mode_t mode, dev_t dev)
164      */
mknod(UnixPath path, int mode, long dev)165     static void mknod(UnixPath path, int mode, long dev) throws UnixException {
166         NativeBuffer buffer = copyToNativeBuffer(path);
167         try {
168             mknod0(buffer.address(), mode, dev);
169         } finally {
170             buffer.release();
171         }
172     }
mknod0(long pathAddress, int mode, long dev)173     private static native void mknod0(long pathAddress, int mode, long dev)
174         throws UnixException;
175 
176     /**
177      *  rename(const char* old, const char* new)
178      */
rename(UnixPath from, UnixPath to)179     static void rename(UnixPath from, UnixPath to) throws UnixException {
180         NativeBuffer fromBuffer = copyToNativeBuffer(from);
181         NativeBuffer toBuffer = copyToNativeBuffer(to);
182         try {
183             rename0(fromBuffer.address(), toBuffer.address());
184         } finally {
185             toBuffer.release();
186             fromBuffer.release();
187         }
188     }
rename0(long fromAddress, long toAddress)189     private static native void rename0(long fromAddress, long toAddress)
190         throws UnixException;
191 
192     /**
193      *  renameat(int fromfd, const char* old, int tofd, const char* new)
194      */
renameat(int fromfd, byte[] from, int tofd, byte[] to)195     static void renameat(int fromfd, byte[] from, int tofd, byte[] to) throws UnixException {
196         NativeBuffer fromBuffer = NativeBuffers.asNativeBuffer(from);
197         NativeBuffer toBuffer = NativeBuffers.asNativeBuffer(to);
198         try {
199             renameat0(fromfd, fromBuffer.address(), tofd, toBuffer.address());
200         } finally {
201             toBuffer.release();
202             fromBuffer.release();
203         }
204     }
renameat0(int fromfd, long fromAddress, int tofd, long toAddress)205     private static native void renameat0(int fromfd, long fromAddress, int tofd, long toAddress)
206         throws UnixException;
207 
208     /**
209      * mkdir(const char* path, mode_t mode)
210      */
mkdir(UnixPath path, int mode)211     static void mkdir(UnixPath path, int mode) throws UnixException {
212         NativeBuffer buffer = copyToNativeBuffer(path);
213         try {
214             mkdir0(buffer.address(), mode);
215         } finally {
216             buffer.release();
217         }
218     }
mkdir0(long pathAddress, int mode)219     private static native void mkdir0(long pathAddress, int mode) throws UnixException;
220 
221     /**
222      * rmdir(const char* path)
223      */
rmdir(UnixPath path)224     static void rmdir(UnixPath path) throws UnixException {
225         NativeBuffer buffer = copyToNativeBuffer(path);
226         try {
227             rmdir0(buffer.address());
228         } finally {
229             buffer.release();
230         }
231     }
rmdir0(long pathAddress)232     private static native void rmdir0(long pathAddress) throws UnixException;
233 
234     /**
235      * readlink(const char* path, char* buf, size_t bufsize)
236      *
237      * @return  link target
238      */
readlink(UnixPath path)239     static byte[] readlink(UnixPath path) throws UnixException {
240         NativeBuffer buffer = copyToNativeBuffer(path);
241         try {
242             return readlink0(buffer.address());
243         } finally {
244             buffer.release();
245         }
246     }
readlink0(long pathAddress)247     private static native byte[] readlink0(long pathAddress) throws UnixException;
248 
249     /**
250      * realpath(const char* path, char* resolved_name)
251      *
252      * @return  resolved path
253      */
realpath(UnixPath path)254     static byte[] realpath(UnixPath path) throws UnixException {
255         NativeBuffer buffer = copyToNativeBuffer(path);
256         try {
257             return realpath0(buffer.address());
258         } finally {
259             buffer.release();
260         }
261     }
realpath0(long pathAddress)262     private static native byte[] realpath0(long pathAddress) throws UnixException;
263 
264     /**
265      * symlink(const char* name1, const char* name2)
266      */
symlink(byte[] name1, UnixPath name2)267     static void symlink(byte[] name1, UnixPath name2) throws UnixException {
268         NativeBuffer targetBuffer = NativeBuffers.asNativeBuffer(name1);
269         NativeBuffer linkBuffer = copyToNativeBuffer(name2);
270         try {
271             symlink0(targetBuffer.address(), linkBuffer.address());
272         } finally {
273             linkBuffer.release();
274             targetBuffer.release();
275         }
276     }
symlink0(long name1, long name2)277     private static native void symlink0(long name1, long name2)
278         throws UnixException;
279 
280     /**
281      * stat(const char* path, struct stat* buf)
282      */
stat(UnixPath path, UnixFileAttributes attrs)283     static void stat(UnixPath path, UnixFileAttributes attrs) throws UnixException {
284         NativeBuffer buffer = copyToNativeBuffer(path);
285         try {
286             stat0(buffer.address(), attrs);
287         } finally {
288             buffer.release();
289         }
290     }
stat0(long pathAddress, UnixFileAttributes attrs)291     private static native void stat0(long pathAddress, UnixFileAttributes attrs)
292         throws UnixException;
293 
294     /**
295      * lstat(const char* path, struct stat* buf)
296      */
lstat(UnixPath path, UnixFileAttributes attrs)297     static void lstat(UnixPath path, UnixFileAttributes attrs) throws UnixException {
298         NativeBuffer buffer = copyToNativeBuffer(path);
299         try {
300             lstat0(buffer.address(), attrs);
301         } finally {
302             buffer.release();
303         }
304     }
lstat0(long pathAddress, UnixFileAttributes attrs)305     private static native void lstat0(long pathAddress, UnixFileAttributes attrs)
306         throws UnixException;
307 
308     /**
309      * fstat(int filedes, struct stat* buf)
310      */
fstat(int fd, UnixFileAttributes attrs)311     static native void fstat(int fd, UnixFileAttributes attrs) throws UnixException;
312 
313     /**
314      * fstatat(int filedes,const char* path,  struct stat* buf, int flag)
315      */
fstatat(int dfd, byte[] path, int flag, UnixFileAttributes attrs)316     static void fstatat(int dfd, byte[] path, int flag, UnixFileAttributes attrs)
317         throws UnixException
318     {
319         NativeBuffer buffer = NativeBuffers.asNativeBuffer(path);
320         try {
321             fstatat0(dfd, buffer.address(), flag, attrs);
322         } finally {
323             buffer.release();
324         }
325     }
fstatat0(int dfd, long pathAddress, int flag, UnixFileAttributes attrs)326     private static native void fstatat0(int dfd, long pathAddress, int flag,
327         UnixFileAttributes attrs) throws UnixException;
328 
329     /**
330      * chown(const char* path, uid_t owner, gid_t group)
331      */
chown(UnixPath path, int uid, int gid)332     static void chown(UnixPath path, int uid, int gid) throws UnixException {
333         NativeBuffer buffer = copyToNativeBuffer(path);
334         try {
335             chown0(buffer.address(), uid, gid);
336         } finally {
337             buffer.release();
338         }
339     }
chown0(long pathAddress, int uid, int gid)340     private static native void chown0(long pathAddress, int uid, int gid)
341         throws UnixException;
342 
343     /**
344      * lchown(const char* path, uid_t owner, gid_t group)
345      */
lchown(UnixPath path, int uid, int gid)346     static void lchown(UnixPath path, int uid, int gid) throws UnixException {
347         NativeBuffer buffer = copyToNativeBuffer(path);
348         try {
349             lchown0(buffer.address(), uid, gid);
350         } finally {
351             buffer.release();
352         }
353     }
lchown0(long pathAddress, int uid, int gid)354     private static native void lchown0(long pathAddress, int uid, int gid)
355         throws UnixException;
356 
357     /**
358      * fchown(int filedes, uid_t owner, gid_t group)
359      */
fchown(int fd, int uid, int gid)360     static native void fchown(int fd, int uid, int gid) throws UnixException;
361 
362     /**
363      * chmod(const char* path, mode_t mode)
364      */
chmod(UnixPath path, int mode)365     static void chmod(UnixPath path, int mode) throws UnixException {
366         NativeBuffer buffer = copyToNativeBuffer(path);
367         try {
368             chmod0(buffer.address(), mode);
369         } finally {
370             buffer.release();
371         }
372     }
chmod0(long pathAddress, int mode)373     private static native void chmod0(long pathAddress, int mode)
374         throws UnixException;
375 
376     /**
377      * fchmod(int fildes, mode_t mode)
378      */
fchmod(int fd, int mode)379     static native void fchmod(int fd, int mode) throws UnixException;
380 
381     /**
382      * utimes(conar char* path, const struct timeval times[2])
383      */
utimes(UnixPath path, long times0, long times1)384     static void utimes(UnixPath path, long times0, long times1)
385         throws UnixException
386     {
387         NativeBuffer buffer = copyToNativeBuffer(path);
388         try {
389             utimes0(buffer.address(), times0, times1);
390         } finally {
391             buffer.release();
392         }
393     }
utimes0(long pathAddress, long times0, long times1)394     private static native void utimes0(long pathAddress, long times0, long times1)
395         throws UnixException;
396 
397     /**
398      * futimes(int fildes,, const struct timeval times[2])
399      */
futimes(int fd, long times0, long times1)400     static native void futimes(int fd, long times0, long times1) throws UnixException;
401 
402     /**
403      * DIR *opendir(const char* dirname)
404      */
opendir(UnixPath path)405     static long opendir(UnixPath path) throws UnixException {
406         NativeBuffer buffer = copyToNativeBuffer(path);
407         try {
408             return opendir0(buffer.address());
409         } finally {
410             buffer.release();
411         }
412     }
opendir0(long pathAddress)413     private static native long opendir0(long pathAddress) throws UnixException;
414 
415     /**
416      * DIR* fdopendir(int filedes)
417      */
fdopendir(int dfd)418     static native long fdopendir(int dfd) throws UnixException;
419 
420 
421     /**
422      * closedir(DIR* dirp)
423      */
closedir(long dir)424     static native void closedir(long dir) throws UnixException;
425 
426     /**
427      * struct dirent* readdir(DIR *dirp)
428      *
429      * @return  dirent->d_name
430      */
readdir(long dir)431     static native byte[] readdir(long dir) throws UnixException;
432 
433     /**
434      * size_t read(int fildes, void* buf, size_t nbyte)
435      */
read(int fildes, long buf, int nbyte)436     static native int read(int fildes, long buf, int nbyte) throws UnixException;
437 
438     /**
439      * size_t writeint fildes, void* buf, size_t nbyte)
440      */
write(int fildes, long buf, int nbyte)441     static native int write(int fildes, long buf, int nbyte) throws UnixException;
442 
443     /**
444      * access(const char* path, int amode);
445      */
access(UnixPath path, int amode)446     static void access(UnixPath path, int amode) throws UnixException {
447         NativeBuffer buffer = copyToNativeBuffer(path);
448         try {
449             access0(buffer.address(), amode);
450         } finally {
451             buffer.release();
452         }
453     }
access0(long pathAddress, int amode)454     private static native void access0(long pathAddress, int amode) throws UnixException;
455 
456     /**
457      * struct passwd *getpwuid(uid_t uid);
458      *
459      * @return  passwd->pw_name
460      */
getpwuid(int uid)461     static native byte[] getpwuid(int uid) throws UnixException;
462 
463     /**
464      * struct group *getgrgid(gid_t gid);
465      *
466      * @return  group->gr_name
467      */
getgrgid(int gid)468     static native byte[] getgrgid(int gid) throws UnixException;
469 
470     /**
471      * struct passwd *getpwnam(const char *name);
472      *
473      * @return  passwd->pw_uid
474      */
getpwnam(String name)475     static int getpwnam(String name) throws UnixException {
476         NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name));
477         try {
478             return getpwnam0(buffer.address());
479         } finally {
480             buffer.release();
481         }
482     }
getpwnam0(long nameAddress)483     private static native int getpwnam0(long nameAddress) throws UnixException;
484 
485     /**
486      * struct group *getgrnam(const char *name);
487      *
488      * @return  group->gr_name
489      */
getgrnam(String name)490     static int getgrnam(String name) throws UnixException {
491         NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name));
492         try {
493             return getgrnam0(buffer.address());
494         } finally {
495             buffer.release();
496         }
497     }
getgrnam0(long nameAddress)498     private static native int getgrnam0(long nameAddress) throws UnixException;
499 
500     /**
501      * statvfs(const char* path, struct statvfs *buf)
502      */
statvfs(UnixPath path, UnixFileStoreAttributes attrs)503     static void statvfs(UnixPath path, UnixFileStoreAttributes attrs)
504         throws UnixException
505     {
506         NativeBuffer buffer = copyToNativeBuffer(path);
507         try {
508             statvfs0(buffer.address(), attrs);
509         } finally {
510             buffer.release();
511         }
512     }
statvfs0(long pathAddress, UnixFileStoreAttributes attrs)513     private static native void statvfs0(long pathAddress, UnixFileStoreAttributes attrs)
514         throws UnixException;
515 
516     /**
517      * long int pathconf(const char *path, int name);
518      */
pathconf(UnixPath path, int name)519     static long pathconf(UnixPath path, int name) throws UnixException {
520         NativeBuffer buffer = copyToNativeBuffer(path);
521         try {
522             return pathconf0(buffer.address(), name);
523         } finally {
524             buffer.release();
525         }
526     }
pathconf0(long pathAddress, int name)527     private static native long pathconf0(long pathAddress, int name)
528         throws UnixException;
529 
530     /**
531      * long fpathconf(int fildes, int name);
532      */
fpathconf(int filedes, int name)533     static native long fpathconf(int filedes, int name) throws UnixException;
534 
535     /**
536      * char* strerror(int errnum)
537      */
strerror(int errnum)538     static native byte[] strerror(int errnum);
539 
540     /**
541      * Capabilities
542      */
543     private static final int SUPPORTS_OPENAT        = 1 << 1;    // syscalls
544     private static final int SUPPORTS_FUTIMES       = 1 << 2;
545     private static final int SUPPORTS_BIRTHTIME     = 1 << 16;   // other features
546     private static final int capabilities;
547 
548     /**
549      * Supports openat and other *at calls.
550      */
openatSupported()551     static boolean openatSupported() {
552         return (capabilities & SUPPORTS_OPENAT) != 0;
553     }
554 
555     /**
556      * Supports futimes or futimesat
557      */
futimesSupported()558     static boolean futimesSupported() {
559         return (capabilities & SUPPORTS_FUTIMES) != 0;
560     }
561 
562     /**
563      * Supports file birth (creation) time attribute
564      */
birthtimeSupported()565     static boolean birthtimeSupported() {
566         return (capabilities & SUPPORTS_BIRTHTIME) != 0;
567     }
568 
init()569     private static native int init();
570     static {
571         capabilities = init();
572     }
573 }
574