local winfs = {}
local arg = arg
_G.arg = nil
function winfs.init(uuid)
return winfs.fordisk(uuid)
end
function winfs.fordisk(uuid)
local uuids = winfs.diskUUIDs()
local letter = uuids[uuid:lower()]
if not letter or letter == '' then
error(('disk for uuid %q not found; run `mountvol` to see what is available'):format(uuid))
end
return {
exists = function(path)
return winfs.osexists(winfs.ospath(letter..'/'..path))
end,
query = function(path, shadowpath)
winfs.copy(winfs.ospath(letter..'/'..path), shadowpath)
end,
apply = function(path, shadowpath)
winfs.osapply(winfs.ospath(letter..'/'..path), shadowpath)
end,
}
end
function winfs.ospath(path)
if not string.match(path, '^[a-zA-Z]/') then
error(('path not valid for Windows, must be "<DISK>/<RELPATH>", got: %q'):format(path))
end
return path:sub(1,1) .. ":\\" .. path:sub(3):gsub("/", "\\")
end
function winfs.osexists(ospath)
local fh, err = io.open(ospath, 'r')
if fh then
fh:close()
end
return not not fh
end
function winfs.osapply(ospath, shadowpath)
if winfs.osexists(shadowpath) then
winfs.mkdirp(ospath)
winfs.copy(shadowpath, ospath)
else
assert(os.remove(ospath))
end
end
function winfs.copy(p1, p2)
local cmd = "copy /b /y " .. p1 .. " " .. p2 .. " >nul"
assert(os.execute(cmd))
end
function winfs.mkdirp(ospath)
local iter = ospath:gmatch "([^\\]+)\\"
local parent = iter() for d in iter do
parent = parent .. '\\' .. d
os.execute("mkdir " .. parent .. " 2>nul >nul")
end
end
function winfs.diskUUIDs()
local pUuid = '^%s*\\\\%?\\Volume{(.*)}\\%s*$'
local pDisk = '([A-Z]):\\'
local pNoDisk = '*** NO MOUNT POINTS ***'
local map = {}
local p = assert(io.popen('mountvol', 'r'))
while true do
local line = p:read '*l'
if not line then break end
local uuid = line:match(pUuid)
if uuid then
local mount = p:read('*l'):gsub('^%s*',''):gsub('%s*$','')
local disk = mount:match('^'..pDisk..'$')
if mount == pNoDisk then
map[uuid:lower()] = ''
elseif disk then
map[uuid:lower()] = disk
else
error(('unexpected format of mount point for UUID %s: %s'):format(uuid, mount))
end
end
end
p:close()
return map
end
return winfs