Advertisement
JackMacWindows

apt-lua installer

Jan 11th, 2020
265
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 33.41 KB | None | 0 0
  1. -- Tape Archive (tar) archiver/unarchiver library (using UStar)
  2. -- Use in the shell or with require
  3.  
  4. local function trim(s) return string.match(s, '^()[%s%z]*$') and '' or string.match(s, '^[%s%z]*(.*[^%s%z])') end
  5. local function u2cc(p) return bit.band(p, 0x1) * 8 + bit.band(p, 0x2) + bit.band(p, 0x4) / 4 + 4 end
  6. local function cc2u(p) return bit.band(p, 0x8) / 8 + bit.band(p, 0x2) + bit.band(p, 0x1) * 4 end
  7. local function pad(str, len, c) return string.len(str) < len and string.sub(str, 1, len) .. string.rep(c or " ", len - string.len(str)) or str end
  8. local function lpad(str, len, c) return string.len(str) < len and string.rep(c or " ", len - string.len(str)) .. string.sub(str, 1, len) or str end
  9. local function tidx(t, i, ...)
  10.     if i and t[i] == nil then t[i] = {} end
  11.     return i ~= nil and tidx(t[i], ...) or t
  12. end
  13. local function split(str, sep)
  14.     local t={}
  15.     for s in string.gmatch(str, "([^"..(sep or "%s").."]+)") do table.insert(t, s) end
  16.     return t
  17. end
  18. local verbosity = 0
  19. local ignore_zero = false
  20.  
  21. local tar = {}
  22.  
  23. -- Converts a serial list of tar entries into a hierarchy
  24. function tar.unserialize(data)
  25.     local retval = {}
  26.     local links = {}
  27.     for k,v in pairs(data) do
  28.         local components = split(v.name, "/")
  29.         local name = table.remove(components, table.maxn(components))
  30.         local dir = tidx(retval, table.unpack(components))
  31.         if v.type == 0 or v.type == 7 then dir[name] = v
  32.         elseif v.type == 1 or v.type == 2 then table.insert(links, v)
  33.         elseif v.type == 5 then dir[name] = {["//"] = v} end
  34.     end
  35.     for k,v in pairs(links) do
  36.         local components = split(v.name, "/")
  37.         local name = table.remove(components, table.maxn(components))
  38.         tidx(retval, table.unpack(components))[name] = tidx(retval, table.unpack(split(v.link, "/")))
  39.     end
  40.     return retval
  41. end
  42.  
  43. -- Converts a hierarchy into a serial list of tar entries
  44. function tar.serialize(data)
  45.     --if data["//"] == nil then error("Invalid directory " .. data.name) end
  46.     local retval = (data["//"] ~= nil and #data["//"] > 0) and {data["//"]} or {}
  47.     for k,v in pairs(data) do if k ~= "//" then
  48.         if v["//"] ~= nil or v.name == nil then
  49.             local t = table.maxn(retval)
  50.             for l,w in ipairs(tar.serialize(v)) do retval[t+l] = w end
  51.         else table.insert(retval, v) end
  52.     end end
  53.     return retval
  54. end
  55.  
  56. -- Loads an archive into a table
  57. function tar.load(path, noser, rawdata)
  58.     if not fs.exists(path) and not rawdata then error("Path does not exist", 2) end
  59.     local file
  60.     if rawdata then
  61.         local s = 1
  62.         file = {
  63.             read = function(num)
  64.                 if num then
  65.                     s=s+num
  66.                     return string.sub(path, s-num, s-1)
  67.                 end
  68.                 s=s+1
  69.                 return string.byte(string.sub(path, s-1, s-1))
  70.             end,
  71.             close = function() end,
  72.             seek = true,
  73.         }
  74.     else file = fs.open(path, "rb") end
  75.     local oldread = file.read
  76.     local sum = 0
  77.     local seek = 0
  78.     file.read = function(c)
  79.         c = c or 1
  80.         if c < 1 then return end
  81.         local retval = nil
  82.         if file.seek then
  83.             retval = oldread(c)
  84.             if retval ~= nil then for ch in retval:gmatch(".") do sum = sum + ch:byte() end end
  85.         else
  86.             for i = 1, c do
  87.                 local n = oldread()
  88.                 if n == nil then return retval end
  89.                 retval = (retval or "") .. string.char(n)
  90.                 sum = sum + n
  91.                 if i % 1000000 == 0 then
  92.                     os.queueEvent("nosleep")
  93.                     os.pullEvent()
  94.                 end
  95.             end
  96.         end
  97.         seek = seek + c
  98.         return retval
  99.     end
  100.     local retval = {}
  101.     local empty_blocks = 0
  102.     while true do
  103.         local data = {}
  104.         sum = 0
  105.         data.name = file.read(100)
  106.         assert(seek % 512 == 100)
  107.         if data.name == nil then break
  108.         elseif data.name == string.rep("\0", 100) then
  109.             file.read(412)
  110.             assert(seek % 512 == 0)
  111.             empty_blocks = empty_blocks + 1
  112.             if empty_blocks == 2 and not ignore_zero then break end
  113.         else
  114.             data.name = trim(data.name)
  115.             data.mode = tonumber(trim(file.read(8)), 8)
  116.             data.owner = tonumber(trim(file.read(8)), 8)
  117.             data.group = tonumber(trim(file.read(8)), 8)
  118.             local size = tonumber(trim(file.read(12)), 8)
  119.             data.timestamp = tonumber(trim(file.read(12)), 8)
  120.             local o = sum
  121.             local checksum = tonumber(trim(file.read(8)), 8)
  122.             sum = o + 256
  123.             local t = file.read()
  124.             data.type = tonumber(t == "\0" and "0" or t) or t
  125.             data.link = trim(file.read(100))
  126.             if trim(file.read(6)) == "ustar" then
  127.                 file.read(2)
  128.                 data.ownerName = trim(file.read(32))
  129.                 data.groupName = trim(file.read(32))
  130.                 data.deviceNumber = {tonumber(trim(file.read(8))), tonumber(trim(file.read(8)))}
  131.                 if data.deviceNumber[1] == nil and data.deviceNumber[2] == nil then data.deviceNumber = nil end
  132.                 data.name = trim(file.read(155)) .. data.name
  133.             end
  134.             file.read(512 - (seek % 512))
  135.             assert(seek % 512 == 0)
  136.             if sum ~= checksum then print("Warning: checksum mismatch for " .. data.name) end
  137.             if size ~= nil and size > 0 then
  138.                 data.data = file.read(size)
  139.                 if size % 512 ~= 0 then file.read(512 - (seek % 512)) end
  140.             end
  141.             assert(seek % 512 == 0)
  142.             table.insert(retval, data)
  143.         end
  144.         os.queueEvent("nosleep")
  145.         os.pullEvent()
  146.     end
  147.     file.close()
  148.     return noser and retval or tar.unserialize(retval)
  149. end
  150.  
  151. -- Extracts files from a table or file to a directory
  152. function tar.extract(data, path, link)
  153.     fs.makeDir(path)
  154.     local links = {}
  155.     for k,v in pairs(data) do if k ~= "//" then
  156.         local p = fs.combine(path, k)
  157.         if v["//"] ~= nil then
  158.             local l = tar.extract(v, p, kernel ~= nil)
  159.             if kernel then for l,w in pairs(l) do table.insert(links, w) end end
  160.         elseif (v.type == 1 or v.type == 2) and kernel then table.insert(links, v)
  161.         elseif v.type == 0 or v.type == 7 then
  162.             local file = fs.open(p, "wb")
  163.             for s in string.gmatch(v.data, ".") do file.write(string.byte(s)) end
  164.             file.close()
  165.             if kernel and v.owner ~= nil then
  166.                 fs.setPermissions(p, "*", u2cc(bit.brshift(v.mode, 6)) + bit.band(v.mode, 0x800) / 0x80)
  167.                 if v.ownerName ~= nil and v.ownerName ~= "" then
  168.                     fs.setPermissions(p, users.getUIDFromName(v.ownerName), u2cc(v.mode) + bit.band(v.mode, 0x800) / 0x80)
  169.                     fs.setOwner(p, users.getUIDFromName(v.ownerName))
  170.                 else
  171.                     fs.setPermissions(p, v.owner, u2cc(v.mode) + bit.band(v.mode, 0x800) / 0x80)
  172.                     fs.setOwner(p, v.owner)
  173.                 end
  174.             end
  175.         elseif v.type ~= nil then print("Unimplemented type " .. v.type) end
  176.         if verbosity > 0 then print(((v["//"] and v["//"].name or v.name) or "?") .. " => " .. (p or "?")) end
  177.         os.queueEvent("nosleep")
  178.         os.pullEvent()
  179.     end end
  180.     if link then return links
  181.     elseif kernel then for k,v in pairs(links) do
  182.         -- soon(tm)
  183.     end end
  184. end
  185.  
  186. -- Reads a file into a table entry
  187. function tar.read(base, p)
  188.     local file = fs.open(fs.combine(base, p), "rb")
  189.     local retval = {
  190.         name = p,
  191.         mode = fs.getPermissions and cc2u(fs.getPermissions(p, fs.getOwner(p) or 0)) * 0x40 + cc2u(fs.getPermissions(p, "*")) + bit.band(fs.getPermissions(p, "*"), 0x10) * 0x80 or 0x1FF,
  192.         owner = fs.getOwner and fs.getOwner(p) or 0,
  193.         group = 0,
  194.         timestamp = os.epoch and math.floor(os.epoch("utc") / 1000) or 0,
  195.         type = 0,
  196.         link = "",
  197.         ownerName = fs.getOwner and users.getShortName(fs.getOwner(p)) or "",
  198.         groupName = "",
  199.         deviceNumber = nil,
  200.         data = ""
  201.     }
  202.     if file.seek then retval.data = file.read(fs.getSize(fs.combine(base, p))) else
  203.         local c = file.read()
  204.         while c ~= nil do
  205.             retval.data = retval.data .. string.char(c)
  206.             c = file.read()
  207.         end
  208.     end
  209.     file.close()
  210.     return retval
  211. end
  212.  
  213. -- Packs files in a directory into a table
  214. function tar.pack(base, path)
  215.     if not fs.isDir(base) then return tar.read(base, path) end
  216.     local retval = {["//"] = {
  217.         name = path .. "/",
  218.         mode = fs.getPermissions and cc2u(fs.getPermissions(path, fs.getOwner(path) or 0)) * 0x40 + cc2u(fs.getPermissions(path, "*")) + bit.band(fs.getPermissions(path, "*"), 0x10) * 0x80 or 0x1FF,
  219.         owner = fs.getOwner and fs.getOwner(path) or 0,
  220.         group = 0,
  221.         timestamp = os.epoch and math.floor(os.epoch("utc") / 1000) or 0,
  222.         type = 5,
  223.         link = "",
  224.         ownerName = fs.getOwner and users.getShortName(fs.getOwner(path)) or "",
  225.         groupName = "",
  226.         deviceNumber = nil,
  227.         data = nil
  228.     }}
  229.     if string.sub(base, -1) == "/" then base = string.sub(base, 1, -1) end
  230.     if path and string.sub(path, 1, 1) == "/" then path = string.sub(path, 2) end
  231.     if path and string.sub(path, -1) == "/" then path = string.sub(path, 1, -1) end
  232.     local p = path and (base .. "/" .. path) or base
  233.     for k,v in pairs(fs.list(p)) do
  234.         if fs.isDir(fs.combine(p, v)) then retval[v] = tar.pack(base, path and (path .. "/" .. v) or v)
  235.         else retval[v] = tar.read(base, path and (path .. "/" .. v) or v) end
  236.         if verbosity > 0 then print(fs.combine(p, v) .. " => " .. (path and (path .. "/" .. v) or v)) end
  237.     end
  238.     return retval
  239. end
  240.  
  241. -- Saves a table to an archive file
  242. function tar.save(data, path, noser)
  243.     if not noser then data = tar.serialize(data) end
  244.     local nosave = path == nil
  245.     local file
  246.     local seek = 0
  247.     if not nosave then
  248.         file = fs.open(path, "wb")
  249.         local oldwrite = file.write
  250.         file.write = function(str)
  251.             for c in string.gmatch(str, ".") do oldwrite(string.byte(c)) end
  252.             seek = seek + string.len(str)
  253.         end
  254.     else file = "" end
  255.     for k,v in pairs(data) do
  256.         local header = ""
  257.         header = header .. pad(string.sub(v.name, -100), 100, "\0")
  258.         header = header .. (v.mode and string.format("%07o\0", v.mode) or string.rep("\0", 8))
  259.         header = header .. (v.owner and string.format("%07o\0", v.owner) or string.rep("\0", 8))
  260.         header = header .. (v.group and string.format("%07o\0", v.group) or string.rep("\0", 8))
  261.         header = header .. (v.data and string.format("%011o\0", string.len(v.data)) or (string.rep("0", 11) .. "\0"))
  262.         header = header .. (v.timestamp and string.format("%011o\0", v.timestamp) or string.rep("\0", 12))
  263.         header = header .. v.type
  264.         header = header .. (v.link and pad(v.link, 100, "\0") or string.rep("\0", 100))
  265.         header = header .. "ustar  \0"
  266.         header = header .. (v.ownerName and pad(v.ownerName, 32, "\0") or string.rep("\0", 32))
  267.         header = header .. (v.groupName and pad(v.groupName, 32, "\0") or string.rep("\0", 32))
  268.         header = header .. (v.deviceNumber and v.deviceNumber[1] and string.format("%07o\0", v.deviceNumber[1]) or string.rep("\0", 8))
  269.         header = header .. (v.deviceNumber and v.deviceNumber[2] and string.format("%07o\0", v.deviceNumber[2]) or string.rep("\0", 8))
  270.         header = header .. (string.len(v.name) > 100 and pad(string.sub(v.name, 1, -101), 155, "\0") or string.rep("\0", 155))
  271.         if string.len(header) < 504 then header = header .. string.rep("\0", 504 - string.len(header)) end
  272.         local sum = 256
  273.         for c in string.gmatch(header, ".") do sum = sum + string.byte(c) end
  274.         header = string.sub(header, 1, 148) .. string.format("%06o\0 ", sum) .. string.sub(header, 149)
  275.         if nosave then file = file .. header else file.write(header) end
  276.         --assert(seek % 512 == 0)
  277.         if v.data ~= nil and v.data ~= "" then
  278.             if nosave then file = file .. pad(v.data, math.ceil(string.len(v.data) / 512) * 512, "\0")
  279.             else file.write(pad(v.data, math.ceil(string.len(v.data) / 512) * 512, "\0")) end
  280.         end
  281.     end
  282.     if nosave then file = file .. string.rep("\0", 1024) else file.write(string.rep("\0", 1024)) end
  283.     if nosave then file = file .. string.rep("\0", 10240 - (string.len(file) % 10240)) else file.write(string.rep("\0", 10240 - (seek % 10240))) end
  284.     if not nosave then file.close() end
  285.     os.queueEvent("nosleep")
  286.     os.pullEvent()
  287.     if nosave then return file end
  288. end
  289.  
  290. local function strmap(num, str, c)
  291.     local retval = ""
  292.     for i = 1, string.len(str) do retval = retval .. (bit.band(num, bit.blshift(1, string.len(str)-i)) == 0 and c or string.sub(str, i, i)) end
  293.     return retval
  294. end
  295.  
  296. local function CurrentDate(z)
  297.     local z = math.floor(z / 86400) + 719468
  298.     local era = math.floor(z / 146097)
  299.     local doe = math.floor(z - era * 146097)
  300.     local yoe = math.floor((doe - doe / 1460 + doe / 36524 - doe / 146096) / 365)
  301.     local y = math.floor(yoe + era * 400)
  302.     local doy = doe - math.floor((365 * yoe + yoe / 4 - yoe / 100))
  303.     local mp = math.floor((5 * doy + 2) / 153)
  304.     local d = math.ceil(doy - (153 * mp + 2) / 5 + 1)
  305.     local m = math.floor(mp + (mp < 10 and 3 or -9))
  306.     return y + (m <= 2 and 1 or 0), m, d
  307. end
  308.    
  309. local function CurrentTime(unixTime)
  310.     local hours = math.floor(unixTime / 3600 % 24)
  311.     local minutes = math.floor(unixTime / 60 % 60)
  312.     local seconds = math.floor(unixTime % 60)
  313.     local year, month, day = CurrentDate(unixTime)
  314.     return {
  315.         year = year,
  316.         month = month,
  317.         day = day,
  318.         hours = hours,
  319.         minutes = minutes < 10 and "0" .. minutes or minutes,
  320.         seconds = seconds < 10 and "0" .. seconds or seconds
  321.     }
  322. end
  323.  
  324. local usage_str = [=[Usage: tar [OPTION...] [FILE]...
  325. CraftOS 'tar' saves many files together into a single tape or disk archive, and
  326. can restore individual files from the archive.
  327.  
  328. Examples:
  329.   tar -cf archive.tar foo bar  # Create archive.tar from files foo and bar.
  330.   tar -tvf archive.tar         # List all files in archive.tar verbosely.
  331.   tar -xf archive.tar          # Extract all files from archive.tar.
  332.  
  333.  Local file name selection:
  334.  
  335.       --add-file=FILE        add given FILE to the archive (useful if its name
  336.                              starts with a dash)
  337.   -C, --directory=DIR        change to directory DIR
  338.       --no-null              disable the effect of the previous --null option
  339.       --no-recursion         avoid descending automatically in directories
  340.       --null                 -T reads null-terminated names; implies
  341.                              --verbatim-files-from
  342.       --recursion            recurse into directories (default)
  343.   -T, --files-from=FILE      get names to extract or create from FILE
  344.  
  345.  Main operation mode:
  346.  
  347.   -A, --catenate, --concatenate   append tar files to an archive
  348.   -c, --create               create a new archive
  349.   -d, --diff, --compare      find differences between archive and file system
  350.       --delete               delete from the archive (not on mag tapes!)
  351.   -r, --append               append files to the end of an archive
  352.   -t, --list                 list the contents of an archive
  353.   -u, --update               only append files newer than copy in archive
  354.   -x, --extract, --get       extract files from an archive
  355.  
  356.  Overwrite control:
  357.  
  358.   -k, --keep-old-files       don't replace existing files when extracting,
  359.                              treat them as errors
  360.       --overwrite            overwrite existing files when extracting
  361.       --remove-files         remove files after adding them to the archive
  362.   -W, --verify               attempt to verify the archive after writing it
  363.  
  364.  Device selection and switching:
  365.  
  366.   -f, --file=ARCHIVE         use archive file or device ARCHIVE
  367.    
  368.  Device blocking:
  369.  
  370.   -i, --ignore-zeros         ignore zeroed blocks in archive (means EOF)
  371.  
  372.  Compression options:
  373.  
  374.   -z, --gzip, --gunzip, --ungzip   filter the archive through gzip
  375.  
  376.  Local file selection:
  377.  
  378.   -N, --newer=DATE-OR-FILE, --after-date=DATE-OR-FILE
  379.                              only store files newer than DATE-OR-FILE
  380.  
  381.  Informative output:
  382.  
  383.   -v, --verbose              verbosely list files processed
  384.  
  385.  Other options:
  386.  
  387.   -?, --help                 give this help list
  388.       --usage                give a short usage message
  389.       --version              print program version]=]
  390.  
  391. if pcall(require, "tar") then
  392.     local args = {...}
  393.     local arch = nil
  394.     local files = {}
  395.     local mode = nil
  396.     local nextarg = nil
  397.     local replace = true
  398.     local delete = false
  399.     local verify = false
  400.     local outdir = nil
  401.     local preserve = false
  402.     local compress = false
  403.     local start = nil
  404.     local newerthan = 0
  405.     local null = false
  406.     local norecurse = false
  407.     for k,v in pairs(args) do
  408.         if nextarg then
  409.             if nextarg == 0 then arch = v
  410.             elseif nextarg == 1 then outdir = v
  411.             elseif nextarg == 2 then start = v
  412.             elseif nextarg == 3 then newerthan = tonumber(v)
  413.             elseif nextarg == 4 then
  414.                 local file = fs.open(shell.resolve(v), "r")
  415.                 local line = file.readLine()
  416.                 while line ~= nil do
  417.                     if null then table.insert(files, line) else table.insert(args, line) end
  418.                     line = file.readLine()
  419.                 end
  420.                 file.close()
  421.             end
  422.             nextarg = nil
  423.         elseif k == 1 or (string.sub(v, 1, 1) == "-" and string.sub(v, 2, 2) ~= "-") then
  424.             if string.find(v, "A") then mode = 0 end
  425.             if string.find(v, "d") then mode = 2 end
  426.             if string.find(v, "c") then mode = 1 end
  427.             if string.find(v, "r") then mode = 3 end
  428.             if string.find(v, "t") then mode = 4 end
  429.             if string.find(v, "u") then mode = 5 end
  430.             if string.find(v, "x") then mode = 6 end
  431.             if string.find(v, "f") then nextarg = 0 end
  432.             if string.find(v, "k") then replace = false end
  433.             if string.find(v, "U") then delete = true end
  434.             if string.find(v, "W") then verify = true end
  435.             if string.find(v, "O") then outdir = 0 end
  436.             if string.find(v, "p") and kernel then preserve = true end
  437.             if string.find(v, "i") then ignore_zero = true end
  438.             if string.find(v, "z") then compress = true end
  439.             if string.find(v, "C") then nextarg = 1 end
  440.             if string.find(v, "K") then nextarg = 2 end
  441.             if string.find(v, "N") then nextarg = 3 end
  442.             if string.find(v, "T") then nextarg = 4 end
  443.             if string.find(v, "v") then verbosity = 1  end
  444.             if string.find(v, "?") then
  445.                 print(usage_str)
  446.                 return 2
  447.             end
  448.         elseif string.sub(v, 1, 2) == "--" then
  449.             if v == "--catenate" then mode = 0
  450.             elseif v == "--concatenate" then mode = 0
  451.             elseif v == "--create" then mode = 1
  452.             elseif v == "--diff" then mode = 2
  453.             elseif v == "--compare" then mode = 2
  454.             elseif v == "--delete" then mode = 7
  455.             elseif v == "--append" then mode = 3
  456.             elseif v == "--list" then mode = 4
  457.             elseif v == "--update" then mode = 5
  458.             elseif v == "--extract" then mode = 6
  459.             elseif v == "--get" then mode = 6
  460.             elseif v == "--help" or v == "--usage" then
  461.                 print(usage_str)
  462.                 return 2
  463.             elseif v == "--version" then
  464.                 print("CraftOS tar v1.0")
  465.                 return 2
  466.             elseif v == "--keep-old-files" then replace = false
  467.             elseif v == "--overwrite" then replace = true
  468.             elseif v == "--remove-files" then delete = true
  469.             elseif v == "--unlink-first" then delete = true
  470.             elseif v == "--verify" then verify = true
  471.             elseif v == "--to-stdout" then outdir = 0
  472.             elseif v == "--preserve-permissions" and kernel then preserve = true
  473.             elseif v == "--same-permissions" and kernel then preserve = true
  474.             elseif v == "--preserve" and kernel then preserve = true
  475.             elseif string.find(v, "--file=") then arch = string.sub(v, 8)
  476.             elseif v == "--ignore-zeros" then ignore_zero = true
  477.             elseif v == "--gzip" or v == "--gunzip" or v == "--ungzip" then compress = true
  478.             elseif string.find(v, "--add-file=") then table.insert(files, string.sub(v, 12))
  479.             elseif string.find(v, "--directory=") then outdir = string.sub(v, 13)
  480.             elseif string.find(v, "--starting-file=") then start = string.sub(v, 17)
  481.             elseif v == "--no-null" then null = false
  482.             elseif v == "--null" then null = true
  483.             elseif string.find(v, "--newer=") then newerthan = tonumber(string.sub(v, 9))
  484.             elseif string.find(v, "--after-date=") then newerthan = tonumber(string.sub(v, 14))
  485.             elseif string.find(v, "--files-from=") then
  486.                 local file = fs.open(shell.resolve(string.sub(v, 14)), "r")
  487.                 local line = file.readLine()
  488.                 while line ~= nil do
  489.                     if null then table.insert(files, line) else table.insert(args, line) end
  490.                     line = file.readLine()
  491.                 end
  492.                 file.close()
  493.             elseif v == "--verbose" then verbosity = 1
  494.             elseif v == "--no-recursion" then norecurse = true end
  495.         else table.insert(files, v) end
  496.     end
  497.     if compress and LibDeflate == nil then
  498.         LibDeflate = require "LibDeflate"
  499.         if LibDeflate == nil then error("Compression is only supported when LibDeflate.lua is available in the PATH.") end
  500.     end
  501.     local olddir = shell.dir()
  502.     if type(outdir) == "string" then shell.setDir(shell.resolve(outdir)) end
  503.     local function err(str)
  504.         shell.setDir(olddir)
  505.         error(str)
  506.     end
  507.     local function loadFile(noser)
  508.         if compress then
  509.             local rawdata = ""
  510.             local file = fs.open(shell.resolve(arch), "rb")
  511.             local c = file.read()
  512.             while c ~= nil do
  513.                 rawdata = rawdata .. string.char(c)
  514.                 c = file.read()
  515.                 if string.len(rawdata) % 10240 == 0 then
  516.                     os.queueEvent("nosleep")
  517.                     os.pullEvent()
  518.                 end
  519.             end
  520.             file.close()
  521.             return load(LibDeflate:DecompressGzip(rawdata), noser, true)
  522.         else return load(shell.resolve(arch), noser) end
  523.     end
  524.     local function saveFile(data)
  525.         if not compress and arch then tar.save(data, shell.resolve(arch)) else
  526.             local retval = tar.save(data, nil)
  527.             if compress then retval = LibDeflate:CompressGzip(retval) end
  528.             if outdir == 0 then write(retval)
  529.             elseif retval then
  530.                 local file = fs.open(shell.resolve(arch), "wb")
  531.                 for c in string.gmatch(retval, ".") do file.write(string.byte(c)) end
  532.                 file.close()
  533.             end
  534.         end
  535.     end
  536.     --[[ reminder:
  537.     local args = {...}
  538.     local arch = nil
  539.     local files = {}
  540.  
  541.     local replace = true
  542.     local delete = false
  543.     local verify = false
  544.     local preserve = false
  545.     local start = nil
  546.     local newerthan = 0
  547.     ]]
  548.     if mode == 0 then --concatenate
  549.         if compress == true then err("Compressed files cannot be concatenated") end
  550.         if arch == nil then err("You must specify an arhive with -f <first.tar>.") end
  551.         local fout = fs.open(shell.resolve(arch), "ab")
  552.         for k,v in pairs(files) do
  553.             local fin = fs.open(shell.resolve(v), "rb")
  554.             local c = fin.read()
  555.             while c do
  556.                 fout.write(c)
  557.                 c = fin.read()
  558.             end
  559.             fin.close()
  560.         end
  561.         fout.close()
  562.     elseif mode == 1 then --create
  563.         if arch == nil and outdir ~= 0 then err("You must specify an archive with -f <output.tar> or -O.") end
  564.         local data = {}
  565.         for k,v in pairs(files) do
  566.             local components = split(v, "/")
  567.             local d = data
  568.             local path = nil
  569.             for k,v in pairs(components) do
  570.                 if k == #components then break end
  571.                 path = path and fs.combine(path, v) or v
  572.                 if d[v] == nil then d[v] = {--[[["//"] = {
  573.                     name = path,
  574.                     mode = fs.getPermissions and cc2u(fs.getPermissions(path, fs.getOwner(path) or 0)) * 0x40 + cc2u(fs.getPermissions(path, "*")) + bit.band(fs.getPermissions(path, "*"), 0x10) * 0x80 or 0x1FF,
  575.                     owner = fs.getOwner and fs.getOwner(path) or 0,
  576.                     group = 0,
  577.                     timestamp = os.epoch and math.floor(os.epoch("utc") / 1000) or 0,
  578.                     type = 5,
  579.                     link = "",
  580.                     ownerName = fs.getOwner and users.getShortName(fs.getOwner(p)) or "",
  581.                     groupName = "",
  582.                     deviceNumber = nil,
  583.                     data = nil
  584.                 }]]} end
  585.                 d = d[v]
  586.             end
  587.             if string.sub(v, 1, 1) == "/" then d[components[#components]] = (norecurse and tar.read or tar.pack)("/", string.sub(v, 2))
  588.             else d[components[#components]] = (norecurse and tar.read or tar.pack)(shell.dir(), v) end
  589.             if delete then fs.delete(shell.resolve(v)) end
  590.         end
  591.         saveFile(data)
  592.     elseif mode == 2 then --diff
  593.         err("Not implemented")
  594.     elseif mode == 3 then --append
  595.         if arch == nil and outdir ~= 0 then err("You must specify an archive with -f <output.tar> or -O.") end
  596.         local data = loadFile(true)
  597.         for k,v in pairs(files) do
  598.             if string.sub(v, 1, 1) == "/" then table.insert(data, (norecurse and tar.read or tar.pack)("/", string.sub(v, 2)))
  599.             else table.insert(data, (norecurse and tar.read or tar.pack)(shell.dir(), v)) end
  600.             if delete then fs.delete(shell.resolve(v)) end
  601.         end
  602.         saveFile(data)
  603.     elseif mode == 4 then --list
  604.         if arch == nil then err("You must specify an archive with -f <file.tar>.") end
  605.         local data = loadFile(true)
  606.         if verbosity > 0 then
  607.             local tmp = {}
  608.             local max = {0, 0, 0, 0, 0}
  609.             for k,v in pairs(data) do
  610.                 local date = CurrentTime(v.timestamp or 0)
  611.                 local d = string.format("%04d-%02d-%02d %02d:%02d", date.year, date.month, date.day, date.hours, date.minutes)
  612.                 local p = {strmap(v.mode + (v.type == 5 and 0x200 or 0), "drwxrwxrwx", "-"), (v.ownerName or v.owner or 0) .. "/" .. (v.groupName or v.group or 0), string.len(v.data or ""), d, v.name .. (v.link and v.link ~= "" and (" -> " .. v.link) or "")}
  613.                 for l,w in pairs(p) do if string.len(w) + 1 > max[l] then max[l] = string.len(w) + 1 end end
  614.                 table.insert(tmp, p)
  615.             end
  616.             for k,v in pairs(tmp) do
  617.                 for l,w in pairs(v) do write((l == 3 and lpad or pad)(w, max[l]) .. (l == 3 and " " or "")) end
  618.                 print("")  
  619.             end
  620.         else for k,v in pairs(data) do print(v.name) end end
  621.     elseif mode == 5 then --update
  622.         if arch == nil and outdir ~= 0 then err("You must specify an archive with -f <output.tar> or -O.") end
  623.         local data = loadFile()
  624.         for k,v in pairs(files) do
  625.             local components = split(v, "/")
  626.             local d = data
  627.             local path = nil
  628.             for k,v in pairs(components) do
  629.                 if k == #components then break end
  630.                 path = path and fs.combine(path, v) or v
  631.                 if d[v] == nil then d[v] = {["//"] = {
  632.                     name = path,
  633.                     mode = fs.getPermissions and cc2u(fs.getPermissions(path, fs.getOwner(path) or 0)) * 0x40 + cc2u(fs.getPermissions(path, "*")) + bit.band(fs.getPermissions(path, "*"), 0x10) * 0x80 or 0x1FF,
  634.                     owner = fs.getOwner and fs.getOwner(path) or 0,
  635.                     group = 0,
  636.                     timestamp = os.epoch and math.floor(os.epoch("utc") / 1000) or 0,
  637.                     type = 5,
  638.                     link = "",
  639.                     ownerName = fs.getOwner and users.getShortName(fs.getOwner(path)) or "",
  640.                     groupName = "",
  641.                     deviceNumber = nil,
  642.                     data = nil
  643.                 }} end
  644.                 d = d[v]
  645.             end
  646.             if string.sub(v, 1, 1) == "/" then d[components[#components]] = (norecurse and tar.read or tar.pack)("/", string.sub(v, 2))
  647.             else d[components[#components]] = (norecurse and tar.read or tar.pack)(shell.dir(), v) end
  648.             if delete then fs.delete(shell.resolve(v)) end
  649.         end
  650.         saveFile(data)
  651.     elseif mode == 6 then --extract
  652.         if arch == nil then err("You must specify an archive with -f <file.tar>.") end
  653.         local data = loadFile()
  654.         tar.extract(data, shell.dir())
  655.     elseif mode == 7 then --delete
  656.         if arch == nil then err("You must specify an archive with -f <file.tar>.") end
  657.         local data = loadFile(true)
  658.         for k,v in pairs(files) do for l,w in pairs(data) do if w.name == v then
  659.             data[l] = nil
  660.             break
  661.         end end end
  662.         saveFile(data)
  663.     else err("You must specify one of -Acdrtux, see --help for details.") end
  664.     shell.setDir(olddir)
  665. end
  666.  
  667. -- Actual installer
  668. write("Enter the desired install path: ")
  669. local install_path = read(nil, nil, nil, "/usr/apt-lua")
  670.  
  671. -- Install dpkg
  672. local temp = false
  673. if not fs.exists(shell.resolve("dpkg-lua.tar")) then
  674.     temp = true
  675.     print("Downloading dpkg-lua...")
  676.     local handle = http.get("https://github.com/MCJack123/apt-lua/blob/master/dpkg-lua.tar", nil, true)
  677.     local first = handle.read(1)
  678.     local file = fs.open(shell.resolve("dpkg-lua.tar"), "wb")
  679.     if type(first) == "number" then
  680.         while first ~= nil do
  681.             file.write(first)
  682.             first = handle.read()
  683.         end
  684.     else
  685.         first = first .. handle.read(4095)
  686.         while first ~= nil do
  687.             file.write(first)
  688.             first = handle.read(4096)
  689.         end
  690.     end
  691.     file.close()
  692.     handle.close()
  693. end
  694. print("Unpacking dpkg-lua.tar ...")
  695. local pkg = tar.load(shell.resolve("dpkg-lua.tar"))
  696. tar.extract(pkg, install_path)
  697. if temp then fs.delete(shell.resolve("dpkg-lua.tar")) end
  698. print("Setting up dpkg ...")
  699. fs.makeDir("/var/lib/dpkg/info")
  700. fs.makeDir("/var/lib/dpkg/triggers")
  701. fs.open("/var/lib/dpkg/triggers/File", "w").close()
  702. fs.open("/var/lib/dpkg/triggers/Unincorp", "w").close()
  703. local file = fs.open("/var/lib/dpkg/status", "w")
  704. file.write([[Package: dpkg
  705. Version: 0.1
  706. Architecture: craftos
  707. Maintainer: JackMacWindows <jackmacwindowslinux@gmail.com>
  708. Status: install ok installed
  709. Installed-Size: 343624
  710. Section: package-managers
  711. Essential: yes
  712. Priority: essential
  713. Description: dpkg package manager for CraftOS
  714.  dpkg-lua is a port of Debian's dpkg package manager for CraftOS.
  715. It supports most of the features available in dpkg.
  716. ]])
  717. file.close()
  718. file = fs.open("/var/lib/dpkg/info/dpkg.list", "w")
  719. for k in pairs(pkg) do file.writeLine(install_path .. "/" .. k) end
  720. file.writeLine("/var\n/var/lib\n/var/lib/dpkg\n/var/lib/dpkg/info\n/var/lib/dpkg/triggers")
  721. file.close()
  722. local md5 = dofile(install_path .. "/md5.lua")
  723. file = fs.open("/var/lib/dpkg/info/dpkg.md5sums", "w")
  724. for k,v in pairs(pkg) do file.writeLine(md5.sumhexa(v.data) .. "  " .. install_path .. "/" .. k) end
  725. file.close()
  726.  
  727. -- Install apt
  728. temp = false
  729. if not fs.exists(shell.resolve("apt-lua.deb")) then
  730.    temp = true
  731.    local handle = http.get("https://api.github.com/repos/MCJack123/apt-lua/contents/apt-lua.deb")
  732.    if handle.readAll():find("Not Found") then
  733.        temp = -1
  734.        handle.close()
  735.    else
  736.        handle.close()
  737.        print("Downloading apt-lua...")
  738.        handle = http.get("https://github.com/MCJack123/apt-lua/blob/master/apt-lua.deb", nil, true)
  739.        local first = handle.read(1)
  740.        file = fs.open(shell.resolve("apt-lua.deb"), "wb")
  741.        if type(first) == "number" then
  742.            while first ~= nil do
  743.                file.write(first)
  744.                first = handle.read()
  745.            end
  746.        else
  747.            first = first .. handle.read(4095)
  748.            while first ~= nil do
  749.                file.write(first)
  750.                first = handle.read(4096)
  751.            end
  752.        end
  753.        file.close()
  754.        handle.close()
  755.    end
  756. end
  757. if temp ~= -1 then
  758.    shell.run(install_path .. "/dpkg -i " .. shell.resolve("apt-lua.deb"))
  759.    if temp then fs.delete(shell.resolve("apt-lua.deb")) end
  760. end
  761.  
  762. -- Update PATH
  763. write("Would you like apt-lua to be added to your PATH? (y/N) ")
  764. local res = read()
  765. if res == "y" or res == "Y" then
  766.    file = fs.open("/startup.lua", fs.exists("/startup.lua") and "a" or "w")
  767.    file.writeLine("")
  768.    file.writeLine("shell.setPath(shell.path() .. ':" .. install_path .. "')")
  769.    file.close()
  770.    shell.setPath(shell.path() .. ':' .. install_path)
  771.    print("apt-lua has been added to your PATH.")
  772. end
  773. print("Done.")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement