1 /*
2 * This file Copyright (C) 2013-2014 Mnemosyne LLC
3 *
4 * It may be used under the GNU GPL versions 2 or 3
5 * or any future license endorsed by Mnemosyne LLC.
6 *
7 */
8
9 #include <string.h> /* strlen() */
10
11 #include "transmission.h"
12 #include "error.h"
13 #include "file.h"
14 #include "tr-assert.h"
15 #include "utils.h"
16
tr_sys_file_read_line(tr_sys_file_t handle,char * buffer,size_t buffer_size,tr_error ** error)17 bool tr_sys_file_read_line(tr_sys_file_t handle, char* buffer, size_t buffer_size, tr_error** error)
18 {
19 TR_ASSERT(handle != TR_BAD_SYS_FILE);
20 TR_ASSERT(buffer != NULL);
21 TR_ASSERT(buffer_size > 0);
22
23 bool ret = false;
24 size_t offset = 0;
25 uint64_t bytes_read;
26
27 while (buffer_size > 0)
28 {
29 size_t const bytes_needed = MIN(buffer_size, 1024u);
30
31 ret = tr_sys_file_read(handle, buffer + offset, bytes_needed, &bytes_read, error);
32
33 if (!ret || (offset == 0 && bytes_read == 0))
34 {
35 ret = false;
36 break;
37 }
38
39 TR_ASSERT(bytes_read <= bytes_needed);
40 TR_ASSERT(bytes_read <= buffer_size);
41
42 int64_t delta = 0;
43
44 for (size_t i = 0; i < bytes_read; ++i, ++offset, --buffer_size)
45 {
46 if (buffer[offset] == '\n')
47 {
48 delta = i - (int64_t)bytes_read + 1;
49 break;
50 }
51 }
52
53 if (delta != 0 || buffer_size == 0 || bytes_read == 0)
54 {
55 if (delta != 0)
56 {
57 ret = tr_sys_file_seek(handle, delta, TR_SEEK_CUR, NULL, error);
58
59 if (!ret)
60 {
61 break;
62 }
63 }
64
65 if (offset > 0 && buffer[offset - 1] == '\r')
66 {
67 buffer[offset - 1] = '\0';
68 }
69 else
70 {
71 buffer[offset] = '\0';
72 }
73
74 break;
75 }
76 }
77
78 return ret;
79 }
80
tr_sys_file_write_line(tr_sys_file_t handle,char const * buffer,tr_error ** error)81 bool tr_sys_file_write_line(tr_sys_file_t handle, char const* buffer, tr_error** error)
82 {
83 TR_ASSERT(handle != TR_BAD_SYS_FILE);
84 TR_ASSERT(buffer != NULL);
85
86 bool ret = tr_sys_file_write(handle, buffer, strlen(buffer), NULL, error);
87
88 if (ret)
89 {
90 ret = tr_sys_file_write(handle, TR_NATIVE_EOL_STR, TR_NATIVE_EOL_STR_SIZE, NULL, error);
91 }
92
93 return ret;
94 }
95
tr_sys_file_write_fmt(tr_sys_file_t handle,char const * format,tr_error ** error,...)96 bool tr_sys_file_write_fmt(tr_sys_file_t handle, char const* format, tr_error** error, ...)
97 {
98 TR_ASSERT(handle != TR_BAD_SYS_FILE);
99 TR_ASSERT(format != NULL);
100
101 bool ret = false;
102 char* buffer;
103 va_list args;
104
105 va_start(args, error);
106 buffer = tr_strdup_vprintf(format, args);
107 va_end(args);
108
109 if (buffer != NULL)
110 {
111 ret = tr_sys_file_write(handle, buffer, strlen(buffer), NULL, error);
112 tr_free(buffer);
113 }
114 else
115 {
116 tr_error_set_literal(error, 0, "Unable to format message.");
117 }
118
119 return ret;
120 }
121