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