// remove file gboolean dir_tree_file_remove (DirTree *dtree, fuse_ino_t ino, DirTree_file_remove_cb file_remove_cb, fuse_req_t req) { DirEntry *en; FileRemoveData *data; LOG_debug (DIR_TREE_LOG, "Removing inode %"INO_FMT, ino); en = g_hash_table_lookup (dtree->h_inodes, GUINT_TO_POINTER (ino)); // if entry does not exist // or it's not a directory type ? if (!en) { LOG_err (DIR_TREE_LOG, "Entry (ino = %"INO_FMT") not found !", ino); file_remove_cb (req, FALSE); return FALSE; } if (en->type != DET_file) { LOG_err (DIR_TREE_LOG, "Entry (ino = %"INO_FMT") is not a file !", ino); file_remove_cb (req, FALSE); return FALSE; } data = g_new0 (FileRemoveData, 1); data->dtree = dtree; data->ino = ino; data->en = en; data->file_remove_cb = file_remove_cb; data->req = req; s3client_pool_get_client (application_get_ops_client_pool (dtree->app), dir_tree_file_remove_on_http_client_cb, data); return TRUE; }
static void fileio_write_on_multipart_init_cb (HttpConnection *con, void *ctx, gboolean success, const gchar *buf, size_t buf_len, G_GNUC_UNUSED struct evkeyvalq *headers) { FileWriteData *wdata = (FileWriteData *) ctx; gchar *uploadid; http_connection_release (con); wdata->fop->multipart_initiated = TRUE; if (!success || !buf_len) { LOG_err (FIO_LOG, INO_CON_H"Failed to get multipart init data from the server !", INO_T (wdata->ino), con); wdata->on_buffer_written_cb (wdata->fop, wdata->ctx, FALSE, 0); g_free (wdata); return; } uploadid = get_uploadid (buf, buf_len); if (!uploadid) { LOG_err (FIO_LOG, INO_CON_H"Failed to parse multipart init data!", INO_T (wdata->ino), con); wdata->on_buffer_written_cb (wdata->fop, wdata->ctx, FALSE, 0); g_free (wdata); return; } wdata->fop->uploadid = g_strdup (uploadid); xmlFree (uploadid); // done, resume uploading part wdata->fop->part_number = 1; fileio_write_send_part (wdata); }
gboolean s3http_connection_file_send (S3HttpConnection *con, int fd, const gchar *resource_path, S3HttpConnection_on_entry_sent_cb on_entry_sent_cb, gpointer ctx) { gchar *req_path; gboolean res; FileSendData *data; struct evbuffer *output_buf = NULL; struct stat st; data = g_new0 (FileSendData, 1); data->on_entry_sent_cb = on_entry_sent_cb; data->ctx = ctx; LOG_debug (CON_SEND_LOG, "Sending file.. %p", data); if (fstat (fd, &st) < 0) { LOG_err (CON_SEND_LOG, "Failed to stat temp file !"); s3http_connection_on_file_send_error (con, (void *) data); return FALSE; } output_buf = evbuffer_new (); if (!output_buf || evbuffer_add_file (output_buf, fd, 0, st.st_size) < 0) { LOG_err (CON_SEND_LOG, "Failed to read temp file !"); s3http_connection_on_file_send_error (con, (void *) data); if (output_buf) evbuffer_free (output_buf); return FALSE; } req_path = g_strdup_printf ("%s", resource_path); LOG_debug (CON_SEND_LOG, "[%p %p] Sending %s file, req: %s, %"OFF_FMT" buff: %zd", con, data, resource_path, req_path, st.st_size, evbuffer_get_length (output_buf)); res = s3http_connection_make_request (con, resource_path, req_path, "PUT", output_buf, s3http_connection_on_file_send_done, s3http_connection_on_file_send_error, data ); g_free (req_path); evbuffer_free (output_buf); if (!res) { LOG_err (CON_SEND_LOG, "Failed to create HTTP request !"); s3http_connection_on_file_send_error (con, (void *) data); return FALSE; } return TRUE; }
// create S3HttpConnection object // establish HTTP connections to S3 gpointer s3http_connection_create (Application *app) { S3HttpConnection *con; int port; AppConf *conf; con = g_new0 (S3HttpConnection, 1); if (!con) { LOG_err (CON_LOG, "Failed to create S3HttpConnection !"); return NULL; } conf = application_get_conf (app); con->app = app; con->bucket_name = g_strdup (application_get_bucket_name (app)); con->is_acquired = FALSE; port = application_get_port (app); // if no port is specified, libevent returns -1 if (port == -1) { port = conf->http_port; } LOG_debug (CON_LOG, "Connecting to %s:%d", application_get_host (app), port ); // XXX: implement SSL con->evcon = evhttp_connection_base_new ( application_get_evbase (app), application_get_dnsbase (app), application_get_host (app), port ); if (!con->evcon) { LOG_err (CON_LOG, "Failed to create evhttp_connection !"); return NULL; } evhttp_connection_set_timeout (con->evcon, conf->timeout); evhttp_connection_set_retries (con->evcon, conf->retries); evhttp_connection_set_closecb (con->evcon, s3http_connection_on_close, con); return (gpointer)con; }
static void fileio_release_complete_multipart (FileIO *fop) { if (!fop->uploadid) { LOG_err (FIO_LOG, INO_H"UploadID is not set, aborting operation !", INO_T (fop->ino)); fileio_destroy (fop); return; } if (!client_pool_get_client (application_get_write_client_pool (fop->app), fileio_release_on_complete_con_cb, fop)) { LOG_err (FIO_LOG, INO_H"Failed to get HTTP client !", INO_T (fop->ino)); fileio_destroy (fop); return; } }
static GHashTable *bvalue_parse_dict (struct evbuffer *in) { GHashTable *h_dict = NULL; gchar tmp[1]; gchar c; BValue *key; gchar *key_str; BValue *value; size_t len; // remove "d" evbuffer_remove (in, tmp, 1); evbuffer_copyout (in, &c, 1); len = evbuffer_get_length (in); h_dict = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, bvalue_dict_item_free); while (c != 'e' && len > 1) { key = bvalue_create_from_buff (in); if (!bvalue_is_string (key)) { LOG_err (B_LOG, "Failed parsing Bencode Dict !"); //XXX return NULL; } key_str = bvalue_get_string (key); if (!key_str) { LOG_err (B_LOG, "Failed parsing Bencode Dict !"); //XXX return NULL; } value = bvalue_create_from_buff (in); g_hash_table_insert (h_dict, g_strdup (key_str), value); bvalue_destroy (key); len = evbuffer_get_length (in); evbuffer_copyout (in, &c, 1); } // remove "e" evbuffer_remove (in, tmp, 1); return h_dict; }
/*{{{ create / destroy */ CacheMng *cache_mng_create (Application *app) { CacheMng *cmng; cmng = g_new0 (CacheMng, 1); cmng->app = app; cmng->h_entries = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, cache_entry_destroy); cmng->q_lru = g_queue_new (); cmng->size = 0; cmng->check_time = time (NULL); cmng->max_size = conf_get_uint (application_get_conf (cmng->app), "filesystem.cache_dir_max_size"); cmng->cache_dir = g_strdup_printf ("%s/%s", conf_get_string (application_get_conf (cmng->app), "filesystem.cache_dir"), CACHE_MNGR_DIR); cmng->cache_hits = 0; cmng->cache_miss = 0; cache_mng_rm_cache_dir (cmng); if (g_mkdir_with_parents (cmng->cache_dir, 0700) != 0) { LOG_err (CMNG_LOG, "Failed to remove directory: %s", cmng->cache_dir); cache_mng_destroy (cmng); return NULL; } return cmng; }
// replies on bucket versioning information static void application_on_bucket_versioning_cb (gpointer ctx, gboolean success, const gchar *buf, size_t buf_len) { Application *app = (Application *)ctx; gchar *tmp; if (!success) { LOG_err (APP_LOG, "Failed to get bucket versioning!"); application_exit (app); return; } if (buf_len > 1) { tmp = (gchar *)buf; tmp[buf_len - 1] = '\0'; if (strstr (buf, "<Status>Enabled</Status>")) { LOG_debug (APP_LOG, "Bucket has versioning enabled !"); conf_set_boolean (app->conf, "s3.versioning", TRUE); } else { LOG_debug (APP_LOG, "Bucket has versioning disabled !"); conf_set_boolean (app->conf, "s3.versioning", FALSE); } } else { conf_set_boolean (app->conf, "s3.versioning", FALSE); } application_finish_initialization_and_run (app); }
// if it's the first fuse read() request - send HEAD request to server // else try to get data from local cache, otherwise download from the server void fileio_read_buffer (FileIO *fop, size_t size, off_t off, fuse_ino_t ino, FileIO_on_buffer_read_cb on_buffer_read_cb, gpointer ctx) { FileReadData *rdata; rdata = g_new0 (FileReadData, 1); rdata->fop = fop; rdata->size = size; rdata->off = off; rdata->ino = ino; rdata->on_buffer_read_cb = on_buffer_read_cb; rdata->ctx = ctx; rdata->request_offset = off; // send HEAD request first if (!rdata->fop->head_req_sent) { // get HTTP connection to download manifest or a full file if (!client_pool_get_client (application_get_read_client_pool (rdata->fop->app), fileio_read_on_head_con_cb, rdata)) { LOG_err (FIO_LOG, INO_H"Failed to get HTTP client !", INO_T (rdata->ino)); rdata->on_buffer_read_cb (rdata->ctx, FALSE, NULL, 0); g_free (rdata); } // HEAD is sent, try to get data from cache } else { fileio_read_get_buf (rdata); } }
/*{{{ GET request */ static void fileio_read_on_get_cb (HttpConnection *con, void *ctx, gboolean success, const gchar *buf, size_t buf_len, G_GNUC_UNUSED struct evkeyvalq *headers) { FileReadData *rdata = (FileReadData *) ctx; const char *versioning_header = NULL; // release HttpConnection http_connection_release (con); if (!success) { LOG_err (FIO_LOG, INO_CON_H"Failed to get file from server !", INO_T (rdata->ino), con); rdata->on_buffer_read_cb (rdata->ctx, FALSE, NULL, 0); g_free (rdata); return; } // store it in the local cache cache_mng_store_file_buf (application_get_cache_mng (rdata->fop->app), rdata->ino, buf_len, rdata->request_offset, (unsigned char *) buf, NULL, NULL); // update version ID versioning_header = http_find_header (headers, "x-amz-version-id"); if (versioning_header) { cache_mng_update_version_id (application_get_cache_mng (rdata->fop->app), rdata->ino, versioning_header); } LOG_debug (FIO_LOG, INO_H"Storing [%"G_GUINT64_FORMAT" %zu]", INO_T(rdata->ino), rdata->request_offset, buf_len); // and read it fileio_read_get_buf (rdata); }
// got HttpConnection object static void fileio_write_on_multipart_init_con_cb (gpointer client, gpointer ctx) { HttpConnection *con = (HttpConnection *) client; FileWriteData *wdata = (FileWriteData *) ctx; gboolean res; gchar *path; http_connection_acquire (con); path = g_strdup_printf ("%s?uploads", wdata->fop->fname); // send storage class with the init request http_connection_add_output_header (con, "x-amz-storage-class", conf_get_string (application_get_conf (con->app), "s3.storage_type")); res = http_connection_make_request (con, path, "POST", NULL, TRUE, NULL, fileio_write_on_multipart_init_cb, wdata ); g_free (path); if (!res) { LOG_err (FIO_LOG, INO_CON_H"Failed to create HTTP request !", INO_T (wdata->ino), con); http_connection_release (con); wdata->on_buffer_written_cb (wdata->fop, wdata->ctx, FALSE, 0); g_free (wdata); return; } }
// buffer is sent static void fileio_write_on_send_cb (HttpConnection *con, void *ctx, gboolean success, G_GNUC_UNUSED const gchar *buf, G_GNUC_UNUSED size_t buf_len, G_GNUC_UNUSED struct evkeyvalq *headers) { FileWriteData *wdata = (FileWriteData *) ctx; const char *versioning_header; http_connection_release (con); if (!success) { LOG_err (FIO_LOG, INO_CON_H"Failed to send bufer to server !", INO_T (wdata->ino), con); wdata->on_buffer_written_cb (wdata->fop, wdata->ctx, FALSE, 0); g_free (wdata); return; } versioning_header = http_find_header (headers, "x-amz-version-id"); if (versioning_header) { cache_mng_update_version_id (application_get_cache_mng (wdata->fop->app), wdata->ino, versioning_header); } // empty part buffer evbuffer_drain (wdata->fop->write_buf, -1); // done sending part wdata->on_buffer_written_cb (wdata->fop, wdata->ctx, TRUE, wdata->buf_size); g_free (wdata); }
// file is sent static void fileio_release_on_part_sent_cb (HttpConnection *con, void *ctx, gboolean success, G_GNUC_UNUSED const gchar *buf, G_GNUC_UNUSED size_t buf_len, G_GNUC_UNUSED struct evkeyvalq *headers) { FileIO *fop = (FileIO *) ctx; const gchar *versioning_header; http_connection_release (con); if (!success) { LOG_err (FIO_LOG, INO_CON_H"Failed to send bufer to server !", INO_T (fop->ino), con); fileio_destroy (fop); return; } versioning_header = http_find_header (headers, "x-amz-version-id"); if (versioning_header) { cache_mng_update_version_id (application_get_cache_mng (fop->app), fop->ino, versioning_header); } // if it's a multi part upload - Complete Multipart Upload if (fop->multipart_initiated) { fileio_release_complete_multipart (fop); // or we are done } else { fileio_release_update_headers (fop); //fileio_destroy (fop); } }
// multipart is sent static void fileio_release_on_complete_cb (HttpConnection *con, void *ctx, gboolean success, G_GNUC_UNUSED const gchar *buf, G_GNUC_UNUSED size_t buf_len, G_GNUC_UNUSED struct evkeyvalq *headers) { FileIO *fop = (FileIO *) ctx; const gchar *versioning_header; http_connection_release (con); if (!success) { LOG_err (FIO_LOG, INO_CON_H"Failed to send Multipart data to the server !", INO_T (fop->ino), con); fileio_destroy (fop); return; } versioning_header = http_find_header (headers, "x-amz-version-id"); if (versioning_header) { cache_mng_update_version_id (application_get_cache_mng (fop->app), fop->ino, versioning_header); } // done LOG_debug (FIO_LOG, INO_CON_H"Multipart Upload is done !", INO_T (fop->ino), con); // fileio_destroy (fop); fileio_release_update_headers (fop); }
// HTTP client is ready for a new request static void dir_tree_file_remove_on_http_client_cb (gpointer client, gpointer ctx) { S3HttpConnection *http_con = (S3HttpConnection *) client; FileRemoveData *data = (FileRemoveData *) ctx; gchar *req_path; gboolean res; s3http_connection_acquire (http_con); req_path = g_strdup_printf ("%s", data->en->fullpath); res = s3http_connection_make_request (http_con, req_path, req_path, "DELETE", NULL, dir_tree_file_remove_on_http_client_data_cb, dir_tree_file_remove_on_http_client_error_cb, data ); g_free (req_path); if (!res) { LOG_err (DIR_TREE_LOG, "Failed to create HTTP request !"); data->file_remove_cb (data->req, FALSE); s3http_connection_release (http_con); g_free (data); } }
void http_connection_get_container_meta (HttpConnection *con, HttpConnection_container_meta_cb container_meta_cb, gpointer ctx) { gchar *req_path; gboolean res; ContainerMeta *meta; LOG_debug (CON_CONT, "Getting container meta for: %s", application_get_container_name (con->app)); // acquire HTTP client http_connection_acquire (con); meta = g_new0 (ContainerMeta, 1); meta->ctx = ctx; meta->container_meta_cb = container_meta_cb; req_path = g_strdup_printf ("/%s", application_get_container_name (con->app)); res = http_connection_make_request_to_storage_url (con, req_path, "HEAD", NULL, http_connection_on_container_meta_cb, meta ); g_free (req_path); if (!res) { LOG_err (CON_CONT, "Failed to create HTTP request !"); container_meta_cb (ctx, FALSE); http_connection_release (con); return; } }
static void fileio_simple_download_on_con_cb (gpointer client, gpointer ctx) { HttpConnection *con = (HttpConnection *) client; FileIOSimpleDownload *fsim = (FileIOSimpleDownload *) ctx; gboolean res; LOG_debug (FIO_LOG, CON_H"Downloading data.", con); http_connection_acquire (con); http_connection_add_output_header (con, "x-amz-storage-class", conf_get_string (application_get_conf (con->app), "s3.storage_type")); res = http_connection_make_request (con, fsim->fname, "GET", NULL, TRUE, NULL, fileio_simple_download_on_sent_cb, fsim ); if (!res) { LOG_err (FIO_LOG, CON_H"Failed to create HTTP request !", con); http_connection_release (con); fsim->on_download_cb (fsim->ctx, FALSE, NULL, 0); fileio_simple_download_destroy (fsim); return; } }
/*{{{ application_set_url*/ gboolean application_set_url (Application *app, const gchar *url) { if (app->uri) evhttp_uri_free (app->uri); // check if URL contains HTTP or HTTPS if (strlen (url) < 4 || !strcasestr (url, "http") || strcasestr (url, "http") != url) { // XXX: check config and decide HTTP or HTTPS ? gchar *tmp; tmp = g_strdup_printf ("http://%s", url); app->uri = evhttp_uri_parse (tmp); g_free (tmp); } else app->uri = evhttp_uri_parse (url); if (!app->uri) { LOG_err (APP_LOG, " URL (%s) is not valid!", url); application_exit (app); return FALSE; } conf_set_string (app->conf, "s3.host", evhttp_uri_get_host (app->uri)); conf_set_int (app->conf, "s3.port", uri_get_port (app->uri)); conf_set_boolean (app->conf, "s3.ssl", uri_is_https (app->uri)); return TRUE; }
// USR2 signal: reopen log file static void sigusr2_cb (G_GNUC_UNUSED evutil_socket_t sig, G_GNUC_UNUSED short events, G_GNUC_UNUSED void *user_data) { Application *app = _app; // just flush, if log file name is not specified if (!app->log_file_name || !app->f_log) { fflush (app->f_log); return; } LOG_msg (APP_LOG, "Reopening log file: %s !", app->log_file_name); fflush (app->f_log); fclose (app->f_log); app->f_log = fopen (app->log_file_name, "a+"); if (!app->f_log) { LOG_err (APP_LOG, "Failed to open log file: %s, output goes to stdout. Error: %s", app->log_file_name, strerror (errno)); // XXX: set output to stdout logger_set_file (stdout); return; } logger_set_file (app->f_log); }
// existing file is opened, create context data gboolean dir_tree_file_open (DirTree *dtree, fuse_ino_t ino, struct fuse_file_info *fi, DirTree_file_open_cb file_open_cb, fuse_req_t req) { DirTreeFileOpData *op_data; DirEntry *en; op_data = file_op_data_create (dtree, ino); op_data->c_fi = fi; op_data->c_req = req; op_data->file_open_cb = file_open_cb; en = g_hash_table_lookup (dtree->h_inodes, GUINT_TO_POINTER (ino)); // if entry does not exist // or it's not a directory type ? if (!en) { LOG_msg (DIR_TREE_LOG, "Entry (ino = %"INO_FMT") not found !", ino); file_open_cb (op_data->c_req, FALSE, op_data->c_fi); return FALSE; } op_data->en = en; op_data->en->op_data = (gpointer) op_data; LOG_debug (DIR_TREE_LOG, "[%p %p] dir_tree_open inode %"INO_FMT, op_data, fi, ino); if (!s3client_pool_get_client (application_get_read_client_pool (dtree->app), dir_tree_file_open_on_http_ready, op_data)) { LOG_err (DIR_TREE_LOG, "Failed to get S3HttpConnection from the pool !"); } return TRUE; }
// file is closed, free context data void dir_tree_file_release (DirTree *dtree, fuse_ino_t ino, struct fuse_file_info *fi) { DirEntry *en; DirTreeFileOpData *op_data; LOG_debug (DIR_TREE_LOG, "dir_tree_file_release inode %d", ino); en = g_hash_table_lookup (dtree->h_inodes, GUINT_TO_POINTER (ino)); // if entry does not exist // or it's not a directory type ? if (!en) { LOG_msg (DIR_TREE_LOG, "Entry (ino = %"INO_FMT") not found !", ino); //XXX return; } op_data = (DirTreeFileOpData *) en->op_data; // op_data->en = en; // op_data->ino = ino; if (op_data->http) s3http_client_release (op_data->http); // releasing written file if (op_data->tmp_write_fd) { if (!s3client_pool_get_client (application_get_write_client_pool (dtree->app), dir_tree_file_release_on_http_ready, op_data)) { LOG_err (DIR_TREE_LOG, "Failed to get S3HttpConnection from the pool !"); } } else { file_op_data_destroy (op_data); } }
// let it know that directory cache have to be updated static void dir_tree_entry_modified (DirTree *dtree, DirEntry *en) { if (en->type == DET_dir) { if (en->dir_cache_size) { g_free (en->dir_cache); en->dir_cache = NULL; en->dir_cache_size = 0; en->dir_cache_created = 0; } } else { DirEntry *parent_en; parent_en = g_hash_table_lookup (dtree->h_inodes, GUINT_TO_POINTER (en->parent_ino)); if (!parent_en) { LOG_err (DIR_TREE_LOG, "Parent not found for ino: %"INO_FMT" !", en->ino); return; } if (parent_en->dir_cache_size) { if (parent_en->dir_cache) g_free (parent_en->dir_cache); parent_en->dir_cache = NULL; parent_en->dir_cache_size = 0; parent_en->dir_cache_created = 0; } // XXX: get parent, update dir cache } }
void dir_tree_update_entry (DirTree *dtree, const gchar *path, DirEntryType type, fuse_ino_t parent_ino, const gchar *entry_name, long long size) { DirEntry *parent_en; DirEntry *en; LOG_debug (DIR_TREE_LOG, "Updating %s %ld", entry_name, size); // get parent parent_en = g_hash_table_lookup (dtree->h_inodes, GUINT_TO_POINTER (parent_ino)); if (!parent_en || parent_en->type != DET_dir) { LOG_err (DIR_TREE_LOG, "DirEntry is not a directory ! ino: %"INO_FMT, parent_ino); return; } // get child en = g_hash_table_lookup (parent_en->h_dir_tree, entry_name); if (en) { en->age = dtree->current_age; en->size = size; } else { mode_t mode; if (type == DET_file) mode = FILE_DEFAULT_MODE; else mode = DIR_DEFAULT_MODE; dir_tree_add_entry (dtree, entry_name, mode, type, parent_ino, size, time (NULL)); } }
static void fileio_write_send_part (FileWriteData *wdata) { if (!wdata->fop->uploadid) { LOG_err (FIO_LOG, INO_H"UploadID is not set, aborting operation !", INO_T (wdata->ino)); wdata->on_buffer_written_cb (wdata->fop, wdata->ctx, FALSE, 0); g_free (wdata); return; } if (!client_pool_get_client (application_get_write_client_pool (wdata->fop->app), fileio_write_on_send_con_cb, wdata)) { LOG_err (FIO_LOG, INO_H"Failed to get HTTP client !", INO_T (wdata->ino)); wdata->on_buffer_written_cb (wdata->fop, wdata->ctx, FALSE, 0); g_free (wdata); return; } }
static void cache_mng_rm_cache_dir (CacheMng *cmng) { if (cmng->cache_dir && strstr (cmng->cache_dir, CACHE_MNGR_DIR)) utils_del_tree (cmng->cache_dir, 1); else { LOG_err (CMNG_LOG, "Cache directory not found: %s", cmng->cache_dir); } }
GList *bvalue_get_list (BValue *bval) { if (!bvalue_is_list (bval)) { LOG_err (B_LOG, "BValue is not a list !"); return NULL; } return bval->value.list; }
static void sigsegv_cb (int sig_num, siginfo_t *info, void * ucontext) { void *array[50]; void *caller_address; char **messages; int size, i; sig_ucontext_t *uc; FILE *f; g_fprintf (stderr, "Got segmentation fault !\n"); // haven't found the way to get caller addr on FreeBSD, and we need to link with -lexecinfo #if !defined(__FreeBSD__) uc = (sig_ucontext_t *)ucontext; /* Get the address at the time the signal was raised from the EIP (x86) */ #if defined(__APPLE__) #ifdef __i368__ caller_address = (void *) uc->uc_mcontext->__ss.__eip; #else caller_address = (void *) uc->uc_mcontext->__ss.__rip; #endif #else /* !__APPLE__ */ #ifdef __i386__ caller_address = (void *) uc->uc_mcontext.eip; #else caller_address = (void *) uc->uc_mcontext.rip; #endif #endif /* !__APPLE__ */ f = stderr; fprintf (f, "signal %d (%s), address is %p from %p\n", sig_num, strsignal (sig_num), info->si_addr, (void *)caller_address); size = backtrace (array, 50); /* overwrite sigaction with caller's address */ array[1] = caller_address; messages = backtrace_symbols (array, size); /* skip first stack frame (points here) */ for (i = 1; i < size && messages != NULL; ++i) { fprintf (f, "[bt]: (%d) %s\n", i, messages[i]); } fflush (f); free (messages); LOG_err (APP_LOG, "signal %d (%s), address is %p from %p\n", sig_num, strsignal (sig_num), info->si_addr, (void *)caller_address); #endif // __FreeBSD__ // try to unmount FUSE mountpoint if (_app && _app->rfuse) rfuse_destroy (_app->rfuse); }
// same as SIGINT static void sigterm_cb (G_GNUC_UNUSED evutil_socket_t sig, G_GNUC_UNUSED short events, void *user_data) { Application *app = (Application *) user_data; LOG_err (APP_LOG, "Got SIGTERM"); // terminate after running all active events application_exit (app); }
// remove all entries which age is less than current void dir_tree_stop_update (DirTree *dtree, fuse_ino_t parent_ino) { DirEntry *parent_en; parent_en = g_hash_table_lookup (dtree->h_inodes, GUINT_TO_POINTER (parent_ino)); if (!parent_en || parent_en->type != DET_dir) { LOG_err (DIR_TREE_LOG, "DirEntry is not a directory ! ino: %"INO_FMT, parent_ino); return; } LOG_debug (DIR_TREE_LOG, "Removing old DirEntries for: %s ..", parent_en->fullpath); if (parent_en->type != DET_dir) { LOG_err (DIR_TREE_LOG, "Parent is not a directory !"); return; } g_hash_table_foreach_remove (parent_en->h_dir_tree, dir_tree_stop_update_on_remove_child_cb, dtree); }
// create and add a new entry (file or dir) to DirTree static DirEntry *dir_tree_add_entry (DirTree *dtree, const gchar *basename, mode_t mode, DirEntryType type, fuse_ino_t parent_ino, off_t size, time_t ctime) { DirEntry *en; DirEntry *parent_en = NULL; en = g_new0 (DirEntry, 1); // get the parent, for inodes > 0 if (parent_ino) { parent_en = g_hash_table_lookup (dtree->h_inodes, GUINT_TO_POINTER (parent_ino)); if (!parent_en) { LOG_err (DIR_TREE_LOG, "Parent not found for ino: %llu !", parent_ino); return NULL; } // update directory buffer dir_tree_entry_modified (dtree, parent_en); if (parent_ino == 1) en->fullpath = g_strdup_printf ("/%s", basename); else en->fullpath = g_strdup_printf ("%s/%s", parent_en->fullpath, basename); } else { en->fullpath = g_strdup ("/"); } en->ino = dtree->max_ino++; en->age = dtree->current_age; en->basename = g_strdup (basename); en->mode = mode; en->size = size; en->parent_ino = parent_ino; en->type = type; en->ctime = ctime; en->is_modified = FALSE; // cache is empty en->dir_cache = NULL; en->dir_cache_size = 0; en->dir_cache_created = 0; LOG_debug (DIR_TREE_LOG, "Creating new DirEntry: %s, inode: %d, fullpath: %s, mode: %d", en->basename, en->ino, en->fullpath, en->mode); if (type == DET_dir) { en->h_dir_tree = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, dir_entry_destroy); } // add to global inode hash g_hash_table_insert (dtree->h_inodes, GUINT_TO_POINTER (en->ino), en); // add to the parent's hash if (parent_ino) g_hash_table_insert (parent_en->h_dir_tree, en->basename, en); return en; }