summarylogtreecommitdiffstats
diff options
context:
space:
mode:
author999cgm2019-03-25 16:38:33 +0200
committer999cgm2019-03-25 16:38:33 +0200
commit6804320aff88a808a5b01c3ad48902f3665446d2 (patch)
tree45c63dbbf7e41e516f0bc0ec44ba52fc8b889e27
parent8358dc165a3f329968b88fef1c29ebf3d1e51b87 (diff)
downloadaur-6804320aff88a808a5b01c3ad48902f3665446d2.tar.gz
ver 0.8
-rw-r--r--.SRCINFO8
-rw-r--r--PKGBUILD6
-rwxr-xr-xcheck-pacman-mtree-0.8.lua357
3 files changed, 364 insertions, 7 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 5ea238b168e6..79e704d3717a 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,15 +1,15 @@
pkgbase = check-pacman-mtree
pkgdesc = pacman db mtree check size/md5/sha256/symlink
- pkgver = 0.7
- pkgrel = 2
+ pkgver = 0.8
+ pkgrel = 1
url = http://luajit.org/luajit.html
arch = any
license = GPL2
depends = luajit
depends = openssl
depends = zlib
- source = check-pacman-mtree-0.7.lua
- sha1sums = 0610fed2efe80a86bb558f9e8a416541f146d604
+ source = check-pacman-mtree-0.8.lua
+ sha512sums = bb385bec9c3f3d122446a256a893161722eba550877c9720f48f32862f55105f3374f2e57c30b2c3359cf00e33a348605ac646bf5a140d39631e6b93b1eab00b
pkgname = check-pacman-mtree
diff --git a/PKGBUILD b/PKGBUILD
index 3b2b9b5bbe90..d4ad7a19cb3f 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -2,15 +2,15 @@
# Maintainer: https://aur.archlinux.org/account/999cgm
pkgname=check-pacman-mtree
-pkgver=0.7
-pkgrel=2
+pkgver=0.8
+pkgrel=1
pkgdesc='pacman db mtree check size/md5/sha256/symlink'
license=('GPL2')
arch=('any')
url="http://luajit.org/luajit.html"
depends=( 'luajit' 'openssl' 'zlib' )
source=("${pkgname}-${pkgver}.lua")
-sha1sums=('0610fed2efe80a86bb558f9e8a416541f146d604')
+sha512sums=('bb385bec9c3f3d122446a256a893161722eba550877c9720f48f32862f55105f3374f2e57c30b2c3359cf00e33a348605ac646bf5a140d39631e6b93b1eab00b')
package() {
install -D -m755 "${srcdir}/${pkgname}-${pkgver}.lua" "${pkgdir}/usr/bin/${pkgname}.lua"
diff --git a/check-pacman-mtree-0.8.lua b/check-pacman-mtree-0.8.lua
new file mode 100755
index 000000000000..2b234e27fd01
--- /dev/null
+++ b/check-pacman-mtree-0.8.lua
@@ -0,0 +1,357 @@
+#!/usr/bin/luajit
+
+-- version 0.7
+-- https://aur.archlinux.org/packages/check-pacman-mtree/
+
+--require "strict"
+
+local ffi = require "ffi"
+
+local C = ffi.C
+local libcrypto = ffi.load("crypto")
+local libz = ffi.load("z")
+
+local function hex_from_ffi_str(s,n)
+ return string.format(string.rep('%02x',n), string.byte(ffi.string(s,n),1,n))
+end
+
+local function C_error(str)
+ return string.format(str .. ': %s', ffi.string(C.strerror(ffi.errno())))
+end
+
+
+ffi.cdef[[
+ static const int LINE_SIZE = 1024;
+ static const int BUFFER_SIZE = 32768;
+
+ //libc start
+ static const int O_RDONLY = 0;
+ static const int SEEK_SET = 0;
+ static const int SEEK_END = 2;
+ static const int ENOENT = 2;
+ char *strerror(int);
+ int open (const char *, int, ...);
+ int read(int , void *, int);
+ int close(int);
+ int lseek(int , int , int );
+ int readlink(const char *, char *,int);
+
+ //libc stop
+
+ //openssl start
+ static const int EVP_MAX_MD_SIZE = 64;
+ void *EVP_md5(void);
+ void *EVP_sha256(void);
+ void *EVP_MD_CTX_new(void);
+ int EVP_DigestInit(void *, void *);
+ int EVP_DigestUpdate(void *,const void *,int);
+ int EVP_DigestFinal_ex(void *,unsigned char *,unsigned int *);
+ void EVP_MD_CTX_free(void *);
+ //openssl stop
+
+ //zlib start
+ void * gzopen (const char *, const char *);
+ int gzclose (void * );
+ char * gzgets (void * , char *, int );
+ //zlib stop
+]]
+
+local function printf_(...)
+ return io.write(string.format(...),"\n")
+end
+
+-- if size matches we will not do md5/sha256
+-- set size to -1 to force MD
+local function get_size_md5_sha256(file,size)
+
+ local fh,mdctx_md5,mdctx_sha256
+ local fs_size,ret_2,ret_3
+
+ do
+
+ fh = C.open(file,C.O_RDONLY)
+ if fh == -1 then return nil,C_error("open " .. file),ffi.errno() end
+
+ fs_size = C.lseek(fh,0,C.SEEK_END)
+
+ if size ~= -1 and fs_size ~= size then goto clean_up_short end
+ --goto clean_up_short
+
+
+ C.lseek(fh,0,C.SEEK_SET)
+
+ mdctx_md5 = libcrypto.EVP_MD_CTX_new()
+ mdctx_sha256 = libcrypto.EVP_MD_CTX_new()
+
+ if mdctx_md5 == nil or mdctx_sha256 == nil then
+ ret_2 = "libcrypto.EVP_MD_CTX_new md5/sha256 failed " .. file
+ goto clean_up
+ end
+
+ local md_value_md5 = ffi.new("char[?]",C.EVP_MAX_MD_SIZE)
+ local md_value_sha256 = ffi.new("char[?]",C.EVP_MAX_MD_SIZE)
+
+ local md_len_md5 = ffi.new("int[1]")
+ local md_len_sha256 = ffi.new("int[1]")
+
+ local buffer = ffi.new("char[?]",C.BUFFER_SIZE)
+
+ if md_value_md5 == nil or md_value_sha256 == nil or md_len_md5 == nil or
+ md_len_sha256 == nil or buffer == nil then
+ ret_2 = "ffi.new failed " ..file
+ goto clean_up
+ end
+
+ if libcrypto.EVP_DigestInit(mdctx_md5, libcrypto.EVP_md5()) ~= 1 or
+ libcrypto.EVP_DigestInit(mdctx_sha256, libcrypto.EVP_sha256()) ~= 1 then
+ ret_2 = "libcrypto.EVP_DigestInit md5/sha256 failed " .. file
+ goto clean_up
+ end
+
+ while (1) do
+ local n = C.read(fh,buffer, C.BUFFER_SIZE)
+ --we should make something better for read ret < 0
+ if n <= 0 then break end
+ if libcrypto.EVP_DigestUpdate(mdctx_md5,buffer,n) ~= 1 or
+ libcrypto.EVP_DigestUpdate(mdctx_sha256,buffer,n) ~= 1 then
+ ret_2 = "libcrypto.EVP_DigestUpdate md5/sha256 failed " .. file
+ goto clean_up
+ end
+ end
+
+ if libcrypto.EVP_DigestFinal_ex(mdctx_md5, md_value_md5, md_len_md5) ~= 1 or
+ libcrypto.EVP_DigestFinal_ex(mdctx_sha256, md_value_sha256, md_len_sha256) ~= 1 then
+ ret_2 = "libcrypto.EVP_DigestFinal_ex md5/sha256 failed " .. file
+ goto clean_up
+ end
+
+ ret_2,ret_3 = hex_from_ffi_str(md_value_md5,md_len_md5[0]),hex_from_ffi_str(md_value_sha256,md_len_sha256[0])
+
+ end
+
+ ::clean_up::
+ if mdctx_md5 ~= nil then libcrypto.EVP_MD_CTX_free(mdctx_md5) end
+ if mdctx_sha256 ~= nil then libcrypto.EVP_MD_CTX_free(mdctx_sha256) end
+
+ ::clean_up_short::
+ if fh >= 0 then C.close(fh) end
+
+ return fs_size,ret_2,ret_3
+
+end
+
+local function get_symlink(file)
+ local line = ffi.new("char[?]",C.LINE_SIZE)
+ if line == nil then return nil,"ffi.new failed " ..file end
+ local size = C.readlink(file,line,C.LINE_SIZE-1)
+
+ if size == -1 then return nil,C_error("readlink " .. file),ffi.errno() end
+
+ return ffi.string(line,size)
+end
+
+local function check_1_mtree_file(pkg,fs_root,verbose,file)
+ local line = ffi.new("char[?]",C.LINE_SIZE)
+ if line == nil then return nil,"ffi.new failed " ..file end
+
+ local gz_fh = libz.gzopen(file,"r")
+ if gz_fh == nil then return nil,C_error("gzopen " .. file) end
+ --libz.gzbuffer(gz_fh,65536)
+
+ local file,root_file,size,md5,sha256
+ local fs_size,symlink_linkto,link_fs
+ local status,msg,aaa,bbb
+ local l_line
+ while(1) do
+ if libz.gzgets(gz_fh,line,C.LINE_SIZE) == nil then break end
+
+ l_line = ffi.string(line)
+ file,size,md5,sha256 = string.match(l_line, "^(%S+) .* size=(%S+) md5digest=(%S+) sha256digest=(%S+)")
+ if file and size and md5 and sha256 then
+ if size then size=tonumber(size) end
+ else
+ file,symlink_linkto = string.match(l_line,"^(%S+) .* type=link link=(.*)%s$")
+ if file and symlink_linkto then
+ --printf_("symlink_name=%s symlink_linkto=%s",file,symlink_linkto)
+ symlink_linkto = string.gsub(symlink_linkto,"\\%d%d%d",
+ function(str) return string.char(tonumber(string.sub(str,2,-1),8)) end
+ )
+ else goto continue
+ end
+ end
+
+ --print (file,size,md5,sha256)
+ file = string.gsub(file,"^%./","",1)
+ if file == '.PKGINFO' or file == '.INSTALL' or file == '.CHANGELOG' then
+ goto continue
+ end
+ if file == '.BUILDINFO' then
+ goto continue
+ end
+
+ file = string.gsub(file,"\\%d%d%d",
+ function(str) return string.char(tonumber(string.sub(str,2,-1),8)) end
+ )
+ --print (file,size,md5,sha256)
+ root_file = fs_root .. file
+
+ if not size then
+ --goto continue
+ -- we are here so this is not a file, so maybe symlink or other type
+ link_fs,aaa,bbb = get_symlink(root_file)
+ -- status is nil so in aaa we have str_err and in bbb we have C.errno
+ if link_fs == nil then
+ if(bbb == C.ENOENT) then
+ --if(string.match(msg,"No such file")) then
+ if verbose > 0 then
+ printf_("EXTRA_MTREE pkg=%s symlink=%s link=%s",pkg,file,symlink_linkto)
+ else
+ printf_("EXTRA_MTREE pkg=%s symlink=%s",pkg,file)
+ end
+ else
+ printf_("FAIL check_symlink %s",aaa)
+ end
+ else
+ if link_fs ~= symlink_linkto then
+ if verbose > 0 then
+ printf_("DIFF pkg=%s symlink=%s link_mtree=%s link_fs=%s",pkg,file,symlink_linkto,link_fs)
+ else
+ printf_("DIFF pkg=%s symlink=%s",pkg,file)
+ end
+ end
+ end
+
+ goto continue
+ end
+
+ -- here we are in type=file case
+
+ -- goto continue
+
+ if verbose > 0 then fs_size,aaa,bbb = get_size_md5_sha256(root_file,-1)
+ else fs_size,aaa,bbb = get_size_md5_sha256(root_file,size)
+ end
+
+ if not fs_size then
+ -- fs_size is nil so in aaa we have str_err and in bbb we have C.errno
+ if(bbb == C.ENOENT) then
+ --if(string.match(msg,"No such file")) then
+ if verbose > 0 then
+ printf_("EXTRA_MTREE pkg=%s file=%s size_mtree=%s md5_mtree=%s sha256_mtree=%s",pkg,file,size,md5,sha256)
+ else
+ printf_("EXTRA_MTREE pkg=%s file=%s",pkg,file)
+ end
+ else
+ printf_("FAIL get_size_md5_sha256 %s",aaa)
+ end
+ goto continue
+ end
+
+ --print(file,type(size),size,type(fs_size),fs_size,aaa,bbb)
+ if fs_size ~= size or aaa ~= md5 or bbb ~= sha256 then
+ if verbose > 0 then
+ printf_("DIFF pkg=%s file=%s size_mtree=%d size_fs=%d md5_mtree=%s md5_fs=%s sha256_mtree=%s sha256_fs=%s",pkg,file,size,fs_size,md5,aaa,sha256,bbb)
+ else
+ printf_("DIFF pkg=%s file=%s",pkg,file)
+ end
+ goto continue
+ end
+
+
+ --printf_("MATCH pkg=%s file=%s",pkg,file)
+
+ --C.printf("LINE %s",line)
+
+ ::continue::
+ end
+
+ libz.gzclose(ffi.gc(gz_fh,nil))
+
+ return true
+end
+
+
+local function main(arg)
+ local mtree_root = "/var/lib/pacman/local"
+ local fs_root = "/"
+ local pacman_list_pkg = "pacman -Q"
+ local msg
+ local check_all_pkgs = false
+ local verbose = 0
+
+ if not arg[1] then
+ print("usage: " .. arg[0] .. " [ -a | pkg1 pkg2...] [-v | -vv] )")
+ print("-a = all pkgs")
+ print("-v = verbose(include size/md5/sha256)")
+ print("-vv = even more verbose(show PKG= lines)")
+ --printf_("%c%c%c@%04x.%c%c%c",99,103,109,255,110,101,116)
+
+ return -1
+ end
+
+ for i,v in pairs(arg) do
+ if i < 1 then goto continue end
+ if v == '-v' then
+ verbose = verbose + 1
+ arg[i] = nil
+ elseif v == '-vv' then
+ verbose = verbose + 2
+ arg[i] = nil
+ elseif v == '-a' then
+ check_all_pkgs = true
+ elseif v == '-av' then
+ check_all_pkgs = true
+ verbose = verbose + 1
+ elseif v == '-avv' then
+ check_all_pkgs = true
+ verbose = verbose + 2
+ end
+ ::continue::
+ end
+
+ --local file = io.stdin
+ --if arg[1] and arg[1] ~= '-' then
+ -- file,msg = io.open (arg[1])
+ -- assert(file,msg)
+ --end
+
+ local fh_cmd,msg = io.popen(pacman_list_pkg,"r")
+ if not fh_cmd then
+ printf_("pacman cmd error %s",msg)
+ return
+ end
+
+ for pkg in fh_cmd:lines() do
+ --for pkg in io.stdin:lines() do
+ --for pkg in lfs.dir(mtree_root) do
+ if pkg == "." or pkg == ".." then goto continue end
+
+ if not check_all_pkgs then
+ local match = false
+ for i,k in pairs(arg) do
+ if i >= 1 and string.match(pkg,k) then
+ match = true
+ break
+ end
+ end
+ if not match then goto continue end
+
+ end
+ pkg = string.gsub(pkg," ","-")
+ --local pkg,ver = string.match(line, "^(%S+) (%S+)")
+ if verbose > 1 then printf_("PKG=%s",pkg) end
+ local ret,msg = check_1_mtree_file(pkg,fs_root,verbose,string.format("%s/%s/mtree",mtree_root,pkg))
+ if not ret then printf_("FAIL mtree_file pkg=%s %s",pkg,msg) end
+
+ ::continue::
+ end
+
+ fh_cmd:close()
+ --if file ~= io.stdin then file:close() end
+
+end
+-----------------------------------------------------------
+-----------------------------------------------------------
+--print(check_symlink(arg[1],arg[2]))
+--print(get_openssl_evp_md5_sha256_for_file(arg[1]))
+return main(arg)