Home | History | Annotate | Download | only in fs
      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 {
     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