You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cryptpad/lib/storage/block.js

91 lines
2.8 KiB
JavaScript

/*jshint esversion: 6 */
const Block = module.exports;
const Util = require("../common-util");
const Path = require("path");
const Fs = require("fs");
const Fse = require("fs-extra");
const nThen = require("nthen");
Block.mkPath = function (Env, publicKey) {
// prepare publicKey to be used as a file name
var safeKey = Util.escapeKeyCharacters(publicKey);
// validate safeKey
if (typeof(safeKey) !== 'string') { return; }
// derive the full path
// /home/cryptpad/cryptpad/block/fg/fg32kefksjdgjkewrjksdfksjdfsdfskdjfsfd
return Path.join(Env.paths.block, safeKey.slice(0, 2), safeKey);
};
Block.mkArchivePath = function (Env, publicKey) {
// prepare publicKey to be used as a file name
var safeKey = Util.escapeKeyCharacters(publicKey);
// validate safeKey
if (typeof(safeKey) !== 'string') {
return;
}
// derive the full path
// /home/cryptpad/cryptpad/block/fg/fg32kefksjdgjkewrjksdfksjdfsdfskdjfsfd
return Path.join(Env.paths.archive, 'block', safeKey.slice(0, 2), safeKey);
};
Block.archive = function (Env, publicKey, _cb) {
var cb = Util.once(Util.mkAsync(_cb));
// derive the filepath
var currentPath = Block.mkPath(Env, publicKey);
// make sure the path is valid
if (typeof(currentPath) !== 'string') {
return void cb('E_INVALID_BLOCK_PATH');
}
var archivePath = Block.mkArchivePath(Env, publicKey);
// make sure the path is valid
if (typeof(archivePath) !== 'string') {
return void cb('E_INVALID_BLOCK_ARCHIVAL_PATH');
}
// TODO Env.incrementBytesWritten
Fse.move(currentPath, archivePath, {
overwrite: true,
}, cb);
};
Block.check = function (Env, publicKey, _cb) { // 'check' because 'exists' implies boolean
var cb = Util.once(Util.mkAsync(_cb));
var path = Block.mkPath(Env, publicKey);
Fs.access(path, Fs.constants.F_OK, cb);
};
Block.write = function (Env, publicKey, buffer, _cb) {
var cb = Util.once(Util.mkAsync(_cb));
var path = Block.mkPath(Env, publicKey);
if (typeof(path) !== 'string') { return void cb('INVALID_PATH'); }
var parsed = Path.parse(path);
nThen(function (w) {
Fse.mkdirp(parsed.dir, w(function (err) {
if (!err) { return; }
w.abort();
cb(err);
}));
}).nThen(function (w) {
Block.archive(Env, publicKey, w(function (/* err */) {
/*
we proceed even if there are errors.
it might be ENOENT (there is no file to archive)
or EACCES (bad filesystem permissions for the existing archived block?)
or lots of other things, none of which justify preventing the write
*/
}));
}).nThen(function () {
Fs.writeFile(path, buffer, { encoding: 'binary' }, cb);
Env.incrementBytesWritten(buffer && buffer.length);
});
};