Comparing version
119
lib/asar.js
@@ -0,30 +1,69 @@ | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var os = require('os'); | ||
var walkdir = require('walkdir'); | ||
var mkdirp = require('mkdirp'); | ||
var Filesystem = require('./filesystem'); | ||
var disk = require('./disk'); | ||
var walkdir = require('walkdir'); | ||
module.exports.createPackage = function(src, dest, cb) { | ||
var filesystem = new Filesystem(src); | ||
var files = []; | ||
var walking = walkdir(filesystem.src); | ||
walking.on('directory', function(p, stat) { | ||
filesystem.insertDirectory(p); | ||
var crawlFilesystem = function(dir, cb) { | ||
var paths = []; | ||
var metadata = {}; | ||
var emitter = walkdir(dir); | ||
emitter.on('directory', function(p, stat) { | ||
paths.push(p); | ||
metadata[p] = {type: 'directory', stat: stat}; | ||
}); | ||
walking.on('file', function(p, stat) { | ||
files.push(p); | ||
filesystem.insertFile(p, stat); | ||
emitter.on('file', function(p, stat) { | ||
paths.push(p); | ||
metadata[p] = {type: 'file', stat: stat}; | ||
}); | ||
walking.on('link', function(p, stat) { | ||
filesystem.insertLink(p, stat); | ||
emitter.on('link', function(p, stat) { | ||
paths.push(p); | ||
metadata[p] = {type: 'link', stat: stat}; | ||
}); | ||
walking.on('end', function() { | ||
disk.writeFilesystem(dest, filesystem, files); | ||
if ('function' === typeof cb) { | ||
cb(null); | ||
}; | ||
emitter.on('end', function() { | ||
paths.sort(); | ||
cb(false, paths, metadata); | ||
}); | ||
emitter.on('error', function(err) { | ||
cb(err); | ||
}); | ||
}; | ||
module.exports.createPackage = function(src, dest, cb) { | ||
crawlFilesystem(src, function(err, filenames, metadata) { | ||
var filesystem = new Filesystem(src); | ||
var files = []; | ||
var i, filename, file; | ||
for (i in filenames) { | ||
filename = filenames[i]; | ||
file = metadata[filename]; | ||
if ('directory' === file.type) { | ||
filesystem.insertDirectory(filename); | ||
} | ||
else if ('file' === file.type) { | ||
files.push(filename); | ||
filesystem.insertFile(filename, file.stat); | ||
} | ||
else if ('link' === file.type) { | ||
filesystem.insertLink(filename, file.stat); | ||
} | ||
} | ||
// create output dir if necessary | ||
mkdirp.sync(path.dirname(dest)); | ||
disk.writeFilesystem(dest, filesystem, files, function() { | ||
if ('function' === typeof cb) | ||
cb(null); | ||
}); | ||
}); | ||
}; | ||
module.exports.listPackage = function(archive) { | ||
return disk.readFilesystem(archive).listFiles() | ||
} | ||
}; | ||
@@ -34,2 +73,44 @@ module.exports.extractFile = function(archive, filename) { | ||
return disk.readFile(filesystem, filesystem.getFile(filename)); | ||
} | ||
}; | ||
module.exports.extractAll = function(archive, dest) { | ||
var filesystem = disk.readFilesystem(archive); | ||
var filenames = filesystem.listFiles(); | ||
var i, content, file, filename, destFilename, linkTo; | ||
// under windows just extract links as regular files | ||
var followLinks = 'win32' === os.platform(); | ||
mkdirp.sync(dest); // create destination directory | ||
for (i in filenames) { | ||
filename = filenames[i].substr(1); // get rid of leading slash | ||
destFilename = path.join(dest, filename); | ||
file = filesystem.getFile(filename, followLinks); | ||
if (file.files) { | ||
// it's a directory, create it and continue with the next entry | ||
mkdirp.sync(destFilename); | ||
} | ||
else if (file.link) { | ||
// it's a symlink, create a symlink | ||
var linkSrcPath = path.dirname(path.join(dest, file.link)); | ||
var linkDestPath = path.dirname(destFilename); | ||
var relativePath = path.relative(linkDestPath, linkSrcPath); | ||
// try to delete output file, because we can't overwrite a link | ||
try { | ||
fs.unlinkSync(destFilename); | ||
} | ||
catch (err) { | ||
} | ||
linkTo = path.join(relativePath, path.basename(file.link)); | ||
fs.symlinkSync(linkTo, destFilename); | ||
} | ||
else { | ||
// it's a file, extract it | ||
content = disk.readFile(filesystem, file); | ||
fs.writeFileSync(destFilename, content); | ||
} | ||
} | ||
return true; | ||
}; |
@@ -69,6 +69,9 @@ var fs = require('fs'); | ||
Filesystem.prototype.getFile = function(p) { | ||
Filesystem.prototype.getFile = function(p, followLinks) { | ||
var name = path.basename(p); | ||
var info = this.searchNodeFromDirectory(path.dirname(p)).files[name]; | ||
if (!info.link) | ||
if ('undefined' === typeof followLinks) | ||
followLinks = true; | ||
// if followLinks is false we don't resolve symlinks | ||
if (!info.link || !followLinks) | ||
return info; | ||
@@ -75,0 +78,0 @@ return this.getFile(info.link); |
@@ -5,3 +5,3 @@ { | ||
"description": "Creating atom-shell app packages", | ||
"version": "0.1.2", | ||
"version": "0.2.0", | ||
"bin": { | ||
@@ -24,2 +24,7 @@ "asar": "bin/asar" | ||
}, | ||
"scripts": { | ||
"pretest": "npm run clean", | ||
"test": "mocha --reporter spec", | ||
"clean": "rm -rf tmp/" | ||
}, | ||
"dependencies": { | ||
@@ -29,4 +34,9 @@ "chromium-pickle": "0.1.3", | ||
"cuint": "0.1.5", | ||
"mkdirp": "^0.5.0", | ||
"walkdir": "0.0.7" | ||
}, | ||
"devDependencies": { | ||
"lodash": "^2.4.1", | ||
"mocha": "^2.0.1" | ||
} | ||
} |
# asar - Atom-Shell Archive | ||
[](https://travis-ci.org/atom/asar) | ||
[](https://david-dm.org/atom/asar) | ||
[](https://npmjs.org/package/asar) | ||
Asar is a simple extensive archive format, it works like `tar` that concatenates | ||
@@ -38,3 +42,6 @@ all files together without compression, while having random access support. | ||
extract|e <archive> <dest> | ||
extract archive | ||
Options: | ||
@@ -59,3 +66,3 @@ | ||
console.log('done.'); | ||
}) | ||
}) | ||
``` | ||
@@ -65,2 +72,6 @@ | ||
## Using with grunt | ||
There is also an inofficial grunt plugin to generate asar archives at [bwin/grunt-asar][grunt-asar]. | ||
## Format | ||
@@ -126,9 +137,10 @@ | ||
`offset` is a UINT64 number represented in string, because there is no way to | ||
precisely represent UINT64 in JavaScript `Number`. `size` is a UINT32 number for | ||
the same reason, which indicates that we can not save a file larger than 4.2GB | ||
(though the archive itself doesn't have size limitation). We didn't store `size` | ||
in UINT64 because file size in Node.js is represented as `Number` and it is not | ||
safe to convert `Number` to UINT64. | ||
precisely represent UINT64 in JavaScript `Number`. `size` is a JavaScript | ||
`Number` that is no larger than `Number.MAX_SAFE_INTEGER`, which has a value of | ||
`9007199254740991` and is about 8PB in size. We didn't store `size` in UINT64 | ||
because file size in Node.js is represented as `Number` and it is not safe to | ||
convert `Number` to UINT64. | ||
[pickle]: https://chromium.googlesource.com/chromium/src/+/master/base/pickle.h | ||
[node-pickle]: https://www.npmjs.org/package/chromium-pickle | ||
[grunt-asar]: https://github.com/bwin/grunt-asar |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
22878
109.49%23
187.5%396
158.82%143
9.16%5
25%2
Infinity%6
200%2
Infinity%+ Added
+ Added
+ Added