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 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). 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(const 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      * lutimes(const char* path, const struct timeval times[2])
 426      */
 427     static void lutimes(UnixPath path, long times0, long times1)
 428         throws UnixException
 429     {
 430         NativeBuffer buffer = copyToNativeBuffer(path);
 431         try {
 432             lutimes0(buffer.address(), times0, times1);
 433         } finally {
 434             buffer.release();
 435         }
 436     }
 437     private static native void lutimes0(long pathAddress, long times0, long times1)
 438         throws UnixException;
 439 
 440     /**
 441      * DIR *opendir(const char* dirname)
 442      */
 443     static long opendir(UnixPath path) throws UnixException {
 444         NativeBuffer buffer = copyToNativeBuffer(path);
 445         try {
 446             return opendir0(buffer.address());
 447         } finally {
 448             buffer.release();
 449         }
 450     }
 451     private static native long opendir0(long pathAddress) throws UnixException;
 452 
 453     /**
 454      * DIR* fdopendir(int filedes)
 455      */
 456     static native long fdopendir(int dfd) throws UnixException;
 457 
 458 
 459     /**
 460      * closedir(DIR* dirp)
 461      */
 462     static native void closedir(long dir) throws UnixException;
 463 
 464     /**
 465      * struct dirent* readdir(DIR *dirp)
 466      *
 467      * @return  dirent->d_name
 468      */
 469     static native byte[] readdir(long dir) throws UnixException;
 470 
 471     /**
 472      * size_t read(int fildes, void* buf, size_t nbyte)
 473      */
 474     static native int read(int fildes, long buf, int nbyte) throws UnixException;
 475 
 476     /**
 477      * size_t writeint fildes, void* buf, size_t nbyte)
 478      */
 479     static native int write(int fildes, long buf, int nbyte) throws UnixException;
 480 
 481     /**
 482      * access(const char* path, int amode);
 483      */
 484     static void access(UnixPath path, int amode) throws UnixException {
 485         NativeBuffer buffer = copyToNativeBuffer(path);
 486         try {
 487             access0(buffer.address(), amode);
 488         } finally {
 489             buffer.release();
 490         }
 491     }
 492     private static native void access0(long pathAddress, int amode) throws UnixException;
 493 
 494     /**
 495      * access(constant char* path, F_OK)
 496      *
 497      * @return true if the file exists, false otherwise
 498      */
 499     static boolean exists(UnixPath path) {
 500         NativeBuffer buffer = copyToNativeBuffer(path);
 501         try {
 502             return exists0(buffer.address());
 503         } finally {
 504             buffer.release();
 505         }
 506     }
 507     private static native boolean exists0(long pathAddress);
 508 
 509 
 510     /**
 511      * struct passwd *getpwuid(uid_t uid);
 512      *
 513      * @return  passwd->pw_name
 514      */
 515     static native byte[] getpwuid(int uid) throws UnixException;
 516 
 517     /**
 518      * struct group *getgrgid(gid_t gid);
 519      *
 520      * @return  group->gr_name
 521      */
 522     static native byte[] getgrgid(int gid) throws UnixException;
 523 
 524     /**
 525      * struct passwd *getpwnam(const char *name);
 526      *
 527      * @return  passwd->pw_uid
 528      */
 529     static int getpwnam(String name) throws UnixException {
 530         NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name));
 531         try {
 532             return getpwnam0(buffer.address());
 533         } finally {
 534             buffer.release();
 535         }
 536     }
 537     private static native int getpwnam0(long nameAddress) throws UnixException;
 538 
 539     /**
 540      * struct group *getgrnam(const char *name);
 541      *
 542      * @return  group->gr_name
 543      */
 544     static int getgrnam(String name) throws UnixException {
 545         NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name));
 546         try {
 547             return getgrnam0(buffer.address());
 548         } finally {
 549             buffer.release();
 550         }
 551     }
 552     private static native int getgrnam0(long nameAddress) throws UnixException;
 553 
 554     /**
 555      * statvfs(const char* path, struct statvfs *buf)
 556      */
 557     static void statvfs(UnixPath path, UnixFileStoreAttributes attrs)
 558         throws UnixException
 559     {
 560         NativeBuffer buffer = copyToNativeBuffer(path);
 561         try {
 562             statvfs0(buffer.address(), attrs);
 563         } finally {
 564             buffer.release();
 565         }
 566     }
 567     private static native void statvfs0(long pathAddress, UnixFileStoreAttributes attrs)
 568         throws UnixException;
 569 
 570     /**
 571      * long int pathconf(const char *path, int name);
 572      */
 573     static long pathconf(UnixPath path, int name) throws UnixException {
 574         NativeBuffer buffer = copyToNativeBuffer(path);
 575         try {
 576             return pathconf0(buffer.address(), name);
 577         } finally {
 578             buffer.release();
 579         }
 580     }
 581     private static native long pathconf0(long pathAddress, int name)
 582         throws UnixException;
 583 
 584     /**
 585      * long fpathconf(int fildes, int name);
 586      */
 587     static native long fpathconf(int filedes, int name) throws UnixException;
 588 
 589     /**
 590      * char* strerror(int errnum)
 591      */
 592     static native byte[] strerror(int errnum);
 593 
 594     /**
 595      * Capabilities
 596      */
 597     private static final int SUPPORTS_OPENAT        = 1 << 1;  // syscalls
 598     private static final int SUPPORTS_FUTIMES       = 1 << 2;
 599     private static final int SUPPORTS_LUTIMES       = 1 << 4;
 600     private static final int SUPPORTS_BIRTHTIME     = 1 << 16; // other features
 601     private static final int capabilities;
 602 
 603     /**
 604      * Supports openat and other *at calls.
 605      */
 606     static boolean openatSupported() {
 607         return (capabilities & SUPPORTS_OPENAT) != 0;
 608     }
 609 
 610     /**
 611      * Supports futimes or futimesat
 612      */
 613     static boolean futimesSupported() {
 614         return (capabilities & SUPPORTS_FUTIMES) != 0;
 615     }
 616 
 617     /**
 618      * Supports lutimes
 619      */
 620     static boolean lutimesSupported() {
 621         return (capabilities & SUPPORTS_LUTIMES) != 0;
 622     }
 623 
 624     /**
 625      * Supports file birth (creation) time attribute
 626      */
 627     static boolean birthtimeSupported() {
 628         return (capabilities & SUPPORTS_BIRTHTIME) != 0;
 629     }
 630 
 631     private static native int init();
 632     static {
 633         AccessController.doPrivileged(new PrivilegedAction<>() {
 634             public Void run() {
 635                 System.loadLibrary("nio");
 636                 return null;
 637         }});
 638         capabilities = init();
 639     }
 640 }