1 /* xwrap.c - wrappers around existing library functions. 2 * 3 * Functions with the x prefix are wrappers that either succeed or kill the 4 * program with an error message, but never return failure. They usually have 5 * the same arguments and return value as the function they wrap. 6 * 7 * Copyright 2006 Rob Landley <rob (at) landley.net> 8 */ 9 10 #include "toys.h" 11 12 // strcpy and strncat with size checking. Size is the total space in "dest", 13 // including null terminator. Exit if there's not enough space for the string 14 // (including space for the null terminator), because silently truncating is 15 // still broken behavior. (And leaving the string unterminated is INSANE.) 16 void xstrncpy(char *dest, char *src, size_t size) 17 { 18 if (strlen(src)+1 > size) error_exit("'%s' > %ld bytes", src, (long)size); 19 strcpy(dest, src); 20 } 21 22 void xstrncat(char *dest, char *src, size_t size) 23 { 24 long len = strlen(dest); 25 26 if (len+strlen(src)+1 > size) 27 error_exit("'%s%s' > %ld bytes", dest, src, (long)size); 28 strcpy(dest+len, src); 29 } 30 31 // We replaced exit(), _exit(), and atexit() with xexit(), _xexit(), and 32 // sigatexit(). This gives _xexit() the option to siglongjmp(toys.rebound, 1) 33 // instead of exiting, lets xexit() report stdout flush failures to stderr 34 // and change the exit code to indicate error, lets our toys.exit function 35 // change happen for signal exit paths and lets us remove the functions 36 // after we've called them. 37 38 void _xexit(void) 39 { 40 if (toys.rebound) siglongjmp(*toys.rebound, 1); 41 42 _exit(toys.exitval); 43 } 44 45 void xexit(void) 46 { 47 // Call toys.xexit functions in reverse order added. 48 while (toys.xexit) { 49 struct arg_list *al = llist_pop(&toys.xexit); 50 51 // typecast xexit->arg to a function pointer, then call it using invalid 52 // signal 0 to let signal handlers tell actual signal from regular exit. 53 ((void (*)(int))(al->arg))(0); 54 55 free(al); 56 } 57 if (fflush(0) || ferror(stdout)) if (!toys.exitval) perror_msg("write"); 58 _xexit(); 59 } 60 61 void *xmmap(void *addr, size_t length, int prot, int flags, int fd, off_t off) 62 { 63 void *ret = mmap(addr, length, prot, flags, fd, off); 64 if (ret == MAP_FAILED) perror_exit("mmap"); 65 return ret; 66 } 67 68 // Die unless we can allocate memory. 69 void *xmalloc(size_t size) 70 { 71 void *ret = malloc(size); 72 if (!ret) error_exit("xmalloc(%ld)", (long)size); 73 74 return ret; 75 } 76 77 // Die unless we can allocate prezeroed memory. 78 void *xzalloc(size_t size) 79 { 80 void *ret = xmalloc(size); 81 memset(ret, 0, size); 82 return ret; 83 } 84 85 // Die unless we can change the size of an existing allocation, possibly 86 // moving it. (Notice different arguments from libc function.) 87 void *xrealloc(void *ptr, size_t size) 88 { 89 ptr = realloc(ptr, size); 90 if (!ptr) error_exit("xrealloc"); 91 92 return ptr; 93 } 94 95 // Die unless we can allocate a copy of this many bytes of string. 96 char *xstrndup(char *s, size_t n) 97 { 98 char *ret = strndup(s, n); 99 100 if (!ret) error_exit("xstrndup"); 101 102 return ret; 103 } 104 105 // Die unless we can allocate a copy of this string. 106 char *xstrdup(char *s) 107 { 108 return xstrndup(s, strlen(s)); 109 } 110 111 void *xmemdup(void *s, long len) 112 { 113 void *ret = xmalloc(len); 114 memcpy(ret, s, len); 115 116 return ret; 117 } 118 119 // Die unless we can allocate enough space to sprintf() into. 120 char *xmprintf(char *format, ...) 121 { 122 va_list va, va2; 123 int len; 124 char *ret; 125 126 va_start(va, format); 127 va_copy(va2, va); 128 129 // How long is it? 130 len = vsnprintf(0, 0, format, va); 131 len++; 132 va_end(va); 133 134 // Allocate and do the sprintf() 135 ret = xmalloc(len); 136 vsnprintf(ret, len, format, va2); 137 va_end(va2); 138 139 return ret; 140 } 141 142 void xflush(void) 143 { 144 if (fflush(stdout) || ferror(stdout)) perror_exit("write"); 145 } 146 147 void xprintf(char *format, ...) 148 { 149 va_list va; 150 va_start(va, format); 151 152 vprintf(format, va); 153 va_end(va); 154 xflush(); 155 } 156 157 // Put string with length (does not append newline) 158 void xputsl(char *s, int len) 159 { 160 int out; 161 162 while (len != (out = fwrite(s, 1, len, stdout))) { 163 if (out<1) perror_exit("write"); 164 len -= out; 165 s += out; 166 } 167 xflush(); 168 } 169 170 // xputs with no newline 171 void xputsn(char *s) 172 { 173 xputsl(s, strlen(s)); 174 } 175 176 // Write string to stdout with newline, flushing and checking for errors 177 void xputs(char *s) 178 { 179 puts(s); 180 xflush(); 181 } 182 183 void xputc(char c) 184 { 185 if (EOF == fputc(c, stdout)) perror_exit("write"); 186 xflush(); 187 } 188 189 // This is called through the XVFORK macro because parent/child of vfork 190 // share a stack, so child returning from a function would stomp the return 191 // address parent would need. Solution: make vfork() an argument so processes 192 // diverge before function gets called. 193 pid_t __attribute__((returns_twice)) xvforkwrap(pid_t pid) 194 { 195 if (pid == -1) perror_exit("vfork"); 196 197 // Signal to xexec() and friends that we vforked so can't recurse 198 toys.stacktop = 0; 199 200 return pid; 201 } 202 203 // Die unless we can exec argv[] (or run builtin command). Note that anything 204 // with a path isn't a builtin, so /bin/sh won't match the builtin sh. 205 void xexec(char **argv) 206 { 207 // Only recurse to builtin when we have multiplexer and !vfork context. 208 if (CFG_TOYBOX && !CFG_TOYBOX_NORECURSE && toys.stacktop && **argv != '/') 209 toy_exec(argv); 210 execvp(argv[0], argv); 211 212 toys.exitval = 126+(errno == ENOENT); 213 perror_msg("exec %s", argv[0]); 214 if (!toys.stacktop) _exit(toys.exitval); 215 xexit(); 216 } 217 218 // Spawn child process, capturing stdin/stdout. 219 // argv[]: command to exec. If null, child re-runs original program with 220 // toys.stacktop zeroed. 221 // pipes[2]: Filehandle to move to stdin/stdout of new process. 222 // If -1, replace with pipe handle connected to stdin/stdout. 223 // NULL treated as {0, 1}, I.E. leave stdin/stdout as is 224 // return: pid of child process 225 pid_t xpopen_both(char **argv, int *pipes) 226 { 227 int cestnepasun[4], pid; 228 229 // Make the pipes? 230 memset(cestnepasun, 0, sizeof(cestnepasun)); 231 if (pipes) for (pid = 0; pid < 2; pid++) { 232 if (pipes[pid] != -1) continue; 233 if (pipe(cestnepasun+(2*pid))) perror_exit("pipe"); 234 } 235 236 if (!(pid = CFG_TOYBOX_FORK ? xfork() : XVFORK())) { 237 // Child process: Dance of the stdin/stdout redirection. 238 if (pipes) { 239 // if we had no stdin/out, pipe handles could overlap, so test for it 240 // and free up potentially overlapping pipe handles before reuse 241 if (cestnepasun[2]) { 242 close(cestnepasun[2]); 243 pipes[1] = cestnepasun[3]; 244 } 245 if (cestnepasun[1]) { 246 close(cestnepasun[1]); 247 pipes[0] = cestnepasun[0]; 248 } 249 250 // If swapping stdin/stdout 251 if (!pipes[1]) pipes[1] = dup(pipes[1]); 252 253 // Are we redirecting stdin? 254 if (pipes[0]) { 255 dup2(pipes[0], 0); 256 close(pipes[0]); 257 } 258 259 // Are we redirecting stdout? 260 if (pipes[1] != 1) { 261 dup2(pipes[1], 1); 262 if (cestnepasun[2]) close(cestnepasun[2]); 263 } 264 } 265 if (argv) xexec(argv); 266 267 // In fork() case, force recursion because we know it's us. 268 if (CFG_TOYBOX_FORK) { 269 toy_init(toys.which, toys.argv); 270 toys.stacktop = 0; 271 toys.which->toy_main(); 272 xexit(); 273 // In vfork() case, exec /proc/self/exe with high bit of first letter set 274 // to tell main() we reentered. 275 } else { 276 char *s = "/proc/self/exe"; 277 278 // We did a nommu-friendly vfork but must exec to continue. 279 // setting high bit of argv[0][0] to let new process know 280 **toys.argv |= 0x80; 281 execv(s, toys.argv); 282 perror_msg_raw(s); 283 284 _exit(127); 285 } 286 } 287 288 // Parent process: vfork had a shared environment, clean up. 289 if (!CFG_TOYBOX_FORK) **toys.argv &= 0x7f; 290 291 if (pipes) { 292 if (cestnepasun[1]) { 293 pipes[0] = cestnepasun[1]; 294 close(cestnepasun[0]); 295 } 296 if (cestnepasun[2]) { 297 pipes[1] = cestnepasun[2]; 298 close(cestnepasun[3]); 299 } 300 } 301 302 return pid; 303 } 304 305 // Wait for child process to exit, then return adjusted exit code. 306 int xwaitpid(pid_t pid) 307 { 308 int status; 309 310 while (-1 == waitpid(pid, &status, 0) && errno == EINTR); 311 312 return WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status)+127; 313 } 314 315 int xpclose_both(pid_t pid, int *pipes) 316 { 317 if (pipes) { 318 close(pipes[0]); 319 close(pipes[1]); 320 } 321 322 return xwaitpid(pid); 323 } 324 325 // Wrapper to xpopen with a pipe for just one of stdin/stdout 326 pid_t xpopen(char **argv, int *pipe, int isstdout) 327 { 328 int pipes[2], pid; 329 330 pipes[0] = isstdout ? 0 : -1; 331 pipes[1] = isstdout ? -1 : 1; 332 pid = xpopen_both(argv, pipes); 333 *pipe = pid ? pipes[!!isstdout] : -1; 334 335 return pid; 336 } 337 338 int xpclose(pid_t pid, int pipe) 339 { 340 close(pipe); 341 342 return xpclose_both(pid, 0); 343 } 344 345 // Call xpopen and wait for it to finish, keeping existing stdin/stdout. 346 int xrun(char **argv) 347 { 348 return xpclose_both(xpopen_both(argv, 0), 0); 349 } 350 351 void xaccess(char *path, int flags) 352 { 353 if (access(path, flags)) perror_exit("Can't access '%s'", path); 354 } 355 356 // Die unless we can delete a file. (File must exist to be deleted.) 357 void xunlink(char *path) 358 { 359 if (unlink(path)) perror_exit("unlink '%s'", path); 360 } 361 362 // Die unless we can open/create a file, returning file descriptor. 363 // The meaning of O_CLOEXEC is reversed (it defaults on, pass it to disable) 364 // and WARN_ONLY tells us not to exit. 365 int xcreate_stdio(char *path, int flags, int mode) 366 { 367 int fd = open(path, (flags^O_CLOEXEC)&~WARN_ONLY, mode); 368 369 if (fd == -1) ((mode&WARN_ONLY) ? perror_msg_raw : perror_exit_raw)(path); 370 return fd; 371 } 372 373 // Die unless we can open a file, returning file descriptor. 374 int xopen_stdio(char *path, int flags) 375 { 376 return xcreate_stdio(path, flags, 0); 377 } 378 379 void xpipe(int *pp) 380 { 381 if (pipe(pp)) perror_exit("xpipe"); 382 } 383 384 void xclose(int fd) 385 { 386 if (close(fd)) perror_exit("xclose"); 387 } 388 389 int xdup(int fd) 390 { 391 if (fd != -1) { 392 fd = dup(fd); 393 if (fd == -1) perror_exit("xdup"); 394 } 395 return fd; 396 } 397 398 // Move file descriptor above stdin/stdout/stderr, using /dev/null to consume 399 // old one. (We should never be called with stdin/stdout/stderr closed, but...) 400 int notstdio(int fd) 401 { 402 if (fd<0) return fd; 403 404 while (fd<3) { 405 int fd2 = xdup(fd); 406 407 close(fd); 408 xopen_stdio("/dev/null", O_RDWR); 409 fd = fd2; 410 } 411 412 return fd; 413 } 414 415 void xrename(char *from, char *to) 416 { 417 if (rename(from, to)) perror_exit("rename %s -> %s", from, to); 418 } 419 420 int xtempfile(char *name, char **tempname) 421 { 422 int fd; 423 424 *tempname = xmprintf("%s%s", name, "XXXXXX"); 425 if(-1 == (fd = mkstemp(*tempname))) error_exit("no temp file"); 426 427 return fd; 428 } 429 430 // Create a file but don't return stdin/stdout/stderr 431 int xcreate(char *path, int flags, int mode) 432 { 433 return notstdio(xcreate_stdio(path, flags, mode)); 434 } 435 436 // Open a file descriptor NOT in stdin/stdout/stderr 437 int xopen(char *path, int flags) 438 { 439 return notstdio(xopen_stdio(path, flags)); 440 } 441 442 // Open read only, treating "-" as a synonym for stdin, defaulting to warn only 443 int openro(char *path, int flags) 444 { 445 if (!strcmp(path, "-")) return 0; 446 447 return xopen(path, flags^WARN_ONLY); 448 } 449 450 // Open read only, treating "-" as a synonym for stdin. 451 int xopenro(char *path) 452 { 453 return openro(path, O_RDONLY|WARN_ONLY); 454 } 455 456 FILE *xfdopen(int fd, char *mode) 457 { 458 FILE *f = fdopen(fd, mode); 459 460 if (!f) perror_exit("xfdopen"); 461 462 return f; 463 } 464 465 // Die unless we can open/create a file, returning FILE *. 466 FILE *xfopen(char *path, char *mode) 467 { 468 FILE *f = fopen(path, mode); 469 if (!f) perror_exit("No file %s", path); 470 return f; 471 } 472 473 // Die if there's an error other than EOF. 474 size_t xread(int fd, void *buf, size_t len) 475 { 476 ssize_t ret = read(fd, buf, len); 477 if (ret < 0) perror_exit("xread"); 478 479 return ret; 480 } 481 482 void xreadall(int fd, void *buf, size_t len) 483 { 484 if (len != readall(fd, buf, len)) perror_exit("xreadall"); 485 } 486 487 // There's no xwriteall(), just xwrite(). When we read, there may or may not 488 // be more data waiting. When we write, there is data and it had better go 489 // somewhere. 490 491 void xwrite(int fd, void *buf, size_t len) 492 { 493 if (len != writeall(fd, buf, len)) perror_exit("xwrite"); 494 } 495 496 // Die if lseek fails, probably due to being called on a pipe. 497 498 off_t xlseek(int fd, off_t offset, int whence) 499 { 500 offset = lseek(fd, offset, whence); 501 if (offset<0) perror_exit("lseek"); 502 503 return offset; 504 } 505 506 char *xgetcwd(void) 507 { 508 char *buf = getcwd(NULL, 0); 509 if (!buf) perror_exit("xgetcwd"); 510 511 return buf; 512 } 513 514 void xstat(char *path, struct stat *st) 515 { 516 if(stat(path, st)) perror_exit("Can't stat %s", path); 517 } 518 519 // Canonicalize path, even to file with one or more missing components at end. 520 // Returns allocated string for pathname or NULL if doesn't exist 521 // exact = 1 file must exist, 0 dir must exist, -1 show theoretical location 522 char *xabspath(char *path, int exact) 523 { 524 struct string_list *todo, *done = 0; 525 int try = 9999, dirfd = open("/", O_PATH), missing = 0; 526 char *ret; 527 528 // If this isn't an absolute path, start with cwd. 529 if (*path != '/') { 530 char *temp = xgetcwd(); 531 532 splitpath(path, splitpath(temp, &todo)); 533 free(temp); 534 } else splitpath(path, &todo); 535 536 // Iterate through path components in todo, prepend processed ones to done. 537 while (todo) { 538 struct string_list *new = llist_pop(&todo), **tail; 539 ssize_t len; 540 541 // Eventually break out of endless loops 542 if (!try--) { 543 errno = ELOOP; 544 goto error; 545 } 546 547 // Removable path componenents. 548 if (!strcmp(new->str, ".") || !strcmp(new->str, "..")) { 549 int x = new->str[1]; 550 551 free(new); 552 if (!x) continue; 553 if (done) free(llist_pop(&done)); 554 len = 0; 555 556 if (missing) missing--; 557 else { 558 if (-1 == (x = openat(dirfd, "..", O_PATH))) goto error; 559 close(dirfd); 560 dirfd = x; 561 } 562 continue; 563 } 564 565 // Is this a symlink? 566 len = readlinkat(dirfd, new->str, libbuf, sizeof(libbuf)); 567 if (len>4095) goto error; 568 569 // Not a symlink: add to linked list, move dirfd, fail if error 570 if (len<1) { 571 int fd; 572 573 new->next = done; 574 done = new; 575 if (errno == EINVAL && !todo) break; 576 if (errno == ENOENT && exact<0) { 577 missing++; 578 continue; 579 } 580 if (errno != EINVAL && (exact || todo)) goto error; 581 582 fd = openat(dirfd, new->str, O_PATH); 583 if (fd == -1 && (exact || todo || errno != ENOENT)) goto error; 584 close(dirfd); 585 dirfd = fd; 586 continue; 587 } 588 589 // If this symlink is to an absolute path, discard existing resolved path 590 libbuf[len] = 0; 591 if (*libbuf == '/') { 592 llist_traverse(done, free); 593 done=0; 594 close(dirfd); 595 dirfd = open("/", O_PATH); 596 } 597 free(new); 598 599 // prepend components of new path. Note symlink to "/" will leave new NULL 600 tail = splitpath(libbuf, &new); 601 602 // symlink to "/" will return null and leave tail alone 603 if (new) { 604 *tail = todo; 605 todo = new; 606 } 607 } 608 close(dirfd); 609 610 // At this point done has the path, in reverse order. Reverse list while 611 // calculating buffer length. 612 613 try = 2; 614 while (done) { 615 struct string_list *temp = llist_pop(&done); 616 617 if (todo) try++; 618 try += strlen(temp->str); 619 temp->next = todo; 620 todo = temp; 621 } 622 623 // Assemble return buffer 624 625 ret = xmalloc(try); 626 *ret = '/'; 627 ret [try = 1] = 0; 628 while (todo) { 629 if (try>1) ret[try++] = '/'; 630 try = stpcpy(ret+try, todo->str) - ret; 631 free(llist_pop(&todo)); 632 } 633 634 return ret; 635 636 error: 637 close(dirfd); 638 llist_traverse(todo, free); 639 llist_traverse(done, free); 640 641 return 0; 642 } 643 644 void xchdir(char *path) 645 { 646 if (chdir(path)) perror_exit("chdir '%s'", path); 647 } 648 649 void xchroot(char *path) 650 { 651 if (chroot(path)) error_exit("chroot '%s'", path); 652 xchdir("/"); 653 } 654 655 struct passwd *xgetpwuid(uid_t uid) 656 { 657 struct passwd *pwd = getpwuid(uid); 658 if (!pwd) error_exit("bad uid %ld", (long)uid); 659 return pwd; 660 } 661 662 struct group *xgetgrgid(gid_t gid) 663 { 664 struct group *group = getgrgid(gid); 665 666 if (!group) perror_exit("gid %ld", (long)gid); 667 return group; 668 } 669 670 unsigned xgetuid(char *name) 671 { 672 struct passwd *up = getpwnam(name); 673 char *s = 0; 674 long uid; 675 676 if (up) return up->pw_uid; 677 678 uid = estrtol(name, &s, 10); 679 if (!errno && s && !*s && uid>=0 && uid<=UINT_MAX) return uid; 680 681 error_exit("bad user '%s'", name); 682 } 683 684 unsigned xgetgid(char *name) 685 { 686 struct group *gr = getgrnam(name); 687 char *s = 0; 688 long gid; 689 690 if (gr) return gr->gr_gid; 691 692 gid = estrtol(name, &s, 10); 693 if (!errno && s && !*s && gid>=0 && gid<=UINT_MAX) return gid; 694 695 error_exit("bad group '%s'", name); 696 } 697 698 struct passwd *xgetpwnam(char *name) 699 { 700 struct passwd *up = getpwnam(name); 701 702 if (!up) perror_exit("user '%s'", name); 703 return up; 704 } 705 706 struct group *xgetgrnam(char *name) 707 { 708 struct group *gr = getgrnam(name); 709 710 if (!gr) perror_exit("group '%s'", name); 711 return gr; 712 } 713 714 // setuid() can fail (for example, too many processes belonging to that user), 715 // which opens a security hole if the process continues as the original user. 716 717 void xsetuser(struct passwd *pwd) 718 { 719 if (initgroups(pwd->pw_name, pwd->pw_gid) || setgid(pwd->pw_uid) 720 || setuid(pwd->pw_uid)) perror_exit("xsetuser '%s'", pwd->pw_name); 721 } 722 723 // This can return null (meaning file not found). It just won't return null 724 // for memory allocation reasons. 725 char *xreadlink(char *name) 726 { 727 int len, size = 0; 728 char *buf = 0; 729 730 // Grow by 64 byte chunks until it's big enough. 731 for(;;) { 732 size +=64; 733 buf = xrealloc(buf, size); 734 len = readlink(name, buf, size); 735 736 if (len<0) { 737 free(buf); 738 return 0; 739 } 740 if (len<size) { 741 buf[len]=0; 742 return buf; 743 } 744 } 745 } 746 747 char *xreadfile(char *name, char *buf, off_t len) 748 { 749 if (!(buf = readfile(name, buf, len))) perror_exit("Bad '%s'", name); 750 751 return buf; 752 } 753 754 // The data argument to ioctl() is actually long, but it's usually used as 755 // a pointer. If you need to feed in a number, do (void *)(long) typecast. 756 int xioctl(int fd, int request, void *data) 757 { 758 int rc; 759 760 errno = 0; 761 rc = ioctl(fd, request, data); 762 if (rc == -1 && errno) perror_exit("ioctl %x", request); 763 764 return rc; 765 } 766 767 // Open a /var/run/NAME.pid file, dying if we can't write it or if it currently 768 // exists and is this executable. 769 void xpidfile(char *name) 770 { 771 char pidfile[256], spid[32]; 772 int i, fd; 773 pid_t pid; 774 775 sprintf(pidfile, "/var/run/%s.pid", name); 776 // Try three times to open the sucker. 777 for (i=0; i<3; i++) { 778 fd = open(pidfile, O_CREAT|O_EXCL|O_WRONLY, 0644); 779 if (fd != -1) break; 780 781 // If it already existed, read it. Loop for race condition. 782 fd = open(pidfile, O_RDONLY); 783 if (fd == -1) continue; 784 785 // Is the old program still there? 786 spid[xread(fd, spid, sizeof(spid)-1)] = 0; 787 close(fd); 788 pid = atoi(spid); 789 if (pid < 1 || (kill(pid, 0) && errno == ESRCH)) unlink(pidfile); 790 791 // An else with more sanity checking might be nice here. 792 } 793 794 if (i == 3) error_exit("xpidfile %s", name); 795 796 xwrite(fd, spid, sprintf(spid, "%ld\n", (long)getpid())); 797 close(fd); 798 } 799 800 // Return bytes copied from in to out. If bytes <0 copy all of in to out. 801 long long sendfile_len(int in, int out, long long bytes) 802 { 803 long long total = 0; 804 long len; 805 806 if (in<0) return 0; 807 for (;;) { 808 if (bytes == total) break; 809 len = bytes-total; 810 if (bytes<0 || len>sizeof(libbuf)) len = sizeof(libbuf); 811 812 len = xread(in, libbuf, len); 813 if (len<1) break; 814 xwrite(out, libbuf, len); 815 total += len; 816 } 817 818 return total; 819 } 820 821 // error_exit if we couldn't copy all bytes 822 long long xsendfile_len(int in, int out, long long bytes) 823 { 824 long long len = sendfile_len(in, out, bytes); 825 826 if (bytes != -1 && bytes != len) error_exit("short file"); 827 828 return len; 829 } 830 831 // warn and pad with zeroes if we couldn't copy all bytes 832 void xsendfile_pad(int in, int out, long long len) 833 { 834 len -= xsendfile_len(in, out, len); 835 if (len) { 836 perror_msg("short read"); 837 memset(libbuf, 0, sizeof(libbuf)); 838 while (len) { 839 int i = len>sizeof(libbuf) ? sizeof(libbuf) : len; 840 841 xwrite(out, libbuf, i); 842 len -= i; 843 } 844 } 845 } 846 847 // copy all of in to out 848 long long xsendfile(int in, int out) 849 { 850 return xsendfile_len(in, out, -1); 851 } 852 853 double xstrtod(char *s) 854 { 855 char *end; 856 double d; 857 858 errno = 0; 859 d = strtod(s, &end); 860 if (!errno && *end) errno = E2BIG; 861 if (errno) perror_exit("strtod %s", s); 862 863 return d; 864 } 865 866 // parse fractional seconds with optional s/m/h/d suffix 867 long xparsetime(char *arg, long zeroes, long *fraction) 868 { 869 long l, fr = 0, mask = 1; 870 char *end; 871 872 if (*arg != '.' && !isdigit(*arg)) error_exit("Not a number '%s'", arg); 873 l = strtoul(arg, &end, 10); 874 if (*end == '.') { 875 end++; 876 while (zeroes--) { 877 fr *= 10; 878 mask *= 10; 879 if (isdigit(*end)) fr += *end++-'0'; 880 } 881 while (isdigit(*end)) end++; 882 } 883 884 // Parse suffix 885 if (*end) { 886 int ismhd[]={1,60,3600,86400}, i = stridx("smhd", *end); 887 888 if (i == -1 || *(end+1)) error_exit("Unknown suffix '%s'", end); 889 l *= ismhd[i]; 890 fr *= ismhd[i]; 891 l += fr/mask; 892 fr %= mask; 893 } 894 if (fraction) *fraction = fr; 895 896 return l; 897 } 898 899 long long xparsemillitime(char *arg) 900 { 901 long l, ll; 902 903 l = xparsetime(arg, 3, &ll); 904 905 return (l*1000LL)+ll; 906 } 907 908 909 910 // Compile a regular expression into a regex_t 911 void xregcomp(regex_t *preg, char *regex, int cflags) 912 { 913 int rc = regcomp(preg, regex, cflags); 914 915 if (rc) { 916 regerror(rc, preg, libbuf, sizeof(libbuf)); 917 error_exit("xregcomp: %s", libbuf); 918 } 919 } 920 921 char *xtzset(char *new) 922 { 923 char *old = getenv("TZ"); 924 925 if (old) old = xstrdup(old); 926 if (new ? setenv("TZ", new, 1) : unsetenv("TZ")) perror_exit("setenv"); 927 tzset(); 928 929 return old; 930 } 931 932 // Set a signal handler 933 void xsignal_flags(int signal, void *handler, int flags) 934 { 935 struct sigaction *sa = (void *)libbuf; 936 937 memset(sa, 0, sizeof(struct sigaction)); 938 sa->sa_handler = handler; 939 sa->sa_flags = flags; 940 941 if (sigaction(signal, sa, 0)) perror_exit("xsignal %d", signal); 942 } 943 944 void xsignal(int signal, void *handler) 945 { 946 xsignal_flags(signal, handler, 0); 947 } 948 949 950 time_t xvali_date(struct tm *tm, char *str) 951 { 952 time_t t; 953 954 if (tm && (unsigned)tm->tm_sec<=60 && (unsigned)tm->tm_min<=59 955 && (unsigned)tm->tm_hour<=23 && tm->tm_mday && (unsigned)tm->tm_mday<=31 956 && (unsigned)tm->tm_mon<=11 && (t = mktime(tm)) != -1) return t; 957 958 error_exit("bad date %s", str); 959 } 960 961 // Parse date string (relative to current *t). Sets time_t and nanoseconds. 962 void xparsedate(char *str, time_t *t, unsigned *nano, int endian) 963 { 964 struct tm tm; 965 time_t now = *t; 966 int len = 0, i = 0; 967 // Formats with seconds come first. Posix can't agree on whether 12 digits 968 // has year before (touch -t) or year after (date), so support both. 969 char *s = str, *p, *oldtz = 0, *formats[] = {"%Y-%m-%d %T", "%Y-%m-%dT%T", 970 "%H:%M:%S", "%Y-%m-%d %H:%M", "%Y-%m-%d", "%H:%M", "%m%d%H%M", 971 endian ? "%m%d%H%M%y" : "%y%m%d%H%M", 972 endian ? "%m%d%H%M%C%y" : "%C%y%m%d%H%M"}; 973 974 *nano = 0; 975 976 // Parse @UNIXTIME[.FRACTION] 977 if (*str == '@') { 978 long long ll; 979 980 // Collect seconds and nanoseconds. 981 // &ll is not just t because we can't guarantee time_t is 64 bit (yet). 982 sscanf(s, "@%lld%n", &ll, &len); 983 if (s[len]=='.') { 984 s += len+1; 985 for (len = 0; len<9; len++) { 986 *nano *= 10; 987 if (isdigit(*s)) *nano += *s++-'0'; 988 } 989 } 990 *t = ll; 991 if (!s[len]) return; 992 xvali_date(0, str); 993 } 994 995 // Trailing Z means UTC timezone, don't expect libc to know this. 996 // (Trimming it off here means it won't show up in error messages.) 997 if ((i = strlen(str)) && toupper(str[i-1])=='Z') { 998 str[--i] = 0; 999 oldtz = getenv("TZ"); 1000 if (oldtz) oldtz = xstrdup(oldtz); 1001 setenv("TZ", "UTC0", 1); 1002 } 1003 1004 // Try each format 1005 for (i = 0; i<ARRAY_LEN(formats); i++) { 1006 localtime_r(&now, &tm); 1007 tm.tm_hour = tm.tm_min = tm.tm_sec = 0; 1008 tm.tm_isdst = -endian; 1009 1010 if ((p = strptime(s, formats[i], &tm))) { 1011 if (*p == '.') { 1012 p++; 1013 // If format didn't already specify seconds, grab seconds 1014 if (i>2) { 1015 len = 0; 1016 sscanf(p, "%2u%n", &tm.tm_sec, &len); 1017 p += len; 1018 } 1019 // nanoseconds 1020 for (len = 0; len<9; len++) { 1021 *nano *= 10; 1022 if (isdigit(*p)) *nano += *p++-'0'; 1023 } 1024 } 1025 1026 if (!*p) break; 1027 } 1028 } 1029 1030 // Sanity check field ranges 1031 *t = xvali_date((i!=ARRAY_LEN(formats)) ? &tm : 0, str); 1032 1033 if (oldtz) setenv("TZ", oldtz, 1); 1034 free(oldtz); 1035 } 1036