1 /* 2 * Copyright (c) 2008, 2013, 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 { UnixNativeDispatcher()36 protected UnixNativeDispatcher() { } 37 38 // returns a NativeBuffer containing the given path copyToNativeBuffer(UnixPath 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 */ getcwd()58 static native byte[] getcwd(); 59 60 /** 61 * int dup(int filedes) 62 */ dup(int filedes)63 static native int dup(int filedes) throws UnixException; 64 65 /** 66 * int open(const char* path, int oflag, mode_t mode) 67 */ open(UnixPath path, int flags, int mode)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 } open0(long pathAddress, int flags, int mode)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 */ openat(int dfd, byte[] path, int flags, int mode)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 } openat0(int dfd, long pathAddress, int flags, int mode)90 private static native int openat0(int dfd, long pathAddress, int flags, int mode) 91 throws UnixException; 92 93 /** 94 * close(int filedes) 95 */ close(int fd)96 static native void close(int fd); 97 98 /** 99 * FILE* fopen(const char *filename, const char* mode); 100 */ fopen(UnixPath filename, String mode)101 static long fopen(UnixPath filename, String mode) throws UnixException { 102 NativeBuffer pathBuffer = copyToNativeBuffer(filename); 103 NativeBuffer modeBuffer = NativeBuffers.asNativeBuffer(Util.toBytes(mode)); 104 try { 105 return fopen0(pathBuffer.address(), modeBuffer.address()); 106 } finally { 107 modeBuffer.release(); 108 pathBuffer.release(); 109 } 110 } fopen0(long pathAddress, long modeAddress)111 private static native long fopen0(long pathAddress, long modeAddress) 112 throws UnixException; 113 114 /** 115 * fclose(FILE* stream) 116 */ fclose(long stream)117 static native void fclose(long stream) throws UnixException; 118 119 /** 120 * link(const char* existing, const char* new) 121 */ link(UnixPath existing, UnixPath newfile)122 static void link(UnixPath existing, UnixPath newfile) throws UnixException { 123 NativeBuffer existingBuffer = copyToNativeBuffer(existing); 124 NativeBuffer newBuffer = copyToNativeBuffer(newfile); 125 try { 126 link0(existingBuffer.address(), newBuffer.address()); 127 } finally { 128 newBuffer.release(); 129 existingBuffer.release(); 130 } 131 } link0(long existingAddress, long newAddress)132 private static native void link0(long existingAddress, long newAddress) 133 throws UnixException; 134 135 /** 136 * unlink(const char* path) 137 */ unlink(UnixPath path)138 static void unlink(UnixPath path) throws UnixException { 139 NativeBuffer buffer = copyToNativeBuffer(path); 140 try { 141 unlink0(buffer.address()); 142 } finally { 143 buffer.release(); 144 } 145 } unlink0(long pathAddress)146 private static native void unlink0(long pathAddress) throws UnixException; 147 148 /** 149 * unlinkat(int dfd, const char* path, int flag) 150 */ unlinkat(int dfd, byte[] path, int flag)151 static void unlinkat(int dfd, byte[] path, int flag) throws UnixException { 152 NativeBuffer buffer = NativeBuffers.asNativeBuffer(path); 153 try { 154 unlinkat0(dfd, buffer.address(), flag); 155 } finally { 156 buffer.release(); 157 } 158 } unlinkat0(int dfd, long pathAddress, int flag)159 private static native void unlinkat0(int dfd, long pathAddress, int flag) 160 throws UnixException; 161 162 /** 163 * mknod(const char* path, mode_t mode, dev_t dev) 164 */ mknod(UnixPath path, int mode, long dev)165 static void mknod(UnixPath path, int mode, long dev) throws UnixException { 166 NativeBuffer buffer = copyToNativeBuffer(path); 167 try { 168 mknod0(buffer.address(), mode, dev); 169 } finally { 170 buffer.release(); 171 } 172 } mknod0(long pathAddress, int mode, long dev)173 private static native void mknod0(long pathAddress, int mode, long dev) 174 throws UnixException; 175 176 /** 177 * rename(const char* old, const char* new) 178 */ rename(UnixPath from, UnixPath to)179 static void rename(UnixPath from, UnixPath to) throws UnixException { 180 NativeBuffer fromBuffer = copyToNativeBuffer(from); 181 NativeBuffer toBuffer = copyToNativeBuffer(to); 182 try { 183 rename0(fromBuffer.address(), toBuffer.address()); 184 } finally { 185 toBuffer.release(); 186 fromBuffer.release(); 187 } 188 } rename0(long fromAddress, long toAddress)189 private static native void rename0(long fromAddress, long toAddress) 190 throws UnixException; 191 192 /** 193 * renameat(int fromfd, const char* old, int tofd, const char* new) 194 */ renameat(int fromfd, byte[] from, int tofd, byte[] to)195 static void renameat(int fromfd, byte[] from, int tofd, byte[] to) throws UnixException { 196 NativeBuffer fromBuffer = NativeBuffers.asNativeBuffer(from); 197 NativeBuffer toBuffer = NativeBuffers.asNativeBuffer(to); 198 try { 199 renameat0(fromfd, fromBuffer.address(), tofd, toBuffer.address()); 200 } finally { 201 toBuffer.release(); 202 fromBuffer.release(); 203 } 204 } renameat0(int fromfd, long fromAddress, int tofd, long toAddress)205 private static native void renameat0(int fromfd, long fromAddress, int tofd, long toAddress) 206 throws UnixException; 207 208 /** 209 * mkdir(const char* path, mode_t mode) 210 */ mkdir(UnixPath path, int mode)211 static void mkdir(UnixPath path, int mode) throws UnixException { 212 NativeBuffer buffer = copyToNativeBuffer(path); 213 try { 214 mkdir0(buffer.address(), mode); 215 } finally { 216 buffer.release(); 217 } 218 } mkdir0(long pathAddress, int mode)219 private static native void mkdir0(long pathAddress, int mode) throws UnixException; 220 221 /** 222 * rmdir(const char* path) 223 */ rmdir(UnixPath path)224 static void rmdir(UnixPath path) throws UnixException { 225 NativeBuffer buffer = copyToNativeBuffer(path); 226 try { 227 rmdir0(buffer.address()); 228 } finally { 229 buffer.release(); 230 } 231 } rmdir0(long pathAddress)232 private static native void rmdir0(long pathAddress) throws UnixException; 233 234 /** 235 * readlink(const char* path, char* buf, size_t bufsize) 236 * 237 * @return link target 238 */ readlink(UnixPath path)239 static byte[] readlink(UnixPath path) throws UnixException { 240 NativeBuffer buffer = copyToNativeBuffer(path); 241 try { 242 return readlink0(buffer.address()); 243 } finally { 244 buffer.release(); 245 } 246 } readlink0(long pathAddress)247 private static native byte[] readlink0(long pathAddress) throws UnixException; 248 249 /** 250 * realpath(const char* path, char* resolved_name) 251 * 252 * @return resolved path 253 */ realpath(UnixPath path)254 static byte[] realpath(UnixPath path) throws UnixException { 255 NativeBuffer buffer = copyToNativeBuffer(path); 256 try { 257 return realpath0(buffer.address()); 258 } finally { 259 buffer.release(); 260 } 261 } realpath0(long pathAddress)262 private static native byte[] realpath0(long pathAddress) throws UnixException; 263 264 /** 265 * symlink(const char* name1, const char* name2) 266 */ symlink(byte[] name1, UnixPath name2)267 static void symlink(byte[] name1, UnixPath name2) throws UnixException { 268 NativeBuffer targetBuffer = NativeBuffers.asNativeBuffer(name1); 269 NativeBuffer linkBuffer = copyToNativeBuffer(name2); 270 try { 271 symlink0(targetBuffer.address(), linkBuffer.address()); 272 } finally { 273 linkBuffer.release(); 274 targetBuffer.release(); 275 } 276 } symlink0(long name1, long name2)277 private static native void symlink0(long name1, long name2) 278 throws UnixException; 279 280 /** 281 * stat(const char* path, struct stat* buf) 282 */ stat(UnixPath path, UnixFileAttributes attrs)283 static void stat(UnixPath path, UnixFileAttributes attrs) throws UnixException { 284 NativeBuffer buffer = copyToNativeBuffer(path); 285 try { 286 stat0(buffer.address(), attrs); 287 } finally { 288 buffer.release(); 289 } 290 } stat0(long pathAddress, UnixFileAttributes attrs)291 private static native void stat0(long pathAddress, UnixFileAttributes attrs) 292 throws UnixException; 293 294 /** 295 * lstat(const char* path, struct stat* buf) 296 */ lstat(UnixPath path, UnixFileAttributes attrs)297 static void lstat(UnixPath path, UnixFileAttributes attrs) throws UnixException { 298 NativeBuffer buffer = copyToNativeBuffer(path); 299 try { 300 lstat0(buffer.address(), attrs); 301 } finally { 302 buffer.release(); 303 } 304 } lstat0(long pathAddress, UnixFileAttributes attrs)305 private static native void lstat0(long pathAddress, UnixFileAttributes attrs) 306 throws UnixException; 307 308 /** 309 * fstat(int filedes, struct stat* buf) 310 */ fstat(int fd, UnixFileAttributes attrs)311 static native void fstat(int fd, UnixFileAttributes attrs) throws UnixException; 312 313 /** 314 * fstatat(int filedes,const char* path, struct stat* buf, int flag) 315 */ fstatat(int dfd, byte[] path, int flag, UnixFileAttributes attrs)316 static void fstatat(int dfd, byte[] path, int flag, UnixFileAttributes attrs) 317 throws UnixException 318 { 319 NativeBuffer buffer = NativeBuffers.asNativeBuffer(path); 320 try { 321 fstatat0(dfd, buffer.address(), flag, attrs); 322 } finally { 323 buffer.release(); 324 } 325 } fstatat0(int dfd, long pathAddress, int flag, UnixFileAttributes attrs)326 private static native void fstatat0(int dfd, long pathAddress, int flag, 327 UnixFileAttributes attrs) throws UnixException; 328 329 /** 330 * chown(const char* path, uid_t owner, gid_t group) 331 */ chown(UnixPath path, int uid, int gid)332 static void chown(UnixPath path, int uid, int gid) throws UnixException { 333 NativeBuffer buffer = copyToNativeBuffer(path); 334 try { 335 chown0(buffer.address(), uid, gid); 336 } finally { 337 buffer.release(); 338 } 339 } chown0(long pathAddress, int uid, int gid)340 private static native void chown0(long pathAddress, int uid, int gid) 341 throws UnixException; 342 343 /** 344 * lchown(const char* path, uid_t owner, gid_t group) 345 */ lchown(UnixPath path, int uid, int gid)346 static void lchown(UnixPath path, int uid, int gid) throws UnixException { 347 NativeBuffer buffer = copyToNativeBuffer(path); 348 try { 349 lchown0(buffer.address(), uid, gid); 350 } finally { 351 buffer.release(); 352 } 353 } lchown0(long pathAddress, int uid, int gid)354 private static native void lchown0(long pathAddress, int uid, int gid) 355 throws UnixException; 356 357 /** 358 * fchown(int filedes, uid_t owner, gid_t group) 359 */ fchown(int fd, int uid, int gid)360 static native void fchown(int fd, int uid, int gid) throws UnixException; 361 362 /** 363 * chmod(const char* path, mode_t mode) 364 */ chmod(UnixPath path, int mode)365 static void chmod(UnixPath path, int mode) throws UnixException { 366 NativeBuffer buffer = copyToNativeBuffer(path); 367 try { 368 chmod0(buffer.address(), mode); 369 } finally { 370 buffer.release(); 371 } 372 } chmod0(long pathAddress, int mode)373 private static native void chmod0(long pathAddress, int mode) 374 throws UnixException; 375 376 /** 377 * fchmod(int fildes, mode_t mode) 378 */ fchmod(int fd, int mode)379 static native void fchmod(int fd, int mode) throws UnixException; 380 381 /** 382 * utimes(conar char* path, const struct timeval times[2]) 383 */ utimes(UnixPath path, long times0, long times1)384 static void utimes(UnixPath path, long times0, long times1) 385 throws UnixException 386 { 387 NativeBuffer buffer = copyToNativeBuffer(path); 388 try { 389 utimes0(buffer.address(), times0, times1); 390 } finally { 391 buffer.release(); 392 } 393 } utimes0(long pathAddress, long times0, long times1)394 private static native void utimes0(long pathAddress, long times0, long times1) 395 throws UnixException; 396 397 /** 398 * futimes(int fildes,, const struct timeval times[2]) 399 */ futimes(int fd, long times0, long times1)400 static native void futimes(int fd, long times0, long times1) throws UnixException; 401 402 /** 403 * DIR *opendir(const char* dirname) 404 */ opendir(UnixPath path)405 static long opendir(UnixPath path) throws UnixException { 406 NativeBuffer buffer = copyToNativeBuffer(path); 407 try { 408 return opendir0(buffer.address()); 409 } finally { 410 buffer.release(); 411 } 412 } opendir0(long pathAddress)413 private static native long opendir0(long pathAddress) throws UnixException; 414 415 /** 416 * DIR* fdopendir(int filedes) 417 */ fdopendir(int dfd)418 static native long fdopendir(int dfd) throws UnixException; 419 420 421 /** 422 * closedir(DIR* dirp) 423 */ closedir(long dir)424 static native void closedir(long dir) throws UnixException; 425 426 /** 427 * struct dirent* readdir(DIR *dirp) 428 * 429 * @return dirent->d_name 430 */ readdir(long dir)431 static native byte[] readdir(long dir) throws UnixException; 432 433 /** 434 * size_t read(int fildes, void* buf, size_t nbyte) 435 */ read(int fildes, long buf, int nbyte)436 static native int read(int fildes, long buf, int nbyte) throws UnixException; 437 438 /** 439 * size_t writeint fildes, void* buf, size_t nbyte) 440 */ write(int fildes, long buf, int nbyte)441 static native int write(int fildes, long buf, int nbyte) throws UnixException; 442 443 /** 444 * access(const char* path, int amode); 445 */ access(UnixPath path, int amode)446 static void access(UnixPath path, int amode) throws UnixException { 447 NativeBuffer buffer = copyToNativeBuffer(path); 448 try { 449 access0(buffer.address(), amode); 450 } finally { 451 buffer.release(); 452 } 453 } access0(long pathAddress, int amode)454 private static native void access0(long pathAddress, int amode) throws UnixException; 455 456 /** 457 * struct passwd *getpwuid(uid_t uid); 458 * 459 * @return passwd->pw_name 460 */ getpwuid(int uid)461 static native byte[] getpwuid(int uid) throws UnixException; 462 463 /** 464 * struct group *getgrgid(gid_t gid); 465 * 466 * @return group->gr_name 467 */ getgrgid(int gid)468 static native byte[] getgrgid(int gid) throws UnixException; 469 470 /** 471 * struct passwd *getpwnam(const char *name); 472 * 473 * @return passwd->pw_uid 474 */ getpwnam(String name)475 static int getpwnam(String name) throws UnixException { 476 NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name)); 477 try { 478 return getpwnam0(buffer.address()); 479 } finally { 480 buffer.release(); 481 } 482 } getpwnam0(long nameAddress)483 private static native int getpwnam0(long nameAddress) throws UnixException; 484 485 /** 486 * struct group *getgrnam(const char *name); 487 * 488 * @return group->gr_name 489 */ getgrnam(String name)490 static int getgrnam(String name) throws UnixException { 491 NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name)); 492 try { 493 return getgrnam0(buffer.address()); 494 } finally { 495 buffer.release(); 496 } 497 } getgrnam0(long nameAddress)498 private static native int getgrnam0(long nameAddress) throws UnixException; 499 500 /** 501 * statvfs(const char* path, struct statvfs *buf) 502 */ statvfs(UnixPath path, UnixFileStoreAttributes attrs)503 static void statvfs(UnixPath path, UnixFileStoreAttributes attrs) 504 throws UnixException 505 { 506 NativeBuffer buffer = copyToNativeBuffer(path); 507 try { 508 statvfs0(buffer.address(), attrs); 509 } finally { 510 buffer.release(); 511 } 512 } statvfs0(long pathAddress, UnixFileStoreAttributes attrs)513 private static native void statvfs0(long pathAddress, UnixFileStoreAttributes attrs) 514 throws UnixException; 515 516 /** 517 * long int pathconf(const char *path, int name); 518 */ pathconf(UnixPath path, int name)519 static long pathconf(UnixPath path, int name) throws UnixException { 520 NativeBuffer buffer = copyToNativeBuffer(path); 521 try { 522 return pathconf0(buffer.address(), name); 523 } finally { 524 buffer.release(); 525 } 526 } pathconf0(long pathAddress, int name)527 private static native long pathconf0(long pathAddress, int name) 528 throws UnixException; 529 530 /** 531 * long fpathconf(int fildes, int name); 532 */ fpathconf(int filedes, int name)533 static native long fpathconf(int filedes, int name) throws UnixException; 534 535 /** 536 * char* strerror(int errnum) 537 */ strerror(int errnum)538 static native byte[] strerror(int errnum); 539 540 /** 541 * Capabilities 542 */ 543 private static final int SUPPORTS_OPENAT = 1 << 1; // syscalls 544 private static final int SUPPORTS_FUTIMES = 1 << 2; 545 private static final int SUPPORTS_BIRTHTIME = 1 << 16; // other features 546 private static final int capabilities; 547 548 /** 549 * Supports openat and other *at calls. 550 */ openatSupported()551 static boolean openatSupported() { 552 return (capabilities & SUPPORTS_OPENAT) != 0; 553 } 554 555 /** 556 * Supports futimes or futimesat 557 */ futimesSupported()558 static boolean futimesSupported() { 559 return (capabilities & SUPPORTS_FUTIMES) != 0; 560 } 561 562 /** 563 * Supports file birth (creation) time attribute 564 */ birthtimeSupported()565 static boolean birthtimeSupported() { 566 return (capabilities & SUPPORTS_BIRTHTIME) != 0; 567 } 568 init()569 private static native int init(); 570 static { 571 // Android-removed: Code to load native libraries, doesn't make sense on Android. 572 /* 573 AccessController.doPrivileged(new PrivilegedAction<Void>() { 574 public Void run() { 575 System.loadLibrary("nio"); 576 return null; 577 }}); 578 */ 579 capabilities = init(); 580 } 581 } 582