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