Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/instrument/FileSystemSupport_md.c
32285 views
/*1* Copyright (c) 2004, 2018 Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <stdio.h>26#include <stdlib.h>27#include <string.h>28#include <malloc.h>2930#include "FileSystemSupport_md.h"3132/*33* Windows implementation of file system support functions34*/3536#define slash '\\'37#define altSlash '/'3839static int isSlash(char c) {40return (c == '\\') || (c == '/');41}4243static int isLetter(char c) {44return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'));45}4647char pathSeparator() {48return ';';49}5051/* filename are case insensitive on windows */52int filenameStrcmp(const char* s1, const char* s2) {53return strcasecmp(s1, s2);54}5556char* basePath(const char* path) {57char* pos = strchr(path, slash);58char* last = NULL;59while (pos != NULL) {60last = pos;61pos++;62pos = strchr(pos, slash);63}64if (last == NULL) {65return (char*)path;66} else {67int len = (int)(last - path);68char* str = (char*)malloc(len+1);69if (str == NULL) {70fprintf(stderr, "OOM error in native tmp buffer allocation");71return NULL;72}73if (len > 0) {74memcpy(str, path, len);75}76str[len] = '\0';77return str;78}79}80818283/* -- Normalization - src/windows/classes/java/io/Win32FileSystem.java */848586/* A normal Win32 pathname contains no duplicate slashes, except possibly87* for a UNC prefix, and does not end with a slash. It may be the empty88* string. Normalized Win32 pathnames have the convenient property that89* the length of the prefix almost uniquely identifies the type of the path90* and whether it is absolute or relative:91*92* 0 relative to both drive and directory93* 1 drive-relative (begins with '\\')94* 2 absolute UNC (if first char is '\\'),95* else directory-relative (has form "z:foo")96* 3 absolute local pathname (begins with "z:\\")97*/98static int normalizePrefix(const char* path, int len, char* sb, int* sbLen) {99char c;100int src = 0;101while ((src < len) && isSlash(path[src])) src++;102if ((len - src >= 2)103&& isLetter(c = path[src])104&& path[src + 1] == ':') {105/* Remove leading slashes if followed by drive specifier.106This hack is necessary to support file URLs containing drive107specifiers (e.g., "file://c:/path"). As a side effect,108"/c:/path" can be used as an alternative to "c:/path". */109sb[(*sbLen)++] = c;110sb[(*sbLen)++] = ':';111src += 2;112} else {113src = 0;114if ((len >= 2)115&& isSlash(path[0])116&& isSlash(path[1])) {117/* UNC pathname: Retain first slash; leave src pointed at118second slash so that further slashes will be collapsed119into the second slash. The result will be a pathname120beginning with "\\\\" followed (most likely) by a host121name. */122src = 1;123sb[(*sbLen)++] = slash;124}125}126return src;127}128129/*130* Normalize the given pathname, whose length is len, starting at the given131* offset; everything before this offset is already normal.132*/133static char* normalizePath(const char* path, int len, int off) {134int src;135char* sb;136int sbLen;137138if (len == 0) return (char*)path;139if (off < 3) off = 0; /* Avoid fencepost cases with UNC pathnames */140141sb = (char*)malloc(len+1);142if (sb == NULL) {143fprintf(stderr, "OOM error in native tmp buffer allocation");144return NULL;145}146sbLen = 0;147148if (off == 0) {149/* Complete normalization, including prefix */150src = normalizePrefix(path, len, sb, &sbLen);151} else {152/* Partial normalization */153src = off;154memcpy(sb+sbLen, path, off);155sbLen += off;156}157158/* Remove redundant slashes from the remainder of the path, forcing all159slashes into the preferred slash */160while (src < len) {161char c = path[src++];162if (isSlash(c)) {163while ((src < len) && isSlash(path[src])) src++;164if (src == len) {165/* Check for trailing separator */166if ((sbLen == 2) && (sb[1] == ':')) {167/* "z:\\" */168sb[sbLen++] = slash;169break;170}171if (sbLen == 0) {172/* "\\" */173sb[sbLen++] = slash;174break;175}176if ((sbLen == 1) && (isSlash(sb[0]))) {177/* "\\\\" is not collapsed to "\\" because "\\\\" marks178the beginning of a UNC pathname. Even though it is179not, by itself, a valid UNC pathname, we leave it as180is in order to be consistent with the win32 APIs,181which treat this case as an invalid UNC pathname182rather than as an alias for the root directory of183the current drive. */184sb[sbLen++] = slash;185break;186}187/* Path does not denote a root directory, so do not append188trailing slash */189break;190} else {191sb[sbLen++] = slash;192}193} else {194sb[sbLen++] = c;195}196}197198sb[sbLen] = '\0';199return sb;200}201202/*203* Check that the given pathname is normal. If not, invoke the real204* normalizer on the part of the pathname that requires normalization.205* This way we iterate through the whole pathname string only once.206*/207char* normalize(char* path) {208int n = (int)strlen(path);209int i;210char c = 0;211int prev = 0;212for (i = 0; i < n; i++) {213char c = path[i];214if (c == altSlash)215return normalizePath(path, n, (prev == slash) ? i - 1 : i);216if ((c == slash) && (prev == slash) && (i > 1))217return normalizePath(path, n, i - 1);218if ((c == ':') && (i > 1))219return normalizePath(path, n, 0);220prev = c;221}222if (prev == slash)223return normalizePath(path, n, n - 1);224return path;225}226227228/* -- Resolution - src/windows/classes/java/io/Win32FileSystem.java */229230231char* resolve(const char* parent, const char* child) {232char* c;233char* theChars;234int parentEnd, childStart, len;235236int pn = (int)strlen(parent);237int cn = (int)strlen(child);238239if (pn == 0) return (char*)child;240if (cn == 0) return (char*)parent;241242c = (char*)child;243childStart = 0;244parentEnd = pn;245246if ((cn > 1) && (c[0] == slash)) {247if (c[1] == slash) {248/* Drop prefix when child is a UNC pathname */249childStart = 2;250} else {251/* Drop prefix when child is drive-relative */252childStart = 1;253254}255if (cn == childStart) { // Child is double slash256if (parent[pn - 1] == slash) {257char* str = strdup(parent);258str[pn-1] = '\0';259return str;260}261return (char*)parent;262}263}264265if (parent[pn - 1] == slash)266parentEnd--;267268len = parentEnd + cn - childStart;269270if (child[childStart] == slash) {271theChars = (char*)malloc(len+1);272if (theChars == NULL) {273fprintf(stderr, "OOM error in native tmp buffer allocation");274return NULL;275}276memcpy(theChars, parent, parentEnd);277memcpy(theChars+parentEnd, child+childStart, (cn-childStart));278theChars[len] = '\0';279} else {280theChars = (char*)malloc(len+2);281if (theChars == NULL) {282fprintf(stderr, "OOM error in native tmp buffer allocation");283return NULL;284}285memcpy(theChars, parent, parentEnd);286theChars[parentEnd] = slash;287memcpy(theChars+parentEnd+1, child+childStart, (cn-childStart));288theChars[len+1] = '\0';289}290return theChars;291}292293294static int prefixLength(const char* path) {295char c0, c1;296297int n = (int)strlen(path);298if (n == 0) return 0;299c0 = path[0];300c1 = (n > 1) ? path[1] : 0;301if (c0 == slash) {302if (c1 == slash) return 2; /* Absolute UNC pathname "\\\\foo" */303return 1; /* Drive-relative "\\foo" */304}305if (isLetter(c0) && (c1 == ':')) {306if ((n > 2) && (path[2] == slash))307return 3; /* Absolute local pathname "z:\\foo" */308return 2; /* Directory-relative "z:foo" */309}310return 0; /* Completely relative */311}312313314int isAbsolute(const char* path) {315int pl = prefixLength(path);316return (((pl == 2) && (path[0] == slash)) || (pl == 3));317}318319320char* fromURIPath(const char* path) {321int start = 0;322int len = (int)strlen(path);323324if ((len > 2) && (path[2] == ':')) {325// "/c:/foo" --> "c:/foo"326start = 1;327// "c:/foo/" --> "c:/foo", but "c:/" --> "c:/"328if ((len > 3) && path[len-1] == '/')329len--;330} else if ((len > 1) && path[len-1] == '/') {331// "/foo/" --> "/foo"332len--;333}334335if (start == 0 && len == (int)strlen(path)) {336return (char*)path;337} else {338char* p = (char*)malloc(len+1);339if (p == NULL) {340fprintf(stderr, "OOM error in native tmp buffer allocation");341return NULL;342}343memcpy(p, path+start, len);344p[len] = '\0';345return p;346}347}348349350