static void free_config(struct sway_config *config) { int i; for (i = 0; i < config->symbols->length; ++i) { free_variable(config->symbols->items[i]); } list_free(config->symbols); for (i = 0; i < config->modes->length; ++i) { free_mode(config->modes->items[i]); } list_free(config->modes); free_flat_list(config->cmd_queue); for (i = 0; i < config->workspace_outputs->length; ++i) { free_workspace_output(config->workspace_outputs->items[i]); } list_free(config->workspace_outputs); for (i = 0; i < config->criteria->length; ++i) { free_criteria(config->criteria->items[i]); } list_free(config->criteria); for (i = 0; i < config->output_configs->length; ++i) { free_output_config(config->output_configs->items[i]); } list_free(config->output_configs); free(config); }
/** * Inits and returns a newly hash_data_t structure. * @returns a newly hash_data_t structure. */ hash_data_t *new_hash_data_t(guchar *data, gssize size_read, guint8 *hash, gshort cmptype) { hash_data_t *hash_data = NULL; compress_t *compress = NULL; hash_data = (hash_data_t *) g_malloc(sizeof(hash_data_t)); g_assert_nonnull(hash_data); if (cmptype != COMPRESS_NONE_TYPE && data != NULL) { compress = compress_buffer(data, size_read, (gint) cmptype); hash_data->data = compress->text; hash_data->read = compress->len; hash_data->uncmplen = size_read; free_variable(compress); /* do not free compress->text as its reference is now used in hash_data->data. */ /* data variable is not used anymore (it has been replaced by compress->text) it has to be freed by the caller */ } else { hash_data->data = data; hash_data->read = size_read; hash_data->uncmplen = size_read; } hash_data->hash = hash; hash_data->cmptype = cmptype; return hash_data; }
/** * Verifies if the tables are created whithin the database and creates * them if there is no tables at all. * @param database : the structure to manage database's connexion. */ static void verify_if_tables_exists(db_t *database) { char *error_message = NULL; int result = 0; int *i = NULL; /** int *i is used to count the number of row */ i = (int *) g_malloc0(sizeof(int)); *i = 0; /* Trying to get all the tables that are in the database */ result = sqlite3_exec(database->db, "SELECT * FROM sqlite_master WHERE type='table';", table_callback, i, &error_message); if (result == SQLITE_OK && *i == 0) /* No row (0) means that there is no table */ { print_debug(_("Creating tables into the database\n")); /* The database does not contain any tables. So we have to create them. */ /* Creation of buffers table that contains checksums and their associated data */ exec_sql_cmd(database, "CREATE TABLE buffers (buffer_id INTEGER PRIMARY KEY AUTOINCREMENT, url TEXT, data TEXT);", _("(%d) Error while creating database table 'buffers': %s\n")); /* Creation of transmited table that may contain id of transmited buffers if any + creation of its indexes */ exec_sql_cmd(database, "CREATE TABLE transmited (buffer_id INTEGER PRIMARY KEY);", _("(%d) Error while creating database table 'transmited': %s\n")); exec_sql_cmd(database, "CREATE INDEX main.transmited_buffer_id ON transmited (buffer_id ASC)", _("(%d) Error while creating index 'transmited_buffer_id': %s\n")); /* Creation of files table that contains everything about a file */ exec_sql_cmd(database, "CREATE TABLE files (file_id INTEGER PRIMARY KEY AUTOINCREMENT, cache_time INTEGER, type INTEGER, inode INTEGER, file_user TEXT, file_group TEXT, uid INTEGER, gid INTEGER, atime INTEGER, ctime INTEGER, mtime INTEGER, mode INTEGER, size INTEGER, name TEXT, transmitted BOOL, link TEXT);", _("(%d) Error while creating database table 'files': %s\n")); exec_sql_cmd(database, "CREATE INDEX main.files_inodes ON files (inode ASC)", _("(%d) Error while creating index 'files_inodes': %s\n")); } free_variable(i); }
/** * makes a GSList of hash_data_t * element where 'hash' field is base64 * decoded hashs from a string containning base64 * encoded hashs that * must be separated by commas. * @param the string containing base64 encoded hashs such as : * * "cCoCVkt/AABf04jn2+rfDmqJaln6P2A9uKolBjEFJV4=", "0G8MaPZ/AADNyaPW7ZP2s0BI4hAdZZIE2xO1EwdOzhE=" * for instance. * @returns a GSList of hash_data_t * where each elements contains a * base64 decoded hash (binary form). */ GList *make_hash_data_list_from_string(gchar *hash_string) { guint i = 0; gchar **hashs = NULL; gchar *a_hash = NULL; hash_data_t *hash_data = NULL; GList *hash_list = NULL; gsize len = 0; if (hash_string != NULL) { /* hash list generation */ hashs = g_strsplit(hash_string, ",", -1); while (hashs[i] != NULL) { a_hash = g_strndup(g_strchug(hashs[i] + 1), strlen(g_strchug(hashs[i])) - 2); /* we have to base64 decode it to insert it into the hash_data_t * structure * and then into the meta_data one. */ hash_data = new_hash_data_t_as_is(NULL, 0, g_base64_decode(a_hash, &len), COMPRESS_NONE_TYPE, 0); hash_list = g_list_prepend(hash_list, hash_data); free_variable(a_hash); i = i + 1; } g_strfreev(hashs); hash_list = g_list_reverse(hash_list); } return hash_list; }
/** * Transmits each row found in the database * @param userp is a pointer to a transmited_t * structure that must contain * a comm_t * pointer and a db_t * pointer. * @param nb_col gives the number of columns in this row. * @param data contains the data of each column. * @param name_col contains the name of each column. * @returns always 0. */ static int transmit_callback(void *userp, int nb_col, char **data, char **name_col) { transmited_t *trans = (transmited_t *) userp; gchar *sql_command = NULL; gint success = 0; if (trans != NULL && data != NULL && trans->comm != NULL && trans->database != NULL) { trans->comm->readbuffer = data[2]; /** data[2] is the data column in buffers table of the database */ success = post_url(trans->comm, data[1]); /** data[1] is the url column in buffers table of the database */ if (success == CURLE_OK) { sql_begin(trans->database); sql_command = g_strdup_printf("INSERT INTO transmited (buffer_id) VALUES ('%s');", data[0]); exec_sql_cmd(trans->database, sql_command, _("(%d) Error while inserting into the table 'transmited': %s\n")); free_variable(sql_command); sql_commit(trans->database); } /** @todo use the result of post to be able to manage errors */ } return 0; }
/** * This function gets meta data and data from a file and sends them * to the server in order to save the file located in the directory * 'directory' and represented by 'fileinfo' variable. * @param main_struct : main structure of the program * @param directory is the directory we are iterating over * @param fileinfo is a glib structure that contains all meta data and * more for a file. * @note This function is not threadable as is. One may have problems * when writing to the database for instance. */ void save_one_file(main_struct_t *main_struct, file_event_t *file_event) { meta_data_t *meta = NULL; a_clock_t *my_clock = NULL; gchar *message = NULL; gchar *another_dir = NULL; filter_file_t *filter = NULL; if (main_struct != NULL && file_event != NULL) { my_clock = new_clock_t(); /* Get data and meta_data for a file. */ filter = new_filter_t(main_struct->database, main_struct->regex_exclude_list, FALSE); meta = get_meta_data_from_fileinfo(file_event, filter, main_struct->opt); /* We want to save all files that are not excluded ie filter->excluded not TRUE */ if (meta != NULL && filter != NULL && filter->excluded == FALSE) { if (meta->in_cache == FALSE) { /* File is not in cache thus unknown thus we need to save it */ if (meta->size < CLIENT_SMALL_FILE_SIZE) { process_small_file_not_in_cache(main_struct, meta); } else { process_big_file_not_in_cache(main_struct, meta); } } if (meta->file_type == G_FILE_TYPE_DIRECTORY) { /* This is a recursive call */ another_dir = g_strdup(meta->name); g_async_queue_push(main_struct->dir_queue, another_dir); } message = g_strdup_printf(_("processing file %s"), meta->name); free_meta_data_t(meta, FALSE); free_filter_file_t(filter); } else if (meta != NULL && filter != NULL && filter->excluded == TRUE) { message = g_strdup_printf(_("processing excluded file %s"), meta->name); free_meta_data_t(meta, FALSE); free_filter_file_t(filter); } else { message = g_strdup_printf(_("Error with meta (%p) or filter (%p) structures\n"), meta, filter); print_error(__FILE__, __LINE__, message); } end_clock(my_clock, message); free_variable(message); } }
/** * Frees memory * @param container is a list_t structure to be freed */ static void free_list_t(list_t *container) { if (container != NULL) { g_list_free_full(container->list, free_gchar_variable); free_variable(container); } }
/** * Frees everything whithin the file_row_t structure * @param row is the variable to be freed totaly */ static void free_file_row_t(file_row_t *row) { if (row != NULL) { g_slist_free_full(row->id_list, free_gchar_variable); free_variable(row); } }
/** * Returns a database connexion or NULL. * @param dirname is the name of the directory where the database is * located. * @param filename is the filename of the file that contains the * database * @result returns a db_t * filled with the database connexion or NULL * in case of an error. */ db_t *open_database(gchar *dirname, gchar *filename) { gchar *database_name = NULL; db_t *database = NULL; sqlite3 *db = NULL; int result = 0; if (dirname != NULL && filename != NULL) { create_directory(dirname); database_name = g_build_filename(dirname, filename, NULL); result = sqlite3_open(database_name, &db); if (result != SQLITE_OK) { print_db_error(_("(%d) Error while trying to open %s database: %s\n"), result, database_name, sqlite3_errmsg(db)); sqlite3_close(db); free_variable(database_name); return NULL; } else { database = (db_t *) g_malloc0(sizeof(db_t)); g_assert_nonnull(database); database->version_filename = g_strdup_printf("%s.version", database_name); database->db = db; sqlite3_extended_result_codes(db, 1); verify_if_tables_exists(database); database->stmts = new_stmts(db); database->version = get_database_version(database->version_filename, KN_CLIENT_DATABASE); migrate_schema_if_needed(database); free_variable(database_name); return database; } } else { return NULL; } }
/** * Converts at max hashs from hash_extract->hash_list into a gchar * * string that are comma separated. * @param hash_extract contains one pointer to a GList og guint8 * binary * hashs and one pointer to a gchar * string that contains thoses * hashs, base64 encoded and comma separated. * @param max is a gint that represents the maximum number of hashs to * convert. * @returns a correctly filled gchar *string */ gchar *convert_max_hashs_from_hash_list_to_gchar(hash_extract_t *hash_extract, gint max) { GList *head = NULL; gchar *base64 = NULL; gchar *hash_string = NULL; gchar *old_list = NULL; hash_data_t *hash_data = NULL; gint i = 0; if (hash_extract != NULL) { head = hash_extract->hash_list; } while (head != NULL && i < max) { hash_data = head->data; base64 = g_base64_encode(hash_data->hash, HASH_LEN); if (old_list == NULL) { hash_string = g_strdup_printf("\"%s\"", base64); old_list = hash_string; } else { hash_string = g_strdup_printf("%s, \"%s\"", old_list, base64); free_variable(old_list); old_list = hash_string; } free_variable(base64); i = i + 1; head = g_list_next(head); } hash_string = old_list; hash_extract->hash_list = head; hash_extract->hash_string = hash_string; return hash_string; }
/** * Frees server's structure * @param server_struct is the structure to be freed */ void free_server_struct_t(server_struct_t *server_struct) { if (server_struct != NULL) { MHD_stop_daemon(server_struct->d); print_debug(_("\tMHD daemon stopped.\n")); free_variable(server_struct->backend); /** we need a backend function to be called to free th backend structure */ print_debug(_("\tbackend variable freed.\n")); g_thread_unref(server_struct->data_thread); print_debug(_("\tdata thread unrefed.\n")); g_thread_unref(server_struct->meta_thread); print_debug(_("\tmeta thread unrefed.\n")); free_options_t(server_struct->opt); print_debug(_("\toption structure freed.\n")); free_variable(server_struct); print_debug(_("\tmain structure freed.\n")); } }
/** * Sends meta data to the server and returns it's answer or NULL in * case of an error. * @param main_struct : main structure of the program (contains pointers * to the communication socket. * @param meta : the meta_data_t * structure to be saved. * @returns a newly allocated gchar * string that may be freed when no * longer needed. */ static gchar *send_meta_data_to_server(main_struct_t *main_struct, meta_data_t *meta, gboolean data_sent) { gchar *json_str = NULL; gchar *answer = NULL; gint success = CURLE_FAILED_INIT; json_t *root = NULL; json_t *array = NULL; if (main_struct != NULL && meta != NULL && main_struct->hostname != NULL) { json_str = convert_meta_data_to_json_string(meta, main_struct->hostname, data_sent); /* Sends meta data here: readbuffer is the buffer sent to server */ print_debug(_("Sending meta data: %s\n"), json_str); main_struct->comm->readbuffer = json_str; success = post_url(main_struct->comm, "/Meta.json"); if (success == CURLE_OK) { answer = g_strdup(main_struct->comm->buffer); main_struct->comm->buffer = free_variable(main_struct->comm->buffer); } else { /* Need to manage HTTP errors ? */ /* Saving meta data that should have been sent to sqlite database */ db_save_buffer(main_struct->database, "/Meta.json", main_struct->comm->readbuffer); /* An error occured -> we need the whole hash list to be saved * we are building a 'fake' answer with the whole hash list. */ array = convert_hash_list_to_json(meta->hash_data_list); root = json_object(); insert_json_value_into_json_root(root, "hash_list", array); answer = json_dumps(root, 0); json_decref(root); } free_variable(main_struct->comm->readbuffer); } return answer; }
/** * Frees the meta_data_t * structure * @param meta is a meta_data_t * structure to be freed * @param free_link is a boolean that when set to TRUE will free * @returns always NULL */ gpointer free_meta_data_t(meta_data_t *meta, gboolean free_link) { if (meta != NULL) { free_variable(meta->owner); free_variable(meta->group); free_variable(meta->name); if (free_link == TRUE) { /* meta->link should not be freed only in 'client' program */ free_variable(meta->link); } g_list_free_full(meta->hash_data_list, free_hdt_struct); free_variable(meta); } return NULL; }
static void proxy_free_variables( var_list_t *args, const char *local_var_prefix ) { const var_t *arg; if (!args) return; LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) if (is_attr(arg->attrs, ATTR_OUT)) { free_variable( arg, local_var_prefix ); fprintf(proxy, "\n"); } }
/** * Process the file that is not already in our local cache * @param main_struct : main structure of the program * @param meta is the meta data of the file to be processed (it does * not contain any hashs at that point). */ static void process_small_file_not_in_cache(main_struct_t *main_struct, meta_data_t *meta) { GFile *a_file = NULL; gchar *answer = NULL; gint success = 0; /** success returns a CURL Error status such as CURLE_OK for instance */ a_clock_t *mesure_time = NULL; if (main_struct != NULL && main_struct->opt != NULL && meta != NULL) { print_debug(_("Processing small file: %s\n"), meta->name); if (meta->file_type == G_FILE_TYPE_REGULAR) { mesure_time = new_clock_t(); /* Calculates hashs and takes care of data */ a_file = g_file_new_for_path(meta->name); meta->hash_data_list = calculate_hash_data_list_for_file(a_file, meta->blocksize); a_file = free_object(a_file); end_clock(mesure_time, "calculate_hash_data_list"); } mesure_time = new_clock_t(); answer = send_meta_data_to_server(main_struct, meta, FALSE); end_clock(mesure_time, "send_meta_data_to_server"); mesure_time = new_clock_t(); if (meta->size < meta->blocksize) { /* Only one block to send (size is less than blocksize's value) */ meta->hash_data_list = send_data_to_server(main_struct, meta->hash_data_list, answer); } else { /* A least 2 blocks to send */ meta->hash_data_list = send_all_data_to_server(main_struct, meta->hash_data_list, answer); } end_clock(mesure_time, "send_(all)_data_to_server"); free_variable(answer); /* Not used by now */ if (success == CURLE_OK) { /* Everything has been transmitted so we can save meta data into the local db cache */ /* This is usefull for file carving to avoid sending too much things to the server */ mesure_time = new_clock_t(); db_save_meta_data(main_struct->database, meta, TRUE); end_clock(mesure_time, "db_save_meta_data"); } } }
/** * Makes an array with the hashs in the list and sends them to * /Hash_Array.json URL of the server. The server must answer with a list * of needed hashs * @param comm a comm_t * structure that must contain an initialized * curl_handle (must not be NULL) * @param hash_data_list : list of hash_data already processed that are * ready to be transmited to server (if needed) * @returns a gchar * containing the JSON array of needed hashs */ static gchar *send_hash_array_to_server(comm_t *comm, GList *hash_data_list) { json_t *array = NULL; json_t *root = NULL; gchar *whole_hash_list = NULL; gchar *answer = NULL; gboolean success = CURLE_FAILED_INIT; if (comm != NULL && hash_data_list != NULL) { array = convert_hash_list_to_json(hash_data_list); root = json_object(); insert_json_value_into_json_root(root, "hash_list", array); whole_hash_list = json_dumps(root, 0); json_decref(root); comm->readbuffer = whole_hash_list; print_debug("Hash_Array: %s\n", whole_hash_list); success = post_url(comm, "/Hash_Array.json"); if (success == CURLE_OK) { answer = g_strdup(comm->buffer); comm->buffer = free_variable(comm->buffer); } else { answer = g_strdup(whole_hash_list); } free_variable(comm->readbuffer); } return answer; }
/** * Makes a symbolic link named with 'file' filename that points to the * target 'points_to' * @param file is the file to create as a symbolic link * @param points_to is the target of the link */ void make_symbolic_link(GFile *file, gchar *points_to) { gchar *filename = NULL; GError *error = NULL; if (file != NULL && points_to != NULL) { if (g_file_make_symbolic_link(file, points_to, NULL, &error) == FALSE && error != NULL) { filename = g_file_get_path(file); print_error(__FILE__, __LINE__, _("Error: unable to create symbolic link %s to %s: %s.\n"), filename, points_to, error->message); free_variable(filename); } } }
/** * Verifies if cmptype is a compression type allowed to be used and * sets the option accordingly or exit the program with an error * message. * @param Structure that manage program's options * @param cmtype a type to be tested */ static void set_compression_type(options_t *opt, gshort cmptype) { gchar *compress_type_string = NULL; if (is_compress_type_allowed(cmptype)) { opt->cmptype = cmptype; } else { compress_type_string = get_compress_type_string(); print_error(__FILE__, __LINE__, _("Unknown compression type: %d. Allowed compression types are: %s\n"), cmptype, compress_type_string); free_variable(compress_type_string); exit(EXIT_FAILURE); } }
/** * Deletes all transmited buffers from the buffers table in database * based on transmited table. * @param userp is a pointer to a db_t * structure * @param nb_col gives the number of columns in this row. * @param data contains the data of each column. * @param name_col contains the name of each column. * @returns always 0. */ static int delete_transmited_callback(void *userp, int nb_col, char **data, char **name_col) { db_t *database = (db_t *) userp; gchar *sql_command = NULL; if (database != NULL && data != NULL) { sql_begin(database); sql_command = g_strdup_printf("DELETE FROM buffers WHERE buffer_id='%s';", data[0]); exec_sql_cmd(database, sql_command, _("(%d - %d) Error while deleting from table 'buffers': %s\n")); sql_commit(database); free_variable(sql_command); } return 0; }
/** * Ends the clock and prints the elapsed time and then frees everything * @param my_clock is a clock_t * structure with begin already filled * @param message is a message that we want to include into the displayed * result in order to know what was measured. */ void end_clock(a_clock_t *my_clock, gchar *message) { GTimeSpan difference = 0; if (my_clock != NULL && my_clock->begin != NULL) { my_clock->end = g_date_time_new_now_local(); difference = g_date_time_difference(my_clock->end, my_clock->begin); g_date_time_unref(my_clock->begin); g_date_time_unref(my_clock->end); free_variable(my_clock); print_debug(_("Elapsed time (%s): %d µs\n"), message, difference); } }
/** * Frees the option structure * @param opt is the structure to be freed */ void free_options_t(options_t *opt) { if (opt != NULL) { free_variable(opt->list); free_variable(opt->restore); free_variable(opt->date); free_variable(opt->configfile); free_variable(opt->ip); free_variable(opt); } }
/** * Gets all data from a list of hash obtained from X-Get-Hash-Array HTTP * header. * @param server_struct is the main structure for the server. * @param connection is the connection in MHD * @returns a newlly allocated gchar * string that contains the anwser to be * sent back to the client (hopefully a json string containing * a hash (that is a fake one here), data and size of the data. */ static gchar *get_data_from_a_list_of_hashs(server_struct_t *server_struct, struct MHD_Connection *connection) { const char *header = NULL; gchar *answer = NULL; gchar *hash = NULL; GList *head = NULL; GList *header_hdl = NULL; GList *hash_data_list = NULL; hash_data_t *header_hd = NULL; hash_data_t *hash_data = NULL; backend_t *backend = server_struct->backend; guint size = 0; header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "X-Get-Hash-Array"); header_hdl = make_hash_data_list_from_string((gchar *)header); head = header_hdl; while (header_hdl != NULL) { header_hd = header_hdl->data; hash = hash_to_string(header_hd->hash); hash_data = backend->retrieve_data(server_struct, hash); free_variable(hash); size = size + hash_data->read; hash_data_list = g_list_prepend(hash_data_list, hash_data); header_hdl = g_list_next(header_hdl); } g_list_free_full(head, free_hdt_struct); hash_data_list = g_list_reverse(hash_data_list); head = hash_data_list; hash_data = create_one_hash_data_t_from_hash_data_list(hash_data_list, size); g_list_free_full(head, free_hdt_struct); answer = convert_hash_data_t_to_string(hash_data); free_hash_data_t(hash_data); return answer; }
/** * 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; }
/** * Function to answer to get requests in a json way. This mode should be * prefered. * @param server_struct is the main structure for the server. * @param connection is the connection in MHD * @param url is the requested url * @note to translators all json requests MUST NOT be translated because * it is the protocol itself ! * @returns a newlly allocated gchar * string that contains the anwser to be * sent back to the client. */ static gchar *get_json_answer(server_struct_t *server_struct, struct MHD_Connection *connection, const char *url) { gchar *answer = NULL; gchar *hash = NULL; size_t hlen = 0; if (g_strcmp0(url, "/Version.json") == 0) { answer = convert_version_to_json(PROGRAM_NAME, SERVER_DATE, SERVER_VERSION, SERVER_AUTHORS, SERVER_LICENSE); } else if (g_str_has_prefix(url, "/File/List.json")) { answer = get_a_list_of_files(server_struct, connection); } else if (g_str_has_prefix(url, "/Data/Hash_Array.json")) { answer = get_data_from_a_list_of_hashs(server_struct, connection); } else if (g_str_has_prefix(url, "/Data/")) { hash = g_strndup((const gchar *) url + 6, HASH_LEN*2); /* HASH_LEN is expressed when hash is in binary form */ hash = g_strcanon(hash, "abcdef0123456789", '\0'); /* replace anything not in hexadecimal format with \0 */ hlen = strlen(hash); if (hlen == HASH_LEN*2) { print_debug(_("Trying to get data for hash %s\n"), hash); answer = get_data_from_a_specific_hash(server_struct, hash); } else { answer = g_strdup_printf("{\"Invalid url: in %s hash has length\": %zd instead of %d}", url, hlen, HASH_LEN*2); } free_variable(hash); } else { /* Some sort of echo to the invalid request */ answer = g_strdup_printf("{\"Invalid url\": %s}", url); } return answer; }
/** * Transforms a binary hashs into a printable string (gchar *) * @param a_hash is a hash in a binary form that we want to transform into * a string. * @returns a string that contains the hash in an hexadecimal form. */ gchar *hash_to_string(guint8 *a_hash) { gchar *string = NULL; gchar *octet = NULL; guint i = 0; if (a_hash != NULL) { string = (gchar *) g_malloc0(HASH_LEN*2 + 1); /* two char per bytes */ for(i = 0; i < HASH_LEN; i++) { octet = g_strdup_printf("%02x", a_hash[i]); memmove(string + i*2, octet, 2); free_variable(octet); } } return string; }
/** * Filters out and returns TRUE if the event concerns a file that has to * be saved FALSE otherwise * @param head is the matching monitired directory * @param event is the fanotify's structure event */ static gboolean filter_out_if_necessary(GSList *head, struct fanotify_event_metadata *event) { gchar *progname = NULL; if (head != NULL) { progname = get_program_name_from_pid(event->pid); if (g_strcmp0(PROGRAM_NAME, progname) != 0) { /* Save files that does not come from our activity */ free_variable(progname); return TRUE; } } return FALSE; }
/** * Does carve all directories from the list in the option list. * This function is a thread that is run at the end of the initialisation * of main_struct structure. * @param data: main structure of the program that contains also * the options structure that should have a list of directories * to save. */ static gpointer carve_all_directories(gpointer data) { main_struct_t *main_struct = (main_struct_t *) data; gchar *directory = NULL; if (main_struct != NULL && main_struct->opt != NULL) { g_slist_foreach(main_struct->opt->dirname_list, carve_one_directory, main_struct); directory = g_async_queue_pop(main_struct->dir_queue); while (directory != NULL) { carve_one_directory(directory, main_struct); free_variable(directory); directory = g_async_queue_pop(main_struct->dir_queue); } } return NULL; }
static char *get_program_name_from_pid(int pid) { int fd = 0; ssize_t len = 0; char *aux = NULL; gchar *cmd = NULL; gchar *buffer = NULL; /* Try to get program name by PID */ cmd = g_strdup_printf("/proc/%d/cmdline", pid); if ((fd = open(cmd, O_RDONLY)) < 0) { return NULL; } buffer = (gchar *) g_malloc(PATH_MAX); /* Read file contents into buffer */ if ((len = read(fd, buffer, PATH_MAX - 1)) <= 0) { close (fd); free_variable(buffer); return NULL; } else { close (fd); buffer[len] = '\0'; aux = strstr(buffer, "^@"); if (aux) { *aux = '\0'; } return buffer; } }
/** * Prints options as selected when invoking the program with -v option * @param opt the options_t * structure that contains all selected options * from the command line and that will be used by the program. */ static void print_selected_options(options_t *opt) { gchar *blocksize = NULL; if (opt != NULL) { fprintf(stdout, _("\n%s options are:\n"), PROGRAM_NAME); print_filelist(opt->dirname_list, _("Directory list:\n")); print_filelist(opt->exclude_list, _("Exclude list:\n")); if (opt->adaptive == FALSE) { /** * We need to translate this number into a string before * inserting it into the final string in order to allow * this final string to be translated in an other language. */ blocksize = g_strdup_printf("%" G_GINT64_FORMAT, opt->blocksize); fprintf(stdout, _("Blocksize: %s\n"), blocksize); free_variable(blocksize); } else { fprintf(stdout, _("Blocksize: adaptive mode\n")); } print_string_option(_("Configuration file: %s\n"), opt->configfile); print_string_option(_("Cache directory: %s\n"), opt->dircache); print_string_option(_("Cache database name: %s\n"), opt->dbname); if (opt->srv_conf != NULL) { print_string_option(_("Server's IP address: %s\n"), opt->srv_conf->ip); fprintf(stdout, _("Server's port number: %d\n"), opt->srv_conf->port); } fprintf(stdout, _("Buffersize: %d\n"), opt->buffersize); } }
/** * Processes events * @param main_struct is the maion structure * @param event is the fanotify's structure event * @param dir_list MUST be a list of gchar * g_utf8_casefold() * transformed. */ static void event_process(main_struct_t *main_struct, struct fanotify_event_metadata *event, GSList *dir_list) { gchar *path = NULL; gboolean to_save = FALSE; GSList *head = NULL; path = get_file_path_from_fd(event->fd); if (path != NULL) { /* Does the event concern a monitored directory ? */ head = does_event_concerns_monitored_directory(path, dir_list); /* Do we need to save this file ? Is it excluded somehow ? */ to_save = filter_out_if_necessary(head, event); if (to_save == TRUE) { print_debug(_("Received event file/directory: %s\n"), path); print_debug(_(" matching directory is: %s\n"), head->data); /* we are only watching this event so it is not necessary to print it ! * if (event->mask & FAN_CLOSE_WRITE) * { * print_debug(_("\tFAN_CLOSE_WRITE\n")); * } */ /* Saving the file effectively */ prepare_before_saving(main_struct, path); fflush(stdout); } close(event->fd); free_variable(path); } }