/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* Pathname canonicalization for Win32 file systems
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <windows.h>
#include <winbase.h>
#include <errno.h>
#include "io_util_md.h"
/* Copy bytes to dst, not going past dend; return dst + number of bytes copied,
or NULL if dend would have been exceeded. If first != '\0', copy that byte
before copying bytes from src to send - 1. */
static char *
{
if (first != '\0') {
if (q < dend) {
*q++ = first;
} else {
return NULL;
}
}
return NULL;
}
while (p < send) {
*q++ = *p++;
}
return q;
}
/* Wide character version of cp */
static WCHAR*
{
if (first != L'\0') {
if (q < dend) {
*q++ = first;
} else {
return NULL;
}
}
return NULL;
}
while (p < send)
*q++ = *p++;
return q;
}
/* Find first instance of '\\' at or following start. Return the address of
that byte or the address of the null terminator if '\\' is not found. */
static char *
{
char *p = start;
int c;
while ((c = *p) && (c != '\\')) {
}
return p;
}
/* Wide character version of nextsep */
static WCHAR *
{
int c;
while ((c = *p) && (c != L'\\'))
p++;
return p;
}
/* Tell whether the given string contains any wildcard characters */
static int
{
char *p = start;
int c;
while (c = *p) {
if ((c == '*') || (c == '?')) return 1;
}
return 0;
}
/* Wide character version of wild */
static int
{
int c;
while (c = *p) {
if ((c == L'*') || (c == L'?'))
return 1;
p++;
}
return 0;
}
/* Tell whether the given string contains prohibited combinations of dots.
In the canonicalized form no path element may have dots at its end.
Allowed canonical paths: c:\xa...dksd\..ksa\.lk c:\...a\.b\cd..x.x
Prohibited canonical paths: c:\..\x c:\x.\d c:\...
*/
static int
{
char *p = start;
while (*p) {
return 0; // no more dots
p++; // next char
while ((*p) == '.') // go to the end of dots
p++;
if (*p && (*p != '\\')) // path element does not end with a dot
p++; // go to the next char
else
return 1; // path element does end with a dot - prohibited
}
return 0; // no prohibited combinations of dots found
}
/* Wide character version of dots */
static int
{
while (*p) {
return 0; // no more dots
p++; // next char
while ((*p) == L'.') // go to the end of dots
p++;
if (*p && (*p != L'\\')) // path element does not end with a dot
p++; // go to the next char
else
return 1; // path element does end with a dot - prohibited
}
return 0; // no prohibited combinations of dots found
}
/* If the lookup of a particular prefix fails because the file does not exist,
because it is of the wrong type, because access is denied, or because the
network is unreachable then canonicalization does not fail, it terminates
successfully after copying the rest of the original path to the result path.
Other I/O errors cause an error return.
*/
int
{
if ((errval == ERROR_FILE_NOT_FOUND)
|| (errval == ERROR_DIRECTORY)
|| (errval == ERROR_PATH_NOT_FOUND)
|| (errval == ERROR_BAD_NETPATH)
|| (errval == ERROR_BAD_NET_NAME)
|| (errval == ERROR_ACCESS_DENIED)
|| (errval == ERROR_NETWORK_UNREACHABLE)
|| (errval == ERROR_NETWORK_ACCESS_DENIED)) {
return 0;
}
#ifdef DEBUG_PATH
#endif
return 1;
}
/* Convert a pathname to canonical form. The input orig_path is assumed to
have been converted to native form already, via JVM_NativePath(). This is
necessary because _fullpath() rejects duplicate separator characters on
Win95, though it accepts them on NT. */
int
{
HANDLE h;
/* Reject paths that contain wildcards */
return -1;
}
/* Collapse instances of "foo\.." and ensure absoluteness. Note that
contrary to the documentation, the _fullpath procedure does not require
the drive to be available. It also does not reliably change all
occurrences of '/' to '\\' on Win95, so now JVM_NativePath does that. */
return -1;
}
/* Correction for Win95: _fullpath may leave a trailing "\\"
on a UNC pathname */
p[-1] = '\0';
}
}
return -1;
/* Copy prefix, assuming path is absolute */
/* Drive specifier */
return -1;
}
src += 2;
/* UNC pathname */
char *p;
if (!*p) {
/* A UNC pathname must begin with "\\\\host\\share",
so reject this path as invalid if there is no share name */
return -1;
}
return -1;
}
src = p;
} else {
/* Invalid path */
return -1;
}
/* Windows 95/98/Me bug - FindFirstFile fails on network mounted drives */
/* for root pathes like "E:\" . If the path has this form, we should */
/* simply return it, it is already canonicalized. */
/* At this point we have already copied the drive specifier ("z:")*/
/* so we need to copy "\" and the null character. */
return 0;
}
/* At this point we have copied either a drive specifier ("z:") or a UNC
prefix ("\\\\host\\share") to the result buffer, and src points to the
first byte of the remainder of the path. We now scan through the rest
of the path, looking up each prefix in order to find the true name of
the last element of each prefix, thereby computing the full true name of
the original path. */
while (*src) {
char c = *p;
*p = '\0'; /* Temporarily clear separator */
*p = c; /* Restore separator */
if (h != INVALID_HANDLE_VALUE) {
/* Lookup succeeded; append true name to result and continue */
FindClose(h);
return -1;
}
src = p;
continue;
} else {
if (!lastErrorReportable()) {
return -1;
}
break;
} else {
return -1;
}
}
}
return -1;
}
*dst = '\0';
return 0;
}
/* Convert a pathname to canonical form. The input prefix is assumed
to be in canonical form already, and the trailing filename must not
that are rejected by the canonicalize() routine above. This
routine is present to allow the canonicalization prefix cache to be
used while still returning canonical names with the correct
capitalization. */
int
canonicalizeWithPrefix(char* canonicalPrefix, char* pathWithCanonicalPrefix, char *result, int size)
{
HANDLE h;
if (h != INVALID_HANDLE_VALUE) {
/* Lookup succeeded; concatenate true name to prefix */
FindClose(h);
return -1;
}
return -1;
}
} else {
if (!lastErrorReportable()) {
return -1;
}
} else {
return -1;
}
}
return -1;
}
*dst = '\0';
return 0;
}
/* Wide character version of canonicalize. Size is a wide-character size. */
int
{
HANDLE h;
/* Reject paths that contain wildcards */
return -1;
}
return -1;
/* Collapse instances of "foo\.." and ensure absoluteness. Note that
contrary to the documentation, the _fullpath procedure does not require
the drive to be available. */
goto err;
}
goto err;
/* Copy prefix, assuming path is absolute */
c = src[0];
if (((c <= L'z' && c >= L'a') || (c <= L'Z' && c >= L'A'))
/* Drive specifier */
goto err;
}
src += 2;
/* UNC pathname */
WCHAR *p;
if (!*p) {
/* A UNC pathname must begin with "\\\\host\\share",
so reject this path as invalid if there is no share name */
goto err;
}
goto err;
src = p;
} else {
/* Invalid path */
goto err;
}
/* At this point we have copied either a drive specifier ("z:") or a UNC
prefix ("\\\\host\\share") to the result buffer, and src points to the
first byte of the remainder of the path. We now scan through the rest
of the path, looking up each prefix in order to find the true name of
the last element of each prefix, thereby computing the full true name of
the original path. */
while (*src) {
WCHAR c = *p;
int pathlen;
*p = L'\0'; /* Temporarily clear separator */
} else
*p = c; /* Restore separator */
if (h != INVALID_HANDLE_VALUE) {
/* Lookup succeeded; append true name to result and continue */
FindClose(h);
goto err;
}
src = p;
continue;
} else {
if (!lastErrorReportable()) {
goto err;
}
break;
} else {
goto err;
}
}
}
goto err;
}
*dst = L'\0';
return 0;
err:
return -1;
}
/* Wide character version of canonicalizeWithPrefix. */
int
wcanonicalizeWithPrefix(WCHAR *canonicalPrefix, WCHAR *pathWithCanonicalPrefix, WCHAR *result, int size)
{
HANDLE h;
int pathlen;
} else
if (h != INVALID_HANDLE_VALUE) {
/* Lookup succeeded; append true name to result and continue */
FindClose(h);
return -1;
}
return -1;
}
} else {
if (!lastErrorReportable()) {
return -1;
}
} else {
return -1;
}
}
return -1;
}
*dst = L'\0';
return 0;
}
/* The appropriate location of getPrefixed() should be io_util_md.c, but
java.lang.instrument package has hardwired canonicalize_md.c into their
dll, to avoid complicate solution such as including io_util_md.c into
that package, as a workaround we put this method here.
*/
/* copy \\?\ or \\?\UNC\ to the front of path*/
if (pathbuf != 0) {
/* if it already has a \\?\ don't do the prefix */
} else {
/* only UNC pathname includes double slashes here */
}
} else {
}
}
return pathbuf;
}