< prev index next >

src/java.base/windows/native/libjava/WinNTFileSystem_md.c

Print this page
rev 52387 : 8211752: JNU_ThrowIOExceptionWithLastErrorAndPath - enhance some IOExceptions with path causing the issue


  61 Java_java_io_WinNTFileSystem_initIDs(JNIEnv *env, jclass cls)
  62 {
  63     HMODULE handle;
  64     jclass fileClass;
  65 
  66     fileClass = (*env)->FindClass(env, "java/io/File");
  67     CHECK_NULL(fileClass);
  68     ids.path = (*env)->GetFieldID(env, fileClass, "path", "Ljava/lang/String;");
  69     CHECK_NULL(ids.path);
  70 
  71     // GetFinalPathNameByHandle requires Windows Vista or newer
  72     if (GetModuleHandleExW((GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
  73                             GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT),
  74                            (LPCWSTR)&CreateFileW, &handle) != 0)
  75     {
  76         GetFinalPathNameByHandle_func = (GetFinalPathNameByHandleProc)
  77             GetProcAddress(handle, "GetFinalPathNameByHandleW");
  78     }
  79 }
  80 








  81 /* -- Path operations -- */
  82 
  83 extern int wcanonicalize(const WCHAR *path, WCHAR *out, int len);
  84 extern int wcanonicalizeWithPrefix(const WCHAR *canonicalPrefix, const WCHAR *pathWithCanonicalPrefix, WCHAR *out, int len);
  85 
  86 /**
  87  * Retrieves the fully resolved (final) path for the given path or NULL
  88  * if the function fails.
  89  */
  90 static WCHAR* getFinalPath(JNIEnv *env, const WCHAR *path)
  91 {
  92     HANDLE h;
  93     WCHAR *result;
  94     DWORD error;
  95 
  96     /* Need Windows Vista or newer to get the final path */
  97     if (GetFinalPathNameByHandle_func == NULL)
  98         return NULL;
  99 
 100     h = CreateFileW(path,


 239         /* we estimate the max length of memory needed as
 240            "currentDir. length + pathname.length"
 241          */
 242         int len = (int)wcslen(path);
 243         len += currentDirLength(path, len);
 244         if (len  > MAX_PATH_LENGTH - 1) {
 245             WCHAR *cp = (WCHAR*)malloc(len * sizeof(WCHAR));
 246             if (cp != NULL) {
 247                 if (wcanonicalize(path, cp, len) >= 0) {
 248                     rv = (*env)->NewString(env, cp, (jsize)wcslen(cp));
 249                 }
 250                 free(cp);
 251             } else {
 252                 JNU_ThrowOutOfMemoryError(env, "native memory allocation failed");
 253             }
 254         } else if (wcanonicalize(path, canonicalPath, MAX_PATH_LENGTH) >= 0) {
 255             rv = (*env)->NewString(env, canonicalPath, (jsize)wcslen(canonicalPath));
 256         }
 257     } END_UNICODE_STRING(env, path);
 258     if (rv == NULL && !(*env)->ExceptionCheck(env)) {





 259         JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");
 260     }

 261     return rv;
 262 }
 263 
 264 
 265 JNIEXPORT jstring JNICALL
 266 Java_java_io_WinNTFileSystem_canonicalizeWithPrefix0(JNIEnv *env, jobject this,
 267                                                      jstring canonicalPrefixString,
 268                                                      jstring pathWithCanonicalPrefixString)
 269 {
 270     jstring rv = NULL;
 271     WCHAR canonicalPath[MAX_PATH_LENGTH];
 272     WITH_UNICODE_STRING(env, canonicalPrefixString, canonicalPrefix) {
 273         WITH_UNICODE_STRING(env, pathWithCanonicalPrefixString, pathWithCanonicalPrefix) {
 274             int len = (int)wcslen(canonicalPrefix) + MAX_PATH;
 275             if (len > MAX_PATH_LENGTH) {
 276                 WCHAR *cp = (WCHAR*)malloc(len * sizeof(WCHAR));
 277                 if (cp != NULL) {
 278                     if (wcanonicalizeWithPrefix(canonicalPrefix,
 279                                                 pathWithCanonicalPrefix,
 280                                                 cp, len) >= 0) {
 281                       rv = (*env)->NewString(env, cp, (jsize)wcslen(cp));
 282                     }
 283                     free(cp);
 284                 } else {
 285                     JNU_ThrowOutOfMemoryError(env, "native memory allocation failed");
 286                 }
 287             } else if (wcanonicalizeWithPrefix(canonicalPrefix,
 288                                                pathWithCanonicalPrefix,
 289                                                canonicalPath, MAX_PATH_LENGTH) >= 0) {
 290                 rv = (*env)->NewString(env, canonicalPath, (jsize)wcslen(canonicalPath));
 291             }
 292         } END_UNICODE_STRING(env, pathWithCanonicalPrefix);
 293     } END_UNICODE_STRING(env, canonicalPrefix);
 294     if (rv == NULL && !(*env)->ExceptionCheck(env)) {





 295         JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");
 296     }

 297     return rv;
 298 }
 299 
 300 /* -- Attribute accessors -- */
 301 
 302 /* Check whether or not the file name in "path" is a Windows reserved
 303    device name (CON, PRN, AUX, NUL, COM[1-9], LPT[1-9]) based on the
 304    returned result from GetFullPathName, which should be in thr form of
 305    "\\.\[ReservedDeviceName]" if the path represents a reserved device
 306    name.
 307    Note1: GetFullPathName doesn't think "CLOCK$" (which is no longer
 308    important anyway) is a device name, so we don't check it here.
 309    GetFileAttributesEx will catch it later by returning 0 on NT/XP/
 310    200X.
 311 
 312    Note2: Theoretically the implementation could just lookup the table
 313    below linearly if the first 4 characters of the fullpath returned
 314    from GetFullPathName are "\\.\". The current implementation should
 315    achieve the same result. If Microsoft add more names into their
 316    reserved device name repository in the future, which probably will


 567         return JNI_FALSE;
 568     }
 569     h = CreateFileW(
 570         pathbuf,                              /* Wide char path name */
 571         GENERIC_READ | GENERIC_WRITE,         /* Read and write permission */
 572         FILE_SHARE_READ | FILE_SHARE_WRITE,   /* File sharing flags */
 573         NULL,                                 /* Security attributes */
 574         CREATE_NEW,                           /* creation disposition */
 575         FILE_ATTRIBUTE_NORMAL |
 576             FILE_FLAG_OPEN_REPARSE_POINT,     /* flags and attributes */
 577         NULL);
 578 
 579     if (h == INVALID_HANDLE_VALUE) {
 580         DWORD error = GetLastError();
 581         if ((error != ERROR_FILE_EXISTS) && (error != ERROR_ALREADY_EXISTS)) {
 582             // return false rather than throwing an exception when there is
 583             // an existing file.
 584             DWORD a = GetFileAttributesW(pathbuf);
 585             if (a == INVALID_FILE_ATTRIBUTES) {
 586                 SetLastError(error);





 587                 JNU_ThrowIOExceptionWithLastError(env, "Could not open file");

 588             }
 589         }
 590         free(pathbuf);
 591         return JNI_FALSE;
 592     }
 593     free(pathbuf);
 594     CloseHandle(h);
 595     return JNI_TRUE;
 596 }
 597 
 598 static int
 599 removeFileOrDirectory(const jchar *path)
 600 {
 601     /* Returns 0 on success */
 602     DWORD a;
 603 
 604     SetFileAttributesW(path, FILE_ATTRIBUTE_NORMAL);
 605     a = GetFileAttributesW(path);
 606     if (a == INVALID_FILE_ATTRIBUTES) {
 607         return 1;




  61 Java_java_io_WinNTFileSystem_initIDs(JNIEnv *env, jclass cls)
  62 {
  63     HMODULE handle;
  64     jclass fileClass;
  65 
  66     fileClass = (*env)->FindClass(env, "java/io/File");
  67     CHECK_NULL(fileClass);
  68     ids.path = (*env)->GetFieldID(env, fileClass, "path", "Ljava/lang/String;");
  69     CHECK_NULL(ids.path);
  70 
  71     // GetFinalPathNameByHandle requires Windows Vista or newer
  72     if (GetModuleHandleExW((GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
  73                             GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT),
  74                            (LPCWSTR)&CreateFileW, &handle) != 0)
  75     {
  76         GetFinalPathNameByHandle_func = (GetFinalPathNameByHandleProc)
  77             GetProcAddress(handle, "GetFinalPathNameByHandleW");
  78     }
  79 }
  80 
  81 static jboolean extendExceptionsWithPath = JNI_FALSE;
  82 
  83 JNIEXPORT void JNICALL
  84 Java_java_io_WinNTFileSystem_initIncludeInExceptions(JNIEnv *env, jclass cls, jboolean b)
  85 {
  86     extendExceptionsWithPath = b;
  87 }
  88 
  89 /* -- Path operations -- */
  90 
  91 extern int wcanonicalize(const WCHAR *path, WCHAR *out, int len);
  92 extern int wcanonicalizeWithPrefix(const WCHAR *canonicalPrefix, const WCHAR *pathWithCanonicalPrefix, WCHAR *out, int len);
  93 
  94 /**
  95  * Retrieves the fully resolved (final) path for the given path or NULL
  96  * if the function fails.
  97  */
  98 static WCHAR* getFinalPath(JNIEnv *env, const WCHAR *path)
  99 {
 100     HANDLE h;
 101     WCHAR *result;
 102     DWORD error;
 103 
 104     /* Need Windows Vista or newer to get the final path */
 105     if (GetFinalPathNameByHandle_func == NULL)
 106         return NULL;
 107 
 108     h = CreateFileW(path,


 247         /* we estimate the max length of memory needed as
 248            "currentDir. length + pathname.length"
 249          */
 250         int len = (int)wcslen(path);
 251         len += currentDirLength(path, len);
 252         if (len  > MAX_PATH_LENGTH - 1) {
 253             WCHAR *cp = (WCHAR*)malloc(len * sizeof(WCHAR));
 254             if (cp != NULL) {
 255                 if (wcanonicalize(path, cp, len) >= 0) {
 256                     rv = (*env)->NewString(env, cp, (jsize)wcslen(cp));
 257                 }
 258                 free(cp);
 259             } else {
 260                 JNU_ThrowOutOfMemoryError(env, "native memory allocation failed");
 261             }
 262         } else if (wcanonicalize(path, canonicalPath, MAX_PATH_LENGTH) >= 0) {
 263             rv = (*env)->NewString(env, canonicalPath, (jsize)wcslen(canonicalPath));
 264         }
 265     } END_UNICODE_STRING(env, path);
 266     if (rv == NULL && !(*env)->ExceptionCheck(env)) {
 267             if (extendExceptionsWithPath) {
 268                 WITH_PLATFORM_STRING(env, pathname, pathstr) {
 269                     JNU_ThrowByNameWithTwoMessagesAndLastError(env, "java/io/IOException", "Bad pathname", pathstr);
 270                 } END_PLATFORM_STRING(env, pathstr);
 271             } else {
 272                 JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");
 273             }
 274     }
 275     return rv;
 276 }
 277 
 278 
 279 JNIEXPORT jstring JNICALL
 280 Java_java_io_WinNTFileSystem_canonicalizeWithPrefix0(JNIEnv *env, jobject this,
 281                                                      jstring canonicalPrefixString,
 282                                                      jstring pathWithCanonicalPrefixString)
 283 {
 284     jstring rv = NULL;
 285     WCHAR canonicalPath[MAX_PATH_LENGTH];
 286     WITH_UNICODE_STRING(env, canonicalPrefixString, canonicalPrefix) {
 287         WITH_UNICODE_STRING(env, pathWithCanonicalPrefixString, pathWithCanonicalPrefix) {
 288             int len = (int)wcslen(canonicalPrefix) + MAX_PATH;
 289             if (len > MAX_PATH_LENGTH) {
 290                 WCHAR *cp = (WCHAR*)malloc(len * sizeof(WCHAR));
 291                 if (cp != NULL) {
 292                     if (wcanonicalizeWithPrefix(canonicalPrefix,
 293                                                 pathWithCanonicalPrefix,
 294                                                 cp, len) >= 0) {
 295                       rv = (*env)->NewString(env, cp, (jsize)wcslen(cp));
 296                     }
 297                     free(cp);
 298                 } else {
 299                     JNU_ThrowOutOfMemoryError(env, "native memory allocation failed");
 300                 }
 301             } else if (wcanonicalizeWithPrefix(canonicalPrefix,
 302                                                pathWithCanonicalPrefix,
 303                                                canonicalPath, MAX_PATH_LENGTH) >= 0) {
 304                 rv = (*env)->NewString(env, canonicalPath, (jsize)wcslen(canonicalPath));
 305             }
 306         } END_UNICODE_STRING(env, pathWithCanonicalPrefix);
 307     } END_UNICODE_STRING(env, canonicalPrefix);
 308     if (rv == NULL && !(*env)->ExceptionCheck(env)) {
 309         if (extendExceptionsWithPath) {
 310             WITH_PLATFORM_STRING(env, pathWithCanonicalPrefixString, path) {
 311                 JNU_ThrowByNameWithTwoMessagesAndLastError(env, "java/io/IOException", "Bad pathname", path);
 312             } END_PLATFORM_STRING(env, path);
 313         } else {
 314             JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");
 315         }
 316     }
 317     return rv;
 318 }
 319 
 320 /* -- Attribute accessors -- */
 321 
 322 /* Check whether or not the file name in "path" is a Windows reserved
 323    device name (CON, PRN, AUX, NUL, COM[1-9], LPT[1-9]) based on the
 324    returned result from GetFullPathName, which should be in thr form of
 325    "\\.\[ReservedDeviceName]" if the path represents a reserved device
 326    name.
 327    Note1: GetFullPathName doesn't think "CLOCK$" (which is no longer
 328    important anyway) is a device name, so we don't check it here.
 329    GetFileAttributesEx will catch it later by returning 0 on NT/XP/
 330    200X.
 331 
 332    Note2: Theoretically the implementation could just lookup the table
 333    below linearly if the first 4 characters of the fullpath returned
 334    from GetFullPathName are "\\.\". The current implementation should
 335    achieve the same result. If Microsoft add more names into their
 336    reserved device name repository in the future, which probably will


 587         return JNI_FALSE;
 588     }
 589     h = CreateFileW(
 590         pathbuf,                              /* Wide char path name */
 591         GENERIC_READ | GENERIC_WRITE,         /* Read and write permission */
 592         FILE_SHARE_READ | FILE_SHARE_WRITE,   /* File sharing flags */
 593         NULL,                                 /* Security attributes */
 594         CREATE_NEW,                           /* creation disposition */
 595         FILE_ATTRIBUTE_NORMAL |
 596             FILE_FLAG_OPEN_REPARSE_POINT,     /* flags and attributes */
 597         NULL);
 598 
 599     if (h == INVALID_HANDLE_VALUE) {
 600         DWORD error = GetLastError();
 601         if ((error != ERROR_FILE_EXISTS) && (error != ERROR_ALREADY_EXISTS)) {
 602             // return false rather than throwing an exception when there is
 603             // an existing file.
 604             DWORD a = GetFileAttributesW(pathbuf);
 605             if (a == INVALID_FILE_ATTRIBUTES) {
 606                 SetLastError(error);
 607                 if (extendExceptionsWithPath) {
 608                     WITH_PLATFORM_STRING(env, path, pathstr) {
 609                         JNU_ThrowByNameWithTwoMessagesAndLastError(env, "java/io/IOException", "Could not open file", pathstr);
 610                     } END_PLATFORM_STRING(env, pathstr);
 611                 } else {
 612                     JNU_ThrowIOExceptionWithLastError(env, "Could not open file");
 613                 }
 614             }
 615         }
 616         free(pathbuf);
 617         return JNI_FALSE;
 618     }
 619     free(pathbuf);
 620     CloseHandle(h);
 621     return JNI_TRUE;
 622 }
 623 
 624 static int
 625 removeFileOrDirectory(const jchar *path)
 626 {
 627     /* Returns 0 on success */
 628     DWORD a;
 629 
 630     SetFileAttributesW(path, FILE_ATTRIBUTE_NORMAL);
 631     a = GetFileAttributesW(path);
 632     if (a == INVALID_FILE_ATTRIBUTES) {
 633         return 1;


< prev index next >