1 /* 2 * Copyright (c) 2001, 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 #include "jni.h" 27 #include "jni_util.h" 28 #include "jvm.h" 29 #include "io_util.h" 30 #include "io_util_md.h" 31 #include <stdio.h> 32 #include <windows.h> 33 34 #include <wchar.h> 35 #include <io.h> 36 #include <fcntl.h> 37 #include <errno.h> 38 #include <string.h> 39 #include <sys/types.h> 40 #include <sys/stat.h> 41 #include <limits.h> 42 #include <wincon.h> 43 44 45 static DWORD MAX_INPUT_EVENTS = 2000; 46 47 /* If this returns NULL then an exception is pending */ 48 WCHAR* 49 fileToNTPath(JNIEnv *env, jobject file, jfieldID id) { 50 jstring path = NULL; 51 if (file != NULL) { 52 path = (*env)->GetObjectField(env, file, id); 53 } 54 return pathToNTPath(env, path, JNI_FALSE); 55 } 56 57 /* Returns the working directory for the given drive, or NULL */ 58 WCHAR* 59 currentDir(int di) { 60 UINT dt; 61 WCHAR root[4]; 62 // verify drive is valid as _wgetdcwd in the VC++ 2010 runtime 63 // library does not handle invalid drives. 64 root[0] = L'A' + (WCHAR)(di - 1); 65 root[1] = L':'; 66 root[2] = L'\\'; 67 root[3] = L'\0'; 68 dt = GetDriveTypeW(root); 69 if (dt == DRIVE_UNKNOWN || dt == DRIVE_NO_ROOT_DIR) { 70 return NULL; 71 } else { 72 return _wgetdcwd(di, NULL, MAX_PATH); 73 } 74 } 75 76 /* We cache the length of current working dir here to avoid 77 calling _wgetcwd() every time we need to resolve a relative 78 path. This piece of code needs to be revisited if chdir 79 makes its way into java runtime. 80 */ 81 82 int 83 currentDirLength(const WCHAR* ps, int pathlen) { 84 WCHAR *dir; 85 if (pathlen > 2 && ps[1] == L':' && ps[2] != L'\\') { 86 //drive-relative 87 WCHAR d = ps[0]; 88 int dirlen = 0; 89 int di = 0; 90 if ((d >= L'a') && (d <= L'z')) di = d - L'a' + 1; 91 else if ((d >= L'A') && (d <= L'Z')) di = d - L'A' + 1; 92 else return 0; /* invalid drive name. */ 93 dir = currentDir(di); 94 if (dir != NULL){ 95 dirlen = (int)wcslen(dir); 96 free(dir); 97 } 98 return dirlen; 99 } else { 100 static int curDirLenCached = -1; 101 //relative to both drive and directory 102 if (curDirLenCached == -1) { 103 int dirlen = -1; 104 dir = _wgetcwd(NULL, MAX_PATH); 105 if (dir != NULL) { 106 curDirLenCached = (int)wcslen(dir); 107 free(dir); 108 } 109 } 110 return curDirLenCached; 111 } 112 } 113 114 /* 115 The "abpathlen" is the size of the buffer needed by _wfullpath. If the 116 "path" is a relative path, it is "the length of the current dir" + "the 117 length of the path", if it's "absolute" already, it's the same as 118 pathlen which is the length of "path". 119 */ 120 WCHAR* prefixAbpath(const WCHAR* path, int pathlen, int abpathlen) { 121 WCHAR* pathbuf = NULL; 122 WCHAR* abpath = NULL; 123 124 abpathlen += 10; //padding 125 abpath = (WCHAR*)malloc(abpathlen * sizeof(WCHAR)); 126 if (abpath) { 127 /* Collapse instances of "foo\.." and ensure absoluteness before 128 going down to prefixing. 129 */ 130 if (_wfullpath(abpath, path, abpathlen)) { 131 pathbuf = getPrefixed(abpath, abpathlen); 132 } else { 133 /* _wfullpath fails if the pathlength exceeds 32k wchar. 134 Instead of doing more fancy things we simply copy the 135 ps into the return buffer, the subsequent win32 API will 136 probably fail with FileNotFoundException, which is expected 137 */ 138 pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR)); 139 if (pathbuf != 0) { 140 wcscpy(pathbuf, path); 141 } 142 } 143 free(abpath); 144 } 145 return pathbuf; 146 } 147 148 /* If this returns NULL then an exception is pending */ 149 WCHAR* 150 pathToNTPath(JNIEnv *env, jstring path, jboolean throwFNFE) { 151 int pathlen = 0; 152 WCHAR *pathbuf = NULL; 153 int max_path = 248; /* CreateDirectoryW() has the limit of 248 */ 154 155 WITH_UNICODE_STRING(env, path, ps) { 156 pathlen = (int)wcslen(ps); 157 if (pathlen != 0) { 158 if (pathlen > 2 && 159 (ps[0] == L'\\' && ps[1] == L'\\' || //UNC 160 ps[1] == L':' && ps[2] == L'\\')) //absolute 161 { 162 if (pathlen > max_path - 1) { 163 pathbuf = prefixAbpath(ps, pathlen, pathlen); 164 } else { 165 pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR)); 166 if (pathbuf != 0) { 167 wcscpy(pathbuf, ps); 168 } else { 169 JNU_ThrowOutOfMemoryError(env, "native memory allocation failed"); 170 return NULL; 171 } 172 } 173 } else { 174 /* If the path came in as a relative path, need to verify if 175 its absolute form is bigger than max_path or not, if yes 176 need to (1)convert it to absolute and (2)prefix. This is 177 obviously a burden to all relative paths (The current dir/len 178 for "drive & directory" relative path is cached, so we only 179 calculate it once but for "drive-relative path we call 180 _wgetdcwd() and wcslen() everytime), but a hit we have 181 to take if we want to support relative path beyond max_path. 182 There is no way to predict how long the absolute path will be 183 (therefor allocate the sufficient memory block) before calling 184 _wfullpath(), we have to get the length of "current" dir first. 185 */ 186 WCHAR *abpath = NULL; 187 int dirlen = currentDirLength(ps, pathlen); 188 if (dirlen + pathlen + 1 > max_path - 1) { 189 pathbuf = prefixAbpath(ps, pathlen, dirlen + pathlen); 190 } else { 191 pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR)); 192 if (pathbuf != 0) { 193 wcscpy(pathbuf, ps); 194 } else { 195 JNU_ThrowOutOfMemoryError(env, "native memory allocation failed"); 196 return NULL; 197 } 198 } 199 } 200 } 201 } END_UNICODE_STRING(env, ps); 202 203 if (pathlen == 0) { 204 if (throwFNFE == JNI_TRUE) { 205 if (!(*env)->ExceptionCheck(env)) { 206 throwFileNotFoundException(env, path); 207 } 208 return NULL; 209 } else { 210 pathbuf = (WCHAR*)malloc(sizeof(WCHAR)); 211 if (pathbuf != NULL) { 212 pathbuf[0] = L'\0'; 213 } else { 214 JNU_ThrowOutOfMemoryError(env, 0); 215 return NULL; 216 } 217 } 218 } 219 if (pathbuf == 0) { 220 JNU_ThrowOutOfMemoryError(env, 0); 221 return NULL; 222 } 223 return pathbuf; 224 } 225 226 FD 227 winFileHandleOpen(JNIEnv *env, jstring path, int flags) 228 { 229 const DWORD access = 230 (flags & O_WRONLY) ? GENERIC_WRITE : 231 (flags & O_RDWR) ? (GENERIC_READ | GENERIC_WRITE) : 232 GENERIC_READ; 233 const DWORD sharing = 234 FILE_SHARE_READ | FILE_SHARE_WRITE; 235 const DWORD disposition = 236 /* Note: O_TRUNC overrides O_CREAT */ 237 (flags & O_TRUNC) ? CREATE_ALWAYS : 238 (flags & O_CREAT) ? OPEN_ALWAYS : 239 OPEN_EXISTING; 240 const DWORD maybeWriteThrough = 241 (flags & (O_SYNC | O_DSYNC)) ? 242 FILE_FLAG_WRITE_THROUGH : 243 FILE_ATTRIBUTE_NORMAL; 244 const DWORD maybeDeleteOnClose = 245 (flags & O_TEMPORARY) ? 246 FILE_FLAG_DELETE_ON_CLOSE : 247 FILE_ATTRIBUTE_NORMAL; 248 const DWORD flagsAndAttributes = maybeWriteThrough | maybeDeleteOnClose; 249 HANDLE h = NULL; 250 251 WCHAR *pathbuf = pathToNTPath(env, path, JNI_TRUE); 252 if (pathbuf == NULL) { 253 /* Exception already pending */ 254 return -1; 255 } 256 h = CreateFileW( 257 pathbuf, /* Wide char path name */ 258 access, /* Read and/or write permission */ 259 sharing, /* File sharing flags */ 260 NULL, /* Security attributes */ 261 disposition, /* creation disposition */ 262 flagsAndAttributes, /* flags and attributes */ 263 NULL); 264 free(pathbuf); 265 266 if (h == INVALID_HANDLE_VALUE) { 267 throwFileNotFoundException(env, path); 268 return -1; 269 } 270 return (jlong) h; 271 } 272 273 void 274 fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags) 275 { 276 FD h = winFileHandleOpen(env, path, flags); 277 if (h >= 0) { 278 SET_FD(this, h, fid); 279 } 280 } 281 282 /* These are functions that use a handle fd instead of the 283 old C style int fd as is used in HPI layer */ 284 285 static int 286 handleNonSeekAvailable(FD, long *); 287 static int 288 handleStdinAvailable(FD, long *); 289 290 int 291 handleAvailable(FD fd, jlong *pbytes) { 292 HANDLE h = (HANDLE)fd; 293 DWORD type = 0; 294 295 type = GetFileType(h); 296 /* Handle is for keyboard or pipe */ 297 if (type == FILE_TYPE_CHAR || type == FILE_TYPE_PIPE) { 298 int ret; 299 long lpbytes; 300 HANDLE stdInHandle = GetStdHandle(STD_INPUT_HANDLE); 301 if (stdInHandle == h) { 302 ret = handleStdinAvailable(fd, &lpbytes); /* keyboard */ 303 } else { 304 ret = handleNonSeekAvailable(fd, &lpbytes); /* pipe */ 305 } 306 (*pbytes) = (jlong)(lpbytes); 307 return ret; 308 } 309 /* Handle is for regular file */ 310 if (type == FILE_TYPE_DISK) { 311 jlong current, end; 312 313 LARGE_INTEGER filesize; 314 current = handleLseek(fd, 0, SEEK_CUR); 315 if (current < 0) { 316 return FALSE; 317 } 318 if (GetFileSizeEx(h, &filesize) == 0) { 319 return FALSE; 320 } 321 end = long_to_jlong(filesize.QuadPart); 322 *pbytes = end - current; 323 return TRUE; 324 } 325 return FALSE; 326 } 327 328 static int 329 handleNonSeekAvailable(FD fd, long *pbytes) { 330 /* This is used for available on non-seekable devices 331 * (like both named and anonymous pipes, such as pipes 332 * connected to an exec'd process). 333 * Standard Input is a special case. 334 * 335 */ 336 HANDLE han; 337 338 if ((han = (HANDLE) fd) == INVALID_HANDLE_VALUE) { 339 return FALSE; 340 } 341 342 if (! PeekNamedPipe(han, NULL, 0, NULL, pbytes, NULL)) { 343 /* PeekNamedPipe fails when at EOF. In that case we 344 * simply make *pbytes = 0 which is consistent with the 345 * behavior we get on Solaris when an fd is at EOF. 346 * The only alternative is to raise and Exception, 347 * which isn't really warranted. 348 */ 349 if (GetLastError() != ERROR_BROKEN_PIPE) { 350 return FALSE; 351 } 352 *pbytes = 0; 353 } 354 return TRUE; 355 } 356 357 static int 358 handleStdinAvailable(FD fd, long *pbytes) { 359 HANDLE han; 360 DWORD numEventsRead = 0; /* Number of events read from buffer */ 361 DWORD numEvents = 0; /* Number of events in buffer */ 362 DWORD i = 0; /* Loop index */ 363 DWORD curLength = 0; /* Position marker */ 364 DWORD actualLength = 0; /* Number of bytes readable */ 365 BOOL error = FALSE; /* Error holder */ 366 INPUT_RECORD *lpBuffer; /* Pointer to records of input events */ 367 DWORD bufferSize = 0; 368 369 if ((han = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) { 370 return FALSE; 371 } 372 373 /* Construct an array of input records in the console buffer */ 374 error = GetNumberOfConsoleInputEvents(han, &numEvents); 375 if (error == 0) { 376 return handleNonSeekAvailable(fd, pbytes); 377 } 378 379 /* lpBuffer must fit into 64K or else PeekConsoleInput fails */ 380 if (numEvents > MAX_INPUT_EVENTS) { 381 numEvents = MAX_INPUT_EVENTS; 382 } 383 384 bufferSize = numEvents * sizeof(INPUT_RECORD); 385 if (bufferSize == 0) 386 bufferSize = 1; 387 lpBuffer = malloc(bufferSize); 388 if (lpBuffer == NULL) { 389 return FALSE; 390 } 391 392 error = PeekConsoleInput(han, lpBuffer, numEvents, &numEventsRead); 393 if (error == 0) { 394 free(lpBuffer); 395 return FALSE; 396 } 397 398 /* Examine input records for the number of bytes available */ 399 for(i=0; i<numEvents; i++) { 400 if (lpBuffer[i].EventType == KEY_EVENT) { 401 KEY_EVENT_RECORD *keyRecord = (KEY_EVENT_RECORD *) 402 &(lpBuffer[i].Event); 403 if (keyRecord->bKeyDown == TRUE) { 404 CHAR *keyPressed = (CHAR *) &(keyRecord->uChar); 405 curLength++; 406 if (*keyPressed == '\r') 407 actualLength = curLength; 408 } 409 } 410 } 411 if(lpBuffer != NULL) 412 free(lpBuffer); 413 *pbytes = (long) actualLength; 414 return TRUE; 415 } 416 417 /* 418 * This is documented to succeed on read-only files, but Win32's 419 * FlushFileBuffers functions fails with "access denied" in such a 420 * case. So we only signal an error if the error is *not* "access 421 * denied". 422 */ 423 424 int 425 handleSync(FD fd) { 426 /* 427 * From the documentation: 428 * 429 * On Windows NT, the function FlushFileBuffers fails if hFile 430 * is a handle to console output. That is because console 431 * output is not buffered. The function returns FALSE, and 432 * GetLastError returns ERROR_INVALID_HANDLE. 433 * 434 * On the other hand, on Win95, it returns without error. I cannot 435 * assume that 0, 1, and 2 are console, because if someone closes 436 * System.out and then opens a file, they might get file descriptor 437 * 1. An error on *that* version of 1 should be reported, whereas 438 * an error on System.out (which was the original 1) should be 439 * ignored. So I use isatty() to ensure that such an error was due 440 * to this bogosity, and if it was, I ignore the error. 441 */ 442 443 HANDLE handle = (HANDLE)fd; 444 445 if (!FlushFileBuffers(handle)) { 446 if (GetLastError() != ERROR_ACCESS_DENIED) { /* from winerror.h */ 447 return -1; 448 } 449 } 450 return 0; 451 } 452 453 454 int 455 handleSetLength(FD fd, jlong length) { 456 HANDLE h = (HANDLE)fd; 457 long high = (long)(length >> 32); 458 DWORD ret; 459 460 if (h == (HANDLE)(-1)) return -1; 461 ret = SetFilePointer(h, (long)(length), &high, FILE_BEGIN); 462 if (ret == 0xFFFFFFFF && GetLastError() != NO_ERROR) { 463 return -1; 464 } 465 if (SetEndOfFile(h) == FALSE) return -1; 466 return 0; 467 } 468 469 JNIEXPORT 470 jint 471 handleRead(FD fd, void *buf, jint len) 472 { 473 DWORD read = 0; 474 BOOL result = 0; 475 HANDLE h = (HANDLE)fd; 476 if (h == INVALID_HANDLE_VALUE) { 477 return -1; 478 } 479 result = ReadFile(h, /* File handle to read */ 480 buf, /* address to put data */ 481 len, /* number of bytes to read */ 482 &read, /* number of bytes read */ 483 NULL); /* no overlapped struct */ 484 if (result == 0) { 485 int error = GetLastError(); 486 if (error == ERROR_BROKEN_PIPE) { 487 return 0; /* EOF */ 488 } 489 return -1; 490 } 491 return (jint)read; 492 } 493 494 static jint writeInternal(FD fd, const void *buf, jint len, jboolean append) 495 { 496 BOOL result = 0; 497 DWORD written = 0; 498 HANDLE h = (HANDLE)fd; 499 if (h != INVALID_HANDLE_VALUE) { 500 OVERLAPPED ov; 501 LPOVERLAPPED lpOv; 502 if (append == JNI_TRUE) { 503 ov.Offset = (DWORD)0xFFFFFFFF; 504 ov.OffsetHigh = (DWORD)0xFFFFFFFF; 505 ov.hEvent = NULL; 506 lpOv = &ov; 507 } else { 508 lpOv = NULL; 509 } 510 result = WriteFile(h, /* File handle to write */ 511 buf, /* pointers to the buffers */ 512 len, /* number of bytes to write */ 513 &written, /* receives number of bytes written */ 514 lpOv); /* overlapped struct */ 515 } 516 if ((h == INVALID_HANDLE_VALUE) || (result == 0)) { 517 return -1; 518 } 519 return (jint)written; 520 } 521 522 jint handleWrite(FD fd, const void *buf, jint len) { 523 return writeInternal(fd, buf, len, JNI_FALSE); 524 } 525 526 jint handleAppend(FD fd, const void *buf, jint len) { 527 return writeInternal(fd, buf, len, JNI_TRUE); 528 } 529 530 jint 531 handleClose(JNIEnv *env, jobject this, jfieldID fid) 532 { 533 FD fd = GET_FD(this, fid); 534 HANDLE h = (HANDLE)fd; 535 536 if (h == INVALID_HANDLE_VALUE) { 537 return 0; 538 } 539 540 /* Set the fd to -1 before closing it so that the timing window 541 * of other threads using the wrong fd (closed but recycled fd, 542 * that gets re-opened with some other filename) is reduced. 543 * Practically the chance of its occurance is low, however, we are 544 * taking extra precaution over here. 545 */ 546 SET_FD(this, -1, fid); 547 548 if (CloseHandle(h) == 0) { /* Returns zero on failure */ 549 JNU_ThrowIOExceptionWithLastError(env, "close failed"); 550 } 551 return 0; 552 } 553 554 jlong 555 handleLseek(FD fd, jlong offset, jint whence) 556 { 557 LARGE_INTEGER pos, distance; 558 DWORD lowPos = 0; 559 long highPos = 0; 560 DWORD op = FILE_CURRENT; 561 HANDLE h = (HANDLE)fd; 562 563 if (whence == SEEK_END) { 564 op = FILE_END; 565 } 566 if (whence == SEEK_CUR) { 567 op = FILE_CURRENT; 568 } 569 if (whence == SEEK_SET) { 570 op = FILE_BEGIN; 571 } 572 573 distance.QuadPart = offset; 574 if (SetFilePointerEx(h, distance, &pos, op) == 0) { 575 return -1; 576 } 577 return long_to_jlong(pos.QuadPart); 578 } 579 580 size_t 581 getLastErrorString(char *utf8_jvmErrorMsg, size_t cbErrorMsg) 582 { 583 size_t n = 0; 584 if (cbErrorMsg > 0) { 585 BOOLEAN noError = FALSE; 586 WCHAR *utf16_osErrorMsg = (WCHAR *)malloc(cbErrorMsg*sizeof(WCHAR)); 587 if (utf16_osErrorMsg == NULL) { 588 // OOM accident 589 strncpy(utf8_jvmErrorMsg, "Out of memory", cbErrorMsg); 590 // truncate if too long 591 utf8_jvmErrorMsg[cbErrorMsg - 1] = '\0'; 592 n = strlen(utf8_jvmErrorMsg); 593 } else { 594 DWORD errval = GetLastError(); 595 if (errval != 0) { 596 // WIN32 error 597 n = (size_t)FormatMessageW( 598 FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 599 NULL, 600 errval, 601 0, 602 utf16_osErrorMsg, 603 (DWORD)cbErrorMsg, 604 NULL); 605 if (n > 3) { 606 // Drop final '.', CR, LF 607 if (utf16_osErrorMsg[n - 1] == L'\n') --n; 608 if (utf16_osErrorMsg[n - 1] == L'\r') --n; 609 if (utf16_osErrorMsg[n - 1] == L'.') --n; 610 utf16_osErrorMsg[n] = L'\0'; 611 } 612 } else if (errno != 0) { 613 // C runtime error that has no corresponding WIN32 error code 614 const WCHAR *rtError = _wcserror(errno); 615 if (rtError != NULL) { 616 wcsncpy(utf16_osErrorMsg, rtError, cbErrorMsg); 617 // truncate if too long 618 utf16_osErrorMsg[cbErrorMsg - 1] = L'\0'; 619 n = wcslen(utf16_osErrorMsg); 620 } 621 } else 622 noError = TRUE; //OS has no error to report 623 624 if (!noError) { 625 if (n > 0) { 626 n = WideCharToMultiByte( 627 CP_UTF8, 628 0, 629 utf16_osErrorMsg, 630 n, 631 utf8_jvmErrorMsg, 632 cbErrorMsg, 633 NULL, 634 NULL); 635 636 // no way to die 637 if (n > 0) 638 utf8_jvmErrorMsg[min(cbErrorMsg - 1, n)] = '\0'; 639 } 640 641 if (n <= 0) { 642 strncpy(utf8_jvmErrorMsg, "Secondary error while OS message extraction", cbErrorMsg); 643 // truncate if too long 644 utf8_jvmErrorMsg[cbErrorMsg - 1] = '\0'; 645 n = strlen(utf8_jvmErrorMsg); 646 } 647 } 648 free(utf16_osErrorMsg); 649 } 650 } 651 return n; 652 }