static void file_recv_request_cb(GaimXfer *xfer, gpointer handle) { GaimAccount *account; GaimBlistNode *node; const char *pref; char *filename; char *dirname; account = xfer->account; node = (GaimBlistNode *)gaim_find_buddy(account, xfer->who); if (!node) { if (gaim_prefs_get_bool(PREF_STRANGER)) xfer->status = GAIM_XFER_STATUS_CANCEL_LOCAL; return; } node = node->parent; g_return_if_fail(GAIM_BLIST_NODE_IS_CONTACT(node)); pref = gaim_prefs_get_string(PREF_PATH); switch (gaim_blist_node_get_int(node, "autoaccept")) { case FT_ASK: break; case FT_ACCEPT: if (ensure_path_exists(pref)) { dirname = g_build_filename(pref, xfer->who, NULL); if (!ensure_path_exists(dirname)) { g_free(dirname); break; } filename = g_build_filename(dirname, xfer->filename, NULL); gaim_xfer_request_accepted(xfer, filename); g_free(dirname); g_free(filename); } gaim_signal_connect(gaim_xfers_get_handle(), "file-recv-complete", handle, GAIM_CALLBACK(auto_accept_complete_cb), xfer); break; case FT_REJECT: xfer->status = GAIM_XFER_STATUS_CANCEL_LOCAL; break; } }
PRIVATE void ensure_path_exists( char *mpath, char *base ) { if( !strcmp( mpath, base ) ) return; GtkWidget *menuaction = gtk_ui_manager_get_widget( ui_manager, mpath ); if( menuaction == NULL ) { char *updir = g_path_get_dirname( mpath ); char *aname = g_path_get_basename( mpath ); ensure_path_exists( updir, base ); GtkAction *tmpact = gtk_action_new( aname, aname, NULL, NULL ); gtk_action_group_add_action( component_actiongroup, tmpact ); gtk_ui_manager_add_ui( ui_manager, gtk_ui_manager_new_merge_id( ui_manager ), updir, aname, g_strdup(aname), GTK_UI_MANAGER_MENU, TRUE ); //free( aname ); //free( updir ); } }
int set_cache_dir (const char * path) { if (ensure_path_exists(path, 0700)) { logprintfl (EUCAERROR, "failed to set cache directory to '%s'\n", path); return 1; } safe_strncpy (cache_path, path, EUCA_MAX_PATH); return 0; }
int set_work_dir (const char * path) { struct stat mystat; if (stat (path, &mystat)) { work_was_created = TRUE; // remember that work directory had to be created } if (ensure_path_exists(path, 0700)) { logprintfl (EUCAERROR, "failed to set work directory to '%s'\n", path); return 1; } safe_strncpy (work_path, path, EUCA_MAX_PATH); return 0; }
/* if path=A/B/C/D but only A exists, this will try to create B and C, but not D */ int ensure_subdirectory_exists (const char * path) { int len = strlen(path); char * path_copy = strdup(path); int i; if (path_copy==NULL) return errno; for (i=len-1; i>0; i--) { if (path[i]=='/') { path_copy[i] = '\0'; ensure_path_exists (path_copy); break; } } free (path_copy); return 0; }
// if path=A/B/C but only A exists, this will try to create B, but not C int ensure_dir_exists (const char * path, mode_t mode) { int len = strlen (path); char * path_copy = strdup (path); int i, err = 0; if (path_copy==NULL) return errno; for (i=len-1; i>0; i--) { if (path[i]=='/') { path_copy[i] = '\0'; err = ensure_path_exists (path_copy, mode); break; } } free (path_copy); return err; }
PUBLIC void comp_create_action( char *menuitem, ComponentClass *k, gpointer init_data, char *name, char *label ) { char *long_name = g_path_get_basename( menuitem ); char *base = "/ui/MainMenu/AddComp"; char *mpath = g_strdup_printf( "%s/%s", base, menuitem ); // GtkAction *action = g_object_new( COMPACTION_TYPE, // "component-class", k, // "init-data", init_data, GtkAction *action = g_object_new( GALAN_TYPE_COMPACTION, "klass", k, "init_data", init_data, "name", g_strdup(name), "label", long_name, "short-label", g_strdup(name), "hide-if-empty", FALSE, NULL ); gtk_action_group_add_action( component_actiongroup, action ); char *dir_path = g_path_get_dirname( mpath); ensure_path_exists( dir_path, base ); //XXX: the half baked tree model GtkTreeIter iter; galan_comptree_model_lookup( tmodel, menuitem, &iter, TRUE ); gtk_tree_store_set( GTK_TREE_STORE(tmodel), &iter, 1, TRUE, 2, action, -1 ); //XXX: //printf( "name = %s\n", gtk_action_get_name( action ) ); gtk_ui_manager_add_ui( ui_manager, gtk_ui_manager_new_merge_id( ui_manager ), dir_path, name, name, GTK_UI_MANAGER_MENUITEM, TRUE ); }
int reserve_cache_slot (disk_item * di) { // TODO: check if there is enough disk space? if (cache_limit==EUCA_SIZE_UNLIMITED) { // cache is always big enough, we never purge cache_used += di->total_size; goto create; } if (di->total_size > cache_limit) // cache isn't big enough return ERROR; while (di->total_size > (cache_limit-cache_used) ) { time_t oldest_mtime = time (NULL) + 1; off_t oldest_size = 0; disk_item * oldest_entry = NULL; struct stat mystat; disk_item * e; // run through cache and find the LRU entry for ( e = cache_head; e; e=e->next) { if (stat (e->path, &mystat)<0) { logprintfl (EUCAERROR, "error: ok_to_cache() can't stat %s\n", e->path); return ERROR; } if (mystat.st_mtime<oldest_mtime) { oldest_mtime = mystat.st_mtime; oldest_size = e->total_size; // (mystat.st_size doesn't include digest) oldest_entry = e; } else { if (mystat.st_mtime==oldest_mtime) { // with same age, smaller ones get purged first if (oldest_size > e->total_size) { oldest_size = e->total_size; oldest_entry = e; } } } } if ( oldest_entry ) { // remove it logprintfl (EUCAINFO, "purging from cache entry %s\n", oldest_entry->base); if ( oldest_entry->next ) { oldest_entry->next->prev = oldest_entry->prev; } if ( oldest_entry->prev ) { oldest_entry->prev->next = oldest_entry->next; } else { cache_head = oldest_entry->next; } delete_disk_item (oldest_entry); cache_used -= oldest_entry->total_size; free_disk_item (oldest_entry); } else { logprintfl (EUCAERROR, "error: cannot find oldest entry in cache\n"); return 1; } } create: if (ensure_path_exists (di->base, 0700)) { logprintfl (EUCAERROR, "error: failed to create cache entry '%d'\n", di->base); return ERROR; } add_to_cache (di); return OK; }
/* returns size of the file in bytes if OK, otherwise a negative error */ static long long get_cached_file (const char * user_id, const char * url, const char * file_id, const char * instance_id, const char * file_name, char * file_path, sem * s, int convert_to_disk, long long limit_mb) { char tmp_digest_path [BUFSIZE]; char cached_dir [BUFSIZE]; char cached_path [BUFSIZE]; char staging_path [BUFSIZE]; char digest_path [BUFSIZE]; snprintf (file_path, BUFSIZE, "%s/%s/%s/%s", sc_instance_path, user_id, instance_id, file_name); snprintf (tmp_digest_path, BUFSIZE, "%s-digest", file_path); snprintf (cached_dir, BUFSIZE, "%s/%s/cache/%s", sc_instance_path, EUCALYPTUS_ADMIN, file_id); /* cache is in admin's directory */ snprintf (cached_path, BUFSIZE, "%s/%s", cached_dir, file_name); snprintf (staging_path, BUFSIZE, "%s-staging", cached_path); snprintf (digest_path, BUFSIZE, "%s-digest", cached_path); retry: /* under a lock, figure out the state of the file */ sem_p (sc_sem); /***** acquire lock *****/ ensure_subdirectory_exists (file_path); /* creates missing directories */ struct stat mystat; int cached_exists = ! stat (cached_path, &mystat); int staging_exists = ! stat (staging_path, &mystat); int e = ERROR; int action; enum { ABORT, VERIFY, WAIT, STAGE }; if ( staging_exists ) { action = WAIT; } else { if ( cached_exists ) { action = VERIFY; } else { action = STAGE; } } /* we return the sum of these */ long long file_size_b = 0; long long digest_size_b = 0; /* while still under lock, decide whether to cache */ int should_cache = 0; if (action==STAGE) { e = walrus_object_by_url (url, tmp_digest_path, 0); /* get the digest to see how big the file is */ if (e==OK && stat (tmp_digest_path, &mystat)) { digest_size_b = (long long)mystat.st_size; } if (e==OK) { /* pull the size out of the digest */ char * xml_file = file2str (tmp_digest_path); if (xml_file) { file_size_b = str2longlong (xml_file, "<size>", "</size>"); free (xml_file); } if (file_size_b > 0) { long long full_size_b = file_size_b+digest_size_b; if (convert_to_disk) { full_size_b += swap_size_mb*MEGABYTE + MEGABYTE; /* TODO: take into account extra padding required for disks (over partitions) */ } if ( full_size_b/MEGABYTE + 1 > limit_mb ) { logprintfl (EUCAFATAL, "error: insufficient disk capacity remaining (%lldMB) in VM Type of instance %s for component %s\n", limit_mb, instance_id, file_name); action = ABORT; } else if ( ok_to_cache (cached_path, full_size_b) ) { /* will invalidate the cache, if needed */ ensure_path_exists (cached_dir); /* creates missing directories */ should_cache = 1; if ( touch (staging_path) ) { /* indicate that we'll be caching it */ logprintfl (EUCAERROR, "error: failed to create staging file %s\n", staging_path); action = ABORT; } } } else { logprintfl (EUCAERROR, "error: failed to obtain file size from digest %s\n", url); action = ABORT; } } else { logprintfl (EUCAERROR, "error: failed to obtain digest from %s\n", url); action = ABORT; } } sem_v (sc_sem); /***** release lock *****/ switch (action) { case STAGE: logprintfl (EUCAINFO, "downloding image into %s...\n", file_path); e = walrus_image_by_manifest_url (url, file_path, 1); /* for KVM, convert partition into disk */ if (e==OK && convert_to_disk) { sem_p (s); /* for the cached disk swap==0 and ephemeral==0 as we'll append them below */ if ((e=vrun("%s %s %d %d", disk_convert_command_path, file_path, 0, 0))!=0) { logprintfl (EUCAERROR, "error: partition-to-disk image conversion command failed\n"); } sem_v (s); /* recalculate file size now that it was converted */ if ( stat (file_path, &mystat ) != 0 ) { logprintfl (EUCAERROR, "error: file %s not found\n", file_path); } else if (mystat.st_size < 1) { logprintfl (EUCAERROR, "error: file %s has the size of 0\n", file_path); } else { file_size_b = (long long)mystat.st_size; } } /* cache the partition or disk, if possible */ if ( e==OK && should_cache ) { if ( (e=vrun ("cp -a %s %s", file_path, cached_path)) != 0) { logprintfl (EUCAERROR, "failed to copy file %s into cache at %s\n", file_path, cached_path); } if ( e==OK && (e=vrun ("cp -a %s %s", tmp_digest_path, digest_path)) != 0) { logprintfl (EUCAERROR, "failed to copy digest file %s into cache at %s\n", tmp_digest_path, digest_path); } } sem_p (sc_sem); if (should_cache) { unlink (staging_path); } if ( e ) { logprintfl (EUCAERROR, "error: failed to download file from Walrus into %s\n", file_path); unlink (file_path); unlink (tmp_digest_path); if (should_cache) { unlink (cached_path); unlink (digest_path); if ( rmdir(cached_dir) ) { logprintfl (EUCAWARN, "warning: failed to remove cache directory %s\n", cached_dir); } } } sem_v (sc_sem); break; case WAIT: logprintfl (EUCAINFO, "waiting for disapperance of %s...\n", staging_path); /* wait for staging_path to disappear, which means both either the * download succeeded or it failed */ if ( (e=wait_for_file (NULL, staging_path, 180, "cached image")) ) return 0L; /* yes, it is OK to fall through */ case VERIFY: logprintfl (EUCAINFO, "verifying cached file in %s...\n", cached_path); sem_p (sc_sem); /***** acquire lock *****/ e = ERROR; if ( stat (cached_path, &mystat ) != 0 ) { logprintfl (EUCAERROR, "error: file %s not found\n", cached_path); } else if (mystat.st_size < 1) { logprintfl (EUCAERROR, "error: file %s has the size of 0\n", cached_path); } else if ((e=walrus_verify_digest (url, digest_path))<0) { /* negative status => digest changed */ unlink (cached_path); unlink (staging_path); /* TODO: needed? */ unlink (digest_path); if ( rmdir (cached_dir) ) { logprintfl (EUCAWARN, "warning: failed to remove cache directory %s\n", cached_dir); } else { logprintfl (EUCAINFO, "due to failure, removed cache directory %s\n", cached_dir); } } else { file_size_b = mystat.st_size; /* touch the digest so cache can use mtime for invalidation */ if ( touch (digest_path) ) { logprintfl (EUCAERROR, "error: failed to touch digest file %s\n", digest_path); } else if ( stat (digest_path, &mystat) ) { logprintfl (EUCAERROR, "error: digest file %s not found\n", digest_path); } else { digest_size_b = (long long)mystat.st_size; } } sem_v (sc_sem); /***** release lock *****/ if (e<0) { /* digest changed */ if (action==VERIFY) { /* i.e. we did not download/waited for this file */ /* try downloading anew */ goto retry; } else { logprintfl (EUCAERROR, "error: digest mismatch, giving up\n"); return 0L; } } else if (e>0) { /* problem with file or digest */ return 0L; } else { /* all good - copy it, finally */ ensure_subdirectory_exists (file_path); /* creates missing directories */ if ( (e=vrun ("cp -a %s %s", cached_path, file_path)) != 0) { logprintfl (EUCAERROR, "failed to copy file %s from cache at %s\n", file_path, cached_path); return 0L; } } break; case ABORT: logprintfl (EUCAERROR, "get_cached_file() failed (errno=%d)\n", e); e = ERROR; } if (e==OK && file_size_b > 0 && convert_to_disk ) { // if all went well above long long ephemeral_mb = limit_mb - swap_size_mb - (file_size_b+digest_size_b)/MEGABYTE; if ( swap_size_mb>0L || ephemeral_mb>0L ) { sem_p (s); if ((e=vrun("%s %s %lld %lld", disk_convert_command_path, file_path, swap_size_mb, ephemeral_mb))!=0) { logprintfl (EUCAERROR, "error: failed to add swap or ephemeral to the disk image\n"); } sem_v (s); /* recalculate file size (again!) now that it was converted */ if ( stat (file_path, &mystat ) != 0 ) { logprintfl (EUCAERROR, "error: file %s not found\n", file_path); } else if (mystat.st_size < 1) { logprintfl (EUCAERROR, "error: file %s has the size of 0\n", file_path); } else { file_size_b = (long long)mystat.st_size; } } } if (e==OK && action!=ABORT) return file_size_b + digest_size_b; return 0L; }
static void file_recv_request_cb(PurpleXfer *xfer, gpointer handle) { PurpleAccount *account; PurpleBlistNode *node; const char *pref; char *filename; char *dirname; int accept_setting; account = xfer->account; node = PURPLE_BLIST_NODE(purple_find_buddy(account, xfer->who)); /* If person is on buddy list, use the buddy setting; otherwise, use the stranger setting. */ if (node) { node = purple_blist_node_get_parent(node); g_return_if_fail(PURPLE_BLIST_NODE_IS_CONTACT(node)); accept_setting = purple_blist_node_get_int(node, "autoaccept"); } else { accept_setting = purple_prefs_get_int(PREF_STRANGER); } switch (accept_setting) { case FT_ASK: break; case FT_ACCEPT: pref = purple_prefs_get_string(PREF_PATH); if (ensure_path_exists(pref)) { int count = 1; const char *escape; gchar **name_and_ext; const gchar *name; gchar *ext; if (purple_prefs_get_bool(PREF_NEWDIR)) dirname = g_build_filename(pref, purple_normalize(account, xfer->who), NULL); else dirname = g_build_filename(pref, NULL); if (!ensure_path_exists(dirname)) { g_free(dirname); break; } /* Escape filename (if escaping is turned on) */ if (purple_prefs_get_bool(PREF_ESCAPE)) { escape = purple_escape_filename(xfer->filename); } else { escape = xfer->filename; } filename = g_build_filename(dirname, escape, NULL); /* Split at the first dot, to avoid uniquifying "foo.tar.gz" to "foo.tar-2.gz" */ name_and_ext = g_strsplit(escape, ".", 2); name = name_and_ext[0]; g_return_if_fail(name != NULL); if (name_and_ext[1] != NULL) { /* g_strsplit does not include the separator in each chunk. */ ext = g_strdup_printf(".%s", name_and_ext[1]); } else { ext = g_strdup(""); } /* Make sure the file doesn't exist. Do we want some better checking than this? */ /* FIXME: There is a race here: if the newly uniquified file name gets created between * this g_file_test and the transfer starting, the file created in the meantime * will be clobbered. But it's not at all straightforward to fix. */ while (g_file_test(filename, G_FILE_TEST_EXISTS)) { char *file = g_strdup_printf("%s-%d%s", name, count++, ext); g_free(filename); filename = g_build_filename(dirname, file, NULL); g_free(file); } purple_xfer_request_accepted(xfer, filename); g_strfreev(name_and_ext); g_free(ext); g_free(dirname); g_free(filename); } purple_signal_connect(purple_xfers_get_handle(), "file-recv-complete", handle, PURPLE_CALLBACK(auto_accept_complete_cb), xfer); break; case FT_REJECT: xfer->status = PURPLE_XFER_STATUS_CANCEL_LOCAL; break; } }