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 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 */ 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). If fd is -1 this is a no-op. 95 */ 96 static void close(int fd) { 97 if (fd != -1) { 98 close0(fd); 99 } 100 } 101 private static native void close0(int fd); 102 103 /** 104 * FILE* fopen(const char *filename, const char* mode); 105 */ 106 static long fopen(UnixPath filename, String mode) throws UnixException { 107 NativeBuffer pathBuffer = copyToNativeBuffer(filename); 108 NativeBuffer modeBuffer = NativeBuffers.asNativeBuffer(Util.toBytes(mode)); 109 try { 110 return fopen0(pathBuffer.address(), modeBuffer.address()); 111 } finally { 112 modeBuffer.release(); 113 pathBuffer.release(); 114 } 115 } 116 private static native long fopen0(long pathAddress, long modeAddress) 117 throws UnixException; 118 119 /** 120 * fclose(FILE* stream) 121 */ 122 static native void fclose(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 /** 301 * stat(const char* path, struct stat* buf) 302 * 303 * @return st_mode (file type and mode) or 0 if an error occurs. 304 */ 305 static int stat(UnixPath path) { 306 NativeBuffer buffer = copyToNativeBuffer(path); 307 try { 308 return stat1(buffer.address()); 309 } finally { 310 buffer.release(); 311 } 312 } 313 private static native int stat1(long pathAddress); 314 315 316 /** 317 * lstat(const char* path, struct stat* buf) 318 */ 319 static void lstat(UnixPath path, UnixFileAttributes attrs) throws UnixException { 320 NativeBuffer buffer = copyToNativeBuffer(path); 321 try { 322 lstat0(buffer.address(), attrs); 323 } finally { 324 buffer.release(); 325 } 326 } 327 private static native void lstat0(long pathAddress, UnixFileAttributes attrs) 328 throws UnixException; 329 330 /** 331 * fstat(int filedes, struct stat* buf) 332 */ 333 static native void fstat(int fd, UnixFileAttributes attrs) throws UnixException; 334 335 /** 336 * fstatat(int filedes,const char* path, struct stat* buf, int flag) 337 */ 338 static void fstatat(int dfd, byte[] path, int flag, UnixFileAttributes attrs) 339 throws UnixException 340 { 341 NativeBuffer buffer = NativeBuffers.asNativeBuffer(path); 342 try { 343 fstatat0(dfd, buffer.address(), flag, attrs); 344 } finally { 345 buffer.release(); 346 } 347 } 348 private static native void fstatat0(int dfd, long pathAddress, int flag, 349 UnixFileAttributes attrs) throws UnixException; 350 351 /** 352 * chown(const char* path, uid_t owner, gid_t group) 353 */ 354 static void chown(UnixPath path, int uid, int gid) throws UnixException { 355 NativeBuffer buffer = copyToNativeBuffer(path); 356 try { 357 chown0(buffer.address(), uid, gid); 358 } finally { 359 buffer.release(); 360 } 361 } 362 private static native void chown0(long pathAddress, int uid, int gid) 363 throws UnixException; 364 365 /** 366 * lchown(const char* path, uid_t owner, gid_t group) 367 */ 368 static void lchown(UnixPath path, int uid, int gid) throws UnixException { 369 NativeBuffer buffer = copyToNativeBuffer(path); 370 try { 371 lchown0(buffer.address(), uid, gid); 372 } finally { 373 buffer.release(); 374 } 375 } 376 private static native void lchown0(long pathAddress, int uid, int gid) 377 throws UnixException; 378 379 /** 380 * fchown(int filedes, uid_t owner, gid_t group) 381 */ 382 static native void fchown(int fd, int uid, int gid) throws UnixException; 383 384 /** 385 * chmod(const char* path, mode_t mode) 386 */ 387 static void chmod(UnixPath path, int mode) throws UnixException { 388 NativeBuffer buffer = copyToNativeBuffer(path); 389 try { 390 chmod0(buffer.address(), mode); 391 } finally { 392 buffer.release(); 393 } 394 } 395 private static native void chmod0(long pathAddress, int mode) 396 throws UnixException; 397 398 /** 399 * fchmod(int fildes, mode_t mode) 400 */ 401 static native void fchmod(int fd, int mode) throws UnixException; 402 403 /** 404 * utimes(const char* path, const struct timeval times[2]) 405 */ 406 static void utimes(UnixPath path, long times0, long times1) 407 throws UnixException 408 { 409 NativeBuffer buffer = copyToNativeBuffer(path); 410 try { 411 utimes0(buffer.address(), times0, times1); 412 } finally { 413 buffer.release(); 414 } 415 } 416 private static native void utimes0(long pathAddress, long times0, long times1) 417 throws UnixException; 418 419 /** 420 * futimes(int fildes, const struct timeval times[2]) 421 */ 422 static native void futimes(int fd, long times0, long times1) throws UnixException; 423 424 /** 425 * lutimes(const char* path, const struct timeval times[2]) 426 */ 427 static void lutimes(UnixPath path, long times0, long times1) 428 throws UnixException 429 { 430 NativeBuffer buffer = copyToNativeBuffer(path); 431 try { 432 lutimes0(buffer.address(), times0, times1); 433 } finally { 434 buffer.release(); 435 } 436 } 437 private static native void lutimes0(long pathAddress, long times0, long times1) 438 throws UnixException; 439 440 /** 441 * DIR *opendir(const char* dirname) 442 */ 443 static long opendir(UnixPath path) throws UnixException { 444 NativeBuffer buffer = copyToNativeBuffer(path); 445 try { 446 return opendir0(buffer.address()); 447 } finally { 448 buffer.release(); 449 } 450 } 451 private static native long opendir0(long pathAddress) throws UnixException; 452 453 /** 454 * DIR* fdopendir(int filedes) 455 */ 456 static native long fdopendir(int dfd) throws UnixException; 457 458 459 /** 460 * closedir(DIR* dirp) 461 */ 462 static native void closedir(long dir) throws UnixException; 463 464 /** 465 * struct dirent* readdir(DIR *dirp) 466 * 467 * @return dirent->d_name 468 */ 469 static native byte[] readdir(long dir) throws UnixException; 470 471 /** 472 * size_t read(int fildes, void* buf, size_t nbyte) 473 */ 474 static native int read(int fildes, long buf, int nbyte) throws UnixException; 475 476 /** 477 * size_t writeint fildes, void* buf, size_t nbyte) 478 */ 479 static native int write(int fildes, long buf, int nbyte) throws UnixException; 480 481 /** 482 * access(const char* path, int amode); 483 */ 484 static void access(UnixPath path, int amode) throws UnixException { 485 NativeBuffer buffer = copyToNativeBuffer(path); 486 try { 487 access0(buffer.address(), amode); 488 } finally { 489 buffer.release(); 490 } 491 } 492 private static native void access0(long pathAddress, int amode) throws UnixException; 493 494 /** 495 * access(constant char* path, F_OK) 496 * 497 * @return true if the file exists, false otherwise 498 */ 499 static boolean exists(UnixPath path) { 500 NativeBuffer buffer = copyToNativeBuffer(path); 501 try { 502 return exists0(buffer.address()); 503 } finally { 504 buffer.release(); 505 } 506 } 507 private static native boolean exists0(long pathAddress); 508 509 510 /** 511 * struct passwd *getpwuid(uid_t uid); 512 * 513 * @return passwd->pw_name 514 */ 515 static native byte[] getpwuid(int uid) throws UnixException; 516 517 /** 518 * struct group *getgrgid(gid_t gid); 519 * 520 * @return group->gr_name 521 */ 522 static native byte[] getgrgid(int gid) throws UnixException; 523 524 /** 525 * struct passwd *getpwnam(const char *name); 526 * 527 * @return passwd->pw_uid 528 */ 529 static int getpwnam(String name) throws UnixException { 530 NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name)); 531 try { 532 return getpwnam0(buffer.address()); 533 } finally { 534 buffer.release(); 535 } 536 } 537 private static native int getpwnam0(long nameAddress) throws UnixException; 538 539 /** 540 * struct group *getgrnam(const char *name); 541 * 542 * @return group->gr_name 543 */ 544 static int getgrnam(String name) throws UnixException { 545 NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name)); 546 try { 547 return getgrnam0(buffer.address()); 548 } finally { 549 buffer.release(); 550 } 551 } 552 private static native int getgrnam0(long nameAddress) throws UnixException; 553 554 /** 555 * statvfs(const char* path, struct statvfs *buf) 556 */ 557 static void statvfs(UnixPath path, UnixFileStoreAttributes attrs) 558 throws UnixException 559 { 560 NativeBuffer buffer = copyToNativeBuffer(path); 561 try { 562 statvfs0(buffer.address(), attrs); 563 } finally { 564 buffer.release(); 565 } 566 } 567 private static native void statvfs0(long pathAddress, UnixFileStoreAttributes attrs) 568 throws UnixException; 569 570 /** 571 * long int pathconf(const char *path, int name); 572 */ 573 static long pathconf(UnixPath path, int name) throws UnixException { 574 NativeBuffer buffer = copyToNativeBuffer(path); 575 try { 576 return pathconf0(buffer.address(), name); 577 } finally { 578 buffer.release(); 579 } 580 } 581 private static native long pathconf0(long pathAddress, int name) 582 throws UnixException; 583 584 /** 585 * long fpathconf(int fildes, int name); 586 */ 587 static native long fpathconf(int filedes, int name) throws UnixException; 588 589 /** 590 * char* strerror(int errnum) 591 */ 592 static native byte[] strerror(int errnum); 593 594 /** 595 * Capabilities 596 */ 597 private static final int SUPPORTS_OPENAT = 1 << 1; // syscalls 598 private static final int SUPPORTS_FUTIMES = 1 << 2; 599 private static final int SUPPORTS_LUTIMES = 1 << 4; 600 private static final int SUPPORTS_BIRTHTIME = 1 << 16; // other features 601 private static final int capabilities; 602 603 /** 604 * Supports openat and other *at calls. 605 */ 606 static boolean openatSupported() { 607 return (capabilities & SUPPORTS_OPENAT) != 0; 608 } 609 610 /** 611 * Supports futimes or futimesat 612 */ 613 static boolean futimesSupported() { 614 return (capabilities & SUPPORTS_FUTIMES) != 0; 615 } 616 617 /** 618 * Supports lutimes 619 */ 620 static boolean lutimesSupported() { 621 return (capabilities & SUPPORTS_LUTIMES) != 0; 622 } 623 624 /** 625 * Supports file birth (creation) time attribute 626 */ 627 static boolean birthtimeSupported() { 628 return (capabilities & SUPPORTS_BIRTHTIME) != 0; 629 } 630 631 private static native int init(); 632 static { 633 AccessController.doPrivileged(new PrivilegedAction<>() { 634 public Void run() { 635 System.loadLibrary("nio"); 636 return null; 637 }}); 638 capabilities = init(); 639 } 640 }