/*
* 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.
*/
/**
*/
class UnixPath
extends AbstractPath
{
// FIXME - eliminate this reference to reduce space
// internal representation
private final byte[] path;
// String representation (created lazily)
// cached hashcode (created lazily, no need to be volatile)
private int hash;
// array of offsets of elements in path (created lazily)
private volatile int[] offsets;
}
// removes redundant slashes and checks for invalid characters
}
// package-private
// removes redundant slashes and check input for invalid characters
char prevChar = 0;
for (int i=0; i < n; i++) {
checkNotNul(input, c);
prevChar = c;
}
if (prevChar == '/')
return input;
}
if (c == '\u0000')
}
if (len == 0)
return input;
int n = len;
if (n == 0)
return "/";
if (off > 0)
char prevChar = 0;
for (int i=off; i < n; i++) {
continue;
checkNotNul(input, c);
prevChar = c;
}
}
// encodes the given path-string into a sequence of bytes
}
// size output buffer for worse-case size
// encode
boolean error;
if (!cr.isUnderflow()) {
error = true;
} else {
}
if (error) {
throw new InvalidPathException(input,
"Malformed input or input contains unmappable chacraters");
}
// trim result to actual length if required
return ba;
}
// package-private
byte[] asByteArray() {
return path;
}
byte[] getByteArrayForSysCalls() {
// resolve against default directory if required (chdir allowed or
// file system default directory is not working directory)
} else {
if (!isEmpty()) {
return path;
} else {
// empty path case will access current directory
byte[] here = { '.' };
return here;
}
}
}
// use this message when throwing exceptions
return toString();
}
// use this path for permission checks
return new String(getByteArrayForSysCalls());
} else {
return toString();
}
}
// Checks that the given file is a UnixPath
throw new NullPointerException();
throw new ProviderMismatchException();
}
// create offset list if not already created
private void initOffsets() {
// count names
count = 0;
index = 0;
if (isEmpty()) {
// empty path has one name
count = 1;
} else {
if (c != '/') {
count++;
index++;
}
}
}
// populate offsets
count = 0;
index = 0;
if (c == '/') {
index++;
} else {
index++;
}
}
synchronized (this) {
}
}
}
// returns {@code true} if this path is an empty path
private boolean isEmpty() {
}
// returns an empty path
}
return fs;
}
return getFileSystem().rootDirectory();
} else {
return null;
}
}
initOffsets();
// no elements so no name
if (count == 0)
return null;
// one name element and no root component
return this;
}
initOffsets();
if (count == 0) {
// no elements so no parent
return null;
}
if (len <= 0) {
// parent is root only (may be null)
return getRoot();
}
}
public int getNameCount() {
initOffsets();
}
initOffsets();
if (index < 0)
throw new IllegalArgumentException();
throw new IllegalArgumentException();
int len;
} else {
}
// construct result
}
initOffsets();
if (beginIndex < 0)
throw new IllegalArgumentException();
throw new IllegalArgumentException();
throw new IllegalArgumentException();
if (beginIndex >= endIndex) {
throw new IllegalArgumentException();
}
// starting offset and length
int len;
} else {
}
// construct result
}
public boolean isAbsolute() {
}
// Resolve child against given base
if (childLength == 0)
return base;
return child;
byte[] result;
} else {
}
return result;
}
}
}
return emptyPath();
// can only relativize paths of the same type
throw new IllegalArgumentException("'other' is different type of Path");
// this path is the empty path
if (this.isEmpty())
return other;
int bn = this.getNameCount();
// skip matching names
int i = 0;
while (i < n) {
break;
i++;
}
if (i < cn) {
// remaining name components in other
if (dotdots == 0)
return remainder;
// other is the empty path
// result is a "../" for each remaining name in base
// followed by the remaining names in other. If the remainder is
// the empty path then we don't add the final trailing slash.
if (isOtherEmpty) {
len--;
}
int pos = 0;
while (dotdots > 0) {
if (isOtherEmpty) {
} else {
}
dotdots--;
}
} else {
// no remaining names in other so result is simply a sequence of ".."
int pos = 0;
while (dotdots > 0) {
// no tailing slash at the end
if (dotdots > 1)
dotdots--;
}
}
}
final int count = getNameCount();
if (count == 0)
return this;
boolean hasDotDot = false; // has at least one ..
boolean isAbsolute = isAbsolute();
// first pass:
// 1. compute length of names
// 2. mark all occurences of "." to ignore
// 3. and look for any occurences of ".."
for (int i=0; i<count; i++) {
int len;
} else {
}
if (len == 1) {
ignore[i] = true; // ignore "."
remaining--;
}
else {
hasDotDot = true;
}
}
}
// multiple passes to eliminate all occurences of name/..
if (hasDotDot) {
int prevRemaining;
do {
int prevName = -1;
for (int i=0; i<count; i++) {
if (ignore[i])
continue;
// not a ".."
if (size[i] != 2) {
prevName = i;
continue;
}
prevName = i;
continue;
}
// ".." found
if (prevName >= 0) {
// name/<ignored>/.. found so mark name and ".." to be
// ignored
ignore[i] = true;
prevName = -1;
} else {
// Case: /<ignored>/.. so mark ".." as ignored
if (isAbsolute) {
boolean hasPrevious = false;
for (int j=0; j<i; j++) {
if (!ignore[j]) {
hasPrevious = true;
break;
}
}
if (!hasPrevious) {
// all proceeding names are ignored
ignore[i] = true;
remaining--;
}
}
}
}
} while (prevRemaining > remaining);
}
// no redundant names
return this;
// corner case - all names removed
if (remaining == 0) {
}
// compute length of result
if (isAbsolute)
len++;
for (int i=0; i<count; i++) {
if (!ignore[i])
}
// copy names into result
int pos = 0;
if (isAbsolute)
for (int i=0; i<count; i++) {
if (!ignore[i]) {
if (--remaining > 0) {
}
}
}
}
return false;
// other path is longer
return false;
int thisOffsetCount = getNameCount();
// other path has no name elements
}
// given path has more elements that this path
if (thatOffsetCount > thisOffsetCount)
return false;
// same number of elements so must be exact match
if ((thatOffsetCount == thisOffsetCount) &&
return false;
}
// check offsets of elements match
for (int i=0; i<thatOffsetCount; i++) {
return false;
}
// offsets match so need to compare bytes
int i=0;
return false;
i++;
}
// final check that match is on name boundary
return false;
return true;
}
return false;
// other path is longer
return false;
// other path is the empty path
return false;
// other path is absolute so this path must be absolute
return false;
int thisOffsetCount = getNameCount();
// given path has more elements that this path
if (thatOffsetCount > thisOffsetCount) {
return false;
} else {
// same number of elements
if (thatOffsetCount == thisOffsetCount) {
if (thisOffsetCount == 0)
return true;
int expectedLen = thisLen;
expectedLen--;
if (thatLen != expectedLen)
return false;
} else {
// this path has more elements so given path must be relative
if (that.isAbsolute())
return false;
}
}
// compare bytes
return false;
return false;
}
return true;
}
int k = 0;
while (k < n) {
}
k++;
}
}
}
return false;
}
public int hashCode() {
// OK if two or more threads compute hash
int h = hash;
if (h == 0) {
}
hash = h;
}
return h;
}
// OK if two or more threads create a String
if (stringValue == null) {
}
return stringValue;
}
// -- file operations --
// package-private
if (!followLinks) {
if (!supportsNoFollowLinks())
throw new IOException("NOFOLLOW_LINKS is not supported on this platform");
flags |= O_NOFOLLOW;
}
try {
} catch (UnixException x) {
// HACK: EINVAL instead of ELOOP on Solaris 10 prior to u4 (see 6460380)
x.getMessage() + " or unable to access attributes of symbolic link");
x.rethrowAsIOException(this);
return -1; // keep compile happy
}
}
void checkRead() {
}
void checkWrite() {
}
void checkDelete() {
}
if (isAbsolute()) {
return this;
}
// The path is relative so need to resolve against default directory,
// taking care not to reveal the user.dir
}
return new UnixPath(getFileSystem(),
}
checkRead();
// if resolving links then use realpath
try {
} catch (UnixException x) {
x.rethrowAsIOException(this);
}
}
// if not resolving links then eliminate "." and also ".."
// where the previous element is not a link.
// eliminate "."
continue;
// cannot eliminate ".." if previous element is a link
{
try {
} catch (UnixException x) {
}
if (!attrs.isSymbolicLink()) {
}
continue;
}
}
}
// check file exists (without following links)
try {
} catch (UnixException x) {
}
return result;
}
return UnixUriUtils.toUri(this);
}
throws IOException
{
throw new NullPointerException();
if (!(watcher instanceof AbstractWatchService))
throw new ProviderMismatchException();
checkRead();
}
}