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