]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/alloc-util.h
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / basic / alloc-util.h
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
b5efdb8a
LP
2#pragma once
3
4/***
5 This file is part of systemd.
6
7 Copyright 2010 Lennart Poettering
8
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
13
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21***/
22
23#include <alloca.h>
11c3a366 24#include <stddef.h>
b5efdb8a
LP
25#include <stdlib.h>
26#include <string.h>
27
28#include "macro.h"
29
30#define new(t, n) ((t*) malloc_multiply(sizeof(t), (n)))
31
32#define new0(t, n) ((t*) calloc((n), sizeof(t)))
33
34#define newa(t, n) ((t*) alloca(sizeof(t)*(n)))
35
36#define newa0(t, n) ((t*) alloca0(sizeof(t)*(n)))
37
38#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
39
c165d97d
LP
40#define newdup_suffix0(t, p, n) ((t*) memdup_suffix0_multiply(p, sizeof(t), (n)))
41
b5efdb8a
LP
42#define malloc0(n) (calloc(1, (n)))
43
44static inline void *mfree(void *memory) {
45 free(memory);
46 return NULL;
47}
48
3b319885
ZJS
49#define free_and_replace(a, b) \
50 ({ \
51 free(a); \
52 (a) = (b); \
53 (b) = NULL; \
54 0; \
55 })
56
b5efdb8a 57void* memdup(const void *p, size_t l) _alloc_(2);
c165d97d 58void* memdup_suffix0(const void*p, size_t l) _alloc_(2);
b5efdb8a
LP
59
60static inline void freep(void *p) {
61 free(*(void**) p);
62}
63
64#define _cleanup_free_ _cleanup_(freep)
65
dbacacaa
AK
66static inline bool size_multiply_overflow(size_t size, size_t need) {
67 return _unlikely_(need != 0 && size > (SIZE_MAX / need));
68}
69
70_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t need) {
71 if (size_multiply_overflow(size, need))
b5efdb8a
LP
72 return NULL;
73
dbacacaa 74 return malloc(size * need);
b5efdb8a
LP
75}
76
dbacacaa
AK
77_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t size, size_t need) {
78 if (size_multiply_overflow(size, need))
b5efdb8a
LP
79 return NULL;
80
dbacacaa 81 return realloc(p, size * need);
b5efdb8a
LP
82}
83
dbacacaa
AK
84_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) {
85 if (size_multiply_overflow(size, need))
b5efdb8a
LP
86 return NULL;
87
dbacacaa 88 return memdup(p, size * need);
b5efdb8a
LP
89}
90
c165d97d
LP
91_alloc_(2, 3) static inline void *memdup_suffix0_multiply(const void *p, size_t size, size_t need) {
92 if (size_multiply_overflow(size, need))
93 return NULL;
94
95 return memdup_suffix0(p, size * need);
96}
97
b5efdb8a
LP
98void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size);
99void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
100
101#define GREEDY_REALLOC(array, allocated, need) \
102 greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0]))
103
104#define GREEDY_REALLOC0(array, allocated, need) \
105 greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0]))
106
107#define alloca0(n) \
108 ({ \
109 char *_new_; \
110 size_t _len_ = n; \
111 _new_ = alloca(_len_); \
112 (void *) memset(_new_, 0, _len_); \
113 })
114
115/* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */
116#define alloca_align(size, align) \
117 ({ \
118 void *_ptr_; \
119 size_t _mask_ = (align) - 1; \
120 _ptr_ = alloca((size) + _mask_); \
121 (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \
122 })
123
124#define alloca0_align(size, align) \
125 ({ \
126 void *_new_; \
127 size_t _size_ = (size); \
128 _new_ = alloca_align(_size_, (align)); \
129 (void*)memset(_new_, 0, _size_); \
130 })