Compare commits

...

17 Commits

Author SHA1 Message Date
YuQing 4c6efd434b INSTALL changed for V1.0.88 2026-09-06 14:57:35 +08:00
YuQing 02227ff318 upgrade version to 1.0.88 2026-09-04 11:10:27 +08:00
YuQing 9493e1ad47 add functions: parse_timestamp and iniGetTimestampValueEx 2026-09-04 09:53:07 +08:00
YuQing 15424dfc1c local_host_ip_addrs_to_string: fix buffer overflow 2026-09-03 15:21:36 +08:00
YuQing 564facf33e INSTALL changed for 1.0.87 2026-08-24 15:21:41 +08:00
YuQing f6f664b33d call getFileContentEx with offset constant 2026-07-22 15:34:16 +08:00
YuQing 7b06207f6f doc/ini_file_reader-Chinese.md beautify 2026-07-15 11:55:03 +08:00
YuQing d21a95b02e upgrade version to 1.0.87 2026-07-14 08:30:01 +08:00
YuQing a755beb263 README.md small changes 2026-07-11 09:21:27 +08:00
YuQing 369fe740d3 README.md: beautify layout 2026-07-10 20:45:30 +08:00
YuQing 176cf19576 rename README to README.md 2026-07-10 20:39:34 +08:00
YuQing 598ae419e7 README add doc links 2026-07-10 20:34:54 +08:00
YuQing 4f87de79ec ini_file_readers can refer env variable as %{env::XXX} 2026-07-10 19:45:08 +08:00
YuQing 3cca66ac15 upgrade version to 1.0.86 2026-06-30 09:51:38 +08:00
YuQing 79cd21f667 change return type of format_ip_address and format_ip_port 2026-06-26 11:08:50 +08:00
YuQing 1edcae9cf4 add function fc_parse_version 2026-06-25 15:13:06 +08:00
YuQing 724b008b0e fc_version() return combined integer version 2026-06-24 08:21:27 +08:00
19 changed files with 331 additions and 119 deletions

12
HISTORY
View File

@ -1,4 +1,16 @@
Version 1.88 2026-09-04
* local_host_ip_addrs_to_string: fix buffer overflow
* shared_func.[hc]: add function parse_timestamp
* ini_file_reader.[hc]: add function iniGetTimestampValueEx
Version 1.87 2026-07-10
* ini_file_readers can refer env variable such as %{env::FASTDFS_IPADDR}
Version 1.86 2026-06-26
* add function fc_parse_version
* change return type of format_ip_address and format_ip_port
Version 1.85 2026-06-23
* add functions fc_safe_srand and fc_safe_rand for more security under Linux
* add function seconds_to_human_str

View File

@ -21,5 +21,5 @@ Debian, Ubuntu etc.:
# the command lines as:
git clone https://github.com/happyfish100/libfastcommon.git
cd libfastcommon; git checkout V1.0.85
cd libfastcommon; git checkout V1.0.88
./make.sh clean && ./make.sh && sudo ./make.sh install

View File

@ -1,11 +1,3 @@
Copyright (C) 2010 Happy Fish / YuQing
libfastcommon may be copied only under the terms of the Less GNU General
Public License(LGPL).
Please visit the libfastcommon Home Page for more detail.
English language: https://github.com/happyfish100/libfastcommon
Chinese language: http://www.fastken.com/
c common functions library extracted from my open source projects FastDFS and
FastDHT. this library is very simple and stable.
@ -14,20 +6,29 @@ some functions are wrappered into php extension, such as fastcommon_gethostaddrs
fastcommon_id_generator_xxx, fastcommon_get_ifconfigs, fastcommon_get_sysinfo etc.
C function including:
logger: [logger.h] asynchronously sync to disk for high performance, thread safe,
log rotate, auto delete old log files, compress log file etc.
ini file reader: [ini_file_reader.h] support sections marked by [SectionName]
ini file reader: [ini_file_reader.h] support sections marked by [SectionName],
support a config item ocurs multiple times for multiple values, such as:
tracker_server = ip1
tracker_server = ip2
#include directive to include other ini file
#@function directive for annotation
#@set directive to set variables for condition of #@if directive
support control statements for special purpose as:
#@if, #@else, #@endif, #@for, #@endfor
```
tracker_server = ip1
tracker_server = ip2
```
id generator: [id_generator.h] generate unique 64 bits integer ID for multi processes
```
#include directive to include other ini file
#@function directive for annotation
#@set directive to set variables for condition of #@if directive
support control statements for special purpose as:
#@if, #@else, #@endif, #@for, #@endfor
```
for more detail, please see [ini file reader guide](doc/ini_file_reader-Chinese.md)
id generator: [id_generator.h] generate unique 64 bits integer ID for multi processes.
for more detail, please see [id generator description](doc/id_generator-Chinese.md)
string operation: [shared_func.h] uppercase, lowercase, trim etc.
@ -72,5 +73,5 @@ C function including:
char convert: [char_converter.h] and [char_convert_loader.h] for fast char convert
detail info please see the c header files.
more detail info please see the c header files.

