update memory

Написал алгоритм сжатия совместимый с UTF-8. Не очень эффективный, экономит 10-15% на тексте.
Добавил генератор стартовой памяти, убран хардкод из MMC
This commit is contained in:
2026-06-14 04:13:57 +03:00
parent 7203572717
commit a67a8a40f3
4 changed files with 620 additions and 176 deletions

View File

@@ -9,6 +9,169 @@ local SEG_SIZE = 8192
local MAX_INODES = 64
local ROOT_INO = 1
local _unpack = table.unpack or unpack
-- === LZ4 compression (pure Lua) ===
function lz4Compress(data)
local n = #data
if n == 0 then return "" end
local ht, res, ip, anchor = {}, {}, 1, 1
local hashSize = 4096
local function hash4(p)
return (((data:byte(p) * 256 + data:byte(p + 1)) * 256 + data:byte(p + 2)) * 256 + data:byte(p + 3)) % hashSize
end
while ip + 3 <= n do
local h = hash4(ip)
local ref = ht[h]
ht[h] = ip
if ref and ip - ref <= 65535 and data:byte(ref) == data:byte(ip)
and data:byte(ref + 1) == data:byte(ip + 1)
and data:byte(ref + 2) == data:byte(ip + 2)
and data:byte(ref + 3) == data:byte(ip + 3) then
local ml = 4
while ip + ml <= n and data:byte(ref + ml) == data:byte(ip + ml) do ml = ml + 1 end
local litLen = ip - anchor
local matchLen = ml - 4
local tokLit = litLen < 15 and litLen or 15
local tokMatch = matchLen < 15 and matchLen or 15
res[#res + 1] = string.char(tokLit * 16 + tokMatch)
if litLen >= 15 then
local e = litLen - 15
while e >= 255 do res[#res + 1] = string.char(255); e = e - 255 end
res[#res + 1] = string.char(e)
end
if litLen > 0 then res[#res + 1] = data:sub(anchor, ip - 1) end
local off = ip - ref
res[#res + 1] = string.char(off % 256)
res[#res + 1] = string.char(math.floor(off / 256))
if matchLen >= 15 then
local e = matchLen - 15
while e >= 255 do res[#res + 1] = string.char(255); e = e - 255 end
res[#res + 1] = string.char(e)
end
ip = ip + ml
anchor = ip
else
ip = ip + 1
end
end
local last = n - anchor + 1
if last > 0 then
local tokLit = last < 15 and last or 15
res[#res + 1] = string.char(tokLit * 16)
if last >= 15 then
local e = last - 15
while e >= 255 do res[#res + 1] = string.char(255); e = e - 255 end
res[#res + 1] = string.char(e)
end
res[#res + 1] = data:sub(anchor, n)
end
return table.concat(res)
end
function lz4Decompress(compressed)
local pos, out, oi = 1, {}, 1
local n = #compressed
while pos <= n do
local token = compressed:byte(pos); pos = pos + 1
local litLen = math.floor(token / 16)
if litLen == 15 then
local s
repeat s = compressed:byte(pos); pos = pos + 1; litLen = litLen + s until s < 255
end
for _ = 1, litLen do out[oi] = compressed:byte(pos); oi = oi + 1; pos = pos + 1 end
if pos > n then break end
local off = compressed:byte(pos) + compressed:byte(pos + 1) * 256; pos = pos + 2
local matchLen = (token % 16) + 4
if matchLen == 19 then
local s
repeat s = compressed:byte(pos); pos = pos + 1; matchLen = matchLen + s until s < 255
end
local mp = oi - off
for _ = 1, matchLen do out[oi] = out[mp]; oi = oi + 1; mp = mp + 1 end
end
return string.char(_unpack(out))
end
local b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
local b64dec = {}
for i = 1, 64 do b64dec[b64:sub(i, i)] = i - 1 end
function encode(s)
local out, i, n = {}, 1, #s
while i <= n do
local a, b, c = s:byte(i), s:byte(i + 1), s:byte(i + 2)
out[#out + 1] = b64:sub(math.floor(a / 4) + 1, math.floor(a / 4) + 1)
out[#out + 1] = b64:sub((a % 4) * 16 + math.floor((b or 0) / 16) + 1, (a % 4) * 16 + math.floor((b or 0) / 16) + 1)
if i + 1 > n then
out[#out + 1] = "="
else
out[#out + 1] = b64:sub(((b or 0) % 16) * 4 + math.floor((c or 0) / 64) + 1, ((b or 0) % 16) * 4 + math.floor((c or 0) / 64) + 1)
end
if i + 2 > n then
out[#out + 1] = "="
else
out[#out + 1] = b64:sub(((c or 0) % 64) + 1, ((c or 0) % 64) + 1)
end
i = i + 3
end
return table.concat(out)
end
function decode(str)
local out, i, n = {}, 1, #str
while i <= n and str:sub(i, i) ~= "=" do
local a = b64dec[str:sub(i, i)] or 0
local b = b64dec[str:sub(i + 1, i + 1)] or 0
local c = b64dec[str:sub(i + 2, i + 2)] or 0
local d = b64dec[str:sub(i + 3, i + 3)] or 0
out[#out + 1] = string.char(a * 4 + math.floor(b / 16))
if str:sub(i + 2, i + 2) ~= "=" then
out[#out + 1] = string.char((b % 16) * 16 + math.floor(c / 4))
end
if str:sub(i + 3, i + 3) ~= "=" then
out[#out + 1] = string.char((c % 4) * 64 + d)
end
i = i + 4
end
return table.concat(out)
end
local function escRaw(s)
s = s:gsub("\x01", "\x01\x01")
s = s:gsub("\n", "\x01n")
return s
end
local function unescRaw(s)
local out, i, n = {}, 1, #s
while i <= n do
local b = s:byte(i)
if b == 1 then
i = i + 1
out[#out + 1] = s:byte(i) == 1 and "\x01" or "\n"
else
out[#out + 1] = s:sub(i, i)
end
i = i + 1
end
return table.concat(out)
end
function compressStr(s)
local lz = encode(lz4Compress(s))
if #lz < #s then return lz end
return "\x01" .. escRaw(s)
end
function decompressStr(c)
if c:byte(1) == 1 then return unescRaw(c:sub(2)) end
return lz4Decompress(decode(c))
end
-- ================================
local function parseMsg(msg)
local p = msg:find("|")
return p and msg:sub(1, p - 1) or msg, p and msg:sub(p + 1) or nil
@@ -29,7 +192,7 @@ local files = {}
local users = {}
local sb = { seg_size = SEG_SIZE, max_inodes = MAX_INODES, root_ino = ROOT_INO }
local function fsSerialize()
function fsSerialize()
local lines = {}
lines[#lines + 1] = "V|1"
lines[#lines + 1] = "S|" .. sb.seg_size .. "|" .. sb.max_inodes .. "|" .. sb.root_ino
@@ -47,7 +210,7 @@ local function fsSerialize()
end
lines[#lines + 1] = "D|" .. ino.ino .. "|" .. table.concat(entries, "|")
elseif ino.typ == "f" and files[ino.ino] then
lines[#lines + 1] = "F|" .. ino.ino .. "|" .. files[ino.ino]
lines[#lines + 1] = "Z|" .. ino.ino .. "|" .. files[ino.ino]
end
end
end
@@ -96,15 +259,15 @@ local function fsDeserialize(str)
end
dirs[ino] = entries
end
elseif typ == "F" then
elseif typ == "Z" then
local parts = split(rest, "|")
if #parts >= 2 then
local ino = tonumber(parts[1])
local content = parts[2] or ""
local b64 = parts[2] or ""
for i = 3, #parts do
content = content .. "|" .. parts[i]
b64 = b64 .. "|" .. parts[i]
end
files[ino] = content
files[ino] = b64
end
end
end
@@ -161,8 +324,8 @@ local function processReq(req)
local ino = findInodeByPath(path)
if not ino then return "ERR|" .. seqStr .. "ENOENT" end
if ino.typ ~= "f" then return "ERR|" .. seqStr .. "EISDIR" end
local content = files[ino.ino] or ""
local data = content:sub(offset + 1, offset + len)
local raw = decompressStr(files[ino.ino]) or ""
local data = raw:sub(offset + 1, offset + len)
return "OK|" .. seqStr .. data
elseif op == "LS" then
@@ -197,187 +360,110 @@ local function processReq(req)
return "ERR|" .. seqStr .. "EINVAL"
end
local function defaultFS()
-- Exported FS API for external tools (generators, tests)
FS = {}
function FS.init()
inodes = {}
dirs = {}
files = {}
users = {}
sb = { seg_size = SEG_SIZE, max_inodes = MAX_INODES, root_ino = ROOT_INO }
inodes[1] = { ino = 1, typ = "d", mode = "755", uid = 0, gid = 0, size = 0, mtime = 0 }
dirs[1] = { { name = ".", ino = 1 }, { name = "..", ino = 1 } }
end
users[0] = { uid = 0, name = "root", gid = 0, home = "/", hash = "-" }
users[100] = { uid = 100, name = "captain", gid = 10, home = "/home/captain", hash = "-" }
function FS.addUser(uid, name, gid, home, hash)
users[uid] = { uid = uid, name = name, gid = gid, home = home, hash = hash or "-" }
end
local function mkIno(num, typ, mode, uid, gid, size)
inodes[num] = { ino = num, typ = typ, mode = mode, uid = uid, gid = gid, size = size or 0, mtime = 0 }
function FS.resolve(path)
return findInodeByPath(path)
end
function FS.serialize()
return fsSerialize()
end
function FS.deserialize(str)
return fsDeserialize(str)
end
function FS.mkdir(path, mode, uid, gid)
local parentPath, name = path:match("^(.*)/([^/]+)$")
if not name then
parentPath, name = "/", path:match("^/?(.+)$") or path
end
local function mkDir(num, entries)
dirs[num] = entries
local parent = findInodeByPath(parentPath)
if not parent then return nil, "parent not found" end
if parent.typ ~= "d" then return nil, "not a directory" end
local ino
for i = 1, MAX_INODES do
if not inodes[i] then ino = i; break end
end
if not ino then return nil, "no free inodes" end
inodes[ino] = { ino = ino, typ = "d", mode = mode or "755", uid = uid or 0, gid = gid or 0, size = 0, mtime = 0 }
dirs[ino] = { { name = ".", ino = ino }, { name = "..", ino = parent.ino } }
table.insert(dirs[parent.ino], { name = name, ino = ino })
return ino
end
local function mkFile(num, content)
files[num] = content or ""
local sz = #(content or "")
if inodes[num] then inodes[num].size = sz end
function FS.mkfile(path, content, mode, uid, gid)
local parentPath, name = path:match("^(.*)/([^/]+)$")
if not name then
parentPath, name = "/", path:match("^/?(.+)$") or path
end
local parent = findInodeByPath(parentPath)
if not parent then return nil, "parent not found" end
if parent.typ ~= "d" then return nil, "not a directory" end
local ino
for i = 1, MAX_INODES do
if not inodes[i] then ino = i; break end
end
if not ino then return nil, "no free inodes" end
content = content or ""
inodes[ino] = { ino = ino, typ = "f", mode = mode or "644", uid = uid or 0, gid = gid or 0, size = #content, mtime = 0 }
files[ino] = compressStr(content)
table.insert(dirs[parent.ino], { name = name, ino = ino })
return ino
end
mkIno(1, "d", "755", 0, 0, 0)
mkDir(1, { { name = ".", ino = 1 }, { name = "..", ino = 1 }, { name = "home", ino = 2 }, { name = "etc", ino = 4 } })
function FS.write(path, content)
local ino = findInodeByPath(path)
if not ino then return nil, "not found" end
if ino.typ ~= "f" then return nil, "not a file" end
content = content or ""
files[ino.ino] = compressStr(content)
inodes[ino.ino].size = #content
return true
end
mkIno(2, "d", "755", 0, 0, 0)
mkDir(2, { { name = ".", ino = 2 }, { name = "..", ino = 1 }, { name = "captain", ino = 5 } })
function FS.read(path)
local ino = findInodeByPath(path)
if not ino then return nil, "not found" end
if ino.typ ~= "f" then return nil, "not a file" end
return decompressStr(files[ino.ino])
end
mkIno(5, "d", "700", 100, 10, 0)
mkDir(5, { { name = ".", ino = 5 }, { name = "..", ino = 2 }, { name = "readme.txt", ino = 3 } })
function FS.ls(path)
local ino = findInodeByPath(path or "/")
if not ino then return nil, "not found" end
if ino.typ ~= "d" then return nil, "not a directory" end
local result = {}
for _, e in ipairs(dirs[ino.ino]) do
result[#result + 1] = e.name
end
return result
end
mkIno(3, "f", "644", 100, 10, 0)
mkFile(3, "Welcome to AtlasOS v2.0!\n")
mkIno(4, "d", "755", 0, 0, 0)
mkDir(4, { { name = ".", ino = 4 }, { name = "..", ino = 1 }, { name = "man", ino = 6 } })
mkIno(6, "d", "755", 0, 0, 0)
mkDir(6, {
{ name = ".", ino = 6 }, { name = "..", ino = 4 },
{ name = "help", ino = 7 }, { name = "echo", ino = 8 },
{ name = "clear", ino = 9 }, { name = "color", ino = 10 },
{ name = "status", ino = 11 }, { name = "ls", ino = 12 },
{ name = "cat", ino = 13 }, { name = "cd", ino = 14 },
{ name = "stat", ino = 15 }, { name = "man", ino = 16 },
})
mkIno(7, "f", "644", 0, 0, 0)
mkFile(7, [[NAME
help - display help information
SYNOPSIS
help
DESCRIPTION
Show a list of all available commands with their usage
and description.
]])
mkIno(8, "f", "644", 0, 0, 0)
mkFile(8, [[NAME
echo - display a line of text
SYNOPSIS
echo <text>
DESCRIPTION
Write the given text to the terminal output.
]])
mkIno(9, "f", "644", 0, 0, 0)
mkFile(9, [[NAME
clear - clear the terminal screen
SYNOPSIS
clear
DESCRIPTION
Clear all text from the terminal display.
]])
mkIno(10, "f", "644", 0, 0, 0)
mkFile(10, [[NAME
color - set terminal text color
SYNOPSIS
color <R> <G> <B>
DESCRIPTION
Change the text color for subsequent output.
Each value must be 0-255 (red, green, blue).
]])
mkIno(11, "f", "644", 0, 0, 0)
mkFile(11, [[NAME
status - show system status
SYNOPSIS
status
DESCRIPTION
Display system information including current user,
working directory, and memory usage.
]])
mkIno(12, "f", "644", 0, 0, 0)
mkFile(12, [[NAME
ls - list directory contents
SYNOPSIS
ls [-la] [path]
DESCRIPTION
List contents of a directory. If no path is given,
list the current directory.
OPTIONS
-a Include hidden entries (. and ..)
-l Long format (detailed listing)
]])
mkIno(13, "f", "644", 0, 0, 0)
mkFile(13, [[NAME
cat - concatenate and display files
SYNOPSIS
cat <path>
DESCRIPTION
Read a file and display its contents on the terminal.
]])
mkIno(14, "f", "644", 0, 0, 0)
mkFile(14, [[NAME
cd - change the working directory
SYNOPSIS
cd [path]
DESCRIPTION
Change the current working directory. If no path
is given, go to root (/). Supports both absolute
and relative paths.
]])
mkIno(15, "f", "644", 0, 0, 0)
mkFile(15, [[NAME
stat - show file metadata
SYNOPSIS
stat <path>
DESCRIPTION
Display metadata for a file or directory, including
inode number, type, permissions, owner, group, size,
and modification time.
]])
mkIno(16, "f", "644", 0, 0, 0)
mkFile(16, [[NAME
man - display manual page
SYNOPSIS
man <command>
DESCRIPTION
Display the manual page for a command. Manual pages
are stored in /etc/man/.
EXAMPLE
man ls
man cat
SEE ALSO
help
]])
local str = fsSerialize()
out[5] = str
out[6] = 1
function FS.stat(path)
local ino = findInodeByPath(path)
if not ino then return nil, "not found" end
local result = {}
for k, v in pairs(ino) do
result[k] = v
end
return result
end
local fsLoaded = false
@@ -393,7 +479,8 @@ function upd()
fsLoaded = true
else
fsLoaded = true
defaultFS()
FS.init()
FS.addUser(0, "root", 0, "/", "-")
writePending = true
end
end

211
atlas_os/tools/example.txt Normal file
View File

@@ -0,0 +1,211 @@
Это читайте, мужик молодец
Добро пожаловать в официальный перевод полного руководства по Neurotrauma!
Если в данный момент вы находитесь в экстренной медицинской ситуации и рядом нет медицинских работников, немедленно перейдите в раздел первой помощи.
Если вы испытываете беспокойство или необычные симптомы, немедленно обратитесь к ближайшему медицинскому специалисту.
Помните! Всегда носите шлем!
Понимание того, как функционирует человеческий организм - или как в нем происходят сбои - может занять некоторое время.
Цель этого руководства - предоставить начинающим врачам важнейшую информацию, пока они не накопят достаточно опыта.
Врачи всегда должны иметь при себе медицинский сканер - вы не узнаете, что именно вызывает все симптомы у вашего пациента, пока не просканируете его (или не будете обладать обширными знаниями)!
Упаковываем аптечку первой помощи
Аптечка первой помощи для экспедиции
должна содержать следующее (более подходящие вещи находятся слева):
Эластичный бинт или обычный
Шовный материал
По крайне мере 1 жгут
Пакет с кровью (предпочтительно O-), Раствор Рингера, физраствор или адреналин
Каликсанид
Антипарализант
Рекомендуется также взять с собой в экспедицию следующее:
Полностью укомплектованный хирургический набор -> более подробно в 13: Хирургические процедуры и вы
Эндоваскулярный баллон
Медицинский стент
Гипс
Эти предметы могут спасти жизнь пациента при катастрофическом не перекрывающемся кровотечении из шеи или аорты, требующем немедленного хирургического вмешательства.
Аптечка первой помощи при несчастных случаях на подлодке
должна содержать следующее (более подходящие вещи находятся слева):
Эластичный бинт или обычный
Шовный материал
По крайне мере 1 жгут
Пакет с кровью (предпочтительно O-), Раствор Рингера, физраствор или адреналин
Дефибриллятор
Гипс
Мод Neurotrauma: 1:Оказание первой помощи
Непосредственные опасности
отсортированы от наиболее до наименее серьезных
Разрыв аорты
Оказание первой помощи
Лечение
Прогноз
Опиоид
Скальпель
Эндоваскулярный баллон
Медицинский стент
Шовный материал
Опиоид
Скальпель
Эндоваскулярный баллон
Медицинский стент
Шовный материал
Мрачный
Кровотечение из сонной артерии
Оказание первой помощи
Лечение
Прогноз
Операция
Операция
Мрачный
В огне
Оказание первой помощи
Лечение
Прогноз
Огнетушитель, вода или любой водолазный костюм
См. ожог
Зависит от того, как долго пациент горел
Артериальное кровотечение
Оказание первой помощи
Лечение
Прогноз
Жгут
Операция
Тревожный
Остановка сердца
Оказание первой помощи
Лечение
Прогноз
СЛР или дефибриллятор
СЛР или дефибриллятор
Данная болезнь является признаком чего-то худшего
Остановка дыхания
Оказание первой помощи
Лечение
Прогноз
СЛР
СЛР
Данная болезнь является признаком чего-то худшего
Припадок
Оказание первой помощи
Лечение
Прогноз
Удаление из небезопасной среды
Лечение первопричин
Данная болезнь является признаком чего-то худшего
Рвота кровью
Оказание первой помощи
Лечение
Прогноз
Внутривенные жидкости
Операция
Данная болезнь является признаком чего-то худшего
Переломы
Оказание первой помощи
Лечение
Прогноз
Бинт + гипс
Остеосинтетическая операция
Выживите
Ожоги
Оказание первой помощи
Лечение
Прогноз
Эластичный бинт или обычный
Эластичный бинт или обычный, антибиотическая мазь в тяжёлых случаях
Частый источник заражения
Раны (укусы, огнестрельные раны, рваные раны)
Оказание первой помощи
Лечение
Прогноз
Шовный материал
Шовный материал
Потенциальный источник заражения
Вывихи
Оказание первой помощи
Лечение
Прогноз
Эластичный бинт или обычный
Удары гаечным ключом (используйте в качестве лечения, как бинт)
(сначала нужно ввести опиаты)
Мучительная боль
Травма от удара тупым предметом
Оказание первой помощи
Лечение
Прогноз
Эластичный бинт или обычный
Операция с полустерильными плоскогубцами
Не проходит без первой помощи или лечения
После оказания себе первой помощи обратитесь к врачу, как только сможете
Мод Neurotrauma: 2:Симптомы и причины
В ПРОЦЕССЕ ДОРАБОТКИ!!!
В приведенной выше таблице вы можете найти симптом, который у вас может быть или вам интересно узнать, и посетить соответствующую главу данного руководства.
Мод Neurotrauma: 3: Мозг
Состояния и симптомы заболеваний головного мозга
отсортированы от наиболее до наименее тяжелых
Нейротравма
Первая помощь
Лечение
Прогноз
Вызвано
Вызывает
Отсутствует
Маннитол (требуется длительное время)
Главный антагонист. Вызвано низким притоком кислорода к мозгу. Непременная смерть при длительном кислородном голодании.
Гипоксемия, инсульт
Потеря сознания, остановка дыхания, смерть
Инсульт(в оф. переводе мода "удар")
Первая помощь
Лечение
Прогноз
Вызвано
Вызывает
Отсутствует
Операция
Инсульт следует лечить как можно скорее, чтобы свести к минимуму риск смерти.
Гипертония
Нейротравма, кома, судороги, боль, головная боль
Кома
Первая помощь
Лечение
Прогноз
Вызвано
Вызывает
Отсутствует
Авто пульс и много времени
Основные причины следует лечить как можно скорее, иначе пациент может впасть в стойкое вегетативное состояние.
Остановка сердца, инсульт, ацидоз
Остановка сердца, остановка дыхания, потеря сознания
Рвота кровью

View File

@@ -0,0 +1,140 @@
-- generate_init_fs.lua
-- Генерирует начальный образ SEG0 с man-страницами в /etc/man/
-- Использует экспортированное FS API из MMC.lua
-- Запуск: lua tools/generate_init_fs.lua > tools/init.amem
local base = arg and arg[0] and arg[0]:match("(.+)/") or "."
dofile(base .. "/../MMC.lua")
FS.init()
FS.addUser(0, "root", 0, "/", "-")
FS.addUser(100, "captain", 10, "/home/captain", "-")
FS.mkdir("/home", "755", 0, 0)
FS.mkdir("/home/captain", "700", 100, 10)
FS.mkfile("/home/captain/readme.txt", "Welcome to AtlasOS v2.0!\n", "644", 100, 10)
FS.mkdir("/etc", "755", 0, 0)
FS.mkdir("/etc/man", "755", 0, 0)
FS.mkfile("/etc/man/help", [[NAME
help - display help information
SYNOPSIS
help
DESCRIPTION
Show a list of all available commands with their usage
and description.
]], "644", 0, 0)
FS.mkfile("/etc/man/echo", [[NAME
echo - display a line of text
SYNOPSIS
echo <text>
DESCRIPTION
Write the given text to the terminal output.
]], "644", 0, 0)
FS.mkfile("/etc/man/clear", [[NAME
clear - clear the terminal screen
SYNOPSIS
clear
DESCRIPTION
Clear all text from the terminal display.
]], "644", 0, 0)
FS.mkfile("/etc/man/color", [[NAME
color - set terminal text color
SYNOPSIS
color <R> <G> <B>
DESCRIPTION
Change the text color for subsequent output.
Each value must be 0-255 (red, green, blue).
]], "644", 0, 0)
FS.mkfile("/etc/man/status", [[NAME
status - show system status
SYNOPSIS
status
DESCRIPTION
Display system information including current user,
working directory, and memory usage.
]], "644", 0, 0)
FS.mkfile("/etc/man/ls", [[NAME
ls - list directory contents
SYNOPSIS
ls [-la] [path]
DESCRIPTION
List contents of a directory. If no path is given,
list the current directory.
OPTIONS
-a Include hidden entries (. and ..)
-l Long format (detailed listing)
]], "644", 0, 0)
FS.mkfile("/etc/man/cat", [[NAME
cat - concatenate and display files
SYNOPSIS
cat <path>
DESCRIPTION
Read a file and display its contents on the terminal.
]], "644", 0, 0)
FS.mkfile("/etc/man/cd", [[NAME
cd - change the working directory
SYNOPSIS
cd [path]
DESCRIPTION
Change the current working directory. If no path
is given, go to root (/). Supports both absolute
and relative paths.
]], "644", 0, 0)
FS.mkfile("/etc/man/stat", [[NAME
stat - show file metadata
SYNOPSIS
stat <path>
DESCRIPTION
Display metadata for a file or directory, including
inode number, type, permissions, owner, group, size,
and modification time.
]], "644", 0, 0)
FS.mkfile("/etc/man/man", [[NAME
man - display manual page
SYNOPSIS
man <command>
DESCRIPTION
Display the manual page for a command. Manual pages
are stored in /etc/man/.
EXAMPLE
man ls
man cat
SEE ALSO
help
]], "644", 0, 0)
print(FS.serialize())

View File

@@ -0,0 +1,6 @@
#!/bin/bash
# make_init_memory.sh
# Генерирует стартовый образ памяти SEG0 и сохраняет в init.amem
lua generate_init_fs.lua > init.amem
echo "init.amem создан ($(wc -c < init.amem) байт)"