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