1#include "removefile.h"
2#include <assert.h>
3#include <errno.h>
4#include <stdio.h>
5#include <fcntl.h>
6#include <pthread.h>
7#include <unistd.h>
8
9static struct timeval tv;
10static void start_timer(const char* str) {
11	fprintf(stderr, "%s... ", str);
12	assert(gettimeofday(&tv, NULL) == 0);
13}
14
15static void stop_timer() {
16	struct timeval tv2;
17	assert(gettimeofday(&tv2, NULL) == 0);
18	long sec = tv2.tv_sec - tv.tv_sec;
19	long usec;
20	if (sec == 0) {
21		usec = tv2.tv_usec - tv.tv_usec;
22	} else {
23		usec = tv2.tv_usec + (1000000 - tv.tv_usec);
24	}
25	fprintf(stderr, "%d.%03d\n", sec, usec);
26}
27
28
29static int removefile_confirm_callback(removefile_state_t state, const char * path, void * context) {
30	assert(context == (void*)1234);
31	fprintf(stderr, "confirm callback: %s\n", path);
32	return REMOVEFILE_PROCEED;
33}
34
35static int removefile_error_callback(removefile_state_t state, const char * path, void * context) {
36	assert(context == (void*)4567);
37	int err = 0;
38	assert(removefile_state_get(state, REMOVEFILE_STATE_ERRNO, &err) == 0);
39	fprintf(stderr, "error callback: %s: %s (%d)\n", path, strerror(err), err);
40	return REMOVEFILE_PROCEED;
41}
42
43static int removefile_status_callback(removefile_state_t state, const char * path, void * context) {
44   fprintf(stderr, "status callback: %s\n", path);
45   return REMOVEFILE_PROCEED;
46}
47
48
49int mkdirs() {
50	start_timer("Creating directory structure");
51	assert(mkdir("/tmp/removefile-test", 0755) == 0);
52	assert(mkdir("/tmp/removefile-test/foo", 0755) == 0);
53	assert(mkdir("/tmp/removefile-test/foo/bar", 0755) == 0);
54	assert(mkdir("/tmp/removefile-test/foo/baz", 0755) == 0);
55	int fd;
56	assert((fd = open("/tmp/removefile-test/foo/baz/woot", O_CREAT | O_TRUNC | O_WRONLY, 0644)) != -1);
57	write(fd, "Hello World\n", 12);
58	close(fd);
59        assert((fd = open("/tmp/removefile-test/foo/baz/wootage", O_CREAT | O_TRUNC | O_WRONLY, 0644)) != -1);
60        write(fd, "Hello World\n", 12);
61	assert(lseek(fd, 1024*1024*30, SEEK_SET) != -1);
62        write(fd, "Goodbye Moon\n", 13);
63        close(fd);
64	stop_timer();
65}
66
67void* threadproc(void* state) {
68	sleep(1);
69	fprintf(stderr, "cancelling...\n");
70	assert(removefile_cancel(state) == 0);
71	return NULL;
72}
73
74int main(int argc, char *argv[]) {
75	removefile_state_t state = NULL;
76	removefile_callback_t callback = NULL;
77	pthread_t thread = NULL;
78	int err = 0;
79
80	mkdirs();
81	start_timer("removefile(NULL)");
82	assert(removefile("/tmp/removefile-test", NULL, REMOVEFILE_SECURE_1_PASS | REMOVEFILE_RECURSIVE) == 0);
83	stop_timer();
84
85
86	mkdirs();
87	assert((state = removefile_state_alloc()) != NULL);
88	assert(pthread_create(&thread, NULL, threadproc, state) == 0);
89	start_timer("removefile(state) with cancel");
90        assert(removefile_state_set(state, REMOVEFILE_STATE_ERROR_CALLBACK, removefile_error_callback) == 0);
91        assert(removefile_state_set(state, REMOVEFILE_STATE_ERROR_CONTEXT, (void*)4567) == 0);
92	assert(removefile("/tmp/removefile-test", state, REMOVEFILE_SECURE_1_PASS | REMOVEFILE_RECURSIVE) == -1 && errno == ECANCELED);
93	stop_timer();
94
95        start_timer("removefile(NULL)");
96        assert(removefile("/tmp/removefile-test", NULL, REMOVEFILE_SECURE_1_PASS | REMOVEFILE_RECURSIVE) == 0);
97        stop_timer();
98
99	mkdirs();
100	assert(removefile_state_set(state, 1234567, (void*)1234567) == -1 && errno == EINVAL);
101
102	assert(removefile_state_set(state, REMOVEFILE_STATE_CONFIRM_CALLBACK, removefile_confirm_callback) == 0);
103	assert(removefile_state_get(state, REMOVEFILE_STATE_CONFIRM_CALLBACK, &callback) == 0);
104	assert(callback == removefile_confirm_callback);
105	assert(removefile_state_set(state, REMOVEFILE_STATE_CONFIRM_CONTEXT, (void*)1234) == 0);
106
107	assert(removefile_state_set(state, REMOVEFILE_STATE_ERROR_CALLBACK, removefile_error_callback) == 0);
108	assert(removefile_state_get(state, REMOVEFILE_STATE_ERROR_CALLBACK, &callback) == 0);
109	assert(callback == removefile_error_callback);
110	assert(removefile_state_set(state, REMOVEFILE_STATE_ERROR_CONTEXT, (void*)4567) == 0);
111
112	assert(removefile_state_set(state, REMOVEFILE_STATE_STATUS_CALLBACK, removefile_status_callback) == 0);
113	assert(removefile_state_get(state, REMOVEFILE_STATE_STATUS_CALLBACK, &callback) == 0);
114	assert(callback == removefile_status_callback);
115	assert(removefile_state_set(state, REMOVEFILE_STATE_STATUS_CONTEXT, (void*)5678) == 0);
116
117	start_timer("removefile(state)");
118	assert(removefile("/tmp/removefile-test", state, REMOVEFILE_SECURE_1_PASS | REMOVEFILE_RECURSIVE) == 0);
119	stop_timer();
120
121	return 0;
122}
123