[2725] | 1 | /* vi: set sw=4 ts=4: */
|
---|
| 2 | /*
|
---|
| 3 | * Utility routines.
|
---|
| 4 | *
|
---|
| 5 | * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
|
---|
| 6 | * Copyright (C) 2006 Rob Landley
|
---|
| 7 | * Copyright (C) 2006 Denys Vlasenko
|
---|
| 8 | *
|
---|
| 9 | * Licensed under GPLv2, see file LICENSE in this source tree.
|
---|
| 10 | */
|
---|
| 11 |
|
---|
| 12 | /* We need to have separate xfuncs.c and xfuncs_printf.c because
|
---|
| 13 | * with current linkers, even with section garbage collection,
|
---|
| 14 | * if *.o module references any of XXXprintf functions, you pull in
|
---|
| 15 | * entire printf machinery. Even if you do not use the function
|
---|
| 16 | * which uses XXXprintf.
|
---|
| 17 | *
|
---|
| 18 | * xfuncs.c contains functions (not necessarily xfuncs)
|
---|
| 19 | * which do not pull in printf, directly or indirectly.
|
---|
| 20 | * xfunc_printf.c contains those which do.
|
---|
| 21 | */
|
---|
| 22 |
|
---|
| 23 | #include "libbb.h"
|
---|
| 24 |
|
---|
| 25 |
|
---|
| 26 | /* All the functions starting with "x" call bb_error_msg_and_die() if they
|
---|
| 27 | * fail, so callers never need to check for errors. If it returned, it
|
---|
| 28 | * succeeded. */
|
---|
| 29 |
|
---|
| 30 | #ifndef DMALLOC
|
---|
| 31 | /* dmalloc provides variants of these that do abort() on failure.
|
---|
| 32 | * Since dmalloc's prototypes overwrite the impls here as they are
|
---|
| 33 | * included after these prototypes in libbb.h, all is well.
|
---|
| 34 | */
|
---|
| 35 | // Warn if we can't allocate size bytes of memory.
|
---|
| 36 | void* FAST_FUNC malloc_or_warn(size_t size)
|
---|
| 37 | {
|
---|
| 38 | void *ptr = malloc(size);
|
---|
| 39 | if (ptr == NULL && size != 0)
|
---|
| 40 | bb_error_msg(bb_msg_memory_exhausted);
|
---|
| 41 | return ptr;
|
---|
| 42 | }
|
---|
| 43 |
|
---|
| 44 | // Die if we can't allocate size bytes of memory.
|
---|
| 45 | void* FAST_FUNC xmalloc(size_t size)
|
---|
| 46 | {
|
---|
| 47 | void *ptr = malloc(size);
|
---|
| 48 | if (ptr == NULL && size != 0)
|
---|
| 49 | bb_error_msg_and_die(bb_msg_memory_exhausted);
|
---|
| 50 | return ptr;
|
---|
| 51 | }
|
---|
| 52 |
|
---|
| 53 | // Die if we can't resize previously allocated memory. (This returns a pointer
|
---|
| 54 | // to the new memory, which may or may not be the same as the old memory.
|
---|
| 55 | // It'll copy the contents to a new chunk and free the old one if necessary.)
|
---|
| 56 | void* FAST_FUNC xrealloc(void *ptr, size_t size)
|
---|
| 57 | {
|
---|
| 58 | ptr = realloc(ptr, size);
|
---|
| 59 | if (ptr == NULL && size != 0)
|
---|
| 60 | bb_error_msg_and_die(bb_msg_memory_exhausted);
|
---|
| 61 | return ptr;
|
---|
| 62 | }
|
---|
| 63 | #endif /* DMALLOC */
|
---|
| 64 |
|
---|
| 65 | // Die if we can't allocate and zero size bytes of memory.
|
---|
| 66 | void* FAST_FUNC xzalloc(size_t size)
|
---|
| 67 | {
|
---|
| 68 | void *ptr = xmalloc(size);
|
---|
| 69 | memset(ptr, 0, size);
|
---|
| 70 | return ptr;
|
---|
| 71 | }
|
---|
| 72 |
|
---|
| 73 | // Die if we can't copy a string to freshly allocated memory.
|
---|
| 74 | char* FAST_FUNC xstrdup(const char *s)
|
---|
| 75 | {
|
---|
| 76 | char *t;
|
---|
| 77 |
|
---|
| 78 | if (s == NULL)
|
---|
| 79 | return NULL;
|
---|
| 80 |
|
---|
| 81 | t = strdup(s);
|
---|
| 82 |
|
---|
| 83 | if (t == NULL)
|
---|
| 84 | bb_error_msg_and_die(bb_msg_memory_exhausted);
|
---|
| 85 |
|
---|
| 86 | return t;
|
---|
| 87 | }
|
---|
| 88 |
|
---|
| 89 | // Die if we can't allocate n+1 bytes (space for the null terminator) and copy
|
---|
| 90 | // the (possibly truncated to length n) string into it.
|
---|
| 91 | char* FAST_FUNC xstrndup(const char *s, int n)
|
---|
| 92 | {
|
---|
| 93 | int m;
|
---|
| 94 | char *t;
|
---|
| 95 |
|
---|
| 96 | if (ENABLE_DEBUG && s == NULL)
|
---|
| 97 | bb_error_msg_and_die("xstrndup bug");
|
---|
| 98 |
|
---|
| 99 | /* We can just xmalloc(n+1) and strncpy into it, */
|
---|
| 100 | /* but think about xstrndup("abc", 10000) wastage! */
|
---|
| 101 | m = n;
|
---|
| 102 | t = (char*) s;
|
---|
| 103 | while (m) {
|
---|
| 104 | if (!*t) break;
|
---|
| 105 | m--;
|
---|
| 106 | t++;
|
---|
| 107 | }
|
---|
| 108 | n -= m;
|
---|
| 109 | t = xmalloc(n + 1);
|
---|
| 110 | t[n] = '\0';
|
---|
| 111 |
|
---|
| 112 | return memcpy(t, s, n);
|
---|
| 113 | }
|
---|
| 114 |
|
---|
| 115 | // Die if we can't open a file and return a FILE* to it.
|
---|
| 116 | // Notice we haven't got xfread(), This is for use with fscanf() and friends.
|
---|
| 117 | FILE* FAST_FUNC xfopen(const char *path, const char *mode)
|
---|
| 118 | {
|
---|
| 119 | FILE *fp = fopen(path, mode);
|
---|
| 120 | if (fp == NULL)
|
---|
| 121 | bb_perror_msg_and_die("can't open '%s'", path);
|
---|
| 122 | return fp;
|
---|
| 123 | }
|
---|
| 124 |
|
---|
| 125 | // Die if we can't open a file and return a fd.
|
---|
| 126 | int FAST_FUNC xopen3(const char *pathname, int flags, int mode)
|
---|
| 127 | {
|
---|
| 128 | int ret;
|
---|
| 129 |
|
---|
| 130 | ret = open(pathname, flags, mode);
|
---|
| 131 | if (ret < 0) {
|
---|
| 132 | bb_perror_msg_and_die("can't open '%s'", pathname);
|
---|
| 133 | }
|
---|
| 134 | return ret;
|
---|
| 135 | }
|
---|
| 136 |
|
---|
| 137 | // Die if we can't open a file and return a fd.
|
---|
| 138 | int FAST_FUNC xopen(const char *pathname, int flags)
|
---|
| 139 | {
|
---|
| 140 | return xopen3(pathname, flags, 0666);
|
---|
| 141 | }
|
---|
| 142 |
|
---|
| 143 | /* Die if we can't open an existing file readonly with O_NONBLOCK
|
---|
| 144 | * and return the fd.
|
---|
| 145 | * Note that for ioctl O_RDONLY is sufficient.
|
---|
| 146 | */
|
---|
| 147 | int FAST_FUNC xopen_nonblocking(const char *pathname)
|
---|
| 148 | {
|
---|
| 149 | return xopen(pathname, O_RDONLY | O_NONBLOCK);
|
---|
| 150 | }
|
---|
| 151 |
|
---|
| 152 | // Warn if we can't open a file and return a fd.
|
---|
| 153 | int FAST_FUNC open3_or_warn(const char *pathname, int flags, int mode)
|
---|
| 154 | {
|
---|
| 155 | int ret;
|
---|
| 156 |
|
---|
| 157 | ret = open(pathname, flags, mode);
|
---|
| 158 | if (ret < 0) {
|
---|
| 159 | bb_perror_msg("can't open '%s'", pathname);
|
---|
| 160 | }
|
---|
| 161 | return ret;
|
---|
| 162 | }
|
---|
| 163 |
|
---|
| 164 | // Warn if we can't open a file and return a fd.
|
---|
| 165 | int FAST_FUNC open_or_warn(const char *pathname, int flags)
|
---|
| 166 | {
|
---|
| 167 | return open3_or_warn(pathname, flags, 0666);
|
---|
| 168 | }
|
---|
| 169 |
|
---|
| 170 | void FAST_FUNC xunlink(const char *pathname)
|
---|
| 171 | {
|
---|
| 172 | if (unlink(pathname))
|
---|
| 173 | bb_perror_msg_and_die("can't remove file '%s'", pathname);
|
---|
| 174 | }
|
---|
| 175 |
|
---|
| 176 | void FAST_FUNC xrename(const char *oldpath, const char *newpath)
|
---|
| 177 | {
|
---|
| 178 | if (rename(oldpath, newpath))
|
---|
| 179 | bb_perror_msg_and_die("can't move '%s' to '%s'", oldpath, newpath);
|
---|
| 180 | }
|
---|
| 181 |
|
---|
| 182 | int FAST_FUNC rename_or_warn(const char *oldpath, const char *newpath)
|
---|
| 183 | {
|
---|
| 184 | int n = rename(oldpath, newpath);
|
---|
| 185 | if (n)
|
---|
| 186 | bb_perror_msg("can't move '%s' to '%s'", oldpath, newpath);
|
---|
| 187 | return n;
|
---|
| 188 | }
|
---|
| 189 |
|
---|
| 190 | void FAST_FUNC xpipe(int filedes[2])
|
---|
| 191 | {
|
---|
| 192 | if (pipe(filedes))
|
---|
| 193 | bb_perror_msg_and_die("can't create pipe");
|
---|
| 194 | }
|
---|
| 195 |
|
---|
| 196 | void FAST_FUNC xdup2(int from, int to)
|
---|
| 197 | {
|
---|
| 198 | if (dup2(from, to) != to)
|
---|
| 199 | bb_perror_msg_and_die("can't duplicate file descriptor");
|
---|
| 200 | }
|
---|
| 201 |
|
---|
| 202 | // "Renumber" opened fd
|
---|
| 203 | void FAST_FUNC xmove_fd(int from, int to)
|
---|
| 204 | {
|
---|
| 205 | if (from == to)
|
---|
| 206 | return;
|
---|
| 207 | xdup2(from, to);
|
---|
| 208 | close(from);
|
---|
| 209 | }
|
---|
| 210 |
|
---|
| 211 | // Die with an error message if we can't write the entire buffer.
|
---|
| 212 | void FAST_FUNC xwrite(int fd, const void *buf, size_t count)
|
---|
| 213 | {
|
---|
| 214 | if (count) {
|
---|
| 215 | ssize_t size = full_write(fd, buf, count);
|
---|
| 216 | if ((size_t)size != count)
|
---|
| 217 | bb_error_msg_and_die("short write");
|
---|
| 218 | }
|
---|
| 219 | }
|
---|
| 220 | void FAST_FUNC xwrite_str(int fd, const char *str)
|
---|
| 221 | {
|
---|
| 222 | xwrite(fd, str, strlen(str));
|
---|
| 223 | }
|
---|
| 224 |
|
---|
| 225 | void FAST_FUNC xclose(int fd)
|
---|
| 226 | {
|
---|
| 227 | if (close(fd))
|
---|
| 228 | bb_perror_msg_and_die("close failed");
|
---|
| 229 | }
|
---|
| 230 |
|
---|
| 231 | // Die with an error message if we can't lseek to the right spot.
|
---|
| 232 | off_t FAST_FUNC xlseek(int fd, off_t offset, int whence)
|
---|
| 233 | {
|
---|
| 234 | off_t off = lseek(fd, offset, whence);
|
---|
| 235 | if (off == (off_t)-1) {
|
---|
| 236 | if (whence == SEEK_SET)
|
---|
| 237 | bb_perror_msg_and_die("lseek(%"OFF_FMT"u)", offset);
|
---|
| 238 | bb_perror_msg_and_die("lseek");
|
---|
| 239 | }
|
---|
| 240 | return off;
|
---|
| 241 | }
|
---|
| 242 |
|
---|
| 243 | int FAST_FUNC xmkstemp(char *template)
|
---|
| 244 | {
|
---|
| 245 | int fd = mkstemp(template);
|
---|
| 246 | if (fd < 0)
|
---|
| 247 | bb_perror_msg_and_die("can't create temp file '%s'", template);
|
---|
| 248 | return fd;
|
---|
| 249 | }
|
---|
| 250 |
|
---|
| 251 | // Die with supplied filename if this FILE* has ferror set.
|
---|
| 252 | void FAST_FUNC die_if_ferror(FILE *fp, const char *fn)
|
---|
| 253 | {
|
---|
| 254 | if (ferror(fp)) {
|
---|
| 255 | /* ferror doesn't set useful errno */
|
---|
| 256 | bb_error_msg_and_die("%s: I/O error", fn);
|
---|
| 257 | }
|
---|
| 258 | }
|
---|
| 259 |
|
---|
| 260 | // Die with an error message if stdout has ferror set.
|
---|
| 261 | void FAST_FUNC die_if_ferror_stdout(void)
|
---|
| 262 | {
|
---|
| 263 | die_if_ferror(stdout, bb_msg_standard_output);
|
---|
| 264 | }
|
---|
| 265 |
|
---|
| 266 | int FAST_FUNC fflush_all(void)
|
---|
| 267 | {
|
---|
| 268 | return fflush(NULL);
|
---|
| 269 | }
|
---|
| 270 |
|
---|
| 271 |
|
---|
| 272 | int FAST_FUNC bb_putchar(int ch)
|
---|
| 273 | {
|
---|
| 274 | return putchar(ch);
|
---|
| 275 | }
|
---|
| 276 |
|
---|
| 277 | /* Die with an error message if we can't copy an entire FILE* to stdout,
|
---|
| 278 | * then close that file. */
|
---|
| 279 | void FAST_FUNC xprint_and_close_file(FILE *file)
|
---|
| 280 | {
|
---|
| 281 | fflush_all();
|
---|
| 282 | // copyfd outputs error messages for us.
|
---|
| 283 | if (bb_copyfd_eof(fileno(file), STDOUT_FILENO) == -1)
|
---|
| 284 | xfunc_die();
|
---|
| 285 |
|
---|
| 286 | fclose(file);
|
---|
| 287 | }
|
---|
| 288 |
|
---|
| 289 | // Die with an error message if we can't malloc() enough space and do an
|
---|
| 290 | // sprintf() into that space.
|
---|
| 291 | char* FAST_FUNC xasprintf(const char *format, ...)
|
---|
| 292 | {
|
---|
| 293 | va_list p;
|
---|
| 294 | int r;
|
---|
| 295 | char *string_ptr;
|
---|
| 296 |
|
---|
| 297 | va_start(p, format);
|
---|
| 298 | r = vasprintf(&string_ptr, format, p);
|
---|
| 299 | va_end(p);
|
---|
| 300 |
|
---|
| 301 | if (r < 0)
|
---|
| 302 | bb_error_msg_and_die(bb_msg_memory_exhausted);
|
---|
| 303 | return string_ptr;
|
---|
| 304 | }
|
---|
| 305 |
|
---|
| 306 | void FAST_FUNC xsetenv(const char *key, const char *value)
|
---|
| 307 | {
|
---|
| 308 | if (setenv(key, value, 1))
|
---|
| 309 | bb_error_msg_and_die(bb_msg_memory_exhausted);
|
---|
| 310 | }
|
---|
| 311 |
|
---|
| 312 | /* Handles "VAR=VAL" strings, even those which are part of environ
|
---|
| 313 | * _right now_
|
---|
| 314 | */
|
---|
| 315 | void FAST_FUNC bb_unsetenv(const char *var)
|
---|
| 316 | {
|
---|
| 317 | char *tp = strchr(var, '=');
|
---|
| 318 |
|
---|
| 319 | if (!tp) {
|
---|
| 320 | unsetenv(var);
|
---|
| 321 | return;
|
---|
| 322 | }
|
---|
| 323 |
|
---|
| 324 | /* In case var was putenv'ed, we can't replace '='
|
---|
| 325 | * with NUL and unsetenv(var) - it won't work,
|
---|
| 326 | * env is modified by the replacement, unsetenv
|
---|
| 327 | * sees "VAR" instead of "VAR=VAL" and does not remove it!
|
---|
| 328 | * horror :( */
|
---|
| 329 | tp = xstrndup(var, tp - var);
|
---|
| 330 | unsetenv(tp);
|
---|
| 331 | free(tp);
|
---|
| 332 | }
|
---|
| 333 |
|
---|
| 334 | void FAST_FUNC bb_unsetenv_and_free(char *var)
|
---|
| 335 | {
|
---|
| 336 | bb_unsetenv(var);
|
---|
| 337 | free(var);
|
---|
| 338 | }
|
---|
| 339 |
|
---|
| 340 | // Die with an error message if we can't set gid. (Because resource limits may
|
---|
| 341 | // limit this user to a given number of processes, and if that fills up the
|
---|
| 342 | // setgid() will fail and we'll _still_be_root_, which is bad.)
|
---|
| 343 | void FAST_FUNC xsetgid(gid_t gid)
|
---|
| 344 | {
|
---|
| 345 | if (setgid(gid)) bb_perror_msg_and_die("setgid");
|
---|
| 346 | }
|
---|
| 347 |
|
---|
| 348 | // Die with an error message if we can't set uid. (See xsetgid() for why.)
|
---|
| 349 | void FAST_FUNC xsetuid(uid_t uid)
|
---|
| 350 | {
|
---|
| 351 | if (setuid(uid)) bb_perror_msg_and_die("setuid");
|
---|
| 352 | }
|
---|
| 353 |
|
---|
| 354 | // Die if we can't chdir to a new path.
|
---|
| 355 | void FAST_FUNC xchdir(const char *path)
|
---|
| 356 | {
|
---|
| 357 | if (chdir(path))
|
---|
[3232] | 358 | bb_perror_msg_and_die("can't change directory to '%s'", path);
|
---|
[2725] | 359 | }
|
---|
| 360 |
|
---|
| 361 | void FAST_FUNC xchroot(const char *path)
|
---|
| 362 | {
|
---|
| 363 | if (chroot(path))
|
---|
[3232] | 364 | bb_perror_msg_and_die("can't change root directory to '%s'", path);
|
---|
| 365 | xchdir("/");
|
---|
[2725] | 366 | }
|
---|
| 367 |
|
---|
| 368 | // Print a warning message if opendir() fails, but don't die.
|
---|
| 369 | DIR* FAST_FUNC warn_opendir(const char *path)
|
---|
| 370 | {
|
---|
| 371 | DIR *dp;
|
---|
| 372 |
|
---|
| 373 | dp = opendir(path);
|
---|
| 374 | if (!dp)
|
---|
| 375 | bb_perror_msg("can't open '%s'", path);
|
---|
| 376 | return dp;
|
---|
| 377 | }
|
---|
| 378 |
|
---|
| 379 | // Die with an error message if opendir() fails.
|
---|
| 380 | DIR* FAST_FUNC xopendir(const char *path)
|
---|
| 381 | {
|
---|
| 382 | DIR *dp;
|
---|
| 383 |
|
---|
| 384 | dp = opendir(path);
|
---|
| 385 | if (!dp)
|
---|
| 386 | bb_perror_msg_and_die("can't open '%s'", path);
|
---|
| 387 | return dp;
|
---|
| 388 | }
|
---|
| 389 |
|
---|
| 390 | // Die with an error message if we can't open a new socket.
|
---|
| 391 | int FAST_FUNC xsocket(int domain, int type, int protocol)
|
---|
| 392 | {
|
---|
| 393 | int r = socket(domain, type, protocol);
|
---|
| 394 |
|
---|
| 395 | if (r < 0) {
|
---|
| 396 | /* Hijack vaguely related config option */
|
---|
| 397 | #if ENABLE_VERBOSE_RESOLUTION_ERRORS
|
---|
| 398 | const char *s = "INET";
|
---|
| 399 | # ifdef AF_PACKET
|
---|
| 400 | if (domain == AF_PACKET) s = "PACKET";
|
---|
| 401 | # endif
|
---|
| 402 | # ifdef AF_NETLINK
|
---|
| 403 | if (domain == AF_NETLINK) s = "NETLINK";
|
---|
| 404 | # endif
|
---|
| 405 | IF_FEATURE_IPV6(if (domain == AF_INET6) s = "INET6";)
|
---|
| 406 | bb_perror_msg_and_die("socket(AF_%s,%d,%d)", s, type, protocol);
|
---|
| 407 | #else
|
---|
| 408 | bb_perror_msg_and_die("socket");
|
---|
| 409 | #endif
|
---|
| 410 | }
|
---|
| 411 |
|
---|
| 412 | return r;
|
---|
| 413 | }
|
---|
| 414 |
|
---|
| 415 | // Die with an error message if we can't bind a socket to an address.
|
---|
| 416 | void FAST_FUNC xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen)
|
---|
| 417 | {
|
---|
| 418 | if (bind(sockfd, my_addr, addrlen)) bb_perror_msg_and_die("bind");
|
---|
| 419 | }
|
---|
| 420 |
|
---|
| 421 | // Die with an error message if we can't listen for connections on a socket.
|
---|
| 422 | void FAST_FUNC xlisten(int s, int backlog)
|
---|
| 423 | {
|
---|
| 424 | if (listen(s, backlog)) bb_perror_msg_and_die("listen");
|
---|
| 425 | }
|
---|
| 426 |
|
---|
| 427 | /* Die with an error message if sendto failed.
|
---|
| 428 | * Return bytes sent otherwise */
|
---|
| 429 | ssize_t FAST_FUNC xsendto(int s, const void *buf, size_t len, const struct sockaddr *to,
|
---|
| 430 | socklen_t tolen)
|
---|
| 431 | {
|
---|
| 432 | ssize_t ret = sendto(s, buf, len, 0, to, tolen);
|
---|
| 433 | if (ret < 0) {
|
---|
| 434 | if (ENABLE_FEATURE_CLEAN_UP)
|
---|
| 435 | close(s);
|
---|
| 436 | bb_perror_msg_and_die("sendto");
|
---|
| 437 | }
|
---|
| 438 | return ret;
|
---|
| 439 | }
|
---|
| 440 |
|
---|
| 441 | // xstat() - a stat() which dies on failure with meaningful error message
|
---|
| 442 | void FAST_FUNC xstat(const char *name, struct stat *stat_buf)
|
---|
| 443 | {
|
---|
| 444 | if (stat(name, stat_buf))
|
---|
| 445 | bb_perror_msg_and_die("can't stat '%s'", name);
|
---|
| 446 | }
|
---|
| 447 |
|
---|
| 448 | void FAST_FUNC xfstat(int fd, struct stat *stat_buf, const char *errmsg)
|
---|
| 449 | {
|
---|
| 450 | /* errmsg is usually a file name, but not always:
|
---|
| 451 | * xfstat may be called in a spot where file name is no longer
|
---|
| 452 | * available, and caller may give e.g. "can't stat input file" string.
|
---|
| 453 | */
|
---|
| 454 | if (fstat(fd, stat_buf))
|
---|
| 455 | bb_simple_perror_msg_and_die(errmsg);
|
---|
| 456 | }
|
---|
| 457 |
|
---|
| 458 | // selinux_or_die() - die if SELinux is disabled.
|
---|
| 459 | void FAST_FUNC selinux_or_die(void)
|
---|
| 460 | {
|
---|
| 461 | #if ENABLE_SELINUX
|
---|
| 462 | int rc = is_selinux_enabled();
|
---|
| 463 | if (rc == 0) {
|
---|
| 464 | bb_error_msg_and_die("SELinux is disabled");
|
---|
| 465 | } else if (rc < 0) {
|
---|
| 466 | bb_error_msg_and_die("is_selinux_enabled() failed");
|
---|
| 467 | }
|
---|
| 468 | #else
|
---|
| 469 | bb_error_msg_and_die("SELinux support is disabled");
|
---|
| 470 | #endif
|
---|
| 471 | }
|
---|
| 472 |
|
---|
| 473 | int FAST_FUNC ioctl_or_perror_and_die(int fd, unsigned request, void *argp, const char *fmt,...)
|
---|
| 474 | {
|
---|
| 475 | int ret;
|
---|
| 476 | va_list p;
|
---|
| 477 |
|
---|
| 478 | ret = ioctl(fd, request, argp);
|
---|
| 479 | if (ret < 0) {
|
---|
| 480 | va_start(p, fmt);
|
---|
| 481 | bb_verror_msg(fmt, p, strerror(errno));
|
---|
| 482 | /* xfunc_die can actually longjmp, so be nice */
|
---|
| 483 | va_end(p);
|
---|
| 484 | xfunc_die();
|
---|
| 485 | }
|
---|
| 486 | return ret;
|
---|
| 487 | }
|
---|
| 488 |
|
---|
| 489 | int FAST_FUNC ioctl_or_perror(int fd, unsigned request, void *argp, const char *fmt,...)
|
---|
| 490 | {
|
---|
| 491 | va_list p;
|
---|
| 492 | int ret = ioctl(fd, request, argp);
|
---|
| 493 |
|
---|
| 494 | if (ret < 0) {
|
---|
| 495 | va_start(p, fmt);
|
---|
| 496 | bb_verror_msg(fmt, p, strerror(errno));
|
---|
| 497 | va_end(p);
|
---|
| 498 | }
|
---|
| 499 | return ret;
|
---|
| 500 | }
|
---|
| 501 |
|
---|
| 502 | #if ENABLE_IOCTL_HEX2STR_ERROR
|
---|
| 503 | int FAST_FUNC bb_ioctl_or_warn(int fd, unsigned request, void *argp, const char *ioctl_name)
|
---|
| 504 | {
|
---|
| 505 | int ret;
|
---|
| 506 |
|
---|
| 507 | ret = ioctl(fd, request, argp);
|
---|
| 508 | if (ret < 0)
|
---|
| 509 | bb_simple_perror_msg(ioctl_name);
|
---|
| 510 | return ret;
|
---|
| 511 | }
|
---|
| 512 | int FAST_FUNC bb_xioctl(int fd, unsigned request, void *argp, const char *ioctl_name)
|
---|
| 513 | {
|
---|
| 514 | int ret;
|
---|
| 515 |
|
---|
| 516 | ret = ioctl(fd, request, argp);
|
---|
| 517 | if (ret < 0)
|
---|
| 518 | bb_simple_perror_msg_and_die(ioctl_name);
|
---|
| 519 | return ret;
|
---|
| 520 | }
|
---|
| 521 | #else
|
---|
| 522 | int FAST_FUNC bb_ioctl_or_warn(int fd, unsigned request, void *argp)
|
---|
| 523 | {
|
---|
| 524 | int ret;
|
---|
| 525 |
|
---|
| 526 | ret = ioctl(fd, request, argp);
|
---|
| 527 | if (ret < 0)
|
---|
| 528 | bb_perror_msg("ioctl %#x failed", request);
|
---|
| 529 | return ret;
|
---|
| 530 | }
|
---|
| 531 | int FAST_FUNC bb_xioctl(int fd, unsigned request, void *argp)
|
---|
| 532 | {
|
---|
| 533 | int ret;
|
---|
| 534 |
|
---|
| 535 | ret = ioctl(fd, request, argp);
|
---|
| 536 | if (ret < 0)
|
---|
| 537 | bb_perror_msg_and_die("ioctl %#x failed", request);
|
---|
| 538 | return ret;
|
---|
| 539 | }
|
---|
| 540 | #endif
|
---|
| 541 |
|
---|
| 542 | char* FAST_FUNC xmalloc_ttyname(int fd)
|
---|
| 543 | {
|
---|
| 544 | char *buf = xzalloc(128);
|
---|
| 545 | int r = ttyname_r(fd, buf, 127);
|
---|
| 546 | if (r) {
|
---|
| 547 | free(buf);
|
---|
| 548 | buf = NULL;
|
---|
| 549 | }
|
---|
| 550 | return buf;
|
---|
| 551 | }
|
---|
| 552 |
|
---|
| 553 | void FAST_FUNC generate_uuid(uint8_t *buf)
|
---|
| 554 | {
|
---|
| 555 | /* http://www.ietf.org/rfc/rfc4122.txt
|
---|
| 556 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
---|
| 557 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
---|
| 558 | * | time_low |
|
---|
| 559 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
---|
| 560 | * | time_mid | time_hi_and_version |
|
---|
| 561 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
---|
| 562 | * |clk_seq_and_variant | node (0-1) |
|
---|
| 563 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
---|
| 564 | * | node (2-5) |
|
---|
| 565 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
---|
| 566 | * IOW, uuid has this layout:
|
---|
| 567 | * uint32_t time_low (big endian)
|
---|
| 568 | * uint16_t time_mid (big endian)
|
---|
| 569 | * uint16_t time_hi_and_version (big endian)
|
---|
| 570 | * version is a 4-bit field:
|
---|
| 571 | * 1 Time-based
|
---|
| 572 | * 2 DCE Security, with embedded POSIX UIDs
|
---|
| 573 | * 3 Name-based (MD5)
|
---|
| 574 | * 4 Randomly generated
|
---|
| 575 | * 5 Name-based (SHA-1)
|
---|
| 576 | * uint16_t clk_seq_and_variant (big endian)
|
---|
| 577 | * variant is a 3-bit field:
|
---|
| 578 | * 0xx Reserved, NCS backward compatibility
|
---|
| 579 | * 10x The variant specified in rfc4122
|
---|
| 580 | * 110 Reserved, Microsoft backward compatibility
|
---|
| 581 | * 111 Reserved for future definition
|
---|
| 582 | * uint8_t node[6]
|
---|
| 583 | *
|
---|
| 584 | * For version 4, these bits are set/cleared:
|
---|
| 585 | * time_hi_and_version & 0x0fff | 0x4000
|
---|
| 586 | * clk_seq_and_variant & 0x3fff | 0x8000
|
---|
| 587 | */
|
---|
| 588 | pid_t pid;
|
---|
| 589 | int i;
|
---|
| 590 |
|
---|
| 591 | i = open("/dev/urandom", O_RDONLY);
|
---|
| 592 | if (i >= 0) {
|
---|
| 593 | read(i, buf, 16);
|
---|
| 594 | close(i);
|
---|
| 595 | }
|
---|
| 596 | /* Paranoia. /dev/urandom may be missing.
|
---|
| 597 | * rand() is guaranteed to generate at least [0, 2^15) range,
|
---|
| 598 | * but lowest bits in some libc are not so "random". */
|
---|
| 599 | srand(monotonic_us()); /* pulls in printf */
|
---|
| 600 | pid = getpid();
|
---|
| 601 | while (1) {
|
---|
| 602 | for (i = 0; i < 16; i++)
|
---|
| 603 | buf[i] ^= rand() >> 5;
|
---|
| 604 | if (pid == 0)
|
---|
| 605 | break;
|
---|
| 606 | srand(pid);
|
---|
| 607 | pid = 0;
|
---|
| 608 | }
|
---|
| 609 |
|
---|
| 610 | /* version = 4 */
|
---|
| 611 | buf[4 + 2 ] = (buf[4 + 2 ] & 0x0f) | 0x40;
|
---|
| 612 | /* variant = 10x */
|
---|
| 613 | buf[4 + 2 + 2] = (buf[4 + 2 + 2] & 0x3f) | 0x80;
|
---|
| 614 | }
|
---|
| 615 |
|
---|
| 616 | #if BB_MMU
|
---|
| 617 | pid_t FAST_FUNC xfork(void)
|
---|
| 618 | {
|
---|
| 619 | pid_t pid;
|
---|
| 620 | pid = fork();
|
---|
| 621 | if (pid < 0) /* wtf? */
|
---|
| 622 | bb_perror_msg_and_die("vfork"+1);
|
---|
| 623 | return pid;
|
---|
| 624 | }
|
---|
| 625 | #endif
|
---|