From 885ac53a48edafa67cf34377812e828c4ee3ad13 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 30 Sep 2014 14:53:41 +0800 Subject: [PATCH] asar: Add support in fs.realpathSync --- atom/common/api/atom_api_asar.cc | 10 ++++++++++ atom/common/asar/archive.cc | 18 ++++++++++++++++++ atom/common/asar/archive.h | 3 +++ atom/common/lib/asar.coffee | 21 +++++++++++++++++---- 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/atom/common/api/atom_api_asar.cc b/atom/common/api/atom_api_asar.cc index 625b16eda1..5cc2616ac0 100644 --- a/atom/common/api/atom_api_asar.cc +++ b/atom/common/api/atom_api_asar.cc @@ -65,6 +65,15 @@ class Archive : public mate::Wrappable { return mate::ConvertToV8(isolate, files); } + // Returns the path of file with symbol link resolved. + v8::Handle Realpath(v8::Isolate* isolate, + const base::FilePath& path) { + base::FilePath realpath; + if (!archive_ || !archive_->Realpath(path, &realpath)) + return v8::False(isolate); + return mate::ConvertToV8(isolate, realpath); + } + // Copy the file out into a temporary file and returns the new path. v8::Handle CopyFileOut(v8::Isolate* isolate, const base::FilePath& path) { @@ -86,6 +95,7 @@ class Archive : public mate::Wrappable { .SetMethod("getFileInfo", &Archive::GetFileInfo) .SetMethod("stat", &Archive::Stat) .SetMethod("readdir", &Archive::Readdir) + .SetMethod("realpath", &Archive::Realpath) .SetMethod("copyFileOut", &Archive::CopyFileOut) .SetMethod("destroy", &Archive::Destroy); } diff --git a/atom/common/asar/archive.cc b/atom/common/asar/archive.cc index ccc712c9b0..fbf1ae2d04 100644 --- a/atom/common/asar/archive.cc +++ b/atom/common/asar/archive.cc @@ -206,6 +206,24 @@ bool Archive::Readdir(const base::FilePath& path, return true; } +bool Archive::Realpath(const base::FilePath& path, base::FilePath* realpath) { + if (!header_) + return false; + + const base::DictionaryValue* node; + if (!GetNodeFromPath(path.AsUTF8Unsafe(), header_.get(), &node)) + return false; + + std::string link; + if (node->GetString("link", &link)) { + *realpath = base::FilePath::FromUTF8Unsafe(link); + return true; + } + + *realpath = path; + return true; +} + bool Archive::CopyFileOut(const base::FilePath& path, base::FilePath* out) { if (external_files_.contains(path)) { *out = external_files_.get(path)->path(); diff --git a/atom/common/asar/archive.h b/atom/common/asar/archive.h index 30926fb9f6..0058f0269d 100644 --- a/atom/common/asar/archive.h +++ b/atom/common/asar/archive.h @@ -51,6 +51,9 @@ class Archive { // Fs.readdir(path). bool Readdir(const base::FilePath& path, std::vector* files); + // Fs.realpath(path). + bool Realpath(const base::FilePath& path, base::FilePath* realpath); + // Copy the file into a temporary file, and return the new path. bool CopyFileOut(const base::FilePath& path, base::FilePath* out); diff --git a/atom/common/lib/asar.coffee b/atom/common/lib/asar.coffee index cb6fe98349..665e759b34 100644 --- a/atom/common/lib/asar.coffee +++ b/atom/common/lib/asar.coffee @@ -75,7 +75,7 @@ fs.lstat = (p, callback) -> return lstat p, callback unless isAsar archive = getOrCreateArchive asarPath - return callback throw new Error("Invalid package #{asarPath}") unless archive + return callback new Error("Invalid package #{asarPath}") unless archive stats = getOrCreateArchive(asarPath).stat filePath return callback createNotFoundError(asarPath, filePath) unless stats @@ -109,13 +109,26 @@ fs.statSyncNoException = (p) -> return false unless stats asarStatsToFsStats stats +realpathSync = fs.realpathSync +fs.realpathSync = (p) -> + [isAsar, asarPath, filePath] = splitPath p + return realpathSync.apply this, arguments unless isAsar + + archive = getOrCreateArchive asarPath + throw new Error("Invalid package #{asarPath}") unless archive + + real = archive.realpath filePath + throw createNotFoundError(asarPath, filePath) unless real + + path.join realpathSync(asarPath), real + exists = fs.exists fs.exists = (p, callback) -> [isAsar, asarPath, filePath] = splitPath p return exists p, callback unless isAsar archive = getOrCreateArchive asarPath - return callback throw new Error("Invalid package #{asarPath}") unless archive + return callback new Error("Invalid package #{asarPath}") unless archive process.nextTick -> callback archive.stat(filePath) isnt false @@ -140,7 +153,7 @@ fs.readFile = (p, options, callback) -> options = undefined archive = getOrCreateArchive asarPath - return callback throw new Error("Invalid package #{asarPath}") unless archive + return callback new Error("Invalid package #{asarPath}") unless archive info = archive.getFileInfo filePath return callback createNotFoundError(asarPath, filePath) unless info @@ -200,7 +213,7 @@ fs.readdir = (p, callback) -> return readdir.apply this, arguments unless isAsar archive = getOrCreateArchive asarPath - return callback throw new Error("Invalid package #{asarPath}") unless archive + return callback new Error("Invalid package #{asarPath}") unless archive files = archive.readdir filePath return callback createNotFoundError(asarPath, filePath) unless files