diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/platform/FileSystem.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/platform/FileSystem.cpp')
-rw-r--r-- | Source/WebCore/platform/FileSystem.cpp | 234 |
1 files changed, 224 insertions, 10 deletions
diff --git a/Source/WebCore/platform/FileSystem.cpp b/Source/WebCore/platform/FileSystem.cpp index 4e0d9d66c..704d0b8ab 100644 --- a/Source/WebCore/platform/FileSystem.cpp +++ b/Source/WebCore/platform/FileSystem.cpp @@ -1,5 +1,6 @@ /* - * Copyright (C) 2007, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2007-2017 Apple Inc. All rights reserved. + * Copyright (C) 2015 Canon Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,9 +27,18 @@ #include "config.h" #include "FileSystem.h" +#include "ScopeGuard.h" #include <wtf/HexNumber.h> +#include <wtf/text/CString.h> #include <wtf/text/StringBuilder.h> +#if !OS(WINDOWS) +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <unistd.h> +#endif + namespace WebCore { // The following lower-ASCII characters need escaping to be used in a filename @@ -73,21 +83,46 @@ static const bool needsEscaping[128] = { /* 78-7F */ false, false, false, false, true, false, false, true, }; -static inline bool shouldEscapeUChar(UChar c) +static inline bool shouldEscapeUChar(UChar character, UChar previousCharacter, UChar nextCharacter) { - return c > 127 ? false : needsEscaping[c]; + if (character <= 127) + return needsEscaping[character]; + + if (U16_IS_LEAD(character) && !U16_IS_TRAIL(nextCharacter)) + return true; + + if (U16_IS_TRAIL(character) && !U16_IS_LEAD(previousCharacter)) + return true; + + return false; } String encodeForFileName(const String& inputString) { - StringBuilder result; - StringImpl* stringImpl = inputString.impl(); unsigned length = inputString.length(); + if (!length) + return inputString; + + StringBuilder result; + result.reserveCapacity(length); + + UChar previousCharacter; + UChar character = 0; + UChar nextCharacter = inputString[0]; for (unsigned i = 0; i < length; ++i) { - UChar character = (*stringImpl)[i]; - if (shouldEscapeUChar(character)) { - result.append('%'); - appendByteAsHex(character, result); + previousCharacter = character; + character = nextCharacter; + nextCharacter = i + 1 < length ? inputString[i + 1] : 0; + + if (shouldEscapeUChar(character, previousCharacter, nextCharacter)) { + if (character <= 255) { + result.append('%'); + appendByteAsHex(character, result); + } else { + result.appendLiteral("%+"); + appendByteAsHex(character >> 8, result); + appendByteAsHex(character, result); + } } else result.append(character); } @@ -95,7 +130,130 @@ String encodeForFileName(const String& inputString) return result.toString(); } -#if !PLATFORM(MAC) || PLATFORM(IOS) +String decodeFromFilename(const String& inputString) +{ + unsigned length = inputString.length(); + if (!length) + return inputString; + + StringBuilder result; + result.reserveCapacity(length); + + for (unsigned i = 0; i < length; ++i) { + if (inputString[i] != '%') { + result.append(inputString[i]); + continue; + } + + // If the input string is a valid encoded filename, it must be at least 2 characters longer + // than the current index to account for this percent encoded value. + if (i + 2 >= length) + return { }; + + if (inputString[i+1] != '+') { + if (!isASCIIHexDigit(inputString[i + 1])) + return { }; + if (!isASCIIHexDigit(inputString[i + 2])) + return { }; + result.append(toASCIIHexValue(inputString[i + 1], inputString[i + 2])); + i += 2; + continue; + } + + // If the input string is a valid encoded filename, it must be at least 5 characters longer + // than the current index to account for this percent encoded value. + if (i + 5 >= length) + return { }; + + if (!isASCIIHexDigit(inputString[i + 2])) + return { }; + if (!isASCIIHexDigit(inputString[i + 3])) + return { }; + if (!isASCIIHexDigit(inputString[i + 4])) + return { }; + if (!isASCIIHexDigit(inputString[i + 5])) + return { }; + + result.append(toASCIIHexValue(inputString[i + 2], inputString[i + 3]) << 8 | toASCIIHexValue(inputString[i + 4], inputString[i + 5])); + i += 5; + } + + return result.toString(); +} + +String lastComponentOfPathIgnoringTrailingSlash(const String& path) +{ +#if OS(WINDOWS) + char pathSeparator = '\\'; +#else + char pathSeparator = '/'; +#endif + + auto position = path.reverseFind(pathSeparator); + if (position == notFound) + return path; + + size_t endOfSubstring = path.length() - 1; + if (position == endOfSubstring) { + --endOfSubstring; + position = path.reverseFind(pathSeparator, endOfSubstring); + } + + return path.substring(position + 1, endOfSubstring - position); +} + +bool appendFileContentsToFileHandle(const String& path, PlatformFileHandle& target) +{ + auto source = openFile(path, OpenForRead); + + if (!isHandleValid(source)) + return false; + + static int bufferSize = 1 << 19; + Vector<char> buffer(bufferSize); + + ScopeGuard fileCloser([source]() { + PlatformFileHandle handle = source; + closeFile(handle); + }); + + do { + int readBytes = readFromFile(source, buffer.data(), bufferSize); + + if (readBytes < 0) + return false; + + if (writeToFile(target, buffer.data(), readBytes) != readBytes) + return false; + + if (readBytes < bufferSize) + return true; + } while (true); + + ASSERT_NOT_REACHED(); +} + + +bool filesHaveSameVolume(const String& fileA, const String& fileB) +{ + auto fsRepFileA = fileSystemRepresentation(fileA); + auto fsRepFileB = fileSystemRepresentation(fileB); + + if (fsRepFileA.isNull() || fsRepFileB.isNull()) + return false; + + bool result = false; + + auto fileADev = getFileDeviceId(fsRepFileA); + auto fileBDev = getFileDeviceId(fsRepFileB); + + if (fileADev && fileBDev) + result = (fileADev == fileBDev); + + return result; +} + +#if !PLATFORM(MAC) void setMetadataURL(String&, const String&, const String&) { @@ -113,4 +271,60 @@ bool excludeFromBackup(const String&) #endif +MappedFileData::~MappedFileData() +{ +#if !OS(WINDOWS) + if (!m_fileData) + return; + munmap(m_fileData, m_fileSize); +#endif +} + +MappedFileData::MappedFileData(const String& filePath, bool& success) +{ +#if OS(WINDOWS) + // FIXME: Implement mapping + success = false; +#else + CString fsRep = fileSystemRepresentation(filePath); + int fd = !fsRep.isNull() ? open(fsRep.data(), O_RDONLY) : -1; + if (fd < 0) { + success = false; + return; + } + + struct stat fileStat; + if (fstat(fd, &fileStat)) { + close(fd); + success = false; + return; + } + + unsigned size; + if (!WTF::convertSafely(fileStat.st_size, size)) { + close(fd); + success = false; + return; + } + + if (!size) { + close(fd); + success = true; + return; + } + + void* data = mmap(0, size, PROT_READ, MAP_FILE | MAP_SHARED, fd, 0); + close(fd); + + if (data == MAP_FAILED) { + success = false; + return; + } + + success = true; + m_fileData = data; + m_fileSize = size; +#endif +} + } // namespace WebCore |