| File: | .build-ci/../libnvme/src/nvme/util-fabrics.c |
| Warning: | line 66, column 4 Opened stream never closed. Potential resource leak |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | // SPDX-License-Identifier: LGPL-2.1-or-later | |||
| 2 | /* | |||
| 3 | * This file is part of libnvme. | |||
| 4 | * Copyright (c) 2026, Dell Technologies Inc. or its subsidiaries. | |||
| 5 | * | |||
| 6 | * Authors: Martin Belanger <Martin.Belanger@dell.com> | |||
| 7 | */ | |||
| 8 | ||||
| 9 | #include <limits.h> | |||
| 10 | #include <string.h> | |||
| 11 | #include <unistd.h> | |||
| 12 | ||||
| 13 | #include <ccan/endian/endian.h> | |||
| 14 | #include <ccan/minmax/minmax.h> | |||
| 15 | ||||
| 16 | #include <shared/compiler-attributes-util.h> | |||
| 17 | ||||
| 18 | #include <libnvme.h> | |||
| 19 | ||||
| 20 | #include <shared/string-util.h> | |||
| 21 | ||||
| 22 | #include "cleanup-linux.h" | |||
| 23 | #include "private-fabrics.h" | |||
| 24 | #include "util.h" | |||
| 25 | ||||
| 26 | __shr_public__attribute__((visibility("default"))) struct nvmf_ext_attr *libnvmf_exat_ptr_next( | |||
| 27 | struct nvmf_ext_attr *p) | |||
| 28 | { | |||
| 29 | __u16 size = libnvmf_exat_size(le16_to_cpu(p->exatlen)); | |||
| 30 | ||||
| 31 | return (struct nvmf_ext_attr *)((uintptr_t)p + (ptrdiff_t)size); | |||
| 32 | } | |||
| 33 | ||||
| 34 | const struct ifaddrs *libnvmf_getifaddrs(struct libnvme_global_ctx *ctx) | |||
| 35 | { | |||
| 36 | if (!ctx->ifaddrs_cache) { | |||
| 37 | struct ifaddrs *p; | |||
| 38 | ||||
| 39 | if (!getifaddrs(&p)) | |||
| 40 | ctx->ifaddrs_cache = p; | |||
| 41 | } | |||
| 42 | ||||
| 43 | return ctx->ifaddrs_cache; | |||
| 44 | } | |||
| 45 | ||||
| 46 | /** | |||
| 47 | * read_file - read contents of file into @buffer. | |||
| 48 | * @fname: File name | |||
| 49 | * @buffer: Where to save file's contents | |||
| 50 | * @bufsz: Size of @buffer. On success, @bufsz gets decremented by the | |||
| 51 | * number of characters that were writtent to @buffer. | |||
| 52 | * | |||
| 53 | * Return: The number of characters read. If the file cannot be opened or | |||
| 54 | * nothing is read from the file, then this function returns 0. | |||
| 55 | */ | |||
| 56 | static size_t read_file(const char * fname, char *buffer, size_t *bufsz) | |||
| 57 | { | |||
| 58 | char *p; | |||
| 59 | __cleanup_file__attribute__((cleanup(shr_cleanup_file))) FILE *file = NULL((void*)0); | |||
| 60 | size_t len; | |||
| 61 | ||||
| 62 | file = fopen(fname, "re"); | |||
| 63 | if (!file
| |||
| 64 | return 0; | |||
| 65 | ||||
| 66 | p = fgets(buffer, *bufsz, file); | |||
| ||||
| 67 | ||||
| 68 | if (!p) | |||
| 69 | return 0; | |||
| 70 | ||||
| 71 | /* Strip unwanted trailing chars */ | |||
| 72 | len = strcspn(buffer, " \t\n\r"); | |||
| 73 | *bufsz -= len; | |||
| 74 | ||||
| 75 | return len; | |||
| 76 | } | |||
| 77 | ||||
| 78 | static size_t copy_value(char *buf, size_t buflen, const char *value) | |||
| 79 | { | |||
| 80 | size_t val_len; | |||
| 81 | ||||
| 82 | memset(buf, 0, buflen); | |||
| 83 | ||||
| 84 | /* Remove leading " */ | |||
| 85 | if (value[0] == '"') | |||
| 86 | value++; | |||
| 87 | ||||
| 88 | /* Remove trailing " */ | |||
| 89 | val_len = strcspn(value, "\""); | |||
| 90 | ||||
| 91 | memcpy(buf, value, min(val_len, buflen-1)({ typeof(val_len) _a = (val_len); typeof(buflen-1) _b = (buflen -1); do { } while (0); _a < _b ? _a : _b; })); | |||
| 92 | ||||
| 93 | return val_len; | |||
| 94 | } | |||
| 95 | ||||
| 96 | size_t libnvmf_get_entity_name(char *buffer, size_t bufsz) | |||
| 97 | { | |||
| 98 | size_t len = !gethostname(buffer, bufsz) ? strlen(buffer) : 0; | |||
| 99 | ||||
| 100 | /* Fill the rest of buffer with zeros */ | |||
| 101 | memset(&buffer[len], '\0', bufsz-len); | |||
| 102 | ||||
| 103 | return len; | |||
| 104 | } | |||
| 105 | ||||
| 106 | size_t libnvmf_get_entity_version(char *buffer, size_t bufsz) | |||
| 107 | { | |||
| 108 | __cleanup_file__attribute__((cleanup(shr_cleanup_file))) FILE *file = NULL((void*)0); | |||
| 109 | size_t num_bytes = 0; | |||
| 110 | ||||
| 111 | /* /proc/sys/kernel/ostype typically contains the string "Linux" */ | |||
| 112 | num_bytes += read_file("/proc/sys/kernel/ostype", | |||
| ||||
| 113 | &buffer[num_bytes], &bufsz); | |||
| 114 | ||||
| 115 | /* /proc/sys/kernel/osrelease contains the Linux | |||
| 116 | * version (e.g. 5.8.0-63-generic) | |||
| 117 | */ | |||
| 118 | if (bufsz) { | |||
| 119 | buffer[num_bytes++] = ' '; /* Append a space */ | |||
| 120 | bufsz--; | |||
| 121 | } | |||
| 122 | num_bytes += read_file("/proc/sys/kernel/osrelease", | |||
| 123 | &buffer[num_bytes], &bufsz); | |||
| 124 | ||||
| 125 | /* /etc/os-release contains Key-Value pairs. We only care about the key | |||
| 126 | * PRETTY_NAME, which contains the Distro's version. For example: | |||
| 127 | * "SUSE Linux Enterprise Server 15 SP4", "Ubuntu 20.04.3 LTS", or | |||
| 128 | * "Fedora Linux 35 (Server Edition)" | |||
| 129 | */ | |||
| 130 | file = fopen("/etc/os-release", "re"); | |||
| 131 | if (file) { | |||
| 132 | char name[64] = {0}; | |||
| 133 | size_t name_len = 0; | |||
| 134 | char ver_id[64] = {0}; | |||
| 135 | size_t ver_id_len = 0; | |||
| 136 | char line[LINE_MAX2048]; | |||
| 137 | char *p; | |||
| 138 | char *s; | |||
| 139 | ||||
| 140 | /* Read key-value pairs one line at a time */ | |||
| 141 | while ((!name_len || !ver_id_len) && | |||
| 142 | (p = fgets(line, sizeof(line), file)) != NULL((void*)0)) { | |||
| 143 | /* Clean up string by removing leading/trailing blanks | |||
| 144 | * and new line characters. Also eliminate trailing | |||
| 145 | * comments, if any. | |||
| 146 | */ | |||
| 147 | p = shr_kv_strip(p); | |||
| 148 | ||||
| 149 | /* Empty string? */ | |||
| 150 | if (*p == '\0') | |||
| 151 | continue; | |||
| 152 | ||||
| 153 | s = shr_kv_keymatch(p, "NAME"); | |||
| 154 | if (s) | |||
| 155 | name_len = copy_value(name, sizeof(name), s); | |||
| 156 | ||||
| 157 | s = shr_kv_keymatch(p, "VERSION_ID"); | |||
| 158 | if (s) | |||
| 159 | ver_id_len = copy_value(ver_id, sizeof(ver_id), s); | |||
| 160 | } | |||
| 161 | ||||
| 162 | if (name_len) { | |||
| 163 | /* Append a space */ | |||
| 164 | if (bufsz) { | |||
| 165 | buffer[num_bytes++] = ' '; | |||
| 166 | bufsz--; | |||
| 167 | } | |||
| 168 | name_len = min(name_len, bufsz)({ typeof(name_len) _a = (name_len); typeof(bufsz) _b = (bufsz ); do { } while (0); _a < _b ? _a : _b; }); | |||
| 169 | memcpy(&buffer[num_bytes], name, name_len); | |||
| 170 | bufsz -= name_len; | |||
| 171 | num_bytes += name_len; | |||
| 172 | } | |||
| 173 | ||||
| 174 | if (ver_id_len) { | |||
| 175 | /* Append a space */ | |||
| 176 | if (bufsz) { | |||
| 177 | buffer[num_bytes++] = ' '; | |||
| 178 | bufsz--; | |||
| 179 | } | |||
| 180 | ver_id_len = min(ver_id_len, bufsz)({ typeof(ver_id_len) _a = (ver_id_len); typeof(bufsz) _b = ( bufsz); do { } while (0); _a < _b ? _a : _b; }); | |||
| 181 | memcpy(&buffer[num_bytes], ver_id, ver_id_len); | |||
| 182 | bufsz -= ver_id_len; | |||
| 183 | num_bytes += ver_id_len; | |||
| 184 | } | |||
| 185 | } | |||
| 186 | ||||
| 187 | /* Fill the rest of buffer with zeros */ | |||
| 188 | memset(&buffer[num_bytes], '\0', bufsz); | |||
| 189 | ||||
| 190 | return num_bytes; | |||
| 191 | } |