/[path-sandbox]/trunk/libsbutil/src/dynbuf.c
Gentoo

Contents of /trunk/libsbutil/src/dynbuf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 370 - (show annotations) (download) (as text)
Sun Nov 9 10:29:58 2008 UTC (5 years, 10 months ago) by vapier
File MIME type: text/x-csrc
File size: 8843 byte(s)
consolidate all random system includes into headers.h
1 /*
2 * dynbuf.c
3 *
4 * Dynamic allocated buffers.
5 *
6 * Copyright 1999-2008 Gentoo Foundation
7 * Copyright 2004-2007 Martin Schlemmer <azarah@nosferatu.za.org>
8 * Licensed under the GPL-2
9 */
10
11 #include "headers.h"
12 #include "rcscripts/rcutil.h"
13
14 #define DYNAMIC_BUFFER_SIZE (sizeof (char) * 2 * 1024)
15
16 static rc_dynbuf_t *rc_dynbuf_reallocate (rc_dynbuf_t *dynbuf, size_t needed);
17
18 rc_dynbuf_t *
19 rc_dynbuf_new (void)
20 {
21 rc_dynbuf_t *dynbuf = NULL;
22
23 dynbuf = xmalloc (sizeof (rc_dynbuf_t));
24 if (NULL == dynbuf)
25 return NULL;
26
27 dynbuf->data = xmalloc (DYNAMIC_BUFFER_SIZE);
28 if (NULL == dynbuf->data)
29 {
30 free (dynbuf);
31 return NULL;
32 }
33
34 dynbuf->length = DYNAMIC_BUFFER_SIZE;
35 dynbuf->rd_index = 0;
36 dynbuf->wr_index = 0;
37 dynbuf->file_map = FALSE;
38
39 return dynbuf;
40 }
41
42 rc_dynbuf_t *
43 rc_dynbuf_new_mmap_file (const char *name)
44 {
45 rc_dynbuf_t *dynbuf = NULL;
46
47 dynbuf = xmalloc (sizeof (rc_dynbuf_t));
48 if (NULL == dynbuf)
49 return NULL;
50
51 if (-1 == rc_file_map (name, &dynbuf->data, &dynbuf->length))
52 {
53 DBG_MSG ("Failed to mmap file '%s'\n", name);
54 free (dynbuf);
55
56 return NULL;
57 }
58
59 dynbuf->wr_index = dynbuf->length;
60 dynbuf->rd_index = 0;
61 dynbuf->file_map = TRUE;
62
63 return dynbuf;
64 }
65
66 rc_dynbuf_t *
67 rc_dynbuf_reallocate (rc_dynbuf_t *dynbuf, size_t needed)
68 {
69 int len;
70
71 if (!rc_check_arg_dynbuf (dynbuf))
72 return NULL;
73
74 if (dynbuf->file_map)
75 {
76 rc_errno_set (EPERM);
77 DBG_MSG ("Cannot reallocate mmap()'d file!\n");
78
79 return NULL;
80 }
81
82 len = sizeof (char) * (dynbuf->wr_index + needed + 1);
83
84 if (dynbuf->length < len)
85 {
86 char *new_ptr;
87
88 /* Increase size in chunks to minimize reallocations */
89 if (len < (dynbuf->length + DYNAMIC_BUFFER_SIZE))
90 len = dynbuf->length + DYNAMIC_BUFFER_SIZE;
91
92 new_ptr = xrealloc (dynbuf->data, len);
93 if (NULL == new_ptr)
94 return NULL;
95
96 dynbuf->data = new_ptr;
97 dynbuf->length = len;
98 }
99
100 return dynbuf;
101 }
102
103 void
104 rc_dynbuf_free (rc_dynbuf_t *dynbuf)
105 {
106 if (NULL == dynbuf)
107 return;
108
109 if (!dynbuf->file_map)
110 {
111 if (NULL != dynbuf->data)
112 {
113 free (dynbuf->data);
114 dynbuf->data = NULL;
115 }
116 }
117 else
118 {
119 rc_file_unmap (dynbuf->data, dynbuf->length);
120 }
121
122 dynbuf->length = 0;
123 dynbuf->rd_index = 0;
124 dynbuf->wr_index = 0;
125
126 free (dynbuf);
127 dynbuf = NULL;
128 }
129
130 int
131 rc_dynbuf_write (rc_dynbuf_t *dynbuf, const char *buf, size_t length)
132 {
133 int len;
134
135 if (!rc_check_arg_dynbuf (dynbuf))
136 return -1;
137
138 if (!check_arg_str (buf))
139 return -1;
140
141 if (dynbuf->file_map)
142 {
143 rc_errno_set (EPERM);
144 DBG_MSG ("Cannot write to readonly mmap()'d file!\n");
145
146 return -1;
147 }
148
149 if (NULL == rc_dynbuf_reallocate (dynbuf, length))
150 {
151 DBG_MSG ("Could not reallocate dynamic buffer!\n");
152 return -1;
153 }
154
155 len = snprintf ((dynbuf->data + dynbuf->wr_index), length + 1, "%s", buf);
156
157 /* If len is less than length, it means the string was shorter than
158 * given length */
159 if (length > len)
160 length = len;
161
162 if (0 < length)
163 dynbuf->wr_index += length;
164
165 if (-1 == length)
166 {
167 rc_errno_set (errno);
168 DBG_MSG ("Failed to write to dynamic buffer!\n");
169 }
170
171 return length;
172 }
173
174 int rc_dynbuf_write_fd (rc_dynbuf_t *dynbuf, int fd, size_t length)
175 {
176 size_t len;
177 size_t total = 0;
178
179 if (!rc_check_arg_dynbuf (dynbuf))
180 return -1;
181
182 if (!check_arg_fd (fd))
183 return -1;
184
185 if (dynbuf->file_map)
186 {
187 rc_errno_set (EPERM);
188 DBG_MSG ("Cannot write to readonly mmap()'d file!\n");
189
190 return -1;
191 }
192
193 if (NULL == rc_dynbuf_reallocate (dynbuf, length))
194 {
195 DBG_MSG ("Could not reallocate dynamic buffer!\n");
196 return -1;
197 }
198
199 do
200 {
201 len = read (fd, (dynbuf->data + dynbuf->wr_index + total),
202 (length - total));
203 if (-1 == len)
204 {
205 if (EINTR == errno)
206 {
207 /* We were interrupted, continue reading */
208 errno = 0;
209 /* Make sure we retry */
210 len = 1;
211 }
212 else
213 {
214 rc_errno_set (errno);
215 break;
216 }
217 }
218 else
219 {
220 total += len;
221 }
222 }
223 while ((0 < len) && (total < len));
224
225 if (0 < total)
226 dynbuf->wr_index += total;
227
228 dynbuf->data[dynbuf->wr_index] = '\0';
229
230 if (-1 == len)
231 /* XXX: We set errno in above while loop. */
232 DBG_MSG ("Failed to write to dynamic buffer!\n");
233
234 return (-1 == len) ? len : total;
235 }
236
237 int
238 rc_dynbuf_sprintf (rc_dynbuf_t *dynbuf, const char *format, ...)
239 {
240 va_list arg1, arg2;
241 char test_str[10];
242 int needed, written = 0;
243
244 if (!rc_check_arg_dynbuf (dynbuf))
245 return -1;
246
247 if (!check_arg_str (format))
248 return -1;
249
250 if (dynbuf->file_map)
251 {
252 rc_errno_set (EPERM);
253 DBG_MSG ("Cannot write to readonly mmap()'d file!\n");
254
255 return -1;
256 }
257
258 va_start (arg1, format);
259 va_copy (arg2, arg1);
260
261 /* XXX: Lame way to try and figure out how much space we need */
262 needed = vsnprintf (test_str, sizeof (test_str), format, arg2);
263 va_end (arg2);
264
265 if (NULL == rc_dynbuf_reallocate (dynbuf, needed))
266 {
267 DBG_MSG ("Could not reallocate dynamic buffer!\n");
268 return -1;
269 }
270
271 written = vsnprintf ((dynbuf->data + dynbuf->wr_index), needed + 1,
272 format, arg1);
273 va_end (arg1);
274
275 if (0 < written)
276 dynbuf->wr_index += written;
277
278 if (-1 == written)
279 {
280 rc_errno_set (errno);
281 DBG_MSG ("Failed to write to dynamic buffer!\n");
282 }
283
284 return written;
285 }
286
287 int
288 rc_dynbuf_read (rc_dynbuf_t *dynbuf, char *buf, size_t length)
289 {
290 int len = length;
291
292 if (!rc_check_arg_dynbuf (dynbuf))
293 return -1;
294
295 if (!check_arg_ptr (buf))
296 return -1;
297
298 if (dynbuf->rd_index >= dynbuf->length)
299 return 0;
300
301 if (dynbuf->wr_index < (dynbuf->rd_index + length))
302 len = dynbuf->wr_index - dynbuf->rd_index;
303
304 len = snprintf (buf, len + 1, "%s", (dynbuf->data + dynbuf->rd_index));
305
306 /* If len is less than length, it means the string was shorter than
307 * given length */
308 if (length > len)
309 length = len;
310
311 if (0 < length)
312 dynbuf->rd_index += length;
313
314 if (-1 == length)
315 {
316 rc_errno_set (errno);
317 DBG_MSG ("Failed to write from dynamic buffer!\n");
318 }
319
320 return length;
321 }
322
323 int
324 rc_dynbuf_read_fd (rc_dynbuf_t *dynbuf, int fd, size_t length)
325 {
326 size_t len;
327 size_t total = 0;
328 size_t max_read = length;
329
330 if (!rc_check_arg_dynbuf (dynbuf))
331 return -1;
332
333 if (!check_arg_fd (fd))
334 return -1;
335
336 if (dynbuf->rd_index >= dynbuf->length)
337 return 0;
338
339 if (dynbuf->wr_index < (dynbuf->rd_index + length))
340 max_read = dynbuf->wr_index - dynbuf->rd_index;
341
342 do
343 {
344 len = write (fd, (dynbuf->data + dynbuf->rd_index + total),
345 (max_read - total));
346 if (-1 == len)
347 {
348 if (EINTR == errno)
349 {
350 /* We were interrupted, continue reading */
351 errno = 0;
352 /* Make sure we retry */
353 len = 1;
354 }
355 else
356 {
357 rc_errno_set (errno);
358 break;
359 }
360 }
361 else
362 {
363 total += len;
364 }
365 }
366 while ((0 < len) && (total < len));
367
368 if (0 < total)
369 dynbuf->rd_index += total;
370
371 if (-1 == len)
372 /* XXX: We set errno in above while loop. */
373 DBG_MSG ("Failed to write from dynamic buffer!\n");
374
375 return (-1 == len) ? len : total;
376 }
377
378 char *
379 rc_dynbuf_read_line (rc_dynbuf_t *dynbuf)
380 {
381 char *buf = NULL;
382 size_t count = 0;
383
384 if (!rc_check_arg_dynbuf (dynbuf))
385 return NULL;
386
387 if (dynbuf->rd_index == dynbuf->wr_index)
388 return NULL;
389
390 for (count = dynbuf->rd_index; count < dynbuf->wr_index && dynbuf->data[count] != '\n'; count++);
391
392 if (count <= dynbuf->wr_index)
393 {
394 buf = xstrndup ((dynbuf->data + dynbuf->rd_index),
395 (count - dynbuf->rd_index));
396 if (NULL == buf)
397 return NULL;
398
399 dynbuf->rd_index = count;
400
401 /* Also skip the '\n' .. */
402 if (dynbuf->rd_index < dynbuf->wr_index)
403 dynbuf->rd_index++;
404 }
405
406 return buf;
407 }
408
409 int
410 rc_dynbuf_replace_char (rc_dynbuf_t *dynbuf, const char old, const char new)
411 {
412 int i;
413 int count = 0;
414
415 if (!rc_check_arg_dynbuf (dynbuf))
416 return -1;
417
418 if (0 == dynbuf->wr_index)
419 return 0;
420
421 for (i = 0; i < dynbuf->wr_index; i++)
422 {
423 if (old == dynbuf->data[i])
424 {
425 dynbuf->data[i] = new;
426 count++;
427 }
428 }
429
430 return count;
431 }
432
433 bool
434 rc_dynbuf_read_eof (rc_dynbuf_t *dynbuf)
435 {
436 if (!rc_check_arg_dynbuf (dynbuf))
437 return FALSE;
438
439 if (dynbuf->rd_index >= dynbuf->wr_index)
440 return TRUE;
441
442 return FALSE;
443 }
444
445 inline bool
446 rc_check_dynbuf (rc_dynbuf_t *dynbuf)
447 {
448 if ((NULL == dynbuf) || (NULL == dynbuf->data) || (0 == dynbuf->length))
449 return FALSE;
450
451 return TRUE;
452 }
453
454 inline bool
455 __rc_check_arg_dynbuf (rc_dynbuf_t *dynbuf, const char *file, const char *func,
456 size_t line)
457 {
458 if (!rc_check_dynbuf (dynbuf))
459 {
460 rc_errno_set (EINVAL);
461
462 debug_message (file, func, line, "Invalid dynamic buffer passed!\n");
463
464 return FALSE;
465 }
466
467 return TRUE;
468 }

  ViewVC Help
Powered by ViewVC 1.1.20