/src/h2o/deps/libyrmcds/send.c
Line | Count | Source (jump to first uncovered line) |
1 | | // (C) 2013-2016 Cybozu et al. |
2 | | |
3 | | #include "yrmcds.h" |
4 | | #include "yrmcds_portability.h" |
5 | | #include "yrmcds_text.h" |
6 | | |
7 | | #ifdef LIBYRMCDS_USE_LZ4 |
8 | | # include "lz4/lib/lz4.h" |
9 | | #endif |
10 | | |
11 | | #include <errno.h> |
12 | | #include <stdlib.h> |
13 | | #include <string.h> |
14 | | #include <sys/socket.h> |
15 | | #include <sys/types.h> |
16 | | #include <sys/uio.h> |
17 | | |
18 | | static const size_t BINARY_HEADER_SIZE = 24; |
19 | | static const size_t MAX_DATA_SIZE = ((size_t)1) << 30; |
20 | | |
21 | 0 | static inline void hton64(uint64_t i, char* p) { |
22 | 0 | uint64_t n = htobe64(i); |
23 | 0 | memcpy(p, &n, sizeof(n)); |
24 | 0 | } |
25 | | |
26 | 0 | static inline void hton32(uint32_t i, char* p) { |
27 | 0 | uint32_t n = htobe32(i); |
28 | 0 | memcpy(p, &n, sizeof(n)); |
29 | 0 | } |
30 | | |
31 | 0 | static inline void hton16(uint16_t i, char* p) { |
32 | 0 | uint16_t n = htobe16(i); |
33 | 0 | memcpy(p, &n, sizeof(n)); |
34 | 0 | } |
35 | | |
36 | | static yrmcds_error send_command( |
37 | | yrmcds* c, yrmcds_command cmd, uint64_t cas, uint32_t* serial, |
38 | | size_t key_len, const char* key, |
39 | | size_t extras_len, const char* extras, |
40 | 0 | size_t data_len, const char* data) { |
41 | 0 | if( cmd >= YRMCDS_CMD_BOTTOM || |
42 | 0 | key_len > 65535 || extras_len > 127 || data_len > MAX_DATA_SIZE || |
43 | 0 | (key_len != 0 && key == NULL) || |
44 | 0 | (extras_len != 0 && extras == NULL) || |
45 | 0 | (data_len != 0 && data == NULL) ) |
46 | 0 | return YRMCDS_BAD_ARGUMENT; |
47 | | |
48 | 0 | char h[BINARY_HEADER_SIZE]; |
49 | 0 | memset(h, 0, sizeof(h)); |
50 | 0 | h[0] = '\x80'; |
51 | 0 | h[1] = (char)cmd; |
52 | 0 | hton16((uint16_t)key_len, &h[2]); |
53 | 0 | h[4] = (char)extras_len; |
54 | 0 | size_t total_len = (key_len + extras_len + data_len); |
55 | 0 | hton32((uint32_t)total_len, &h[8]); |
56 | 0 | hton64(cas, &h[16]); |
57 | |
|
58 | 0 | #ifndef LIBYRMCDS_NO_INTERNAL_LOCK |
59 | 0 | int e = pthread_mutex_lock(&c->lock); |
60 | 0 | if( e != 0 ) { |
61 | 0 | errno = e; |
62 | 0 | return YRMCDS_SYSTEM_ERROR; |
63 | 0 | } |
64 | 0 | #endif // ! LIBYRMCDS_NO_INTERNAL_LOCK |
65 | | |
66 | 0 | yrmcds_error ret = YRMCDS_OK; |
67 | 0 | c->serial = c->serial + 1; |
68 | 0 | memcpy(&h[12], &c->serial, 4); |
69 | 0 | if( serial != NULL ) |
70 | 0 | *serial = c->serial; |
71 | |
|
72 | 0 | struct iovec iov[4]; |
73 | 0 | int iovcnt = 1; |
74 | 0 | iov[0].iov_base = h; |
75 | 0 | iov[0].iov_len = sizeof(h); |
76 | |
|
77 | 0 | if( extras_len > 0 ) { |
78 | 0 | iov[iovcnt].iov_base = (void*)extras; |
79 | 0 | iov[iovcnt].iov_len = extras_len; |
80 | 0 | iovcnt++; |
81 | 0 | } |
82 | 0 | if( key_len > 0 ) { |
83 | 0 | iov[iovcnt].iov_base = (void*)key; |
84 | 0 | iov[iovcnt].iov_len = key_len; |
85 | 0 | iovcnt++; |
86 | 0 | } |
87 | 0 | if( data_len > 0 ) { |
88 | 0 | iov[iovcnt].iov_base = (void*)data; |
89 | 0 | iov[iovcnt].iov_len = data_len; |
90 | 0 | iovcnt++; |
91 | 0 | } |
92 | |
|
93 | 0 | while( iovcnt > 0 ) { |
94 | 0 | ssize_t n = writev(c->sock, iov, iovcnt); |
95 | 0 | size_t n2 = (size_t)n; |
96 | 0 | if( n == -1 ) { |
97 | 0 | if( errno == EINTR ) continue; |
98 | 0 | ret = YRMCDS_SYSTEM_ERROR; |
99 | 0 | goto OUT; |
100 | 0 | } |
101 | 0 | while( n2 > 0 ) { |
102 | 0 | if( n2 < iov[0].iov_len ) { |
103 | 0 | iov[0].iov_base = (char*)iov[0].iov_base + n2; |
104 | 0 | iov[0].iov_len -= n2; |
105 | 0 | break; |
106 | 0 | } |
107 | 0 | n2 -= iov[0].iov_len; |
108 | 0 | iovcnt --; |
109 | 0 | if( iovcnt == 0 ) |
110 | 0 | break; |
111 | | |
112 | 0 | int i; |
113 | 0 | for( i = 0; i < iovcnt; ++i ) |
114 | 0 | iov[i] = iov[i+1]; |
115 | 0 | } |
116 | 0 | } |
117 | | |
118 | 0 | OUT: |
119 | 0 | #ifndef LIBYRMCDS_NO_INTERNAL_LOCK |
120 | 0 | pthread_mutex_unlock(&c->lock); |
121 | 0 | #endif |
122 | 0 | return ret; |
123 | 0 | } |
124 | | |
125 | | static yrmcds_error send_data( |
126 | | yrmcds* c, yrmcds_command cmd, const char* key, size_t key_len, |
127 | | const char* data, size_t data_len, uint32_t flags, uint32_t expire, |
128 | 0 | uint64_t cas, uint32_t* serial) { |
129 | 0 | if( c == NULL || key == NULL || key_len == 0 || |
130 | 0 | data == NULL || data_len == 0 ) |
131 | 0 | return YRMCDS_BAD_ARGUMENT; |
132 | | |
133 | 0 | int compressed = 0; |
134 | | #ifdef LIBYRMCDS_USE_LZ4 |
135 | | if( (c->compress_size > 0) && (data_len > c->compress_size) ) { |
136 | | if( flags & YRMCDS_FLAG_COMPRESS ) |
137 | | return YRMCDS_BAD_ARGUMENT; |
138 | | |
139 | | size_t bound = (size_t)LZ4_compressBound((int)data_len); |
140 | | char* new_data = (char*)malloc(bound + sizeof(uint32_t)); |
141 | | if( new_data == NULL ) |
142 | | return YRMCDS_OUT_OF_MEMORY; |
143 | | uint32_t new_size = |
144 | | (uint32_t)LZ4_compress(data, new_data + sizeof(uint32_t), |
145 | | (int)data_len); |
146 | | if( new_size == 0 ) { |
147 | | free(new_data); |
148 | | return YRMCDS_COMPRESS_FAILED; |
149 | | } |
150 | | hton32((uint32_t)data_len, new_data); |
151 | | flags |= YRMCDS_FLAG_COMPRESS; |
152 | | data_len = sizeof(uint32_t) + new_size; |
153 | | data = new_data; |
154 | | compressed = 1; |
155 | | } |
156 | | #endif // LIBYRMCDS_USE_LZ4 |
157 | |
|
158 | 0 | char extras[8]; |
159 | 0 | hton32(flags, extras); |
160 | 0 | hton32(expire, &extras[4]); |
161 | 0 | yrmcds_error e = send_command(c, cmd, cas, serial, key_len, key, |
162 | 0 | sizeof(extras), extras, data_len, data); |
163 | 0 | if( compressed ) |
164 | 0 | free((void*)data); |
165 | 0 | return e; |
166 | 0 | } |
167 | | |
168 | 0 | yrmcds_error yrmcds_noop(yrmcds* c, uint32_t* serial) { |
169 | 0 | if( c == NULL ) |
170 | 0 | return YRMCDS_BAD_ARGUMENT; |
171 | | |
172 | 0 | if( c->text_mode ) |
173 | 0 | return YRMCDS_NOT_IMPLEMENTED; |
174 | | |
175 | 0 | return send_command(c, YRMCDS_CMD_NOOP, 0, serial, |
176 | 0 | 0, NULL, 0, NULL, 0, NULL); |
177 | 0 | } |
178 | | |
179 | | yrmcds_error yrmcds_get(yrmcds* c, const char* key, size_t key_len, |
180 | 0 | int quiet, uint32_t* serial) { |
181 | 0 | if( c == NULL || key == NULL || key_len == 0 ) |
182 | 0 | return YRMCDS_BAD_ARGUMENT; |
183 | | |
184 | 0 | if( c->text_mode ) |
185 | 0 | return yrmcds_text_get(c, key, key_len, quiet, serial); |
186 | | |
187 | 0 | return send_command(c, quiet ? YRMCDS_CMD_GETQ : YRMCDS_CMD_GET, |
188 | 0 | 0, serial, key_len, key, 0, NULL, 0, NULL); |
189 | 0 | } |
190 | | |
191 | | yrmcds_error yrmcds_getk(yrmcds* c, const char* key, size_t key_len, |
192 | 0 | int quiet, uint32_t* serial) { |
193 | 0 | if( c == NULL || key == NULL || key_len == 0 ) |
194 | 0 | return YRMCDS_BAD_ARGUMENT; |
195 | | |
196 | 0 | if( c->text_mode ) |
197 | 0 | return yrmcds_text_get(c, key, key_len, quiet, serial); |
198 | | |
199 | 0 | return send_command(c, quiet ? YRMCDS_CMD_GETKQ : YRMCDS_CMD_GETK, |
200 | 0 | 0, serial, key_len, key, 0, NULL, 0, NULL); |
201 | 0 | } |
202 | | |
203 | | yrmcds_error yrmcds_get_touch(yrmcds* c, const char* key, size_t key_len, |
204 | 0 | uint32_t expire, int quiet, uint32_t* serial) { |
205 | 0 | if( c == NULL || key == NULL || key_len == 0 ) |
206 | 0 | return YRMCDS_BAD_ARGUMENT; |
207 | | |
208 | 0 | if( c->text_mode ) |
209 | 0 | return YRMCDS_NOT_IMPLEMENTED; |
210 | | |
211 | 0 | char extras[4]; |
212 | 0 | hton32(expire, extras); |
213 | 0 | return send_command(c, quiet ? YRMCDS_CMD_GATQ : YRMCDS_CMD_GAT, |
214 | 0 | 0, serial, key_len, key, |
215 | 0 | sizeof(extras), extras, 0, NULL); |
216 | 0 | } |
217 | | |
218 | | yrmcds_error yrmcds_getk_touch(yrmcds* c, const char* key, size_t key_len, |
219 | 0 | uint32_t expire, int quiet, uint32_t* serial) { |
220 | 0 | if( c == NULL || key == NULL || key_len == 0 ) |
221 | 0 | return YRMCDS_BAD_ARGUMENT; |
222 | | |
223 | 0 | if( c->text_mode ) |
224 | 0 | return YRMCDS_NOT_IMPLEMENTED; |
225 | | |
226 | 0 | char extras[4]; |
227 | 0 | hton32(expire, extras); |
228 | 0 | return send_command(c, quiet ? YRMCDS_CMD_GATKQ : YRMCDS_CMD_GATK, |
229 | 0 | 0, serial, key_len, key, |
230 | 0 | sizeof(extras), extras, 0, NULL); |
231 | 0 | } |
232 | | |
233 | | yrmcds_error yrmcds_lock_get(yrmcds* c, const char* key, size_t key_len, |
234 | 0 | int quiet, uint32_t* serial) { |
235 | 0 | if( c == NULL || key == NULL || key_len == 0 ) |
236 | 0 | return YRMCDS_BAD_ARGUMENT; |
237 | | |
238 | 0 | if( c->text_mode ) |
239 | 0 | return YRMCDS_NOT_IMPLEMENTED; |
240 | | |
241 | 0 | return send_command(c, quiet ? YRMCDS_CMD_LAGQ : YRMCDS_CMD_LAG, |
242 | 0 | 0, serial, key_len, key, 0, NULL, 0, NULL); |
243 | 0 | } |
244 | | |
245 | | yrmcds_error yrmcds_lock_getk(yrmcds* c, const char* key, size_t key_len, |
246 | 0 | int quiet, uint32_t* serial) { |
247 | 0 | if( c == NULL || key == NULL || key_len == 0 ) |
248 | 0 | return YRMCDS_BAD_ARGUMENT; |
249 | | |
250 | 0 | if( c->text_mode ) |
251 | 0 | return YRMCDS_NOT_IMPLEMENTED; |
252 | | |
253 | 0 | return send_command(c, quiet ? YRMCDS_CMD_LAGKQ : YRMCDS_CMD_LAGK, |
254 | 0 | 0, serial, key_len, key, 0, NULL, 0, NULL); |
255 | 0 | } |
256 | | |
257 | | yrmcds_error yrmcds_touch(yrmcds* c, const char* key, size_t key_len, |
258 | 0 | uint32_t expire, int quiet, uint32_t* serial) { |
259 | 0 | if( c == NULL || key == NULL || key_len == 0 ) |
260 | 0 | return YRMCDS_BAD_ARGUMENT; |
261 | | |
262 | 0 | if( c->text_mode ) |
263 | 0 | return yrmcds_text_touch(c, key, key_len, expire, quiet, serial); |
264 | | |
265 | 0 | char extras[4]; |
266 | 0 | hton32(expire, extras); |
267 | 0 | return send_command(c, YRMCDS_CMD_TOUCH, 0, serial, key_len, key, |
268 | 0 | sizeof(extras), extras, 0, NULL); |
269 | 0 | } |
270 | | |
271 | | yrmcds_error yrmcds_set(yrmcds* c, const char* key, size_t key_len, |
272 | | const char* data, size_t data_len, |
273 | | uint32_t flags, uint32_t expire, uint64_t cas, |
274 | 0 | int quiet, uint32_t* serial) { |
275 | 0 | if( c && c->text_mode ) |
276 | 0 | return yrmcds_text_set(c, key, key_len, data, data_len, |
277 | 0 | flags, expire, cas, quiet, serial); |
278 | | |
279 | 0 | return send_data(c, quiet ? YRMCDS_CMD_SETQ : YRMCDS_CMD_SET, |
280 | 0 | key, key_len, data, data_len, flags, expire, cas, serial); |
281 | 0 | } |
282 | | |
283 | | yrmcds_error yrmcds_replace(yrmcds* c, const char* key, size_t key_len, |
284 | | const char* data, size_t data_len, |
285 | | uint32_t flags, uint32_t expire, uint64_t cas, |
286 | 0 | int quiet, uint32_t* serial) { |
287 | 0 | if( c && c->text_mode ) |
288 | 0 | return yrmcds_text_replace(c, key, key_len, data, data_len, |
289 | 0 | flags, expire, cas, quiet, serial); |
290 | | |
291 | 0 | return send_data(c, quiet ? YRMCDS_CMD_REPLACEQ : YRMCDS_CMD_REPLACE, |
292 | 0 | key, key_len, data, data_len, flags, expire, cas, serial); |
293 | 0 | } |
294 | | |
295 | | yrmcds_error yrmcds_add(yrmcds* c, const char* key, size_t key_len, |
296 | | const char* data, size_t data_len, |
297 | | uint32_t flags, uint32_t expire, uint64_t cas, |
298 | 0 | int quiet, uint32_t* serial) { |
299 | 0 | if( c && c->text_mode ) |
300 | 0 | return yrmcds_text_add(c, key, key_len, data, data_len, |
301 | 0 | flags, expire, cas, quiet, serial); |
302 | | |
303 | 0 | return send_data(c, quiet ? YRMCDS_CMD_ADDQ : YRMCDS_CMD_ADD, |
304 | 0 | key, key_len, data, data_len, flags, expire, cas, serial); |
305 | 0 | } |
306 | | |
307 | | yrmcds_error yrmcds_replace_unlock(yrmcds* c, const char* key, size_t key_len, |
308 | | const char* data, size_t data_len, |
309 | | uint32_t flags, uint32_t expire, |
310 | 0 | int quiet, uint32_t* serial) { |
311 | 0 | if( c && c->text_mode ) |
312 | 0 | return YRMCDS_NOT_IMPLEMENTED; |
313 | | |
314 | 0 | return send_data(c, quiet ? YRMCDS_CMD_RAUQ : YRMCDS_CMD_RAU, |
315 | 0 | key, key_len, data, data_len, flags, expire, 0, serial); |
316 | 0 | } |
317 | | |
318 | | yrmcds_error yrmcds_incr(yrmcds* c, const char* key, size_t key_len, |
319 | 0 | uint64_t value, int quiet, uint32_t* serial) { |
320 | 0 | if( c == NULL || key == NULL || key_len == 0 ) |
321 | 0 | return YRMCDS_BAD_ARGUMENT; |
322 | | |
323 | 0 | if( c->text_mode ) |
324 | 0 | return yrmcds_text_incr(c, key, key_len, value, quiet, serial); |
325 | | |
326 | 0 | char extras[20]; |
327 | 0 | hton64(value, extras); |
328 | 0 | hton64((uint64_t)0, &extras[8]); |
329 | 0 | hton32(~(uint32_t)0, &extras[16]); |
330 | 0 | return send_command(c, quiet ? YRMCDS_CMD_INCREMENTQ : YRMCDS_CMD_INCREMENT, |
331 | 0 | 0, serial, key_len, key, |
332 | 0 | sizeof(extras), extras, 0, NULL); |
333 | 0 | } |
334 | | |
335 | | yrmcds_error yrmcds_incr2(yrmcds* c, const char* key, size_t key_len, |
336 | | uint64_t value, uint64_t initial, uint32_t expire, |
337 | 0 | int quiet, uint32_t* serial) { |
338 | 0 | if( c == NULL || key == NULL || key_len == 0 ) |
339 | 0 | return YRMCDS_BAD_ARGUMENT; |
340 | | |
341 | 0 | if( c->text_mode ) |
342 | 0 | return YRMCDS_NOT_IMPLEMENTED; |
343 | | |
344 | 0 | char extras[20]; |
345 | 0 | hton64(value, extras); |
346 | 0 | hton64(initial, &extras[8]); |
347 | 0 | hton32(expire, &extras[16]); |
348 | 0 | return send_command(c, quiet ? YRMCDS_CMD_INCREMENTQ : YRMCDS_CMD_INCREMENT, |
349 | 0 | 0, serial, key_len, key, |
350 | 0 | sizeof(extras), extras, 0, NULL); |
351 | 0 | } |
352 | | |
353 | | yrmcds_error yrmcds_decr(yrmcds* c, const char* key, size_t key_len, |
354 | 0 | uint64_t value, int quiet, uint32_t* serial) { |
355 | 0 | if( c == NULL || key == NULL || key_len == 0 ) |
356 | 0 | return YRMCDS_BAD_ARGUMENT; |
357 | | |
358 | 0 | if( c->text_mode ) |
359 | 0 | return yrmcds_text_decr(c, key, key_len, value, quiet, serial); |
360 | | |
361 | 0 | char extras[20]; |
362 | 0 | hton64(value, extras); |
363 | 0 | hton64((uint64_t)0, &extras[8]); |
364 | 0 | hton32(~(uint32_t)0, &extras[16]); |
365 | 0 | return send_command(c, quiet ? YRMCDS_CMD_DECREMENTQ : YRMCDS_CMD_DECREMENT, |
366 | 0 | 0, serial, key_len, key, |
367 | 0 | sizeof(extras), extras, 0, NULL); |
368 | 0 | } |
369 | | |
370 | | yrmcds_error yrmcds_decr2(yrmcds* c, const char* key, size_t key_len, |
371 | | uint64_t value, uint64_t initial, uint32_t expire, |
372 | 0 | int quiet, uint32_t* serial) { |
373 | 0 | if( c == NULL || key == NULL || key_len == 0 ) |
374 | 0 | return YRMCDS_BAD_ARGUMENT; |
375 | | |
376 | 0 | if( c->text_mode ) |
377 | 0 | return YRMCDS_NOT_IMPLEMENTED; |
378 | | |
379 | 0 | char extras[20]; |
380 | 0 | hton64(value, extras); |
381 | 0 | hton64(initial, &extras[8]); |
382 | 0 | hton32(expire, &extras[16]); |
383 | 0 | return send_command(c, quiet ? YRMCDS_CMD_DECREMENTQ : YRMCDS_CMD_DECREMENT, |
384 | 0 | 0, serial, key_len, key, |
385 | 0 | sizeof(extras), extras, 0, NULL); |
386 | 0 | } |
387 | | |
388 | | yrmcds_error yrmcds_append(yrmcds* c, const char* key, size_t key_len, |
389 | | const char* data, size_t data_len, |
390 | 0 | int quiet, uint32_t* serial) { |
391 | 0 | if( c == NULL || key == NULL || key_len == 0 || |
392 | 0 | data == NULL || data_len == 0 ) |
393 | 0 | return YRMCDS_BAD_ARGUMENT; |
394 | | |
395 | 0 | if( c->text_mode ) |
396 | 0 | return yrmcds_text_append(c, key, key_len, data, data_len, |
397 | 0 | quiet, serial); |
398 | | |
399 | 0 | return send_command(c, quiet ? YRMCDS_CMD_APPENDQ : YRMCDS_CMD_APPEND, |
400 | 0 | 0, serial, key_len, key, 0, NULL, data_len, data); |
401 | 0 | } |
402 | | |
403 | | yrmcds_error yrmcds_prepend(yrmcds* c, const char* key, size_t key_len, |
404 | | const char* data, size_t data_len, |
405 | 0 | int quiet, uint32_t* serial) { |
406 | 0 | if( c == NULL || key == NULL || key_len == 0 || |
407 | 0 | data == NULL || data_len == 0 ) |
408 | 0 | return YRMCDS_BAD_ARGUMENT; |
409 | | |
410 | 0 | if( c->text_mode ) |
411 | 0 | return yrmcds_text_prepend(c, key, key_len, data, data_len, |
412 | 0 | quiet, serial); |
413 | | |
414 | 0 | return send_command(c, quiet ? YRMCDS_CMD_PREPENDQ : YRMCDS_CMD_PREPEND, |
415 | 0 | 0, serial, key_len, key, 0, NULL, data_len, data); |
416 | 0 | } |
417 | | |
418 | | yrmcds_error yrmcds_remove(yrmcds* c, const char* key, size_t key_len, |
419 | 0 | int quiet, uint32_t* serial) { |
420 | 0 | if( c == NULL || key == NULL || key_len == 0 ) |
421 | 0 | return YRMCDS_BAD_ARGUMENT; |
422 | | |
423 | 0 | if( c->text_mode ) |
424 | 0 | return yrmcds_text_remove(c, key, key_len, quiet, serial); |
425 | | |
426 | 0 | return send_command(c, quiet ? YRMCDS_CMD_DELETEQ : YRMCDS_CMD_DELETE, |
427 | 0 | 0, serial, key_len, key, 0, NULL, 0, NULL); |
428 | 0 | } |
429 | | |
430 | | yrmcds_error yrmcds_lock(yrmcds* c, const char* key, size_t key_len, |
431 | 0 | int quiet, uint32_t* serial) { |
432 | 0 | if( c == NULL || key == NULL || key_len == 0 ) |
433 | 0 | return YRMCDS_BAD_ARGUMENT; |
434 | | |
435 | 0 | if( c->text_mode ) |
436 | 0 | return YRMCDS_NOT_IMPLEMENTED; |
437 | | |
438 | 0 | return send_command(c, quiet ? YRMCDS_CMD_LOCKQ : YRMCDS_CMD_LOCK, |
439 | 0 | 0, serial, key_len, key, 0, NULL, 0, NULL); |
440 | 0 | } |
441 | | |
442 | | yrmcds_error yrmcds_unlock(yrmcds* c, const char* key, size_t key_len, |
443 | 0 | int quiet, uint32_t* serial) { |
444 | 0 | if( c == NULL || key == NULL || key_len == 0 ) |
445 | 0 | return YRMCDS_BAD_ARGUMENT; |
446 | | |
447 | 0 | if( c->text_mode ) |
448 | 0 | return YRMCDS_NOT_IMPLEMENTED; |
449 | | |
450 | 0 | return send_command(c, quiet ? YRMCDS_CMD_UNLOCKQ : YRMCDS_CMD_UNLOCK, |
451 | 0 | 0, serial, key_len, key, 0, NULL, 0, NULL); |
452 | 0 | } |
453 | | |
454 | 0 | yrmcds_error yrmcds_unlockall(yrmcds* c, int quiet, uint32_t* serial) { |
455 | 0 | if( c == NULL ) |
456 | 0 | return YRMCDS_BAD_ARGUMENT; |
457 | | |
458 | 0 | if( c->text_mode ) |
459 | 0 | return YRMCDS_NOT_IMPLEMENTED; |
460 | | |
461 | 0 | return send_command(c, quiet ? YRMCDS_CMD_UNLOCKALLQ : YRMCDS_CMD_UNLOCKALL, |
462 | 0 | 0, serial, 0, NULL, 0, NULL, 0, NULL); |
463 | 0 | } |
464 | | |
465 | | yrmcds_error yrmcds_flush(yrmcds* c, uint32_t delay, |
466 | 0 | int quiet, uint32_t* serial) { |
467 | 0 | if( c == NULL ) |
468 | 0 | return YRMCDS_BAD_ARGUMENT; |
469 | | |
470 | 0 | if( c->text_mode ) |
471 | 0 | return yrmcds_text_flush(c, delay, quiet, serial); |
472 | | |
473 | 0 | if( delay == 0 ) |
474 | 0 | return send_command(c, quiet ? YRMCDS_CMD_FLUSHQ : YRMCDS_CMD_FLUSH, |
475 | 0 | 0, serial, 0, NULL, 0, NULL, 0, NULL); |
476 | | |
477 | 0 | char extra[4]; |
478 | 0 | hton32(delay, extra); |
479 | 0 | return send_command(c, quiet ? YRMCDS_CMD_FLUSHQ : YRMCDS_CMD_FLUSH, |
480 | 0 | 0, serial, 0, NULL, sizeof(extra), extra, 0, NULL); |
481 | 0 | } |
482 | | |
483 | 0 | yrmcds_error yrmcds_stat_general(yrmcds* c, uint32_t* serial) { |
484 | 0 | if( c == NULL ) |
485 | 0 | return YRMCDS_BAD_ARGUMENT; |
486 | | |
487 | 0 | if( c->text_mode ) |
488 | 0 | return YRMCDS_NOT_IMPLEMENTED; |
489 | | |
490 | 0 | return send_command(c, YRMCDS_CMD_STAT, |
491 | 0 | 0, serial, 0, NULL, 0, NULL, 0, NULL); |
492 | 0 | } |
493 | | |
494 | 0 | yrmcds_error yrmcds_stat_settings(yrmcds* c, uint32_t* serial) { |
495 | 0 | if( c == NULL ) |
496 | 0 | return YRMCDS_BAD_ARGUMENT; |
497 | | |
498 | 0 | if( c->text_mode ) |
499 | 0 | return YRMCDS_NOT_IMPLEMENTED; |
500 | | |
501 | 0 | const char key[] = "settings"; |
502 | 0 | return send_command(c, YRMCDS_CMD_STAT, |
503 | 0 | 0, serial, sizeof(key) - 1, key, 0, NULL, 0, NULL); |
504 | 0 | } |
505 | | |
506 | 0 | yrmcds_error yrmcds_stat_items(yrmcds* c, uint32_t* serial) { |
507 | 0 | if( c == NULL ) |
508 | 0 | return YRMCDS_BAD_ARGUMENT; |
509 | | |
510 | 0 | if( c->text_mode ) |
511 | 0 | return YRMCDS_NOT_IMPLEMENTED; |
512 | | |
513 | 0 | const char key[] = "items"; |
514 | 0 | return send_command(c, YRMCDS_CMD_STAT, |
515 | 0 | 0, serial, sizeof(key) - 1, key, 0, NULL, 0, NULL); |
516 | 0 | } |
517 | | |
518 | 0 | yrmcds_error yrmcds_stat_sizes(yrmcds* c, uint32_t* serial) { |
519 | 0 | if( c == NULL ) |
520 | 0 | return YRMCDS_BAD_ARGUMENT; |
521 | | |
522 | 0 | if( c->text_mode ) |
523 | 0 | return YRMCDS_NOT_IMPLEMENTED; |
524 | | |
525 | 0 | const char key[] = "sizes"; |
526 | 0 | return send_command(c, YRMCDS_CMD_STAT, |
527 | 0 | 0, serial, sizeof(key) - 1, key, 0, NULL, 0, NULL); |
528 | 0 | } |
529 | | |
530 | | yrmcds_error yrmcds_keys(yrmcds* c, const char* prefix, size_t prefix_len, |
531 | 0 | uint32_t* serial) { |
532 | 0 | if( c == NULL || |
533 | 0 | (prefix == NULL && prefix_len != 0) || |
534 | 0 | (prefix != NULL && prefix_len == 0) ) |
535 | 0 | return YRMCDS_BAD_ARGUMENT; |
536 | | |
537 | 0 | if( c->text_mode ) |
538 | 0 | return YRMCDS_NOT_IMPLEMENTED; |
539 | | |
540 | 0 | return send_command(c, YRMCDS_CMD_KEYS, |
541 | 0 | 0, serial, prefix_len, prefix, 0, NULL, 0, NULL); |
542 | 0 | } |
543 | | |
544 | 0 | yrmcds_error yrmcds_version(yrmcds* c, uint32_t* serial) { |
545 | 0 | if( c == NULL ) |
546 | 0 | return YRMCDS_BAD_ARGUMENT; |
547 | | |
548 | 0 | if( c->text_mode ) |
549 | 0 | return yrmcds_text_version(c, serial); |
550 | | |
551 | 0 | return send_command(c, YRMCDS_CMD_VERSION, |
552 | 0 | 0, serial, 0, NULL, 0, NULL, 0, NULL); |
553 | 0 | } |
554 | | |
555 | 0 | yrmcds_error yrmcds_quit(yrmcds* c, int quiet, uint32_t* serial) { |
556 | 0 | if( c == NULL ) |
557 | 0 | return YRMCDS_BAD_ARGUMENT; |
558 | | |
559 | 0 | if( c->text_mode ) |
560 | 0 | return yrmcds_text_quit(c, serial); |
561 | | |
562 | 0 | return send_command(c, quiet ? YRMCDS_CMD_QUITQ : YRMCDS_CMD_QUIT, |
563 | 0 | 0, serial, 0, NULL, 0, NULL, 0, NULL); |
564 | 0 | } |