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 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 }