2014-11-12 06:14:37 -05:00
|
|
|
var fs = require('fs')
|
|
|
|
var Error = require('http-errors')
|
|
|
|
var mkdirp = require('mkdirp')
|
|
|
|
var Path = require('path')
|
|
|
|
var MyStreams = require('./streams')
|
2014-09-10 12:55:26 -05:00
|
|
|
|
|
|
|
function FSError(code) {
|
2014-11-12 06:14:37 -05:00
|
|
|
var err = Error(code)
|
|
|
|
err.code = code
|
|
|
|
return err
|
2014-09-10 12:55:26 -05:00
|
|
|
}
|
2013-05-31 17:57:28 -05:00
|
|
|
|
2016-05-01 04:02:01 -05:00
|
|
|
var locker = require('./file-locking')
|
2014-03-30 23:32:11 -05:00
|
|
|
|
2014-11-01 15:05:26 -05:00
|
|
|
function tempFile(str) {
|
2014-11-12 06:14:37 -05:00
|
|
|
return str + '.tmp' + String(Math.random()).substr(2)
|
2014-11-01 15:05:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
function renameTmp(src, dst, _cb) {
|
2014-11-12 06:14:37 -05:00
|
|
|
function cb(err) {
|
2017-04-20 10:33:28 -05:00
|
|
|
if (err) fs.unlink(src, function() {})
|
2014-11-12 06:14:37 -05:00
|
|
|
_cb(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (process.platform !== 'win32') {
|
|
|
|
return fs.rename(src, dst, cb)
|
|
|
|
}
|
|
|
|
|
|
|
|
// windows can't remove opened file,
|
|
|
|
// but it seem to be able to rename it
|
|
|
|
var tmp = tempFile(dst)
|
|
|
|
fs.rename(dst, tmp, function(err) {
|
|
|
|
fs.rename(src, dst, cb)
|
2017-04-20 10:33:28 -05:00
|
|
|
if (!err) fs.unlink(tmp, function () {})
|
2014-11-12 06:14:37 -05:00
|
|
|
})
|
2014-11-01 15:05:26 -05:00
|
|
|
}
|
|
|
|
|
2013-06-18 13:14:55 -05:00
|
|
|
function write(dest, data, cb) {
|
2014-11-12 06:14:37 -05:00
|
|
|
var safe_write = function(cb) {
|
|
|
|
var tmpname = tempFile(dest)
|
|
|
|
fs.writeFile(tmpname, data, function(err) {
|
|
|
|
if (err) return cb(err)
|
|
|
|
renameTmp(tmpname, dest, cb)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
safe_write(function(err) {
|
|
|
|
if (err && err.code === 'ENOENT') {
|
|
|
|
mkdirp(Path.dirname(dest), function(err) {
|
|
|
|
if (err) return cb(err)
|
|
|
|
safe_write(cb)
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
cb(err)
|
|
|
|
}
|
|
|
|
})
|
2013-05-31 17:57:28 -05:00
|
|
|
}
|
|
|
|
|
2013-06-20 08:07:34 -05:00
|
|
|
function write_stream(name) {
|
2014-11-12 06:14:37 -05:00
|
|
|
var stream = MyStreams.UploadTarballStream()
|
|
|
|
|
|
|
|
var _ended = 0
|
|
|
|
stream.on('end', function() {
|
|
|
|
_ended = 1
|
|
|
|
})
|
|
|
|
|
|
|
|
fs.exists(name, function(exists) {
|
|
|
|
if (exists) return stream.emit('error', FSError('EEXISTS'))
|
|
|
|
|
|
|
|
var tmpname = name + '.tmp-'+String(Math.random()).replace(/^0\./, '')
|
|
|
|
var file = fs.createWriteStream(tmpname)
|
|
|
|
var opened = false
|
|
|
|
stream.pipe(file)
|
|
|
|
|
|
|
|
stream.done = function() {
|
|
|
|
function onend() {
|
|
|
|
file.on('close', function() {
|
|
|
|
renameTmp(tmpname, name, function(err) {
|
|
|
|
if (err) {
|
|
|
|
stream.emit('error', err)
|
|
|
|
} else {
|
|
|
|
stream.emit('success')
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
file.destroySoon()
|
|
|
|
}
|
|
|
|
if (_ended) {
|
|
|
|
onend()
|
|
|
|
} else {
|
|
|
|
stream.on('end', onend)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
stream.abort = function() {
|
|
|
|
if (opened) {
|
|
|
|
opened = false
|
|
|
|
file.on('close', function() {
|
|
|
|
fs.unlink(tmpname, function(){})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
file.destroySoon()
|
|
|
|
}
|
|
|
|
file.on('open', function() {
|
|
|
|
opened = true
|
|
|
|
// re-emitting open because it's handled in storage.js
|
|
|
|
stream.emit('open')
|
|
|
|
})
|
|
|
|
file.on('error', function(err) {
|
|
|
|
stream.emit('error', err)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
return stream
|
2013-06-20 08:07:34 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
function read_stream(name, stream, callback) {
|
2014-11-12 06:14:37 -05:00
|
|
|
var rstream = fs.createReadStream(name)
|
|
|
|
rstream.on('error', function(err) {
|
|
|
|
stream.emit('error', err)
|
|
|
|
})
|
|
|
|
rstream.on('open', function(fd) {
|
|
|
|
fs.fstat(fd, function(err, stats) {
|
|
|
|
if (err) return stream.emit('error', err)
|
|
|
|
stream.emit('content-length', stats.size)
|
|
|
|
stream.emit('open')
|
|
|
|
rstream.pipe(stream)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2016-05-01 04:02:01 -05:00
|
|
|
stream = MyStreams.ReadTarballStream()
|
2014-11-12 06:14:37 -05:00
|
|
|
stream.abort = function() {
|
|
|
|
rstream.close()
|
|
|
|
}
|
|
|
|
return stream
|
2013-06-20 08:07:34 -05:00
|
|
|
}
|
|
|
|
|
2013-05-31 17:57:28 -05:00
|
|
|
function create(name, contents, callback) {
|
2014-11-12 06:14:37 -05:00
|
|
|
fs.exists(name, function(exists) {
|
|
|
|
if (exists) return callback( FSError('EEXISTS') )
|
|
|
|
write(name, contents, callback)
|
|
|
|
})
|
2013-05-31 17:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
function update(name, contents, callback) {
|
2014-11-12 06:14:37 -05:00
|
|
|
fs.exists(name, function(exists) {
|
|
|
|
if (!exists) return callback( FSError('ENOENT') )
|
|
|
|
write(name, contents, callback)
|
|
|
|
})
|
2013-05-31 17:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
function read(name, callback) {
|
2014-11-12 06:14:37 -05:00
|
|
|
fs.readFile(name, callback)
|
2013-10-22 00:10:25 -05:00
|
|
|
}
|
|
|
|
|
2014-01-13 11:48:51 -05:00
|
|
|
module.exports.read = read
|
2013-06-14 03:34:29 -05:00
|
|
|
|
2014-01-13 11:48:51 -05:00
|
|
|
module.exports.read_json = function(name, cb) {
|
2014-11-12 06:14:37 -05:00
|
|
|
read(name, function(err, res) {
|
|
|
|
if (err) return cb(err)
|
|
|
|
|
|
|
|
var args = []
|
|
|
|
try {
|
|
|
|
args = [ null, JSON.parse(res.toString('utf8')) ]
|
|
|
|
} catch(err) {
|
|
|
|
args = [ err ]
|
|
|
|
}
|
|
|
|
cb.apply(null, args)
|
|
|
|
})
|
2013-06-14 03:34:29 -05:00
|
|
|
}
|
|
|
|
|
2016-05-01 04:02:01 -05:00
|
|
|
module.exports.lock_and_read = function(name, cb) {
|
|
|
|
locker.readFile(name, {lock: true}, function(err, res) {
|
|
|
|
if (err) return cb(err)
|
|
|
|
return cb(null, res)
|
|
|
|
})
|
|
|
|
}
|
2013-10-22 00:10:25 -05:00
|
|
|
|
2014-01-13 11:48:51 -05:00
|
|
|
module.exports.lock_and_read_json = function(name, cb) {
|
2016-05-01 04:02:01 -05:00
|
|
|
locker.readFile(name, {lock: true, parse: true}, function(err, res) {
|
|
|
|
if (err) return cb(err)
|
|
|
|
return cb(null, res);
|
2014-11-12 06:14:37 -05:00
|
|
|
})
|
2013-10-22 00:10:25 -05:00
|
|
|
}
|
|
|
|
|
2016-05-01 04:02:01 -05:00
|
|
|
module.exports.unlock_file = function (name, cb) {
|
|
|
|
locker.unlockFile(name, cb)
|
|
|
|
}
|
|
|
|
|
2014-01-13 11:48:51 -05:00
|
|
|
module.exports.create = create
|
2013-10-18 16:17:53 -05:00
|
|
|
|
2014-01-13 11:48:51 -05:00
|
|
|
module.exports.create_json = function(name, value, cb) {
|
2014-11-12 06:14:37 -05:00
|
|
|
create(name, JSON.stringify(value, null, '\t'), cb)
|
2013-06-14 03:34:29 -05:00
|
|
|
}
|
|
|
|
|
2014-01-13 11:48:51 -05:00
|
|
|
module.exports.update = update
|
2013-06-14 03:34:29 -05:00
|
|
|
|
2014-01-13 11:48:51 -05:00
|
|
|
module.exports.update_json = function(name, value, cb) {
|
2014-11-12 06:14:37 -05:00
|
|
|
update(name, JSON.stringify(value, null, '\t'), cb)
|
2013-06-14 03:34:29 -05:00
|
|
|
}
|
|
|
|
|
2014-01-13 11:48:51 -05:00
|
|
|
module.exports.write = write
|
2013-06-14 03:34:29 -05:00
|
|
|
|
2014-01-13 11:48:51 -05:00
|
|
|
module.exports.write_json = function(name, value, cb) {
|
2014-11-12 06:14:37 -05:00
|
|
|
write(name, JSON.stringify(value, null, '\t'), cb)
|
2013-06-18 13:14:55 -05:00
|
|
|
}
|
|
|
|
|
2014-01-13 11:48:51 -05:00
|
|
|
module.exports.write_stream = write_stream
|
2013-06-18 13:14:55 -05:00
|
|
|
|
2014-01-13 11:48:51 -05:00
|
|
|
module.exports.read_stream = read_stream
|
2013-06-20 08:07:34 -05:00
|
|
|
|
2014-01-13 11:48:51 -05:00
|
|
|
module.exports.unlink = fs.unlink
|
2013-10-06 03:27:50 -05:00
|
|
|
|
2014-01-13 11:48:51 -05:00
|
|
|
module.exports.rmdir = fs.rmdir
|
2013-05-31 17:57:28 -05:00
|
|
|
|