+Remove XML files and its directory structure once they have been utilized.
+Mark as visited TAL information related to RRDP once per cycle; if no RRDP information was visited (means, the TAL wasn't validated during the cycle) the data is forgotten, including its local data.
+Move the directory tree removal functions to 'common.h', so that it can be called from multiple parts.
+Remove created file in case of error during an HTTP download.
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <sys/types.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
#include <sys/socket.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
#include <sys/stat.h>
+#include "config.h"
#include "log.h"
int
free(localuri);
return 0;
}
+
+static int
+remove_file(char const *path)
+{
+ int error;
+
+ errno = 0;
+ error = remove(path);
+ if (error)
+ return pr_errno(errno, "Couldn't delete %s", path);
+
+ return 0;
+}
+
+/*
+ * Delete parent dirs of @path only if dirs are empty, @path must be a file
+ * location and will be deleted first.
+ *
+ * The algorithm is a bit aggressive, but rmdir() won't delete
+ * something unless is empty, so in case the dir still has something in
+ * it the cycle is finished.
+ */
+int
+delete_dir_recursive_bottom_up(char const *path)
+{
+ char *config_repo;
+ char *work_loc, *tmp;
+ size_t config_len;
+ int error;
+
+ error = remove_file(path);
+ if (error)
+ return error;
+
+ config_repo = strdup(config_get_local_repository());
+ if (config_repo == NULL)
+ return pr_enomem();
+
+ /* Stop dir removal when the work_dir has this length */
+ config_len = strlen(config_repo);
+ if (config_repo[config_len - 1] == '/')
+ config_len--;
+ free(config_repo);
+
+ work_loc = strdup(path);
+ if (work_loc == NULL)
+ return pr_enomem();
+
+ do {
+ tmp = strrchr(work_loc, '/');
+ if (tmp == NULL)
+ break;
+ *tmp = '\0';
+
+ /* Stop if the root dir is reached */
+ if (strlen(work_loc) == config_len)
+ break;
+
+ errno = 0;
+ error = rmdir(work_loc);
+ if (!error)
+ continue; /* Keep deleting up */
+
+ /* Stop if there's content in the dir */
+ if (errno == ENOTEMPTY || errno == EEXIST)
+ break;
+
+ error = pr_errno(errno, "Couldn't delete dir %s", work_loc);
+ goto release_str;
+ } while (true);
+
+ free(work_loc);
+ return 0;
+release_str:
+ free(work_loc);
+ return error;
+}
char const *addr2str6(struct in6_addr const *, char *);
int create_dir_recursive(char const *);
+int delete_dir_recursive_bottom_up(char const *);
#endif /* SRC_RTR_COMMON_H_ */
return error;
close_file:
file_close(out);
+ delete_dir_recursive_bottom_up(uri_get_local(uri));
return error;
}
struct thread *thread;
int error;
+ /* Set existent tal RRDP info to non visited */
+ db_rrdp_reset_visited_tals();
+
SLIST_INIT(&threads);
error = process_file_or_dir(config_get_tal(), TAL_FILE_EXTENSION,
__do_file_validation, table);
thread_destroy(thread);
}
- /* FIXME (now) Remove non-visited rrdps URIS by tal */
+ /* Remove non-visited rrdps URIS by tal */
+ db_rrdp_rem_nonvisited_tals();
return error;
}
}
static void
-tal_elem_destroy(struct tal_elem *elem)
+tal_elem_destroy(struct tal_elem *elem, bool remove_local)
{
+ if (remove_local)
+ db_rrdp_uris_remove_all_local(elem->uris);
db_rrdp_uris_destroy(elem->uris);
free(elem->file_name);
free(elem);
while (!SLIST_EMPTY(&db.tals)) {
elem = db.tals.slh_first;
SLIST_REMOVE_HEAD(&db.tals, next);
- tal_elem_destroy(elem);
+ tal_elem_destroy(elem, false);
}
pthread_rwlock_destroy(&lock);
}
int
db_rrdp_add_tal(char const *tal_name)
{
- struct tal_elem *elem;
+ struct tal_elem *elem, *found;
int error;
/* Element exists, no need to create it again */
- if (db_rrdp_find_tal(tal_name) != NULL)
+ found = db_rrdp_find_tal(tal_name);
+ if (found != NULL) {
+ found->visited = true;
return 0;
+ }
error = tal_elem_create(&elem, tal_name);
if (error)
SLIST_REMOVE(&db.tals, found, tal_elem, next);
rwlock_unlock(&lock);
- tal_elem_destroy(found);
+ tal_elem_destroy(found, true);
}
/* Returns the reference to RRDP URIs of a TAL */
found = db_rrdp_find_tal(tal_name);
return found != NULL ? found->uris : NULL;
}
+
+/* Set all tals to non-visited */
+void
+db_rrdp_reset_visited_tals(void)
+{
+ struct tal_elem *found;
+
+ rwlock_read_lock(&lock);
+ SLIST_FOREACH(found, &db.tals, next)
+ found->visited = false;
+
+ rwlock_unlock(&lock);
+}
+
+/* Remove non-visited tals */
+void
+db_rrdp_rem_nonvisited_tals(void)
+{
+ struct tal_elem *found;
+
+ rwlock_read_lock(&lock);
+ SLIST_FOREACH(found, &db.tals, next) {
+ if (!found->visited) {
+ SLIST_REMOVE(&db.tals, found, tal_elem, next);
+ tal_elem_destroy(found, true);
+ }
+ }
+ rwlock_unlock(&lock);
+}
void db_rrdp_rem_tal(char const *);
struct db_rrdp_uri *db_rrdp_get_uris(char const *);
+void db_rrdp_reset_visited_tals(void);
+void db_rrdp_rem_nonvisited_tals(void);
+
#endif /* SRC_RRDP_DB_DB_RRDP_H_ */
return false;
}
+
+int
+db_rrdp_uris_remove_all_local(struct db_rrdp_uri *uris)
+{
+ struct uris_table *uri_node, *uri_tmp;
+ int error;
+
+ /* Remove each 'visited_uris' from all the table */
+ HASH_ITER(hh, uris->table, uri_node, uri_tmp) {
+ error = visited_uris_remove_local(uri_node->visited_uris);
+ if (error)
+ return error;
+ }
+
+ return 0;
+}
int db_rrdp_uris_get_visited_uris(char const *, struct visited_uris **);
bool db_rrdp_uris_visited_exists(struct db_rrdp_uri *, char const *);
+int db_rrdp_uris_remove_all_local(struct db_rrdp_uri *);
#endif /* SRC_RRDP_DB_DB_RRDP_URIS_H_ */
#include "rrdp/db/db_rrdp_uris.h"
#include "rrdp/rrdp_objects.h"
#include "rrdp/rrdp_parser.h"
-#include "delete_dir_daemon.h"
#include "log.h"
#include "thread_var.h"
#include "visited_uris.h"
error = rrdp_parse_snapshot(notification, tmp);
if (error) {
- free(tmp);
+ visited_uris_refput(tmp);
return error;
}
}
static int
-remove_rrdp_uri_files(struct update_notification *notification)
+remove_rrdp_uri_files(char const *notification_uri)
{
struct visited_uris *tmp;
- char *root_path;
int error;
/* Work with the existent visited uris */
- error = db_rrdp_uris_get_visited_uris(notification->uri, &tmp);
+ error = db_rrdp_uris_get_visited_uris(notification_uri, &tmp);
if (error)
return error;
- error = visited_uris_get_root(tmp, &root_path);
- if (error)
- return error;
-
- error = delete_dir_daemon_start(root_path);
- if (error) {
- free(root_path);
- return error;
- }
-
- free(root_path);
- return 0;
+ return visited_uris_remove_local(tmp);
}
int
pr_warn("There was an error processing RRDP deltas, using the snapshot instead.");
case RRDP_URI_DIFF_SESSION:
/* Delete the old session files */
- error = remove_rrdp_uri_files(upd_notification);
+ error = remove_rrdp_uri_files(upd_notification->uri);
if (error)
break;
case RRDP_URI_NOTFOUND:
goto return_val; /* Error O is OK */
/*
- * FIXME (now) Prepare the callers to receive positive error values,
- * which means the file was successfully parsed but is has a logic error
- * (in this case, session ID doesn't match parent's).
+ * Positive error value means the file was successfully parsed but it
+ * has a logic error (in this case, session ID doesn't match parent's).
*/
if (strcmp(expected_session, session_id) != 0) {
pr_info("File session id [%s] doesn't match parent's session id [%s]",
}
static int
-delete_from_uri(char const *location, struct visited_uris *visited_uris)
+delete_from_uri(struct rpki_uri *uri, struct visited_uris *visited_uris)
{
- struct rpki_uri *uri;
- char *local_uri, *work_loc, *tmp;
int error;
- error = uri_create_mixed_str(&uri, location, strlen(location));
- if (error)
- return error;
-
- local_uri = strdup(uri_get_local(uri));
- if (local_uri == NULL) {
- error = pr_enomem();
- goto release_uri;
- }
-
- errno = 0;
- error = remove(local_uri);
- if (error) {
- error = pr_errno(errno, "Couldn't delete %s", local_uri);
- goto release_str;
+ if (visited_uris) {
+ error = rem_mft_from_list(visited_uris, uri_get_global(uri));
+ if (error)
+ return error;
}
- error = rem_mft_from_list(visited_uris, uri_get_global(uri));
- if (error)
- goto release_str;
-
- /*
- * Delete parent dirs only if empty.
- *
- * The algorithm is a bit aggressive, but rmdir() won't delete
- * something unless is empty, so in case the dir still has something in
- * it the cycle is finished.
- */
- work_loc = local_uri;
- do {
- tmp = strrchr(work_loc, '/');
- if (tmp == NULL)
- break;
- *tmp = '\0';
-
- /* FIXME (now) use a lock, what if the root dir is reached? */
+ /* Delete parent dirs only if empty. */
+ return delete_dir_recursive_bottom_up(uri_get_local(uri));
+}
- errno = 0;
- error = rmdir(work_loc);
- if (!error)
- continue; /* Keep deleting up */
+int
+__delete_from_uri(char const *location, struct visited_uris *visited_uris)
+{
+ struct rpki_uri *uri;
+ int error;
- /* Stop if there's content in the dir */
- if (errno == ENOTEMPTY || errno == EEXIST)
- break;
+ error = uri_create_mixed_str(&uri, location, strlen(location));
+ if (error)
+ return error;
- error = pr_errno(errno, "Couldn't delete dir %s", work_loc);
- goto release_str;
- } while (true);
+ error = delete_from_uri(uri, visited_uris);
- uri_refput(uri);
- free(local_uri);
- return 0;
-release_str:
- free(local_uri);
-release_uri:
+ /* Error 0 is ok */
uri_refput(uri);
return error;
}
if (error)
return error;
- error = delete_from_uri(tmp->doc_data.uri, visited_uris);
+ error = __delete_from_uri(tmp->doc_data.uri, visited_uris);
withdraw_destroy(tmp);
if (error)
return error;
error = parse_delta(uri, delta_head, arg);
+ delete_from_uri(uri, NULL);
/* Error 0 its ok */
release_uri:
uri_refput(uri);
/* No updates yet */
if (error > 0) {
+ delete_from_uri(uri, NULL);
*result = NULL;
return 0;
}
fnstack_push_uri(uri);
error = parse_notification(uri, result);
+ delete_from_uri(uri, NULL);
if (error) {
fnstack_pop();
return error;
error = parse_snapshot(uri, &args);
+ delete_from_uri(uri, NULL);
/* Error 0 is ok */
release_uri:
uri_refput(uri);
#include <stddef.h>
#include <string.h>
#include "log.h"
+#include "delete_dir_daemon.h"
/*
* FIXME (now) This should be replaced with something better (rtrie?)
elem = SLIST_FIRST(uris->list);
+ /* No elements yet */
+ if (elem == NULL) {
+ *result = NULL;
+ return 0;
+ }
+
i = 0;
ptr = strchr(elem->uri, '/');
while(i < 2) {
*result = tmp;
return 0;
}
+
+int
+visited_uris_remove_local(struct visited_uris *uris)
+{
+ char *root_path;
+ int error;
+
+ error = visited_uris_get_root(uris, &root_path);
+ if (error)
+ return error;
+
+ if (root_path == NULL)
+ return 0;
+
+ error = delete_dir_daemon_start(root_path);
+ if (error) {
+ free(root_path);
+ return error;
+ }
+
+ free(root_path);
+ return 0;
+}
int visited_uris_remove(struct visited_uris *, char const *);
bool visited_uris_exists(struct visited_uris *, char const *);
int visited_uris_get_root(struct visited_uris *, char **);
+int visited_uris_remove_local(struct visited_uris *);
#endif /* SRC_VISITED_URIS_H_ */
return NULL;
}
+void
+db_rrdp_reset_visited_tals(void)
+{
+ /* Empty */
+}
+
+void
+db_rrdp_rem_nonvisited_tals(void)
+{
+ /* Empty */
+}
+
START_TEST(tal_load_normal)
{
struct tal *tal;