^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include "cache.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include "strbuf.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/zalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Used as the default ->buf value, so that people can always assume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * buf is non NULL and ->buf is NUL terminated even for a freshly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * initialized strbuf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) char strbuf_slopbuf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) int strbuf_init(struct strbuf *sb, ssize_t hint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) sb->alloc = sb->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) sb->buf = strbuf_slopbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) if (hint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return strbuf_grow(sb, hint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) void strbuf_release(struct strbuf *sb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (sb->alloc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) zfree(&sb->buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) strbuf_init(sb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) char *strbuf_detach(struct strbuf *sb, size_t *sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) char *res = sb->alloc ? sb->buf : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) *sz = sb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) strbuf_init(sb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int strbuf_grow(struct strbuf *sb, size_t extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) size_t nr = sb->len + extra + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (nr < sb->alloc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (nr <= sb->len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (alloc_nr(sb->alloc) > nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) nr = alloc_nr(sb->alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * Note that sb->buf == strbuf_slopbuf if sb->alloc == 0, and it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * a static variable. Thus we have to avoid passing it to realloc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) buf = realloc(sb->alloc ? sb->buf : NULL, nr * sizeof(*buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) sb->buf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) sb->alloc = nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) int strbuf_addch(struct strbuf *sb, int c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int ret = strbuf_grow(sb, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) sb->buf[sb->len++] = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) sb->buf[sb->len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int strbuf_add(struct strbuf *sb, const void *data, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) int ret = strbuf_grow(sb, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) memcpy(sb->buf + sb->len, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return strbuf_setlen(sb, sb->len + len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static int strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int len, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) va_list ap_saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (!strbuf_avail(sb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) ret = strbuf_grow(sb, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) va_copy(ap_saved, ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (len < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) va_end(ap_saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (len > strbuf_avail(sb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) ret = strbuf_grow(sb, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) va_end(ap_saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (len > strbuf_avail(sb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) pr_debug("this should not happen, your vsnprintf is broken");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) va_end(ap_saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) va_end(ap_saved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return strbuf_setlen(sb, sb->len + len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) int strbuf_addf(struct strbuf *sb, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) va_list ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) va_start(ap, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ret = strbuf_addv(sb, fmt, ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) va_end(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) size_t oldlen = sb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) size_t oldalloc = sb->alloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) ret = strbuf_grow(sb, hint ? hint : 8192);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ssize_t cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) cnt = read(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (cnt < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (oldalloc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) strbuf_release(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) strbuf_setlen(sb, oldlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (!cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) sb->len += cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ret = strbuf_grow(sb, 8192);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) sb->buf[sb->len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return sb->len - oldlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }