removefile.c   [plain text]


#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;
		}
		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;

	// allocate the state if it was not passed in
	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_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;
	}

	// deallocate if allocated locally
	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;
	}
}