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 { UnixNativeDispatcher()36 protected UnixNativeDispatcher() { } 37 38 // returns a NativeBuffer containing the given path copyToNativeBuffer(UnixPath 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 */ getcwd()58 static native byte[] getcwd(); 59 60 /** 61 * int dup(int filedes) 62 */ dup(int filedes)63 static native int dup(int filedes) throws UnixException; 64 65 /** 66 * int open(const char* path, int oflag, mode_t mode) 67 */ open(UnixPath path, int flags, int mode)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 } open0(long pathAddress, int flags, int mode)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 */ openat(int dfd, byte[] path, int flags, int mode)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 } openat0(int dfd, long pathAddress, int flags, int mode)90 private static native int openat0(int dfd, long pathAddress, int flags, int mode) 91 throws UnixException; 92 93 /** 94 * close(int filedes) 95 */ close(int fd)96 static native void close(int fd); 97 98 /** 99 * FILE* fopen(const char *filename, const char* mode); 100 */ fopen(UnixPath filename, String mode)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 } fopen0(long pathAddress, long modeAddress)111 private static native long fopen0(long pathAddress, long modeAddress) 112 throws UnixException; 113 114 /** 115 * fclose(FILE* stream) 116 */ fclose(long stream)117 static native void fclose(long stream) throws UnixException; 118 119 /** 120 * link(const char* existing, const char* new) 121 */ link(UnixPath existing, UnixPath newfile)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 } link0(long existingAddress, long newAddress)132 private static native void link0(long existingAddress, long newAddress) 133 throws UnixException; 134 135 /** 136 * unlink(const char* path) 137 */ unlink(UnixPath path)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 } unlink0(long pathAddress)146 private static native void unlink0(long pathAddress) throws UnixException; 147 148 /** 149 * unlinkat(int dfd, const char* path, int flag) 150 */ unlinkat(int dfd, byte[] path, int flag)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 } unlinkat0(int dfd, long pathAddress, int flag)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 */ mknod(UnixPath path, int mode, long dev)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 } mknod0(long pathAddress, int mode, long dev)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 */ rename(UnixPath from, UnixPath to)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 } rename0(long fromAddress, long toAddress)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 */ renameat(int fromfd, byte[] from, int tofd, byte[] to)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 } renameat0(int fromfd, long fromAddress, int tofd, long toAddress)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 */ mkdir(UnixPath path, int mode)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 } mkdir0(long pathAddress, int mode)219 private static native void mkdir0(long pathAddress, int mode) throws UnixException; 220 221 /** 222 * rmdir(const char* path) 223 */ rmdir(UnixPath path)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 } rmdir0(long pathAddress)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 */ readlink(UnixPath path)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 } readlink0(long pathAddress)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 */ realpath(UnixPath path)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 } realpath0(long pathAddress)262 private static native byte[] realpath0(long pathAddress) throws UnixException; 263 264 /** 265 * symlink(const char* name1, const char* name2) 266 */ symlink(byte[] name1, UnixPath name2)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 } symlink0(long name1, long name2)277 private static native void symlink0(long name1, long name2) 278 throws UnixException; 279 280 /** 281 * stat(const char* path, struct stat* buf) 282 */ stat(UnixPath path, UnixFileAttributes attrs)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 } stat0(long pathAddress, UnixFileAttributes attrs)291 private static native void stat0(long pathAddress, UnixFileAttributes attrs) 292 throws UnixException; 293 294 295 /** 296 * stat(const char* path, struct stat* buf) 297 * 298 * @return st_mode (file type and mode) or 0 if an error occurs. 299 */ stat(UnixPath path)300 static int stat(UnixPath path) { 301 NativeBuffer buffer = copyToNativeBuffer(path); 302 try { 303 return stat1(buffer.address()); 304 } finally { 305 buffer.release(); 306 } 307 } stat1(long pathAddress)308 private static native int stat1(long pathAddress); 309 310 311 /** 312 * lstat(const char* path, struct stat* buf) 313 */ lstat(UnixPath path, UnixFileAttributes attrs)314 static void lstat(UnixPath path, UnixFileAttributes attrs) throws UnixException { 315 NativeBuffer buffer = copyToNativeBuffer(path); 316 try { 317 lstat0(buffer.address(), attrs); 318 } finally { 319 buffer.release(); 320 } 321 } lstat0(long pathAddress, UnixFileAttributes attrs)322 private static native void lstat0(long pathAddress, UnixFileAttributes attrs) 323 throws UnixException; 324 325 /** 326 * fstat(int filedes, struct stat* buf) 327 */ fstat(int fd, UnixFileAttributes attrs)328 static native void fstat(int fd, UnixFileAttributes attrs) throws UnixException; 329 330 /** 331 * fstatat(int filedes,const char* path, struct stat* buf, int flag) 332 */ fstatat(int dfd, byte[] path, int flag, UnixFileAttributes attrs)333 static void fstatat(int dfd, byte[] path, int flag, UnixFileAttributes attrs) 334 throws UnixException 335 { 336 NativeBuffer buffer = NativeBuffers.asNativeBuffer(path); 337 try { 338 fstatat0(dfd, buffer.address(), flag, attrs); 339 } finally { 340 buffer.release(); 341 } 342 } fstatat0(int dfd, long pathAddress, int flag, UnixFileAttributes attrs)343 private static native void fstatat0(int dfd, long pathAddress, int flag, 344 UnixFileAttributes attrs) throws UnixException; 345 346 /** 347 * chown(const char* path, uid_t owner, gid_t group) 348 */ chown(UnixPath path, int uid, int gid)349 static void chown(UnixPath path, int uid, int gid) throws UnixException { 350 NativeBuffer buffer = copyToNativeBuffer(path); 351 try { 352 chown0(buffer.address(), uid, gid); 353 } finally { 354 buffer.release(); 355 } 356 } chown0(long pathAddress, int uid, int gid)357 private static native void chown0(long pathAddress, int uid, int gid) 358 throws UnixException; 359 360 /** 361 * lchown(const char* path, uid_t owner, gid_t group) 362 */ lchown(UnixPath path, int uid, int gid)363 static void lchown(UnixPath path, int uid, int gid) throws UnixException { 364 NativeBuffer buffer = copyToNativeBuffer(path); 365 try { 366 lchown0(buffer.address(), uid, gid); 367 } finally { 368 buffer.release(); 369 } 370 } lchown0(long pathAddress, int uid, int gid)371 private static native void lchown0(long pathAddress, int uid, int gid) 372 throws UnixException; 373 374 /** 375 * fchown(int filedes, uid_t owner, gid_t group) 376 */ fchown(int fd, int uid, int gid)377 static native void fchown(int fd, int uid, int gid) throws UnixException; 378 379 /** 380 * chmod(const char* path, mode_t mode) 381 */ chmod(UnixPath path, int mode)382 static void chmod(UnixPath path, int mode) throws UnixException { 383 NativeBuffer buffer = copyToNativeBuffer(path); 384 try { 385 chmod0(buffer.address(), mode); 386 } finally { 387 buffer.release(); 388 } 389 } chmod0(long pathAddress, int mode)390 private static native void chmod0(long pathAddress, int mode) 391 throws UnixException; 392 393 /** 394 * fchmod(int fildes, mode_t mode) 395 */ fchmod(int fd, int mode)396 static native void fchmod(int fd, int mode) throws UnixException; 397 398 /** 399 * utimes(conar char* path, const struct timeval times[2]) 400 */ utimes(UnixPath path, long times0, long times1)401 static void utimes(UnixPath path, long times0, long times1) 402 throws UnixException 403 { 404 NativeBuffer buffer = copyToNativeBuffer(path); 405 try { 406 utimes0(buffer.address(), times0, times1); 407 } finally { 408 buffer.release(); 409 } 410 } utimes0(long pathAddress, long times0, long times1)411 private static native void utimes0(long pathAddress, long times0, long times1) 412 throws UnixException; 413 414 /** 415 * futimes(int fildes,, const struct timeval times[2]) 416 */ futimes(int fd, long times0, long times1)417 static native void futimes(int fd, long times0, long times1) throws UnixException; 418 419 /** 420 * DIR *opendir(const char* dirname) 421 */ opendir(UnixPath path)422 static long opendir(UnixPath path) throws UnixException { 423 NativeBuffer buffer = copyToNativeBuffer(path); 424 try { 425 return opendir0(buffer.address()); 426 } finally { 427 buffer.release(); 428 } 429 } opendir0(long pathAddress)430 private static native long opendir0(long pathAddress) throws UnixException; 431 432 /** 433 * DIR* fdopendir(int filedes) 434 */ fdopendir(int dfd)435 static native long fdopendir(int dfd) throws UnixException; 436 437 438 /** 439 * closedir(DIR* dirp) 440 */ closedir(long dir)441 static native void closedir(long dir) throws UnixException; 442 443 /** 444 * struct dirent* readdir(DIR *dirp) 445 * 446 * @return dirent->d_name 447 */ readdir(long dir)448 static native byte[] readdir(long dir) throws UnixException; 449 450 /** 451 * size_t read(int fildes, void* buf, size_t nbyte) 452 */ read(int fildes, long buf, int nbyte)453 static native int read(int fildes, long buf, int nbyte) throws UnixException; 454 455 /** 456 * size_t writeint fildes, void* buf, size_t nbyte) 457 */ write(int fildes, long buf, int nbyte)458 static native int write(int fildes, long buf, int nbyte) throws UnixException; 459 460 /** 461 * access(const char* path, int amode); 462 */ access(UnixPath path, int amode)463 static void access(UnixPath path, int amode) throws UnixException { 464 NativeBuffer buffer = copyToNativeBuffer(path); 465 try { 466 access0(buffer.address(), amode); 467 } finally { 468 buffer.release(); 469 } 470 } access0(long pathAddress, int amode)471 private static native void access0(long pathAddress, int amode) throws UnixException; 472 473 /** 474 * access(constant char* path, F_OK) 475 * 476 * @return true if the file exists, false otherwise 477 */ exists(UnixPath path)478 static boolean exists(UnixPath path) { 479 NativeBuffer buffer = copyToNativeBuffer(path); 480 try { 481 return exists0(buffer.address()); 482 } finally { 483 buffer.release(); 484 } 485 } exists0(long pathAddress)486 private static native boolean exists0(long pathAddress); 487 488 489 /** 490 * struct passwd *getpwuid(uid_t uid); 491 * 492 * @return passwd->pw_name 493 */ getpwuid(int uid)494 static native byte[] getpwuid(int uid) throws UnixException; 495 496 /** 497 * struct group *getgrgid(gid_t gid); 498 * 499 * @return group->gr_name 500 */ getgrgid(int gid)501 static native byte[] getgrgid(int gid) throws UnixException; 502 503 /** 504 * struct passwd *getpwnam(const char *name); 505 * 506 * @return passwd->pw_uid 507 */ getpwnam(String name)508 static int getpwnam(String name) throws UnixException { 509 NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name)); 510 try { 511 return getpwnam0(buffer.address()); 512 } finally { 513 buffer.release(); 514 } 515 } getpwnam0(long nameAddress)516 private static native int getpwnam0(long nameAddress) throws UnixException; 517 518 /** 519 * struct group *getgrnam(const char *name); 520 * 521 * @return group->gr_name 522 */ getgrnam(String name)523 static int getgrnam(String name) throws UnixException { 524 NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name)); 525 try { 526 return getgrnam0(buffer.address()); 527 } finally { 528 buffer.release(); 529 } 530 } getgrnam0(long nameAddress)531 private static native int getgrnam0(long nameAddress) throws UnixException; 532 533 /** 534 * statvfs(const char* path, struct statvfs *buf) 535 */ statvfs(UnixPath path, UnixFileStoreAttributes attrs)536 static void statvfs(UnixPath path, UnixFileStoreAttributes attrs) 537 throws UnixException 538 { 539 NativeBuffer buffer = copyToNativeBuffer(path); 540 try { 541 statvfs0(buffer.address(), attrs); 542 } finally { 543 buffer.release(); 544 } 545 } statvfs0(long pathAddress, UnixFileStoreAttributes attrs)546 private static native void statvfs0(long pathAddress, UnixFileStoreAttributes attrs) 547 throws UnixException; 548 549 /** 550 * long int pathconf(const char *path, int name); 551 */ pathconf(UnixPath path, int name)552 static long pathconf(UnixPath path, int name) throws UnixException { 553 NativeBuffer buffer = copyToNativeBuffer(path); 554 try { 555 return pathconf0(buffer.address(), name); 556 } finally { 557 buffer.release(); 558 } 559 } pathconf0(long pathAddress, int name)560 private static native long pathconf0(long pathAddress, int name) 561 throws UnixException; 562 563 /** 564 * long fpathconf(int fildes, int name); 565 */ fpathconf(int filedes, int name)566 static native long fpathconf(int filedes, int name) throws UnixException; 567 568 /** 569 * char* strerror(int errnum) 570 */ strerror(int errnum)571 static native byte[] strerror(int errnum); 572 573 /** 574 * Capabilities 575 */ 576 private static final int SUPPORTS_OPENAT = 1 << 1; // syscalls 577 private static final int SUPPORTS_FUTIMES = 1 << 2; 578 private static final int SUPPORTS_BIRTHTIME = 1 << 16; // other features 579 private static final int capabilities; 580 581 /** 582 * Supports openat and other *at calls. 583 */ openatSupported()584 static boolean openatSupported() { 585 return (capabilities & SUPPORTS_OPENAT) != 0; 586 } 587 588 /** 589 * Supports futimes or futimesat 590 */ futimesSupported()591 static boolean futimesSupported() { 592 return (capabilities & SUPPORTS_FUTIMES) != 0; 593 } 594 595 /** 596 * Supports file birth (creation) time attribute 597 */ birthtimeSupported()598 static boolean birthtimeSupported() { 599 return (capabilities & SUPPORTS_BIRTHTIME) != 0; 600 } 601 init()602 private static native int init(); 603 static { 604 // Android-removed: Code to load native libraries, doesn't make sense on Android. 605 /* 606 AccessController.doPrivileged(new PrivilegedAction<Void>() { 607 public Void run() { 608 System.loadLibrary("nio"); 609 return null; 610 }}); 611 */ 612 capabilities = init(); 613 } 614 } 615