bool env_universal_t::move_new_vars_file_into_place(const wcstring &src, const wcstring &dst) { int ret = wrename(src, dst); if (ret != 0) { int err = errno; report_error(err, L"Unable to rename file from '%ls' to '%ls'", src.c_str(), dst.c_str()); } return ret == 0; }
bool env_universal_t::load() { scoped_lock locker(lock); callback_data_list_t callbacks; const wcstring vars_path = explicit_vars_path.empty() ? default_vars_path() : explicit_vars_path; bool success = load_from_path(vars_path, &callbacks); if (! success && ! tried_renaming && errno == ENOENT) { /* We failed to load, because the file was not found. Older fish used the hostname only. Try *moving* the filename based on the hostname into place; if that succeeds try again. Silently "upgraded." */ tried_renaming = true; std::string hostname_id; if (get_hostname_identifier(&hostname_id)) { const wcstring hostname_path = wdirname(vars_path) + L'/' + str2wcstring(hostname_id); if (0 == wrename(hostname_path, vars_path)) { /* We renamed - try again */ success = this->load(); } } } return success; }
/** Save the specified mode to file */ void history_t::save_internal() { /* This must be called while locked */ ASSERT_IS_LOCKED(lock); /* Nothing to do if there's no new items */ if (new_items.empty() && deleted_items.empty()) return; /* Compact our new items so we don't have duplicates */ this->compact_new_items(); bool ok = true; wcstring tmp_name = history_filename(name, L".tmp"); if( ! tmp_name.empty() ) { /* Make an LRU cache to save only the last N elements */ history_lru_cache_t lru(HISTORY_SAVE_MAX); /* Insert old items in, from old to new. Merge them with our new items, inserting items with earlier timestamps first. */ std::vector<history_item_t>::const_iterator new_item_iter = new_items.begin(); /* Map in existing items (which may have changed out from underneath us, so don't trust our old mmap'd data) */ const char *local_mmap_start = NULL; size_t local_mmap_size = 0; if (map_file(name, &local_mmap_start, &local_mmap_size)) { size_t cursor = 0; for (;;) { size_t offset = offset_of_next_item(local_mmap_start, local_mmap_size, &cursor, 0); /* If we get back -1, we're done */ if (offset == (size_t)(-1)) break; /* Try decoding an old item */ const history_item_t old_item = history_t::decode_item(local_mmap_start + offset, local_mmap_size - offset); if (old_item.empty() || is_deleted(old_item)) { // debug(0, L"Item is deleted : %s\n", old_item.str().c_str()); continue; } /* The old item may actually be more recent than our new item, if it came from another session. Insert all new items at the given index with an earlier timestamp. */ for (; new_item_iter != new_items.end(); ++new_item_iter) { if (new_item_iter->timestamp() < old_item.timestamp()) { /* This "new item" is in fact older. */ lru.add_item(*new_item_iter); } else { /* The new item is not older. */ break; } } /* Now add this old item */ lru.add_item(old_item); } munmap((void *)local_mmap_start, local_mmap_size); } /* Insert any remaining new items */ for (; new_item_iter != new_items.end(); ++new_item_iter) { lru.add_item(*new_item_iter); } signal_block(); FILE *out; if( (out=wfopen( tmp_name, "w" ) ) ) { /* Write them out */ for (history_lru_cache_t::iterator iter = lru.begin(); iter != lru.end(); ++iter) { const history_lru_node_t *node = *iter; if (! node->write_yaml_to_file(out)) { ok = false; break; } } if( fclose( out ) || !ok ) { /* This message does not have high enough priority to be shown by default. */ debug( 2, L"Error when writing history file" ); } else { wcstring new_name = history_filename(name, wcstring()); wrename(tmp_name, new_name); } } signal_unblock(); /* Make sure we clear all nodes, since this doesn't happen automatically */ lru.evict_all_nodes(); /* We've saved everything, so we have no more unsaved items */ unsaved_item_count = 0; } if( ok ) { /* Our history has been written to the file, so clear our state so we can re-reference the file. */ this->clear_file_state(); } }
/** Save the specified mode to file */ static void history_save_mode( void *n, history_mode_t *m ) { FILE *out; history_mode_t *on_disk; int i; int has_new=0; wchar_t *tmp_name; int ok = 1; /* First check if there are any new entries to save. If not, then we can just return */ for( i=0; i<al_get_count(&m->item); i++ ) { void *ptr = al_get( &m->item, i ); has_new = item_is_new( m, ptr ); if( has_new ) { break; } } if( !has_new ) { return; } signal_block(); /* Set up on_disk variable to describe the current contents of the history file */ on_disk = history_create_mode( m->name ); history_load( on_disk ); tmp_name = history_filename( on_disk, m->name, L".tmp" ); if( tmp_name ) { tmp_name = wcsdup(tmp_name ); if( (out=wfopen( tmp_name, "w" ) ) ) { hash_table_t mine; hash_init( &mine, &hash_item_func, &hash_item_cmp ); for( i=0; i<al_get_count(&m->item); i++ ) { void *ptr = al_get( &m->item, i ); int is_new = item_is_new( m, ptr ); if( is_new ) { hash_put( &mine, item_get( m, ptr ), L"" ); } } /* Re-save the old history */ for( i=0; ok && (i<al_get_count(&on_disk->item)); i++ ) { void *ptr = al_get( &on_disk->item, i ); item_t *i = item_get( on_disk, ptr ); if( !hash_get( &mine, i ) ) { if( item_write( out, on_disk, ptr ) == -1 ) { ok = 0; break; } } } hash_destroy( &mine ); /* Add our own items last */ for( i=0; ok && (i<al_get_count(&m->item)); i++ ) { void *ptr = al_get( &m->item, i ); int is_new = item_is_new( m, ptr ); if( is_new ) { if( item_write( out, m, ptr ) == -1 ) { ok = 0; } } } if( fclose( out ) || !ok ) { /* This message does not have high enough priority to be shown by default. */ debug( 2, L"Error when writing history file" ); } else { wrename( tmp_name, history_filename( on_disk, m->name, 0 ) ); } } free( tmp_name ); } halloc_free( on_disk); if( ok ) { /* Reset the history. The item_t entries created in this session are not lost or dropped, they are stored in the session_item hash table. On reload, they will be automatically inserted at the end of the history list. */ if( m->mmap_start && (m->mmap_start != MAP_FAILED ) ) { munmap( m->mmap_start, m->mmap_length ); } al_truncate( &m->item, 0 ); al_truncate( &m->used, 0 ); m->pos = 0; m->has_loaded = 0; m->mmap_start=0; m->mmap_length=0; m->save_timestamp=time(0); m->new_count = 0; } signal_unblock(); }