commit 6f31da9325d09fac22a67a8a2b6b32ca04d1b996
parent 7dcf2a44ceb7b9792c7b60e20fc69a933ea85894
Author: sin <sin@2f30.org>
Date: Tue, 24 Jun 2014 13:49:52 +0100
Import queue.h and use it
Diffstat:
M | db.c | | | 109 | ++++++++++++++++++++++++++++++------------------------------------------------- |
M | db.h | | | 15 | +++++++-------- |
M | infopkg.c | | | 2 | +- |
A | queue.h | | | 574 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | removepkg.c | | | 1 | + |
5 files changed, 624 insertions(+), 77 deletions(-)
diff --git a/db.c b/db.c
@@ -24,8 +24,8 @@ struct db {
DIR *pkgdir;
char prefix[PATH_MAX];
char path[PATH_MAX];
- struct rejrule *rejrules;
- struct pkg *head;
+ TAILQ_HEAD(rejrule_head, rejrule) rejrule_head;
+ TAILQ_HEAD(pkg_head, pkg) pkg_head;
};
int fflag = 0;
@@ -39,7 +39,7 @@ db_new(const char *prefix)
struct sigaction sa;
db = emalloc(sizeof(*db));
- db->head = NULL;
+ TAILQ_INIT(&db->pkg_head);
if (!realpath(prefix, db->prefix)) {
weprintf("realpath %s:", prefix);
@@ -57,7 +57,8 @@ db_new(const char *prefix)
return NULL;
}
- db->rejrules = rej_load(db->prefix);
+ TAILQ_INIT(&db->rejrule_head);
+ rej_load(db);
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_IGN;
@@ -75,14 +76,12 @@ db_free(struct db *db)
{
struct pkg *pkg, *tmp;
- pkg = db->head;
- while (pkg) {
- tmp = pkg->next;
+ for (pkg = TAILQ_FIRST(&db->pkg_head); pkg; pkg = tmp) {
+ tmp = TAILQ_NEXT(pkg, entry);
pkg_free(pkg);
- pkg = tmp;
}
closedir(db->pkgdir);
- rej_free(db->rejrules);
+ rej_free(db);
free(db);
return 0;
}
@@ -113,7 +112,7 @@ db_add(struct db *db, struct pkg *pkg)
return -1;
}
- for (pe = pkg->head; pe; pe = pe->next) {
+ TAILQ_FOREACH(pe, &pkg->pe_head, entry) {
if (vflag == 1)
printf("installed %s\n", pe->path);
fputs(pe->rpath, fp);
@@ -134,8 +133,6 @@ db_add(struct db *db, struct pkg *pkg)
int
db_rm(struct pkg *pkg)
{
- if (pkg->deleted == 0)
- return -1;
if (vflag == 1)
printf("removing %s\n", pkg->path);
if (remove(pkg->path) < 0) {
@@ -160,8 +157,7 @@ db_load(struct db *db)
pkg = pkg_load(db, dp->d_name);
if (!pkg)
return -1;
- pkg->next = db->head;
- db->head = pkg;
+ TAILQ_INSERT_TAIL(&db->pkg_head, pkg, entry);
}
return 0;
@@ -174,9 +170,7 @@ db_walk(struct db *db, int (*cb)(struct db *, struct pkg *, void *), void *data)
struct pkg *pkg;
int r;
- for (pkg = db->head; pkg; pkg = pkg->next) {
- if (pkg->deleted == 1)
- continue;
+ TAILQ_FOREACH(pkg, &db->pkg_head, entry) {
r = cb(db, pkg, data);
if (r < 0)
return -1;
@@ -195,13 +189,10 @@ db_links(struct db *db, const char *path)
struct pkgentry *pe;
int links = 0;
- for (pkg = db->head; pkg; pkg = pkg->next) {
- if (pkg->deleted == 1)
- continue;
- for (pe = pkg->head; pe; pe = pe->next)
+ TAILQ_FOREACH(pkg, &db->pkg_head, entry)
+ TAILQ_FOREACH(pe, &pkg->pe_head, entry)
if (strcmp(pe->path, path) == 0)
links++;
- }
return links;
}
@@ -260,8 +251,7 @@ pkg_load(struct db *db, const char *filename)
if(!realpath(path, pe->path))
estrlcpy(pe->path, path, sizeof(pe->path));
estrlcpy(pe->rpath, buf, sizeof(pe->rpath));
- pe->next = pkg->head;
- pkg->head = pe;
+ TAILQ_INSERT_TAIL(&pkg->pe_head, pe, entry);
}
free(buf);
if (ferror(fp)) {
@@ -330,8 +320,7 @@ pkg_load_file(struct db *db, const char *filename)
estrlcpy(pe->path, path, sizeof(pe->path));
estrlcpy(pe->rpath, archive_entry_pathname(entry),
sizeof(pe->rpath));
- pe->next = pkg->head;
- pkg->head = pe;
+ TAILQ_INSERT_TAIL(&pkg->pe_head, pe, entry);
}
archive_read_free(ar);
@@ -427,10 +416,7 @@ pkg_remove(struct db *db, struct pkg *pkg)
struct pkgentry *pe;
struct stat sb;
- if (pkg->deleted == 1)
- return 0;
-
- for (pe = pkg->head; pe; pe = pe->next) {
+ TAILQ_FOREACH_REVERSE(pe, &pkg->pe_head, pe_head, entry) {
if (rej_match(db, pe->rpath) > 0) {
weprintf("rejecting %s\n", pe->rpath);
continue;
@@ -457,15 +443,13 @@ pkg_remove(struct db *db, struct pkg *pkg)
if (vflag == 1)
printf("removing %s\n", pe->path);
- if (remove(pe->path) < 0) {
+ if (remove(pe->path) < 0)
weprintf("remove %s:", pe->path);
- continue;
- }
}
if (fflag == 1) {
/* prune empty directories as well */
- for (pe = pkg->head; pe; pe = pe->next) {
+ TAILQ_FOREACH_REVERSE(pe, &pkg->pe_head, pe_head, entry) {
if (rej_match(db, pe->rpath) > 0)
continue;
if (db_links(db, pe->path) > 1)
@@ -474,7 +458,7 @@ pkg_remove(struct db *db, struct pkg *pkg)
}
}
- pkg->deleted = 1;
+ TAILQ_REMOVE(&db->pkg_head, pkg, entry);
return 0;
}
@@ -489,7 +473,7 @@ pkg_collisions(struct pkg *pkg)
struct stat sb;
int ok = 0;
- for (pe = pkg->head; pe; pe = pe->next) {
+ TAILQ_FOREACH(pe, &pkg->pe_head, entry) {
if (access(pe->path, F_OK) == 0) {
if (stat(pe->path, &sb) < 0) {
weprintf("lstat %s:", pe->path);
@@ -521,9 +505,7 @@ pkg_new(const char *path, const char *name, const char *version)
else
pkg->version = NULL;
estrlcpy(pkg->path, path, sizeof(pkg->path));
- pkg->deleted = 0;
- pkg->head = NULL;
- pkg->next = NULL;
+ TAILQ_INIT(&pkg->pe_head);
return pkg;
}
@@ -533,11 +515,9 @@ pkg_free(struct pkg *pkg)
{
struct pkgentry *pe, *tmp;
- pe = pkg->head;
- while (pe) {
- tmp = pe->next;
+ for (pe = TAILQ_FIRST(&pkg->pe_head); pe; pe = tmp) {
+ tmp = TAILQ_NEXT(pe, entry);
free(pe);
- pe = tmp;
}
free(pkg->name);
free(pkg->version);
@@ -609,23 +589,22 @@ err:
/* Release the pre-loaded regexes */
void
-rej_free(struct rejrule *list)
+rej_free(struct db *db)
{
struct rejrule *rule, *tmp;
- rule = list;
- while(rule) {
- tmp = rule->next;
- regfree(&(rule->preg));
+
+ for (rule = TAILQ_FIRST(&db->rejrule_head); rule; rule = tmp) {
+ tmp = TAILQ_NEXT(rule, entry);
+ regfree(&rule->preg);
free(rule);
- rule = tmp;
}
}
/* Parse reject.conf and pre-compute regexes */
-struct rejrule *
-rej_load(const char *prefix)
+int
+rej_load(struct db *db)
{
- struct rejrule *rule, *next, *list = NULL;
+ struct rejrule *rule;
char rejpath[PATH_MAX];
FILE *fp;
char *buf = NULL;
@@ -633,11 +612,11 @@ rej_load(const char *prefix)
ssize_t len;
int r;
- estrlcpy(rejpath, prefix, sizeof(rejpath));
+ estrlcpy(rejpath, db->prefix, sizeof(rejpath));
estrlcat(rejpath, DBPATHREJECT, sizeof(rejpath));
if (!(fp = fopen(rejpath, "r")))
- return NULL;
+ return -1;
while ((len = getline(&buf, &sz, fp)) != -1) {
if (!len || buf[0] == '#' || buf[0] == '\n')
@@ -647,7 +626,6 @@ rej_load(const char *prefix)
/* copy and add regex */
rule = emalloc(sizeof(*rule));
- rule->next = NULL;
r = regcomp(&(rule->preg), buf, REG_NOSUB | REG_EXTENDED);
if (r != 0) {
@@ -655,27 +633,22 @@ rej_load(const char *prefix)
weprintf("invalid pattern: %s\n", buf);
free(buf);
fclose(fp);
- rej_free(list);
- return NULL;
+ rej_free(db);
+ return -1;
}
- /* append to list: first item? or append to previous rule */
- if (!list)
- list = next = rule;
- else
- next->next = rule;
- next = rule;
+ TAILQ_INSERT_TAIL(&db->rejrule_head, rule, entry);
}
free(buf);
if (ferror(fp)) {
weprintf("%s: read error:", rejpath);
fclose(fp);
- rej_free(list);
- return NULL;
+ rej_free(db);
+ return -1;
}
fclose(fp);
- return list;
+ return 0;
}
/* Match pre-computed regexes against the given filename */
@@ -688,8 +661,8 @@ rej_match(struct db *db, const char *file)
if (strncmp(file, "./", 2) == 0)
file++;
- for(rule = db->rejrules; rule; rule = rule->next) {
- if (regexec(&(rule->preg), file, 0, NULL, 0) != REG_NOMATCH)
+ TAILQ_FOREACH(rule, &db->rejrule_head, entry) {
+ if (regexec(&rule->preg, file, 0, NULL, 0) != REG_NOMATCH)
return 1;
}
diff --git a/db.h b/db.h
@@ -2,27 +2,27 @@
#include <regex.h>
#include <sys/types.h>
+#include "queue.h"
struct pkgentry {
/* full path */
char path[PATH_MAX];
/* relative path */
char rpath[PATH_MAX];
- struct pkgentry *next;
+ TAILQ_ENTRY(pkgentry) entry;
};
struct rejrule {
regex_t preg;
- struct rejrule *next;
+ TAILQ_ENTRY(rejrule) entry;
};
struct pkg {
char *name;
char *version;
char path[PATH_MAX];
- int deleted;
- struct pkgentry *head;
- struct pkg *next;
+ TAILQ_HEAD(pe_head, pkgentry) pe_head;
+ TAILQ_ENTRY(pkg) entry;
};
extern int fflag;
@@ -47,7 +47,6 @@ void pkg_free(struct pkg *);
void parse_version(const char *, char **);
void parse_name(const char *, char **);
-void rej_free(struct rejrule *);
-struct rejrule * rej_load(const char *);
+void rej_free(struct db *);
+int rej_load(struct db *);
int rej_match(struct db *, const char *);
-struct rejrule * rej_load(const char *);
diff --git a/infopkg.c b/infopkg.c
@@ -83,7 +83,7 @@ own_pkg_cb(struct db *db, struct pkg *pkg, void *file)
if (lstat(path, &sb1) < 0)
eprintf("lstat %s:", path);
- for (pe = pkg->head; pe; pe = pe->next) {
+ TAILQ_FOREACH(pe, &pkg->pe_head, entry) {
if (lstat(pe->path, &sb2) < 0) {
weprintf("lstat %s:", pe->path);
continue;
diff --git a/queue.h b/queue.h
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues, and circular queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The
+ * elements are singly linked for minimum space and pointer manipulation
+ * overhead at the expense of O(n) removal for arbitrary elements. New
+ * elements can be added to the list after an existing element or at the
+ * head of the list. Elements being removed from the head of the list
+ * should use the explicit macro for this purpose for optimum
+ * efficiency. A singly-linked list may only be traversed in the forward
+ * direction. Singly-linked lists are ideal for applications with large
+ * datasets and few or no removals or for implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List functions.
+ */
+#define LIST_INIT(head) do { \
+ (head)->lh_first = NULL; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
+ (listelm)->field.le_next->field.le_prev = \
+ &(elm)->field.le_next; \
+ (listelm)->field.le_next = (elm); \
+ (elm)->field.le_prev = &(listelm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ (elm)->field.le_next = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &(elm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.le_next = (head)->lh_first) != NULL) \
+ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+ (head)->lh_first = (elm); \
+ (elm)->field.le_prev = &(head)->lh_first; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_REMOVE(elm, field) do { \
+ if ((elm)->field.le_next != NULL) \
+ (elm)->field.le_next->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = (elm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_FOREACH(var, head, field) \
+ for ((var) = ((head)->lh_first); \
+ (var); \
+ (var) = ((var)->field.le_next))
+
+/*
+ * List access methods.
+ */
+#define LIST_EMPTY(head) ((head)->lh_first == NULL)
+#define LIST_FIRST(head) ((head)->lh_first)
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+
+/*
+ * Singly-linked List definitions.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_INIT(head) do { \
+ (head)->slh_first = NULL; \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ (elm)->field.sle_next = (slistelm)->field.sle_next; \
+ (slistelm)->field.sle_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.sle_next = (head)->slh_first; \
+ (head)->slh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ (head)->slh_first = (head)->slh_first->field.sle_next; \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if ((head)->slh_first == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = (head)->slh_first; \
+ while(curelm->field.sle_next != (elm)) \
+ curelm = curelm->field.sle_next; \
+ curelm->field.sle_next = \
+ curelm->field.sle_next->field.sle_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_FOREACH(var, head, field) \
+ for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
+
+/*
+ * Singly-linked List access methods.
+ */
+#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
+#define SLIST_FIRST(head) ((head)->slh_first)
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define STAILQ_HEAD(name, type) \
+struct name { \
+ struct type *stqh_first; /* first element */ \
+ struct type **stqh_last; /* addr of last next element */ \
+}
+
+#define STAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).stqh_first }
+
+#define STAILQ_ENTRY(type) \
+struct { \
+ struct type *stqe_next; /* next element */ \
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define STAILQ_INIT(head) do { \
+ (head)->stqh_first = NULL; \
+ (head)->stqh_last = &(head)->stqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+ (head)->stqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.stqe_next = NULL; \
+ *(head)->stqh_last = (elm); \
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+ (listelm)->field.stqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \
+ (head)->stqh_last = &(head)->stqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_REMOVE(head, elm, type, field) do { \
+ if ((head)->stqh_first == (elm)) { \
+ STAILQ_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->stqh_first; \
+ while (curelm->field.stqe_next != (elm)) \
+ curelm = curelm->field.stqe_next; \
+ if ((curelm->field.stqe_next = \
+ curelm->field.stqe_next->field.stqe_next) == NULL) \
+ (head)->stqh_last = &(curelm)->field.stqe_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->stqh_first); \
+ (var); \
+ (var) = ((var)->field.stqe_next))
+
+#define STAILQ_CONCAT(head1, head2) do { \
+ if (!STAILQ_EMPTY((head2))) { \
+ *(head1)->stqh_last = (head2)->stqh_first; \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+/*
+ * Singly-linked Tail queue access methods.
+ */
+#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
+#define STAILQ_FIRST(head) ((head)->stqh_first)
+#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+
+
+/*
+ * Simple queue definitions.
+ */
+#define SIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqh_first; /* first element */ \
+ struct type **sqh_last; /* addr of last next element */ \
+}
+
+#define SIMPLEQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).sqh_first }
+
+#define SIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqe_next; /* next element */ \
+}
+
+/*
+ * Simple queue functions.
+ */
+#define SIMPLEQ_INIT(head) do { \
+ (head)->sqh_first = NULL; \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (head)->sqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqe_next = NULL; \
+ *(head)->sqh_last = (elm); \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (listelm)->field.sqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_REMOVE(head, elm, type, field) do { \
+ if ((head)->sqh_first == (elm)) { \
+ SIMPLEQ_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->sqh_first; \
+ while (curelm->field.sqe_next != (elm)) \
+ curelm = curelm->field.sqe_next; \
+ if ((curelm->field.sqe_next = \
+ curelm->field.sqe_next->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(curelm)->field.sqe_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->sqh_first); \
+ (var); \
+ (var) = ((var)->field.sqe_next))
+
+/*
+ * Simple queue access methods.
+ */
+#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL)
+#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
+#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
+
+
+/*
+ * Tail queue definitions.
+ */
+#define _TAILQ_HEAD(name, type, qual) \
+struct name { \
+ qual type *tqh_first; /* first element */ \
+ qual type *qual *tqh_last; /* addr of last next element */ \
+}
+#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,)
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define _TAILQ_ENTRY(type, qual) \
+struct { \
+ qual type *tqe_next; /* next element */ \
+ qual type *qual *tqe_prev; /* address of previous next element */\
+}
+#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,)
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_INIT(head) do { \
+ (head)->tqh_first = NULL; \
+ (head)->tqh_last = &(head)->tqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
+ (head)->tqh_first->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_prev = &(head)->tqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.tqe_next = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+ (elm)->field.tqe_next->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ if (((elm)->field.tqe_next) != NULL) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->tqh_first); \
+ (var); \
+ (var) = ((var)->field.tqe_next))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
+ (var); \
+ (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
+
+#define TAILQ_CONCAT(head1, head2, field) do { \
+ if (!TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ TAILQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+/*
+ * Tail queue access methods.
+ */
+#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type) \
+struct name { \
+ struct type *cqh_first; /* first element */ \
+ struct type *cqh_last; /* last element */ \
+}
+
+#define CIRCLEQ_HEAD_INITIALIZER(head) \
+ { (void *)&head, (void *)&head }
+
+#define CIRCLEQ_ENTRY(type) \
+struct { \
+ struct type *cqe_next; /* next element */ \
+ struct type *cqe_prev; /* previous element */ \
+}
+
+/*
+ * Circular queue functions.
+ */
+#define CIRCLEQ_INIT(head) do { \
+ (head)->cqh_first = (void *)(head); \
+ (head)->cqh_last = (void *)(head); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm)->field.cqe_next; \
+ (elm)->field.cqe_prev = (listelm); \
+ if ((listelm)->field.cqe_next == (void *)(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (listelm)->field.cqe_next->field.cqe_prev = (elm); \
+ (listelm)->field.cqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm); \
+ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
+ if ((listelm)->field.cqe_prev == (void *)(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (listelm)->field.cqe_prev->field.cqe_next = (elm); \
+ (listelm)->field.cqe_prev = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.cqe_next = (head)->cqh_first; \
+ (elm)->field.cqe_prev = (void *)(head); \
+ if ((head)->cqh_last == (void *)(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (head)->cqh_first->field.cqe_prev = (elm); \
+ (head)->cqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.cqe_next = (void *)(head); \
+ (elm)->field.cqe_prev = (head)->cqh_last; \
+ if ((head)->cqh_first == (void *)(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (head)->cqh_last->field.cqe_next = (elm); \
+ (head)->cqh_last = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_REMOVE(head, elm, field) do { \
+ if ((elm)->field.cqe_next == (void *)(head)) \
+ (head)->cqh_last = (elm)->field.cqe_prev; \
+ else \
+ (elm)->field.cqe_next->field.cqe_prev = \
+ (elm)->field.cqe_prev; \
+ if ((elm)->field.cqe_prev == (void *)(head)) \
+ (head)->cqh_first = (elm)->field.cqe_next; \
+ else \
+ (elm)->field.cqe_prev->field.cqe_next = \
+ (elm)->field.cqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->cqh_first); \
+ (var) != (const void *)(head); \
+ (var) = ((var)->field.cqe_next))
+
+#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
+ for ((var) = ((head)->cqh_last); \
+ (var) != (const void *)(head); \
+ (var) = ((var)->field.cqe_prev))
+
+/*
+ * Circular queue access methods.
+ */
+#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
+#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
+#define CIRCLEQ_LAST(head) ((head)->cqh_last)
+#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
+#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
+
+#define CIRCLEQ_LOOP_NEXT(head, elm, field) \
+ (((elm)->field.cqe_next == (void *)(head)) \
+ ? ((head)->cqh_first) \
+ : (elm->field.cqe_next))
+#define CIRCLEQ_LOOP_PREV(head, elm, field) \
+ (((elm)->field.cqe_prev == (void *)(head)) \
+ ? ((head)->cqh_last) \
+ : (elm->field.cqe_prev))
+
+#endif /* sys/queue.h */
diff --git a/removepkg.c b/removepkg.c
@@ -75,6 +75,7 @@ pkg_remove_cb(struct db *db, struct pkg *pkg, void *name)
return -1;
db_rm(pkg);
printf("removed %s\n", pkg->name);
+ pkg_free(pkg);
return 1;
}
return 0;