Add a way to copy a file in archive into filesystem.
This commit is contained in:
parent
e5e1e207b6
commit
c95a93ef1c
6 changed files with 138 additions and 1 deletions
2
atom.gyp
2
atom.gyp
|
@ -196,6 +196,8 @@
|
||||||
'atom/common/asar/archive.h',
|
'atom/common/asar/archive.h',
|
||||||
'atom/common/asar/archive_factory.cc',
|
'atom/common/asar/archive_factory.cc',
|
||||||
'atom/common/asar/archive_factory.h',
|
'atom/common/asar/archive_factory.h',
|
||||||
|
'atom/common/asar/scoped_temporary_file.cc',
|
||||||
|
'atom/common/asar/scoped_temporary_file.h',
|
||||||
'atom/common/common_message_generator.cc',
|
'atom/common/common_message_generator.cc',
|
||||||
'atom/common/common_message_generator.h',
|
'atom/common/common_message_generator.h',
|
||||||
'atom/common/crash_reporter/crash_reporter.cc',
|
'atom/common/crash_reporter/crash_reporter.cc',
|
||||||
|
|
|
@ -67,13 +67,23 @@ class Archive : public mate::Wrappable {
|
||||||
return mate::ConvertToV8(isolate, files);
|
return mate::ConvertToV8(isolate, files);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy the file out into a temporary file and returns the new path.
|
||||||
|
v8::Handle<v8::Value> CopyFileOut(v8::Isolate* isolate,
|
||||||
|
const base::FilePath& path) {
|
||||||
|
base::FilePath new_path;
|
||||||
|
if (!archive_->CopyFileOut(path, &new_path))
|
||||||
|
return v8::False(isolate);
|
||||||
|
return mate::ConvertToV8(isolate, new_path);
|
||||||
|
}
|
||||||
|
|
||||||
// mate::Wrappable:
|
// mate::Wrappable:
|
||||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate) {
|
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate) {
|
||||||
return mate::ObjectTemplateBuilder(isolate)
|
return mate::ObjectTemplateBuilder(isolate)
|
||||||
.SetValue("path", archive_->path())
|
.SetValue("path", archive_->path())
|
||||||
.SetMethod("getFileInfo", &Archive::GetFileInfo)
|
.SetMethod("getFileInfo", &Archive::GetFileInfo)
|
||||||
.SetMethod("stat", &Archive::Stat)
|
.SetMethod("stat", &Archive::Stat)
|
||||||
.SetMethod("readdir", &Archive::Readdir);
|
.SetMethod("readdir", &Archive::Readdir)
|
||||||
|
.SetMethod("copyFileOut", &Archive::CopyFileOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -7,10 +7,12 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "atom/common/asar/scoped_temporary_file.h"
|
||||||
#include "base/files/file.h"
|
#include "base/files/file.h"
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "base/pickle.h"
|
#include "base/pickle.h"
|
||||||
#include "base/json/json_string_value_serializer.h"
|
#include "base/json/json_string_value_serializer.h"
|
||||||
|
#include "base/stl_util.h"
|
||||||
#include "base/strings/string_number_conversions.h"
|
#include "base/strings/string_number_conversions.h"
|
||||||
|
|
||||||
namespace asar {
|
namespace asar {
|
||||||
|
@ -181,4 +183,23 @@ bool Archive::Readdir(const base::FilePath& path,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Archive::CopyFileOut(const base::FilePath& path, base::FilePath* out) {
|
||||||
|
if (ContainsKey(external_files_, path)) {
|
||||||
|
*out = external_files_[path]->path();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileInfo info;
|
||||||
|
if (!GetFileInfo(path, &info))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
scoped_refptr<ScopedTemporaryFile> temp_file(new ScopedTemporaryFile);
|
||||||
|
if (!temp_file->InitFromFile(path_, info.offset, info.size))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
external_files_[path] = temp_file;
|
||||||
|
*out = temp_file->path();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace asar
|
} // namespace asar
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "base/containers/hash_tables.h"
|
||||||
#include "base/files/file_path.h"
|
#include "base/files/file_path.h"
|
||||||
#include "base/memory/ref_counted.h"
|
#include "base/memory/ref_counted.h"
|
||||||
#include "base/memory/scoped_ptr.h"
|
#include "base/memory/scoped_ptr.h"
|
||||||
|
@ -17,6 +18,10 @@ class DictionaryValue;
|
||||||
|
|
||||||
namespace asar {
|
namespace asar {
|
||||||
|
|
||||||
|
class ScopedTemporaryFile;
|
||||||
|
|
||||||
|
// This class represents an asar package, and provides methods to read
|
||||||
|
// information from it.
|
||||||
class Archive : public base::RefCounted<Archive> {
|
class Archive : public base::RefCounted<Archive> {
|
||||||
public:
|
public:
|
||||||
struct FileInfo {
|
struct FileInfo {
|
||||||
|
@ -46,6 +51,9 @@ class Archive : public base::RefCounted<Archive> {
|
||||||
// Fs.readdir(path).
|
// Fs.readdir(path).
|
||||||
bool Readdir(const base::FilePath& path, std::vector<base::FilePath>* files);
|
bool Readdir(const base::FilePath& path, std::vector<base::FilePath>* files);
|
||||||
|
|
||||||
|
// Copy the file into a temporary file, and return the new path.
|
||||||
|
bool CopyFileOut(const base::FilePath& path, base::FilePath* out);
|
||||||
|
|
||||||
base::FilePath path() const { return path_; }
|
base::FilePath path() const { return path_; }
|
||||||
base::DictionaryValue* header() const { return header_.get(); }
|
base::DictionaryValue* header() const { return header_.get(); }
|
||||||
|
|
||||||
|
@ -57,6 +65,10 @@ class Archive : public base::RefCounted<Archive> {
|
||||||
uint32 header_size_;
|
uint32 header_size_;
|
||||||
scoped_ptr<base::DictionaryValue> header_;
|
scoped_ptr<base::DictionaryValue> header_;
|
||||||
|
|
||||||
|
// Cached external temporary files.
|
||||||
|
base::hash_map<base::FilePath, // NOLINT
|
||||||
|
scoped_refptr<ScopedTemporaryFile> > external_files_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(Archive);
|
DISALLOW_COPY_AND_ASSIGN(Archive);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
52
atom/common/asar/scoped_temporary_file.cc
Normal file
52
atom/common/asar/scoped_temporary_file.cc
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "atom/common/asar/scoped_temporary_file.h"
|
||||||
|
|
||||||
|
#include "base/file_util.h"
|
||||||
|
#include "base/threading/thread_restrictions.h"
|
||||||
|
|
||||||
|
namespace asar {
|
||||||
|
|
||||||
|
ScopedTemporaryFile::ScopedTemporaryFile() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedTemporaryFile::~ScopedTemporaryFile() {
|
||||||
|
if (!path_.empty()) {
|
||||||
|
base::ThreadRestrictions::ScopedAllowIO allow_io;
|
||||||
|
base::DeleteFile(path_, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScopedTemporaryFile::Init() {
|
||||||
|
if (!path_.empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
base::ThreadRestrictions::ScopedAllowIO allow_io;
|
||||||
|
return base::CreateTemporaryFile(&path_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScopedTemporaryFile::InitFromFile(const base::FilePath& path,
|
||||||
|
uint64 offset, uint64 size) {
|
||||||
|
if (!Init())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
base::File src(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
|
||||||
|
if (!src.IsValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::vector<char> buf(size);
|
||||||
|
int len = src.Read(offset, buf.data(), buf.size());
|
||||||
|
if (len != static_cast<int>(size))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
base::File dest(path_, base::File::FLAG_OPEN | base::File::FLAG_WRITE);
|
||||||
|
if (!dest.IsValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return dest.WriteAtCurrentPos(buf.data(), buf.size()) ==
|
||||||
|
static_cast<int>(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace asar
|
40
atom/common/asar/scoped_temporary_file.h
Normal file
40
atom/common/asar/scoped_temporary_file.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef ATOM_COMMON_ASAR_SCOPED_TEMPORARY_FILE_H_
|
||||||
|
#define ATOM_COMMON_ASAR_SCOPED_TEMPORARY_FILE_H_
|
||||||
|
|
||||||
|
#include "base/files/file_path.h"
|
||||||
|
#include "base/memory/ref_counted.h"
|
||||||
|
|
||||||
|
namespace asar {
|
||||||
|
|
||||||
|
// An object representing a temporary file that should be cleaned up when this
|
||||||
|
// object goes out of scope. Note that since deletion occurs during the
|
||||||
|
// destructor, no further error handling is possible if the directory fails to
|
||||||
|
// be deleted. As a result, deletion is not guaranteed by this class.
|
||||||
|
class ScopedTemporaryFile : public base::RefCounted<ScopedTemporaryFile> {
|
||||||
|
public:
|
||||||
|
ScopedTemporaryFile();
|
||||||
|
|
||||||
|
// Init an empty temporary file.
|
||||||
|
bool Init();
|
||||||
|
|
||||||
|
// Init an temporary file and fill it with content of |path|.
|
||||||
|
bool InitFromFile(const base::FilePath& path, uint64 offset, uint64 size);
|
||||||
|
|
||||||
|
base::FilePath path() const { return path_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class base::RefCounted<ScopedTemporaryFile>;
|
||||||
|
virtual ~ScopedTemporaryFile();
|
||||||
|
|
||||||
|
base::FilePath path_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(ScopedTemporaryFile);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asar
|
||||||
|
|
||||||
|
#endif // ATOM_COMMON_ASAR_SCOPED_TEMPORARY_FILE_H_
|
Loading…
Reference in a new issue