mirror of
https://github.com/IgorTimofeev/MineOS.git
synced 2025-12-20 19:19:21 +01:00
212 lines
6.3 KiB
Lua
Executable File
212 lines
6.3 KiB
Lua
Executable File
|
|
require("advancedLua")
|
|
local bit32 = require("bit32")
|
|
local unicode = require("unicode")
|
|
local fs = require("filesystem")
|
|
|
|
-----------------------------------------------------------------------------------------------
|
|
|
|
local module = {}
|
|
|
|
local encodingMethods = {}
|
|
local OCAFSignature = "OCAF"
|
|
local readBufferSize = 1024
|
|
local ignoredFiles = {
|
|
[".DS_Store"] = true
|
|
}
|
|
|
|
-----------------------------------------------------------------------------------------------
|
|
|
|
local function getFileList(path)
|
|
local fileList = {}
|
|
for file in fs.list(path) do
|
|
table.insert(fileList, path .. "/" .. file)
|
|
end
|
|
|
|
return fileList
|
|
end
|
|
|
|
local function readPath(archiveFileHandle)
|
|
local sizeOfSizeArray = {}
|
|
for i = 1, string.byte(archiveFileHandle:read(1)) do
|
|
table.insert(sizeOfSizeArray, string.byte(archiveFileHandle:read(1)))
|
|
end
|
|
|
|
return archiveFileHandle:read(bit32.byteArrayToNumber(sizeOfSizeArray))
|
|
end
|
|
|
|
-- Записываем путь в виде <кол-во байт для размера пути> <размер пути> <путь>
|
|
local function writePath(archiveFileHandle, path)
|
|
-- Получаем юникод-байтики названия файла или папки
|
|
local pathBytes = {}
|
|
for i = 1, unicode.len(path) do
|
|
local charBytes = { string.byte(unicode.sub(path, i, i), 1, 6) }
|
|
for j = 1, #charBytes do
|
|
table.insert(pathBytes, charBytes[j])
|
|
end
|
|
end
|
|
|
|
-- Записываем количество всякой хуйни
|
|
local bytesForCountPathBytes = bit32.numberToByteArray(#pathBytes)
|
|
archiveFileHandle:write(string.char(#bytesForCountPathBytes))
|
|
for i = 1, #bytesForCountPathBytes do
|
|
archiveFileHandle:write(string.char(bytesForCountPathBytes[i]))
|
|
end
|
|
|
|
-- Записываем путь
|
|
for i = 1, #pathBytes do
|
|
archiveFileHandle:write(string.char(pathBytes[i]))
|
|
end
|
|
end
|
|
|
|
-----------------------------------------------------------------------------------------------
|
|
|
|
encodingMethods[0] = {}
|
|
|
|
encodingMethods[0].pack = function(archiveFileHandle, fileList, localPath)
|
|
for i = 1, #fileList do
|
|
local filename = fs.name(fileList[i]) or ""
|
|
local currentLocalPath = (localPath or "") .. "/" .. filename
|
|
-- print("Writing path:", currentLocalPath)
|
|
|
|
if not ignoredFiles[filename] then
|
|
if fs.isDirectory(fileList[i]) then
|
|
archiveFileHandle:write(string.char(1))
|
|
writePath(archiveFileHandle, currentLocalPath)
|
|
|
|
local success, reason = encodingMethods[0].pack(archiveFileHandle, getFileList(fileList[i]), currentLocalPath)
|
|
if not success then
|
|
return success, reason
|
|
end
|
|
else
|
|
archiveFileHandle:write(string.char(0))
|
|
writePath(archiveFileHandle, currentLocalPath)
|
|
|
|
local fileHandle, reason = io.open(fileList[i], "rb")
|
|
if fileHandle then
|
|
-- Пишем размер файла
|
|
local fileSize = fs.size(fileList[i])
|
|
local fileSizeBytes = bit32.numberToByteArray(fileSize)
|
|
archiveFileHandle:write(string.char(#fileSizeBytes))
|
|
for i = 1, #fileSizeBytes do
|
|
archiveFileHandle:write(string.char(fileSizeBytes[i]))
|
|
end
|
|
|
|
-- Пишем содержимое
|
|
local data
|
|
while true do
|
|
data = fileHandle:read(readBufferSize)
|
|
if data then
|
|
archiveFileHandle:write(data)
|
|
else
|
|
break
|
|
end
|
|
end
|
|
|
|
fileHandle:close()
|
|
else
|
|
return false, "Failed to open file for reading: " .. tostring(reason)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
encodingMethods[0].unpack = function(archiveFileHandle, unpackPath)
|
|
while true do
|
|
local typeData = archiveFileHandle:read(1)
|
|
if typeData then
|
|
local type = string.byte(typeData)
|
|
local localPath = unpackPath .. readPath(archiveFileHandle)
|
|
-- print("Readed path:", localPath)
|
|
|
|
if type == 0 then
|
|
-- Читаем размер файлика
|
|
local sizeOfSizeArray = {}
|
|
for i = 1, string.byte(archiveFileHandle:read(1)) do
|
|
table.insert(sizeOfSizeArray, string.byte(archiveFileHandle:read(1)))
|
|
end
|
|
local fileSize = bit32.byteArrayToNumber(sizeOfSizeArray)
|
|
-- print("Readed file size:", fileSize)
|
|
|
|
-- Читаем и записываем содержимое файлика
|
|
local fileHandle, reason = io.open(localPath, "wb")
|
|
if fileHandle then
|
|
local readedCount, needToRead, data = 0
|
|
while readedCount < fileSize do
|
|
needToRead = math.min(readBufferSize, fileSize - readedCount)
|
|
fileHandle:write(archiveFileHandle:read(needToRead))
|
|
readedCount = readedCount + needToRead
|
|
end
|
|
|
|
fileHandle:close()
|
|
else
|
|
return false, "Failed to open file for writing: " .. tostring(reason)
|
|
end
|
|
else
|
|
fs.makeDirectory(localPath)
|
|
end
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
-----------------------------------------------------------------------------------------------
|
|
|
|
module.pack = function(archivePath, fileList, encodingMethod)
|
|
local archiveFileHandle, reason = io.open(archivePath, "wb")
|
|
if archiveFileHandle then
|
|
archiveFileHandle:write(OCAFSignature)
|
|
archiveFileHandle:write(string.char(encodingMethod))
|
|
|
|
if encodingMethods[encodingMethod] then
|
|
local success, reason = encodingMethods[encodingMethod].pack(archiveFileHandle, fileList)
|
|
archiveFileHandle:close()
|
|
|
|
return success, reason
|
|
else
|
|
archiveFileHandle:close()
|
|
|
|
return false, "Encoding method " .. tostring(encodingMethod) .. " doesn't supported"
|
|
end
|
|
else
|
|
return false, "Failed to open archive file for writing: " .. tostring(reason)
|
|
end
|
|
end
|
|
|
|
|
|
module.unpack = function(archivePath, unpackPath)
|
|
local archiveFileHandle, reason = io.open(archivePath, "rb")
|
|
if archiveFileHandle then
|
|
local readedSignature = archiveFileHandle:read(#OCAFSignature)
|
|
if readedSignature == OCAFSignature then
|
|
local readedEncodingMethod = string.byte(archiveFileHandle:read(1))
|
|
if encodingMethods[readedEncodingMethod] then
|
|
local success, reason = encodingMethods[readedEncodingMethod].unpack(archiveFileHandle, unpackPath)
|
|
archiveFileHandle:close()
|
|
|
|
return success, reason
|
|
else
|
|
archiveFileHandle:close()
|
|
|
|
return false, "Encoding method " .. tostring(encodingMethod) .. " doesn't supported"
|
|
end
|
|
else
|
|
archiveFileHandle:close()
|
|
|
|
return false, "Archive signature doesn't match OCAF"
|
|
end
|
|
else
|
|
return false, "Failed to open archive file for reading: " .. tostring(reason)
|
|
end
|
|
end
|
|
|
|
-----------------------------------------------------------------------------------------------
|
|
|
|
return module
|
|
|
|
|