mirror of
https://github.com/holub/mame
synced 2025-05-30 09:33:05 +03:00
223 lines
5.7 KiB
Lua
223 lines
5.7 KiB
Lua
local exports = {}
|
|
exports.name = "creationix/coro-fs"
|
|
exports.version = "1.3.0"
|
|
exports.homepage = "https://github.com/luvit/lit/blob/master/deps/coro-fs.lua"
|
|
exports.description = "A coro style interface to the filesystem."
|
|
exports.tags = {"coro", "fs"}
|
|
exports.license = "MIT"
|
|
exports.author = { name = "Tim Caswell" }
|
|
|
|
local uv = require('luv')
|
|
local fs = exports
|
|
local pathJoin = require('path').join
|
|
|
|
local function noop() end
|
|
|
|
local function makeCallback()
|
|
local thread = coroutine.running()
|
|
return function (err, value, ...)
|
|
if err then
|
|
assert(coroutine.resume(thread, nil, err))
|
|
else
|
|
assert(coroutine.resume(thread, value == nil and true or value, ...))
|
|
end
|
|
end
|
|
end
|
|
|
|
function fs.mkdir(path, mode)
|
|
uv.fs_mkdir(path, mode or 511, makeCallback())
|
|
return coroutine.yield()
|
|
end
|
|
function fs.open(path, flags, mode)
|
|
uv.fs_open(path, flags or "r", mode or 438, makeCallback())
|
|
return coroutine.yield()
|
|
end
|
|
function fs.unlink(path)
|
|
uv.fs_unlink(path, makeCallback())
|
|
return coroutine.yield()
|
|
end
|
|
function fs.stat(path)
|
|
uv.fs_stat(path, makeCallback())
|
|
return coroutine.yield()
|
|
end
|
|
function fs.lstat(path)
|
|
uv.fs_lstat(path, makeCallback())
|
|
return coroutine.yield()
|
|
end
|
|
function fs.symlink(target, path)
|
|
uv.fs_symlink(target, path, makeCallback())
|
|
return coroutine.yield()
|
|
end
|
|
function fs.readlink(path)
|
|
uv.fs_readlink(path, makeCallback())
|
|
return coroutine.yield()
|
|
end
|
|
function fs.fstat(fd)
|
|
uv.fs_fstat(fd, makeCallback())
|
|
return coroutine.yield()
|
|
end
|
|
function fs.chmod(fd, path)
|
|
uv.fs_chmod(fd, path, makeCallback())
|
|
return coroutine.yield()
|
|
end
|
|
function fs.fchmod(fd, mode)
|
|
uv.fs_fchmod(fd, mode, makeCallback())
|
|
return coroutine.yield()
|
|
end
|
|
function fs.read(fd, length, offset)
|
|
uv.fs_read(fd, length or 1024*48, offset or -1, makeCallback())
|
|
return coroutine.yield()
|
|
end
|
|
function fs.write(fd, data, offset)
|
|
uv.fs_write(fd, data, offset or -1, makeCallback())
|
|
return coroutine.yield()
|
|
end
|
|
function fs.close(fd)
|
|
uv.fs_close(fd, makeCallback())
|
|
return coroutine.yield()
|
|
end
|
|
function fs.access(path, flags)
|
|
uv.fs_access(path, flags or "", makeCallback())
|
|
return coroutine.yield()
|
|
end
|
|
function fs.rename(path, newPath)
|
|
uv.fs_rename(path, newPath, makeCallback())
|
|
return coroutine.yield()
|
|
end
|
|
function fs.rmdir(path)
|
|
uv.fs_rmdir(path, makeCallback())
|
|
return coroutine.yield()
|
|
end
|
|
function fs.rmrf(path)
|
|
local success, err
|
|
success, err = fs.rmdir(path)
|
|
if success then return success end
|
|
if err:match("^ENOTDIR:") then return fs.unlink(path) end
|
|
if not err:match("^ENOTEMPTY:") then return success, err end
|
|
for entry in assert(fs.scandir(path)) do
|
|
local subPath = pathJoin(path, entry.name)
|
|
if entry.type == "directory" then
|
|
success, err = fs.rmrf(pathJoin(path, entry.name))
|
|
else
|
|
success, err = fs.unlink(subPath)
|
|
end
|
|
if not success then return success, err end
|
|
end
|
|
return fs.rmdir(path)
|
|
end
|
|
function fs.scandir(path)
|
|
uv.fs_scandir(path, makeCallback())
|
|
local req, err = coroutine.yield()
|
|
if not req then return nil, err end
|
|
return function ()
|
|
return uv.fs_scandir_next(req)
|
|
end
|
|
end
|
|
|
|
function fs.readFile(path)
|
|
local fd, stat, data, err
|
|
fd, err = fs.open(path)
|
|
if err then return nil, err end
|
|
stat, err = fs.fstat(fd)
|
|
if stat then
|
|
data, err = fs.read(fd, stat.size)
|
|
end
|
|
uv.fs_close(fd, noop)
|
|
return data, err
|
|
end
|
|
|
|
function fs.writeFile(path, data, mkdir)
|
|
local fd, success, err
|
|
fd, err = fs.open(path, "w")
|
|
if err then
|
|
if mkdir and string.match(err, "^ENOENT:") then
|
|
success, err = fs.mkdirp(pathJoin(path, ".."))
|
|
if success then return fs.writeFile(path, data) end
|
|
end
|
|
return nil, err
|
|
end
|
|
success, err = fs.write(fd, data)
|
|
uv.fs_close(fd, noop)
|
|
return success, err
|
|
end
|
|
|
|
function fs.mkdirp(path, mode)
|
|
local success, err = fs.mkdir(path, mode)
|
|
if success or string.match(err, "^EEXIST") then
|
|
return true
|
|
end
|
|
if string.match(err, "^ENOENT:") then
|
|
success, err = fs.mkdirp(pathJoin(path, ".."), mode)
|
|
if not success then return nil, err end
|
|
return fs.mkdir(path, mode)
|
|
end
|
|
return nil, err
|
|
end
|
|
|
|
function fs.chroot(base)
|
|
local chroot = {
|
|
base = base,
|
|
fstat = fs.fstat,
|
|
fchmod = fs.fchmod,
|
|
read = fs.read,
|
|
write = fs.write,
|
|
close = fs.close,
|
|
}
|
|
local function resolve(path)
|
|
assert(path, "path missing")
|
|
return pathJoin(base, pathJoin(path))
|
|
end
|
|
function chroot.mkdir(path, mode)
|
|
return fs.mkdir(resolve(path), mode)
|
|
end
|
|
function chroot.mkdirp(path, mode)
|
|
return fs.mkdirp(resolve(path), mode)
|
|
end
|
|
function chroot.open(path, flags, mode)
|
|
return fs.open(resolve(path), flags, mode)
|
|
end
|
|
function chroot.unlink(path)
|
|
return fs.unlink(resolve(path))
|
|
end
|
|
function chroot.stat(path)
|
|
return fs.stat(resolve(path))
|
|
end
|
|
function chroot.lstat(path)
|
|
return fs.lstat(resolve(path))
|
|
end
|
|
function chroot.symlink(target, path)
|
|
-- TODO: should we resolve absolute target paths or treat it as opaque data?
|
|
return fs.symlink(target, resolve(path))
|
|
end
|
|
function chroot.readlink(path)
|
|
return fs.readlink(resolve(path))
|
|
end
|
|
function chroot.chmod(path, mode)
|
|
return fs.chmod(resolve(path), mode)
|
|
end
|
|
function chroot.access(path, flags)
|
|
return fs.access(resolve(path), flags)
|
|
end
|
|
function chroot.rename(path, newPath)
|
|
return fs.rename(resolve(path), resolve(newPath))
|
|
end
|
|
function chroot.rmdir(path)
|
|
return fs.rmdir(resolve(path))
|
|
end
|
|
function chroot.rmrf(path)
|
|
return fs.rmrf(resolve(path))
|
|
end
|
|
function chroot.scandir(path, iter)
|
|
return fs.scandir(resolve(path), iter)
|
|
end
|
|
function chroot.readFile(path)
|
|
return fs.readFile(resolve(path))
|
|
end
|
|
function chroot.writeFile(path, data, mkdir)
|
|
return fs.writeFile(resolve(path), data, mkdir)
|
|
end
|
|
return chroot
|
|
end
|
|
|
|
return exports
|