source: src/router/proftpd/src/sets.c @ 17876

Last change on this file since 17876 was 17876, checked in by BrainSlayer, 19 months ago

update proftp

File size: 5.5 KB
Line 
1/*
2 * ProFTPD - FTP server daemon
3 * Copyright (c) 1997, 1998 Public Flood Software
4 * Copyright (c) 2001-2008 The ProFTPD Project team
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
19 *
20 * As a special exemption, Public Flood Software/MacGyver aka Habeeb J. Dihu
21 * and other respective copyright holders give permission to link this program
22 * with OpenSSL, and distribute the resulting executable, without including
23 * the source code for OpenSSL in the source distribution.
24 */
25
26/* Generic set manipulation
27 * $Id: sets.c,v 1.16 2011/05/23 21:22:24 castaglia Exp $
28 */
29
30#include "conf.h"
31
32/* Create a new set, cmpfunc is a pointer to the function used to to compare
33 * members of the set ... it should return 1, 0, or -1 after the fashion of
34 * strcmp.  Returns NULL if memory allocation fails.
35 */
36
37xaset_t *xaset_create(pool *p, XASET_COMPARE cmpfunc) {
38  xaset_t *new_set;
39
40  if (p == NULL &&
41      permanent_pool == NULL) {
42    errno = EPERM;
43    return NULL;
44  }
45
46  p = p ? p : permanent_pool;
47
48  new_set = palloc(p, sizeof(xaset_t));
49
50  if (!new_set)
51    return NULL;
52
53  new_set->xas_list = NULL;
54  new_set->pool = p;
55  new_set->xas_compare = cmpfunc;
56
57  return new_set;
58}
59
60/* Inserts a new member into an existing set.  The member is inserted
61 * at the beginning of the set.  Returns 0 if successful, -1 otherwise (with
62 * errno set appropriately).
63 */
64int xaset_insert(xaset_t *set, xasetmember_t *member) {
65
66  if (set == NULL ||
67      member == NULL) {
68    errno = EINVAL;
69    return -1;
70  }
71
72  member->next = set->xas_list;
73
74  if (set->xas_list)
75    set->xas_list->prev = member;
76
77  set->xas_list = member;
78  return 0;
79}
80
81/* Inserts a new member into an existing set at the end of the list.
82 */
83int xaset_insert_end(xaset_t *set, xasetmember_t *member) {
84  xasetmember_t **tmp, *prev = NULL;
85
86  if (set == NULL ||
87      member == NULL) {
88    errno = EINVAL;
89    return -1;
90  }
91
92  for (tmp = &set->xas_list; *tmp; prev = *tmp, tmp = &(*tmp)->next)
93    ;
94
95  *tmp = member;
96  member->prev = prev;
97  member->next = NULL;
98
99  if (prev)
100    prev->next = member;
101
102  return 0;
103}
104
105/* Inserts a new member into an existing set, sorted using the set's compare
106 * callback.  If dups_allowed is non-0, returns 0 and the member is not added
107 * to the set.  Otherwise, it is added immediately before the first duplicate.
108 * If the set is not empty and not pre-sorted, results are undefined.
109 * Returns 0 if successful, -1 otherwise (with errno set appropriately).
110 */
111int xaset_insert_sort(xaset_t *set, xasetmember_t *member, int dups_allowed) {
112  xasetmember_t **setp = NULL, *mprev = NULL;
113
114  if (!set || !member || !set->xas_compare) {
115    errno = EINVAL;
116    return -1;
117  }
118
119  for (setp = &set->xas_list; *setp; setp = &(*setp)->next) {
120    int res;
121
122    res = set->xas_compare(member, *setp);
123    if (res <= 0) {
124      if (res == 0 &&
125          !dups_allowed)
126        return 0;
127      break;
128    }
129
130    mprev = *setp;
131  }
132
133  if (*setp)
134    (*setp)->prev = member;
135
136  member->prev = mprev;
137  member->next = *setp;
138  *setp = member;
139
140  return 0;
141}
142
143/* Remove a member from a set.  The set need not be sorted.  Note that this
144 * does NOT free the memory used by the member.  Returns 0 if successful,
145 * and -1 if there was a problem (with errno set appropriately).
146 */
147int xaset_remove(xaset_t *set, xasetmember_t *member) {
148  xasetmember_t *m = NULL;
149
150  if (set == NULL ||
151      member == NULL) {
152    errno = EINVAL;
153    return -1;
154  }
155
156  /* Check if member is actually a member of set. */
157  for (m = set->xas_list; m; m = m->next) {
158    if (m == member)
159      break;
160  }
161
162  if (m == NULL) {
163    errno = ENOENT;
164    return -1; 
165  }
166
167  if (member->prev)
168    member->prev->next = member->next;
169
170  else /* assume that member is first in the list */
171    set->xas_list = member->next;
172
173  if (member->next)
174    member->next->prev = member->prev;
175
176  member->next = member->prev = NULL;
177  return 0;
178}
179
180/* Perform an exact copy of the entire set, returning the new set.  msize
181 * specifies the size of each member.  If copyfunc is non-NULL, it is called
182 * instead to copy each member.  Returns NULL if out of memory condition
183 * occurs.
184 */
185xaset_t *xaset_copy(pool *p, xaset_t *set, size_t msize, XASET_MCOPY copyfunc) {
186  xaset_t *new_set;
187  xasetmember_t *n, *m, **pos;
188
189  if (set == NULL) {
190    errno = EINVAL;
191    return NULL;
192  }
193
194  if (!copyfunc && !msize) {
195    errno = EINVAL;
196    return NULL;
197  }
198
199  p = (p ? p : set->pool);
200
201  new_set = xaset_create(p, set->xas_compare);
202  if (new_set == NULL)
203    return NULL;
204
205  pos = &new_set->xas_list;
206
207  /* NOTE: xaset_insert_sort is not used here for performance reasons. */
208
209  for (m = set->xas_list; m; m = m->next) {
210    n = copyfunc ? copyfunc(m) : (xasetmember_t *) palloc(p, msize);
211    if (!n)
212      return NULL;                      /* Could clean up here */
213
214    if (!copyfunc)
215      memcpy(n, m, msize);
216
217    /* Create links */
218    n->prev = *pos;
219    n->next = NULL;
220    if (*pos)
221      pos = &(*pos)->next;
222    *pos = n;
223  }
224
225  return new_set;
226}
Note: See TracBrowser for help on using the repository browser.