mirror of
https://github.com/InfrastructureServices/vsftpd.git
synced 2025-04-19 01:24:02 +03:00
181 lines
3.9 KiB
C
181 lines
3.9 KiB
C
/*
|
|
* Part of Very Secure FTPd
|
|
* Licence: GPL v2
|
|
* Author: Chris Evans
|
|
* strlist.c
|
|
*/
|
|
|
|
/* Anti-lamer measures deployed, sir! */
|
|
#define PRIVATE_HANDS_OFF_alloc_len alloc_len
|
|
#define PRIVATE_HANDS_OFF_list_len list_len
|
|
#define PRIVATE_HANDS_OFF_p_nodes p_nodes
|
|
#include "strlist.h"
|
|
|
|
#include "str.h"
|
|
#include "utility.h"
|
|
#include "sysutil.h"
|
|
|
|
struct mystr_list_node
|
|
{
|
|
struct mystr str;
|
|
struct mystr sort_key_str;
|
|
};
|
|
|
|
/* File locals */
|
|
static const unsigned int kMaxStrlist = 10 * 1000 * 1000;
|
|
|
|
static struct mystr s_null_str;
|
|
|
|
static int sort_compare_func(const void* p1, const void* p2);
|
|
static int sort_compare_func_reverse(const void* p1, const void* p2);
|
|
static int sort_compare_common(const void* p1, const void* p2, int reverse);
|
|
|
|
void
|
|
str_list_free(struct mystr_list* p_list)
|
|
{
|
|
unsigned int i;
|
|
for (i=0; i < p_list->list_len; ++i)
|
|
{
|
|
str_free(&p_list->p_nodes[i].str);
|
|
str_free(&p_list->p_nodes[i].sort_key_str);
|
|
}
|
|
p_list->list_len = 0;
|
|
p_list->alloc_len = 0;
|
|
if (p_list->p_nodes)
|
|
{
|
|
vsf_sysutil_free(p_list->p_nodes);
|
|
p_list->p_nodes = 0;
|
|
}
|
|
}
|
|
|
|
unsigned int
|
|
str_list_get_length(const struct mystr_list* p_list)
|
|
{
|
|
return p_list->list_len;
|
|
}
|
|
|
|
int
|
|
str_list_contains_str(const struct mystr_list* p_list,
|
|
const struct mystr* p_str)
|
|
{
|
|
unsigned int i;
|
|
for (i=0; i < p_list->list_len; ++i)
|
|
{
|
|
if (str_equal(p_str, &p_list->p_nodes[i].str))
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
str_list_add(struct mystr_list* p_list, const struct mystr* p_str,
|
|
const struct mystr* p_sort_key_str)
|
|
{
|
|
struct mystr_list_node* p_node;
|
|
/* Expand the node allocation if we have to */
|
|
if (p_list->list_len == p_list->alloc_len)
|
|
{
|
|
if (p_list->alloc_len == 0)
|
|
{
|
|
p_list->alloc_len = 32;
|
|
p_list->p_nodes = vsf_sysutil_malloc(
|
|
p_list->alloc_len * (unsigned int) sizeof(struct mystr_list_node));
|
|
}
|
|
else
|
|
{
|
|
p_list->alloc_len *= 2;
|
|
if (p_list->alloc_len > kMaxStrlist)
|
|
{
|
|
die("excessive strlist");
|
|
}
|
|
p_list->p_nodes = vsf_sysutil_realloc(
|
|
p_list->p_nodes,
|
|
p_list->alloc_len * (unsigned int) sizeof(struct mystr_list_node));
|
|
}
|
|
}
|
|
p_node = &p_list->p_nodes[p_list->list_len];
|
|
p_node->str = s_null_str;
|
|
p_node->sort_key_str = s_null_str;
|
|
str_copy(&p_node->str, p_str);
|
|
if (p_sort_key_str)
|
|
{
|
|
str_copy(&p_node->sort_key_str, p_sort_key_str);
|
|
}
|
|
p_list->list_len++;
|
|
}
|
|
|
|
void
|
|
str_list_sort(struct mystr_list* p_list, int reverse)
|
|
{
|
|
if (!reverse)
|
|
{
|
|
vsf_sysutil_qsort(p_list->p_nodes, p_list->list_len,
|
|
sizeof(struct mystr_list_node), sort_compare_func);
|
|
}
|
|
else
|
|
{
|
|
vsf_sysutil_qsort(p_list->p_nodes, p_list->list_len,
|
|
sizeof(struct mystr_list_node),
|
|
sort_compare_func_reverse);
|
|
}
|
|
}
|
|
|
|
static int
|
|
sort_compare_func(const void* p1, const void* p2)
|
|
{
|
|
return sort_compare_common(p1, p2, 0);
|
|
}
|
|
|
|
static int
|
|
sort_compare_func_reverse(const void* p1, const void* p2)
|
|
{
|
|
return sort_compare_common(p1, p2, 1);
|
|
}
|
|
|
|
static int
|
|
sort_compare_common(const void* p1, const void* p2, int reverse)
|
|
{
|
|
const struct mystr* p_cmp1;
|
|
const struct mystr* p_cmp2;
|
|
const struct mystr_list_node* p_node1 = (const struct mystr_list_node*) p1;
|
|
const struct mystr_list_node* p_node2 = (const struct mystr_list_node*) p2;
|
|
if (!str_isempty(&p_node1->sort_key_str))
|
|
{
|
|
p_cmp1 = &p_node1->sort_key_str;
|
|
}
|
|
else
|
|
{
|
|
p_cmp1 = &p_node1->str;
|
|
}
|
|
if (!str_isempty(&p_node2->sort_key_str))
|
|
{
|
|
p_cmp2 = &p_node2->sort_key_str;
|
|
}
|
|
else
|
|
{
|
|
p_cmp2 = &p_node2->str;
|
|
}
|
|
|
|
if (reverse)
|
|
{
|
|
return str_strcmp(p_cmp2, p_cmp1);
|
|
}
|
|
else
|
|
{
|
|
return str_strcmp(p_cmp1, p_cmp2);
|
|
}
|
|
}
|
|
|
|
const struct mystr*
|
|
str_list_get_pstr(const struct mystr_list* p_list, unsigned int indexx)
|
|
{
|
|
if (indexx >= p_list->list_len)
|
|
{
|
|
bug("indexx out of range in str_list_get_str");
|
|
}
|
|
return &p_list->p_nodes[indexx].str;
|
|
}
|
|
|