View File

@ -10,38 +10,42 @@ libfastcommon是在github开源的⼀个C函数库。它提供了ini⽂件解析
## ini_file_reader的主要特点
### 1、⽀持section
例如:
```
例如: [workers]
[workers]
threads = 4
# 其他配置项
```
### 2、⼀个配置项可以出现多次
通过iniGetValues或者iniGetValuesEx获取。例如
```
通过iniGetValues或者iniGetValuesEx获取。例如
tracker_server = ip1
tracker_server = ip2
tracker_server = 172.16.168.10
tracker_server = 172.16.168.11
```
### 3、 #include指令包含其他配置⽂件
可以包含本地配置⽂件也可以包含URL目前仅⽀持HTTP。例如
```
可以包含本地⽂件也可以包含URL目前仅⽀持HTTP。例如
#include http.conf
#include http.conf
```
### 4、 #@function指令⽀持标注
配置项的取值为扩展(外部)动态库的返回值。
⽀持三个内置标注:
```
配置项的取值为扩展(外部)动态库的返回值
V1.39⽀持三个内置标注:
I. LOCAL_IP_GET [inner | private | outer | public] 获取本机IP地址
inner或private表示获取内网IPouter或public表示获取外网IP
[index]表示获取指定序号的本机IP0表示获取第一个IP-1表示获取最后一个IP
例如:[0]、inner[-1], outer[1]等等
II. SHELL_EXEC 获取命令⾏输出执行的command为配置项
III. REPLACE_VARS 替换配置项中%{VARIABLE}格式的变量,变量由#@set指令设置
III. REPLACE_VARS 替换配置项中%{VARIABLE}格式的变量,普通变量由#@set指令设置。
可以引用环境变量,格式为 %{env::VARIABLE},例如 %{env::FASTDFS_IPADDR}
```
```
配置⽰例:
```
#@function SHELL_EXEC
host = hostname
@ -57,12 +61,14 @@ libfastcommon是在github开源的⼀个C函数库。它提供了ini⽂件解析
### 5、 #@add_annotation 扩展#@function标签
```
格式:
```
#@add_annotation <function> <动态库文件名> [参数1, 参数2, ...]
```
参数个数0到3个。
使用libshmcache扩展标签CONFIG_GET示例
```
#@add_annotation CONFIG_GET /usr/lib/libshmcache.so /etc/libshmcache.conf
#@function CONFIG_GET

View File

@ -3,7 +3,7 @@
%define CommitVersion %(echo $COMMIT_VERSION)
Name: libfastcommon
Version: 1.0.85
Version: 1.0.88
Release: 1%{?dist}
Summary: c common functions library extracted from my open source projects FastDFS
License: LGPL

View File

@ -372,6 +372,16 @@ typedef void* (*MallocFunc)(size_t size);
#define FC_SET_CHAIN_TAIL_NEXT(chain, type, ptr) \
((type *)(chain).tail)->next = ptr
#define FC_VERSION_TO_INT(major, minor, patch) \
(major * 1000 * 1000 + minor * 1000 + patch)
#define FC_VERSION_TO_INT1(version) \
FC_VERSION_TO_INT((version).major, \
(version).minor, (version).patch)
#define FC_COMPARE_INT_VERSIONS_TO_OPERATOR_STR(v1, v2) \
(v1 < v2 ? "<" : (v1 == v2 ? "==" : ">"))
#ifdef WIN32
#define strcasecmp _stricmp
#endif

View File

@ -180,6 +180,7 @@ int fast_buffer_append_binary(FastBuffer *buffer,
int fast_buffer_append_file(FastBuffer *buffer, const char *filename)
{
const int64_t offset = 0;
struct stat st;
int result;
int64_t file_size;
@ -213,7 +214,7 @@ int fast_buffer_append_file(FastBuffer *buffer, const char *filename)
}
if ((result=getFileContentEx(filename, buffer->data + buffer->length,
0, &file_size)) != 0)
offset, &file_size)) != 0)
{
return result;
}

View File

@ -15,9 +15,10 @@
#include "fc_version.h"
void fc_version(Version *version)
int fc_version(Version *version)
{
version->major = FC_MAJOR_VERSION;
version->minor = FC_MINOR_VERSION;
version->patch = FC_PATCH_VERSION;
return FC_VERSION_TO_INT1(*version);
}

View File

@ -22,13 +22,16 @@
#define FC_MAJOR_VERSION 1
#define FC_MINOR_VERSION 0
#define FC_PATCH_VERSION 85
#define FC_PATCH_VERSION 88
#define FC_VERSION_INT FC_VERSION_TO_INT(FC_MAJOR_VERSION, \
FC_MINOR_VERSION, FC_PATCH_VERSION)
#ifdef __cplusplus
extern "C" {
#endif
void fc_version(Version *version);
int fc_version(Version *version);
#ifdef __cplusplus
}

View File

