Перейти к содержанию
Материалы раздела

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 данных)