libmpm

morphux C package management library
Log | Files | Refs | Submodules | README | LICENSE | git clone https://git.ne02ptzero.me/git/libmpm

commit 3303b95273798d20dcef1887c87ca60b6bd9d7dd
parent 3a32a1a86a0738a8fcf37ac805ffb6c47dea3c2e
Author: Ne02ptzero <louis@ne02ptzero.me>
Date:   Wed,  1 Feb 2017 19:45:09 +0100

Add(Files): Add file_add and file_get_by_id function in database:

With tests !

Diffstat:
Minc/database.h | 6++++++
Minc/files.h | 2++
Msrc/database.c | 112++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/files.c | 2++
Mtests/test_database.c | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 216 insertions(+), 1 deletion(-)

diff --git a/inc/database.h b/inc/database.h @@ -27,6 +27,7 @@ # define QUERY_GET_PACKAGE_BY_ID(id) "SELECT * FROM " PKG_TABLE " WHERE id = %lld", id # define QUERY_GET_PACKAGE_BY_NAME(name) "SELECT * FROM " PKG_TABLE " WHERE name = \"%s\"", name +# define QUERY_GET_FILES_BY_ID(id) "SELECT * FROM " FILE_TABLE " WHERE id = %lld", id # define SQL_CREATE_TABLE "CREATE table " # define SQL_INSERT_TABLE "INSERT INTO " @@ -51,5 +52,10 @@ u8_t mpm_get_package_by_name(database_t *ptr, const char *name, package_t *sql_to_package(package_t *ptr, char *name, char *val); u8_t mpm_database_init(database_t *ptr); u8_t mpm_database_add_pkg(database_t *ptr, package_t *pkg); +u8_t mpm_get_file_by_id(database_t *ptr, u64_t id, + mlist_t **files); +SQL_CALLBACK_DEF(callback_files); +file_t *sql_to_file(file_t *ptr, char *name, char *val); +u8_t mpm_database_add_file(database_t *ptr, file_t *file); #endif /* DATABASE_H */ diff --git a/inc/files.h b/inc/files.h @@ -38,9 +38,11 @@ enum { }; typedef struct s_file { + u64_t id; char *path; u8_t type; package_t *parent; + char *parent_name; char *hash; } file_t; diff --git a/src/database.c b/src/database.c @@ -185,7 +185,7 @@ u8_t mpm_get_package_by_name(database_t *ptr, const char *name, * * This function will transform an SQL result, given through an sqlite callback, * and fill a package_t structure with it. - * All the types conversion needed (strint -> *) are done in this function. + * All the types conversion needed (string -> *) are done in this function. * * \note If a unknown column is passed to this function, a panic will be throwed. */ @@ -300,3 +300,113 @@ u8_t mpm_database_add_pkg(database_t *ptr, package_t *pkg) { sqlite3_free(err); return ret; } + +/*! + * \brief Get a file by his Id + * \param ptr Opened Database connection + * \param id ID to search for + * \param files Pointer on a list, used to store the results + * \return Error code + * + * This function will search in an already opened database a file with a + * given id. + * A sql QUERY is constructed in this function, with the following content: + * SELECT * FROM files WHERE id = %d, where %d is the given id + * This function will call list_add to add results to the given list, + * caller should properly free this list. + * + * \note This function will set files to NULL before filling it with the results. + * You should not call this function with an existing files list. + */ +u8_t mpm_get_file_by_id(database_t *ptr, u64_t id, + mlist_t **files) { + char *query; + u8_t ret; + + if (ptr == NULL) + return 1; + + *files = NULL; + asprintf(&query, QUERY_GET_FILES_BY_ID(id)); + ret = sqlite3_exec(ptr->sql, query, &callback_files, files, NULL); + free(query); + return ret; +} + +/** + * int name(void *context, int col_num, char **col_txt, char **col_name) + */ +SQL_CALLBACK_DEF(callback_files) { + mlist_t **head = context; + file_t *ptr; + + ptr = malloc(sizeof(file_t)); + assert(ptr != NULL); + mpm_file_init(ptr); + + for (u8_t i = 0; i < col_num; i++) + sql_to_file(ptr, col_name[i], col_txt[i]); + + list_add(*(head), ptr, sizeof(file_t)); + free(ptr); + return 0; +} + +/*! + * \brief Fill a file_t structure with a SQL result + * \param ptr Pointer to file_t. Must not be NULL. + * \param name Name of the column + * \param val Value of the column + * + * This function will transform an SQL result, given through an sqlite callback, + * and fill a file_t structure with it. + * All the types conversion needed (string -> *) are done in this function. + * + * \note If a unknown column is passed to this function, a panic will be throwed. + */ +file_t *sql_to_file(file_t *ptr, char *name, char *val) { + if (ptr == NULL) + return ptr; + + if (strcmp(name, FILE_COL_ID) == 0) { + ptr->id = strtoull(val, (char **)NULL, 10); + } else if (strcmp(name, FILE_COL_PATH) == 0) { + ptr->path = strdup(val); + } else if (strcmp(name, FILE_COL_TYPE) == 0) { + ptr->type = val[0] - '0'; + } else if (strcmp(name, FILE_COL_PARENT) == 0) { + ptr->parent = NULL; + } else if (strcmp(name, FILE_COL_PARENT_NAME) == 0) { + ptr->parent_name = strdup(val); + } else if (strcmp(name, FILE_COL_HASH) == 0) { + ptr->hash = strdup(val); + } else { + m_panic("Unknown column '%s' in get_file\n", name); + } + return ptr; +} + +/*! + * \brief Add a file entry to the database + * \param ptr Opened connection to a database + * \param file File to add + */ +u8_t mpm_database_add_file(database_t *ptr, file_t *file) { + char *query, *err; + u8_t ret; + + if (ptr == NULL || file == NULL) + return 1; + + asprintf(&query, SQL_INSERT_TABLE FILE_TABLE \ + " (%s, %s, %s, %s, %s) " \ + "VALUES (\"%s\", \"%d\", \"%d\", \"%s\", \"%s\");", + FILE_COL_PATH, FILE_COL_TYPE, FILE_COL_PARENT, FILE_COL_PARENT_NAME, + FILE_COL_HASH, + file->path, file->type, /* TMP */0, file->parent_name, file->hash); + ret = mpm_database_exec(ptr, query, NULL, NULL, &err); + free(query); + assert(ret == 0 && err == NULL); + sqlite3_free(err); + return ret; +} diff --git a/src/files.c b/src/files.c @@ -25,6 +25,7 @@ void mpm_file_init(file_t *ptr) { ptr->path = NULL; ptr->parent = NULL; ptr->hash = NULL; + ptr->parent_name = NULL; } } @@ -39,6 +40,7 @@ int mpm_file_free(void *tmp) { free(ptr->path); free(ptr->hash); mpm_package_free(ptr->parent); + free(ptr->parent_name); } return 1; } diff --git a/tests/test_database.c b/tests/test_database.c @@ -228,6 +228,46 @@ TEST(database_add_pkg_2) { return TEST_SUCCESS; } +TEST(database_add_file_1) { + file_t *file = NULL; + package_t *parent = NULL; + database_t *ptr; + u8_t ret; + + (void)parent; + ptr = mpm_database_open(&ret, NULL); + TEST_ASSERT((ret == 0), "Can't open the database"); + TEST_ASSERT((ptr != NULL), "Can't open the database"); + + ret = mpm_database_init(ptr); + TEST_ASSERT((ret == 0), "Can't init database"); + + file = malloc(sizeof(file_t)); + + assert(file != NULL); + mpm_file_init(file); + file->path = strdup("/tmp/test"); + file->hash = strdup("Totally not a hash."); + file->parent_name = strdup("Some Star Wars joke"); + file->type = FILE_TYPE_BIN; + + ret = mpm_database_add_file(ptr, file); + TEST_ASSERT((ret == 0), "Can't add a file to the database"); + mpm_database_close(ptr); + mpm_file_free(file); + free(file); + return TEST_SUCCESS; +} + +TEST(database_add_file_2) { + u8_t ret = 0; + + ret = mpm_database_add_file(NULL, NULL); + TEST_ASSERT((ret == 1), "Can't handle NULL pointer"); + return TEST_SUCCESS; +} + + TEST(database_get_pkg_by_id_1) { mlist_t *lst; database_t *ptr = NULL; @@ -284,6 +324,56 @@ TEST(database_sql_to_package) { ptr = sql_to_package(NULL, NULL, NULL); TEST_ASSERT((ptr == NULL), "Pointer is not NULL"); + clean_db(DB_FN); + return TEST_SUCCESS; +} + +TEST(database_get_file_by_id_1) { + mlist_t *lst; + database_t *ptr = NULL; + u8_t ret = 0; + + ptr = mpm_database_open(&ret, NULL); + TEST_ASSERT((ret == 0), "Can't open the database"); + TEST_ASSERT((ptr != NULL), "Can't open the database"); + + ret = mpm_get_file_by_id(ptr, 1, &lst); + TEST_ASSERT((list_size(lst) == 1), "Can't find the package"); + mpm_database_close(ptr); + list_free(lst, &mpm_file_free); + return TEST_SUCCESS; +} + +TEST(database_get_file_by_id_2) { + mlist_t *lst; + u8_t ret = 0; + + ret = mpm_get_file_by_id(NULL, 1, &lst); + TEST_ASSERT((ret == 1), "Can't handle NULL pointer"); + + return TEST_SUCCESS; +} + +TEST(database_sql_to_file) { + file_t *ptr = NULL; + int st, fd[2]; + pid_t pid; + + ptr = sql_to_file(NULL, NULL, NULL); + TEST_ASSERT((ptr == NULL), "Pointer is not NULL"); + + ptr = malloc(sizeof(file_t)); + + pipe(fd); + if ((pid = fork()) == 0) { + DUP_ALL_OUTPUTS(fd); + ptr = sql_to_file(ptr, "Unknown", "Nothing"); + } else { + WAIT_AND_CLOSE(pid, st, fd); + TEST_ASSERT((WEXITSTATUS(st) == 1), "Exit code is wrong"); + } + free(ptr); + clean_db(DB_FN); return TEST_SUCCESS; } @@ -352,4 +442,9 @@ void register_test_database(void) { reg_test("database", database_get_pkg_by_name_1); reg_test("database", database_get_pkg_by_name_2); reg_test("database", database_sql_to_package); + reg_test("database", database_add_file_1); + reg_test("database", database_add_file_2); + reg_test("database", database_get_file_by_id_1); + reg_test("database", database_get_file_by_id_2); + reg_test("database", database_sql_to_file); }