luci-app-pdnsd: remove useless package

This commit is contained in:
CN_SZTL 2020-01-22 17:55:35 +08:00
parent 2db380ce79
commit 05a2dd8a1c
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
13 changed files with 0 additions and 1028 deletions

View File

@ -1,49 +0,0 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-pdnsd
PKG_VERSION=1.2
PKG_RELEASE:=1
PKG_MAINTAINER:=Alex Zhuo <1886090@gmail.com>
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME)
SECTION:=luci
CATEGORY:=LuCI
SUBMENU:=3. Applications
PKGARCH:=all
TITLE:=luci for pdnsd to invoid DNS pollution
DEPENDS:=+pdnsd-alt
endef
define Package/$(PKG_NAME)/description
A luci app for pdnsd
endef
define Package/$(PKG_NAME)/postinst
#!/bin/sh
rm -rf /tmp/luci*
endef
define Build/Prepare
$(foreach po,$(wildcard ${CURDIR}/i18n/zh-cn/*.po), \
po2lmo $(po) $(PKG_BUILD_DIR)/$(patsubst %.po,%.lmo,$(notdir $(po)));)
endef
define Build/Configure
endef
define Build/Compile
endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n
$(INSTALL_DATA) $(PKG_BUILD_DIR)/*.*.lmo $(1)/usr/lib/lua/luci/i18n/
$(CP) ./files/* $(1)/
endef
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@ -1,60 +0,0 @@
# luci-app-pdnsd
为OpenWRT路由器Pdnsd设计的luci页面和配置文件用于使用TCP协议请求DNS以方便代理转发或避免投毒已在[该固件][A]中使用
简介
---
本软件包为OpenWRT路由器使用Pdnsd进行TCP协议的DNS请求提供了修改配置文件的luci页面并在应用之后自动配置dnsmasq并重启Pdnsd
默认显示的配置文件: /etc/pdnsd_gfw.cfg
默认监听端口: `0.0.0.0:5053`
默认模式: tcp_only
默认上游DNS服务器 `114.114.114.114`
默认备用服务器: `OpenDNS`
默认备用服务器DNS端口 `53`
该配置文件无需修改即可防止DNS污染。点击【保存&应用】后会将此配置文件覆盖"/etc/pdnsd.conf"并重启pdnsd同时会后台自动修改【DHCP/DNS】的【DNS转发】为【127.0.0.1#5053】并勾选【忽略解析文件】并重启dnsmasq刷新Pdnsd界面会自动检查这个配置如果没有配置成功会以红色字提示。在取消启用后会自动恢复【DHCP/DNS】的配置。但是需要你手动去点击【DHCP/DNS】的【保存&应用】否则重启会失效并红字提示。
使用效果和更多使用方法请[参考这里][A]
依赖
---
显式依赖 `pdnsd`,支持开机自启,但是重启请注意【DHCP/DNS】中的【DNS转发】有没有成功配置成【127.0.0.1#5053】并【忽略解析文件】
配置
---
进入luci页面默认读取的是 "/etc/pdnsd_gfw.cfg" ,点击保存&应用后会以此文件覆盖"/etc/pdnsd.conf"
编译
---
从 OpenWrt 的 [SDK][openwrt-sdk] 编译
```bash
# 解压下载好的 SDK
tar xjf OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2.tar.bz2
cd OpenWrt-SDK-ar71xx-*
# Clone 项目
git clone https://github.com/AlexZhuo/luci-app-pdnsd package/luci-app-pdnsd
# 编译 po2lmo (如果有po2lmo可跳过)
pushd package/luci-app-pdnsd/tools/po2lmo
make && sudo make install
popd
# 选择要编译的包 Utilities -> LuCI -> luci-app-pdnsd
make menuconfig
# 开始编译
make package/luci-app-pdnsd/compile V=99
```
截图
---
![demo](https://github.com/AlexZhuo/BreakwallOpenWrt/raw/master/screenshots/pdnsd.png)
[A]: http://www.right.com.cn/forum/thread-198649-1-1.html
[openwrt-sdk]: https://wiki.openwrt.org/doc/howto/obtain.firmware.sdk

View File

@ -1,4 +0,0 @@
config arguments
option enabled '0'

View File

@ -1,129 +0,0 @@
global {
perm_cache=512; # dns缓存大小单位KB建议不要写的太大
cache_dir="/var/pdnsd"; # 缓存文件的位置
server_ip = 0.0.0.0; # pdnsd监听的网卡0.0.0.0是全部网卡
server_port=5353; # pdnsd监听的端口不要和别的服务冲突即可
status_ctl = on;
paranoid=on; # 二次请求模式如果请求主DNS服务器返回的是垃圾地址就向备用服务器请求
query_method=tcp_only; # 请求模式推荐使用仅TCP模式UDP模式一般需要二次请求
neg_domain_pol = off;
par_queries = 400; # 最多同时请求数
min_ttl = 1d; # DNS结果最短缓存时间
max_ttl = 1w; # DNS结果最长缓存时间
timeout = 10; # DNS请求超时时间单位秒
}
/* 上游DNS服务器的配置 */
server {
label = "routine"; # 这个随便写
ip = 114.114.114.114; # 这里为主要上级 dns 的 ip 地址建议填写一个当地最快的DNS地址
timeout = 5; # DNS请求超时时间
reject = 74.125.127.102, # 以下是脏IP也就是DNS污染一般会返回的结果如果收到如下DNS结果会触发二次请求TCP协议一般不会碰到脏IP
74.125.155.102,
74.125.39.102,
74.125.39.113,
209.85.229.138,
128.121.126.139,
159.106.121.75,
169.132.13.103,
192.67.198.6,
202.106.1.2,
202.181.7.85,
203.161.230.171,
203.98.7.65,
207.12.88.98,
208.56.31.43,
209.145.54.50,
209.220.30.174,
209.36.73.33,
211.94.66.147,
213.169.251.35,
216.221.188.182,
216.234.179.13,
243.185.187.39,
37.61.54.158,
4.36.66.178,
46.82.174.68,
59.24.3.173,
64.33.88.161,
64.33.99.47,
64.66.163.251,
65.104.202.252,
65.160.219.113,
66.45.252.237,
69.55.52.253,
72.14.205.104,
72.14.205.99,
78.16.49.15,
8.7.198.45,
93.46.8.89,
37.61.54.158,
243.185.187.39,
190.93.247.4,
190.93.246.4,
190.93.245.4,
190.93.244.4,
65.49.2.178,
189.163.17.5,
23.89.5.60,
49.2.123.56,
54.76.135.1,
77.4.7.92,
118.5.49.6,
159.24.3.173,
188.5.4.96,
197.4.4.12,
220.250.64.24,
243.185.187.30,
249.129.46.48,
253.157.14.165;
reject_policy = fail;
exclude = ".google.com",
".cn", #排除国内DNS解析如果正常翻则可以在前面加#注释
".baidu.com", #排除国内DNS解析如果正常翻则可以在前面加#注释
".qq.com", #排除国内DNS解析如果正常翻则可以在前面加#注释
".gstatic.com",
".googleusercontent.com",
".googlepages.com",
".googlevideo.com",
".googlecode.com",
".googleapis.com",
".googlesource.com",
".googledrive.com",
".ggpht.com",
".youtube.com",
".youtu.be",
".ytimg.com",
".twitter.com",
".facebook.com",
".fastly.net",
".akamai.net",
".akamaiedge.net",
".akamaihd.net",
".edgesuite.net",
".edgekey.net";
}
server {
# 以下为备用DNS服务器的配置也是二次请求服务器的配置
label = "special"; # 这个随便写
ip = 208.67.222.222,208.67.220.220; # 这里为备用DNS服务器的 ip 地址
port = 5353; # 推荐使用53以外的端口DNS服务器必须支持
proxy_only = on;
timeout = 5;
}
source {
owner=localhost;
// serve_aliases=on;
file="/etc/hosts";
}
rr {
name=localhost;
reverse=on;
a=127.0.0.1;
owner=localhost;
soa=localhost,root.localhost,42,86400,900,86400,86400;
}

View File

@ -1,33 +0,0 @@
#!/bin/sh /etc/rc.common
restart(){
echo luci for pdnsd
sleep 1s
local vt_enabled=`uci get pdnsd.@arguments[0].enabled 2>/dev/null`
echo $vt_enabled
logger -t alex !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!pdnsd is initializing enabled is $vt_enabled
if [ $vt_enabled = 1 ]; then
logger -t alex restarting pdnsd
echo "restarting pdnsd"
uci delete dhcp.@dnsmasq[0].server
uci add_list dhcp.@dnsmasq[0].server=127.0.0.1#5053
uci delete dhcp.@dnsmasq[0].resolvfile
uci set dhcp.@dnsmasq[0].noresolv=1
uci commit dhcp
cp /etc/pdnsd_gfw.cfg /etc/pdnsd.conf
/etc/init.d/dnsmasq restart
/etc/init.d/pdnsd enable
/etc/init.d/pdnsd restart
else
logger -t alex stopping pdnsd
echo "stopping pdnsd"
/etc/init.d/pdnsd disable
/etc/init.d/pdnsd stop
uci del_list dhcp.@dnsmasq[0].server=127.0.0.1#5053
uci set dhcp.@dnsmasq[0].resolvfile=/tmp/resolv.conf.auto
uci delete dhcp.@dnsmasq[0].noresolv
uci commit dhcp
/etc/init.d/dnsmasq restart
fi
}

View File

@ -1,7 +0,0 @@
module("luci.controller.pdnsd", package.seeall)
function index()
if not nixio.fs.access("/etc/config/pdnsd") then
return
end
entry({"admin", "services", "pdnsd"}, cbi("pdnsd"), _("Pdnsd")).dependent = true
end

View File

@ -1,59 +0,0 @@
--Alex<1886090@gmail.com>
local fs = require "nixio.fs"
local CONFIG_FILE = "/etc/pdnsd_gfw.cfg";
function sync_value_to_file(value, file)
value = value:gsub("\r\n?", "\n")
local old_value = nixio.fs.readfile(file)
if value ~= old_value then
nixio.fs.writefile(file, value)
end
end
local state_msg = ""
local pdnsd_on = string.len(luci.sys.exec("cat /var/run/pdnsd.pid"))>0
local other_pdnsd = (luci.sys.call("pidof pdnsd > /dev/null") == 0)
local resolv_file = luci.sys.exec("uci get dhcp.@dnsmasq[0].resolvfile")
if pdnsd_on then
state_msg = "<b><font color=\"green\">" .. translate("Running") .. "</font></b>"
else
state_msg = "<b><font color=\"red\">" .. translate("Not running") .. "</font></b>"
end
local listen_port = luci.sys.exec("uci get dhcp.@dnsmasq[0].server")
if pdnsd_on and string.sub(listen_port,1,14) == "127.0.0.1#5053" then
state_msg=state_msg .. "并恭喜你DNS转发正常"
elseif pdnsd_on then
state_msg=state_msg .. "<b><font color=\"red\">但是当前DNS转发为" .. listen_port .."请到【DHCP/DNS】修改为【127.0.0.1#5353】否则Pdnsd无效果</font></b>"
elseif other_pdnsd then
state_msg=state_msg .. "但是有其他程序开启了Pdnsd如ShadowsocksR"
end
if resolv_file=="" then
else if pdnsd_on then
state_msg=state_msg .. "<b><font color=\"red\">请到【DHCP/DNS】【HOSTS和解析文件】勾上【忽略解析文件】的勾否则Pdnsd可能无效果</font></b>"
end
end
m=Map("pdnsd",translate("Pdnsd"),translate("Pdnsd可以通过TCP协议进行DNS解析,可以方便的使用iptables进行透明代理配合ipset、GFWList使用效果更佳。默认上游服务器为114DNS可以在【DHCP/DNS】中设置【DNS转发】为【127.0.0.1#5353】即可将全局DNS请求交给pdnsd进行解析由于pdnsd自带缓存所以可以加快解析速度。另外你可以使用dig来检测DNS解析情况方法dig @127.0.0.1 -p 5053 www.facebook.com ).. "<br><br> - " .. state_msg)
s=m:section(TypedSection,"arguments","")
s.addremove=false
s.anonymous=true
view_enable = s:option(Flag,"enabled",translate("Enable"))
view_cfg = s:option(TextValue, "1", nil)
view_cfg.rmempty = false
view_cfg.rows = 43
function view_cfg.cfgvalue()
return nixio.fs.readfile(CONFIG_FILE) or ""
end
function view_cfg.write(self, section, value)
sync_value_to_file(value, CONFIG_FILE)
end
-- ---------------------------------------------------
local apply = luci.http.formvalue("cbi.apply")
if apply then
os.execute("/etc/pdnsd_init.sh restart >/dev/null 2>&1 &")
end
return m

View File

@ -1,8 +0,0 @@
msgid "Enable"
msgstr "启用"
msgid "Running"
msgstr "运行中"
msgid "Not running"
msgstr "未运行"

View File

@ -1,12 +0,0 @@
INSTALL = install
PREFIX = /usr/bin
po2lmo: src/po2lmo.o src/template_lmo.o
$(CC) $(LDFLAGS) -o src/po2lmo src/po2lmo.o src/template_lmo.o
install:
$(INSTALL) -m 755 src/po2lmo $(PREFIX)
clean:
$(RM) src/po2lmo src/*.o

View File

@ -1,247 +0,0 @@
/*
* lmo - Lua Machine Objects - PO to LMO conversion tool
*
* Copyright (C) 2009-2012 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "template_lmo.h"
static void die(const char *msg)
{
fprintf(stderr, "Error: %s\n", msg);
exit(1);
}
static void usage(const char *name)
{
fprintf(stderr, "Usage: %s input.po output.lmo\n", name);
exit(1);
}
static void print(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
if( fwrite(ptr, size, nmemb, stream) == 0 )
die("Failed to write stdout");
}
static int extract_string(const char *src, char *dest, int len)
{
int pos = 0;
int esc = 0;
int off = -1;
for( pos = 0; (pos < strlen(src)) && (pos < len); pos++ )
{
if( (off == -1) && (src[pos] == '"') )
{
off = pos + 1;
}
else if( off >= 0 )
{
if( esc == 1 )
{
switch (src[pos])
{
case '"':
case '\\':
off++;
break;
}
dest[pos-off] = src[pos];
esc = 0;
}
else if( src[pos] == '\\' )
{
dest[pos-off] = src[pos];
esc = 1;
}
else if( src[pos] != '"' )
{
dest[pos-off] = src[pos];
}
else
{
dest[pos-off] = '\0';
break;
}
}
}
return (off > -1) ? strlen(dest) : -1;
}
static int cmp_index(const void *a, const void *b)
{
uint32_t x = ((const lmo_entry_t *)a)->key_id;
uint32_t y = ((const lmo_entry_t *)b)->key_id;
if (x < y)
return -1;
else if (x > y)
return 1;
return 0;
}
static void print_uint32(uint32_t x, FILE *out)
{
uint32_t y = htonl(x);
print(&y, sizeof(uint32_t), 1, out);
}
static void print_index(void *array, int n, FILE *out)
{
lmo_entry_t *e;
qsort(array, n, sizeof(*e), cmp_index);
for (e = array; n > 0; n--, e++)
{
print_uint32(e->key_id, out);
print_uint32(e->val_id, out);
print_uint32(e->offset, out);
print_uint32(e->length, out);
}
}
int main(int argc, char *argv[])
{
char line[4096];
char key[4096];
char val[4096];
char tmp[4096];
int state = 0;
int offset = 0;
int length = 0;
int n_entries = 0;
void *array = NULL;
lmo_entry_t *entry = NULL;
uint32_t key_id, val_id;
FILE *in;
FILE *out;
if( (argc != 3) || ((in = fopen(argv[1], "r")) == NULL) || ((out = fopen(argv[2], "w")) == NULL) )
usage(argv[0]);
memset(line, 0, sizeof(key));
memset(key, 0, sizeof(val));
memset(val, 0, sizeof(val));
while( (NULL != fgets(line, sizeof(line), in)) || (state >= 2 && feof(in)) )
{
if( state == 0 && strstr(line, "msgid \"") == line )
{
switch(extract_string(line, key, sizeof(key)))
{
case -1:
die("Syntax error in msgid");
case 0:
state = 1;
break;
default:
state = 2;
}
}
else if( state == 1 || state == 2 )
{
if( strstr(line, "msgstr \"") == line || state == 2 )
{
switch(extract_string(line, val, sizeof(val)))
{
case -1:
state = 4;
break;
default:
state = 3;
}
}
else
{
switch(extract_string(line, tmp, sizeof(tmp)))
{
case -1:
state = 2;
break;
default:
strcat(key, tmp);
}
}
}
else if( state == 3 )
{
switch(extract_string(line, tmp, sizeof(tmp)))
{
case -1:
state = 4;
break;
default:
strcat(val, tmp);
}
}
if( state == 4 )
{
if( strlen(key) > 0 && strlen(val) > 0 )
{
key_id = sfh_hash(key, strlen(key));
val_id = sfh_hash(val, strlen(val));
if( key_id != val_id )
{
n_entries++;
array = realloc(array, n_entries * sizeof(lmo_entry_t));
entry = (lmo_entry_t *)array + n_entries - 1;
if (!array)
die("Out of memory");
entry->key_id = key_id;
entry->val_id = val_id;
entry->offset = offset;
entry->length = strlen(val);
length = strlen(val) + ((4 - (strlen(val) % 4)) % 4);
print(val, length, 1, out);
offset += length;
}
}
state = 0;
memset(key, 0, sizeof(key));
memset(val, 0, sizeof(val));
}
memset(line, 0, sizeof(line));
}
print_index(array, n_entries, out);
if( offset > 0 )
{
print_uint32(offset, out);
fsync(fileno(out));
fclose(out);
}
else
{
fclose(out);
unlink(argv[2]);
}
fclose(in);
return(0);
}

View File

@ -1,328 +0,0 @@
/*
* lmo - Lua Machine Objects - Base functions
*
* Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "template_lmo.h"
/*
* Hash function from http://www.azillionmonkeys.com/qed/hash.html
* Copyright (C) 2004-2008 by Paul Hsieh
*/
uint32_t sfh_hash(const char *data, int len)
{
uint32_t hash = len, tmp;
int rem;
if (len <= 0 || data == NULL) return 0;
rem = len & 3;
len >>= 2;
/* Main loop */
for (;len > 0; len--) {
hash += sfh_get16(data);
tmp = (sfh_get16(data+2) << 11) ^ hash;
hash = (hash << 16) ^ tmp;
data += 2*sizeof(uint16_t);
hash += hash >> 11;
}
/* Handle end cases */
switch (rem) {
case 3: hash += sfh_get16(data);
hash ^= hash << 16;
hash ^= data[sizeof(uint16_t)] << 18;
hash += hash >> 11;
break;
case 2: hash += sfh_get16(data);
hash ^= hash << 11;
hash += hash >> 17;
break;
case 1: hash += *data;
hash ^= hash << 10;
hash += hash >> 1;
}
/* Force "avalanching" of final 127 bits */
hash ^= hash << 3;
hash += hash >> 5;
hash ^= hash << 4;
hash += hash >> 17;
hash ^= hash << 25;
hash += hash >> 6;
return hash;
}
uint32_t lmo_canon_hash(const char *str, int len)
{
char res[4096];
char *ptr, prev;
int off;
if (!str || len >= sizeof(res))
return 0;
for (prev = ' ', ptr = res, off = 0; off < len; prev = *str, off++, str++)
{
if (isspace(*str))
{
if (!isspace(prev))
*ptr++ = ' ';
}
else
{
*ptr++ = *str;
}
}
if ((ptr > res) && isspace(*(ptr-1)))
ptr--;
return sfh_hash(res, ptr - res);
}
lmo_archive_t * lmo_open(const char *file)
{
int in = -1;
uint32_t idx_offset = 0;
struct stat s;
lmo_archive_t *ar = NULL;
if (stat(file, &s) == -1)
goto err;
if ((in = open(file, O_RDONLY)) == -1)
goto err;
if ((ar = (lmo_archive_t *)malloc(sizeof(*ar))) != NULL)
{
memset(ar, 0, sizeof(*ar));
ar->fd = in;
ar->size = s.st_size;
fcntl(ar->fd, F_SETFD, fcntl(ar->fd, F_GETFD) | FD_CLOEXEC);
if ((ar->mmap = mmap(NULL, ar->size, PROT_READ, MAP_SHARED, ar->fd, 0)) == MAP_FAILED)
goto err;
idx_offset = ntohl(*((const uint32_t *)
(ar->mmap + ar->size - sizeof(uint32_t))));
if (idx_offset >= ar->size)
goto err;
ar->index = (lmo_entry_t *)(ar->mmap + idx_offset);
ar->length = (ar->size - idx_offset - sizeof(uint32_t)) / sizeof(lmo_entry_t);
ar->end = ar->mmap + ar->size;
return ar;
}
err:
if (in > -1)
close(in);
if (ar != NULL)
{
if ((ar->mmap != NULL) && (ar->mmap != MAP_FAILED))
munmap(ar->mmap, ar->size);
free(ar);
}
return NULL;
}
void lmo_close(lmo_archive_t *ar)
{
if (ar != NULL)
{
if ((ar->mmap != NULL) && (ar->mmap != MAP_FAILED))
munmap(ar->mmap, ar->size);
close(ar->fd);
free(ar);
ar = NULL;
}
}
lmo_catalog_t *_lmo_catalogs = NULL;
lmo_catalog_t *_lmo_active_catalog = NULL;
int lmo_load_catalog(const char *lang, const char *dir)
{
DIR *dh = NULL;
char pattern[16];
char path[PATH_MAX];
struct dirent *de = NULL;
lmo_archive_t *ar = NULL;
lmo_catalog_t *cat = NULL;
if (!lmo_change_catalog(lang))
return 0;
if (!dir || !(dh = opendir(dir)))
goto err;
if (!(cat = malloc(sizeof(*cat))))
goto err;
memset(cat, 0, sizeof(*cat));
snprintf(cat->lang, sizeof(cat->lang), "%s", lang);
snprintf(pattern, sizeof(pattern), "*.%s.lmo", lang);
while ((de = readdir(dh)) != NULL)
{
if (!fnmatch(pattern, de->d_name, 0))
{
snprintf(path, sizeof(path), "%s/%s", dir, de->d_name);
ar = lmo_open(path);
if (ar)
{
ar->next = cat->archives;
cat->archives = ar;
}
}
}
closedir(dh);
cat->next = _lmo_catalogs;
_lmo_catalogs = cat;
if (!_lmo_active_catalog)
_lmo_active_catalog = cat;
return 0;
err:
if (dh) closedir(dh);
if (cat) free(cat);
return -1;
}
int lmo_change_catalog(const char *lang)
{
lmo_catalog_t *cat;
for (cat = _lmo_catalogs; cat; cat = cat->next)
{
if (!strncmp(cat->lang, lang, sizeof(cat->lang)))
{
_lmo_active_catalog = cat;
return 0;
}
}
return -1;
}
static lmo_entry_t * lmo_find_entry(lmo_archive_t *ar, uint32_t hash)
{
unsigned int m, l, r;
uint32_t k;
l = 0;
r = ar->length - 1;
while (1)
{
m = l + ((r - l) / 2);
if (r < l)
break;
k = ntohl(ar->index[m].key_id);
if (k == hash)
return &ar->index[m];
if (k > hash)
{
if (!m)
break;
r = m - 1;
}
else
{
l = m + 1;
}
}
return NULL;
}
int lmo_translate(const char *key, int keylen, char **out, int *outlen)
{
uint32_t hash;
lmo_entry_t *e;
lmo_archive_t *ar;
if (!key || !_lmo_active_catalog)
return -2;
hash = lmo_canon_hash(key, keylen);
for (ar = _lmo_active_catalog->archives; ar; ar = ar->next)
{
if ((e = lmo_find_entry(ar, hash)) != NULL)
{
*out = ar->mmap + ntohl(e->offset);
*outlen = ntohl(e->length);
return 0;
}
}
return -1;
}
void lmo_close_catalog(const char *lang)
{
lmo_archive_t *ar, *next;
lmo_catalog_t *cat, *prev;
for (prev = NULL, cat = _lmo_catalogs; cat; prev = cat, cat = cat->next)
{
if (!strncmp(cat->lang, lang, sizeof(cat->lang)))
{
if (prev)
prev->next = cat->next;
else
_lmo_catalogs = cat->next;
for (ar = cat->archives; ar; ar = next)
{
next = ar->next;
lmo_close(ar);
}
free(cat);
break;
}
}
}

View File

@ -1,92 +0,0 @@
/*
* lmo - Lua Machine Objects - General header
*
* Copyright (C) 2009-2012 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _TEMPLATE_LMO_H_
#define _TEMPLATE_LMO_H_
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <fnmatch.h>
#include <dirent.h>
#include <ctype.h>
#include <limits.h>
#if (defined(__GNUC__) && defined(__i386__))
#define sfh_get16(d) (*((const uint16_t *) (d)))
#else
#define sfh_get16(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
+(uint32_t)(((const uint8_t *)(d))[0]) )
#endif
struct lmo_entry {
uint32_t key_id;
uint32_t val_id;
uint32_t offset;
uint32_t length;
} __attribute__((packed));
typedef struct lmo_entry lmo_entry_t;
struct lmo_archive {
int fd;
int length;
uint32_t size;
lmo_entry_t *index;
char *mmap;
char *end;
struct lmo_archive *next;
};
typedef struct lmo_archive lmo_archive_t;
struct lmo_catalog {
char lang[6];
struct lmo_archive *archives;
struct lmo_catalog *next;
};
typedef struct lmo_catalog lmo_catalog_t;
uint32_t sfh_hash(const char *data, int len);
uint32_t lmo_canon_hash(const char *data, int len);
lmo_archive_t * lmo_open(const char *file);
void lmo_close(lmo_archive_t *ar);
extern lmo_catalog_t *_lmo_catalogs;
extern lmo_catalog_t *_lmo_active_catalog;
int lmo_load_catalog(const char *lang, const char *dir);
int lmo_change_catalog(const char *lang);
int lmo_translate(const char *key, int keylen, char **out, int *outlen);
void lmo_close_catalog(const char *lang);
#endif