Remove inclusion of sys/socket.h from nntp-thread.c
[claws.git] / src / plugins / mailmbox / mmapstring.c
blobb4f04ad3ce19114f2f6a133633b68a5945eb9926
1 /*
2 * libEtPan! -- a mail stuff library
4 * Copyright (C) 2001, 2002 - DINH Viet Hoa
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
33 * $Id$
36 #include "config.h"
38 #include "mmapstring.h"
40 #include "chash.h"
42 #include <glib.h>
43 #include <stdlib.h>
44 #include <unistd.h>
45 #include <sys/mman.h>
46 #include <string.h>
47 #include <pthread.h>
48 #include <limits.h>
50 #include "utils.h"
52 #define MMAP_STRING_DEFAULT_CEIL (8 * 1024 * 1024)
54 #define DEFAULT_TMP_PATH "/tmp"
56 static char tmpdir[PATH_MAX] = DEFAULT_TMP_PATH;
58 static size_t mmap_string_ceil = MMAP_STRING_DEFAULT_CEIL;
60 /* MMAPString references */
62 static pthread_mutex_t mmapstring_lock = PTHREAD_MUTEX_INITIALIZER;
63 static chash * mmapstring_hashtable = NULL;
65 static void mmapstring_hashtable_init()
67 mmapstring_hashtable = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
70 void mmap_string_set_tmpdir(char * directory)
72 strncpy(tmpdir, directory, PATH_MAX);
73 tmpdir[PATH_MAX - 1] = 0;
77 int mmap_string_ref(MMAPString * string)
79 chash * ht;
80 int r;
81 chashdatum key;
82 chashdatum data;
84 pthread_mutex_lock(&mmapstring_lock);
85 if (mmapstring_hashtable == NULL) {
86 mmapstring_hashtable_init();
88 ht = mmapstring_hashtable;
90 if (ht == NULL) {
91 pthread_mutex_unlock(&mmapstring_lock);
92 return -1;
95 key.data = &string->str;
96 key.len = sizeof(string->str);
97 data.data = string;
98 data.len = 0;
100 r = chash_set(mmapstring_hashtable, &key, &data, NULL);
101 pthread_mutex_unlock(&mmapstring_lock);
103 if (r < 0)
104 return r;
106 return 0;
109 int mmap_string_unref(char * str)
111 MMAPString * string;
112 chash * ht;
113 chashdatum key;
114 chashdatum data;
115 int r;
117 pthread_mutex_lock(&mmapstring_lock);
118 ht = mmapstring_hashtable;
120 if (ht == NULL) {
121 pthread_mutex_unlock(&mmapstring_lock);
122 return -1;
125 key.data = &str;
126 key.len = sizeof(str);
128 r = chash_get(ht, &key, &data);
129 if (r < 0)
130 string = NULL;
131 else
132 string = data.data;
134 if (string != NULL) {
135 chash_delete(ht, &key, NULL);
136 if (chash_count(ht) == 0) {
137 chash_free(ht);
138 mmapstring_hashtable = NULL;
142 pthread_mutex_unlock(&mmapstring_lock);
144 if (string != NULL) {
145 mmap_string_free(string);
146 return 0;
148 else
149 return -1;
154 /* MMAPString */
156 #define MY_MAXSIZE ((size_t) -1)
158 static inline size_t
159 nearest_power (size_t base, size_t num)
161 if (num > MY_MAXSIZE / 2) {
162 return MY_MAXSIZE;
164 else {
165 size_t n = base;
167 while (n < num)
168 n <<= 1;
170 return n;
174 void mmap_string_set_ceil(size_t ceil)
176 mmap_string_ceil = ceil;
179 /* Strings.
182 static MMAPString * mmap_string_realloc_file(MMAPString * string)
184 char * data;
186 if (string->fd == -1) {
187 char tmpfilename[PATH_MAX];
188 int fd;
190 * tmpfilename = 0;
191 strcat(tmpfilename, tmpdir);
192 strcat(tmpfilename, "/libetpan-mmapstring-XXXXXX");
194 fd = g_mkstemp(tmpfilename);
195 if (fd == -1)
196 return NULL;
198 if (unlink(tmpfilename) == -1) {
199 close(fd);
200 return NULL;
203 if (ftruncate(fd, string->allocated_len) == -1) {
204 close(fd);
205 return NULL;
208 data = mmap(NULL, string->allocated_len, PROT_WRITE | PROT_READ,
209 MAP_SHARED, fd, 0);
211 if (data == MAP_FAILED) {
212 close(fd);
213 return NULL;
216 if (string->str != NULL)
217 memcpy(data, string->str, string->len + 1);
219 string->fd = fd;
220 string->mmapped_size = string->allocated_len;
221 free(string->str);
222 string->str = data;
224 else {
225 if (munmap(string->str, string->mmapped_size) == -1)
226 return NULL;
228 if (ftruncate(string->fd, string->allocated_len) == -1)
229 return NULL;
231 data = mmap(NULL, string->allocated_len, PROT_WRITE | PROT_READ,
232 MAP_SHARED, string->fd, 0);
234 if (data == MAP_FAILED)
235 return NULL;
237 string->mmapped_size = string->allocated_len;
238 string->str = data;
241 return string;
244 static MMAPString * mmap_string_realloc_memory(MMAPString * string)
246 char * tmp;
248 tmp = realloc (string->str, string->allocated_len);
250 if (tmp == NULL)
251 string = NULL;
252 else
253 string->str = tmp;
255 return string;
258 static MMAPString *
259 mmap_string_maybe_expand (MMAPString* string,
260 size_t len)
262 if (string->len + len >= string->allocated_len)
264 size_t old_size;
265 MMAPString * newstring;
267 old_size = string->allocated_len;
269 string->allocated_len = nearest_power (1, string->len + len + 1);
271 #ifndef MMAP_UNAVAILABLE
272 if (string->allocated_len > mmap_string_ceil)
273 newstring = mmap_string_realloc_file(string);
274 else {
275 #endif
276 newstring = mmap_string_realloc_memory(string);
277 #ifndef MMAP_UNAVAILABLE
278 if (newstring == NULL)
279 newstring = mmap_string_realloc_file(string);
281 #endif
283 if (newstring == NULL)
284 string->allocated_len = old_size;
287 return string;
290 MMAPString*
291 mmap_string_sized_new (size_t dfl_size)
293 MMAPString *string;
295 string = malloc(sizeof(* string));
296 if (string == NULL)
297 return NULL;
299 string->allocated_len = 0;
300 string->len = 0;
301 string->str = NULL;
302 string->fd = -1;
303 string->mmapped_size = 0;
305 if (mmap_string_maybe_expand (string, MAX (dfl_size, 2)) == NULL) {
306 free(string);
307 return NULL;
310 if (string->str == NULL) {
311 free(string);
312 return NULL;
315 string->str[0] = '\0';
317 return string;
320 MMAPString*
321 mmap_string_new (const char *init)
323 MMAPString *string;
325 string = mmap_string_sized_new (init ? strlen (init) + 2 : 2);
326 if (string == NULL)
327 return NULL;
329 if (init)
330 mmap_string_append (string, init);
332 return string;
335 MMAPString*
336 mmap_string_new_len (const char *init,
337 size_t len)
339 MMAPString *string;
341 if (len <= 0)
342 return mmap_string_new (init);
343 else
345 string = mmap_string_sized_new (len);
347 if (init)
348 mmap_string_append_len (string, init, len);
350 return string;
354 void
355 mmap_string_free (MMAPString *string)
357 if (string == NULL)
358 return;
360 if (string->fd != -1) {
361 munmap(string->str, string->mmapped_size);
362 close(string->fd);
364 else {
365 free (string->str);
367 free(string);
370 MMAPString*
371 mmap_string_assign (MMAPString *string,
372 const char *rval)
374 mmap_string_truncate (string, 0);
375 if (mmap_string_append (string, rval) == NULL)
376 return NULL;
378 return string;
381 MMAPString*
382 mmap_string_truncate (MMAPString *string,
383 size_t len)
385 string->len = MIN (len, string->len);
386 string->str[string->len] = 0;
388 return string;
392 * mmap_string_set_size:
393 * @string: a #MMAPString
394 * @len: the new length
396 * Sets the length of a #MMAPString. If the length is less than
397 * the current length, the string will be truncated. If the
398 * length is greater than the current length, the contents
399 * of the newly added area are undefined. (However, as
400 * always, string->str[string->len] will be a nul byte.)
402 * Return value: @string
404 MMAPString*
405 mmap_string_set_size (MMAPString *string,
406 size_t len)
408 if (len >= string->allocated_len)
409 if (mmap_string_maybe_expand (string, len - string->len) == NULL)
410 return NULL;
412 string->len = len;
413 string->str[len] = 0;
415 return string;
419 static int in_mapped_zone(MMAPString * string, char * val)
421 return (val >= string->str) && (val < string->str + string->mmapped_size);
425 MMAPString*
426 mmap_string_insert_len (MMAPString *string,
427 size_t pos,
428 const char *val,
429 size_t len)
431 if (mmap_string_maybe_expand (string, len) == NULL)
432 return NULL;
434 if (pos < string->len)
435 memmove (string->str + pos + len, string->str + pos, string->len - pos);
437 /* insert the new string */
438 memmove (string->str + pos, val, len);
440 string->len += len;
442 string->str[string->len] = 0;
444 return string;
447 MMAPString*
448 mmap_string_append (MMAPString *string,
449 const char *val)
451 return mmap_string_insert_len (string, string->len, val, strlen(val));
454 MMAPString*
455 mmap_string_append_len (MMAPString *string,
456 const char *val,
457 size_t len)
459 return mmap_string_insert_len (string, string->len, val, len);
462 MMAPString*
463 mmap_string_append_c (MMAPString *string,
464 char c)
466 return mmap_string_insert_c (string, string->len, c);
469 MMAPString*
470 mmap_string_prepend (MMAPString *string,
471 const char *val)
473 return mmap_string_insert_len (string, 0, val, strlen(val));
476 MMAPString*
477 mmap_string_prepend_len (MMAPString *string,
478 const char *val,
479 size_t len)
481 return mmap_string_insert_len (string, 0, val, len);
484 MMAPString*
485 mmap_string_prepend_c (MMAPString *string,
486 char c)
488 return mmap_string_insert_c (string, 0, c);
491 MMAPString*
492 mmap_string_insert (MMAPString *string,
493 size_t pos,
494 const char *val)
496 return mmap_string_insert_len (string, pos, val, strlen(val));
499 MMAPString*
500 mmap_string_insert_c (MMAPString *string,
501 size_t pos,
502 char c)
504 if (mmap_string_maybe_expand (string, 1) == NULL)
505 return NULL;
507 /* If not just an append, move the old stuff */
508 if (pos < string->len)
509 memmove (string->str + pos + 1, string->str + pos, string->len - pos);
511 string->str[pos] = c;
513 string->len += 1;
515 string->str[string->len] = 0;
517 return string;
520 MMAPString*
521 mmap_string_erase (MMAPString *string,
522 size_t pos,
523 size_t len)
525 if ((pos + len) < string->len)
526 memmove (string->str + pos, string->str + pos + len,
527 string->len - (pos + len));
529 string->len -= len;
531 string->str[string->len] = 0;
533 return string;