b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#pragma once
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering/***
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering This file is part of systemd.
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering Copyright 2010 Lennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering systemd is free software; you can redistribute it and/or modify it
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering under the terms of the GNU Lesser General Public License as published by
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering (at your option) any later version.
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering systemd is distributed in the hope that it will be useful, but
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering Lesser General Public License for more details.
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering You should have received a copy of the GNU Lesser General Public License
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering***/
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include <alloca.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <stddef.h>
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include <stdlib.h>
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include <string.h>
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "macro.h"
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#define new(t, n) ((t*) malloc_multiply(sizeof(t), (n)))
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#define new0(t, n) ((t*) calloc((n), sizeof(t)))
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#define newa(t, n) ((t*) alloca(sizeof(t)*(n)))
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#define newa0(t, n) ((t*) alloca0(sizeof(t)*(n)))
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#define malloc0(n) (calloc(1, (n)))
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poetteringstatic inline void *mfree(void *memory) {
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering free(memory);
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering return NULL;
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering}
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poetteringvoid* memdup(const void *p, size_t l) _alloc_(2);
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poetteringstatic inline void freep(void *p) {
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering free(*(void**) p);
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering}
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#define _cleanup_free_ _cleanup_(freep)
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t a, size_t b) {
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering return NULL;
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering return malloc(a * b);
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering}
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t a, size_t b) {
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering return NULL;
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering return realloc(p, a * b);
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering}
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t a, size_t b) {
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering return NULL;
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering return memdup(p, a * b);
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering}
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poetteringvoid* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size);
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poetteringvoid* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#define GREEDY_REALLOC(array, allocated, need) \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0]))
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#define GREEDY_REALLOC0(array, allocated, need) \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0]))
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#define alloca0(n) \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering ({ \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering char *_new_; \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering size_t _len_ = n; \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering _new_ = alloca(_len_); \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering (void *) memset(_new_, 0, _len_); \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering })
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering/* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#define alloca_align(size, align) \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering ({ \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering void *_ptr_; \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering size_t _mask_ = (align) - 1; \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering _ptr_ = alloca((size) + _mask_); \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering })
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#define alloca0_align(size, align) \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering ({ \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering void *_new_; \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering size_t _size_ = (size); \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering _new_ = alloca_align(_size_, (align)); \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering (void*)memset(_new_, 0, _size_); \
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering })