summaryrefslogtreecommitdiff
path: root/Source/WebCore/platform/FileSystem.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/platform/FileSystem.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/platform/FileSystem.cpp')
-rw-r--r--Source/WebCore/platform/FileSystem.cpp234
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