| // SPDX-License-Identifier: GPL-2.0 | |
| /* | |
| * linux/lib/kasprintf.c | |
| * | |
| * Copyright (C) 1991, 1992 Linus Torvalds | |
| */ | |
| #include <stdarg.h> | |
| #include <linux/export.h> | |
| #include <linux/slab.h> | |
| #include <linux/types.h> | |
| #include <linux/string.h> | |
| /* Simplified asprintf. */ | |
| char *kvasprintf(gfp_t gfp, const char *fmt, va_list ap) | |
| { | |
| unsigned int first, second; | |
| char *p; | |
| va_list aq; | |
| va_copy(aq, ap); | |
| first = vsnprintf(NULL, 0, fmt, aq); | |
| va_end(aq); | |
| p = kmalloc_track_caller(first+1, gfp); | |
| if (!p) | |
| return NULL; | |
| second = vsnprintf(p, first+1, fmt, ap); | |
| WARN(first != second, "different return values (%u and %u) from vsnprintf(\"%s\", ...)", | |
| first, second, fmt); | |
| return p; | |
| } | |
| EXPORT_SYMBOL(kvasprintf); | |
| /* | |
| * If fmt contains no % (or is exactly %s), use kstrdup_const. If fmt | |
| * (or the sole vararg) points to rodata, we will then save a memory | |
| * allocation and string copy. In any case, the return value should be | |
| * freed using kfree_const(). | |
| */ | |
| const char *kvasprintf_const(gfp_t gfp, const char *fmt, va_list ap) | |
| { | |
| if (!strchr(fmt, '%')) | |
| return kstrdup_const(fmt, gfp); | |
| if (!strcmp(fmt, "%s")) | |
| return kstrdup_const(va_arg(ap, const char*), gfp); | |
| return kvasprintf(gfp, fmt, ap); | |
| } | |
| EXPORT_SYMBOL(kvasprintf_const); | |
| char *kasprintf(gfp_t gfp, const char *fmt, ...) | |
| { | |
| va_list ap; | |
| char *p; | |
| va_start(ap, fmt); | |
| p = kvasprintf(gfp, fmt, ap); | |
| va_end(ap); | |
| return p; | |
| } | |
| EXPORT_SYMBOL(kasprintf); |