Microtar
Модуль для работы с TAR архивами. Позволяет читать и создавать tar файлы как из файловой системы, так и в памяти.
Microtar полезен для:
- Упаковки нескольких файлов для передачи по сети
- Создания резервных копий конфигураций
- Распаковки обновлений прошивки
- Работы с архивами в памяти (без обращения к файловой системе)
microtar.open(filename, mode)
Открывает tar архив из файла.
Аргументы:
- filename: путь к tar файлу
- mode: режим открытия — “r” для чтения, “w” для записи (по умолчанию “r”)
Возвращает: объект archive или nil, error.
-- Открытие для чтения
local tar = microtar.open("/sd/backup.tar", "r")
-- Открытие для записи
local tar = microtar.open("/sd/archive.tar", "w")
microtar.memory([data])
Создает tar архив в памяти.
Аргументы:
- data (опционально): строка с tar данными для чтения. Если не указана — создаётся архив для записи.
Возвращает: объект memarchive.
-- Создание нового архива в памяти
local tar = microtar.memory()
-- Открытие существующего tar из строки
local tar_data = file:read("*a")
local tar = microtar.memory(tar_data)
Методы archive/memarchive (чтение)
archive:next()
Переходит к следующему файлу в архиве.
Возвращает: таблицу с информацией о файле; nil означает конец архива. При
повреждении архива возвращает nil, message, code, поэтому при ручном цикле
следует отличать обычный конец от ошибки.
local tar = microtar.open("/sd/backup.tar", "r")
while true do
local header, message, code = tar:next()
if not header then
assert(not message, string.format("tar error %s: %s", code, message))
break
end
print(header.name, header.size, header.type_name)
end
tar:close()
Поля header:
- name — имя файла
- size — размер в байтах
- mode — права доступа (octal)
- mtime — время модификации (Unix timestamp)
- type — тип записи (число)
- type_name — тип записи (“file”, “directory”, “symlink”, “hardlink”, “other”)
- linkname — имя ссылки (для symlink/hardlink)
archive:rewind()
Возвращается к началу архива.
Возвращает: true или nil, error.
tar:rewind()
archive:find(name)
Ищет файл в архиве по имени.
Аргументы:
- name: имя файла для поиска
Возвращает: таблица header или nil если не найден.
local header = tar:find("config.json")
if header then
local content = tar:read()
print(content)
end
archive:read([size])
Читает содержимое текущего файла.
Аргументы:
- size (опционально): количество байт для чтения. По умолчанию читает весь файл.
Возвращает: строка с данными.
local tar = microtar.open("/sd/backup.tar", "r")
local header = tar:find("readme.txt")
if header then
local content = tar:read()
print(content)
end
tar:close()
archive:files()
Возвращает итератор для перебора файлов в архиве. Итератор сначала проверяет
rewind(), а затем каждую запись. Любая ошибка перемотки или повреждение
архива вызывает Lua-исключение; только штатная нулевая запись завершает цикл.
local tar = microtar.open("/sd/backup.tar", "r")
for header in tar:files() do
print(header.name, header.size)
end
tar:close()
Методы archive/memarchive (запись)
archive:write_file(name, data)
Записывает файл в архив.
Аргументы:
- name: имя файла в архиве
- data: содержимое файла (строка)
Возвращает: true или nil, error.
local tar = microtar.open("/sd/backup.tar", "w")
tar:write_file("config.json", '{"key": "value"}')
tar:write_file("script.lua", 'print("Hello")')
tar:finalize()
tar:close()
archive:write_dir(name)
Создает директорию в архиве.
Аргументы:
- name: имя директории
Возвращает: true или nil, error.
tar:write_dir("configs/")
tar:write_file("configs/main.json", data)
archive:finalize()
Завершает запись архива. Обязательно вызвать перед закрытием.
Возвращает: true или nil, error.
tar:finalize()
tar:close()
memarchive:getdata()
Возвращает содержимое архива в памяти как строку (только для memarchive).
Возвращает: строка с tar данными.
local tar = microtar.memory()
tar:write_file("test.txt", "Hello, World!")
tar:finalize()
local data = tar:getdata()
tar:close()
-- data теперь содержит готовый tar архив
archive:close()
Закрывает архив и освобождает ресурсы.
tar:close()
Константы
- microtar.TREG — обычный файл (‘0’)
- microtar.TDIR — директория (‘5’)
- microtar.TLNK — жёсткая ссылка (‘1’)
- microtar.TSYM — символическая ссылка (‘2’)
Примеры
Создание архива с конфигурациями
local tar = microtar.open("/sd/configs.tar", "w")
-- Записываем файлы
tar:write_file("wifi.json", '{"ssid": "MyNetwork", "password": "secret"}')
tar:write_file("mqtt.json", '{"broker": "192.168.1.100", "port": 1883}')
tar:write_file("sensors.lua", 'return {temp=true, humidity=true}')
-- Завершаем и закрываем
tar:finalize()
tar:close()
print("Archive created")
Распаковка архива
local tar = microtar.open("/sd/configs.tar", "r")
for header in tar:files() do
if header.type_name == "file" then
local content = tar:read()
-- Сохраняем файл
local f = io.open("/sd/extracted/" .. header.name, "w")
f:write(content)
f:close()
print("Extracted: " .. header.name)
end
end
tar:close()
Работа с архивом в памяти
-- Создание архива в памяти
local tar = microtar.memory()
tar:write_file("data.txt", "Some data")
tar:write_file("info.json", '{"version": 1}')
tar:finalize()
-- Получаем tar как строку
local tar_data = tar:getdata()
tar:close()
-- Отправляем по сети
net.send(tar_data)
-- Или сохраняем в файл
local f = io.open("/sd/backup.tar", "w")
f:write(tar_data)
f:close()
Чтение архива из сети
-- Получаем tar данные из сети
local tar_data = net.receive()
-- Открываем из памяти
local tar = microtar.memory(tar_data)
-- Читаем содержимое
for header in tar:files() do
print(header.name, header.size)
if header.name == "config.json" then
local config = tar:read()
-- Обрабатываем конфиг
end
end
tar:close()
Поиск и извлечение конкретного файла
local tar = microtar.open("/sd/update.tar", "r")
-- Ищем файл прошивки
local header = tar:find("firmware.bin")
if header then
print("Found firmware, size: " .. header.size)
local firmware = tar:read()
-- Применяем обновление
ota.write(firmware)
else
print("Firmware not found in archive")
end
tar:close()
Создание резервной копии
local function backup_configs()
local tar = microtar.memory()
-- Список файлов для бэкапа
local files = {
"/sd/config.json",
"/sd/sensors.lua",
"/sd/network.cfg"
}
for _, path in ipairs(files) do
local f = io.open(path, "r")
if f then
local content = f:read("*a")
f:close()
-- Извлекаем имя файла из пути
local name = path:match("([^/]+)$")
tar:write_file(name, content)
end
end
tar:finalize()
local backup = tar:getdata()
tar:close()
return backup
end
-- Использование
local backup_data = backup_configs()
print("Backup size: " .. #backup_data .. " bytes")
Ограничения
- Максимальная длина имени файла: 100 символов
- Поддерживается только “old-style” tar формат (совместим с GNU tar)
- Не поддерживается сжатие (используйте heatshrink для сжатия tar данных)