clamav/libclamav/table.c

211 lines
5.4 KiB
C
Raw Normal View History

2003-07-29 15:48:06 +00:00
/*
2015-09-17 13:41:26 -04:00
* Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2007-2008 Sourcefire, Inc.
*
* Authors: Nigel Horne
2003-07-29 15:48:06 +00:00
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
2003-07-29 15:48:06 +00:00
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* TODO: Allow individual items to be updated or removed
*
* It is up to the caller to create a mutex for the table if needed
2003-07-29 15:48:06 +00:00
*/
2004-10-01 13:50:47 +00:00
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
2003-07-29 15:48:06 +00:00
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_STRINGS_H
2003-07-29 15:48:06 +00:00
#include <strings.h>
#endif
2003-07-29 15:48:06 +00:00
#include <assert.h>
2014-07-01 19:38:01 -04:00
#include "clamav.h"
2003-07-29 15:48:06 +00:00
#include "table.h"
#include "others.h"
struct table *
tableCreate(void)
{
return (struct table *)cli_calloc(1, sizeof(struct table));
2003-07-29 15:48:06 +00:00
}
void tableDestroy(table_t *table)
2003-07-29 15:48:06 +00:00
{
tableEntry *tableItem;
2003-07-29 15:48:06 +00:00
assert(table != NULL);
2003-07-29 15:48:06 +00:00
tableItem = table->tableHead;
2003-07-29 15:48:06 +00:00
while (tableItem) {
tableEntry *tableNext = tableItem->next;
2003-07-29 15:48:06 +00:00
if (tableItem->key)
free(tableItem->key);
free(tableItem);
2003-07-29 15:48:06 +00:00
tableItem = tableNext;
}
2003-07-29 15:48:06 +00:00
free(table);
2003-07-29 15:48:06 +00:00
}
/*
* Returns the value, or -1 for failure
*/
int tableInsert(table_t *table, const char *key, int value)
2003-07-29 15:48:06 +00:00
{
const int v = tableFind(table, key);
2003-07-29 15:48:06 +00:00
if (v > 0) /* duplicate key */
return (v == value) ? value : -1; /* allow real dups */
2003-07-29 15:48:06 +00:00
assert(value != -1); /* that would confuse us */
2003-07-29 15:48:06 +00:00
if (table->tableHead == NULL)
table->tableLast = table->tableHead = (tableEntry *)cli_malloc(sizeof(tableEntry));
else {
/*
2006-07-19 12:55:44 +00:00
* Re-use deleted items
*/
if (table->flags & TABLE_HAS_DELETED_ENTRIES) {
tableEntry *tableItem;
2006-07-19 12:55:44 +00:00
assert(table->tableHead != NULL);
2006-07-19 12:55:44 +00:00
for (tableItem = table->tableHead; tableItem; tableItem = tableItem->next)
if (tableItem->key == NULL) {
/* This item has been deleted */
tableItem->key = cli_strdup(key);
tableItem->value = value;
return value;
}
2006-07-19 12:55:44 +00:00
table->flags &= ~TABLE_HAS_DELETED_ENTRIES;
}
2006-07-19 12:55:44 +00:00
table->tableLast = table->tableLast->next =
(tableEntry *)cli_malloc(sizeof(tableEntry));
}
2003-07-29 15:48:06 +00:00
if (table->tableLast == NULL) {
cli_dbgmsg("tableInsert: Unable to allocate memory for table\n");
return -1;
}
2004-09-18 15:03:15 +00:00
table->tableLast->next = NULL;
table->tableLast->key = cli_strdup(key);
table->tableLast->value = value;
2003-07-29 15:48:06 +00:00
return value;
2003-07-29 15:48:06 +00:00
}
/*
* Returns the value - -1 for not found. This means the value of a valid key
* can't be -1 :-(
*
* Linear search. Since tables are rarely more than 3 or 4 in size, and never
Spelling Adjustments (#30) * spelling: accessed * spelling: alignment * spelling: amalgamated * spelling: answers * spelling: another * spelling: acquisition * spelling: apitid * spelling: ascii * spelling: appending * spelling: appropriate * spelling: arbitrary * spelling: architecture * spelling: asynchronous * spelling: attachments * spelling: argument * spelling: authenticode * spelling: because * spelling: boundary * spelling: brackets * spelling: bytecode * spelling: calculation * spelling: cannot * spelling: changes * spelling: check * spelling: children * spelling: codegen * spelling: commands * spelling: container * spelling: concatenated * spelling: conditions * spelling: continuous * spelling: conversions * spelling: corresponding * spelling: corrupted * spelling: coverity * spelling: crafting * spelling: daemon * spelling: definition * spelling: delivered * spelling: delivery * spelling: delimit * spelling: dependencies * spelling: dependency * spelling: detection * spelling: determine * spelling: disconnects * spelling: distributed * spelling: documentation * spelling: downgraded * spelling: downloading * spelling: endianness * spelling: entities * spelling: especially * spelling: empty * spelling: expected * spelling: explicitly * spelling: existent * spelling: finished * spelling: flexibility * spelling: flexible * spelling: freshclam * spelling: functions * spelling: guarantee * spelling: hardened * spelling: headaches * spelling: heighten * spelling: improper * spelling: increment * spelling: indefinitely * spelling: independent * spelling: inaccessible * spelling: infrastructure Conflicts: docs/html/node68.html * spelling: initializing * spelling: inited * spelling: instream * spelling: installed * spelling: initialization * spelling: initialize * spelling: interface * spelling: intrinsics * spelling: interpreter * spelling: introduced * spelling: invalid * spelling: latency * spelling: lawyers * spelling: libclamav * spelling: likelihood * spelling: loop * spelling: maximum * spelling: million * spelling: milliseconds * spelling: minimum * spelling: minzhuan * spelling: multipart * spelling: misled * spelling: modifiers * spelling: notifying * spelling: objects * spelling: occurred * spelling: occurs * spelling: occurrences * spelling: optimization * spelling: original * spelling: originated * spelling: output * spelling: overridden * spelling: parenthesis * spelling: partition * spelling: performance * spelling: permission * spelling: phishing * spelling: portions * spelling: positives * spelling: preceded * spelling: properties * spelling: protocol * spelling: protos * spelling: quarantine * spelling: recursive * spelling: referring * spelling: reorder * spelling: reset * spelling: resources * spelling: resume * spelling: retrieval * spelling: rewrite * spelling: sanity * spelling: scheduled * spelling: search * spelling: section * spelling: separator * spelling: separated * spelling: specify * spelling: special * spelling: statement * spelling: streams * spelling: succession * spelling: suggests * spelling: superfluous * spelling: suspicious * spelling: synonym * spelling: temporarily * spelling: testfiles * spelling: transverse * spelling: turkish * spelling: typos * spelling: unable * spelling: unexpected * spelling: unexpectedly * spelling: unfinished * spelling: unfortunately * spelling: uninitialized * spelling: unlocking * spelling: unnecessary * spelling: unpack * spelling: unrecognized * spelling: unsupported * spelling: usable * spelling: wherever * spelling: wishlist * spelling: white * spelling: infrastructure * spelling: directories * spelling: overridden * spelling: permission * spelling: yesterday * spelling: initialization * spelling: intrinsics * space adjustment for spelling changes * minor modifications by klin
2018-02-21 15:00:59 -05:00
* reach double figures, there's no need for optimization
2003-07-29 15:48:06 +00:00
*/
int tableFind(const table_t *table, const char *key)
2003-07-29 15:48:06 +00:00
{
const tableEntry *tableItem;
#ifdef CL_DEBUG
int cost;
2004-10-01 13:50:47 +00:00
#endif
2003-07-29 15:48:06 +00:00
assert(table != NULL);
2003-07-29 15:48:06 +00:00
if (key == NULL)
return -1; /* not treated as a fatal error */
2003-07-29 15:48:06 +00:00
#ifdef CL_DEBUG
cost = 0;
#endif
2004-10-01 13:50:47 +00:00
for (tableItem = table->tableHead; tableItem; tableItem = tableItem->next) {
#ifdef CL_DEBUG
cost++;
2004-10-01 13:50:47 +00:00
#endif
if (tableItem->key && (strcasecmp(tableItem->key, key) == 0)) {
#ifdef CL_DEBUG
cli_dbgmsg("tableFind: Cost of '%s' = %d\n", key, cost);
2004-10-01 13:50:47 +00:00
#endif
return tableItem->value;
}
}
2003-07-29 15:48:06 +00:00
return -1; /* not found */
2003-07-29 15:48:06 +00:00
}
/*
* Change a value in the table. If the key isn't in the table insert it
* Returns -1 for error, otherwise the new value
*/
int tableUpdate(table_t *table, const char *key, int new_value)
{
tableEntry *tableItem;
assert(table != NULL);
if (key == NULL)
return -1; /* not treated as a fatal error */
for (tableItem = table->tableHead; tableItem; tableItem = tableItem->next)
if (tableItem->key && (strcasecmp(tableItem->key, key) == 0)) {
tableItem->value = new_value;
return new_value;
}
/* not found */
return tableInsert(table, key, new_value);
}
/*
* Remove an item from the table
*/
void tableRemove(table_t *table, const char *key)
{
tableEntry *tableItem;
assert(table != NULL);
if (key == NULL)
return; /* not treated as a fatal error */
for (tableItem = table->tableHead; tableItem; tableItem = tableItem->next)
if (tableItem->key && (strcasecmp(tableItem->key, key) == 0)) {
free(tableItem->key);
tableItem->key = NULL;
table->flags |= TABLE_HAS_DELETED_ENTRIES;
/* don't break, duplicate keys are allowed */
}
}
void tableIterate(table_t *table, void (*callback)(char *key, int value, void *arg), void *arg)
{
tableEntry *tableItem;
if (table == NULL)
return;
for (tableItem = table->tableHead; tableItem; tableItem = tableItem->next)
if (tableItem->key) /* check node has not been deleted */
(*callback)(tableItem->key, tableItem->value, arg);
}