/* If this returns NULL then an exception is pending */
WCHAR*
fileToNTPath(JNIEnv *env, jobject file, jfieldID id) {
jstring path = NULL; if (file != NULL) {
path = (*env)->GetObjectField(env, file, id);
} return pathToNTPath(env, path, JNI_FALSE);
}
/* Returns the working directory for the given drive, or NULL */
WCHAR*
currentDir(int di) {
UINT dt;
WCHAR root[4]; // verify drive is valid as _wgetdcwd in the VC++ 2010 runtime // library does not handle invalid drives.
root[0] = L'A' + (WCHAR)(di - 1);
root[1] = L':';
root[2] = L'\\';
root[3] = L'\0';
dt = GetDriveTypeW(root); if (dt == DRIVE_UNKNOWN || dt == DRIVE_NO_ROOT_DIR) { return NULL;
} else { return _wgetdcwd(di, NULL, MAX_PATH);
}
}
/* We cache the length of current working dir here to avoid calling_wgetcwd()everytimeweneedtoresolvearelative path.Thispieceofcodeneedstoberevisitedifchdir makesitswayintojavaruntime.
*/
int
currentDirLength(const WCHAR* ps, int pathlen) {
WCHAR *dir; if (pathlen > 2 && ps[1] == L':' && ps[2] != L'\\') { //drive-relative
WCHAR d = ps[0]; int dirlen = 0; int di = 0; if ((d >= L'a') && (d <= L'z')) di = d - L'a' + 1; elseif ((d >= L'A') && (d <= L'Z')) di = d - L'A' + 1; elsereturn0; /* invalid drive name. */
dir = currentDir(di); if (dir != NULL){
dirlen = (int)wcslen(dir);
free(dir);
} return dirlen;
} else { staticint curDirLenCached = -1; //relative to both drive and directory if (curDirLenCached == -1) {
dir = _wgetcwd(NULL, MAX_PATH); if (dir != NULL) {
curDirLenCached = (int)wcslen(dir);
free(dir);
}
} return curDirLenCached;
}
}
abpathlen += 10; //padding
abpath = (WCHAR*)malloc(abpathlen * sizeof(WCHAR)); if (abpath) { /* Collapse instances of "foo\.." and ensure absoluteness before goingdowntoprefixing.
*/ if (_wfullpath(abpath, path, abpathlen)) {
pathbuf = getPrefixed(abpath, abpathlen);
} else { /* _wfullpath fails if the pathlength exceeds 32k wchar. Insteadofdoingmorefancythingswesimplycopythe psintothereturnbuffer,thesubsequentwin32APIwill probablyfailwithFileNotFoundException,whichisexpected
*/
pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR)); if (pathbuf != 0) {
wcscpy(pathbuf, path);
}
}
free(abpath);
} return pathbuf;
}
/* If this returns NULL then an exception is pending */
WCHAR*
pathToNTPath(JNIEnv *env, jstring path, jboolean throwFNFE) { int pathlen = 0;
WCHAR *pathbuf = NULL; int max_path = 248; /* CreateDirectoryW() has the limit of 248 */
WITH_UNICODE_STRING(env, path, ps) {
pathlen = (int)wcslen(ps); if (pathlen != 0) { if (pathlen > 2 &&
(ps[0] == L'\\' && ps[1] == L'\\' || //UNC
ps[1] == L':' && ps[2] == L'\\')) //absolute
{ if (pathlen > max_path - 1) {
pathbuf = prefixAbpath(ps, pathlen, pathlen);
} else {
pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR)); if (pathbuf != 0) {
wcscpy(pathbuf, ps);
}
}
} else { /* If the path came in as a relative path, need to verify if itsabsoluteformisbiggerthanmax_pathornot,ifyes needto(1)convertittoabsoluteand(2)prefix.Thisis obviouslyaburdentoallrelativepaths(Thecurrentdir/len for"drive&directory"relativepathiscached,soweonly calculateitoncebutfor"drive-relativepathwecall _wgetdcwd()andwcslen()everytime),butahitwehave totakeifwewanttosupportrelativepathbeyondmax_path. Thereisnowaytopredicthowlongtheabsolutepathwillbe (thereforeallocatethesufficientmemoryblock)beforecalling _wfullpath(),wehavetogetthelengthof"current"dirfirst.
*/ int dirlen = currentDirLength(ps, pathlen); if (dirlen + pathlen + 1 > max_path - 1) {
pathbuf = prefixAbpath(ps, pathlen, dirlen + pathlen);
} else {
pathbuf = (WCHAR*)malloc((pathlen + 6) * sizeof(WCHAR)); if (pathbuf != 0) {
wcscpy(pathbuf, ps);
}
}
}
}
} END_UNICODE_STRING(env, ps);
if (pathlen == 0) { if (throwFNFE == JNI_TRUE) { if (!(*env)->ExceptionCheck(env)) {
throwFileNotFoundException(env, path);
} return NULL;
} else {
pathbuf = (WCHAR*)malloc(sizeof(WCHAR)); if (pathbuf != NULL) {
pathbuf[0] = L'\0';
}
}
} if (pathbuf == 0) {
JNU_ThrowOutOfMemoryError(env, "native memory allocation failed");
} return pathbuf;
}
/* These are functions that use a handle fd instead of the
old C style int fd as is used in HPI layer */
staticint
handleNonSeekAvailable(FD, long *); staticint
handleStdinAvailable(FD, long *);
int
handleAvailable(FD fd, jlong *pbytes) {
HANDLE h = (HANDLE)fd;
DWORD type = 0;
type = GetFileType(h); /* Handle is for keyboard or pipe */ if (type == FILE_TYPE_CHAR || type == FILE_TYPE_PIPE) { int ret; long lpbytes;
HANDLE stdInHandle = GetStdHandle(STD_INPUT_HANDLE); if (stdInHandle == h) {
ret = handleStdinAvailable(fd, &lpbytes); /* keyboard */
} else {
ret = handleNonSeekAvailable(fd, &lpbytes); /* pipe */
}
(*pbytes) = (jlong)(lpbytes); return ret;
} /* Handle is for regular file */ if (type == FILE_TYPE_DISK) {
jlong current, end;
LARGE_INTEGER filesize;
current = handleLseek(fd, 0, SEEK_CUR); if (current < 0) { returnFALSE;
} if (GetFileSizeEx(h, &filesize) == 0) { returnFALSE;
}
end = long_to_jlong(filesize.QuadPart);
*pbytes = end - current; returnTRUE;
} returnFALSE;
}
staticint
handleNonSeekAvailable(FD fd, long *pbytes) { /* This is used for available on non-seekable devices *(likebothnamedandanonymouspipes,suchaspipes *connectedtoanexec'dprocess). *StandardInputisaspecialcase. *
*/
HANDLE han;
if ((han = (HANDLE) fd) == INVALID_HANDLE_VALUE) { returnFALSE;
}
if (! PeekNamedPipe(han, NULL, 0, NULL, pbytes, NULL)) { /* PeekNamedPipe fails when at EOF. In that case we *simplymake*pbytes=0whichisconsistentwiththe *behaviorwegetonSolariswhenanfdisatEOF. *TheonlyalternativeistoraiseandException, *whichisn'treallywarranted.
*/ if (GetLastError() != ERROR_BROKEN_PIPE) { returnFALSE;
}
*pbytes = 0;
} returnTRUE;
}
staticint
handleStdinAvailable(FD fd, long *pbytes) {
HANDLE han;
DWORD numEventsRead = 0; /* Number of events read from buffer */
DWORD numEvents = 0; /* Number of events in buffer */
DWORD i = 0; /* Loop index */
DWORD curLength = 0; /* Position marker */
DWORD actualLength = 0; /* Number of bytes readable */ BOOL error = FALSE; /* Error holder */
INPUT_RECORD *lpBuffer; /* Pointer to records of input events */
DWORD bufferSize = 0;
if ((han = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) { returnFALSE;
}
/* Construct an array of input records in the console buffer */
error = GetNumberOfConsoleInputEvents(han, &numEvents); if (error == 0) { return handleNonSeekAvailable(fd, pbytes);
}
/* lpBuffer must fit into 64K or else PeekConsoleInput fails */ if (numEvents > MAX_INPUT_EVENTS) {
numEvents = MAX_INPUT_EVENTS;
}
// Function to close the fd held by this FileDescriptor and set fd to -1. void
fileDescriptorClose(JNIEnv *env, jobject this)
{
FD fd = (*env)->GetLongField(env, this, IO_handle_fdID);
HANDLE h = (HANDLE)fd; if ((*env)->ExceptionOccurred(env)) { return;
}
if (h == INVALID_HANDLE_VALUE) { return;
}
/* Set the fd to -1 before closing it so that the timing window *ofotherthreadsusingthewrongfd(closedbutrecycledfd, *thatgetsre-openedwithsomeotherfilename)isreduced. *Practicallythechanceofitsoccurrenceislow,however,weare *takingextraprecautionoverhere.
*/
(*env)->SetLongField(env, this, IO_handle_fdID, -1); if ((*env)->ExceptionOccurred(env)) { return;
}
if (CloseHandle(h) == 0) { /* Returns zero on failure */
JNU_ThrowIOExceptionWithLastError(env, "close failed");
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.