#include "removefile.h"
#include "removefile_priv.h"
removefile_state_t
removefile_state_alloc() {
removefile_state_t state = (removefile_state_t)calloc(1, sizeof(struct _removefile_state));
if (state != NULL)
state->urand_file = -1;
return state;
}
int
removefile_state_free(removefile_state_t state) {
if (state != NULL) {
if (state->urand_file != -1) {
close(state->urand_file);
state->urand_file = -1;
}
if (state->buffer != NULL) {
free(state->buffer);
state->buffer = NULL;
}
free(state);
}
return 0;
}
int
removefile_state_get(removefile_state_t state, uint32_t key, void* dst) {
switch(key) {
case REMOVEFILE_STATE_CONFIRM_CALLBACK:
*(removefile_callback_t*)dst = state->confirm_callback;
break;
case REMOVEFILE_STATE_CONFIRM_CONTEXT:
*(void**)dst = state->confirm_context;
break;
case REMOVEFILE_STATE_ERROR_CALLBACK:
*(removefile_callback_t*)dst = state->error_callback;
break;
case REMOVEFILE_STATE_ERROR_CONTEXT:
*(void**)dst = state->error_context;
break;
case REMOVEFILE_STATE_ERRNO:
*(int*)dst = state->error_num;
break;
case REMOVEFILE_STATE_STATUS_CALLBACK:
*(removefile_callback_t*)dst = state->status_callback;
break;
case REMOVEFILE_STATE_STATUS_CONTEXT:
*(void**)dst = state->status_context;
break;
default:
errno = EINVAL;
return -1;
}
return 0;
}
int
removefile_state_set(removefile_state_t state, uint32_t key, const void* value) {
switch(key) {
case REMOVEFILE_STATE_CONFIRM_CALLBACK:
state->confirm_callback = value;
break;
case REMOVEFILE_STATE_CONFIRM_CONTEXT:
state->confirm_context = (void *) value;
break;
case REMOVEFILE_STATE_ERROR_CALLBACK:
state->error_callback = value;
break;
case REMOVEFILE_STATE_ERROR_CONTEXT:
state->error_context = (void *) value;
break;
case REMOVEFILE_STATE_ERRNO:
state->error_num = *(int*)value;
break;
case REMOVEFILE_STATE_STATUS_CALLBACK:
state->status_callback = value;
break;
case REMOVEFILE_STATE_STATUS_CONTEXT:
state->status_context = (void *) value;
break;
default:
errno = EINVAL;
return -1;
}
return 0;
}
int
removefile(const char* path, removefile_state_t state_param, removefile_flags_t flags) {
int res = 0;
char* paths[] = { NULL, NULL };
removefile_state_t state = state_param;
if (state_param == NULL) {
state = removefile_state_alloc();
if (state == NULL) {
errno = ENOMEM;
return -1;
}
}
state->cancelled = 0;
state->unlink_flags = flags;
if (flags & (REMOVEFILE_SECURE_7_PASS | REMOVEFILE_SECURE_35_PASS | REMOVEFILE_SECURE_1_PASS | REMOVEFILE_SECURE_3_PASS)) {
__removefile_init_random(getpid(), state);
}
paths[0] = strdup(path);
if (paths[0]) {
res = __removefile_tree_walker(paths, state);
free(paths[0]);
} else {
errno = ENOMEM;
res = -1;
}
if (res == 0) {
sync_volume_np(path, SYNC_VOLUME_WAIT | SYNC_VOLUME_FULLSYNC);
}
if (state_param == NULL) {
removefile_state_free(state);
}
return res;
}
int
removefile_cancel(removefile_state_t state) {
if (state == NULL) {
errno = EINVAL;
return -1;
} else {
state->cancelled = 1;
return 0;
}
}