Change indentation to follow the updated standard.
Alot of mixed indentation. use 4 chars wide soft tabs.
This commit is contained in:
parent
9cc5420447
commit
f46ae1970b
51 changed files with 634 additions and 639 deletions
|
|
@ -2,7 +2,7 @@
|
||||||
# Common Makefile configuration for Archived
|
# Common Makefile configuration for Archived
|
||||||
#
|
#
|
||||||
|
|
||||||
CFLAGS += $(shell getconf LFS_CFLAGS) -D_GNU_SOURCE=1
|
CFLAGS += $(shell getconf LFS_CFLAGS) -D_GNU_SOURCE=1
|
||||||
LDFLAGS += $(shell getconf LFS_LDFLAGS)
|
LDFLAGS += $(shell getconf LFS_LDFLAGS)
|
||||||
|
|
||||||
# output tuning
|
# output tuning
|
||||||
|
|
|
||||||
|
|
@ -95,5 +95,4 @@ All API's should be externaly documented in the doc/ directory.
|
||||||
Things to keep in mind when modify or write code
|
Things to keep in mind when modify or write code
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
include and change the comment found in TEMPLATE file, at the top of the .c/.h file
|
include and change the comment found in TEMPLATE file, at the top of the .c/.h file
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ Configuration
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
Archive uses a .ini style configuration. The following options are
|
Archive uses a .ini style configuration. The following options are
|
||||||
available.
|
available.
|
||||||
|
|
||||||
Value types
|
Value types
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
@ -10,7 +10,7 @@ Value types
|
||||||
Boolean ;;
|
Boolean ;;
|
||||||
True: Y, T, 1 +
|
True: Y, T, 1 +
|
||||||
False: N, F, 0
|
False: N, F, 0
|
||||||
|
|
||||||
String ;;
|
String ;;
|
||||||
Anything else.
|
Anything else.
|
||||||
|
|
||||||
|
|
@ -48,4 +48,3 @@ database (String);;
|
||||||
Database to use
|
Database to use
|
||||||
table (String);;
|
table (String);;
|
||||||
Tablename to use
|
Tablename to use
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ This API is here to provide an abstraction to the underlaying low-level filesyst
|
||||||
to try to make applications portable but also throw away detail from client-code.
|
to try to make applications portable but also throw away detail from client-code.
|
||||||
|
|
||||||
IMPORTANT: The design is only tested with inotify and the API may
|
IMPORTANT: The design is only tested with inotify and the API may
|
||||||
need to change in the future to support more subsystems that may have some limitations.
|
need to change in the future to support more subsystems that may have some limitations.
|
||||||
|
|
||||||
Data structures
|
Data structures
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|
@ -39,10 +39,10 @@ NOTIFY_MOVE_TO;;
|
||||||
|
|
||||||
`dir`::
|
`dir`::
|
||||||
non zero if event is triggered on a directory
|
non zero if event is triggered on a directory
|
||||||
|
|
||||||
`path`::
|
`path`::
|
||||||
path of the triggered event
|
path of the triggered event
|
||||||
|
|
||||||
`filename`::
|
`filename`::
|
||||||
the filename the event was triggered on
|
the filename the event was triggered on
|
||||||
|
|
||||||
|
|
@ -91,7 +91,7 @@ in this function, the only requirement is that the function never blocks.
|
||||||
`notify_event_set_*()`::
|
`notify_event_set_*()`::
|
||||||
|
|
||||||
use these functions to set members of the `notify_event` structure.
|
use these functions to set members of the `notify_event` structure.
|
||||||
|
|
||||||
`notify_event_del()`::
|
`notify_event_del()`::
|
||||||
|
|
||||||
free's all the memory from the `notify_event` structure.
|
free's all the memory from the `notify_event` structure.
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@ Holds information about a node on the filesystem
|
||||||
|
|
||||||
`name`::
|
`name`::
|
||||||
name of the entry (filename, directory name)
|
name of the entry (filename, directory name)
|
||||||
|
|
||||||
`base`::
|
`base`::
|
||||||
The base directory where `name` exists in.
|
The base directory where `name` exists in.
|
||||||
|
|
||||||
`dir`::
|
`dir`::
|
||||||
zero if the entry is a file, non zero otherwise
|
zero if the entry is a file, non zero otherwise
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,16 +10,16 @@ Macros
|
||||||
|
|
||||||
`LOG_INFO`::
|
`LOG_INFO`::
|
||||||
Information, Someone thinks you may find this important.
|
Information, Someone thinks you may find this important.
|
||||||
|
|
||||||
`LOG_WARN`::
|
`LOG_WARN`::
|
||||||
Warning, just a warning. can be ignored if you simply just don't care about it.
|
Warning, just a warning. can be ignored if you simply just don't care about it.
|
||||||
|
|
||||||
`LOG_CRIT`::
|
`LOG_CRIT`::
|
||||||
Critical condition, some things may not work as supposed to.
|
Critical condition, some things may not work as supposed to.
|
||||||
|
|
||||||
`LOG_DEBUG`::
|
`LOG_DEBUG`::
|
||||||
Debug level, messages that is usefull when debugging.
|
Debug level, messages that is usefull when debugging.
|
||||||
|
|
||||||
`LOG_ALL`::
|
`LOG_ALL`::
|
||||||
All of the above.
|
All of the above.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ NOTE: no data is copied, only the address 'obj' is stored in the queue.
|
||||||
`queue_isempty()`::
|
`queue_isempty()`::
|
||||||
|
|
||||||
Returns non zero if 'q' is empty. zero otherwise.
|
Returns non zero if 'q' is empty. zero otherwise.
|
||||||
|
|
||||||
`queue_num_items`::
|
`queue_num_items`::
|
||||||
|
|
||||||
Returns the number of items in 'q' at this given moment.
|
Returns the number of items in 'q' at this given moment.
|
||||||
|
|
|
||||||
|
|
@ -44,11 +44,11 @@ NOTE: The memory pointed to by the 'key' pointer is *not* copied so you must ens
|
||||||
|
|
||||||
Deletes a node from the tree. +
|
Deletes a node from the tree. +
|
||||||
Returns the node's key if a node was removed, `NULL` otherwise.
|
Returns the node's key if a node was removed, `NULL` otherwise.
|
||||||
|
|
||||||
`rbtree_free()`::
|
`rbtree_free()`::
|
||||||
|
|
||||||
Deletes the whole tree. if provided, calls 'free_fn' for every node.
|
Deletes the whole tree. if provided, calls 'free_fn' for every node.
|
||||||
|
|
||||||
`rbtree_walk()`::
|
`rbtree_walk()`::
|
||||||
|
|
||||||
Walks the tree in-order and passes a pointer to `key`
|
Walks the tree in-order and passes a pointer to `key`
|
||||||
|
|
@ -61,4 +61,4 @@ NOTE: The memory pointed to by the 'key' pointer is *not* copied so you must ens
|
||||||
|
|
||||||
`rbtree_is_empty()`::
|
`rbtree_is_empty()`::
|
||||||
|
|
||||||
Checks if a tree is empty, retruns zero if the tree is empty, nonzero otherwise.
|
Checks if a tree is empty, retruns zero if the tree is empty, nonzero otherwise.
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
@ -52,36 +52,36 @@ static int load_config(const char *file) {
|
||||||
when in main loop is by signal */
|
when in main loop is by signal */
|
||||||
static void clean_exit(int excode) {
|
static void clean_exit(int excode) {
|
||||||
|
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
|
|
||||||
notify_exit();
|
notify_exit();
|
||||||
|
|
||||||
database_close();
|
database_close();
|
||||||
|
|
||||||
iniparser_freedict(config);
|
iniparser_freedict(config);
|
||||||
|
|
||||||
printf("\nprocess exit at: %s", ctime(&t));
|
printf("\nprocess exit at: %s", ctime(&t));
|
||||||
exit(excode);
|
exit(excode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Signal handler */
|
/* Signal handler */
|
||||||
static void sighandl(int sig) {
|
static void sighandl(int sig) {
|
||||||
|
|
||||||
switch(sig) {
|
switch(sig) {
|
||||||
/* normal exit signals */
|
/* normal exit signals */
|
||||||
case SIGTERM :
|
case SIGTERM :
|
||||||
case SIGKILL :
|
case SIGKILL :
|
||||||
case SIGINT :
|
case SIGINT :
|
||||||
clean_exit(EXIT_SUCCESS);
|
clean_exit(EXIT_SUCCESS);
|
||||||
/* segmentation violation, let user now */
|
/* segmentation violation, let user now */
|
||||||
case SIGSEGV :
|
case SIGSEGV :
|
||||||
fprintf(stderr, "SEGFAULT: o no he didn't\n");
|
fprintf(stderr, "SEGFAULT: o no he didn't\n");
|
||||||
clean_exit(EXIT_FAILURE);
|
clean_exit(EXIT_FAILURE);
|
||||||
case SIGUSR1 :
|
case SIGUSR1 :
|
||||||
case SIGUSR2 :
|
case SIGUSR2 :
|
||||||
printf("notify stat:\n");
|
printf("notify stat:\n");
|
||||||
notify_stat();
|
notify_stat();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -97,7 +97,7 @@ static void main_loop() {
|
||||||
|
|
||||||
if (event == NULL)
|
if (event == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
logmsg(LOG_DEBUG, "%s: (%c) %s%s", notify_event_typetostr(event),
|
logmsg(LOG_DEBUG, "%s: (%c) %s%s", notify_event_typetostr(event),
|
||||||
event->dir ? 'D' : 'F', event->path, event->filename);
|
event->dir ? 'D' : 'F', event->path, event->filename);
|
||||||
|
|
||||||
|
|
@ -163,7 +163,7 @@ int main(int argc, char **argv) {
|
||||||
} else {
|
} else {
|
||||||
die("config (log:level): no levels defined\n");
|
die("config (log:level): no levels defined\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
init_log(level, path);
|
init_log(level, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __DATABASE_H
|
#ifndef __DATABASE_H
|
||||||
#define __DATABASE_H
|
#define __DATABASE_H
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ int database_init(dictionary *conf) {
|
||||||
|
|
||||||
char *confdb = iniparser_getstring(conf, "mongo:database", NULL);
|
char *confdb = iniparser_getstring(conf, "mongo:database", NULL);
|
||||||
char *confcoll = iniparser_getstring(conf, "mongo:collection", NULL);
|
char *confcoll = iniparser_getstring(conf, "mongo:collection", NULL);
|
||||||
|
|
||||||
if (!confcoll) {
|
if (!confcoll) {
|
||||||
fprintf(stderr, "mongo: missing 'collection' in configuration\n");
|
fprintf(stderr, "mongo: missing 'collection' in configuration\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -67,13 +67,13 @@ int database_init(dictionary *conf) {
|
||||||
|
|
||||||
strncpy(db.opts.host, iniparser_getstring(conf, "mongo:host", "127.0.0.1"), sizeof(db.opts.host));
|
strncpy(db.opts.host, iniparser_getstring(conf, "mongo:host", "127.0.0.1"), sizeof(db.opts.host));
|
||||||
db.opts.port = iniparser_getint(conf, "mongo:port", 27017);
|
db.opts.port = iniparser_getint(conf, "mongo:port", 27017);
|
||||||
|
|
||||||
mongo_conn_return status = mongo_connect(&db.conn, &db.opts);
|
mongo_conn_return status = mongo_connect(&db.conn, &db.opts);
|
||||||
|
|
||||||
if (status != mongo_conn_success) {
|
if (status != mongo_conn_success) {
|
||||||
|
|
||||||
char *err;
|
char *err;
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case mongo_conn_bad_arg :
|
case mongo_conn_bad_arg :
|
||||||
err = "Bad arguments";
|
err = "Bad arguments";
|
||||||
|
|
@ -90,7 +90,7 @@ int database_init(dictionary *conf) {
|
||||||
default:
|
default:
|
||||||
err = "Unkown error";
|
err = "Unkown error";
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "mongo: %s (%s:%i)\n", err, db.opts.host, db.opts.port);
|
fprintf(stderr, "mongo: %s (%s:%i)\n", err, db.opts.host, db.opts.port);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -115,7 +115,7 @@ int database_init(dictionary *conf) {
|
||||||
/* prepare collection */
|
/* prepare collection */
|
||||||
coll_clear();
|
coll_clear();
|
||||||
coll_create_index();
|
coll_create_index();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,7 +159,7 @@ int database_delete(const char *path, const char *filename) {
|
||||||
bson_buffer_init(&buf);
|
bson_buffer_init(&buf);
|
||||||
bson_append_regex(&buf, "Path", fpath, "");
|
bson_append_regex(&buf, "Path", fpath, "");
|
||||||
bson_from_buffer(&cond, &buf);
|
bson_from_buffer(&cond, &buf);
|
||||||
|
|
||||||
mongo_remove(&db.conn, db.ns, &cond);
|
mongo_remove(&db.conn, db.ns, &cond);
|
||||||
|
|
||||||
bson_destroy(&cond);
|
bson_destroy(&cond);
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@ static char* escape(const char *str) {
|
||||||
|
|
||||||
size_t len = strlen(str);
|
size_t len = strlen(str);
|
||||||
char *esc = xmalloc(len * 2 + 1);
|
char *esc = xmalloc(len * 2 + 1);
|
||||||
|
|
||||||
mysql_real_escape_string(db.connection, esc, str, len);
|
mysql_real_escape_string(db.connection, esc, str, len);
|
||||||
|
|
||||||
return esc;
|
return esc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,13 +158,13 @@ int database_insert(const char *path, const char *filename, const int isdir) {
|
||||||
fprintf(stderr, "mysql: Lost connection to database. Could not reconnect\n");
|
fprintf(stderr, "mysql: Lost connection to database. Could not reconnect\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Escape the strings */
|
/* Escape the strings */
|
||||||
escaped_path = escape(path);
|
escaped_path = escape(path);
|
||||||
escaped_filename = escape(filename);
|
escaped_filename = escape(filename);
|
||||||
|
|
||||||
stmt = xmalloc(strlen(stmt_insert) + strlen(db.table) + strlen(escaped_path) + strlen(escaped_filename) - 6);
|
stmt = xmalloc(strlen(stmt_insert) + strlen(db.table) + strlen(escaped_path) + strlen(escaped_filename) - 6);
|
||||||
|
|
||||||
/* Create mysql query */
|
/* Create mysql query */
|
||||||
sprintf(stmt, stmt_insert, db.table, escaped_path, escaped_filename, isdir != 0);
|
sprintf(stmt, stmt_insert, db.table, escaped_path, escaped_filename, isdir != 0);
|
||||||
|
|
||||||
|
|
|
||||||
126
src/event.c
126
src/event.c
|
|
@ -1,5 +1,5 @@
|
||||||
/* event.c
|
/* event.c
|
||||||
*
|
*
|
||||||
* (C) Copyright 2010 Henrik Hautakoski <henrik@fiktivkod.org>
|
* (C) Copyright 2010 Henrik Hautakoski <henrik@fiktivkod.org>
|
||||||
* (C) Copyright 2010 Fredric Nilsson <fredric@fiktivkod.org>
|
* (C) Copyright 2010 Fredric Nilsson <fredric@fiktivkod.org>
|
||||||
*
|
*
|
||||||
|
|
@ -14,29 +14,29 @@
|
||||||
#include "xalloc.h"
|
#include "xalloc.h"
|
||||||
|
|
||||||
#define dealloc_data(ev) \
|
#define dealloc_data(ev) \
|
||||||
if (ev->path) \
|
if (ev->path) \
|
||||||
xfree(ev->path); \
|
xfree(ev->path); \
|
||||||
if (ev->filename) \
|
if (ev->filename) \
|
||||||
xfree(ev->filename)
|
xfree(ev->filename)
|
||||||
|
|
||||||
static void init_event(notify_event* ev) {
|
static void init_event(notify_event* ev) {
|
||||||
|
|
||||||
ev->filename = NULL;
|
ev->filename = NULL;
|
||||||
ev->path = NULL;
|
ev->path = NULL;
|
||||||
ev->type = NOTIFY_UNKNOWN;
|
ev->type = NOTIFY_UNKNOWN;
|
||||||
ev->dir = 0;
|
ev->dir = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create event
|
* Create event
|
||||||
*/
|
*/
|
||||||
notify_event* notify_event_new() {
|
notify_event* notify_event_new() {
|
||||||
|
|
||||||
notify_event *ev = xmalloc(sizeof(notify_event));
|
notify_event *ev = xmalloc(sizeof(notify_event));
|
||||||
|
|
||||||
init_event(ev);
|
init_event(ev);
|
||||||
|
|
||||||
return ev;
|
return ev;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -44,11 +44,11 @@ notify_event* notify_event_new() {
|
||||||
*/
|
*/
|
||||||
void notify_event_del(notify_event *event) {
|
void notify_event_del(notify_event *event) {
|
||||||
|
|
||||||
if (event == NULL)
|
if (event == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dealloc_data(event);
|
dealloc_data(event);
|
||||||
xfree(event);
|
xfree(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -56,74 +56,74 @@ void notify_event_del(notify_event *event) {
|
||||||
*/
|
*/
|
||||||
void notify_event_clear(notify_event *event) {
|
void notify_event_clear(notify_event *event) {
|
||||||
|
|
||||||
if (event == NULL)
|
if (event == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dealloc_data(event);
|
dealloc_data(event);
|
||||||
init_event(event);
|
init_event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set event path
|
* Set event path
|
||||||
*/
|
*/
|
||||||
void notify_event_set_path(notify_event *event, const char *path) {
|
void notify_event_set_path(notify_event *event, const char *path) {
|
||||||
|
|
||||||
if (event == NULL || path == NULL)
|
if (event == NULL || path == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
event->path = xrealloc(event->path, strlen(path)+1);
|
event->path = xrealloc(event->path, strlen(path)+1);
|
||||||
|
|
||||||
memcpy(event->path, path, strlen(path)+1);
|
memcpy(event->path, path, strlen(path)+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set event filename
|
* Set event filename
|
||||||
*/
|
*/
|
||||||
void notify_event_set_filename(notify_event *event, const char *filename) {
|
void notify_event_set_filename(notify_event *event, const char *filename) {
|
||||||
|
|
||||||
if (event == NULL || filename == NULL)
|
if (event == NULL || filename == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
event->filename = xrealloc(event->filename, strlen(filename)+1);
|
event->filename = xrealloc(event->filename, strlen(filename)+1);
|
||||||
|
|
||||||
memcpy(event->filename, filename, strlen(filename)+1);
|
memcpy(event->filename, filename, strlen(filename)+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set directory */
|
/* set directory */
|
||||||
void notify_event_set_dir(notify_event *event, uint8_t dir) {
|
void notify_event_set_dir(notify_event *event, uint8_t dir) {
|
||||||
|
|
||||||
if (event == NULL)
|
if (event == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
event->dir = dir;
|
event->dir = dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
void notify_event_set_type(notify_event *event, uint8_t type) {
|
void notify_event_set_type(notify_event *event, uint8_t type) {
|
||||||
|
|
||||||
if (event == NULL)
|
if (event == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
event->type = type;
|
event->type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* notify_event_typetostr(notify_event *event) {
|
const char* notify_event_typetostr(notify_event *event) {
|
||||||
|
|
||||||
if (!event)
|
if (!event)
|
||||||
return "(null)";
|
return "(null)";
|
||||||
|
|
||||||
switch(event->type) {
|
switch(event->type) {
|
||||||
case NOTIFY_CREATE :
|
case NOTIFY_CREATE :
|
||||||
return "CREATE";
|
return "CREATE";
|
||||||
case NOTIFY_DELETE :
|
case NOTIFY_DELETE :
|
||||||
return "DELETE";
|
return "DELETE";
|
||||||
break;
|
break;
|
||||||
case NOTIFY_MOVE_FROM :
|
case NOTIFY_MOVE_FROM :
|
||||||
return "MOVE_FROM";
|
return "MOVE_FROM";
|
||||||
break;
|
break;
|
||||||
case NOTIFY_MOVE_TO :
|
case NOTIFY_MOVE_TO :
|
||||||
return "MOVE_TO";
|
return "MOVE_TO";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
20
src/event.h
20
src/event.h
|
|
@ -1,5 +1,5 @@
|
||||||
/* event.h - event data structure and operation's for notify API
|
/* event.h - event data structure and operation's for notify API
|
||||||
*
|
*
|
||||||
* (C) Copyright 2010 Henrik Hautakoski <henrik@fiktivkod.org>
|
* (C) Copyright 2010 Henrik Hautakoski <henrik@fiktivkod.org>
|
||||||
* (C) Copyright 2010 Fredric Nilsson <fredric@fiktivkod.org>
|
* (C) Copyright 2010 Fredric Nilsson <fredric@fiktivkod.org>
|
||||||
*
|
*
|
||||||
|
|
@ -15,17 +15,17 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/* event types */
|
/* event types */
|
||||||
#define NOTIFY_UNKNOWN (1 << 0)
|
#define NOTIFY_UNKNOWN (1 << 0)
|
||||||
#define NOTIFY_CREATE (1 << 1)
|
#define NOTIFY_CREATE (1 << 1)
|
||||||
#define NOTIFY_DELETE (1 << 2)
|
#define NOTIFY_DELETE (1 << 2)
|
||||||
#define NOTIFY_MOVE_FROM (1 << 3)
|
#define NOTIFY_MOVE_FROM (1 << 3)
|
||||||
#define NOTIFY_MOVE_TO (1 << 4)
|
#define NOTIFY_MOVE_TO (1 << 4)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t type; /* type of event */
|
uint8_t type; /* type of event */
|
||||||
uint8_t dir; /* non zero if event is triggered on a directory */
|
uint8_t dir; /* non zero if event is triggered on a directory */
|
||||||
char *path; /* path of the triggered event */
|
char *path; /* path of the triggered event */
|
||||||
char *filename; /* the filename event was triggered on */
|
char *filename; /* the filename event was triggered on */
|
||||||
} notify_event;
|
} notify_event;
|
||||||
|
|
||||||
notify_event* notify_event_new();
|
notify_event* notify_event_new();
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
(x)->fts_info == FTS_SLNONE)
|
(x)->fts_info == FTS_SLNONE)
|
||||||
|
|
||||||
struct __fscrawl {
|
struct __fscrawl {
|
||||||
FTS *fts;
|
FTS *fts;
|
||||||
fs_entry ent;
|
fs_entry ent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -43,11 +43,11 @@ static fs_entry* ftsentcpy(fs_entry *dest, FTSENT *src) {
|
||||||
|
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
char *newbase = realloc(dest->base, len + 1);
|
char *newbase = realloc(dest->base, len + 1);
|
||||||
|
|
||||||
if (newbase) {
|
if (newbase) {
|
||||||
memcpy(newbase, src->fts_path, len);
|
memcpy(newbase, src->fts_path, len);
|
||||||
newbase[len] = '\0';
|
newbase[len] = '\0';
|
||||||
|
|
||||||
dest->base = newbase;
|
dest->base = newbase;
|
||||||
dest->name = src->fts_name;
|
dest->name = src->fts_name;
|
||||||
dest->dir = src->fts_info == FTS_D;
|
dest->dir = src->fts_info == FTS_D;
|
||||||
|
|
@ -59,13 +59,13 @@ static fs_entry* ftsentcpy(fs_entry *dest, FTSENT *src) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fscrawl_t fsc_open(const char *path) {
|
fscrawl_t fsc_open(const char *path) {
|
||||||
|
|
||||||
struct __fscrawl *f;
|
struct __fscrawl *f;
|
||||||
char *npath;
|
char *npath;
|
||||||
|
|
||||||
f = malloc(sizeof(struct __fscrawl));
|
f = malloc(sizeof(struct __fscrawl));
|
||||||
if (!f)
|
if (!f)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
npath = path_normalize(path, NULL, 1);
|
npath = path_normalize(path, NULL, 1);
|
||||||
if (!npath)
|
if (!npath)
|
||||||
|
|
@ -82,7 +82,7 @@ fscrawl_t fsc_open(const char *path) {
|
||||||
f->ent.base = NULL;
|
f->ent.base = NULL;
|
||||||
f->ent.name = NULL;
|
f->ent.name = NULL;
|
||||||
f->ent.dir = 0;
|
f->ent.dir = 0;
|
||||||
return f;
|
return f;
|
||||||
free:
|
free:
|
||||||
if (f)
|
if (f)
|
||||||
free(f);
|
free(f);
|
||||||
|
|
@ -101,23 +101,23 @@ void fsc_close(fscrawl_t f) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_entry* fsc_cpy(fs_entry *ent) {
|
fs_entry* fsc_cpy(fs_entry *ent) {
|
||||||
|
|
||||||
void *ptr = malloc(sizeof(fs_entry));
|
void *ptr = malloc(sizeof(fs_entry));
|
||||||
|
|
||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
memcpy(ptr, ent, sizeof(fs_entry));
|
memcpy(ptr, ent, sizeof(fs_entry));
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_entry* fsc_read(fscrawl_t f) {
|
fs_entry* fsc_read(fscrawl_t f) {
|
||||||
|
|
||||||
FTSENT *ent;
|
FTSENT *ent;
|
||||||
|
|
||||||
if (!f)
|
if (!f)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
ent = fts_read(f->fts);
|
ent = fts_read(f->fts);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/* fscrawl.h - Filesystem traversal
|
/* fscrawl.h - Filesystem traversal
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010 Henrik Hautakoski <henrik@fiktivkod.org>
|
* Copyright (C) 2010 Henrik Hautakoski <henrik@fiktivkod.org>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
|
|
||||||
|
|
@ -84,12 +84,12 @@ void inotify_backend_exit(void) {
|
||||||
int inotify_backend_watch(const char *path) {
|
int inotify_backend_watch(const char *path) {
|
||||||
|
|
||||||
int wd = inotify_add_watch(fd, path, WATCH_MASK);
|
int wd = inotify_add_watch(fd, path, WATCH_MASK);
|
||||||
|
|
||||||
if (wd < 0) {
|
if (wd < 0) {
|
||||||
if (errno != EACCES && errno != ENOTDIR)
|
if (errno != EACCES && errno != ENOTDIR)
|
||||||
logerrno(LOG_CRIT, "inotify_watch", errno);
|
logerrno(LOG_CRIT, "inotify_watch", errno);
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
return wd;
|
return wd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,41 +16,41 @@
|
||||||
|
|
||||||
/* Structure describing an inotify event. */
|
/* Structure describing an inotify event. */
|
||||||
struct inotify_event {
|
struct inotify_event {
|
||||||
int wd; /* Watch descriptor. */
|
int wd; /* Watch descriptor. */
|
||||||
uint32_t mask; /* Watch mask. */
|
uint32_t mask; /* Watch mask. */
|
||||||
uint32_t cookie; /* Cookie to synchronize two events. */
|
uint32_t cookie; /* Cookie to synchronize two events. */
|
||||||
uint32_t len; /* Length (including NULs) of name. */
|
uint32_t len; /* Length (including NULs) of name. */
|
||||||
char name __flexarr; /* Name. */
|
char name __flexarr; /* Name. */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IN_EVENT_SIZE (sizeof(struct inotify_event) + 0x40)
|
#define IN_EVENT_SIZE (sizeof(struct inotify_event) + 0x40)
|
||||||
|
|
||||||
/* Supported events suitable for MASK parameter of INOTIFY_ADD_WATCH. */
|
/* Supported events suitable for MASK parameter of INOTIFY_ADD_WATCH. */
|
||||||
#define IN_ACCESS 0x00000001 /* File was accessed. */
|
#define IN_ACCESS 0x00000001 /* File was accessed. */
|
||||||
#define IN_MODIFY 0x00000002 /* File was modified. */
|
#define IN_MODIFY 0x00000002 /* File was modified. */
|
||||||
#define IN_ATTRIB 0x00000004 /* Metadata changed. */
|
#define IN_ATTRIB 0x00000004 /* Metadata changed. */
|
||||||
#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed. */
|
#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed. */
|
||||||
#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed. */
|
#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed. */
|
||||||
#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* Close. */
|
#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* Close. */
|
||||||
#define IN_OPEN 0x00000020 /* File was opened. */
|
#define IN_OPEN 0x00000020 /* File was opened. */
|
||||||
#define IN_MOVED_FROM 0x00000040 /* File was moved from X. */
|
#define IN_MOVED_FROM 0x00000040 /* File was moved from X. */
|
||||||
#define IN_MOVED_TO 0x00000080 /* File was moved to Y. */
|
#define IN_MOVED_TO 0x00000080 /* File was moved to Y. */
|
||||||
#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* Moves. */
|
#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* Moves. */
|
||||||
#define IN_CREATE 0x00000100 /* Subfile was created. */
|
#define IN_CREATE 0x00000100 /* Subfile was created. */
|
||||||
#define IN_DELETE 0x00000200 /* Subfile was deleted. */
|
#define IN_DELETE 0x00000200 /* Subfile was deleted. */
|
||||||
#define IN_DELETE_SELF 0x00000400 /* Self was deleted. */
|
#define IN_DELETE_SELF 0x00000400 /* Self was deleted. */
|
||||||
#define IN_MOVE_SELF 0x00000800 /* Self was moved. */
|
#define IN_MOVE_SELF 0x00000800 /* Self was moved. */
|
||||||
|
|
||||||
/* Events sent by the kernel. */
|
/* Events sent by the kernel. */
|
||||||
#define IN_UNMOUNT 0x00002000 /* Backing fs was unmounted. */
|
#define IN_UNMOUNT 0x00002000 /* Backing fs was unmounted. */
|
||||||
#define IN_Q_OVERFLOW 0x00004000 /* Event queued overflowed. */
|
#define IN_Q_OVERFLOW 0x00004000 /* Event queued overflowed. */
|
||||||
#define IN_IGNORED 0x00008000 /* File was ignored. */
|
#define IN_IGNORED 0x00008000 /* File was ignored. */
|
||||||
|
|
||||||
/* Helper events. */
|
/* Helper events. */
|
||||||
#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* Close. */
|
#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* Close. */
|
||||||
#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* Moves. */
|
#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* Moves. */
|
||||||
|
|
||||||
#define IN_ISDIR 0x40000000 /* Event occurred against dir. */
|
#define IN_ISDIR 0x40000000 /* Event occurred against dir. */
|
||||||
|
|
||||||
int inotify_backend_init(void);
|
int inotify_backend_init(void);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/* inotify-map.c
|
/* inotify-map.c
|
||||||
*
|
*
|
||||||
* (C) Copyright 2011 Henrik Hautakoski <henrik@fiktivkod.org>
|
* (C) Copyright 2011 Henrik Hautakoski <henrik@fiktivkod.org>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
|
@ -118,7 +118,7 @@ static int unmap_wd(struct watch *watch) {
|
||||||
int index;
|
int index;
|
||||||
struct list s = { (void**)&watch, 1 }, *list;
|
struct list s = { (void**)&watch, 1 }, *list;
|
||||||
|
|
||||||
list = rbtree_search(&tree_wd_paths, &s);
|
list = rbtree_search(&tree_wd_paths, &s);
|
||||||
if (list) {
|
if (list) {
|
||||||
|
|
||||||
index = list_indexof(list, watch);
|
index = list_indexof(list, watch);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/* inotify-map.h
|
/* inotify-map.h
|
||||||
*
|
*
|
||||||
* (C) Copyright 2011 Henrik Hautakoski <henrik@fiktivkod.org>
|
* (C) Copyright 2011 Henrik Hautakoski <henrik@fiktivkod.org>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#if defined(__i386__)
|
#if defined(__i386__)
|
||||||
# define __NR_inotify_init 291
|
# define __NR_inotify_init 291
|
||||||
# define __NR_inotify_add_watch 292
|
# define __NR_inotify_add_watch 292
|
||||||
# define __NR_inotify_rm_watch 293
|
# define __NR_inotify_rm_watch 293
|
||||||
#elif defined(__x86_64__)
|
#elif defined(__x86_64__)
|
||||||
# define __NR_inotify_init 253
|
# define __NR_inotify_init 253
|
||||||
# define __NR_inotify_add_watch 254
|
# define __NR_inotify_add_watch 254
|
||||||
# define __NR_inotify_rm_watch 255
|
# define __NR_inotify_rm_watch 255
|
||||||
#elif defined(__alpha__)
|
#elif defined(__alpha__)
|
||||||
# define __NR_inotify_init 444
|
# define __NR_inotify_init 444
|
||||||
# define __NR_inotify_add_watch 445
|
# define __NR_inotify_add_watch 445
|
||||||
|
|
@ -26,23 +26,23 @@
|
||||||
# define __NR_inotify_add_watch 152
|
# define __NR_inotify_add_watch 152
|
||||||
# define __NR_inotify_rm_watch 156
|
# define __NR_inotify_rm_watch 156
|
||||||
#elif defined (__ia64__)
|
#elif defined (__ia64__)
|
||||||
# define __NR_inotify_init 1277
|
# define __NR_inotify_init 1277
|
||||||
# define __NR_inotify_add_watch 1278
|
# define __NR_inotify_add_watch 1278
|
||||||
# define __NR_inotify_rm_watch 1279
|
# define __NR_inotify_rm_watch 1279
|
||||||
#elif defined (__s390__) || defined (__s390x__)
|
#elif defined (__s390__) || defined (__s390x__)
|
||||||
# define __NR_inotify_init 284
|
# define __NR_inotify_init 284
|
||||||
# define __NR_inotify_add_watch 285
|
# define __NR_inotify_add_watch 285
|
||||||
# define __NR_inotify_rm_watch 286
|
# define __NR_inotify_rm_watch 286
|
||||||
#elif defined (__arm__)
|
#elif defined (__arm__)
|
||||||
# define __NR_inotify_init 316
|
# define __NR_inotify_init 316
|
||||||
# define __NR_inotify_add_watch 317
|
# define __NR_inotify_add_watch 317
|
||||||
# define __NR_inotify_rm_watch 318
|
# define __NR_inotify_rm_watch 318
|
||||||
#elif defined (__SH4__)
|
#elif defined (__SH4__)
|
||||||
# define __NR_inotify_init 290
|
# define __NR_inotify_init 290
|
||||||
# define __NR_inotify_add_watch 291
|
# define __NR_inotify_add_watch 291
|
||||||
# define __NR_inotify_rm_watch 292
|
# define __NR_inotify_rm_watch 292
|
||||||
#elif defined (__SH5__)
|
#elif defined (__SH5__)
|
||||||
# define __NR_inotify_init 318
|
# define __NR_inotify_init 318
|
||||||
# define __NR_inotify_add_watch 319
|
# define __NR_inotify_add_watch 319
|
||||||
# define __NR_inotify_rm_watch 320
|
# define __NR_inotify_rm_watch 320
|
||||||
#else
|
#else
|
||||||
|
|
@ -56,12 +56,12 @@ static inline int inotify_init(void) {
|
||||||
|
|
||||||
static inline int inotify_add_watch(int fd, const char *name, __u32 mask) {
|
static inline int inotify_add_watch(int fd, const char *name, __u32 mask) {
|
||||||
|
|
||||||
return syscall(__NR_inotify_add_watch, fd, name, mask);
|
return syscall(__NR_inotify_add_watch, fd, name, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int inotify_rm_watch(int fd, __u32 wd) {
|
static inline int inotify_rm_watch(int fd, __u32 wd) {
|
||||||
|
|
||||||
return syscall(__NR_inotify_rm_watch, fd, wd);
|
return syscall(__NR_inotify_rm_watch, fd, wd);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _LINUX_INOTIFY_SYSCALLS_H */
|
#endif /* _LINUX_INOTIFY_SYSCALLS_H */
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ struct watch* inotify_watch_new(int wd, const char *path) {
|
||||||
|
|
||||||
w->wd = wd;
|
w->wd = wd;
|
||||||
w->path = path;
|
w->path = path;
|
||||||
|
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,7 +28,7 @@ void inotify_watch_destroy(struct watch *watch, void (*fn)(struct watch *)) {
|
||||||
|
|
||||||
if (watch) {
|
if (watch) {
|
||||||
struct tree *tree = (struct tree*) watch;
|
struct tree *tree = (struct tree*) watch;
|
||||||
|
|
||||||
if (!tree_is_root(tree))
|
if (!tree_is_root(tree))
|
||||||
tree_detach(tree);
|
tree_detach(tree);
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ struct watch* inotify_watch_add(struct watch *parent, struct watch *watch) {
|
||||||
|
|
||||||
if (parent->tree.child) {
|
if (parent->tree.child) {
|
||||||
struct watch *it = (struct watch*)parent->tree.child;
|
struct watch *it = (struct watch*)parent->tree.child;
|
||||||
|
|
||||||
/* move nodes that are children of this watch alongside watch */
|
/* move nodes that are children of this watch alongside watch */
|
||||||
while(it) {
|
while(it) {
|
||||||
if (path_isparent(it->path, watch->path)) {
|
if (path_isparent(it->path, watch->path)) {
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ void inotify_exit(void) {
|
||||||
if (event_queue) {
|
if (event_queue) {
|
||||||
notify_event *e;
|
notify_event *e;
|
||||||
while((e = queue_dequeue(event_queue)))
|
while((e = queue_dequeue(event_queue)))
|
||||||
notify_event_del(e);
|
notify_event_del(e);
|
||||||
queue_destroy(event_queue);
|
queue_destroy(event_queue);
|
||||||
event_queue = NULL;
|
event_queue = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -50,7 +50,7 @@ int inotify_ignore(const char *path) {
|
||||||
/* unmap and remove watch */
|
/* unmap and remove watch */
|
||||||
if (inotify_unmap_path(path) == 0) {
|
if (inotify_unmap_path(path) == 0) {
|
||||||
logmsg(LOG_DEBUG, "remove watch: %i %s", wd, path);
|
logmsg(LOG_DEBUG, "remove watch: %i %s", wd, path);
|
||||||
|
|
||||||
if (inotify_backend_ignore(wd) < 0)
|
if (inotify_backend_ignore(wd) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -61,24 +61,24 @@ static void proc_event(struct inotify_event *iev) {
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
struct list *watch_list;
|
struct list *watch_list;
|
||||||
|
|
||||||
logmsg(LOG_DEBUG, "RAW EVENT: %i, %x, %s", iev->wd, iev->mask, iev->name);
|
logmsg(LOG_DEBUG, "RAW EVENT: %i, %x, %s", iev->wd, iev->mask, iev->name);
|
||||||
|
|
||||||
if (iev->mask & IN_IGNORED) {
|
if (iev->mask & IN_IGNORED) {
|
||||||
inotify_unmap_wd(iev->wd);
|
inotify_unmap_wd(iev->wd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* lookup watch descriptors */
|
/* lookup watch descriptors */
|
||||||
watch_list = inotify_map_get_path(iev->wd);
|
watch_list = inotify_map_get_path(iev->wd);
|
||||||
|
|
||||||
if (!watch_list) {
|
if (!watch_list) {
|
||||||
logmsg(LOG_WARN, "-- IGNORING EVENT -- invalid watchdescriptor %i", iev->wd);
|
logmsg(LOG_WARN, "-- IGNORING EVENT -- invalid watchdescriptor %i", iev->wd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i=0; i < watch_list->nr; i++) {
|
for(i=0; i < watch_list->nr; i++) {
|
||||||
|
|
||||||
struct watch *watch = watch_list->items[i];
|
struct watch *watch = watch_list->items[i];
|
||||||
notify_event *event = notify_event_new();
|
notify_event *event = notify_event_new();
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ static void proc_event(struct inotify_event *iev) {
|
||||||
* or some other file.
|
* or some other file.
|
||||||
*/
|
*/
|
||||||
if (iev->mask & IN_CREATE || iev->mask & IN_MOVED_TO) {
|
if (iev->mask & IN_CREATE || iev->mask & IN_MOVED_TO) {
|
||||||
event->dir = (iev->mask & IN_ISDIR) ? 1 :
|
event->dir = (iev->mask & IN_ISDIR) ? 1 :
|
||||||
is_dir(mkpath("%s/%s", event->path, event->filename));
|
is_dir(mkpath("%s/%s", event->path, event->filename));
|
||||||
|
|
||||||
event->type = NOTIFY_CREATE;
|
event->type = NOTIFY_CREATE;
|
||||||
|
|
|
||||||
60
src/list.c
60
src/list.c
|
|
@ -24,10 +24,10 @@ static void resize(struct list *l) {
|
||||||
|
|
||||||
struct list* list_create(void) {
|
struct list* list_create(void) {
|
||||||
|
|
||||||
struct list *list = xmalloc(sizeof(struct list));
|
struct list *list = xmalloc(sizeof(struct list));
|
||||||
list->items = NULL;
|
list->items = NULL;
|
||||||
list->nr = 0;
|
list->nr = 0;
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct list* list_copy(struct list *list) {
|
struct list* list_copy(struct list *list) {
|
||||||
|
|
@ -69,22 +69,22 @@ void list_clear_fn(struct list *list, clear_fn_t *fn) {
|
||||||
|
|
||||||
int list_insert(struct list *list, const void *item) {
|
int list_insert(struct list *list, const void *item) {
|
||||||
|
|
||||||
if (!list)
|
if (!list)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
list->items = xrealloc(list->items, sizeof(list->items) * (++list->nr));
|
list->items = xrealloc(list->items, sizeof(list->items) * (++list->nr));
|
||||||
list->items[list->nr - 1] = (void *) item;
|
list->items[list->nr - 1] = (void *) item;
|
||||||
|
|
||||||
return list->nr;
|
return list->nr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* list_remove(struct list *list, unsigned index) {
|
void* list_remove(struct list *list, unsigned index) {
|
||||||
|
|
||||||
void *item = NULL;
|
void *item = NULL;
|
||||||
|
|
||||||
if (list && index < list->nr) {
|
if (list && index < list->nr) {
|
||||||
if (index < --list->nr) {
|
if (index < --list->nr) {
|
||||||
memmove(list->items + index, list->items + index + 1,
|
memmove(list->items + index, list->items + index + 1,
|
||||||
sizeof(list->items) * (list->nr - index));
|
sizeof(list->items) * (list->nr - index));
|
||||||
}
|
}
|
||||||
resize(list);
|
resize(list);
|
||||||
|
|
@ -105,29 +105,29 @@ void* list_reduce(struct list *list) {
|
||||||
|
|
||||||
int list_indexof(struct list *list, const void *item) {
|
int list_indexof(struct list *list, const void *item) {
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for(i=0; i < list->nr; i++) {
|
for(i=0; i < list->nr; i++) {
|
||||||
|
|
||||||
if (list->items[i] == item)
|
if (list->items[i] == item)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* list_lookup(struct list *list, const void *item, cmp_fn_t *fn) {
|
void* list_lookup(struct list *list, const void *item, cmp_fn_t *fn) {
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (fn) {
|
if (fn) {
|
||||||
for(i=0; i < list->nr; i++) {
|
for(i=0; i < list->nr; i++) {
|
||||||
if (fn(list->items[i], item) == 0)
|
if (fn(list->items[i], item) == 0)
|
||||||
return list->items[i];
|
return list->items[i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
i = list_indexof(list, item);
|
i = list_indexof(list, item);
|
||||||
if (i >= 0)
|
if (i >= 0)
|
||||||
return list->items[i];
|
return list->items[i];
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
src/log.c
10
src/log.c
|
|
@ -136,7 +136,7 @@ unsigned logstrtolvl(const char *str) {
|
||||||
|
|
||||||
void logmsg(unsigned level, const char *fmt, ...) {
|
void logmsg(unsigned level, const char *fmt, ...) {
|
||||||
|
|
||||||
va_list vl;
|
va_list vl;
|
||||||
|
|
||||||
if (!validmask(level, 1))
|
if (!validmask(level, 1))
|
||||||
die("log: invalid level: %x\n", level);
|
die("log: invalid level: %x\n", level);
|
||||||
|
|
@ -155,9 +155,9 @@ void logmsg(unsigned level, const char *fmt, ...) {
|
||||||
|
|
||||||
void logerrno(unsigned level, const char *prefix, int err) {
|
void logerrno(unsigned level, const char *prefix, int err) {
|
||||||
|
|
||||||
char *str = strerror(err);
|
char *str = strerror(err);
|
||||||
|
|
||||||
if (str && level & mask) {
|
if (str && level & mask) {
|
||||||
|
|
||||||
if (!validmask(level, 1))
|
if (!validmask(level, 1))
|
||||||
die("logerrno: invalid level: %x\n", level);
|
die("logerrno: invalid level: %x\n", level);
|
||||||
|
|
@ -169,5 +169,5 @@ void logerrno(unsigned level, const char *prefix, int err) {
|
||||||
fputs(str, logfd);
|
fputs(str, logfd);
|
||||||
fputc('\n', logfd);
|
fputc('\n', logfd);
|
||||||
fflush(logfd);
|
fflush(logfd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#define LOG_INFO (1<<0)
|
#define LOG_INFO (1<<0)
|
||||||
#define LOG_WARN (1<<1)
|
#define LOG_WARN (1<<1)
|
||||||
#define LOG_CRIT (1<<2)
|
#define LOG_CRIT (1<<2)
|
||||||
#define LOG_DEBUG (1<<3)
|
#define LOG_DEBUG (1<<3)
|
||||||
#define LOG_ALL (LOG_INFO | LOG_WARN | LOG_CRIT | LOG_DEBUG)
|
#define LOG_ALL (LOG_INFO | LOG_WARN | LOG_CRIT | LOG_DEBUG)
|
||||||
|
|
|
||||||
|
|
@ -93,13 +93,13 @@ static int rmwatch(const char *path, const char *name) {
|
||||||
|
|
||||||
int notify_init() {
|
int notify_init() {
|
||||||
|
|
||||||
if (!init) {
|
if (!init) {
|
||||||
if (inotify_init() < 0)
|
if (inotify_init() < 0)
|
||||||
return -1;
|
return -1;
|
||||||
init_ev_q = queue_init();
|
init_ev_q = queue_init();
|
||||||
init = 1;
|
init = 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void notify_exit() {
|
void notify_exit() {
|
||||||
|
|
@ -107,12 +107,12 @@ void notify_exit() {
|
||||||
if (init) {
|
if (init) {
|
||||||
notify_event *e;
|
notify_event *e;
|
||||||
while((e = queue_dequeue(init_ev_q)))
|
while((e = queue_dequeue(init_ev_q)))
|
||||||
notify_event_del(e);
|
notify_event_del(e);
|
||||||
queue_destroy(init_ev_q);
|
queue_destroy(init_ev_q);
|
||||||
init_ev_q = NULL;
|
init_ev_q = NULL;
|
||||||
|
|
||||||
inotify_exit();
|
inotify_exit();
|
||||||
|
|
||||||
init = 0;
|
init = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -128,10 +128,10 @@ int notify_add_watch(const char *path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int notify_rm_watch(const char *path) {
|
int notify_rm_watch(const char *path) {
|
||||||
|
|
||||||
if (!init)
|
if (!init)
|
||||||
die("inotify is not instantiated.");
|
die("inotify is not instantiated.");
|
||||||
return rmwatch(path, NULL);
|
return rmwatch(path, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
notify_event* notify_read() {
|
notify_event* notify_read() {
|
||||||
|
|
@ -140,10 +140,10 @@ notify_event* notify_read() {
|
||||||
|
|
||||||
if (!init)
|
if (!init)
|
||||||
die("inotify is not instantiated.");
|
die("inotify is not instantiated.");
|
||||||
|
|
||||||
if (!queue_isempty(init_ev_q))
|
if (!queue_isempty(init_ev_q))
|
||||||
return queue_dequeue(init_ev_q);
|
return queue_dequeue(init_ev_q);
|
||||||
|
|
||||||
ev = inotify_read();
|
ev = inotify_read();
|
||||||
|
|
||||||
if (ev && ev->dir && ev->type == NOTIFY_CREATE)
|
if (ev && ev->dir && ev->type == NOTIFY_CREATE)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/* notify.h - filesystem notification API
|
/* notify.h - filesystem notification API
|
||||||
*
|
*
|
||||||
* (C) Copyright 2010 Henrik Hautakoski <henrik@fiktivkod.org>
|
* (C) Copyright 2010 Henrik Hautakoski <henrik@fiktivkod.org>
|
||||||
* (C) Copyright 2010 Fredric Nilsson <fredric@fiktivkod.org>
|
* (C) Copyright 2010 Fredric Nilsson <fredric@fiktivkod.org>
|
||||||
*
|
*
|
||||||
|
|
|
||||||
32
src/path.c
32
src/path.c
|
|
@ -1,5 +1,5 @@
|
||||||
/* path.c - path handling routines
|
/* path.c - path handling routines
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2011 Henrik Hautakoski <henrik.hautakoski@gmail.com>
|
* Copyright (C) 2010-2011 Henrik Hautakoski <henrik.hautakoski@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* The design goal here is to not use fixed size buffers because
|
* The design goal here is to not use fixed size buffers because
|
||||||
* path's can be extremely long (slightly overexaggerated but extreme cases are extreme).
|
* path's can be extremely long (slightly overexaggerated but extreme cases are extreme).
|
||||||
* so we use funky heap memory based algorithms instead :)
|
* so we use funky heap memory based algorithms instead :)
|
||||||
*/
|
*/
|
||||||
|
|
@ -24,17 +24,17 @@
|
||||||
static char path_null = '\0';
|
static char path_null = '\0';
|
||||||
|
|
||||||
static inline int has_delim(const char *str) {
|
static inline int has_delim(const char *str) {
|
||||||
|
|
||||||
if (str == NULL)
|
if (str == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return strchr(str, '/') != NULL;
|
return strchr(str, '/') != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_abspath(const char *path) {
|
int is_abspath(const char *path) {
|
||||||
|
|
||||||
if (path == NULL || *path != '/')
|
if (path == NULL || *path != '/')
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for(; *path; path++) {
|
for(; *path; path++) {
|
||||||
|
|
||||||
|
|
@ -47,7 +47,7 @@ int is_abspath(const char *path) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_file(const char *path) {
|
int is_file(const char *path) {
|
||||||
|
|
@ -62,7 +62,7 @@ int is_file(const char *path) {
|
||||||
int is_dir(const char *path) {
|
int is_dir(const char *path) {
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (path && stat(path, &st) >= 0)
|
if (path && stat(path, &st) >= 0)
|
||||||
return S_ISDIR(st.st_mode);
|
return S_ISDIR(st.st_mode);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -72,7 +72,7 @@ int path_isparent(const char *path, const char *parent) {
|
||||||
|
|
||||||
if (*path++ != '/' || *parent++ != '/')
|
if (*path++ != '/' || *parent++ != '/')
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
while(*path) {
|
while(*path) {
|
||||||
if (*parent == '\0')
|
if (*parent == '\0')
|
||||||
return *path == '/' || *(path-1) == '/';
|
return *path == '/' || *(path-1) == '/';
|
||||||
|
|
@ -118,7 +118,7 @@ const char *mkpath(const char *fmt, ...) {
|
||||||
} else {
|
} else {
|
||||||
strbuf_expand(&sb, 1);
|
strbuf_expand(&sb, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
va_start(va, fmt);
|
va_start(va, fmt);
|
||||||
len = strbuf_append_va(&sb, fmt, va);
|
len = strbuf_append_va(&sb, fmt, va);
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
|
@ -146,8 +146,8 @@ char* path_normalize(const char *base, const char *name, unsigned dir) {
|
||||||
|
|
||||||
strbuf_t sb = STRBUF_INIT;
|
strbuf_t sb = STRBUF_INIT;
|
||||||
|
|
||||||
if (base == NULL || has_delim(name))
|
if (base == NULL || has_delim(name))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (*base == '~') {
|
if (*base == '~') {
|
||||||
base++;
|
base++;
|
||||||
|
|
@ -163,7 +163,7 @@ char* path_normalize(const char *base, const char *name, unsigned dir) {
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
strbuf_append_str(&sb, name);
|
strbuf_append_str(&sb, name);
|
||||||
|
|
||||||
if (dir)
|
if (dir)
|
||||||
strbuf_append_ch(&sb, '/');
|
strbuf_append_ch(&sb, '/');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/* path.h - path handling routines
|
/* path.h - path handling routines
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2011 Henrik Hautakoski <henrik@fiktivkod.org>
|
* Copyright (C) 2010-2011 Henrik Hautakoski <henrik@fiktivkod.org>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
|
|
||||||
23
src/queue.c
23
src/queue.c
|
|
@ -19,7 +19,7 @@
|
||||||
/* linked list node holding a chunk of queue elements */
|
/* linked list node holding a chunk of queue elements */
|
||||||
struct node {
|
struct node {
|
||||||
void *block[BLOCK_SIZE];
|
void *block[BLOCK_SIZE];
|
||||||
struct node *next;
|
struct node *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ref {
|
struct ref {
|
||||||
|
|
@ -28,22 +28,22 @@ struct ref {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct __queue {
|
struct __queue {
|
||||||
struct ref tail;
|
struct ref tail;
|
||||||
struct ref head;
|
struct ref head;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void alloc_node(struct ref *head) {
|
static void alloc_node(struct ref *head) {
|
||||||
|
|
||||||
struct node *n = xmalloc(sizeof(struct node));
|
struct node *n = xmalloc(sizeof(struct node));
|
||||||
|
|
||||||
n->next = NULL;
|
n->next = NULL;
|
||||||
head->n = head->n->next = n;
|
head->n = head->n->next = n;
|
||||||
head->i = 0;
|
head->i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dealloc_node(struct ref *tail) {
|
static void dealloc_node(struct ref *tail) {
|
||||||
|
|
||||||
struct node *next = tail->n->next;
|
struct node *next = tail->n->next;
|
||||||
|
|
||||||
if (next) {
|
if (next) {
|
||||||
xfree(tail->n);
|
xfree(tail->n);
|
||||||
|
|
@ -58,7 +58,7 @@ queue_t queue_init() {
|
||||||
q->tail.n = q->head.n = xmalloc(sizeof(struct node));
|
q->tail.n = q->head.n = xmalloc(sizeof(struct node));
|
||||||
q->tail.n->next = q->head.n->next = NULL;
|
q->tail.n->next = q->head.n->next = NULL;
|
||||||
q->tail.i = q->head.i = 0;
|
q->tail.i = q->head.i = 0;
|
||||||
|
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,10 +81,10 @@ void queue_enqueue(queue_t q, void *obj) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (q->head.i >= BLOCK_SIZE) {
|
if (q->head.i >= BLOCK_SIZE) {
|
||||||
alloc_node(&q->head);
|
alloc_node(&q->head);
|
||||||
}
|
}
|
||||||
|
|
||||||
q->head.n->block[q->head.i++] = obj;
|
q->head.n->block[q->head.i++] = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* queue_dequeue(queue_t q) {
|
void* queue_dequeue(queue_t q) {
|
||||||
|
|
@ -101,7 +101,7 @@ void* queue_dequeue(queue_t q) {
|
||||||
} else if (q->tail.i >= BLOCK_SIZE) {
|
} else if (q->tail.i >= BLOCK_SIZE) {
|
||||||
dealloc_node(&q->tail);
|
dealloc_node(&q->tail);
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,4 +129,3 @@ size_t queue_num_items(queue_t q) {
|
||||||
len += BLOCK_SIZE;
|
len += BLOCK_SIZE;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
376
src/rbtree.c
376
src/rbtree.c
|
|
@ -1,5 +1,5 @@
|
||||||
/* rbtree.c - red black tree implementation
|
/* rbtree.c - red black tree implementation
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2011 Henrik Hautakoski <henrik@fiktivkod.org>
|
* Copyright (C) 2010-2011 Henrik Hautakoski <henrik@fiktivkod.org>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
|
@ -24,84 +24,84 @@
|
||||||
/* node definition */
|
/* node definition */
|
||||||
typedef struct _rbn {
|
typedef struct _rbn {
|
||||||
const void *key;
|
const void *key;
|
||||||
struct _rbn *child[2];
|
struct _rbn *child[2];
|
||||||
unsigned char color;
|
unsigned char color;
|
||||||
} rbnode;
|
} rbnode;
|
||||||
|
|
||||||
#define is_red(n) ((n) != NULL && (n)->color == RB_RED)
|
#define is_red(n) ((n) != NULL && (n)->color == RB_RED)
|
||||||
#define swap(n,d,q) ((n)->child[(n)->child[d] == (q)])
|
#define swap(n,d,q) ((n)->child[(n)->child[d] == (q)])
|
||||||
|
|
||||||
static rbnode* node_alloc(const void *key) {
|
static rbnode* node_alloc(const void *key) {
|
||||||
|
|
||||||
rbnode *n = xmalloc(sizeof(rbnode));
|
rbnode *n = xmalloc(sizeof(rbnode));
|
||||||
|
|
||||||
n->key = key;
|
n->key = key;
|
||||||
n->color = RB_RED;
|
n->color = RB_RED;
|
||||||
n->child[0] = NULL;
|
n->child[0] = NULL;
|
||||||
n->child[1] = NULL;
|
n->child[1] = NULL;
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Recursivly deallocate a tree.
|
* Recursivly deallocate a tree.
|
||||||
*/
|
*/
|
||||||
static void node_dealloc(rbnode *n, void (*dealloc)(void *)) {
|
static void node_dealloc(rbnode *n, void (*dealloc)(void *)) {
|
||||||
|
|
||||||
if (!n)
|
if (!n)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (dealloc)
|
if (dealloc)
|
||||||
dealloc((void *)n->key);
|
dealloc((void *)n->key);
|
||||||
|
|
||||||
node_dealloc(n->child[0], dealloc);
|
node_dealloc(n->child[0], dealloc);
|
||||||
node_dealloc(n->child[1], dealloc);
|
node_dealloc(n->child[1], dealloc);
|
||||||
|
|
||||||
free(n);
|
free(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __DEBUG__
|
#ifdef __DEBUG__
|
||||||
#define rb_err(msg) fputs("rbtree error: " msg, stderr)
|
#define rb_err(msg) fputs("rbtree error: " msg, stderr)
|
||||||
|
|
||||||
static int rb_assert_r(rbnode *node, int (*cmp)(const void *, const void *)) {
|
static int rb_assert_r(rbnode *node, int (*cmp)(const void *, const void *)) {
|
||||||
|
|
||||||
int rh, lh;
|
int rh, lh;
|
||||||
rbnode *ln, *rn;
|
rbnode *ln, *rn;
|
||||||
|
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
ln = node->child[0];
|
ln = node->child[0];
|
||||||
rn = node->child[1];
|
rn = node->child[1];
|
||||||
|
|
||||||
if (is_red(node)) {
|
if (is_red(node)) {
|
||||||
/* double red violation */
|
/* double red violation */
|
||||||
if (is_red(ln) || is_red(rn)) {
|
if (is_red(ln) || is_red(rn)) {
|
||||||
rb_err("Double red violation");
|
rb_err("Double red violation");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lh = rb_assert_r(ln, cmp);
|
lh = rb_assert_r(ln, cmp);
|
||||||
rh = rb_assert_r(rn, cmp);
|
rh = rb_assert_r(rn, cmp);
|
||||||
|
|
||||||
if ( (ln && cmp(ln->key, node->key) >= 0) &&
|
if ( (ln && cmp(ln->key, node->key) >= 0) &&
|
||||||
(rn && cmp(rn->key, node->key) <= 0) ) {
|
(rn && cmp(rn->key, node->key) <= 0) ) {
|
||||||
rb_err("Binary tree violation");
|
rb_err("Binary tree violation");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rh != 0 && lh != 0) {
|
if (rh != 0 && lh != 0) {
|
||||||
|
|
||||||
if (rh != lh) {
|
if (rh != lh) {
|
||||||
rb_err("Black height violation");
|
rb_err("Black height violation");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return is_red(node) ? lh : lh+1;
|
return is_red(node) ? lh : lh+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#undef rb_err
|
#undef rb_err
|
||||||
|
|
||||||
|
|
@ -118,67 +118,67 @@ static void rb_assert(rbtree *tree) {
|
||||||
* Recursivly walks a tree, applying action function on every node
|
* Recursivly walks a tree, applying action function on every node
|
||||||
*/
|
*/
|
||||||
static void rbwalk(rbnode *n, void (*action)(const void *)) {
|
static void rbwalk(rbnode *n, void (*action)(const void *)) {
|
||||||
|
|
||||||
if (!n)
|
if (!n)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
rbwalk(n->child[0], action);
|
rbwalk(n->child[0], action);
|
||||||
action(n->key);
|
action(n->key);
|
||||||
rbwalk(n->child[1], action);
|
rbwalk(n->child[1], action);
|
||||||
}
|
}
|
||||||
|
|
||||||
static rbnode* rotate_single(rbnode *root, int dir) {
|
static rbnode* rotate_single(rbnode *root, int dir) {
|
||||||
|
|
||||||
rbnode *save = root->child[!dir];
|
rbnode *save = root->child[!dir];
|
||||||
|
|
||||||
root->child[!dir] = save->child[dir];
|
root->child[!dir] = save->child[dir];
|
||||||
save->child[dir] = root;
|
save->child[dir] = root;
|
||||||
|
|
||||||
root->color = RB_RED;
|
root->color = RB_RED;
|
||||||
save->color = RB_BLACK;
|
save->color = RB_BLACK;
|
||||||
|
|
||||||
return save;
|
return save;
|
||||||
}
|
}
|
||||||
|
|
||||||
static rbnode* rotate_double(rbnode *root, int dir) {
|
static rbnode* rotate_double(rbnode *root, int dir) {
|
||||||
root->child[!dir] = rotate_single(root->child[!dir], !dir);
|
root->child[!dir] = rotate_single(root->child[!dir], !dir);
|
||||||
return rotate_single(root, dir);
|
return rotate_single(root, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rbtree_is_empty(rbtree *tree) {
|
int rbtree_is_empty(rbtree *tree) {
|
||||||
|
|
||||||
return tree == NULL || tree->root == NULL;
|
return tree == NULL || tree->root == NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Searches a tree by key.
|
* Searches a tree by key.
|
||||||
*/
|
*/
|
||||||
void* rbtree_search(rbtree *tree, const void *key) {
|
void* rbtree_search(rbtree *tree, const void *key) {
|
||||||
|
|
||||||
rbnode *n;
|
rbnode *n;
|
||||||
|
|
||||||
if (!tree || !tree->cmp_fn)
|
if (!tree || !tree->cmp_fn)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
n = tree->root;
|
n = tree->root;
|
||||||
|
|
||||||
while(n) {
|
while(n) {
|
||||||
int cmp = tree->cmp_fn(n->key, key);
|
int cmp = tree->cmp_fn(n->key, key);
|
||||||
|
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
return (void *) n->key;
|
return (void *) n->key;
|
||||||
|
|
||||||
n = n->child[cmp < 0];
|
n = n->child[cmp < 0];
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rbtree_walk(rbtree *tree, void (*action)(const void *)) {
|
void rbtree_walk(rbtree *tree, void (*action)(const void *)) {
|
||||||
|
|
||||||
if (!tree || !action)
|
if (!tree || !action)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
rbwalk(tree->root, action);
|
rbwalk(tree->root, action);
|
||||||
|
|
||||||
#ifdef __DEBUG__
|
#ifdef __DEBUG__
|
||||||
rb_assert(tree);
|
rb_assert(tree);
|
||||||
|
|
@ -186,12 +186,12 @@ void rbtree_walk(rbtree *tree, void (*action)(const void *)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void rbtree_free(rbtree *tree, void (*free_fn)(void *)) {
|
void rbtree_free(rbtree *tree, void (*free_fn)(void *)) {
|
||||||
|
|
||||||
if (!tree)
|
if (!tree)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
node_dealloc(tree->root, free_fn);
|
node_dealloc(tree->root, free_fn);
|
||||||
tree->root = NULL;
|
tree->root = NULL;
|
||||||
|
|
||||||
#ifdef __DEBUG__
|
#ifdef __DEBUG__
|
||||||
rb_assert(tree);
|
rb_assert(tree);
|
||||||
|
|
@ -199,71 +199,71 @@ void rbtree_free(rbtree *tree, void (*free_fn)(void *)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int rbtree_insert(rbtree *tree, const void *key) {
|
int rbtree_insert(rbtree *tree, const void *key) {
|
||||||
|
|
||||||
rbnode head = {0};
|
rbnode head = {0};
|
||||||
|
|
||||||
/* grandparent and parent */
|
/* grandparent and parent */
|
||||||
rbnode *g, *t;
|
rbnode *g, *t;
|
||||||
|
|
||||||
/* iterator and parent */
|
/* iterator and parent */
|
||||||
rbnode *p, *q;
|
rbnode *p, *q;
|
||||||
|
|
||||||
int dir = 0, last = 0;
|
int dir = 0, last = 0;
|
||||||
|
|
||||||
if (!tree || !tree->cmp_fn)
|
if (!tree || !tree->cmp_fn)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!tree->root) {
|
if (!tree->root) {
|
||||||
tree->root = q = node_alloc(key);
|
tree->root = q = node_alloc(key);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
t = &head;
|
t = &head;
|
||||||
g = p = NULL;
|
g = p = NULL;
|
||||||
q = t->child[1] = tree->root;
|
q = t->child[1] = tree->root;
|
||||||
|
|
||||||
/* somewhere in here, there should be dragons */
|
/* somewhere in here, there should be dragons */
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
int cmp;
|
int cmp;
|
||||||
|
|
||||||
if (q == NULL) {
|
if (q == NULL) {
|
||||||
p->child[dir] = q = node_alloc(key);
|
p->child[dir] = q = node_alloc(key);
|
||||||
} else if (is_red(q->child[0]) && is_red(q->child[1])) {
|
} else if (is_red(q->child[0]) && is_red(q->child[1])) {
|
||||||
/* color flip case */
|
/* color flip case */
|
||||||
q->color = RB_RED;
|
q->color = RB_RED;
|
||||||
q->child[0]->color = RB_BLACK;
|
q->child[0]->color = RB_BLACK;
|
||||||
q->child[1]->color = RB_BLACK;
|
q->child[1]->color = RB_BLACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fix red validation */
|
/* fix red validation */
|
||||||
if (is_red(q) && is_red(p)) {
|
if (is_red(q) && is_red(p)) {
|
||||||
int dir2 = (t->child[1] == g);
|
int dir2 = (t->child[1] == g);
|
||||||
if (q == p->child[last])
|
if (q == p->child[last])
|
||||||
t->child[dir2] = rotate_single(g, !last);
|
t->child[dir2] = rotate_single(g, !last);
|
||||||
else
|
else
|
||||||
t->child[dir2] = rotate_double(g, !last);
|
t->child[dir2] = rotate_double(g, !last);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmp = tree->cmp_fn(q->key, key);
|
cmp = tree->cmp_fn(q->key, key);
|
||||||
|
|
||||||
if (cmp == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
last = dir;
|
|
||||||
dir = cmp < 0;
|
|
||||||
|
|
||||||
if (g)
|
|
||||||
t = g;
|
|
||||||
g = p, p = q;
|
|
||||||
q = q->child[dir];
|
|
||||||
}
|
|
||||||
|
|
||||||
tree->root = head.child[1];
|
if (cmp == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
last = dir;
|
||||||
|
dir = cmp < 0;
|
||||||
|
|
||||||
|
if (g)
|
||||||
|
t = g;
|
||||||
|
g = p, p = q;
|
||||||
|
q = q->child[dir];
|
||||||
|
}
|
||||||
|
|
||||||
|
tree->root = head.child[1];
|
||||||
|
|
||||||
done:
|
done:
|
||||||
/* root should be black */
|
/* root should be black */
|
||||||
tree->root->color = RB_BLACK;
|
tree->root->color = RB_BLACK;
|
||||||
|
|
||||||
#ifdef __DEBUG__
|
#ifdef __DEBUG__
|
||||||
rb_assert(tree);
|
rb_assert(tree);
|
||||||
|
|
@ -273,46 +273,46 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
void* rbtree_delete(rbtree *tree, const void *key) {
|
void* rbtree_delete(rbtree *tree, const void *key) {
|
||||||
|
|
||||||
rbnode head = {0};
|
|
||||||
|
|
||||||
/* helpers*/
|
|
||||||
rbnode *q, *p, *g, *s;
|
|
||||||
|
|
||||||
/* found item */
|
|
||||||
rbnode *f = NULL, *ret = NULL;
|
|
||||||
|
|
||||||
int dir = 1, dir2, last;
|
|
||||||
|
|
||||||
if (rbtree_is_empty(tree) || !tree->cmp_fn)
|
rbnode head = {0};
|
||||||
return 0;
|
|
||||||
|
/* helpers*/
|
||||||
q = &head;
|
rbnode *q, *p, *g, *s;
|
||||||
g = p = NULL;
|
|
||||||
q->child[1] = tree->root;
|
/* found item */
|
||||||
|
rbnode *f = NULL, *ret = NULL;
|
||||||
/* more dragons (killed some of them though) */
|
|
||||||
|
int dir = 1, dir2, last;
|
||||||
while(q->child[dir]) {
|
|
||||||
|
if (rbtree_is_empty(tree) || !tree->cmp_fn)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
q = &head;
|
||||||
|
g = p = NULL;
|
||||||
|
q->child[1] = tree->root;
|
||||||
|
|
||||||
|
/* more dragons (killed some of them though) */
|
||||||
|
|
||||||
|
while(q->child[dir]) {
|
||||||
int cmp;
|
int cmp;
|
||||||
|
|
||||||
g = p, p = q;
|
g = p, p = q;
|
||||||
q = q->child[dir];
|
q = q->child[dir];
|
||||||
last = dir;
|
last = dir;
|
||||||
|
|
||||||
cmp = tree->cmp_fn(q->key, key);
|
cmp = tree->cmp_fn(q->key, key);
|
||||||
dir = cmp < 0;
|
dir = cmp < 0;
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
f = q;
|
f = q;
|
||||||
|
|
||||||
if (is_red(q) || is_red(q->child[dir]))
|
if (is_red(q) || is_red(q->child[dir]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (is_red(q->child[!dir])) {
|
if (is_red(q->child[!dir])) {
|
||||||
p = p->child[last] = rotate_single(q, dir);
|
p = p->child[last] = rotate_single(q, dir);
|
||||||
} else {
|
} else {
|
||||||
s = p->child[!last];
|
s = p->child[!last];
|
||||||
|
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -321,35 +321,35 @@ void* rbtree_delete(rbtree *tree, const void *key) {
|
||||||
s->color = q->color = RB_RED;
|
s->color = q->color = RB_RED;
|
||||||
} else {
|
} else {
|
||||||
dir2 = (g->child[1] == p);
|
dir2 = (g->child[1] == p);
|
||||||
|
|
||||||
if (is_red(s->child[last]))
|
if (is_red(s->child[last]))
|
||||||
g->child[dir2] = rotate_double(p, last);
|
g->child[dir2] = rotate_double(p, last);
|
||||||
else if (is_red(s->child[!last]))
|
else if (is_red(s->child[!last]))
|
||||||
g->child[dir2] = rotate_single(p, last);
|
g->child[dir2] = rotate_single(p, last);
|
||||||
|
|
||||||
q->color = g->child[dir2]->color = RB_RED;
|
q->color = g->child[dir2]->color = RB_RED;
|
||||||
g->child[dir2]->child[0]->color = RB_BLACK;
|
g->child[dir2]->child[0]->color = RB_BLACK;
|
||||||
g->child[dir2]->child[1]->color = RB_BLACK;
|
g->child[dir2]->child[1]->color = RB_BLACK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remove if found */
|
/* remove if found */
|
||||||
if (f) {
|
if (f) {
|
||||||
ret = (void*)f->key;
|
ret = (void*)f->key;
|
||||||
if (f != q)
|
if (f != q)
|
||||||
f->key = q->key;
|
f->key = q->key;
|
||||||
swap(p, 1, q) = swap(q, 0, NULL);
|
swap(p, 1, q) = swap(q, 0, NULL);
|
||||||
xfree(q);
|
xfree(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
tree->root = head.child[1];
|
tree->root = head.child[1];
|
||||||
if (tree->root)
|
if (tree->root)
|
||||||
tree->root->color = RB_BLACK;
|
tree->root->color = RB_BLACK;
|
||||||
|
|
||||||
#ifdef __DEBUG__
|
#ifdef __DEBUG__
|
||||||
rb_assert(tree);
|
rb_assert(tree);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/* rbtree.h
|
/* rbtree.h
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2011 Henrik Hautakoski <henrik@fiktivkod.org>
|
* Copyright (C) 2010-2011 Henrik Hautakoski <henrik@fiktivkod.org>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct _rbn *root;
|
struct _rbn *root;
|
||||||
/* user defined operations */
|
/* user defined operations */
|
||||||
int (*cmp_fn)(const void *, const void *);
|
int (*cmp_fn)(const void *, const void *);
|
||||||
} rbtree;
|
} rbtree;
|
||||||
|
|
|
||||||
|
|
@ -95,13 +95,13 @@ int str_list_insert(struct str_list *list, const char *str) {
|
||||||
|
|
||||||
list->items = xrealloc(list->items, sizeof(list->items) * (list->nr + 1));
|
list->items = xrealloc(list->items, sizeof(list->items) * (list->nr + 1));
|
||||||
if (index < list->nr) {
|
if (index < list->nr) {
|
||||||
memmove(list->items + index + 1, list->items + index,
|
memmove(list->items + index + 1, list->items + index,
|
||||||
sizeof(list->items) * (list->nr - index));
|
sizeof(list->items) * (list->nr - index));
|
||||||
}
|
}
|
||||||
|
|
||||||
list->items[index] = (char *) str;
|
list->items[index] = (char *) str;
|
||||||
list->nr++;
|
list->nr++;
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,7 +114,7 @@ char* str_list_remove(struct str_list *list, const char *str) {
|
||||||
if (match && index < list->nr) {
|
if (match && index < list->nr) {
|
||||||
item = list->items[index];
|
item = list->items[index];
|
||||||
if (index < --list->nr) {
|
if (index < --list->nr) {
|
||||||
memmove(list->items + index, list->items + index + 1,
|
memmove(list->items + index, list->items + index + 1,
|
||||||
sizeof(list->items) * (list->nr - index));
|
sizeof(list->items) * (list->nr - index));
|
||||||
}
|
}
|
||||||
resize(list);
|
resize(list);
|
||||||
|
|
@ -160,12 +160,10 @@ char** str_list_export(struct str_list *list) {
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
char **out = xmalloc(sizeof(char*) * (list->nr + 1));
|
char **out = xmalloc(sizeof(char*) * (list->nr + 1));
|
||||||
|
|
||||||
for(i=0; i < list->nr; i++)
|
for(i=0; i < list->nr; i++)
|
||||||
out[i] = list->items[i];
|
out[i] = list->items[i];
|
||||||
out[list->nr] = NULL;
|
out[list->nr] = NULL;
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
70
src/strbuf.c
70
src/strbuf.c
|
|
@ -22,26 +22,26 @@ char strbuf_null = '\0';
|
||||||
|
|
||||||
void strbuf_init(strbuf_t *s) {
|
void strbuf_init(strbuf_t *s) {
|
||||||
|
|
||||||
s->buf = &strbuf_null;
|
s->buf = &strbuf_null;
|
||||||
s->alloc_size = s->len = 0;
|
s->alloc_size = s->len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t strbuf_avail(strbuf_t *s) {
|
size_t strbuf_avail(strbuf_t *s) {
|
||||||
|
|
||||||
return s->alloc_size ? s->alloc_size - (s->len + 1) : 0;
|
return s->alloc_size ? s->alloc_size - (s->len + 1) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void strbuf_expand(strbuf_t *s, size_t len) {
|
void strbuf_expand(strbuf_t *s, size_t len) {
|
||||||
|
|
||||||
if (s->len + len + 1 < s->alloc_size)
|
if (s->len + len + 1 < s->alloc_size)
|
||||||
return;
|
return;
|
||||||
if (!s->alloc_size)
|
if (!s->alloc_size)
|
||||||
s->buf = NULL;
|
s->buf = NULL;
|
||||||
|
|
||||||
do
|
do
|
||||||
s->alloc_size += CHNK_SIZE;
|
s->alloc_size += CHNK_SIZE;
|
||||||
while(s->len + len + 1 > s->alloc_size);
|
while(s->len + len + 1 > s->alloc_size);
|
||||||
|
|
||||||
s->buf = xrealloc(s->buf, s->alloc_size);
|
s->buf = xrealloc(s->buf, s->alloc_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,25 +66,25 @@ void strbuf_setlen(strbuf_t *s, size_t len) {
|
||||||
|
|
||||||
char* strbuf_release(strbuf_t *s) {
|
char* strbuf_release(strbuf_t *s) {
|
||||||
|
|
||||||
char *ret;
|
char *ret;
|
||||||
|
|
||||||
if (!s->alloc_size)
|
if (!s->alloc_size)
|
||||||
ret = xmallocz(1);
|
ret = xmallocz(1);
|
||||||
else if (s->len + 1 != s->alloc_size)
|
else if (s->len + 1 != s->alloc_size)
|
||||||
ret = xrealloc(s->buf, s->len + 1);
|
ret = xrealloc(s->buf, s->len + 1);
|
||||||
else
|
else
|
||||||
ret = s->buf;
|
ret = s->buf;
|
||||||
|
|
||||||
strbuf_init(s);
|
strbuf_init(s);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void strbuf_free(strbuf_t *s) {
|
void strbuf_free(strbuf_t *s) {
|
||||||
|
|
||||||
if (!s->alloc_size)
|
if (!s->alloc_size)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
xfree(s->buf);
|
xfree(s->buf);
|
||||||
strbuf_init(s);
|
strbuf_init(s);
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +122,7 @@ void strbuf_appendf(strbuf_t *s, const char *fmt, ...) {
|
||||||
|
|
||||||
va_list va;
|
va_list va;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (!strbuf_avail(s))
|
if (!strbuf_avail(s))
|
||||||
strbuf_expand(s, CHNK_SIZE-1);
|
strbuf_expand(s, CHNK_SIZE-1);
|
||||||
|
|
||||||
|
|
@ -131,10 +131,10 @@ void strbuf_appendf(strbuf_t *s, const char *fmt, ...) {
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
strbuf_expand(s, len);
|
strbuf_expand(s, len);
|
||||||
va_start(va, fmt);
|
va_start(va, fmt);
|
||||||
len = strbuf_append_va(s, fmt, va);
|
len = strbuf_append_va(s, fmt, va);
|
||||||
va_end(va);
|
va_end(va);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -186,8 +186,8 @@ void strbuf_term(strbuf_t *s, char ch) {
|
||||||
|
|
||||||
void strbuf_trim(strbuf_t *s) {
|
void strbuf_trim(strbuf_t *s) {
|
||||||
|
|
||||||
strbuf_rtrim(s);
|
strbuf_rtrim(s);
|
||||||
strbuf_ltrim(s);
|
strbuf_ltrim(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void strbuf_rtrim(strbuf_t *s) {
|
void strbuf_rtrim(strbuf_t *s) {
|
||||||
|
|
@ -200,15 +200,15 @@ void strbuf_rtrim(strbuf_t *s) {
|
||||||
void strbuf_ltrim(strbuf_t *s) {
|
void strbuf_ltrim(strbuf_t *s) {
|
||||||
|
|
||||||
size_t i, of = 0;
|
size_t i, of = 0;
|
||||||
|
|
||||||
for(; of < s->len && isspace(s->buf[of]); of++);
|
|
||||||
|
|
||||||
if (of < 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
s->len -= of;
|
for(; of < s->len && isspace(s->buf[of]); of++);
|
||||||
for(i=0; i <= s->len; i++)
|
|
||||||
s->buf[i] = s->buf[i + of];
|
if (of < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
s->len -= of;
|
||||||
|
for(i=0; i <= s->len; i++)
|
||||||
|
s->buf[i] = s->buf[i + of];
|
||||||
}
|
}
|
||||||
|
|
||||||
void strbuf_rev(strbuf_t *s) {
|
void strbuf_rev(strbuf_t *s) {
|
||||||
|
|
@ -251,7 +251,7 @@ strbuf_t** strbuf_explode(const strbuf_t *s, char sep) {
|
||||||
strbuf_t *tmp, **list;
|
strbuf_t *tmp, **list;
|
||||||
|
|
||||||
list = xmallocz(sizeof(strbuf_t *) * count);
|
list = xmallocz(sizeof(strbuf_t *) * count);
|
||||||
|
|
||||||
p = s->buf;
|
p = s->buf;
|
||||||
while(p < s->buf + s->len) {
|
while(p < s->buf + s->len) {
|
||||||
char *d = memchr(p, sep, s->len - (p - s->buf));
|
char *d = memchr(p, sep, s->len - (p - s->buf));
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ void tree_traverse(struct tree *tree, tree_traverse_fn fn, void *data) {
|
||||||
size_t tree_parent_count(struct tree *tree) {
|
size_t tree_parent_count(struct tree *tree) {
|
||||||
|
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
|
|
||||||
if (tree) {
|
if (tree) {
|
||||||
for(; tree->parent; count++)
|
for(; tree->parent; count++)
|
||||||
tree = tree->parent;
|
tree = tree->parent;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TREE_H
|
#ifndef __TREE_H
|
||||||
#define __TREE_H
|
#define __TREE_H
|
||||||
|
|
||||||
|
|
@ -37,7 +37,7 @@ struct tree* tree_link(struct tree *parent, struct tree *tree);
|
||||||
|
|
||||||
void tree_unlink(struct tree *tree);
|
void tree_unlink(struct tree *tree);
|
||||||
|
|
||||||
void tree_move(struct tree *dest, struct tree *src);
|
void tree_move(struct tree *dest, struct tree *src);
|
||||||
|
|
||||||
void tree_detach(struct tree *tree);
|
void tree_detach(struct tree *tree);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ void* xrealloc(void *ptr, size_t size) {
|
||||||
|
|
||||||
void *new;
|
void *new;
|
||||||
CHECK_INPUT(size, "xrealloc");
|
CHECK_INPUT(size, "xrealloc");
|
||||||
|
|
||||||
new = realloc(ptr, size);
|
new = realloc(ptr, size);
|
||||||
if (!new)
|
if (!new)
|
||||||
die("xrealloc: Can't resize memory block (%s) on '%p' with size '%lu'",
|
die("xrealloc: Can't resize memory block (%s) on '%p' with size '%lu'",
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
# Helper for touching a number of files in a directory.
|
# Helper for touching a number of files in a directory.
|
||||||
|
|
||||||
if [ $# -lt 1 ]; then
|
if [ $# -lt 1 ]; then
|
||||||
echo "usage: $0 <dir> [ <nfiles> ]"
|
echo "usage: $0 <dir> [ <nfiles> ]"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -d $1 ]; then
|
if [ ! -d $1 ]; then
|
||||||
|
|
@ -23,5 +23,5 @@ if [ $# -gt 1 ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for i in `seq 0 ${NFILES}`; do
|
for i in `seq 0 ${NFILES}`; do
|
||||||
touch "${1}/file${i}"
|
touch "${1}/file${i}"
|
||||||
done
|
done
|
||||||
|
|
|
||||||
|
|
@ -4,43 +4,43 @@
|
||||||
#include "../src/fscrawl.h"
|
#include "../src/fscrawl.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
fscrawl_t crawl;
|
fscrawl_t crawl;
|
||||||
unsigned int c_ent = 0, verbose = 0;
|
unsigned int c_ent = 0, verbose = 0;
|
||||||
time_t t1, t2, tdiff;
|
time_t t1, t2, tdiff;
|
||||||
|
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (argc > 2 && (argv[2][0] == '1' && argv[2][1] == '\0'))
|
if (argc > 2 && (argv[2][0] == '1' && argv[2][1] == '\0'))
|
||||||
verbose = 1;
|
verbose = 1;
|
||||||
|
|
||||||
crawl = fsc_open(argv[1]);
|
crawl = fsc_open(argv[1]);
|
||||||
|
|
||||||
if (crawl == NULL) {
|
if (crawl == NULL) {
|
||||||
printf("Invalid path\n");
|
printf("Invalid path\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
t1 = time(NULL);
|
t1 = time(NULL);
|
||||||
for(;;) {
|
for(;;) {
|
||||||
fs_entry *ent = fsc_read(crawl);
|
fs_entry *ent = fsc_read(crawl);
|
||||||
|
|
||||||
if (!ent)
|
if (!ent)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf("%s%s%c\n", ent->base, ent->name,
|
printf("%s%s%c\n", ent->base, ent->name,
|
||||||
ent->dir ? '/' : '\0');
|
ent->dir ? '/' : '\0');
|
||||||
|
|
||||||
c_ent++;
|
c_ent++;
|
||||||
}
|
}
|
||||||
t2 = time(NULL);
|
t2 = time(NULL);
|
||||||
|
|
||||||
fsc_close(crawl);
|
fsc_close(crawl);
|
||||||
|
|
||||||
tdiff = t2 - t1;
|
tdiff = t2 - t1;
|
||||||
printf("Nodes: %u\n"
|
printf("Nodes: %u\n"
|
||||||
"Time (sec): %ld\n", c_ent, tdiff);
|
"Time (sec): %ld\n", c_ent, tdiff);
|
||||||
|
|
||||||
printf("Node/sec: ");
|
printf("Node/sec: ");
|
||||||
|
|
@ -50,5 +50,5 @@ int main(int argc, char *argv[]) {
|
||||||
puts("INF");
|
puts("INF");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ static void validate_list(int index, struct list *list) {
|
||||||
|
|
||||||
if (i != wdref[index])
|
if (i != wdref[index])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
assert(list_has(list, pathref[index], cmp));
|
assert(list_has(list, pathref[index], cmp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +78,7 @@ void test_inotify_unmap_path() {
|
||||||
void test_inotify_unmap_all() {
|
void test_inotify_unmap_all() {
|
||||||
|
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
inotify_unmap_all();
|
inotify_unmap_all();
|
||||||
assert(inotify_map_isempty());
|
assert(inotify_map_isempty());
|
||||||
|
|
||||||
|
|
@ -90,7 +90,7 @@ void test_inotify_map_get_wd() {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
for(i=0; i < 4; i++)
|
for(i=0; i < 4; i++)
|
||||||
assert(inotify_map_get_wd(pathref[i]) == wdref[i]);
|
assert(inotify_map_get_wd(pathref[i]) == wdref[i]);
|
||||||
|
|
||||||
|
|
@ -107,7 +107,7 @@ void test_inotify_map_get_path() {
|
||||||
validate_list(i, inotify_map_get_path(wdref[i]));
|
validate_list(i, inotify_map_get_path(wdref[i]));
|
||||||
|
|
||||||
assert(inotify_map_get_path(25) == NULL);
|
assert(inotify_map_get_path(25) == NULL);
|
||||||
|
|
||||||
teardown();
|
teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,6 +118,6 @@ int main() {
|
||||||
test_inotify_unmap_all();
|
test_inotify_unmap_all();
|
||||||
test_inotify_map_get_wd();
|
test_inotify_map_get_wd();
|
||||||
test_inotify_map_get_path();
|
test_inotify_map_get_path();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ int main() {
|
||||||
|
|
||||||
printf("---\n");
|
printf("---\n");
|
||||||
tree_traverse((struct tree*)root, print_node, NULL);
|
tree_traverse((struct tree*)root, print_node, NULL);
|
||||||
|
|
||||||
inotify_watch_destroy(root, NULL);
|
inotify_watch_destroy(root, NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ void test_size() {
|
||||||
list_insert(l, NULL);
|
list_insert(l, NULL);
|
||||||
list_insert(l, NULL);
|
list_insert(l, NULL);
|
||||||
assert(list_size(l) == 2);
|
assert(list_size(l) == 2);
|
||||||
|
|
||||||
list_destroy(l);
|
list_destroy(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ int main() {
|
||||||
|
|
||||||
logerrno(LOG_CRIT, "malloc", ENOMEM);
|
logerrno(LOG_CRIT, "malloc", ENOMEM);
|
||||||
logerrno(LOG_CRIT, NULL, ENOENT);
|
logerrno(LOG_CRIT, NULL, ENOENT);
|
||||||
|
|
||||||
logmsg(LOG_DEBUG, "Should not show");
|
logmsg(LOG_DEBUG, "Should not show");
|
||||||
|
|
||||||
logmsg(LOG_INFO | LOG_CRIT, "Should not work, can only log to one priority");
|
logmsg(LOG_INFO | LOG_CRIT, "Should not work, can only log to one priority");
|
||||||
|
|
|
||||||
|
|
@ -3,34 +3,35 @@
|
||||||
#include "../src/notify.h"
|
#include "../src/notify.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
notify_event *event;
|
|
||||||
|
|
||||||
if (argc < 2)
|
notify_event *event;
|
||||||
return 1;
|
|
||||||
|
|
||||||
notify_init();
|
if (argc < 2)
|
||||||
|
return 1;
|
||||||
if (!notify_add_watch(argv[1]))
|
|
||||||
return 1;
|
notify_init();
|
||||||
|
|
||||||
printf("begin watching on: %s\n", argv[1]);
|
if (!notify_add_watch(argv[1]))
|
||||||
|
return 1;
|
||||||
for (;;) {
|
|
||||||
|
printf("begin watching on: %s\n", argv[1]);
|
||||||
event = notify_read();
|
|
||||||
|
for (;;) {
|
||||||
if (event == NULL)
|
|
||||||
continue;
|
event = notify_read();
|
||||||
|
|
||||||
printf("====================\n"
|
if (event == NULL)
|
||||||
"Type: %s\n"
|
continue;
|
||||||
"Path: %s\n"
|
|
||||||
"Filename: %s\n"
|
printf("====================\n"
|
||||||
"Directory: %u\n"
|
"Type: %s\n"
|
||||||
"====================\n"
|
"Path: %s\n"
|
||||||
, notify_event_typetostr(event), event->path, event->filename, event->dir);
|
"Filename: %s\n"
|
||||||
}
|
"Directory: %u\n"
|
||||||
|
"====================\n"
|
||||||
return 0;
|
, notify_event_typetostr(event), event->path,
|
||||||
|
event->filename, event->dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ void test_dequeue() {
|
||||||
|
|
||||||
for(i=0; i < 512; i++)
|
for(i=0; i < 512; i++)
|
||||||
assert(queue_dequeue(q) == &map[i]);
|
assert(queue_dequeue(q) == &map[i]);
|
||||||
|
|
||||||
tierdown();
|
tierdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ void test_isempty() {
|
||||||
|
|
||||||
assert(queue_isempty(q));
|
assert(queue_isempty(q));
|
||||||
assert(queue_isempty(NULL));
|
assert(queue_isempty(NULL));
|
||||||
|
|
||||||
tierdown();
|
tierdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,6 +94,6 @@ int main() {
|
||||||
|
|
||||||
if (q)
|
if (q)
|
||||||
queue_destroy(q);
|
queue_destroy(q);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ static void vdelete(void *ptr) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(exists);
|
assert(exists);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,7 +68,7 @@ static void setup(int sorted) {
|
||||||
|
|
||||||
if (sorted)
|
if (sorted)
|
||||||
qsort(keyref, NODES, sizeof(keyref[0]), vcmp);
|
qsort(keyref, NODES, sizeof(keyref[0]), vcmp);
|
||||||
|
|
||||||
for(i=0; i < NODES; i++)
|
for(i=0; i < NODES; i++)
|
||||||
rbtree_insert(&tree, &keyref[i]);
|
rbtree_insert(&tree, &keyref[i]);
|
||||||
}
|
}
|
||||||
|
|
@ -106,7 +106,7 @@ void test_rbtree_delete() {
|
||||||
|
|
||||||
if (keyref_exists(NODES/2, i-1, keyref[i]))
|
if (keyref_exists(NODES/2, i-1, keyref[i]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
assert(rbtree_delete(&tree, &keyref[i]));
|
assert(rbtree_delete(&tree, &keyref[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,7 +127,7 @@ void test_rbtree_delete_all() {
|
||||||
|
|
||||||
if (keyref_exists(0, i-1, keyref[i]))
|
if (keyref_exists(0, i-1, keyref[i]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
assert(rbtree_delete(&tree, &keyref[i]));
|
assert(rbtree_delete(&tree, &keyref[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,10 @@ void test_insert() {
|
||||||
str_list_insert(l, "c");
|
str_list_insert(l, "c");
|
||||||
str_list_insert(l, "b");
|
str_list_insert(l, "b");
|
||||||
str_list_insert(l, "d");
|
str_list_insert(l, "d");
|
||||||
|
|
||||||
for(i=0; i < 4; i++)
|
for(i=0; i < 4; i++)
|
||||||
assert(strcmp(l->items[i], ref[i]) == 0);
|
assert(strcmp(l->items[i], ref[i]) == 0);
|
||||||
|
|
||||||
str_list_clear_fn(l, NULL);
|
str_list_clear_fn(l, NULL);
|
||||||
str_list_destroy(l);
|
str_list_destroy(l);
|
||||||
}
|
}
|
||||||
|
|
@ -27,36 +27,36 @@ void test_remove() {
|
||||||
|
|
||||||
char *ref[2] = { "a", "c" };
|
char *ref[2] = { "a", "c" };
|
||||||
struct str_list *l = str_list_create();
|
struct str_list *l = str_list_create();
|
||||||
|
|
||||||
str_list_insert(l, "a");
|
str_list_insert(l, "a");
|
||||||
str_list_insert(l, "c");
|
str_list_insert(l, "c");
|
||||||
str_list_insert(l, "b");
|
str_list_insert(l, "b");
|
||||||
str_list_insert(l, "d");
|
str_list_insert(l, "d");
|
||||||
|
|
||||||
str_list_remove(l, "d");
|
str_list_remove(l, "d");
|
||||||
str_list_remove(l, "b");
|
str_list_remove(l, "b");
|
||||||
|
|
||||||
assert(str_list_size(l) == 2);
|
assert(str_list_size(l) == 2);
|
||||||
assert(strcmp(l->items[0], ref[0]) == 0);
|
assert(strcmp(l->items[0], ref[0]) == 0);
|
||||||
assert(strcmp(l->items[1], ref[1]) == 0);
|
assert(strcmp(l->items[1], ref[1]) == 0);
|
||||||
|
|
||||||
str_list_remove(l, "c");
|
str_list_remove(l, "c");
|
||||||
str_list_remove(l, "a");
|
str_list_remove(l, "a");
|
||||||
|
|
||||||
assert(str_list_size(l) == 0);
|
assert(str_list_size(l) == 0);
|
||||||
str_list_destroy(l);
|
str_list_destroy(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_isempty() {
|
void test_isempty() {
|
||||||
|
|
||||||
struct str_list *l = NULL;
|
struct str_list *l = NULL;
|
||||||
|
|
||||||
assert(str_list_isempty(l));
|
assert(str_list_isempty(l));
|
||||||
l = str_list_create();
|
l = str_list_create();
|
||||||
assert(str_list_isempty(l));
|
assert(str_list_isempty(l));
|
||||||
str_list_insert(l, "string");
|
str_list_insert(l, "string");
|
||||||
assert(str_list_isempty(l) == 0);
|
assert(str_list_isempty(l) == 0);
|
||||||
|
|
||||||
str_list_clear_fn(l, NULL);
|
str_list_clear_fn(l, NULL);
|
||||||
str_list_destroy(l);
|
str_list_destroy(l);
|
||||||
}
|
}
|
||||||
|
|
@ -64,14 +64,14 @@ void test_isempty() {
|
||||||
void test_size() {
|
void test_size() {
|
||||||
|
|
||||||
struct str_list *l = NULL;
|
struct str_list *l = NULL;
|
||||||
|
|
||||||
assert(str_list_size(l) == 0);
|
assert(str_list_size(l) == 0);
|
||||||
l = str_list_create();
|
l = str_list_create();
|
||||||
assert(str_list_size(l) == 0);
|
assert(str_list_size(l) == 0);
|
||||||
str_list_insert(l, "a");
|
str_list_insert(l, "a");
|
||||||
str_list_insert(l, "b");
|
str_list_insert(l, "b");
|
||||||
assert(str_list_size(l) == 2);
|
assert(str_list_size(l) == 2);
|
||||||
|
|
||||||
str_list_clear_fn(l, NULL);
|
str_list_clear_fn(l, NULL);
|
||||||
str_list_destroy(l);
|
str_list_destroy(l);
|
||||||
}
|
}
|
||||||
|
|
@ -105,7 +105,7 @@ void test_foreach() {
|
||||||
|
|
||||||
str_list_foreach(item, l) {
|
str_list_foreach(item, l) {
|
||||||
assert_string(ref[i], *item);
|
assert_string(ref[i], *item);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
str_list_clear_fn(l, NULL);
|
str_list_clear_fn(l, NULL);
|
||||||
|
|
@ -115,12 +115,12 @@ void test_foreach() {
|
||||||
void test_has() {
|
void test_has() {
|
||||||
|
|
||||||
struct str_list *l = str_list_create();
|
struct str_list *l = str_list_create();
|
||||||
|
|
||||||
str_list_insert(l, "something");
|
str_list_insert(l, "something");
|
||||||
str_list_insert(l, "somethingelse");
|
str_list_insert(l, "somethingelse");
|
||||||
assert(str_list_has(l, l->items[1]));
|
assert(str_list_has(l, l->items[1]));
|
||||||
assert(str_list_has(l, "don't exists") == 0);
|
assert(str_list_has(l, "don't exists") == 0);
|
||||||
|
|
||||||
str_list_clear_fn(l, NULL);
|
str_list_clear_fn(l, NULL);
|
||||||
str_list_destroy(l);
|
str_list_destroy(l);
|
||||||
}
|
}
|
||||||
|
|
@ -132,10 +132,10 @@ void test_lookup() {
|
||||||
str_list_insert(l, "something");
|
str_list_insert(l, "something");
|
||||||
str_list_insert(l, "find me");
|
str_list_insert(l, "find me");
|
||||||
str_list_insert(l, "random");
|
str_list_insert(l, "random");
|
||||||
|
|
||||||
assert(strcmp(str_list_lookup(l, "find me"), "find me") == 0);
|
assert(strcmp(str_list_lookup(l, "find me"), "find me") == 0);
|
||||||
assert(str_list_lookup(l, "don't exists") == NULL);
|
assert(str_list_lookup(l, "don't exists") == NULL);
|
||||||
|
|
||||||
str_list_clear_fn(l, NULL);
|
str_list_clear_fn(l, NULL);
|
||||||
str_list_destroy(l);
|
str_list_destroy(l);
|
||||||
}
|
}
|
||||||
|
|
@ -160,7 +160,7 @@ void test_export() {
|
||||||
|
|
||||||
assert(i == 3);
|
assert(i == 3);
|
||||||
free(export);
|
free(export);
|
||||||
|
|
||||||
str_list_clear_fn(l, NULL);
|
str_list_clear_fn(l, NULL);
|
||||||
str_list_destroy(l);
|
str_list_destroy(l);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ void test_setlen() {
|
||||||
|
|
||||||
strbuf_setlen(&b, 25);
|
strbuf_setlen(&b, 25);
|
||||||
assert(b.len == 0);
|
assert(b.len == 0);
|
||||||
|
|
||||||
strbuf_expand(&b, 25);
|
strbuf_expand(&b, 25);
|
||||||
strbuf_setlen(&b, b.alloc_size);
|
strbuf_setlen(&b, b.alloc_size);
|
||||||
assert(b.len == b.alloc_size-1);
|
assert(b.len == b.alloc_size-1);
|
||||||
|
|
@ -60,10 +60,10 @@ void test_release() {
|
||||||
print_strbuf(&b);
|
print_strbuf(&b);
|
||||||
|
|
||||||
str = strbuf_release(&b);
|
str = strbuf_release(&b);
|
||||||
|
|
||||||
printf("released |%s|\n", str);
|
printf("released |%s|\n", str);
|
||||||
|
|
||||||
free(str);
|
free(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_release_empty() {
|
void test_release_empty() {
|
||||||
|
|
@ -107,7 +107,7 @@ void test_chop() {
|
||||||
print_strbuf(&b);
|
print_strbuf(&b);
|
||||||
|
|
||||||
strbuf_append_str(&b, "X");
|
strbuf_append_str(&b, "X");
|
||||||
|
|
||||||
strbuf_rchop(&b, 'X');
|
strbuf_rchop(&b, 'X');
|
||||||
print_strbuf(&b);
|
print_strbuf(&b);
|
||||||
|
|
||||||
|
|
@ -118,7 +118,7 @@ void test_chop() {
|
||||||
|
|
||||||
strbuf_rchop(&b, 'X');
|
strbuf_rchop(&b, 'X');
|
||||||
print_strbuf(&b);
|
print_strbuf(&b);
|
||||||
|
|
||||||
strbuf_free(&b);
|
strbuf_free(&b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,16 +138,16 @@ void test_term() {
|
||||||
void test_trim() {
|
void test_trim() {
|
||||||
|
|
||||||
strbuf_t b = STRBUF_INIT;
|
strbuf_t b = STRBUF_INIT;
|
||||||
|
|
||||||
print_strbuf(&b);
|
print_strbuf(&b);
|
||||||
|
|
||||||
strbuf_append_repeat(&b, ' ', 4);
|
strbuf_append_repeat(&b, ' ', 4);
|
||||||
strbuf_append(&b, "abcdef", 6);
|
strbuf_append(&b, "abcdef", 6);
|
||||||
|
|
||||||
print_strbuf(&b);
|
print_strbuf(&b);
|
||||||
|
|
||||||
strbuf_append(&b, "012345678901234567890123456789", 30);
|
strbuf_append(&b, "012345678901234567890123456789", 30);
|
||||||
strbuf_append_ch(&b, 'a');
|
strbuf_append_ch(&b, 'a');
|
||||||
strbuf_append_repeat(&b, ' ', 6);
|
strbuf_append_repeat(&b, ' ', 6);
|
||||||
|
|
||||||
print_strbuf(&b);
|
print_strbuf(&b);
|
||||||
|
|
@ -155,10 +155,10 @@ void test_trim() {
|
||||||
strbuf_rtrim(&b);
|
strbuf_rtrim(&b);
|
||||||
|
|
||||||
print_strbuf(&b);
|
print_strbuf(&b);
|
||||||
|
|
||||||
strbuf_ltrim(&b);
|
strbuf_ltrim(&b);
|
||||||
|
|
||||||
print_strbuf(&b);
|
print_strbuf(&b);
|
||||||
|
|
||||||
strbuf_free(&b);
|
strbuf_free(&b);
|
||||||
}
|
}
|
||||||
|
|
@ -171,9 +171,9 @@ void test_rev() {
|
||||||
|
|
||||||
print_strbuf(&b);
|
print_strbuf(&b);
|
||||||
|
|
||||||
strbuf_rev(&b);
|
strbuf_rev(&b);
|
||||||
|
|
||||||
print_strbuf(&b);
|
print_strbuf(&b);
|
||||||
|
|
||||||
strbuf_free(&b);
|
strbuf_free(&b);
|
||||||
}
|
}
|
||||||
|
|
@ -239,6 +239,6 @@ int main() {
|
||||||
test_chop();
|
test_chop();
|
||||||
test_explode();
|
test_explode();
|
||||||
test_free_empty();
|
test_free_empty();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ void test_unlink() {
|
||||||
assert(nodes[0].parent == NULL);
|
assert(nodes[0].parent == NULL);
|
||||||
assert(nodes[0].next == NULL);
|
assert(nodes[0].next == NULL);
|
||||||
assert(nodes[0].child == &nodes[1]);
|
assert(nodes[0].child == &nodes[1]);
|
||||||
|
|
||||||
/* move to depth 2 */
|
/* move to depth 2 */
|
||||||
assert(nodes[1].parent == &nodes[0]);
|
assert(nodes[1].parent == &nodes[0]);
|
||||||
assert(nodes[2].parent == &nodes[0]);
|
assert(nodes[2].parent == &nodes[0]);
|
||||||
|
|
@ -71,14 +71,14 @@ void test_unlink() {
|
||||||
assert(nodes[3].child == NULL);
|
assert(nodes[3].child == NULL);
|
||||||
assert(nodes[4].child == NULL);
|
assert(nodes[4].child == NULL);
|
||||||
assert(nodes[5].child == NULL);
|
assert(nodes[5].child == NULL);
|
||||||
|
|
||||||
tree_unlink(&nodes[1]);
|
tree_unlink(&nodes[1]);
|
||||||
|
|
||||||
/* check the new tree */
|
/* check the new tree */
|
||||||
assert(nodes[0].parent == NULL);
|
assert(nodes[0].parent == NULL);
|
||||||
assert(nodes[0].next == NULL);
|
assert(nodes[0].next == NULL);
|
||||||
assert(nodes[0].child == &nodes[2]);
|
assert(nodes[0].child == &nodes[2]);
|
||||||
|
|
||||||
/* move to depth 2 */
|
/* move to depth 2 */
|
||||||
assert(nodes[2].parent == &nodes[0]);
|
assert(nodes[2].parent == &nodes[0]);
|
||||||
assert(nodes[3].parent == &nodes[0]);
|
assert(nodes[3].parent == &nodes[0]);
|
||||||
|
|
@ -89,7 +89,7 @@ void test_unlink() {
|
||||||
assert(nodes[2].child == &nodes[5]);
|
assert(nodes[2].child == &nodes[5]);
|
||||||
assert(nodes[3].child == NULL);
|
assert(nodes[3].child == NULL);
|
||||||
assert(nodes[4].child == NULL);
|
assert(nodes[4].child == NULL);
|
||||||
|
|
||||||
/* move to depth 3 */
|
/* move to depth 3 */
|
||||||
assert(nodes[5].parent == &nodes[2]);
|
assert(nodes[5].parent == &nodes[2]);
|
||||||
assert(nodes[5].next == NULL);
|
assert(nodes[5].next == NULL);
|
||||||
|
|
@ -111,7 +111,7 @@ void test_detach() {
|
||||||
assert(nodes[0].parent == NULL);
|
assert(nodes[0].parent == NULL);
|
||||||
assert(nodes[0].next == NULL);
|
assert(nodes[0].next == NULL);
|
||||||
assert(nodes[0].child == &nodes[1]);
|
assert(nodes[0].child == &nodes[1]);
|
||||||
|
|
||||||
/* move to depth 2 */
|
/* move to depth 2 */
|
||||||
assert(nodes[1].parent == &nodes[0]);
|
assert(nodes[1].parent == &nodes[0]);
|
||||||
assert(nodes[2].parent == &nodes[0]);
|
assert(nodes[2].parent == &nodes[0]);
|
||||||
|
|
@ -137,7 +137,7 @@ void test_detach() {
|
||||||
assert(nodes[0].parent == NULL);
|
assert(nodes[0].parent == NULL);
|
||||||
assert(nodes[0].next == NULL);
|
assert(nodes[0].next == NULL);
|
||||||
assert(nodes[0].child == &nodes[2]);
|
assert(nodes[0].child == &nodes[2]);
|
||||||
|
|
||||||
/* move to depth 2 */
|
/* move to depth 2 */
|
||||||
assert(nodes[2].parent == &nodes[0]);
|
assert(nodes[2].parent == &nodes[0]);
|
||||||
assert(nodes[2].next == NULL);
|
assert(nodes[2].next == NULL);
|
||||||
|
|
|
||||||
|
|
@ -15,22 +15,21 @@ static inline char ranchr() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void __assert_str(const char *file, int line, const char *func, const char *a, const char *b) {
|
void __assert_str(const char *file, int line, const char *func, const char *a, const char *b) {
|
||||||
|
|
||||||
if (a == NULL || b == NULL)
|
if (a == NULL || b == NULL)
|
||||||
__uexit(file, line, func, "a or b is null\n", NULL);
|
__uexit(file, line, func, "a or b is null\n", NULL);
|
||||||
|
|
||||||
if (strcmp(a, b) != 0)
|
if (strcmp(a, b) != 0)
|
||||||
__uexit(file, line, func, "\"%s\" != \"%s\"\n", a, b);
|
__uexit(file, line, func, "\"%s\" != \"%s\"\n", a, b);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void utest_init_RNG() {
|
void utest_init_RNG() {
|
||||||
|
|
||||||
static unsigned char init = 0;
|
static unsigned char init = 0;
|
||||||
|
|
||||||
if (init)
|
if (init)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
init = 1;
|
init = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -52,7 +51,7 @@ char* utest_ran_string(size_t size) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
utest_init_RNG();
|
utest_init_RNG();
|
||||||
|
|
||||||
for(i=0; i < size; i++)
|
for(i=0; i < size; i++)
|
||||||
str[i] = ranchr();
|
str[i] = ranchr();
|
||||||
str[i] = 0;
|
str[i] = 0;
|
||||||
|
|
|
||||||
Reference in a new issue