Advertisement
VlaD00m

copytape.lua

Aug 16th, 2020 (edited)
959
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.12 KB | None | 0 0
  1. --[[ copytape program, provides copying tapes with two tape drives
  2. Author: Bs()Dd (uses original "tape" program code by Bizzycola and Vexatos)
  3. ]]
  4. local component = require("component")
  5. local shell = require("shell")
  6. local term = require("term")
  7.  
  8. local args, options = shell.parse(...)
  9.  
  10. if not component.isAvailable("tape_drive") then
  11.   io.stderr:write("Tape drive is not found in system.")
  12.   return
  13. end
  14.  
  15. local function printUsage()
  16.   print("Usage:")
  17.   print(" - 'copytape adr1 adr2' to copy tape from adr1 tape drive to adr2")
  18.   print(" '--cut' to cut record when second tape is smaller")
  19.   print(" '--b=<bytes>' to specify the size of the chunks the program will write to a tape")
  20.   print(" '-y' to not ask for confirmation before starting to write")
  21.   return
  22. end
  23.  
  24. local function getTapeDrive()
  25.   --Credits to gamax92 for this
  26.   local tape
  27.   if args[1] then
  28.     if type(args[1]) ~= "string" then
  29.       io.stderr:write("'address' may only be a string.\n")
  30.       return
  31.     end
  32.     local fulladdr = component.get(args[1])
  33.     if fulladdr == nil then
  34.       io.stderr:write("No component at first address.\n")
  35.       return
  36.     end
  37.     if component.type(fulladdr) ~= "tape_drive" then
  38.       io.stderr:write("No tape drive at first address.\n")
  39.       return
  40.     end
  41.     tape = component.proxy(fulladdr)
  42.   else
  43.     io.stderr:write("Primary tape adress is not found.\n")
  44.     return
  45.   end
  46.   return tape
  47.   --End of gamax92's part
  48. end
  49.  
  50. local function getTapeDriveTwo()
  51.   --Credits to gamax92 for this
  52.   local tape
  53.   if args[2] then
  54.     if type(args[2]) ~= "string" then
  55.       io.stderr:write("'address' may only be a string.\n")
  56.       return
  57.     end
  58.     local fulladdr = component.get(args[2])
  59.     if fulladdr == nil then
  60.       io.stderr:write("No component at second address.\n")
  61.       return
  62.     end
  63.     if component.type(fulladdr) ~= "tape_drive" then
  64.       io.stderr:write("No tape drive at second address.\n")
  65.       return
  66.     end
  67.     tape = component.proxy(fulladdr)
  68.   else
  69.     io.stderr:write("Secondary tape adress is not found.\n")
  70.     return
  71.   end
  72.   return tape
  73.   --End of gamax92's part
  74. end
  75.  
  76. local function confirm(msg)
  77.   if not options.y then
  78.     print(msg)
  79.     print("Type `y` to confirm, `n` to cancel.")
  80.     repeat
  81.       local response = io.read()
  82.       if response and response:lower():sub(1, 1) == "n" then
  83.         print("Canceled.")
  84.         return false
  85.       end
  86.     until response and response:lower():sub(1, 1) == "y"
  87.   end
  88.   return true
  89. end
  90.  
  91. local function ctape(tape, tapeTwo)
  92.   local block = 2048
  93.   if options.b then
  94.     local nBlock = tonumber(options.b)
  95.     if nBlock then
  96.       print("Setting chunk size to " .. options.b)
  97.       block = nBlock
  98.     else
  99.       io.stderr:write("option --b is not a number.\n")
  100.       return
  101.     end
  102.   end
  103.   local _, y
  104.   local filesize = tape.getSize()
  105.   if not tape.isReady() then
  106.     io.stderr:write("First tape is not inserted.\n")
  107.     os.exit()
  108.   end
  109.   print("Size of first tape is: " .. tape.getSize())
  110.   if not tapeTwo.isReady() then
  111.     io.stderr:write("Second tape is not inserted.\n")
  112.     os.exit()
  113.   end
  114.   print("Size of second tape is: " .. tapeTwo.getSize())
  115.   if tape.getSize() > tapeTwo.getSize() and not options.cut then
  116.     io.stderr:write("Second tape size is not enough to copy.\n")
  117.     os.exit()
  118.   end
  119.   if tape.getSize() > tapeTwo.getSize() and options.cut then
  120.     print("Second tape size is not enough to full copy. Record will cut.")
  121.     filesize = tapeTwo.getSize()
  122.   end
  123.   if not confirm("\nAre you sure you want to copy tape?") then return end
  124.   tape.stop()
  125.   tape.seek(-tape.getSize())
  126.   tape.stop()
  127.   tapeTwo.stop()
  128.   tapeTwo.seek(-tapeTwo.getSize())
  129.   tapeTwo.stop()
  130.   local bytery = 0
  131.   print("Copying...")
  132.   _, y = term.getCursor()
  133.   local function fancyNumber(n)
  134.     return tostring(math.floor(n)):reverse():gsub("(%d%d%d)", "%1,"):gsub("%D$", ""):reverse()
  135.   end
  136.   repeat
  137.   if not tape.isReady() then
  138.         io.stderr:write("\nError: First tape was removed during reading.\n")
  139.     tape.stop()
  140.     tape.seek(-tape.getSize())
  141.     tape.stop()
  142.         os.exit()
  143.       end
  144.       if not tapeTwo.isReady() then
  145.         io.stderr:write("\nError: Second tape was removed during writing.\n")
  146.     tape.stop()
  147.     tape.seek(-tape.getSize())
  148.     tape.stop()
  149.         os.exit()
  150.       end
  151.   local byte = tape.read(block)
  152.     if byte and #byte > 0 then
  153.       term.setCursor(1, y)
  154.       bytery = bytery + #byte
  155.       local displaySize = math.min(bytery, filesize)
  156.       term.write(string.format("Copy %s of %s bytes... (%.2f %%)", fancyNumber(displaySize),    fancyNumber(filesize), 100 * displaySize / filesize))
  157.       tapeTwo.write(byte)
  158.     end
  159.   until not byte or bytery > filesize
  160.   tape.stop()
  161.   tape.seek(-tape.getSize())
  162.   tape.stop()
  163.   tapeTwo.stop()
  164.   tapeTwo.seek(-tapeTwo.getSize())
  165.   tapeTwo.stop()
  166.   tapeTwo.setLabel(tape.getLabel())
  167.   print("\nDone.")
  168. end
  169.  
  170. if args[1] ~= nil and args[2] ~= nil then
  171.   local tape = getTapeDrive()
  172.   if tape == nil then
  173.     os.exit()
  174.   end
  175.   local tapeTwo = getTapeDriveTwo()
  176.   if tapeTwo == nil then
  177.     os.exit()
  178.   end
  179.   ctape(tape, tapeTwo)
  180. else
  181.   printUsage()
  182. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement