1、strspn 与 strcspn:
size_t strspn(const char *str1, const char *str2):查找 str1 中第一个不出现在 str2 的字符的下标。
size_t strcspn(const char *s, const char * reject):从字符串 s 的第一个字符开始,计算连续多少个字符不在 reject 所指的字符串中。返回值:连续字符的个数
2、strdup 与 strndupa:
char *strdup(const char *s):返回一个指向 s 副本的指针,这个副本内存是由 malloc 分配,使用完之后,需要使用 free() 释放内存。
char *strndupa(const char *s, size_t n):与 strdup() 类似,但是最多拷贝 n 个字节,若 s 的长度大于 n,则复制 n 个字节,并在末尾添加 ‘\0’
3、void memmove( void dest, const void* src, size_t count ):
拷贝字节
若目标区域与源区域没有重叠,则和memcpy函数功能相同
若目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,但复制后源内容会被更改。
4、int glob(const char *pattern, int flags, int errfunc(const char *epath, int eerrno), glob_t *pglob)
头文件:glob.h
功能:用于 Linux 文件系统中,查找匹配指定模式的目录或文件名。
参数:
pattern:匹配模式
flags:
GLOB_MARK:在每个返回的项目中加一个斜线
GLOB_NOSORT:按照文件在目录中出现的原始顺序返回(不排序)
GLOB_NOCHECK:如果没有文件匹配则返回用于搜索的模式
GLOB_NOESCAPE:反斜线不转义元字符
GLOB_BRACE:扩充 {a,b,c} 来匹配 ‘a’,‘b’ 或 ‘c’
GLOB_ONLYDIR:仅返回与模式匹配的目录项
GLOB_ERR:停止并读取错误信息(比如说不可读的目录),默认的情况下忽略所有错误
errfunc:查看错误信息用,一般置为NULL
pglob:返回包含所有匹配项的数组
返回值:
0:查找到响应匹配项
GLOB_NOMATCH:未找到匹配项
其他:查找出错
5、void globfree(glob_t *pglob)
释放 glob() 产生的动态内存
static bool
read_conf_file(const char *conf_file)
{
FILE *stream;
glob_t globbuf;
size_t i;
int res;
struct stat stb;
unsigned num_matches = 0;
globbuf.gl_offs = 0;
/* 查找满足匹配项的目录或文件名 */
res = glob(conf_file, GLOB_MARK
#if HAVE_DECL_GLOB_BRACE
| GLOB_BRACE
#endif
, NULL, &globbuf);
if (res) {
if (res == GLOB_NOMATCH)
log_message(LOG_INFO, "No config files matched '%s'.", conf_file);
else
log_message(LOG_INFO, "Error reading config file(s): glob(\"%s\") returned %d, skipping.", conf_file, res);
return true;
}
/* 遍历所有匹配项 */
for (i = 0; i < globbuf.gl_pathc; i++) {
if (globbuf.gl_pathv[i][strlen(globbuf.gl_pathv[i])-1] == '/') {
/* This is a directory - so skip */
continue;
}
log_message(LOG_INFO, "Opening file '%s'.", globbuf.gl_pathv[i]);
stream = fopen(globbuf.gl_pathv[i], "r");
if (!stream) {
log_message(LOG_INFO, "Configuration file '%s' open problem (%s) - skipping"
, globbuf.gl_pathv[i], strerror(errno));
continue;
}
/* Make sure what we have opened is a regular file, and not for example a directory or executable */
if (fstat(fileno(stream), &stb) ||
!S_ISREG(stb.st_mode) ||
(stb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
log_message(LOG_INFO, "Configuration file '%s' is not a regular non-executable file - skipping", globbuf.gl_pathv[i]);
fclose(stream);
continue;
}
num_matches++;
current_stream = stream;
/* We only want to report the file name if there is more than one file used */
if (current_file_name || globbuf.gl_pathc > 1)
current_file_name = globbuf.gl_pathv[i];
current_file_line_no = 0;
int curdir_fd = -1;
if (strchr(globbuf.gl_pathv[i], '/')) {
/* If the filename contains a directory element, change to that directory.
The man page open(2) states that fchdir() didn't support O_PATH until Linux 3.5,
even though testing on Linux 3.1 shows it appears to work. To be safe, don't
use it until Linux 3.5. */
/* 打开当前目录 */
curdir_fd = open(".", O_RDONLY | O_DIRECTORY
#if HAVE_DECL_O_PATH && LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
| O_PATH
#endif
);
/* 复制字符串 */
char *confpath = strdup(globbuf.gl_pathv[i]);
/* 返回路径部分 */
dirname(confpath);
/* 切换目录 */
if (chdir(confpath) < 0)
log_message(LOG_INFO, "chdir(%s) error (%s)", confpath, strerror(errno));
free(confpath);
}
/* 读取配置文件 */
process_stream(current_keywords, 0);
fclose(stream);
free_list(&seq_list);
/* If we changed directory, restore the previous directory */
if (curdir_fd != -1) {
if ((res = fchdir(curdir_fd)))
log_message(LOG_INFO, "Failed to restore previous directory after include");
close(curdir_fd);
if (res)
return true;
}
}
globfree(&globbuf);
if (!num_matches)
log_message(LOG_INFO, "No config files matched '%s'.", conf_file);
return false;
}
vector_t *
alloc_strvec_r(const char *string)
{
const char *cp, *start;
size_t str_len;
vector_t *strvec;
if (!string)
return NULL;
/* 创建 vector */
strvec = vector_alloc();
cp = string;
while (true) {
/*
size_t strspn(const char *str1, const char *str2):
查找 str1 中第一个不出现在 str2 的字符的下标
*/
cp += strspn(cp, WHITE_SPACE);
if (!*cp)
break;
start = cp;
/* Save a quoted string without the ""s as a single string */
if (*start == '"') {
start++;
if (!(cp = strchr(start, '"'))) {
report_config_error(CONFIG_UNMATCHED_QUOTE, "Unmatched quote: '%s'", string);
break;
}
str_len = (size_t)(cp - start);
cp++;
} else {
/*
size_t strcspn(const char *s, const char * reject):
从字符串 s 的第一个字符开始,计算连续多少个字符不在 reject 所指的字符串中。
返回值:连续字符的个数
*/
cp += strcspn(start, WHITE_SPACE_STR "\"");
str_len = (size_t)(cp - start);
}
/* 新增一个节点 */
vector_alloc_slot(strvec);
/*
char *strdup(const char *s):
返回一个指向 s 副本的指针,这个副本内存是由 malloc 分配,使用完之后,需要使用 free() 释放内存。
char *strndupa(const char *s, size_t n):
与 strdup() 类似,但是最多拷贝 n 个字节,若 s 的长度大于 n,则复制 n 个字节,并在末尾添加 '\0'
*/
/* 从 start 复制 str_len 个字节,存储到 strvec 最后一个节点 */
vector_set_slot(strvec, STRNDUP(start, str_len));
}
if (!vector_size(strvec)) {
free_strvec(strvec);
return NULL;
}
return strvec;
}