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     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      * void rewind(FILE* stream);
 121      */
 122     static native void rewind(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      * lstat(const char* path, struct stat* buf)
 301      */
 302     static void lstat(UnixPath path, UnixFileAttributes attrs) throws UnixException {
 303         NativeBuffer buffer = copyToNativeBuffer(path);
 304         try {
 305             lstat0(buffer.address(), attrs);
 306         } finally {
 307             buffer.release();
 308         }
 309     }
 310     private static native void lstat0(long pathAddress, UnixFileAttributes attrs)
 311         throws UnixException;
 312 
 313     /**
 314      * fstat(int filedes, struct stat* buf)
 315      */
 316     static native void fstat(int fd, UnixFileAttributes attrs) throws UnixException;
 317 
 318     /**
 319      * fstatat(int filedes,const char* path,  struct stat* buf, int flag)
 320      */
 321     static void fstatat(int dfd, byte[] path, int flag, UnixFileAttributes attrs)
 322         throws UnixException
 323     {
 324         NativeBuffer buffer = NativeBuffers.asNativeBuffer(path);
 325         try {
 326             fstatat0(dfd, buffer.address(), flag, attrs);
 327         } finally {
 328             buffer.release();
 329         }
 330     }
 331     private static native void fstatat0(int dfd, long pathAddress, int flag,
 332         UnixFileAttributes attrs) throws UnixException;
 333 
 334     /**
 335      * chown(const char* path, uid_t owner, gid_t group)
 336      */
 337     static void chown(UnixPath path, int uid, int gid) throws UnixException {
 338         NativeBuffer buffer = copyToNativeBuffer(path);
 339         try {
 340             chown0(buffer.address(), uid, gid);
 341         } finally {
 342             buffer.release();
 343         }
 344     }
 345     private static native void chown0(long pathAddress, int uid, int gid)
 346         throws UnixException;
 347 
 348     /**
 349      * lchown(const char* path, uid_t owner, gid_t group)
 350      */
 351     static void lchown(UnixPath path, int uid, int gid) throws UnixException {
 352         NativeBuffer buffer = copyToNativeBuffer(path);
 353         try {
 354             lchown0(buffer.address(), uid, gid);
 355         } finally {
 356             buffer.release();
 357         }
 358     }
 359     private static native void lchown0(long pathAddress, int uid, int gid)
 360         throws UnixException;
 361 
 362     /**
 363      * fchown(int filedes, uid_t owner, gid_t group)
 364      */
 365     static native void fchown(int fd, int uid, int gid) throws UnixException;
 366 
 367     /**
 368      * chmod(const char* path, mode_t mode)
 369      */
 370     static void chmod(UnixPath path, int mode) throws UnixException {
 371         NativeBuffer buffer = copyToNativeBuffer(path);
 372         try {
 373             chmod0(buffer.address(), mode);
 374         } finally {
 375             buffer.release();
 376         }
 377     }
 378     private static native void chmod0(long pathAddress, int mode)
 379         throws UnixException;
 380 
 381     /**
 382      * fchmod(int fildes, mode_t mode)
 383      */
 384     static native void fchmod(int fd, int mode) throws UnixException;
 385 
 386     /**
 387      * utimes(conar char* path, const struct timeval times[2])
 388      */
 389     static void utimes(UnixPath path, long times0, long times1)
 390         throws UnixException
 391     {
 392         NativeBuffer buffer = copyToNativeBuffer(path);
 393         try {
 394             utimes0(buffer.address(), times0, times1);
 395         } finally {
 396             buffer.release();
 397         }
 398     }
 399     private static native void utimes0(long pathAddress, long times0, long times1)
 400         throws UnixException;
 401 
 402     /**
 403      * futimes(int fildes,, const struct timeval times[2])
 404      */
 405     static native void futimes(int fd, long times0, long times1) throws UnixException;
 406 
 407     /**
 408      * DIR *opendir(const char* dirname)
 409      */
 410     static long opendir(UnixPath path) throws UnixException {
 411         NativeBuffer buffer = copyToNativeBuffer(path);
 412         try {
 413             return opendir0(buffer.address());
 414         } finally {
 415             buffer.release();
 416         }
 417     }
 418     private static native long opendir0(long pathAddress) throws UnixException;
 419 
 420     /**
 421      * DIR* fdopendir(int filedes)
 422      */
 423     static native long fdopendir(int dfd) throws UnixException;
 424 
 425 
 426     /**
 427      * closedir(DIR* dirp)
 428      */
 429     static native void closedir(long dir) throws UnixException;
 430 
 431     /**
 432      * struct dirent* readdir(DIR *dirp)
 433      *
 434      * @return  dirent->d_name
 435      */
 436     static native byte[] readdir(long dir) throws UnixException;
 437 
 438     /**
 439      * size_t read(int fildes, void* buf, size_t nbyte)
 440      */
 441     static native int read(int fildes, long buf, int nbyte) throws UnixException;
 442 
 443     /**
 444      * size_t writeint fildes, void* buf, size_t nbyte)
 445      */
 446     static native int write(int fildes, long buf, int nbyte) throws UnixException;
 447 
 448     /**
 449      * access(const char* path, int amode);
 450      */
 451     static void access(UnixPath path, int amode) throws UnixException {
 452         NativeBuffer buffer = copyToNativeBuffer(path);
 453         try {
 454             access0(buffer.address(), amode);
 455         } finally {
 456             buffer.release();
 457         }
 458     }
 459     private static native void access0(long pathAddress, int amode) throws UnixException;
 460 
 461     /**
 462      * struct passwd *getpwuid(uid_t uid);
 463      *
 464      * @return  passwd->pw_name
 465      */
 466     static native byte[] getpwuid(int uid) throws UnixException;
 467 
 468     /**
 469      * struct group *getgrgid(gid_t gid);
 470      *
 471      * @return  group->gr_name
 472      */
 473     static native byte[] getgrgid(int gid) throws UnixException;
 474 
 475     /**
 476      * struct passwd *getpwnam(const char *name);
 477      *
 478      * @return  passwd->pw_uid
 479      */
 480     static int getpwnam(String name) throws UnixException {
 481         NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name));
 482         try {
 483             return getpwnam0(buffer.address());
 484         } finally {
 485             buffer.release();
 486         }
 487     }
 488     private static native int getpwnam0(long nameAddress) throws UnixException;
 489 
 490     /**
 491      * struct group *getgrnam(const char *name);
 492      *
 493      * @return  group->gr_name
 494      */
 495     static int getgrnam(String name) throws UnixException {
 496         NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name));
 497         try {
 498             return getgrnam0(buffer.address());
 499         } finally {
 500             buffer.release();
 501         }
 502     }
 503     private static native int getgrnam0(long nameAddress) throws UnixException;
 504 
 505     /**
 506      * statvfs(const char* path, struct statvfs *buf)
 507      */
 508     static void statvfs(UnixPath path, UnixFileStoreAttributes attrs)
 509         throws UnixException
 510     {
 511         NativeBuffer buffer = copyToNativeBuffer(path);
 512         try {
 513             statvfs0(buffer.address(), attrs);
 514         } finally {
 515             buffer.release();
 516         }
 517     }
 518     private static native void statvfs0(long pathAddress, UnixFileStoreAttributes attrs)
 519         throws UnixException;
 520 
 521     /**
 522      * long int pathconf(const char *path, int name);
 523      */
 524     static long pathconf(UnixPath path, int name) throws UnixException {
 525         NativeBuffer buffer = copyToNativeBuffer(path);
 526         try {
 527             return pathconf0(buffer.address(), name);
 528         } finally {
 529             buffer.release();
 530         }
 531     }
 532     private static native long pathconf0(long pathAddress, int name)
 533         throws UnixException;
 534 
 535     /**
 536      * long fpathconf(int fildes, int name);
 537      */
 538     static native long fpathconf(int filedes, int name) throws UnixException;
 539 
 540     /**
 541      * char* strerror(int errnum)
 542      */
 543     static native byte[] strerror(int errnum);
 544 
 545     /**
 546      * Capabilities
 547      */
 548     private static final int SUPPORTS_OPENAT        = 1 << 1;    // syscalls
 549     private static final int SUPPORTS_FUTIMES       = 1 << 2;
 550     private static final int SUPPORTS_BIRTHTIME     = 1 << 16;   // other features
 551     private static final int capabilities;
 552 
 553     /**
 554      * Supports openat and other *at calls.
 555      */
 556     static boolean openatSupported() {
 557         return (capabilities & SUPPORTS_OPENAT) != 0;
 558     }
 559 
 560     /**
 561      * Supports futimes or futimesat
 562      */
 563     static boolean futimesSupported() {
 564         return (capabilities & SUPPORTS_FUTIMES) != 0;
 565     }
 566 
 567     /**
 568      * Supports file birth (creation) time attribute
 569      */
 570     static boolean birthtimeSupported() {
 571         return (capabilities & SUPPORTS_BIRTHTIME) != 0;
 572     }
 573 
 574     private static native int init();
 575     static {
 576         AccessController.doPrivileged(new PrivilegedAction<Void>() {
 577             public Void run() {
 578                 System.loadLibrary("nio");
 579                 return null;
 580         }});
 581         capabilities = init();
 582     }
 583 }