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 }