mirror of
https://github.com/chatmail/core.git
synced 2026-04-06 07:32:12 +03:00
398 lines
11 KiB
Rust
398 lines
11 KiB
Rust
use std::sync::Mutex;
|
|
|
|
use lazy_static::lazy_static;
|
|
use libc;
|
|
|
|
use crate::chash::*;
|
|
use crate::other::*;
|
|
|
|
lazy_static! {
|
|
static ref mmapstring_lock: Mutex<()> = Mutex::new(());
|
|
}
|
|
|
|
#[derive(Copy, Clone)]
|
|
#[repr(C)]
|
|
pub struct MMAPString {
|
|
pub str_0: *mut libc::c_char,
|
|
pub len: size_t,
|
|
pub allocated_len: size_t,
|
|
pub fd: libc::c_int,
|
|
pub mmapped_size: size_t,
|
|
}
|
|
|
|
pub const TMPDIR: &'static str = "/tmp";
|
|
|
|
pub unsafe fn mmap_string_new(mut init: *const libc::c_char) -> *mut MMAPString {
|
|
let mut string: *mut MMAPString = 0 as *mut MMAPString;
|
|
string = mmap_string_sized_new(if !init.is_null() {
|
|
strlen(init).wrapping_add(2i32 as libc::size_t)
|
|
} else {
|
|
2i32 as libc::size_t
|
|
});
|
|
if string.is_null() {
|
|
return 0 as *mut MMAPString;
|
|
}
|
|
if !init.is_null() {
|
|
mmap_string_append(string, init);
|
|
}
|
|
return string;
|
|
}
|
|
|
|
pub unsafe fn mmap_string_append(
|
|
mut string: *mut MMAPString,
|
|
mut val: *const libc::c_char,
|
|
) -> *mut MMAPString {
|
|
return mmap_string_insert_len(string, (*string).len, val, strlen(val));
|
|
}
|
|
|
|
pub unsafe fn mmap_string_insert_len(
|
|
mut string: *mut MMAPString,
|
|
mut pos: size_t,
|
|
mut val: *const libc::c_char,
|
|
mut len: size_t,
|
|
) -> *mut MMAPString {
|
|
if mmap_string_maybe_expand(string, len).is_null() {
|
|
return 0 as *mut MMAPString;
|
|
}
|
|
if pos < (*string).len {
|
|
memmove(
|
|
(*string).str_0.offset(pos as isize).offset(len as isize) as *mut libc::c_void,
|
|
(*string).str_0.offset(pos as isize) as *const libc::c_void,
|
|
(*string).len.wrapping_sub(pos),
|
|
);
|
|
}
|
|
memmove(
|
|
(*string).str_0.offset(pos as isize) as *mut libc::c_void,
|
|
val as *const libc::c_void,
|
|
len,
|
|
);
|
|
(*string).len = ((*string).len as libc::size_t).wrapping_add(len) as size_t as size_t;
|
|
*(*string).str_0.offset((*string).len as isize) = 0i32 as libc::c_char;
|
|
return string;
|
|
}
|
|
unsafe fn mmap_string_maybe_expand(
|
|
mut string: *mut MMAPString,
|
|
mut len: size_t,
|
|
) -> *mut MMAPString {
|
|
if (*string).len.wrapping_add(len) >= (*string).allocated_len {
|
|
let mut old_size: size_t = 0;
|
|
let mut newstring: *mut MMAPString = 0 as *mut MMAPString;
|
|
old_size = (*string).allocated_len;
|
|
(*string).allocated_len = nearest_power(
|
|
1i32 as size_t,
|
|
(*string)
|
|
.len
|
|
.wrapping_add(len)
|
|
.wrapping_add(1i32 as libc::size_t),
|
|
);
|
|
newstring = mmap_string_realloc_memory(string);
|
|
if newstring.is_null() {
|
|
(*string).allocated_len = old_size
|
|
}
|
|
return newstring;
|
|
}
|
|
return string;
|
|
}
|
|
/* Strings.
|
|
*/
|
|
/* SEB */
|
|
unsafe fn mmap_string_realloc_memory(mut string: *mut MMAPString) -> *mut MMAPString {
|
|
let mut tmp: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
tmp = realloc(
|
|
(*string).str_0 as *mut libc::c_void,
|
|
(*string).allocated_len,
|
|
) as *mut libc::c_char;
|
|
if tmp.is_null() {
|
|
string = 0 as *mut MMAPString
|
|
} else {
|
|
(*string).str_0 = tmp
|
|
}
|
|
return string;
|
|
}
|
|
/* MMAPString */
|
|
#[inline]
|
|
unsafe fn nearest_power(mut base: size_t, mut num: size_t) -> size_t {
|
|
if num > (-1i32 as size_t).wrapping_div(2i32 as libc::size_t) {
|
|
return -1i32 as size_t;
|
|
} else {
|
|
let mut n: size_t = base;
|
|
while n < num {
|
|
n <<= 1i32
|
|
}
|
|
return n;
|
|
};
|
|
}
|
|
|
|
pub unsafe fn mmap_string_sized_new(mut dfl_size: size_t) -> *mut MMAPString {
|
|
let mut string: *mut MMAPString = 0 as *mut MMAPString;
|
|
string = malloc(::std::mem::size_of::<MMAPString>() as libc::size_t) as *mut MMAPString;
|
|
if string.is_null() {
|
|
return 0 as *mut MMAPString;
|
|
}
|
|
(*string).allocated_len = 0i32 as size_t;
|
|
(*string).len = 0i32 as size_t;
|
|
(*string).str_0 = 0 as *mut libc::c_char;
|
|
(*string).fd = -1i32;
|
|
(*string).mmapped_size = 0i32 as size_t;
|
|
if mmap_string_maybe_expand(
|
|
string,
|
|
if dfl_size > 2i32 as libc::size_t {
|
|
dfl_size
|
|
} else {
|
|
2i32 as libc::size_t
|
|
},
|
|
)
|
|
.is_null()
|
|
{
|
|
free(string as *mut libc::c_void);
|
|
return 0 as *mut MMAPString;
|
|
}
|
|
*(*string).str_0.offset(0isize) = 0i32 as libc::c_char;
|
|
return string;
|
|
}
|
|
|
|
pub unsafe fn mmap_string_new_len(
|
|
mut init: *const libc::c_char,
|
|
mut len: size_t,
|
|
) -> *mut MMAPString {
|
|
let mut string: *mut MMAPString = 0 as *mut MMAPString;
|
|
if len <= 0i32 as libc::size_t {
|
|
return mmap_string_new(b"\x00" as *const u8 as *const libc::c_char);
|
|
} else {
|
|
string = mmap_string_sized_new(len);
|
|
if string.is_null() {
|
|
return string;
|
|
}
|
|
if !init.is_null() {
|
|
mmap_string_append_len(string, init, len);
|
|
}
|
|
return string;
|
|
};
|
|
}
|
|
|
|
pub unsafe fn mmap_string_append_len(
|
|
mut string: *mut MMAPString,
|
|
mut val: *const libc::c_char,
|
|
mut len: size_t,
|
|
) -> *mut MMAPString {
|
|
return mmap_string_insert_len(string, (*string).len, val, len);
|
|
}
|
|
|
|
pub unsafe fn mmap_string_free(mut string: *mut MMAPString) {
|
|
if string.is_null() {
|
|
return;
|
|
}
|
|
free((*string).str_0 as *mut libc::c_void);
|
|
free(string as *mut libc::c_void);
|
|
}
|
|
|
|
pub unsafe fn mmap_string_assign(
|
|
mut string: *mut MMAPString,
|
|
mut rval: *const libc::c_char,
|
|
) -> *mut MMAPString {
|
|
mmap_string_truncate(string, 0i32 as size_t);
|
|
if mmap_string_append(string, rval).is_null() {
|
|
return 0 as *mut MMAPString;
|
|
}
|
|
return string;
|
|
}
|
|
|
|
pub unsafe fn mmap_string_truncate(
|
|
mut string: *mut MMAPString,
|
|
mut len: size_t,
|
|
) -> *mut MMAPString {
|
|
(*string).len = if len < (*string).len {
|
|
len
|
|
} else {
|
|
(*string).len
|
|
};
|
|
*(*string).str_0.offset((*string).len as isize) = 0i32 as libc::c_char;
|
|
return string;
|
|
}
|
|
|
|
pub unsafe fn mmap_string_set_size(
|
|
mut string: *mut MMAPString,
|
|
mut len: size_t,
|
|
) -> *mut MMAPString {
|
|
if len >= (*string).allocated_len {
|
|
if mmap_string_maybe_expand(string, len.wrapping_sub((*string).len)).is_null() {
|
|
return 0 as *mut MMAPString;
|
|
}
|
|
}
|
|
(*string).len = len;
|
|
*(*string).str_0.offset(len as isize) = 0i32 as libc::c_char;
|
|
return string;
|
|
}
|
|
|
|
pub unsafe fn mmap_string_append_c(
|
|
mut string: *mut MMAPString,
|
|
mut c: libc::c_char,
|
|
) -> *mut MMAPString {
|
|
return mmap_string_insert_c(string, (*string).len, c);
|
|
}
|
|
|
|
pub unsafe fn mmap_string_insert_c(
|
|
mut string: *mut MMAPString,
|
|
mut pos: size_t,
|
|
mut c: libc::c_char,
|
|
) -> *mut MMAPString {
|
|
if mmap_string_maybe_expand(string, 1i32 as size_t).is_null() {
|
|
return 0 as *mut MMAPString;
|
|
}
|
|
if pos < (*string).len {
|
|
memmove(
|
|
(*string).str_0.offset(pos as isize).offset(1isize) as *mut libc::c_void,
|
|
(*string).str_0.offset(pos as isize) as *const libc::c_void,
|
|
(*string).len.wrapping_sub(pos),
|
|
);
|
|
}
|
|
*(*string).str_0.offset(pos as isize) = c;
|
|
(*string).len =
|
|
((*string).len as libc::size_t).wrapping_add(1i32 as libc::size_t) as size_t as size_t;
|
|
*(*string).str_0.offset((*string).len as isize) = 0i32 as libc::c_char;
|
|
return string;
|
|
}
|
|
|
|
pub unsafe fn mmap_string_prepend(
|
|
mut string: *mut MMAPString,
|
|
mut val: *const libc::c_char,
|
|
) -> *mut MMAPString {
|
|
return mmap_string_insert_len(string, 0i32 as size_t, val, strlen(val));
|
|
}
|
|
|
|
pub unsafe fn mmap_string_prepend_c(
|
|
mut string: *mut MMAPString,
|
|
mut c: libc::c_char,
|
|
) -> *mut MMAPString {
|
|
return mmap_string_insert_c(string, 0i32 as size_t, c);
|
|
}
|
|
|
|
pub unsafe fn mmap_string_prepend_len(
|
|
mut string: *mut MMAPString,
|
|
mut val: *const libc::c_char,
|
|
mut len: size_t,
|
|
) -> *mut MMAPString {
|
|
return mmap_string_insert_len(string, 0i32 as size_t, val, len);
|
|
}
|
|
|
|
pub unsafe fn mmap_string_insert(
|
|
mut string: *mut MMAPString,
|
|
mut pos: size_t,
|
|
mut val: *const libc::c_char,
|
|
) -> *mut MMAPString {
|
|
return mmap_string_insert_len(string, pos, val, strlen(val));
|
|
}
|
|
|
|
pub unsafe fn mmap_string_erase(
|
|
mut string: *mut MMAPString,
|
|
mut pos: size_t,
|
|
mut len: size_t,
|
|
) -> *mut MMAPString {
|
|
if pos.wrapping_add(len) < (*string).len {
|
|
memmove(
|
|
(*string).str_0.offset(pos as isize) as *mut libc::c_void,
|
|
(*string).str_0.offset(pos as isize).offset(len as isize) as *const libc::c_void,
|
|
(*string).len.wrapping_sub(pos.wrapping_add(len)),
|
|
);
|
|
}
|
|
(*string).len = ((*string).len as libc::size_t).wrapping_sub(len) as size_t as size_t;
|
|
*(*string).str_0.offset((*string).len as isize) = 0i32 as libc::c_char;
|
|
return string;
|
|
}
|
|
|
|
pub unsafe fn mmap_string_set_ceil(mut ceil: size_t) {
|
|
mmap_string_ceil = ceil;
|
|
}
|
|
static mut mmap_string_ceil: size_t = (8i32 * 1024i32 * 1024i32) as size_t;
|
|
|
|
pub unsafe fn mmap_string_ref(mut string: *mut MMAPString) -> libc::c_int {
|
|
let mut ht: *mut chash = 0 as *mut chash;
|
|
let mut r: libc::c_int = 0;
|
|
let mut key: chashdatum = chashdatum {
|
|
data: 0 as *mut libc::c_void,
|
|
len: 0,
|
|
};
|
|
let mut data: chashdatum = chashdatum {
|
|
data: 0 as *mut libc::c_void,
|
|
len: 0,
|
|
};
|
|
mmapstring_lock.lock().unwrap();
|
|
if mmapstring_hashtable.is_null() {
|
|
mmapstring_hashtable_init();
|
|
}
|
|
ht = mmapstring_hashtable;
|
|
if ht.is_null() {
|
|
return -1i32;
|
|
}
|
|
key.data = &mut (*string).str_0 as *mut *mut libc::c_char as *mut libc::c_void;
|
|
key.len = ::std::mem::size_of::<*mut libc::c_char>() as libc::size_t as libc::c_uint;
|
|
data.data = string as *mut libc::c_void;
|
|
data.len = 0i32 as libc::c_uint;
|
|
r = chash_set(
|
|
mmapstring_hashtable,
|
|
&mut key,
|
|
&mut data,
|
|
0 as *mut chashdatum,
|
|
);
|
|
|
|
if r < 0i32 {
|
|
return r;
|
|
}
|
|
return 0i32;
|
|
}
|
|
|
|
static mut mmapstring_hashtable: *mut chash = 0 as *const chash as *mut chash;
|
|
unsafe fn mmapstring_hashtable_init() {
|
|
mmapstring_hashtable = chash_new(13i32 as libc::c_uint, 1i32);
|
|
}
|
|
|
|
pub unsafe fn mmap_string_unref(mut str: *mut libc::c_char) -> libc::c_int {
|
|
let mut string: *mut MMAPString = 0 as *mut MMAPString;
|
|
let mut ht: *mut chash = 0 as *mut chash;
|
|
let mut key: chashdatum = chashdatum {
|
|
data: 0 as *mut libc::c_void,
|
|
len: 0,
|
|
};
|
|
let mut data: chashdatum = chashdatum {
|
|
data: 0 as *mut libc::c_void,
|
|
len: 0,
|
|
};
|
|
let mut r: libc::c_int = 0;
|
|
if str.is_null() {
|
|
return -1i32;
|
|
}
|
|
mmapstring_lock.lock().unwrap();
|
|
ht = mmapstring_hashtable;
|
|
if ht.is_null() {
|
|
return -1i32;
|
|
}
|
|
key.data = &mut str as *mut *mut libc::c_char as *mut libc::c_void;
|
|
key.len = ::std::mem::size_of::<*mut libc::c_char>() as libc::size_t as libc::c_uint;
|
|
r = chash_get(ht, &mut key, &mut data);
|
|
if r < 0i32 {
|
|
string = 0 as *mut MMAPString
|
|
} else {
|
|
string = data.data as *mut MMAPString
|
|
}
|
|
if !string.is_null() {
|
|
chash_delete(ht, &mut key, 0 as *mut chashdatum);
|
|
if chash_count(ht) == 0i32 as libc::c_uint {
|
|
chash_free(ht);
|
|
mmapstring_hashtable = 0 as *mut chash
|
|
}
|
|
}
|
|
if !string.is_null() {
|
|
mmap_string_free(string);
|
|
return 0i32;
|
|
} else {
|
|
return -1i32;
|
|
};
|
|
}
|
|
#[inline]
|
|
unsafe fn chash_count(mut hash: *mut chash) -> libc::c_uint {
|
|
return (*hash).count;
|
|
}
|
|
|
|
pub unsafe fn mmapstring_init_lock() {}
|
|
pub unsafe fn mmapstring_uninit_lock() {}
|