/** * Insert file into cache. One should have verified that the file * does not already exists in the database. * @todo Use statements to avoid bugs when dealing with strings from user * space and thus avoid sql injection a bit. See * https://sqlite.org/c3ref/prepare.html * @param database is the structure that contains everything that is * related to the database (it's connexion for instance). * @param meta is the file's metadata that we want to insert into the * cache. * @param only_meta : a gboolean that when set to TRUE only meta_data will * be saved and hashs data will not ! FALSE means that something * went wrong with server and that all data will be cached localy. */ void db_save_meta_data(db_t *database, meta_data_t *meta, gboolean only_meta) { guint64 cache_time = 0; gint result = 0; sqlite3_stmt *stmt = NULL; if (meta != NULL && database != NULL && database->stmts != NULL) { cache_time = g_get_real_time(); /* beginning a transaction */ sql_begin(database); /* Inserting the file into the files table */ stmt = database->stmts->save_meta_stmt; if (stmt != NULL) { bind_values_to_save_meta_data(database->db, stmt, meta, only_meta, cache_time); result = sqlite3_step(stmt); print_on_db_error(database->db, result, "sqlite3_step"); } /* ending the transaction here */ sql_commit(database); sqlite3_reset(stmt); } }
/** * Returns the file_id for the specified file. * @param database is the structure that contains everything that is * related to the database (it's connexion for instance). * @param meta is the file's metadata that we want to insert into the * cache. * @returns a file_row_t structure filed with values returned by the * database. */ static file_row_t *get_file_id(db_t *database, meta_data_t *meta) { file_row_t *row = NULL; sqlite3_stmt *stmt = NULL; gint result = 0; if (database != NULL && database->stmts != NULL && database->db != NULL) { row = new_file_row_t(); stmt = database->stmts->get_file_id_stmt; bind_values_to_get_file_id(database->db, stmt, meta); result = sqlite3_step(stmt); while (result == SQLITE_ROW) { row->nb_row = row->nb_row + 1; result = sqlite3_step(stmt); } print_on_db_error(database->db, result, "get_file_id"); sqlite3_reset(stmt); } return row; }
/** * Creates the statements that will be used to retrieve a file_id if it * exist with the given parameters. * @param db is an sqlite * pointer to an opened database. * @returns the newly created statement. */ static sqlite3_stmt *create_get_file_id_stmt(sqlite3 *db) { sqlite3_stmt *stmt = NULL; int result = 0; result = sqlite3_prepare_v2(db, "SELECT file_id from files WHERE inode=:inode AND name=:name AND type=:file_type AND uid=:uid AND gid=:gid AND ctime=:ctime AND mtime=:mtime AND mode=:mode AND size=:size;", -1, &stmt, NULL); print_on_db_error(db, result, "create_save_buffer_stmt"); return stmt; }
/** * Creates the statements that will be used to save buffer data and url * that should have been sent to the server * @param db is an sqlite * pointer to an opened database. * @returns the newly created statement. */ static sqlite3_stmt *create_save_buffer_stmt(sqlite3 *db) { sqlite3_stmt *stmt = NULL; int result = 0; result = sqlite3_prepare_v2(db, "INSERT INTO buffers (url, data) VALUES (:url, :data);", -1, &stmt, NULL); print_on_db_error(db, result, "create_save_buffer_stmt"); return stmt; }
/** * Creates the statements that will be used to save file's meta data to * the database * @param db is an sqlite * pointer to an opened database. * @returns the newly created statement. */ static sqlite3_stmt *create_save_meta_stmt(sqlite3 *db) { sqlite3_stmt *stmt = NULL; int result = 0; result = sqlite3_prepare_v2(db, "INSERT INTO files (cache_time, type, inode, file_user, file_group, uid, gid, atime, ctime, mtime, mode, size, name, transmitted, link) VALUES (:cache_time, :type, :inode, :file_user, :file_group, :uid, :gid, :atime, :ctime, :mtime, :mode, :size, :name, :transmited, :link);", -1, &stmt, NULL); print_on_db_error(db, result, "create_save_meta_stmt"); return stmt; }
/** * Binds a gchar *value into the prepared statement. * @param db is the database concerned by stmt statement. It is only used * here to print an error if any. * @param stmt is the prepared statement in which we want to bind the string * 'value' in 'name' parameter * @param name represents the name of the parameter in the prepared statement * which we want to fill in with 'value' * @param value is a gchar * string to be filled in 'name' parameter in the * prepared statement. */ static void bind_text_value(sqlite3 *db, sqlite3_stmt *stmt, const gchar *name, gchar *value) { int index = 0; int result = 0; if (stmt != NULL && name != NULL) { index = sqlite3_bind_parameter_index(stmt, name); result = sqlite3_bind_text(stmt, index, value, -1, NULL); print_on_db_error(db, result, name); } }
/** * Binds a gchar *blob_value into the prepared statement. * @param db is the database concerned by stmt statement. It is only used * here to print an error if any. * @param stmt is the prepared statement in which we want to bind the string * 'value' in 'name' parameter * @param name represents the name of the parameter in the prepared statement * which we want to fill in with 'value' * @param blob_value is a gchar * string to be filled in 'name' parameter in the * prepared statement. * @param length is the total number of bytes in blob_values to be taken into * account. */ static void bind_blob_value(sqlite3 *db, sqlite3_stmt *stmt, const gchar *name, gchar *blob_value, gsize length) { int index = 0; int result = 0; if (stmt != NULL && name != NULL) { index = sqlite3_bind_parameter_index(stmt, name); result = sqlite3_bind_blob64(stmt, index, blob_value, length, NULL); print_on_db_error(db, result, name); } }
/** * Saves buffers that could not be sent to server * @param database is the structure that contains everything that is * related to the database (it's connexion for instance). * @param url is the url where buffer should have been POSTed * @param buffer is the buffer containing data that should have been * POSTed to server but couldn't. */ void db_save_buffer(db_t *database, gchar *url, gchar *buffer) { sqlite3_stmt *stmt = NULL; gint result = 0; if (database != NULL && url != NULL && buffer != NULL) { sql_begin(database); stmt = database->stmts->save_buffer_stmt; bind_values_to_save_buffer(database->db, stmt, url, buffer); result = sqlite3_step(stmt); print_on_db_error(database->db, result, "db_save_buffer"); sql_commit(database); sqlite3_reset(stmt); } }
/** * Tells if a specific table or index exists or not in the selected * and opened database. * @param database is the database structure * @param name is a gchar * string that is the name of * the table or index to look for. * @param type is an integer that represents the type of the * object to look for. * @returns 0 if the table exists, 1 if it doesn't and -1 on * if an error occurs. */ static gint does_db_object_exists(db_t *database, gchar *name, gint type) { char *error_message = NULL; int result = -3; /* result is used for the sqlite execution result */ list_t *container = NULL; gint object_exists = -1; /* -1 is an SQL error and -2 is a struct error */ gchar *cmd = NULL; cmd = get_select_command_upon_type(type); if (cmd == NULL) { return object_exists; } /* this structure is needed by sqlite3_exec call bak make_list_first_column_callback.*/ container = new_list_t(); if (database != NULL && database->db != NULL) { /* Trying to get all the table names that are in the database */ result = sqlite3_exec(database->db, cmd, make_list_first_column_callback, container, &error_message); } free_variable(cmd); if (result == SQLITE_OK && container != NULL) { object_exists = does_object_name_exists_in_returned_list(name, container->list); } else if (database != NULL && database->db != NULL) { print_on_db_error(database->db, result, "sqlite_master table"); object_exists = -1; } else { object_exists = -2; } free_list_t(container); return object_exists; }