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 private 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 * lutimes(const char* path, const struct timeval times[2]) 423 */ 424 static void lutimes(UnixPath path, long times0, long times1) 425 throws UnixException 426 { 427 NativeBuffer buffer = copyToNativeBuffer(path); 428 try { 429 lutimes0(buffer.address(), times0, times1); 430 } finally { 431 buffer.release(); 432 } 433 } 434 private static native void lutimes0(long pathAddress, long times0, long times1) 435 throws UnixException; 436 437 /** 438 * DIR *opendir(const char* dirname) 439 */ 440 static long opendir(UnixPath path) throws UnixException { 441 NativeBuffer buffer = copyToNativeBuffer(path); 442 try { 443 return opendir0(buffer.address()); 444 } finally { 445 buffer.release(); 446 } 447 } 448 private static native long opendir0(long pathAddress) throws UnixException; 449 450 /** 451 * DIR* fdopendir(int filedes) 452 */ 453 static native long fdopendir(int dfd) throws UnixException; 454 455 456 /** 457 * closedir(DIR* dirp) 458 */ 459 static native void closedir(long dir) throws UnixException; 460 461 /** 462 * struct dirent* readdir(DIR *dirp) 463 * 464 * @return dirent->d_name 465 */ 466 static native byte[] readdir(long dir) throws UnixException; 467 468 /** 469 * size_t read(int fildes, void* buf, size_t nbyte) 470 */ 471 static native int read(int fildes, long buf, int nbyte) throws UnixException; 472 473 /** 474 * size_t writeint fildes, void* buf, size_t nbyte) 475 */ 476 static native int write(int fildes, long buf, int nbyte) throws UnixException; 477 478 /** 479 * access(const char* path, int amode); 480 */ 481 static void access(UnixPath path, int amode) throws UnixException { 482 NativeBuffer buffer = copyToNativeBuffer(path); 483 try { 484 access0(buffer.address(), amode); 485 } finally { 486 buffer.release(); 487 } 488 } 489 private static native void access0(long pathAddress, int amode) throws UnixException; 490 491 /** 492 * access(constant char* path, F_OK) 493 * 494 * @return true if the file exists, false otherwise 495 */ 496 static boolean exists(UnixPath path) { 497 NativeBuffer buffer = copyToNativeBuffer(path); 498 try { 499 return exists0(buffer.address()); 500 } finally { 501 buffer.release(); 502 } 503 } 504 private static native boolean exists0(long pathAddress); 505 506 507 /** 508 * struct passwd *getpwuid(uid_t uid); 509 * 510 * @return passwd->pw_name 511 */ 512 static native byte[] getpwuid(int uid) throws UnixException; 513 514 /** 515 * struct group *getgrgid(gid_t gid); 516 * 517 * @return group->gr_name 518 */ 519 static native byte[] getgrgid(int gid) throws UnixException; 520 521 /** 522 * struct passwd *getpwnam(const char *name); 523 * 524 * @return passwd->pw_uid 525 */ 526 static int getpwnam(String name) throws UnixException { 527 NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name)); 528 try { 529 return getpwnam0(buffer.address()); 530 } finally { 531 buffer.release(); 532 } 533 } 534 private static native int getpwnam0(long nameAddress) throws UnixException; 535 536 /** 537 * struct group *getgrnam(const char *name); 538 * 539 * @return group->gr_name 540 */ 541 static int getgrnam(String name) throws UnixException { 542 NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name)); 543 try { 544 return getgrnam0(buffer.address()); 545 } finally { 546 buffer.release(); 547 } 548 } 549 private static native int getgrnam0(long nameAddress) throws UnixException; 550 551 /** 552 * statvfs(const char* path, struct statvfs *buf) 553 */ 554 static void statvfs(UnixPath path, UnixFileStoreAttributes attrs) 555 throws UnixException 556 { 557 NativeBuffer buffer = copyToNativeBuffer(path); 558 try { 559 statvfs0(buffer.address(), attrs); 560 } finally { 561 buffer.release(); 562 } 563 } 564 private static native void statvfs0(long pathAddress, UnixFileStoreAttributes attrs) 565 throws UnixException; 566 567 /** 568 * long int pathconf(const char *path, int name); 569 */ 570 static long pathconf(UnixPath path, int name) throws UnixException { 571 NativeBuffer buffer = copyToNativeBuffer(path); 572 try { 573 return pathconf0(buffer.address(), name); 574 } finally { 575 buffer.release(); 576 } 577 } 578 private static native long pathconf0(long pathAddress, int name) 579 throws UnixException; 580 581 /** 582 * long fpathconf(int fildes, int name); 583 */ 584 static native long fpathconf(int filedes, int name) throws UnixException; 585 586 /** 587 * char* strerror(int errnum) 588 */ 589 static native byte[] strerror(int errnum); 590 591 /** 592 * Capabilities 593 */ 594 private static final int SUPPORTS_OPENAT = 1 << 1; // syscalls 595 private static final int SUPPORTS_FUTIMES = 1 << 2; 596 private static final int SUPPORTS_LUTIMES = 1 << 4; 597 private static final int SUPPORTS_BIRTHTIME = 1 << 16; // other features 598 private static final int capabilities; 599 600 /** 601 * Supports openat and other *at calls. 602 */ 603 static boolean openatSupported() { 604 return (capabilities & SUPPORTS_OPENAT) != 0; 605 } 606 607 /** 608 * Supports futimes or futimesat 609 */ 610 static boolean futimesSupported() { 611 return (capabilities & SUPPORTS_FUTIMES) != 0; 612 } 613 614 /** 615 * Supports lutimes 616 */ 617 static boolean lutimesSupported() { 618 return (capabilities & SUPPORTS_LUTIMES) != 0; 619 } 620 621 /** 622 * Supports file birth (creation) time attribute 623 */ 624 static boolean birthtimeSupported() { 625 return (capabilities & SUPPORTS_BIRTHTIME) != 0; 626 } 627 628 private static native int init(); 629 static { 630 jdk.internal.loader.BootLoader.loadLibrary("nio"); 631 capabilities = init(); 632 } 633 }