Merge pull request #1642 from atom/archive-update-header
Keep asar archive's file opened in the archive's whole life time
This commit is contained in:
commit
e5380fd671
6 changed files with 59 additions and 30 deletions
|
@ -88,6 +88,13 @@ class Archive : public mate::Wrappable {
|
|||
return mate::ConvertToV8(isolate, new_path);
|
||||
}
|
||||
|
||||
// Return the file descriptor.
|
||||
int GetFD() const {
|
||||
if (!archive_)
|
||||
return -1;
|
||||
return archive_->GetFD();
|
||||
}
|
||||
|
||||
// Free the resources used by archive.
|
||||
void Destroy() {
|
||||
archive_.reset();
|
||||
|
@ -102,6 +109,7 @@ class Archive : public mate::Wrappable {
|
|||
.SetMethod("readdir", &Archive::Readdir)
|
||||
.SetMethod("realpath", &Archive::Realpath)
|
||||
.SetMethod("copyFileOut", &Archive::CopyFileOut)
|
||||
.SetMethod("getFd", &Archive::GetFD)
|
||||
.SetMethod("destroy", &Archive::Destroy);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
|
||||
#include "atom/common/asar/archive.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -104,6 +108,7 @@ bool FillFileInfoWithNode(Archive::FileInfo* info,
|
|||
|
||||
Archive::Archive(const base::FilePath& path)
|
||||
: path_(path),
|
||||
file_(path_, base::File::FLAG_OPEN | base::File::FLAG_READ),
|
||||
header_size_(0) {
|
||||
}
|
||||
|
||||
|
@ -111,15 +116,14 @@ Archive::~Archive() {
|
|||
}
|
||||
|
||||
bool Archive::Init() {
|
||||
base::File file(path_, base::File::FLAG_OPEN | base::File::FLAG_READ);
|
||||
if (!file.IsValid())
|
||||
if (!file_.IsValid())
|
||||
return false;
|
||||
|
||||
std::vector<char> buf;
|
||||
int len;
|
||||
|
||||
buf.resize(8);
|
||||
len = file.ReadAtCurrentPos(buf.data(), buf.size());
|
||||
len = file_.ReadAtCurrentPos(buf.data(), buf.size());
|
||||
if (len != static_cast<int>(buf.size())) {
|
||||
PLOG(ERROR) << "Failed to read header size from " << path_.value();
|
||||
return false;
|
||||
|
@ -132,7 +136,7 @@ bool Archive::Init() {
|
|||
}
|
||||
|
||||
buf.resize(size);
|
||||
len = file.ReadAtCurrentPos(buf.data(), buf.size());
|
||||
len = file_.ReadAtCurrentPos(buf.data(), buf.size());
|
||||
if (len != static_cast<int>(buf.size())) {
|
||||
PLOG(ERROR) << "Failed to read header from " << path_.value();
|
||||
return false;
|
||||
|
@ -250,7 +254,7 @@ bool Archive::CopyFileOut(const base::FilePath& path, base::FilePath* out) {
|
|||
}
|
||||
|
||||
scoped_ptr<ScopedTemporaryFile> temp_file(new ScopedTemporaryFile);
|
||||
if (!temp_file->InitFromFile(path_, info.offset, info.size))
|
||||
if (!temp_file->InitFromFile(&file_, info.offset, info.size))
|
||||
return false;
|
||||
|
||||
*out = temp_file->path();
|
||||
|
@ -258,4 +262,18 @@ bool Archive::CopyFileOut(const base::FilePath& path, base::FilePath* out) {
|
|||
return true;
|
||||
}
|
||||
|
||||
int Archive::GetFD() const {
|
||||
if (!file_.IsValid())
|
||||
return -1;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
return
|
||||
_open_osfhandle(reinterpret_cast<intptr_t>(file_.GetPlatformFile()), 0);
|
||||
#elif defined(OS_POSIX)
|
||||
return file_.GetPlatformFile();
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace asar
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "base/containers/scoped_ptr_hash_map.h"
|
||||
#include "base/files/file.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
|
||||
|
@ -59,11 +60,15 @@ class Archive {
|
|||
// For unpacked file, this method will return its real path.
|
||||
bool CopyFileOut(const base::FilePath& path, base::FilePath* out);
|
||||
|
||||
// Returns the file's fd.
|
||||
int GetFD() const;
|
||||
|
||||
base::FilePath path() const { return path_; }
|
||||
base::DictionaryValue* header() const { return header_.get(); }
|
||||
|
||||
private:
|
||||
base::FilePath path_;
|
||||
base::File file_;
|
||||
uint32 header_size_;
|
||||
scoped_ptr<base::DictionaryValue> header_;
|
||||
|
||||
|
|
|
@ -36,17 +36,16 @@ bool ScopedTemporaryFile::Init() {
|
|||
return base::CreateTemporaryFile(&path_);
|
||||
}
|
||||
|
||||
bool ScopedTemporaryFile::InitFromFile(const base::FilePath& path,
|
||||
bool ScopedTemporaryFile::InitFromFile(base::File* src,
|
||||
uint64 offset, uint64 size) {
|
||||
if (!src->IsValid())
|
||||
return false;
|
||||
|
||||
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());
|
||||
int len = src->Read(offset, buf.data(), buf.size());
|
||||
if (len != static_cast<int>(size))
|
||||
return false;
|
||||
|
||||
|
|
|
@ -7,6 +7,10 @@
|
|||
|
||||
#include "base/files/file_path.h"
|
||||
|
||||
namespace base {
|
||||
class File;
|
||||
}
|
||||
|
||||
namespace asar {
|
||||
|
||||
// An object representing a temporary file that should be cleaned up when this
|
||||
|
@ -22,7 +26,7 @@ class ScopedTemporaryFile {
|
|||
bool Init();
|
||||
|
||||
// Init an temporary file and fill it with content of |path|.
|
||||
bool InitFromFile(const base::FilePath& path, uint64 offset, uint64 size);
|
||||
bool InitFromFile(base::File* src, uint64 offset, uint64 size);
|
||||
|
||||
base::FilePath path() const { return path_; }
|
||||
|
||||
|
|
|
@ -236,21 +236,20 @@ exports.wrapFsWithAsar = (fs) ->
|
|||
return fs.readFile realPath, options, callback
|
||||
|
||||
if not options
|
||||
options = encoding: null, flag: 'r'
|
||||
options = encoding: null
|
||||
else if util.isString options
|
||||
options = encoding: options, flag: 'r'
|
||||
options = encoding: options
|
||||
else if not util.isObject options
|
||||
throw new TypeError('Bad arguments')
|
||||
|
||||
flag = options.flag || 'r'
|
||||
encoding = options.encoding
|
||||
|
||||
buffer = new Buffer(info.size)
|
||||
open archive.path, flag, (error, fd) ->
|
||||
return callback error if error
|
||||
fs.read fd, buffer, 0, info.size, info.offset, (error) ->
|
||||
fs.close fd, ->
|
||||
callback error, if encoding then buffer.toString encoding else buffer
|
||||
fd = archive.getFd()
|
||||
return notFoundError asarPath, filePath, callback unless fd >= 0
|
||||
|
||||
fs.read fd, buffer, 0, info.size, info.offset, (error) ->
|
||||
callback error, if encoding then buffer.toString encoding else buffer
|
||||
|
||||
openSync = fs.openSync
|
||||
readFileSync = fs.readFileSync
|
||||
|
@ -270,23 +269,19 @@ exports.wrapFsWithAsar = (fs) ->
|
|||
return fs.readFileSync realPath, options
|
||||
|
||||
if not options
|
||||
options = encoding: null, flag: 'r'
|
||||
options = encoding: null
|
||||
else if util.isString options
|
||||
options = encoding: options, flag: 'r'
|
||||
options = encoding: options
|
||||
else if not util.isObject options
|
||||
throw new TypeError('Bad arguments')
|
||||
|
||||
flag = options.flag || 'r'
|
||||
encoding = options.encoding
|
||||
|
||||
buffer = new Buffer(info.size)
|
||||
fd = openSync archive.path, flag
|
||||
try
|
||||
fs.readSync fd, buffer, 0, info.size, info.offset
|
||||
catch e
|
||||
throw e
|
||||
finally
|
||||
fs.closeSync fd
|
||||
fd = archive.getFd()
|
||||
notFoundError asarPath, filePath unless fd >= 0
|
||||
|
||||
fs.readSync fd, buffer, 0, info.size, info.offset
|
||||
if encoding then buffer.toString encoding else buffer
|
||||
|
||||
readdir = fs.readdir
|
||||
|
|
Loading…
Reference in a new issue