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         AccessController.doPrivileged(new PrivilegedAction<Void>() {
 572             public Void run() {
 573                 System.loadLibrary("nio");
 574                 return null;
 575         }});
 576         capabilities = init();
 577     }
 578 }