b0VIM 7.4 Wq*andrewandrew-XPS-13-9350~andrew/Development/copy-on-write/index.jsutf-8 3210#"! Utp4I6~ d|ead 4hI* po_P<+* q T +  Z   y u ^ =     r r q U 1  f F  wlc]\/vQ K?vYON8! [Z? YOF@?{G" gte: gte, var rs = db.createReadStream({ var lt = toIndexKey(p.join(resolved, '\xff')) var gte = toIndexKey(resolved) if (!/\/$/.test(resolved)) resolved += '/' var resolved = p.resolve(path) log('readdir', path) handlers.readdir = function (path, cb) { } }) } return sizeAndMode(stat, cb) } else { }) return sizeAndMode(stat, cb) stat.nlink = s.nlink if (err) return cb(err) fs.stat(entry.layer, function (err, s) { if (entry.layer) { if (opts.gid !== undefined) stat.gid = opts.gid if (opts.uid !== undefined) stat.uid = opts.uid stat.mtime = entry.mtim stat.atime = entry.atim stat.size = 0 stat.nlink = 1 var stat = {} } return cb(0, stat) } stat.mode = entry.mode if (entry.type === 'device') { } stat.mode = parseInt('120000', 8) | entry.mode if (entry.type === 'symlink') { } stat.mode = parseInt('040000', 8) | entry.mode | dmode stat.size = 4096 stat.nlink = entry.nlink || 2 if (entry.type === 'directory') { } stat.mode = parseInt('0100000', 8) | entry.mode | fmode stat.size = entry.length if (entry.type === 'file') { function sizeAndMode (stat, cb) { if (err) return cb(ENOENT) get(path, function (err, entry) { log('getattr', path) handlers.getattr = function (path, cb) { } }) }) cb(null, entry) entry.length = stat ? stat.size : 0 if (err) return cb(err) fs.stat(entry.layer, function (err, stat) { if (!entry.layer) return cb(null, entry) if (err) return cb(err) db.get(toIndexKey(path), {valueEncoding: 'json'}, function (err, entry) { if (path === '/') return cb(null, {name: '/', mode: parseInt('0755', 8), type: 'directory'}) log('get', path) var get = function (path, cb) { var ready = function () { if (!entry.length || ) return u if (!en if (!entry.length) return util.empty() var createReadStream = function (entry, offset) { var handlers = {} } fmode |= parseInt('0222', 8) dmode |= parseInt('0333', 8) if (opts.writable) { } fmode |= parseInt('0444', 8) dmode |= parseInt('0555', 8) if (opts.readable) { var log = opts.log || function () {} var fmode = 0 var dmode = 0 var createIndexStream = opts.createIndexStream || util.empty var createFileStream = opts.createFileStream || util.empty } var dbPath = p.join(dir, 'dbs', id + '.db') } else { db = opts.db if (opts.db) { var db = null var mnt = p.join(dir, 'mnt', id) var layers = p.join(dir, 'layers', id) var id = opts.id || cuid() var dir = opts.dir || p.join('.', 'containers') if (!opts) opts = {} if (typeof opts === 'function') return module.exports(mnt, null, opts)function createFilesystem (opts, cb) {var EEXIST = -17// var EINVAL = -22var EPERM = -1var ENOENT = -2var toIndexKey = util.toIndexKeyvar util = require('./lib/util')var map = require('through2-map')var level = require('level')var cuid = require('cuid')var mknod = require('mknod')var shasum = require('shasum')var mkdirp = require('mkdirp')var pump = require('pump')var p = require('path')var collect = require('stream-collector')var fs = require('fs')var fuse = require('fuse-bindings')ad$esh_YX*bE) X % j G k P A 4 )   | V $ w c ] \ 5  wgO@6/+* ]A}~tO2module.exports = createFilesystem} }) }) }) }) return begin() db = level(dbPath) mkdirp(dbPath, function () { } return begin() if (db) { } indexStream.resume() }) }) if (err) return cb(err) db.put(toIndexKey(p.resolve(entry.name)), entry, { valueEncoding: 'json' }, function (err) { indexStream.on('data', function (entry) { }) fuse.unmount(mnt, ready) indexStream.on('end', function () { var indexStream = createIndexStream() function begin () { mkdirp(layers, function () { } return fuse.unmount(mnt, ready) if (exists) { fs.exists(layers, function (exists) { if (err) return cb(err) mkdirp(mnt, function (err) { } }) })) id: id layers: layers, db: db, mnt: mnt, createChangesStream: createChangesStream, cb(null, Object.assign({}, handlers, { if (err) return cb(err) fuse.mount(mnt, handlers, function (err) { handlers.options = ['allow_other'] } return stream db.createReadStream({ valueEncoding: 'object' }).pipe(stream) }) cb() this.push(Object.assign({}, chunk, { key: util.fromIndexKey(chunk.key) })) var stream = map.obj(function (chunk, cb) { function createChangesStream () { */ Generate a stream of the changes in the writable layer of the filesystem /* } return cb(0) handlers.destroy = function (cb) { } }) }) }) }) return cb(0) if (err) return cb(err) db.put(toIndexKey(dest), entry, { valueEncoding: 'json' }, function (err) { if (err) return cb(err) fs.link(srcTarget, destTarget, function (err) { entry.layer = destTarget var destTarget = getTargetPath(dest) var srcTarget = (entry) ? entry.layer : list[3].entry.layer if ((err || !entry) && (list.length < 3)) return cb(ENOENT) if (err && !err.notFound) return cb(err) get(src, function (err, entry) { var list = files[src] || [] if (existing) return cb(EEXIST) if (err && !err.notFound) return cb(err) get(dest, function (err, existing) { src = processSrc(src) log('link', src, dest) handlers.link = function (src, dest, cb) { } }) return cb(0, entry.linkname) if (err) return cb(err) get(path, function (err, entry) { log('readlink', path) handlers.readlink = function (path, cb) { } }) }) return cb(0) if (err) return cb(err) db.put(toIndexKey(dest), entry, { valueEncoding: 'json' }, function (err) {ad I4tV;32 i $ { Y X %  d X   z q k j % o F - % $ uRu[3fTG<3-,b=aSA4) O< console.error('mkdir, err:', err) if (err) { db.put(toIndexKey(path), {name: path, mode: mode, type: 'directory', size: 0}, {valueEncoding: 'json'}, function (err) { log('mkdir', path) handlers.mkdir = function (path, mode, cb) { } }) }) }) cb(0) } return cb(EPERM) console.error('rename:batch, err:', err) if (err) { db.batch(batch, function (err) { entry.name = dst var batch = [{type: 'del', key: toIndexKey(entry.name)}, {type: 'put', key: toIndexKey(dst), valueEncoding: 'json', value: entry}] delete files[src] files[dst] = files[src] || [] } return cb(EPERM) console.error('rename, err:', err) if (err || !entry.layer) { get(src, function (err, entry) { if (err) return cb(err) copyOnWrite(src, 0, false, function (err) { log('rename', src, dst) handlers.rename = function (src, dst, cb) { } }) }) }) cb(0) fs.unlink(entry.layer, function () { if (!entry.layer) return cb(0) db.del(toIndexKey(path), function () { if (!entry) return cb(ENOENT) if (err) return cb(err) get(path, function (err, entry) { log('unlink', path) handlers.unlink = function (path, cb) { } }) }) return cb(bytes) if (err) return cb(err) db.put(toIndexKey(path), file.entry, { valueEncoding: 'json' }, function (err) { file.entry.length += bytes } return cb(EPERM) console.error('write:write, err:', err) if (err) { fs.write(file.fd, buf, 0, len, offset, function (err, bytes) { } return cb(EPERM) console.error('write:fd error') if (file.fd === undefined) { if (!file) return cb(ENOENT) var file = list[handle] var list = files[path] || [] log('write', path, offset, len, handle) handlers.write = function (path, handle, buf, len, offset, cb) { } }) }) }) cb(0) } return cb(EPERM) console.error('truncate:fs, err:', err) if (err) { fs.truncate(entry.layer, size, function (err) { } return cb(EPERM) console.error('truncate:get, err:', err) if (err || !entry.layer) { get(path, function (err, entry) { if (err) return cb(err) copyOnWrite(path, 0, false, function (err) { log('truncate', path, size) handlers.truncate = function (path, size, cb) { } loop() } cb(result.length) result.copy(buf) file.offset += result.length if (!result) return file.stream.once('readable', loop) console.log('in loop for path:', path) var loop = function () { } file.offset = offset file.stream = createReadStream(file.entry, offset) if (!file.stream) { } file.stream = null file.stream.destroy() if (file.stream && file.offset !== offset) { } return }) cb(bytes) } return cb(EPERM) console.error('read, err:', err) if (err) { fs.read(file.fd, buf, 0, len, offset, function (err, bytes) { if (file.fd !== undefined) { if (len + offset > file.entry.length) len = file.entry.length - offsetaddqX>65("!wM( y C $   i h E '  Q > k I . #    _ 0  nPOcW/k@)ZA@5 co console.er console.error('mkdir, err:', err) if console.error('mkdir, err:', err) if (err) { db.put(t console.error('mkdir, err:', err) if (err) { db.put(toIndexKey(path), {name: path, mode: mode, type: 'directory', size: 0}, {valueEncoding: 'json'}, function (err) { log('mkdir', path) handlers.mkdir = function (path, mode, cb) { } }) }) }) cb(0) } return cb(EPERM) console.error('rename:batch, err:', err) if (err) { db.batch(batch, function (err) { entry.name = dst var batch = [{type: 'del', key: toIndexKey(entry.name)}, {type: 'put', key: toIndexKey(dst), valueEncoding: 'json', value: entry}] delete files[src] files[dst] = files[src] || [] } return cb(EPERM) console.error('rename, err:', err) if (err || !entry.layer) { get(src, function (err, entry) { if (err) return cb(err) copyOnWrite(src, 0, false, function (err) { log('rename', src, dst) handlers.rename = function (src, dst, cb) { } }) }) }) cb(0) fs.unlink(entry.layer, function () { if (!entry.layer) return cb(0) db.del(toIndexKey(path), function () { if (!entry) return cb(ENOENT) if (err) return cb(err) get(path, function (err, entry) { log('unlink', path) handlers.unlink = function (path, cb) { } }) }) return cb(bytes) if (err) return cb(err) db.put(toIndexKey(path), file.entry, { valueEncoding: 'json' }, function (err) { file.entry.length += bytes } return cb(EPERM) console.error('write:write, err:', err) if (err) { fs.write(file.fd, buf, 0, len, offset, function (err, bytes) { } return cb(EPERM) console.error('write:fd error') if (file.fd === undefined) { if (!file) return cb(ENOENT) var file = list[handle] var list = files[path] || [] log('write', path, offset, len, handle) handlers.write = function (path, handle, buf, len, offset, cb) { } }) }) }) cb(0) } return cb(EPERM) console.error('truncate:fs, err:', err) if (err) { fs.truncate(entry.layer, size, function (err) { } return cb(EPERM) console.error('truncate:get, err:', err) if (err || !entry.layer) { get(path, function (err, entry) { if (err) return cb(err) copyOnWrite(path, 0, false, function (err) { log('truncate', path, size) handlers.truncate = function (path, size, cb) { } loop() } cb(result.length) result.copy(buf) file.offset += result.length if (!result) return file.stream.once('readable', loop) var result = file.stream.read(len)ad 3yxE  6 l  Y N E ? >  u t M L ( c W G < 4 3  x ;   wI0&a`zof`_.cZTShN#"ndVMGFdc321 if (file.entry.length === 0) return cb(0) if (!file) return cb(ENOENT) var file = list[handle] var list = files[path] || [] log('read', path, offset, len, handle, buf.length) handlers.read = function (path, handle, buf, len, offset, cb) { } }) cb(0) } return cb(EPERM) console.error('release, err:', err) if (err) { fs.close(file.fd, function (err) { if (file.fd === undefined) return cb(0) if (!list.length) delete files[path] list[handle] = null if (file.stream) file.stream.destroy() if (!file) return cb(ENOENT) var file = list[handle] var list = files[path] || [] log('release', path, handle) handlers.release = function (path, handle, cb) { } }) open(path, flags, cb) if (err) return cb(err) copyOnWrite(path, 0, false, function (err) { if ((flags & 3) === 0) return open(path, flags, cb) log('open', path, flags) handlers.open = function (path, flags, cb) { } }) }) done(entry) } return cb(EPERM) console.error('copy-on-write:get, err:', err) if (err) { pump(createReadStream(entry, 0), fs.createWriteStream(target), function (err) { if (mode) entry.mode = mode entry.layer = target if (!entry) return cb(ENOENT) if (!entry && upsert) return create() if (entry && entry.layer) return cb(0) } return cb(err) if (err.notFound) return cb(ENOENT) if (err.notFound && upsert) return create() if (err) { get(path, function (err, entry) { } }) done(entry) } return cb(EPERM) console.error('copy-on-write:create, err:', err) if (err) { fs.writeFile(target, '', function (err) { var entry = {name: path, size: 0, type: 'file', mode: mode, layer: target} var create = function () { } }) cb(0) } return cb(EPERM) console.error('copy-on-write:done, err:', err) if (err) { db.put(toIndexKey(entry.name), entry, {valueEncoding: 'json'}, function (err) { var done = function (entry) { var target = getTargetPath(path) log('copy-on-write', path) var copyOnWrite = function (path, mode, upsert, cb) { } return p.join(layers, shasum(path + '-' + Date.now())) var getTargetPath = function (path) { } }) }) push({fd: fd, entry: entry}) if (err) return cb(EPERM) fs.open(entry.layer, flags, function (err, fd) { if (!entry.layer) return push({offset: 0, entry: entry}) if (entry.type === 'symlink') return open(entry.linkname, flags, cb) if (err) return cb(ENOENT) get(path, function (err, entry) { } cb(0, fd) list[fd] = data if (fd === -1) fd = list.length var fd = list.indexOf(null) var list = files[path] = files[path] || [true, true, true] // fd > 3 var push = function (data) { var open = function (path, flags, cb) { var files = [] } }) cb(0, files) }) return p.basename(entry.value.name) var files = entries.map(function (entry) { if (err) return cb(ENOENT) collect(rs, function (err, entries) { }) valueEncoding: 'json' lt: lt,ad.yxD1i_=4.- u ] y s r A " ! m X *  N .    ; % $    u\D,~R*fD-"Eh]TNM'`@}. var entry = { name: dest, type: 'symlink', linkname: src, mode: mode } var mode = parseInt('120000', 8) | parseInt('0777', 8) if (existing) return cb(EEXIST) if (err && !err.notFound) return cb(err) get(dest, function (err, existing) { log('symlink', src, dest) handlers.symlink = function (src, dest, cb) { } return src if (!src.startsWith('/')) src = '/' + src } src = src.slice(mnt.length) if (src.startsWith(mnt)) { var processSrc = function (src) { } }) }) return cb(0) if (err) return cb(err) db.put(toIndexKey(path), entry, { valueEncoding: 'json' }, function (err) { if (err) return cb(err) mknod(target, mode, dev, function (err) { var entry = { name: path, type: 'device', mode: mode, layer: target } var target = getTargetPath(path) log('mknod', path, mode, dev) handlers.mknod = function (path, mode, dev, cb) { } }) }) return cb(0) if (err) return cb(err) db.put(toIndexKey(path), entry, { valueEncoding: 'json' }, function (err) { entry.mtim = modtime.getTime() entry.atim = actime.getTime() if (err) return cb(ENOENT) get(path, function (err, entry) { log('utimens', path, actime, modtime) handlers.utimens = function (path, actime, modtime, cb) { } }) namemax: 1000000 flag: 1000000, fsid: 1000000, favail: 1000000, ffree: 1000000, files: 1000000, bavail: 1000000, bfree: 1000000, blocks: 1000000, frsize: 1000000, bsize: 1000000, cb(0, { handlers.statfs = function (path, cb) { } cb(0) log('setxattr') handlers.setxattr = function (path, name, buffer, length, offset, flags, cb) { } cb(0) log('getxattr') handlers.getxattr = function (path, name, buffer, length, offset, cb) { } }) open(path, 2, cb) if (err) return cb(err) copyOnWrite(path, mode, true, function (err) { log('create', path, mode) handlers.create = function (path, mode, cb) { } }) }) cb(0) } return cb(EPERM) console.error('chmod, err:', err) if (err) { db.put(toIndexKey(path), entry, {valueEncoding: 'json'}, function (err) { entry.mode = mode if (err) return cb(err) get(path, function (err, entry) { log('chmod', path, mode) handlers.chmod = function (path, mode, cb) { } }) }) cb(0) } return cb(EPERM) console.error('chown, err:', err) if (err) { db.put(toIndexKey(path), entry, { valueEncoding: 'json' }, function (err) { entry.gid = gid entry.uid = uid if (err) return cb(err) get(path, function (err, entry) { log('chown', path, uid, gid) handlers.chown = function (path, uid, gid, cb) { } }) handlers.unlink(path, cb) } return cb(EPERM) console.error('rmdir, list.length, err:', err) if (list.length) { } return cb(EPERM) console.error('rmdir:readdir, err:', err) if (err) { handlers.readdir(path, function (err, list) { log('rmdir', path) handlers.rmdir = function (path, cb) { } }) cb(0) } return cb(EPERM)ad/oIyt@ s r J ' & l ` 4 t 9 -  j J * k G & qVU0o gte: gte, var rs = db.createReadStream({ var lt = toIndexKey(p.join(resolved, '\xff')) var gte = toIndexKey(resolved) if (!/\/$/.test(resolved)) resolved += '/' var resolved = p.resolve(path) log('readdir', path) handlers.readdir = function (path, cb) { } }) } return sizeAndMode(stat, cb) } else { }) return sizeAndMode(stat, cb) stat.nlink = s.nlink if (err) return cb(err) fs.stat(entry.layer, function (err, s) { if (entry.layer) { if (opts.gid !== undefined) stat.gid = opts.gid if (opts.uid !== undefined) stat.uid = opts.uid stat.mtime = entry.mtim stat.atime = entry.atim stat.size = 0 stat.nlink = 1 var stat = {} } return cb(0, stat) } stat.mode = entry.mode if (entry.type === 'device') { } stat.mode = parseInt('120000', 8) | entry.mode if (entry.type === 'symlink') { } stat.mode = parseInt('040000', 8) | entry.mode | dmode stat.size = 4096 stat.nlink = entry.nlink || 2 if (entry.type === 'directory') { } stat.mode = parseInt('0100000', 8) | entry.mode | fmode stat.size = entry.length if (entry.type === 'file') { function sizeAndMode (stat, cb) { if (err) return cb(ENOENT) get(path, function (err, entry) { log('getattr', path) handlers.getattr = function (path, cb) { } }) }) cb(null, entry) entry.length = stat ? stat.size : 0 if (err) return cb(err) fs.stat(entry.layer, function (err, stat) { if (!entry.layer) return cb(null, entry) if (err) return cb(err) db.get(toIndexKey(path), {valueEncoding: 'json'}, function (err, entry) { if (path === '/') return cb(null, {name: '/', mode: parseInt('0755', 8), type: 'directory'}) log('get', path) var get = function (path, cb) { var ready = function () { } return createFileStream(entry, offset)ad