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