1 /*
2  * Copyright (c) 2015-2017 Red Hat, Inc.
3  *
4  * All rights reserved.
5  *
6  * Author: Jan Friesse (jfriesse@redhat.com)
7  *
8  * This software licensed under BSD license, the text of which follows:
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  *
13  * - Redistributions of source code must retain the above copyright notice,
14  *   this list of conditions and the following disclaimer.
15  * - Redistributions in binary form must reproduce the above copyright notice,
16  *   this list of conditions and the following disclaimer in the documentation
17  *   and/or other materials provided with the distribution.
18  * - Neither the name of the Red Hat, Inc. nor the names of its
19  *   contributors may be used to endorse or promote products derived from this
20  *   software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32  * THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <inttypes.h>
36 #include <stdlib.h>
37 #include <string.h>
38 
39 #include "qdevice-heuristics-exec-list.h"
40 
41 void
qdevice_heuristics_exec_list_init(struct qdevice_heuristics_exec_list * list)42 qdevice_heuristics_exec_list_init(struct qdevice_heuristics_exec_list *list)
43 {
44 
45 	TAILQ_INIT(list);
46 }
47 
48 struct qdevice_heuristics_exec_list_entry *
qdevice_heuristics_exec_list_add(struct qdevice_heuristics_exec_list * list,char * name,char * command)49 qdevice_heuristics_exec_list_add(struct qdevice_heuristics_exec_list *list,
50     char *name, char *command)
51 {
52 	struct qdevice_heuristics_exec_list_entry *entry;
53 
54 	entry = (struct qdevice_heuristics_exec_list_entry *)malloc(sizeof(*entry));
55 	if (entry == NULL) {
56 		return (NULL);
57 	}
58 
59 	memset(entry, 0, sizeof(*entry));
60 
61 	entry->name = strdup(name);
62 	if (entry->name == NULL) {
63 		free(entry);
64 
65 		return (NULL);
66 	}
67 
68 	entry->command = strdup(command);
69 	if (entry->command == NULL) {
70 		free(entry->name);
71 		free(entry);
72 
73 		return (NULL);
74 	}
75 
76 	TAILQ_INSERT_TAIL(list, entry, entries);
77 
78 	return (entry);
79 }
80 
81 void
qdevice_heuristics_exec_list_free(struct qdevice_heuristics_exec_list * list)82 qdevice_heuristics_exec_list_free(struct qdevice_heuristics_exec_list *list)
83 {
84 	struct qdevice_heuristics_exec_list_entry *entry;
85 	struct qdevice_heuristics_exec_list_entry *entry_next;
86 
87 	entry = TAILQ_FIRST(list);
88 
89 	while (entry != NULL) {
90 		entry_next = TAILQ_NEXT(entry, entries);
91 
92 		free(entry->name);
93 		free(entry->command);
94 		free(entry);
95 
96 		entry = entry_next;
97 	}
98 
99 	TAILQ_INIT(list);
100 }
101 
102 size_t
qdevice_heuristics_exec_list_size(const struct qdevice_heuristics_exec_list * list)103 qdevice_heuristics_exec_list_size(const struct qdevice_heuristics_exec_list *list)
104 {
105 	struct qdevice_heuristics_exec_list_entry *entry;
106 	size_t res;
107 
108 	res = 0;
109 
110 	TAILQ_FOREACH(entry, list, entries) {
111 		res++;
112 	}
113 
114 	return (res);
115 }
116 
117 int
qdevice_heuristics_exec_list_clone(struct qdevice_heuristics_exec_list * dst_list,const struct qdevice_heuristics_exec_list * src_list)118 qdevice_heuristics_exec_list_clone(struct qdevice_heuristics_exec_list *dst_list,
119     const struct qdevice_heuristics_exec_list *src_list)
120 {
121 	struct qdevice_heuristics_exec_list_entry *entry;
122 
123 	qdevice_heuristics_exec_list_init(dst_list);
124 
125 	TAILQ_FOREACH(entry, src_list, entries) {
126 		if (qdevice_heuristics_exec_list_add(dst_list, entry->name, entry->command) == NULL) {
127 			qdevice_heuristics_exec_list_free(dst_list);
128 
129 			return (-1);
130 		}
131 	}
132 
133 	return (0);
134 }
135 
136 void
qdevice_heuristics_exec_list_del(struct qdevice_heuristics_exec_list * list,struct qdevice_heuristics_exec_list_entry * entry)137 qdevice_heuristics_exec_list_del(struct qdevice_heuristics_exec_list *list,
138     struct qdevice_heuristics_exec_list_entry *entry)
139 {
140 
141 	TAILQ_REMOVE(list, entry, entries);
142 
143 	free(entry->name);
144 	free(entry->command);
145 	free(entry);
146 }
147 
148 int
qdevice_heuristics_exec_list_is_empty(const struct qdevice_heuristics_exec_list * list)149 qdevice_heuristics_exec_list_is_empty(const struct qdevice_heuristics_exec_list *list)
150 {
151 
152 	return (TAILQ_EMPTY(list));
153 }
154 
155 struct qdevice_heuristics_exec_list_entry *
qdevice_heuristics_exec_list_find_name(const struct qdevice_heuristics_exec_list * list,const char * name)156 qdevice_heuristics_exec_list_find_name(const struct qdevice_heuristics_exec_list *list,
157     const char *name)
158 {
159 	struct qdevice_heuristics_exec_list_entry *entry;
160 
161 	TAILQ_FOREACH(entry, list, entries) {
162 		if (strcmp(entry->name, name) == 0) {
163 			return (entry);
164 		}
165 	}
166 
167 	return (NULL);
168 }
169 
170 int
qdevice_heuristics_exec_list_eq(const struct qdevice_heuristics_exec_list * list1,const struct qdevice_heuristics_exec_list * list2)171 qdevice_heuristics_exec_list_eq(const struct qdevice_heuristics_exec_list *list1,
172     const struct qdevice_heuristics_exec_list *list2)
173 {
174 	struct qdevice_heuristics_exec_list_entry *entry1;
175 	struct qdevice_heuristics_exec_list_entry *entry2;
176 	struct qdevice_heuristics_exec_list tmp_list;
177 	int res;
178 
179 	res = 1;
180 
181 	if (qdevice_heuristics_exec_list_clone(&tmp_list, list2) != 0) {
182 		return (-1);
183 	}
184 
185 	TAILQ_FOREACH(entry1, list1, entries) {
186 		entry2 = qdevice_heuristics_exec_list_find_name(&tmp_list, entry1->name);
187 		if (entry2 == NULL) {
188 			res = 0;
189 			goto return_res;
190 		}
191 
192 		if (strcmp(entry1->command, entry2->command) != 0) {
193 			res = 0;
194 			goto return_res;
195 		}
196 
197 		qdevice_heuristics_exec_list_del(&tmp_list, entry2);
198 	}
199 
200 	if (!qdevice_heuristics_exec_list_is_empty(&tmp_list)) {
201 		res = 0;
202 		goto return_res;
203 	}
204 
205 return_res:
206 	qdevice_heuristics_exec_list_free(&tmp_list);
207 
208 	return (res);
209 }
210