keepalived源码解析 —— parser.c

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值