< prev index next >

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

Print this page
rev 52921 : 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 int extendExceptionsWithPath = -1;
  82 
  83 static int checkExtendExceptionsWithPath(JNIEnv *env) {
  84     if (extendExceptionsWithPath == -1) {
  85         jclass cls = (*env)->FindClass(env, "java/io/FileSystem");
  86         if (cls == NULL) return -1;
  87         jmethodID hasPathInExceptionsMethod = (*env)->GetStaticMethodID(env, cls,
  88                                      "hasPathInExceptions", "()Z");
  89         if (hasPathInExceptionsMethod == NULL) return -1;
  90         jboolean res = (*env)->CallStaticBooleanMethod(env, cls, hasPathInExceptionsMethod);
  91         if (res == JNI_TRUE) {
  92             extendExceptionsWithPath = 1;
  93         } else {
  94             extendExceptionsWithPath = 0;
  95         }
  96     }
  97     return extendExceptionsWithPath;
  98 }
  99 
 100 /* -- Path operations -- */
 101 
 102 extern int wcanonicalize(const WCHAR *path, WCHAR *out, int len);
 103 extern int wcanonicalizeWithPrefix(const WCHAR *canonicalPrefix, const WCHAR *pathWithCanonicalPrefix, WCHAR *out, int len);
 104 
 105 /**
 106  * Retrieves the fully resolved (final) path for the given path or NULL
 107  * if the function fails.
 108  */
 109 static WCHAR* getFinalPath(JNIEnv *env, const WCHAR *path)
 110 {
 111     HANDLE h;
 112     WCHAR *result;
 113     DWORD error;
 114 
 115     /* Need Windows Vista or newer to get the final path */
 116     if (GetFinalPathNameByHandle_func == NULL)
 117         return NULL;
 118 
 119     h = CreateFileW(path,


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


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


< prev index next >