/* * This file Copyright (C) 2013-2014 Mnemosyne LLC * * It may be used under the GNU GPL versions 2 or 3 * or any future license endorsed by Mnemosyne LLC. * */ #include #include /* strlen() */ #include "transmission.h" #include "error.h" #include "file.h" #include "utils.h" bool tr_sys_file_read_line(tr_sys_file_t handle, char* buffer, size_t buffer_size, tr_error** error) { bool ret = false; size_t offset = 0; uint64_t bytes_read; assert(handle != TR_BAD_SYS_FILE); assert(buffer != NULL); assert(buffer_size > 0); while (buffer_size > 0) { size_t i; bool found_eol = false; ret = tr_sys_file_read(handle, buffer + offset, MIN(buffer_size, 1024u), &bytes_read, error); if (!ret || (offset == 0 && bytes_read == 0)) { ret = false; break; } for (i = 0; i < bytes_read; ++i, ++offset, --buffer_size) { if (buffer[offset] == '\n') { found_eol = true; break; } } if (found_eol || buffer_size == 0 || bytes_read == 0) { int64_t const delta = -(int64_t)bytes_read + i + (found_eol ? 1 : 0); if (delta != 0) { ret = tr_sys_file_seek(handle, delta, TR_SEEK_CUR, NULL, error); if (!ret) { break; } } if (offset > 0 && buffer[offset - 1] == '\r') { buffer[offset - 1] = '\0'; } else { buffer[offset] = '\0'; } break; } } return ret; } bool tr_sys_file_write_line(tr_sys_file_t handle, char const* buffer, tr_error** error) { bool ret; assert(handle != TR_BAD_SYS_FILE); assert(buffer != NULL); ret = tr_sys_file_write(handle, buffer, strlen(buffer), NULL, error); if (ret) { ret = tr_sys_file_write(handle, TR_NATIVE_EOL_STR, TR_NATIVE_EOL_STR_SIZE, NULL, error); } return ret; } bool tr_sys_file_write_fmt(tr_sys_file_t handle, char const* format, tr_error** error, ...) { bool ret = false; char* buffer; va_list args; assert(handle != TR_BAD_SYS_FILE); assert(format != NULL); va_start(args, error); buffer = tr_strdup_vprintf(format, args); va_end(args); if (buffer != NULL) { ret = tr_sys_file_write(handle, buffer, strlen(buffer), NULL, error); tr_free(buffer); } else { tr_error_set_literal(error, 0, "Unable to format message."); } return ret; }