@ -299,6 +299,11 @@ static char *doReplaceVars(IniContext *pContext, const char *param,
{
#define VARIABLE_TAG_MIN_LENGTH 4 //%{v}
#define ENV_VAR_NAME_STARTWITH_STR "env::"
#define ENV_VAR_NAME_STARTWITH_LEN (sizeof(ENV_VAR_NAME_STARTWITH_STR) - 1)
#define ENV_VARIABLE_MARK_STR "%{"ENV_VAR_NAME_STARTWITH_STR
SetDirectiveVars *set;
const char *p;
const char *e;
@ -319,11 +324,13 @@ static char *doReplaceVars(IniContext *pContext, const char *param,
set = iniGetVars(pContext);
if (set == NULL || set->vars == NULL) {
logWarning("file: "__FILE__", line: %d, "
"NO set directives before, set value to %s",
__LINE__, param);
fc_strlcpy(output, param, FAST_INI_ITEM_VALUE_SIZE);
return output;
if (strstr(param, ENV_VARIABLE_MARK_STR) == NULL) {
logWarning("file: "__FILE__", line: %d, "
"NO set directives before, set value to %s",
__LINE__, param);
fc_strlcpy(output, param, FAST_INI_ITEM_VALUE_SIZE);
return output;
}
}
pEnd = param + strlen(param);
@ -354,25 +361,33 @@ static char *doReplaceVars(IniContext *pContext, const char *param,
*(name + name_len) = '\0';
fc_trim(name);
name_len = strlen(name);
if (name_len > 0) {
value = (char *)fc_hash_find(set->vars, name, name_len);
if (name_len > ENV_VAR_NAME_STARTWITH_LEN &&
memcmp(name, ENV_VAR_NAME_STARTWITH_STR,
ENV_VAR_NAME_STARTWITH_LEN) == 0)
{
value = getenv(name + ENV_VAR_NAME_STARTWITH_LEN);
} else if (name_len > 0) {
if (set != NULL && set->vars != NULL) {
value = (char *)fc_hash_find(set->vars, name, name_len);
} else {
value = NULL;
}
} else {
value = NULL;
}
if (value != NULL) {
len = strlen(value);
}
else {
} else {
logWarning("file: "__FILE__", line: %d, "
"name: %s NOT found, keep the origin",
"variable \"%s\" NOT found, keep the origin",
__LINE__, name);
value = start - 2;
len = p - value;
}
pDest += iniCopyBuffer(pDest, FAST_INI_ITEM_VALUE_SIZE -
(pDest - output), value, len);
}
else {
} else {
if (pDest - output < FAST_INI_ITEM_VALUE_LEN) {
*pDest++ = *p++;
}
@ -3516,3 +3531,26 @@ int iniGetPercentValueEx(IniFullContext *ini_ctx,
return 0;
}
int64_t iniGetTimestampValueEx(const char *szSectionName,
const char *szItemName, IniContext *pContext,
const int64_t nDefaultValue, const int nDefaultUnitTS,
const bool bRetryGlobal)
{
char *pValue;
int64_t nValue;
pValue = iniGetStrValueEx(szSectionName,
szItemName, pContext, bRetryGlobal);
if (pValue == NULL)
{
return nDefaultValue;
}
if (parse_timestamp(pValue, nDefaultUnitTS, &nValue) != 0)
{
return nDefaultValue;
}
return nValue;
}

View File

@ -140,6 +140,10 @@ extern "C" {
#define iniGetPercentValue(ini_ctx, item_name, item_value, default_value) \
iniGetPercentValueEx(ini_ctx, item_name, item_value, default_value, false)
#define iniGetTimestampValue(szSectionName, szItemName, pContext, nDefaultValue) \
iniGetTimestampValueEx(szSectionName, szItemName, \
pContext, nDefaultValue, 1, false)
#define iniGetByteValue(szSectionName, szItemName, pContext, nDefaultValue) \
iniGetByteValueEx(szSectionName, szItemName, \
pContext, nDefaultValue, 1, false)
@ -424,6 +428,22 @@ int64_t iniGetByteCorrectValueEx(IniFullContext *pIniContext,
const int nDefaultUnitBytes, const int64_t nMinValue,
const int64_t nMaxValue, const bool bRetryGlobal);
/** get item timestamp value (64 bits integer)
* parameters:
* szSectionName: the section name, NULL or empty string for
* global section
* szItemName: the item name
* pContext: the ini context
* nDefaultValue: the default value
* nDefaultUnitBytes: the default timestamp unit, such as 1 for second, 86400 for day
* bRetryGlobal: if fetch from global section when the item not exist
* return: int64 value, return nDefaultValue when the item not exist
*/
int64_t iniGetTimestampValueEx(const char *szSectionName,
const char *szItemName, IniContext *pContext,
const int64_t nDefaultValue, const int nDefaultUnitTS,
const bool bRetryGlobal);
/** get item boolean value
* parameters:
* szSectionName: the section name, NULL or empty string for

View File

@ -70,12 +70,21 @@ const char *local_host_ip_addrs_to_string(char *buff, const int size)
len = snprintf(buff, size, "local_host_ip_count: %d,",
g_local_host_ip_count);
if (len >= size)
{
return buff;
}
pEnd = g_local_host_ip_addrs +
IP_ADDRESS_SIZE * g_local_host_ip_count;
for (p=g_local_host_ip_addrs; p<pEnd; p+=IP_ADDRESS_SIZE)
{
len += snprintf(buff + len, size - len, " %s", p);
}
{
len += snprintf(buff + len, size - len, " %s", p);
if (len >= size)
{
break;
}
}
return buff;
}

View File

@ -140,26 +140,27 @@ static int fast_multi_sock_client_do_send(FastMultiSockClient *client,
if (errno == EAGAIN || errno == EWOULDBLOCK) {
break;
} else if (errno == EINTR) { //should retry
format_ip_address(entry->conn->ip_addr, formatted_ip);
logDebug("file: "__FILE__", line: %d, "
"server: %s:%u, ignore interupt signal", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip),
entry->conn->port);
formatted_ip, entry->conn->port);
continue;
} else {
result = errno != 0 ? errno : ECONNRESET;
format_ip_address(entry->conn->ip_addr, formatted_ip);
logError("file: "__FILE__", line: %d, "
"send to server %s:%u fail, "
"errno: %d, error info: %s", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip),
entry->conn->port, result, strerror(result));
formatted_ip, entry->conn->port,
result, strerror(result));
break;
}
} else if (bytes == 0) {
format_ip_address(entry->conn->ip_addr, formatted_ip);
logError("file: "__FILE__", line: %d, "
"send to server %s:%u, sock: %d fail, "
"connection disconnected", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip),
"connection disconnected", __LINE__, formatted_ip,
entry->conn->port, entry->conn->sock);
result = ECONNRESET;
@ -203,10 +204,10 @@ static int fast_multi_sock_client_send_data(FastMultiSockClient *client,
if (client->entries[i].conn->sock < 0) {
client->entries[i].error_no = ENOTCONN;
client->entries[i].done = true;
format_ip_address(client->entries[i].conn->ip_addr, formatted_ip);
logError("file: "__FILE__", line: %d, "
"NOT connected to %s:%u", __LINE__,
format_ip_address(client->entries[i].conn->ip_addr,
formatted_ip), client->entries[i].conn->port);
formatted_ip, client->entries[i].conn->port);
continue;
}
@ -256,26 +257,27 @@ static int fast_multi_sock_client_do_recv(FastMultiSockClient *client,
if (errno == EAGAIN || errno == EWOULDBLOCK) {
break;
} else if (errno == EINTR) { //should retry
format_ip_address(entry->conn->ip_addr, formatted_ip);
logDebug("file: "__FILE__", line: %d, "
"server: %s:%u, ignore interupt signal", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip),
entry->conn->port);
formatted_ip, entry->conn->port);
continue;
} else {
result = errno != 0 ? errno : ECONNRESET;
format_ip_address(entry->conn->ip_addr, formatted_ip);
logError("file: "__FILE__", line: %d, "
"server: %s:%u, recv failed, "
"errno: %d, error info: %s", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip),
entry->conn->port, result, strerror(result));
formatted_ip, entry->conn->port,
result, strerror(result));
break;
}
} else if (bytes == 0) {
format_ip_address(entry->conn->ip_addr, formatted_ip);
logError("file: "__FILE__", line: %d, "
"server: %s:%u, sock: %d, recv failed, "
"connection disconnected", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip),
"connection disconnected", __LINE__, formatted_ip,
entry->conn->port, entry->conn->sock);
result = ECONNRESET;
@ -290,10 +292,10 @@ static int fast_multi_sock_client_do_recv(FastMultiSockClient *client,
entry->recv_stage = fms_stage_recv_body;
body_length = client->get_body_length_func(&entry->recv_buffer);
if (body_length < 0) {
format_ip_address(entry->conn->ip_addr, formatted_ip);
logError("file: "__FILE__", line: %d, "
"server: %s:%u, body_length: %d < 0", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip),
entry->conn->port, body_length);
formatted_ip, entry->conn->port, body_length);
result = EPIPE;
break;
} else if (body_length == 0) {
@ -374,10 +376,10 @@ static int fast_multi_sock_client_deal_io(FastMultiSockClient *client)
&client->ioevent, index);
if (event & IOEVENT_ERROR) {
format_ip_address(entry->conn->ip_addr, formatted_ip);
logError("file: "__FILE__", line: %d, "
"server: %s:%u, recv error event: %d, connection "
"reset", __LINE__, format_ip_address(entry->conn->
ip_addr, formatted_ip), entry->conn->port, event);
"server: %s:%u, recv error event: %d, connection reset",
__LINE__, formatted_ip, entry->conn->port, event);
fast_multi_sock_client_finish(client, entry, ECONNRESET);
continue;
@ -404,10 +406,10 @@ static int fast_multi_sock_client_deal_io(FastMultiSockClient *client)
if (!client->entries[i].done) {
fast_multi_sock_client_finish(client,
client->entries + i, ETIMEDOUT);
format_ip_address(client->entries[i].conn->ip_addr, formatted_ip);
logError("file: "__FILE__", line: %d, "
"recv from %s:%u timedout", __LINE__,
format_ip_address(client->entries[i].conn->ip_addr,
formatted_ip), client->entries[i].conn->port);
formatted_ip, client->entries[i].conn->port);
}
}
}

View File

@ -24,6 +24,7 @@
int get_pid_from_file(const char *pidFilename, pid_t *pid)
{
const int64_t offset = 0;
char buff[32];
int64_t file_size;
int result;
@ -33,7 +34,7 @@ int get_pid_from_file(const char *pidFilename, pid_t *pid)
}
file_size = sizeof(buff);
if ((result=getFileContentEx(pidFilename, buff, 0, &file_size)) != 0) {
if ((result=getFileContentEx(pidFilename, buff, offset, &file_size)) != 0) {
return result;
}
@ -183,12 +184,13 @@ static const char *process_get_exename(const char* program)
static const char *get_exename_by_pid(const pid_t pid, char *buff,
const int buff_size, int *result)
{
const int64_t offset = 0;
char cmdfile[MAX_PATH_SIZE];
int64_t cmdsz;
cmdsz = buff_size;
sprintf(cmdfile, "/proc/%d/cmdline", pid);
if ((*result=getFileContentEx(cmdfile, buff, 0, &cmdsz)) != 0) {
if ((*result=getFileContentEx(cmdfile, buff, offset, &cmdsz)) != 0) {
fprintf(stderr, "read file %s fail, errno: %d, error info: %s\n",
cmdfile, *result, strerror(*result));
return NULL;

View File

@ -259,11 +259,11 @@ static int fc_server_check_ip_port(FCServerConfig *ctx,
id1 = current->server->id;
id2 = previous->server->id;
}
format_ip_address(previous->ip_addr.str, formatted_ip);
logError("file: "__FILE__", line: %d, "
"config file: %s, duplicate ip:port %s:%u, "
"the server ids: %d, %d", __LINE__,
config_filename, format_ip_address(previous->ip_addr.str,
formatted_ip), previous->port, id1, id2);
"the server ids: %d, %d", __LINE__, config_filename,
formatted_ip, previous->port, id1, id2);
return EEXIST;
}
@ -714,14 +714,14 @@ static int check_addresses_duplicate(FCServerConfig *ctx,
ppend = group_addr->address_array.addrs + group_addr->address_array.count;
for (ppaddr=group_addr->address_array.addrs+1; ppaddr<ppend; ppaddr++) {
if (fc_server_cmp_address_ptr(ppaddr, pprevious) == 0) {
format_ip_address((*ppaddr)->conn.ip_addr, formatted_ip),
logError("file: "__FILE__", line: %d, "
"config filename: %s, section: %s, group: %.*s, "
"duplicate ip and port: %s:%u", __LINE__,
config_filename, section_name,
group_addr->server_group->group_name.len,
group_addr->server_group->group_name.str,
format_ip_address((*ppaddr)->conn.ip_addr, formatted_ip),
(*ppaddr)->conn.port);
formatted_ip, (*ppaddr)->conn.port);
return EEXIST;
}
pprevious = ppaddr;
@ -967,12 +967,12 @@ static int fc_server_set_host(FCServerConfig *ctx, FCServerInfo *server,
}
if (!ctx->share_between_groups && (count > 1 && addr->conn.port > 0)) {
format_ip_address(addr->conn.ip_addr, formatted_ip),
logError("file: "__FILE__", line: %d, "
"config filename: %s, section: %s, "
"host %s:%u belongs to %d groups",
__LINE__, config_filename, section_name,
format_ip_address(addr->conn.ip_addr, formatted_ip),
addr->conn.port, count);
formatted_ip, addr->conn.port, count);
return EEXIST;
}
@ -1544,9 +1544,10 @@ static void fc_group_servers_to_string(FCServerConfig *ctx,
gaddr->server_group->group_name.str,
SERVER_ITEM_HOST_AFFIX_STR);
}
format_ip_address((*addr)->conn.ip_addr, formatted_ip),
fast_buffer_append(buffer, " = %s:%u\n",
format_ip_address((*addr)->conn.ip_addr, formatted_ip),
(*addr)->conn.port);
formatted_ip, (*addr)->conn.port);
}
}
@ -1655,9 +1656,9 @@ static void fc_server_log_group_servers(FCGroupAddresses *gaddr)
end = gaddr->address_array.addrs + gaddr->address_array.count;
for (addr=gaddr->address_array.addrs; addr<end; addr++) {
format_ip_address((*addr)->conn.ip_addr, formatted_ip),
logInfo(" %d. %s:%u", (int)(addr - gaddr->address_array.addrs + 1),
format_ip_address((*addr)->conn.ip_addr, formatted_ip),
(*addr)->conn.port);
formatted_ip, (*addr)->conn.port);
}
}

View File

@ -2484,6 +2484,88 @@ int parse_bytes(const char *pStr, const int default_unit_bytes, int64_t *bytes)
return result;
}
int parse_timestamp(const char *str, const int default_unit_secs, int64_t *seconds)
{
char *pReservedEnd;
int result;
pReservedEnd = NULL;
*seconds = strtoll(str, &pReservedEnd, 10);
if (*seconds < 0)
{
logError("file: "__FILE__", line: %d, "
"timestamp: %"PRId64" < 0, input string: %s",
__LINE__, *seconds, str);
return EINVAL;
}
if (pReservedEnd == NULL || *pReservedEnd == '\0')
{
*seconds *= default_unit_secs;
return 0;
}
if (*pReservedEnd == ' ' || *pReservedEnd == '\t')
{
do {
++pReservedEnd;
} while (*pReservedEnd == ' ' || *pReservedEnd == '\t');
if (*pReservedEnd == '\0')
{
*seconds *= default_unit_secs;
return 0;
}
}
if (*(pReservedEnd + 1) != '\0')
{
logError("file: "__FILE__", line: %d, "
"unkown timestamp unit: \"%s\", input string: \"%s\"",
__LINE__, pReservedEnd, str);
return EINVAL;
}
switch (*pReservedEnd)
{
case 's':
result = 0;
break;
case 'm':
*seconds *= 60;
result = 0;
break;
case 'h':
*seconds *= 3600;
result = 0;
break;
case 'd':
*seconds *= 86400;
result = 0;
break;
case 'W':
*seconds *= 7 * 86400;
result = 0;
break;
case 'M':
*seconds *= 30 * 86400;
result = 0;
break;
case 'Y':
*seconds *= 365 * 86400;
result = 0;
break;
default:
result = EINVAL;
logError("file: "__FILE__", line: %d, "
"unkown timestamp unit: \"%s\", input string: \"%s\"",
__LINE__, pReservedEnd, str);
break;
}
return result;
}
int set_rand_seed()
{
time_t ts;
@ -3283,6 +3365,7 @@ static int format_bytes_string(const int64_t input_bytes,
}
p = buff + fc_itoa(n, buff);
}
return p - buff;
}
@ -4090,12 +4173,13 @@ int fc_check_rename_ex(const char *oldpath, const char *newpath,
int fc_get_first_line(const char *filename, char *buff,
const int buff_size, string_t *line)
{
const int64_t offset = 0;
int result;
int64_t read_bytes;
char *line_end;
read_bytes = buff_size - 1;
if ((result=getFileContentEx(filename, buff, 0, &read_bytes)) != 0) {
if ((result=getFileContentEx(filename, buff, offset, &read_bytes)) != 0) {
FC_SET_STRING_EMPTY(*line, buff);
return result;
}
@ -4121,6 +4205,7 @@ int fc_get_first_line(const char *filename, char *buff,
int fc_get_first_lines(const char *filename, char *buff,
const int buff_size, string_t *lines, int *count)
{
const int64_t offset = 0;
int result;
int target_count;
int64_t read_bytes;
@ -4134,7 +4219,7 @@ int fc_get_first_lines(const char *filename, char *buff,
}
read_bytes = buff_size - 1;
if ((result=getFileContentEx(filename, buff, 0, &read_bytes)) != 0) {
if ((result=getFileContentEx(filename, buff, offset, &read_bytes)) != 0) {
*count = 0;
FC_SET_STRING_EMPTY(*lines, buff);
return result;
@ -4691,3 +4776,27 @@ int fc_safe_rand()
return (n & RAND_MAX);
}
#endif
int fc_parse_version(const char *src, Version *version)
{
const char *p;
int numbers[2];
int i;
numbers[0] = numbers[1] = 0;
p = src;
for (i=0; i<2; i++) {
p = strchr(p, '.');
if (p == NULL) {
break;
}
p++;
numbers[i] = strtol(p, NULL, 10);
}
version->major = strtol(src, NULL, 10);
version->minor = numbers[0];
version->patch = numbers[1];
return FC_VERSION_TO_INT1(*version);
}

View File

@ -878,7 +878,7 @@ int getFileContentEx1(int fd, const char *filename, char *buff,
* size: specify the size to fetch and return the fetched size
* return: error no , 0 success, != 0 fail
*/
int getFileContentEx(const char *filename, char *buff, \
int getFileContentEx(const char *filename, char *buff,
int64_t offset, int64_t *size);
/** get file size
@ -979,12 +979,22 @@ int fc_compare_int64_ptr(const int64_t *n1, const int64_t *n2);
/** parse bytes
* parameters:
* pStr: the string to parse
* default_unit_bytes: default unit if not specified the unit like MB etc.
* default_unit_bytes: default unit if not specified, the unit like MB etc.
* bytes: store the parsed bytes
* return: error no , 0 success, != 0 fail
*/
int parse_bytes(const char *pStr, const int default_unit_bytes, int64_t *bytes);
/** parse timestamp
* parameters:
* str: the string to parse
* default_unit_secs: default unit if not specified
* seconds: store the parsed seconds
* return: error no , 0 success, != 0 fail
*/
int parse_timestamp(const char *str, const int default_unit_secs, int64_t *seconds);
/** set rand seed
* return: error no , 0 success, != 0 fail
*/
@ -1877,6 +1887,8 @@ int fc_safe_rand();
#define fc_safe_rand() rand()
#endif
int fc_parse_version(const char *src, Version *version);
#ifdef __cplusplus
}
#endif

View File

@ -706,11 +706,11 @@ static inline bool is_ipv6_addr(const char *ip)
return (*ip == ':' || strchr(ip, ':') != NULL); //ipv6
}
static inline const char *format_ip_address(const char *ip, char *buff)
static inline int format_ip_address(const char *ip, char *buff)
{
int ip_len;
if (is_ipv6_addr(ip))
{
int ip_len;
char *p;
ip_len = strlen(ip);
@ -720,17 +720,17 @@ static inline const char *format_ip_address(const char *ip, char *buff)
p += ip_len;
*p++ = ']';
*p = '\0';
return p - buff;
}
else
{
strcpy(buff, ip);
ip_len = strlen(ip);
memcpy(buff, ip, ip_len + 1);
return ip_len;
}
return buff;
}
static inline const char *format_ip_port(const char *ip,
const int port, char *buff)
static inline int format_ip_port(const char *ip, const int port, char *buff)
{
int ip_len;
bool is_ipv6;
@ -753,7 +753,7 @@ static inline const char *format_ip_port(const char *ip,
p += fc_itoa(port, p);
*p = '\0';
return buff;
return p - buff;
}
void tcp_set_try_again_when_interrupt(const bool value);

View File

@ -118,12 +118,13 @@ int get_sys_cpu_count()
int get_boot_time(struct timeval *boot_time)
{
#ifdef OS_LINUX
const int64_t offset = 0;
char buff[256];
int64_t bytes;
struct sysinfo si;
bytes = sizeof(buff);
if (getFileContentEx("/proc/uptime", buff, 0, &bytes) == 0)
if (getFileContentEx("/proc/uptime", buff, offset, &bytes) == 0)
{
double uptime;
double btime;
@ -621,6 +622,7 @@ static void parse_proc_stat(char *buff, const int len,
int get_processes(struct fast_process_info **processes, int *count)
{
const int64_t offset = 0;
const char *dirname = "/proc";
char filename[128];
char buff[4096];
@ -679,7 +681,7 @@ int get_processes(struct fast_process_info **processes, int *count)
sprintf(filename, "%s/%s/stat", dirname, ent->d_name);
bytes = sizeof(buff);
if (getFileContentEx(filename, buff, 0, &bytes) != 0)
if (getFileContentEx(filename, buff, offset, &bytes) != 0)
{
continue;
}
@ -960,33 +962,16 @@ int get_sysinfo(struct fast_sysinfo *info)
int get_kernel_version(Version *version)
{
struct utsname name;
char *p;
int numbers[2];
int i;
if (uname(&name) < 0)
{
logError("file: "__FILE__", line: %d, "
"call uname fail, errno: %d, error info: %s",
__LINE__, errno, STRERROR(errno));
logError("file: "__FILE__", line: %d, "
"call uname fail, errno: %d, error info: %s",
__LINE__, errno, STRERROR(errno));
return errno != 0 ? errno : EFAULT;
}
numbers[0] = numbers[1] = 0;
p = name.release;
for (i=0; i<2; i++) {
p = strchr(p, '.');
if (p == NULL) {
break;
}
p++;
numbers[i] = strtol(p, NULL, 10);
}
version->major = strtol(name.release, NULL, 10);
version->minor = numbers[0];
version->patch = numbers[1];
fc_parse_version(name.release, version);
return 0;
}