Remove connection_t usage from write_to_fd

This commit is contained in:
ridiculousfish 2014-06-09 12:57:44 -07:00
parent ef646f0f78
commit 11c1562512
5 changed files with 112 additions and 26 deletions

View File

@ -428,7 +428,7 @@ static int builtin_set(parser_t &parser, wchar_t **argv)
int slice=0; int slice=0;
int i; int i;
wchar_t *bad_char; const wchar_t *bad_char = NULL;
/* Parse options to obtain the requested operation and the modifiers */ /* Parse options to obtain the requested operation and the modifiers */

View File

@ -486,17 +486,17 @@ void append_format(wcstring &str, const wchar_t *format, ...)
va_end(va); va_end(va);
} }
wchar_t *wcsvarname(const wchar_t *str) const wchar_t *wcsvarname(const wchar_t *str)
{ {
while (*str) while (*str)
{ {
if ((!iswalnum(*str)) && (*str != L'_')) if ((!iswalnum(*str)) && (*str != L'_'))
{ {
return (wchar_t *)str; return str;
} }
str++; str++;
} }
return 0; return NULL;
} }
const wchar_t *wcsfuncname(const wchar_t *str) const wchar_t *wcsfuncname(const wchar_t *str)

View File

@ -650,7 +650,7 @@ char **wcsv2strv(const wchar_t * const *in);
\return null if this is a valid name, and a pointer to the first invalid character otherwise \return null if this is a valid name, and a pointer to the first invalid character otherwise
*/ */
wchar_t *wcsvarname(const wchar_t *str); const wchar_t *wcsvarname(const wchar_t *str);
/** /**

View File

@ -42,21 +42,6 @@
*/ */
#define SET_EXPORT_MBS "SET_EXPORT" #define SET_EXPORT_MBS "SET_EXPORT"
/**
Non-wide version of the erase command
*/
#define ERASE_MBS "ERASE"
/**
Non-wide version of the barrier command
*/
#define BARRIER_MBS "BARRIER"
/**
Non-wide version of the barrier_reply command
*/
#define BARRIER_REPLY_MBS "BARRIER_REPLY"
/** /**
Error message Error message
*/ */
@ -409,6 +394,72 @@ void set_body(message_t *msg, ...)
va_end(arg_list); va_end(arg_list);
} }
/* Converts input to UTF-8 and appends it to receiver, using storage as temp storage */
static bool append_utf8(const wcstring &input, std::string *receiver, std::string *storage)
{
bool result = false;
if (wchar_to_utf8_string(input, storage))
{
receiver->append(*storage);
result = true;
}
return result;
}
/* Creates a file entry like "SET fish_color_cwd:FF0". Appends the result to *result (as UTF8). Returns true on success. storage may be used for temporary storage, to avoid allocations */
static bool append_file_entry(fish_message_type_t type, const wcstring &key_in, const wcstring &val_in, std::string *result, std::string *storage)
{
assert(storage != NULL);
assert(result != NULL);
// Record the length on entry, in case we need to back up
bool success = true;
const size_t result_length_on_entry = result->size();
// Append header like "SET "
result->append(type==SET ? SET_MBS : SET_EXPORT_MBS);
result->push_back(' ');
// Append variable name like "fish_color_cwd"
if (wcsvarname(key_in.c_str()))
{
debug(0, L"Illegal variable name: '%ls'", key_in.c_str());
success = false;
}
if (success && ! append_utf8(key_in, result, storage))
{
debug(0, L"Could not convert %ls to narrow character string", key_in.c_str());
success = false;
}
// Append ":"
if (success)
{
result->push_back(':');
}
// Append value
if (success && ! append_utf8(full_escape(val_in.c_str()), result, storage))
{
debug(0, L"Could not convert %ls to narrow character string", val_in.c_str());
success = false;
}
// Append newline
if (success)
{
result->push_back('\n');
}
// Don't modify result on failure. It's sufficient to simply resize it since all we ever did was append to it.
if (! success)
{
result->resize(result_length_on_entry);
}
return success;
}
/* Returns an instance of message_t allocated via new */ /* Returns an instance of message_t allocated via new */
message_t *create_message(fish_message_type_t type, message_t *create_message(fish_message_type_t type,
const wchar_t *key_in, const wchar_t *key_in,
@ -614,6 +665,7 @@ void env_universal_t::enqueue_all_internal(connection_t *c) const
message_t *msg = create_message(entry.exportv ? SET_EXPORT : SET, key.c_str(), entry.val.c_str()); message_t *msg = create_message(entry.exportv ? SET_EXPORT : SET, key.c_str(), entry.val.c_str());
msg->count=1; msg->count=1;
c->unsent.push(msg); c->unsent.push(msg);
fprintf(stderr, "%s", msg->body.c_str());
} }
try_send_all(c); try_send_all(c);
} }
@ -689,18 +741,52 @@ bool env_universal_t::load_from_path(const wcstring &path, callback_data_list_t
return result; return result;
} }
void env_universal_t::write_to_fd(int fd) /* Writes our state to the fd. path is provided only for error reporting */
bool env_universal_t::write_to_fd(int fd, const wcstring &path)
{ {
ASSERT_IS_LOCKED(lock); ASSERT_IS_LOCKED(lock);
assert(fd >= 0); assert(fd >= 0);
connection_t conn(fd); bool success = true;
// Stuff we output to fd
std::string contents;
// Temporary storage
std::string storage;
// Write the save message. If this fails, we don't bother complaining.
write_loop(fd, SAVE_MSG, strlen(SAVE_MSG)); write_loop(fd, SAVE_MSG, strlen(SAVE_MSG));
this->enqueue_all_internal(&conn);
var_table_t::const_iterator iter = vars.begin();
while (iter != vars.end())
{
// Append the entry. Note that append_file_entry may fail, but that only affects one variable; soldier on.
const wcstring &key = iter->first;
const var_entry_t &entry = iter->second;
append_file_entry(entry.exportv ? SET_EXPORT : SET, key, entry.val, &contents, &storage);
// Go to next
++iter;
// Flush if this is the last iteration or we exceed a page
if (iter == vars.end() || contents.size() >= 4096)
{
if (write_loop(fd, contents.data(), contents.size()) < 0)
{
int err = errno;
report_error(err, L"Unable to write to universal variables file '%ls'", path.c_str());
success = false;
break;
}
contents.clear();
}
}
/* Since we just wrote out this file, it matches our internal state; pretend we read from it */ /* Since we just wrote out this file, it matches our internal state; pretend we read from it */
this->last_read_file = file_id_for_fd(fd); this->last_read_file = file_id_for_fd(fd);
/* Do not destroy the connection; we don't close the file */ /* We don't close the file */
return success;
} }
bool env_universal_t::move_new_vars_file_into_place(const wcstring &src, const wcstring &dst) bool env_universal_t::move_new_vars_file_into_place(const wcstring &src, const wcstring &dst)
@ -985,7 +1071,7 @@ bool env_universal_t::sync(callback_data_list_t *callbacks)
if (success) if (success)
{ {
assert(private_fd >= 0); assert(private_fd >= 0);
this->write_to_fd(private_fd); success = this->write_to_fd(private_fd, private_file_path);
} }
if (success) if (success)

View File

@ -209,7 +209,7 @@ class env_universal_t
/* Functions concerned with saving */ /* Functions concerned with saving */
bool open_and_acquire_lock(const wcstring &path, int *out_fd); bool open_and_acquire_lock(const wcstring &path, int *out_fd);
bool open_temporary_file(const wcstring &directory, wcstring *out_path, int *out_fd); bool open_temporary_file(const wcstring &directory, wcstring *out_path, int *out_fd);
void write_to_fd(int fd); bool write_to_fd(int fd, const wcstring &path);
bool move_new_vars_file_into_place(const wcstring &src, const wcstring &dst); bool move_new_vars_file_into_place(const wcstring &src, const wcstring &dst);
/* File id from which we last read */ /* File id from which we last read */