Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F160472025
D50833.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
31 KB
Referenced Files
None
Subscribers
None
D50833.diff
View Options
diff --git a/etc/mtree/BSD.usr.dist b/etc/mtree/BSD.usr.dist
--- a/etc/mtree/BSD.usr.dist
+++ b/etc/mtree/BSD.usr.dist
@@ -394,6 +394,8 @@
firmware
..
flua
+ mtree
+ ..
..
games
fortune
diff --git a/libexec/flua/share/Makefile b/libexec/flua/share/Makefile
new file mode 100644
--- /dev/null
+++ b/libexec/flua/share/Makefile
@@ -0,0 +1,8 @@
+
+BINDIR?= ${SHAREDIR}
+
+SUBDIR+= examples
+SUBDIR+= mtree
+
+.include "Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/libexec/flua/share/Makefile.inc b/libexec/flua/share/Makefile.inc
new file mode 100644
--- /dev/null
+++ b/libexec/flua/share/Makefile.inc
@@ -0,0 +1 @@
+SHAREDIR?= /usr/share/flua
diff --git a/libexec/flua/share/examples/METALOG b/libexec/flua/share/examples/METALOG
new file mode 100644
--- /dev/null
+++ b/libexec/flua/share/examples/METALOG
@@ -0,0 +1,74 @@
+#mtree 2.0
+. type=dir uname=root gname=wheel mode=0755
+./bin type=dir uname=root gname=wheel mode=0755
+./boot type=dir uname=root gname=wheel mode=0755
+./boot/defaults type=dir uname=root gname=wheel mode=0755
+./boot/dtb type=dir uname=root gname=wheel mode=0755
+./boot/dtb/allwinner type=dir uname=root gname=wheel mode=0755 tags=package=runtime
+./boot/dtb/overlays type=dir uname=root gname=wheel mode=0755 tags=package=runtime
+./boot/dtb/rockchip type=dir uname=root gname=wheel mode=0755 tags=package=runtime
+./boot/efi type=dir uname=root gname=wheel mode=0755
+./boot/firmware type=dir uname=root gname=wheel mode=0755
+./boot/fonts type=dir uname=root gname=wheel mode=0755
+./boot/images type=dir uname=root gname=wheel mode=0755
+./boot/kernel type=dir uname=root gname=wheel mode=0755
+./boot/loader.conf.d type=dir uname=root gname=wheel mode=0755 tags=package=bootloader
+./boot/lua type=dir uname=root gname=wheel mode=0755
+./boot/modules type=dir uname=root gname=wheel mode=0755
+./boot/uboot type=dir uname=root gname=wheel mode=0755
+./boot/zfs type=dir uname=root gname=wheel mode=0755
+./dev type=dir uname=root gname=wheel mode=0555
+./etc type=dir uname=root gname=wheel mode=0755
+./etc/X11 type=dir uname=root gname=wheel mode=0755
+./etc/authpf type=dir uname=root gname=wheel mode=0755
+./etc/autofs type=dir uname=root gname=wheel mode=0755
+./etc/bluetooth type=dir uname=root gname=wheel mode=0755
+./etc/cron.d type=dir uname=root gname=wheel mode=0755
+./etc/defaults type=dir uname=root gname=wheel mode=0755
+./etc/devd type=dir uname=root gname=wheel mode=0755
+./etc/dma type=dir uname=root gname=wheel mode=0755
+./etc/gss type=dir uname=root gname=wheel mode=0755
+./etc/jail.conf.d type=dir uname=root gname=wheel mode=0755
+./etc/kyua type=dir uname=root gname=wheel mode=0755 tags=package=tests
+./etc/mail type=dir uname=root gname=wheel mode=0755
+./etc/mtree type=dir uname=root gname=wheel mode=0755
+./etc/newsyslog.conf.d type=dir uname=root gname=wheel mode=0755
+./etc/ntp type=dir uname=root gname=wheel mode=0700
+./etc/pam.d type=dir uname=root gname=wheel mode=0755
+./etc/periodic type=dir uname=root gname=wheel mode=0755
+./etc/periodic/daily type=dir uname=root gname=wheel mode=0755
+./etc/periodic/monthly type=dir uname=root gname=wheel mode=0755
+./etc/periodic/security type=dir uname=root gname=wheel mode=0755
+./etc/periodic/weekly type=dir uname=root gname=wheel mode=0755
+./etc/pkg type=dir uname=root gname=wheel mode=0755
+./etc/ppp type=dir uname=root gname=wheel mode=0755
+./etc/profile.d type=dir uname=root gname=wheel mode=0755
+./etc/rc.conf.d type=dir uname=root gname=wheel mode=0755
+./etc/rc.d type=dir uname=root gname=wheel mode=0755
+./etc/security type=dir uname=root gname=wheel mode=0755
+./etc/ssh type=dir uname=root gname=wheel mode=0755
+./etc/ssl type=dir uname=root gname=wheel mode=0755
+./etc/ssl/certs type=dir uname=root gname=wheel mode=0755
+./etc/ssl/untrusted type=dir uname=root gname=wheel mode=0755
+./etc/sysctl.kld.d type=dir uname=root gname=wheel mode=0755
+./etc/syslog.d type=dir uname=root gname=wheel mode=0755
+./etc/zfs type=dir uname=root gname=wheel mode=0755
+./etc/zfs/compatibility.d type=dir uname=root gname=wheel mode=0755
+./etc/gss type=dir uname=root gname=wheel mode=0755 tags=package=utilities
+./etc/gss/mech type=file uname=root gname=wheel mode=0444 size=239 tags=package=utilities
+./etc/gss/qop type=file uname=root gname=wheel mode=0444 size=89 tags=package=utilities
+./etc/mtree type=dir uname=root gname=wheel mode=0755 tags=package=mtree
+./etc/mtree/BSD.debug.dist type=file uname=root gname=wheel mode=0444 size=1435 tags=package=mtree
+./etc/mtree/BSD.root.dist type=file uname=root gname=wheel mode=0444 size=2121 tags=package=mtree
+./etc/mtree/BSD.include.dist type=file uname=root gname=wheel mode=0444 size=5351 tags=package=mtree
+./etc/mtree/BSD.lib32.dist type=file uname=root gname=wheel mode=0444 size=377 tags=package=mtree
+./etc/mtree/BSD.tests.dist type=file uname=root gname=wheel mode=0444 size=24891 tags=package=mtree
+./etc/mtree/BSD.var.dist type=file uname=root gname=wheel mode=0444 size=2357 tags=package=mtree
+./etc/mtree/BSD.usr.dist type=file uname=root gname=wheel mode=0444 size=17353 tags=package=mtree
+./etc/termcap type=link uname=root gname=wheel mode=0755 link=/usr/share/misc/termcap tags=package=runtime
+./etc/rmt type=link uname=root gname=wheel mode=0755 link=../usr/sbin/rmt tags=package=utilities
+./etc/os-release type=link uname=root gname=wheel mode=0755 link=../var/run/os-release tags=package=runtime
+./etc/unbound type=link uname=root gname=wheel mode=0755 link=../var/unbound tags=package=unbound
+# If we're parsing correctly, this one should end up under the root and not
+# etc/mtree (last directory)
+libexec type=dir uname=root gname=wheel mode=0755
diff --git a/libexec/flua/share/examples/METALOG.dupes b/libexec/flua/share/examples/METALOG.dupes
new file mode 100644
--- /dev/null
+++ b/libexec/flua/share/examples/METALOG.dupes
@@ -0,0 +1,76 @@
+#mtree 2.0
+. type=dir uname=root gname=wheel mode=0755
+. type=dir uname=root gname=wheel mode=0755
+./bin type=dir uname=root gname=wheel mode=0755
+./boot type=dir uname=root gname=wheel mode=0755
+./boot/defaults type=dir uname=root gname=wheel mode=0755
+./boot/dtb type=dir uname=root gname=wheel mode=0755
+./boot/dtb/allwinner type=dir uname=root gname=wheel mode=0755 tags=package=runtime
+./boot/dtb/overlays type=dir uname=root gname=wheel mode=0755 tags=package=runtime
+./boot/dtb/rockchip type=dir uname=root gname=wheel mode=0755 tags=package=runtime
+./boot/efi type=dir uname=root gname=wheel mode=0755
+./boot/firmware type=dir uname=root gname=wheel mode=0755
+./boot/fonts type=dir uname=root gname=wheel mode=0755
+./boot/images type=dir uname=root gname=wheel mode=0755
+./boot/kernel type=dir uname=root gname=wheel mode=0755
+./boot/loader.conf.d type=dir uname=root gname=wheel mode=0755 tags=package=bootloader
+./boot/lua type=dir uname=root gname=wheel mode=0755
+./boot/modules type=dir uname=root gname=wheel mode=0755
+./boot/uboot type=dir uname=root gname=wheel mode=0755
+./boot/zfs type=dir uname=root gname=wheel mode=0755
+./dev type=dir uname=root gname=wheel mode=0555
+./etc type=dir uname=root gname=wheel mode=0755
+./etc/X11 type=dir uname=root gname=wheel mode=0755
+./etc/authpf type=dir uname=root gname=wheel mode=0755
+./etc/autofs type=dir uname=root gname=wheel mode=0755
+./etc/bluetooth type=dir uname=root gname=wheel mode=0755
+./etc/cron.d type=dir uname=root gname=wheel mode=0755
+./etc/defaults type=dir uname=root gname=wheel mode=0755
+./etc/devd type=dir uname=root gname=wheel mode=0755
+./etc/dma type=dir uname=root gname=wheel mode=0755
+./etc/gss type=dir uname=root gname=wheel mode=0755
+./etc/jail.conf.d type=dir uname=root gname=wheel mode=0755
+./etc/kyua type=dir uname=root gname=wheel mode=0755 tags=package=tests
+./etc/mail type=dir uname=root gname=wheel mode=0755
+./etc/mtree type=dir uname=root gname=wheel mode=0755
+./etc/newsyslog.conf.d type=dir uname=root gname=wheel mode=0755
+./etc/ntp type=dir uname=root gname=wheel mode=0700
+./etc/pam.d type=dir uname=root gname=wheel mode=0755
+./etc/periodic/daily type=dir uname=root gname=wheel mode=0755
+./etc/periodic/monthly type=dir uname=root gname=wheel mode=0755
+./etc/periodic/security type=dir uname=root gname=wheel mode=0755
+./etc/periodic/weekly type=dir uname=root gname=wheel mode=0755
+./etc/periodic type=dir uname=root gname=wheel mode=0755
+./etc/periodic/weekly type=file uname=root gname=wheel mode=0644
+./etc/pkg type=dir uname=root gname=wheel mode=0755
+./etc/ppp type=dir uname=root gname=wheel mode=0755
+./etc/profile.d type=dir uname=root gname=wheel mode=0755
+./etc/rc.conf.d type=dir uname=root gname=wheel mode=0755
+./etc/rc.d type=dir uname=root gname=wheel mode=0755
+./etc/security type=dir uname=root gname=wheel mode=0755
+./etc/ssh type=dir uname=root gname=wheel mode=0755
+./etc/ssl type=dir uname=root gname=wheel mode=0755
+./etc/ssl/certs type=dir uname=root gname=wheel mode=0755
+./etc/ssl/untrusted type=dir uname=root gname=wheel mode=0755
+./etc/sysctl.kld.d type=dir uname=root gname=wheel mode=0755
+./etc/syslog.d type=dir uname=root gname=wheel mode=0755
+./etc/zfs type=dir uname=root gname=wheel mode=0755
+./etc/zfs/compatibility.d type=dir uname=root gname=wheel mode=0755
+./etc/gss type=dir uname=root gname=wheel mode=0755 tags=package=utilities
+./etc/gss/mech type=file uname=root gname=wheel mode=0444 size=239 tags=package=utilities
+./etc/gss/qop type=file uname=root gname=wheel mode=0444 size=89 tags=package=utilities
+./etc/mtree type=dir uname=root gname=wheel mode=0755 tags=package=mtree
+./etc/mtree/BSD.debug.dist type=file uname=root gname=wheel mode=0444 size=1435 tags=package=mtree
+./etc/mtree/BSD.root.dist type=file uname=root gname=wheel mode=0444 size=2121 tags=package=mtree
+./etc/mtree/BSD.include.dist type=file uname=root gname=wheel mode=0444 size=5351 tags=package=mtree
+./etc/mtree/BSD.lib32.dist type=file uname=root gname=wheel mode=0444 size=377 tags=package=mtree
+./etc/mtree/BSD.tests.dist type=file uname=root gname=wheel mode=0444 size=24891 tags=package=mtree
+./etc/mtree/BSD.var.dist type=file uname=root gname=wheel mode=0444 size=2357 tags=package=mtree
+./etc/mtree/BSD.usr.dist type=file uname=root gname=wheel mode=0444 size=17353 tags=package=mtree
+./etc/termcap type=link uname=root gname=wheel mode=0755 link=/usr/share/misc/termcap tags=package=runtime
+./etc/rmt type=link uname=root gname=wheel mode=0755 link=../usr/sbin/rmt tags=package=utilities
+./etc/os-release type=link uname=root gname=wheel mode=0755 link=../var/run/os-release tags=package=runtime
+./etc/unbound type=link uname=root gname=wheel mode=0755 link=../var/unbound tags=package=unbound
+# If we're parsing correctly, this one should end up under the root and not
+# etc/mtree (last directory)
+libexec type=dir uname=root gname=wheel mode=0755
diff --git a/libexec/flua/share/examples/METALOG.relative b/libexec/flua/share/examples/METALOG.relative
new file mode 100644
--- /dev/null
+++ b/libexec/flua/share/examples/METALOG.relative
@@ -0,0 +1,138 @@
+#mtree 1.0
+. gname=wheel uname=root mode=0755 type=dir
+ bin gname=wheel mode=0755 uname=root type=dir
+ ..
+ boot gname=wheel mode=0755 uname=root type=dir
+ defaults gname=wheel mode=0755 uname=root type=dir
+ ..
+ dtb gname=wheel mode=0755 uname=root type=dir
+ allwinner gname=wheel uname=root tags=package=runtime mode=0755 type=dir
+ ..
+ overlays gname=wheel uname=root tags=package=runtime mode=0755 type=dir
+ ..
+ rockchip gname=wheel uname=root tags=package=runtime mode=0755 type=dir
+ ..
+ ..
+ efi gname=wheel mode=0755 uname=root type=dir
+ ..
+ firmware gname=wheel mode=0755 uname=root type=dir
+ ..
+ fonts gname=wheel mode=0755 uname=root type=dir
+ ..
+ images gname=wheel mode=0755 uname=root type=dir
+ ..
+ kernel gname=wheel mode=0755 uname=root type=dir
+ ..
+ loader.conf.d gname=wheel uname=root tags=package=bootloader mode=0755 type=dir
+ ..
+ lua gname=wheel mode=0755 uname=root type=dir
+ ..
+ modules gname=wheel mode=0755 uname=root type=dir
+ ..
+ uboot gname=wheel mode=0755 uname=root type=dir
+ ..
+ zfs gname=wheel mode=0755 uname=root type=dir
+ ..
+ ..
+ dev gname=wheel mode=0555 uname=root type=dir
+ ..
+ etc gname=wheel mode=0755 uname=root type=dir
+ X11 gname=wheel mode=0755 uname=root type=dir
+ ..
+ authpf gname=wheel mode=0755 uname=root type=dir
+ ..
+ autofs gname=wheel mode=0755 uname=root type=dir
+ ..
+ bluetooth gname=wheel mode=0755 uname=root type=dir
+ ..
+ cron.d gname=wheel mode=0755 uname=root type=dir
+ ..
+ defaults gname=wheel mode=0755 uname=root type=dir
+ ..
+ devd gname=wheel mode=0755 uname=root type=dir
+ ..
+ dma gname=wheel mode=0755 uname=root type=dir
+ ..
+ gss gname=wheel uname=root tags=package=utilities mode=0755 type=dir
+ mech gname=wheel uname=root size=239 tags=package=utilities mode=0444 type=file
+ ..
+ qop gname=wheel uname=root size=89 tags=package=utilities mode=0444 type=file
+ ..
+ ..
+ jail.conf.d gname=wheel mode=0755 uname=root type=dir
+ ..
+ kyua gname=wheel uname=root tags=package=tests mode=0755 type=dir
+ ..
+ mail gname=wheel mode=0755 uname=root type=dir
+ ..
+ mtree gname=wheel uname=root tags=package=mtree mode=0755 type=dir
+ BSD.debug.dist gname=wheel uname=root size=1435 tags=package=mtree mode=0444 type=file
+ ..
+ BSD.include.dist gname=wheel uname=root size=5351 tags=package=mtree mode=0444 type=file
+ ..
+ BSD.lib32.dist gname=wheel uname=root size=377 tags=package=mtree mode=0444 type=file
+ ..
+ BSD.root.dist gname=wheel uname=root size=2121 tags=package=mtree mode=0444 type=file
+ ..
+ BSD.tests.dist gname=wheel uname=root size=24891 tags=package=mtree mode=0444 type=file
+ ..
+ BSD.usr.dist gname=wheel uname=root size=17353 tags=package=mtree mode=0444 type=file
+ ..
+ BSD.var.dist gname=wheel uname=root size=2357 tags=package=mtree mode=0444 type=file
+ ..
+ ..
+ newsyslog.conf.d gname=wheel mode=0755 uname=root type=dir
+ ..
+ ntp gname=wheel mode=0700 uname=root type=dir
+ ..
+ os-release gname=wheel uname=root tags=package=runtime link=../var/run/os-release mode=0755 type=link
+ ..
+ pam.d gname=wheel mode=0755 uname=root type=dir
+ ..
+ periodic gname=wheel mode=0755 uname=root type=dir
+ daily gname=wheel mode=0755 uname=root type=dir
+ ..
+ monthly gname=wheel mode=0755 uname=root type=dir
+ ..
+ security gname=wheel mode=0755 uname=root type=dir
+ ..
+ weekly gname=wheel mode=0755 uname=root type=dir
+ ..
+ ..
+ pkg gname=wheel mode=0755 uname=root type=dir
+ ..
+ ppp gname=wheel mode=0755 uname=root type=dir
+ ..
+ profile.d gname=wheel mode=0755 uname=root type=dir
+ ..
+ rc.conf.d gname=wheel mode=0755 uname=root type=dir
+ ..
+ rc.d gname=wheel mode=0755 uname=root type=dir
+ ..
+ rmt gname=wheel uname=root tags=package=utilities link=../usr/sbin/rmt mode=0755 type=link
+ ..
+ security gname=wheel mode=0755 uname=root type=dir
+ ..
+ ssh gname=wheel mode=0755 uname=root type=dir
+ ..
+ ssl gname=wheel mode=0755 uname=root type=dir
+ certs gname=wheel mode=0755 uname=root type=dir
+ ..
+ untrusted gname=wheel mode=0755 uname=root type=dir
+ ..
+ ..
+ sysctl.kld.d gname=wheel mode=0755 uname=root type=dir
+ ..
+ syslog.d gname=wheel mode=0755 uname=root type=dir
+ ..
+ termcap gname=wheel uname=root tags=package=runtime link=/usr/share/misc/termcap mode=0755 type=link
+ ..
+ unbound gname=wheel uname=root tags=package=unbound link=../var/unbound mode=0755 type=link
+ ..
+ zfs gname=wheel mode=0755 uname=root type=dir
+ compatibility.d gname=wheel mode=0755 uname=root type=dir
+ ..
+ ..
+ ..
+..
+
diff --git a/libexec/flua/share/examples/Makefile b/libexec/flua/share/examples/Makefile
new file mode 100644
--- /dev/null
+++ b/libexec/flua/share/examples/Makefile
@@ -0,0 +1,10 @@
+
+PACKAGE?= examples
+BINDIR?= /usr/share/examples/flua
+
+FILES+= libjail.lua
+FILES+= mtree-read.lua
+FILES+= mtree-alter.lua
+FILES+= METALOG
+
+.include <bsd.prog.mk>
diff --git a/share/examples/flua/libjail.lua b/libexec/flua/share/examples/libjail.lua
rename from share/examples/flua/libjail.lua
rename to libexec/flua/share/examples/libjail.lua
diff --git a/libexec/flua/share/examples/mtree-alter.lua b/libexec/flua/share/examples/mtree-alter.lua
new file mode 100644
--- /dev/null
+++ b/libexec/flua/share/examples/mtree-alter.lua
@@ -0,0 +1,37 @@
+#!/usr/libexec/flua
+
+local mtree = require('mtree')
+
+local path = arg[0]
+-- Turn path into something useful for us
+local dirlen = #path - (string.find(path:reverse(), "/") or #path)
+path = path:sub(1, dirlen)
+if #path == 0 then
+ path = "."
+end
+
+local tree = assert(mtree.load(path .. "/METALOG"))
+
+-- waffles gets tagged as a dir automatically when we start adding entries
+-- beneath it. We set the mode to demonstrate that that type-setting doesn't
+-- override our dir mode with the auto-deduced mode.
+local leaf = tree:append("/etc/waffles")
+leaf:keyword("mode", "01777")
+leaf:keyword("tags", "package=breakfast")
+
+-- Adding new entries by absolute path may be the most convenient; append()
+-- will return the leaf node that we just added.
+leaf = tree:append("/etc/waffles/chocolate")
+leaf:keyword("type", "file")
+-- Note that any slash makes it an absolute path, so ./ is not from "pwd".
+leaf = tree:append("./etc/waffles/strawberry")
+leaf:keyword("type", "device")
+
+-- We can also chdir() to the path if we're going to be doing a lot of additions
+-- in a row to it.
+tree:chdir("/etc/waffles")
+leaf = tree:append("cherry")
+leaf:keyword("type", "link")
+leaf:keyword("link", "/nonexistent")
+
+print(tree:dump(true))
diff --git a/libexec/flua/share/examples/mtree-lint.lua b/libexec/flua/share/examples/mtree-lint.lua
new file mode 100644
--- /dev/null
+++ b/libexec/flua/share/examples/mtree-lint.lua
@@ -0,0 +1,23 @@
+#!/usr/libexec/flua
+
+local filename = arg[1]
+local mtree = require('mtree')
+
+if not filename then
+ io.stderr:write("usage: " .. arg[0] .. " [file]\n")
+ os.exit(1)
+end
+
+local function handle_dupe(dirent, props, line)
+ local dtype = dirent:keyword("type")
+
+ if props['type'] and props['type'] ~= dtype then
+ return nil, filename .. ":" .. line ..
+ " duplicate encountered of different type"
+ end
+
+ return true
+end
+
+local tree = assert(mtree.load(filename, { handle_dupe = handle_dupe }))
+print(tostring(tree))
diff --git a/libexec/flua/share/examples/mtree-read.lua b/libexec/flua/share/examples/mtree-read.lua
new file mode 100644
--- /dev/null
+++ b/libexec/flua/share/examples/mtree-read.lua
@@ -0,0 +1,12 @@
+#!/usr/libexec/flua
+
+local filename = arg[1]
+local mtree = require('mtree')
+
+if not filename then
+ io.stderr:write("usage: " .. arg[0] .. " [file]\n")
+ os.exit(1)
+end
+
+local tree = assert(mtree.load(filename))
+print(tree:dump(true))
diff --git a/libexec/flua/share/examples/mtree-walk.lua b/libexec/flua/share/examples/mtree-walk.lua
new file mode 100644
--- /dev/null
+++ b/libexec/flua/share/examples/mtree-walk.lua
@@ -0,0 +1,21 @@
+#!/usr/libexec/flua
+
+local filename = arg[1]
+local mtree = require('mtree')
+
+if not filename then
+ io.stderr:write("usage: " .. arg[0] .. " [file]\n")
+ os.exit(1)
+end
+
+local tree = assert(mtree.load(filename))
+local node = tree:get("/")
+
+-- Simple example of walking through the tree, starting at the root. Note that
+-- these clearly won't be sorted in any particular order.
+for name, topdir in pairs(node.children) do
+ print(name)
+ for sname, cdir in pairs(topdir.children) do
+ print(" " .. sname)
+ end
+end
diff --git a/libexec/flua/share/mtree/Makefile b/libexec/flua/share/mtree/Makefile
new file mode 100644
--- /dev/null
+++ b/libexec/flua/share/mtree/Makefile
@@ -0,0 +1,7 @@
+BINDIR?= ${SHAREDIR}/mtree
+
+FILES+= init.lua
+FILES+= parser.lua
+FILES+= tree.lua
+
+.include <bsd.prog.mk>
diff --git a/libexec/flua/share/mtree/init.lua b/libexec/flua/share/mtree/init.lua
new file mode 100644
--- /dev/null
+++ b/libexec/flua/share/mtree/init.lua
@@ -0,0 +1,23 @@
+--
+-- Copyright (c) 2025 Kyle Evans <kevans@FreeBSD.org>
+--
+-- SPDX-License-Identifier: BSD-2-Clause
+--
+
+local mtree = {}
+local parser = require('mtree.parser')
+
+-- Valid options:
+-- - handle_dupe(direntry, keywords, line)
+-- Return true to merge keywords in, false to discard, or nil and error
+mtree.parse = parser.parse
+function mtree.load(filename, options)
+ local file, err = io.open(filename, "r")
+ if not file then
+ return nil, err
+ end
+ local contents = file:read("a")
+ return mtree.parse(contents, options)
+end
+
+return mtree
diff --git a/libexec/flua/share/mtree/parser.lua b/libexec/flua/share/mtree/parser.lua
new file mode 100644
--- /dev/null
+++ b/libexec/flua/share/mtree/parser.lua
@@ -0,0 +1,161 @@
+--
+-- Copyright (c) 2025 Kyle Evans <kevans@FreeBSD.org>
+--
+-- SPDX-License-Identifier: BSD-2-Clause
+--
+
+local tree = require('mtree.tree')
+local parser = {}
+
+function parser.parse(mtree, options)
+ local count = 0
+ local defaults = {}
+ local parsed_tree = tree:new()
+ local handle_dupe = options and options.handle_dupe
+
+ -- Returns key, value pair
+ local function parse_keyword(keyword)
+ local key = keyword:match("^[^=]+")
+ local value = keyword:sub(#key + 2)
+
+ if not key then
+ return nil, "Malformed keyword: " .. keyword
+ end
+
+ return key, value
+ end
+
+ -- Processes an entry, returns the directory name part of it so that the
+ -- parent can chdir() into it.
+ local function process_entry(line)
+ local dir = line:match("[^%s]+")
+ local dirent, created = parsed_tree:append(dir)
+ local kwords_set = {}
+
+ if not dirent then
+ return nil, created
+ end
+
+ -- Every tree must have a root, so we'll almost certainly have
+ -- a dupe there and we should ignore it unless we see it
+ -- multiple times.
+ local duped = not created and
+ (dirent.parent ~= dirent or dirent.seen == 1)
+
+ dirent.seen = dirent.seen + 1
+ line = line:sub(#dir + 1)
+
+ for kword in line:gmatch("[^%s]+") do
+ local k, v = parse_keyword(kword)
+ if not k then
+ return nil, v
+ end
+
+ kwords_set[k] = v
+ end
+
+ for k, v in pairs(defaults) do
+ if not kwords_set[k] then
+ kwords_set[k] = v
+ end
+ end
+
+ if duped and handle_dupe then
+ local merge, err = handle_dupe(dirent, kwords_set, count)
+
+ if merge == nil then
+ return nil, err
+ end
+
+ if not merge then
+ kwords_set = {}
+ end
+ end
+
+ for k, v in pairs(kwords_set) do
+ dirent:keyword(k, v)
+ end
+
+ if dirent:keyword("type") ~= "dir" then
+ -- Non-dir entries do not change the current directory.
+ return nil
+ elseif dir:match("/") then
+ -- Absolute paths do not change the current directory.
+ return nil
+ end
+
+ return dir
+ end
+
+ for line in mtree:gmatch("[^\n]+") do
+ local dir, err, indent, ok
+
+ count = count + 1
+
+ -- First line may be a version spec.
+ if count == 1 and line:match("^#mtree") then
+ tree:version(line:match("mtree v([%d]+%.[%d]+)"))
+ goto next
+ end
+
+ -- Strip off any comments and any leading whitespace. Internal
+ -- whitespace is significant, so we'll leave that alone.
+ line = line:match("^[^#]+") or ""
+ indent = line:match("^[%s]+") or ""
+ line = line:sub(#indent + 1)
+
+ -- Ignore empty lines
+ if #line == 0 then
+ goto next
+ end
+
+ if line:match("^/set") or line:match("^/unset") then
+ local command = line:match("^/u?n?set")
+ local is_set = command == "/set"
+
+ line = line:sub(#command + 1)
+
+ for kword in line:gmatch("[^%s]+") do
+ if not is_set then
+ if kword:match("=") then
+ return nil, "Malformed /unset"
+ end
+
+ defaults[kword] = nil
+ else
+ local k, v = parse_keyword(kword, true)
+ if not k then
+ return nil, v
+ end
+
+ defaults[k] = v
+ end
+ end
+
+ goto next
+ elseif line:match("^/") then
+ return nil, "Unrecognized command: " .. line
+ end
+
+ dir = line
+ if line ~= ".." then
+ dir, err = process_entry(line)
+ if not dir and err then
+ return nil, err
+ end
+ end
+
+ if dir then
+ ok, err = parsed_tree:chdir(dir)
+ if not ok then
+ return nil, err
+ end
+ end
+
+ ::next::
+ end
+
+ return parsed_tree
+end
+
+return parser
diff --git a/libexec/flua/share/mtree/tree.lua b/libexec/flua/share/mtree/tree.lua
new file mode 100644
--- /dev/null
+++ b/libexec/flua/share/mtree/tree.lua
@@ -0,0 +1,293 @@
+--
+-- Copyright (c) 2025 Kyle Evans <kevans@FreeBSD.org>
+--
+-- SPDX-License-Identifier: BSD-2-Clause
+--
+
+local inherited = {
+ -- Almost certainly we want the same ownership as the parent,
+ -- the caller can override that.
+ "uname", "gname", "uid", "gid",
+
+ -- We use tags mostly for the package, but also to signify
+ -- config files. If we're a leaf entry, the parent should only
+ -- really have package tags if anything, and it doesn't hurt to
+ -- inherit those.
+ "tags",
+}
+
+local function encoded_name(name)
+ local function needescape(c)
+ -- Printable ASCII do not need escaping, with exception to a
+ -- backslash.
+ return not (c ~= 0x5c and c >= 0x20 and c < 0x7f)
+ end
+
+ local encoded = ""
+ for i = 1, #name do
+ local c = name:byte(i)
+
+ if not needescape(c) then
+ encoded = encoded .. string.char(c)
+ else
+ encoded = encoded .. string.format("\\%.3o", c)
+ end
+ end
+
+ return encoded
+end
+local function dirent_name(name)
+ for oct in name:gmatch("\\[0-7][0-7][0-7]") do
+ local rep = tonumber(oct:sub(2), 8)
+
+ name = name:gsub(oct, string.char(rep))
+ end
+
+ return name
+end
+
+local dirent = {}
+-- XXX Note that new dirents inherit the parent uname/gname/tags by default.
+function dirent:new(tree, parent, name)
+ local obj = setmetatable({}, self)
+ self.__index = self
+
+ if name:match("/") then
+ return nil, "Illegal filename: " .. name
+ end
+ obj.name = dirent_name(name)
+ obj.mtree_name = encoded_name(obj.name)
+ obj.parent = parent
+ obj.tree = tree
+ obj.seen = 0
+ obj.children = {}
+ obj._keywords = {}
+
+ if parent then
+ for _, kword in ipairs(inherited) do
+ obj:keyword(kword, parent:keyword(kword))
+ end
+
+ local ptype = parent:keyword("type")
+ if not ptype then
+ parent:keyword("type", "dir")
+ elseif ptype ~= "dir" then
+ return nil, "Entry added to non-directory type"
+ end
+ end
+
+ return obj
+end
+function dirent:add(de)
+ self.children[de.name] = de
+end
+function dirent:child(path)
+ return self.children[path]
+end
+function dirent:keyword(key, ...)
+ local args = { ... }
+
+ -- A bit of a hack: dirent:keyword("foo") should return the value of
+ -- foo, but dirent:keyword("foo", nil) should unset it.
+ if #args == 0 then
+ return self._keywords[key]
+ end
+
+ local value = args[1]
+ self._keywords[key] = value
+
+ -- Set a mode if they're setting a type, but let's not override an
+ -- existing mode. These are just reasonable defaults.
+ if key == "type" and not self._keywords["mode"] then
+ if value == "dir" then
+ self._keywords["mode"] = "0755"
+ else
+ self._keywords["mode"] = "0644"
+ end
+ end
+ return true
+end
+function dirent:dump(absolute_path, pretty)
+ local strv = self.mtree_name
+
+ if absolute_path and self.parent ~= self then
+ local parent = self
+ local cmp
+
+ repeat
+ parent = parent.parent
+ cmp = parent.mtree_name
+ strv = cmp .. "/" .. strv
+ until cmp == "."
+ end
+ if self._keywords then
+ local count = 0
+ local pathsep = " "
+ local kwdelim = (pretty and ", ") or " "
+
+ if not absolute_path then
+ pathsep = string.rep(" ", 8)
+ end
+ for k, v in pairs(self._keywords) do
+ if count == 0 then
+ if not pretty then
+ strv = strv .. pathsep
+ else
+ strv = strv .. "["
+ end
+ else
+ strv = strv .. kwdelim
+ end
+
+ strv = strv .. k .. "=" .. v
+ count = count + 1
+ end
+
+ if count > 0 and pretty then
+ strv = strv .. "]"
+ end
+ end
+
+ return strv
+end
+function dirent:__tostring()
+ return self:dump(false, true)
+end
+
+local tree = {}
+function tree:new()
+ local obj = setmetatable({}, self)
+ self.__index = self
+
+ local root = assert(dirent:new(obj, nil, "."))
+ root.parent = root
+
+ obj._version = nil
+ obj.root = root
+ obj.pwd = root
+
+ return obj
+end
+local function traverse(self, path, create_missing)
+ local last_created
+ local is_abs = path:match("/")
+ local pwd = (is_abs and self.root) or self.pwd
+
+ for cmp in path:gmatch("[^/]+") do
+ local next
+
+ if cmp == ".." then
+ next = pwd.parent
+ elseif cmp == "." then
+ -- If this is the leading component of an absolute path,
+ -- this just means the root since pwd isn't set to
+ -- self.pwd if a / appears in the path.
+ next = pwd
+ else
+ next = pwd:child(cmp)
+ end
+
+ -- Just construct the missing entry
+ if not next and create_missing then
+ local de, err = dirent:new(self, pwd, cmp)
+
+ if not de then
+ return nil, err
+ end
+
+ -- We now know that the last dirent we created was not
+ -- a leaf, so we can assume it's a directory and set the
+ -- type appropriately.
+ if last_created then
+ local type = last_created:keyword("type")
+ if not type then
+ last_created:keyword("type", "dir")
+ elseif type ~= "dir" then
+ return nil, "Child added to non-dir entry"
+ end
+ end
+
+ pwd:add(de)
+ last_created = de
+ next = de
+ elseif not next then
+ return nil, "Missing component"
+ end
+
+ pwd = next
+ end
+
+ return pwd, not (not last_created)
+end
+
+function tree:append(path)
+ return traverse(self, path, true)
+end
+function tree:chdir(path)
+ local new_pwd, err = traverse(self, path)
+ if not new_pwd then
+ return nil, err
+ end
+
+ self.pwd = new_pwd
+ return true
+end
+function tree:get(path)
+ local getdir, err = traverse(self, path)
+ if not getdir then
+ return nil, err
+ end
+ return getdir
+end
+function tree:version(newvers)
+ if newvers then
+ self._version = newvers
+ end
+
+ return self._version or "2.0"
+end
+function tree:dump(pretty)
+ local pwd = self.root
+ local version = self:version()
+ local strv
+
+ if not pretty then
+ strv = "#mtree " .. version .. "\n"
+ else
+ strv = ""
+ end
+
+ local major_version = tonumber(version:match("^([0-9]+)"))
+ local absolute_path = not pretty and major_version >= 2
+ local function walk(node, indentlvl)
+ local sorted = {}
+ local indentation = ""
+
+ if not absolute_path then
+ indentation = string.rep("\t", indentlvl)
+ end
+
+ for name in pairs(node.children) do
+ sorted[#sorted + 1] = name
+ end
+
+ table.sort(sorted)
+ strv = strv .. indentation ..
+ node:dump(absolute_path, pretty) .. "\n"
+ for _, name in ipairs(sorted) do
+ local de = node.children[name]
+ walk(de, indentlvl + 1)
+ end
+ if not pretty and not absolute_path then
+ strv = strv .. indentation .. "..\n"
+ end
+ end
+
+ walk(pwd, 0)
+ return strv
+end
+function tree:__tostring()
+ return self:dump(false)
+end
+
+return tree
diff --git a/share/examples/Makefile b/share/examples/Makefile
--- a/share/examples/Makefile
+++ b/share/examples/Makefile
@@ -12,7 +12,6 @@
csh \
etc \
find_interface \
- flua \
indent \
inotify \
ipfw \
@@ -85,9 +84,6 @@
README \
find_interface.c
-SE_DIRS+= flua
-SE_FLUA= libjail.lua
-
SE_DIRS+= indent
SE_INDENT= indent.pro
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jun 25, 8:48 PM (9 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34329407
Default Alt Text
D50833.diff (31 KB)
Attached To
Mode
D50833: Initial version of an mtree module
Attached
Detach File
Event Timeline
Log In to Comment