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