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
26package sun.nio.fs;
27
28import java.security.AccessController;
29import java.security.PrivilegedAction;
30
31/**
32 * Unix system and library calls.
33 */
34
35class UnixNativeDispatcher {
36    protected UnixNativeDispatcher() { }
37
38    // returns a NativeBuffer containing the given 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     */
58    static native byte[] getcwd();
59
60    /**
61     * int dup(int filedes)
62     */
63    static native int dup(int filedes) throws UnixException;
64
65    /**
66     * int open(const char* path, int oflag, mode_t mode)
67     */
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    }
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     */
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    }
90    private static native int openat0(int dfd, long pathAddress, int flags, int mode)
91        throws UnixException;
92
93    /**
94     * close(int filedes)
95     */
96    static native void close(int fd);
97
98    /**
99     * FILE* fopen(const char *filename, const char* mode);
100     */
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    }
111    private static native long fopen0(long pathAddress, long modeAddress)
112        throws UnixException;
113
114    /**
115     * fclose(FILE* stream)
116     */
117    static native void fclose(long stream) throws UnixException;
118
119    /**
120     * link(const char* existing, const char* new)
121     */
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    }
132    private static native void link0(long existingAddress, long newAddress)
133        throws UnixException;
134
135    /**
136     * unlink(const char* path)
137     */
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    }
146    private static native void unlink0(long pathAddress) throws UnixException;
147
148    /**
149     * unlinkat(int dfd, const char* path, int flag)
150     */
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    }
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     */
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    }
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     */
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    }
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     */
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    }
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     */
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    }
219    private static native void mkdir0(long pathAddress, int mode) throws UnixException;
220
221    /**
222     * rmdir(const char* path)
223     */
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    }
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     */
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    }
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     */
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    }
262    private static native byte[] realpath0(long pathAddress) throws UnixException;
263
264    /**
265     * symlink(const char* name1, const char* name2)
266     */
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    }
277    private static native void symlink0(long name1, long name2)
278        throws UnixException;
279
280    /**
281     * stat(const char* path, struct stat* buf)
282     */
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    }
291    private static native void stat0(long pathAddress, UnixFileAttributes attrs)
292        throws UnixException;
293
294    /**
295     * lstat(const char* path, struct stat* buf)
296     */
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    }
305    private static native void lstat0(long pathAddress, UnixFileAttributes attrs)
306        throws UnixException;
307
308    /**
309     * fstat(int filedes, struct stat* buf)
310     */
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     */
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    }
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     */
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    }
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     */
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    }
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     */
360    static native void fchown(int fd, int uid, int gid) throws UnixException;
361
362    /**
363     * chmod(const char* path, mode_t mode)
364     */
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    }
373    private static native void chmod0(long pathAddress, int mode)
374        throws UnixException;
375
376    /**
377     * fchmod(int fildes, mode_t mode)
378     */
379    static native void fchmod(int fd, int mode) throws UnixException;
380
381    /**
382     * utimes(conar char* path, const struct timeval times[2])
383     */
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    }
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     */
400    static native void futimes(int fd, long times0, long times1) throws UnixException;
401
402    /**
403     * DIR *opendir(const char* dirname)
404     */
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    }
413    private static native long opendir0(long pathAddress) throws UnixException;
414
415    /**
416     * DIR* fdopendir(int filedes)
417     */
418    static native long fdopendir(int dfd) throws UnixException;
419
420
421    /**
422     * closedir(DIR* dirp)
423     */
424    static native void closedir(long dir) throws UnixException;
425
426    /**
427     * struct dirent* readdir(DIR *dirp)
428     *
429     * @return  dirent->d_name
430     */
431    static native byte[] readdir(long dir) throws UnixException;
432
433    /**
434     * size_t read(int fildes, void* buf, size_t nbyte)
435     */
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     */
441    static native int write(int fildes, long buf, int nbyte) throws UnixException;
442
443    /**
444     * access(const char* path, int amode);
445     */
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    }
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     */
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     */
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     */
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    }
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     */
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    }
498    private static native int getgrnam0(long nameAddress) throws UnixException;
499
500    /**
501     * statvfs(const char* path, struct statvfs *buf)
502     */
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    }
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     */
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    }
527    private static native long pathconf0(long pathAddress, int name)
528        throws UnixException;
529
530    /**
531     * long fpathconf(int fildes, int name);
532     */
533    static native long fpathconf(int filedes, int name) throws UnixException;
534
535    /**
536     * char* strerror(int errnum)
537     */
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     */
551    static boolean openatSupported() {
552        return (capabilities & SUPPORTS_OPENAT) != 0;
553    }
554
555    /**
556     * Supports futimes or futimesat
557     */
558    static boolean futimesSupported() {
559        return (capabilities & SUPPORTS_FUTIMES) != 0;
560    }
561
562    /**
563     * Supports file birth (creation) time attribute
564     */
565    static boolean birthtimeSupported() {
566        return (capabilities & SUPPORTS_BIRTHTIME) != 0;
567    }
568
569    private static native int init();
570    static {
571        // Android-removed: Code to load native libraries, doesn't make sense on Android.
572        /*
573        AccessController.doPrivileged(new PrivilegedAction<Void>() {
574            public Void run() {
575                System.loadLibrary("nio");
576                return null;
577        }});
578        */
579        capabilities = init();
580    }
581}
582