brintos

brintos / linux-shallow public Read only

0
0
Text · 4.2 KiB · 8a868cb Raw
209 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com>4 */5 6#include "strlist.h"7#include <errno.h>8#include <stdio.h>9#include <stdlib.h>10#include <string.h>11#include <unistd.h>12#include <linux/zalloc.h>13 14static15struct rb_node *strlist__node_new(struct rblist *rblist, const void *entry)16{17	const char *s = entry;18	struct rb_node *rc = NULL;19	struct strlist *strlist = container_of(rblist, struct strlist, rblist);20	struct str_node *snode = malloc(sizeof(*snode));21 22	if (snode != NULL) {23		if (strlist->dupstr) {24			s = strdup(s);25			if (s == NULL)26				goto out_delete;27		}28		snode->s = s;29		rc = &snode->rb_node;30	}31 32	return rc;33 34out_delete:35	free(snode);36	return NULL;37}38 39static void str_node__delete(struct str_node *snode, bool dupstr)40{41	if (dupstr)42		zfree((char **)&snode->s);43	free(snode);44}45 46static47void strlist__node_delete(struct rblist *rblist, struct rb_node *rb_node)48{49	struct strlist *slist = container_of(rblist, struct strlist, rblist);50	struct str_node *snode = container_of(rb_node, struct str_node, rb_node);51 52	str_node__delete(snode, slist->dupstr);53}54 55static int strlist__node_cmp(struct rb_node *rb_node, const void *entry)56{57	const char *str = entry;58	struct str_node *snode = container_of(rb_node, struct str_node, rb_node);59 60	return strcmp(snode->s, str);61}62 63int strlist__add(struct strlist *slist, const char *new_entry)64{65	return rblist__add_node(&slist->rblist, new_entry);66}67 68int strlist__load(struct strlist *slist, const char *filename)69{70	char entry[1024];71	int err;72	FILE *fp = fopen(filename, "r");73 74	if (fp == NULL)75		return -errno;76 77	while (fgets(entry, sizeof(entry), fp) != NULL) {78		const size_t len = strlen(entry);79 80		if (len == 0)81			continue;82		entry[len - 1] = '\0';83 84		err = strlist__add(slist, entry);85		if (err != 0)86			goto out;87	}88 89	err = 0;90out:91	fclose(fp);92	return err;93}94 95void strlist__remove(struct strlist *slist, struct str_node *snode)96{97	rblist__remove_node(&slist->rblist, &snode->rb_node);98}99 100struct str_node *strlist__find(struct strlist *slist, const char *entry)101{102	struct str_node *snode = NULL;103	struct rb_node *rb_node = rblist__find(&slist->rblist, entry);104 105	if (rb_node)106		snode = container_of(rb_node, struct str_node, rb_node);107 108	return snode;109}110 111static int strlist__parse_list_entry(struct strlist *slist, const char *s,112				     const char *subst_dir)113{114	int err;115	char *subst = NULL;116 117	if (strncmp(s, "file://", 7) == 0)118		return strlist__load(slist, s + 7);119 120	if (subst_dir) {121		err = -ENOMEM;122		if (asprintf(&subst, "%s/%s", subst_dir, s) < 0)123			goto out;124 125		if (access(subst, F_OK) == 0) {126			err = strlist__load(slist, subst);127			goto out;128		}129 130		if (slist->file_only) {131			err = -ENOENT;132			goto out;133		}134	}135 136	err = strlist__add(slist, s);137out:138	free(subst);139	return err;140}141 142static int strlist__parse_list(struct strlist *slist, const char *s, const char *subst_dir)143{144	char *sep;145	int err;146 147	while ((sep = strchr(s, ',')) != NULL) {148		*sep = '\0';149		err = strlist__parse_list_entry(slist, s, subst_dir);150		*sep = ',';151		if (err != 0)152			return err;153		s = sep + 1;154	}155 156	return *s ? strlist__parse_list_entry(slist, s, subst_dir) : 0;157}158 159struct strlist *strlist__new(const char *list, const struct strlist_config *config)160{161	struct strlist *slist = malloc(sizeof(*slist));162 163	if (slist != NULL) {164		bool dupstr = true;165		bool file_only = false;166		const char *dirname = NULL;167 168		if (config) {169			dupstr = !config->dont_dupstr;170			dirname = config->dirname;171			file_only = config->file_only;172		}173 174		rblist__init(&slist->rblist);175		slist->rblist.node_cmp    = strlist__node_cmp;176		slist->rblist.node_new    = strlist__node_new;177		slist->rblist.node_delete = strlist__node_delete;178 179		slist->dupstr	 = dupstr;180		slist->file_only = file_only;181 182		if (list && strlist__parse_list(slist, list, dirname) != 0)183			goto out_error;184	}185 186	return slist;187out_error:188	free(slist);189	return NULL;190}191 192void strlist__delete(struct strlist *slist)193{194	if (slist != NULL)195		rblist__delete(&slist->rblist);196}197 198struct str_node *strlist__entry(const struct strlist *slist, unsigned int idx)199{200	struct str_node *snode = NULL;201	struct rb_node *rb_node;202 203	rb_node = rblist__entry(&slist->rblist, idx);204	if (rb_node)205		snode = container_of(rb_node, struct str_node, rb_node);206 207	return snode;208}209