xwrap.c revision 46e8e1dcb3f616a675bf33c83531ee05a4dd8374
1d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley/* xwrap.c - wrappers around existing library functions. 2d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley * 3d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley * Functions with the x prefix are wrappers that either succeed or kill the 4d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley * program with an error message, but never return failure. They usually have 5d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley * the same arguments and return value as the function they wrap. 6d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley * 7d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley * Copyright 2006 Rob Landley <rob@landley.net> 8d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley */ 9d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 10d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley#include "toys.h" 11d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 12d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Strcpy with size checking: exit if there's not enough space for the string. 13d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xstrncpy(char *dest, char *src, size_t size) 14d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 15d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (strlen(src)+1 > size) error_exit("xstrcpy"); 16d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley strcpy(dest, src); 17d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 18d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 19d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xexit(void) 20d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 21d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (toys.rebound) longjmp(*toys.rebound, 1); 22d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley else exit(toys.exitval); 23d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 24d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 25d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can allocate memory. 26d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid *xmalloc(size_t size) 27d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 28d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley void *ret = malloc(size); 29d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (!ret) error_exit("xmalloc"); 30d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 31d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return ret; 32d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 33d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 34d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can allocate prezeroed memory. 35d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid *xzalloc(size_t size) 36d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 37d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley void *ret = xmalloc(size); 38d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley memset(ret, 0, size); 39d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return ret; 40d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 41d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 42d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can change the size of an existing allocation, possibly 43d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// moving it. (Notice different arguments from libc function.) 44d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid *xrealloc(void *ptr, size_t size) 45d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 46d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley ptr = realloc(ptr, size); 47d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (!ptr) error_exit("xrealloc"); 48d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 49d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return ptr; 50d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 51d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 52d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can allocate a copy of this many bytes of string. 53d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleychar *xstrndup(char *s, size_t n) 54d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 55d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char *ret = xmalloc(++n); 56d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley strncpy(ret, s, n); 57d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley ret[--n]=0; 58d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 59d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return ret; 60d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 61d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 62d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can allocate a copy of this string. 63d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleychar *xstrdup(char *s) 64d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 65d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return xstrndup(s, strlen(s)); 66d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 67d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 68d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can allocate enough space to sprintf() into. 69d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleychar *xmsprintf(char *format, ...) 70d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 71d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley va_list va, va2; 72d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley int len; 73d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char *ret; 74d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 75d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley va_start(va, format); 76d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley va_copy(va2, va); 77d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 78d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // How long is it? 79d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley len = vsnprintf(0, 0, format, va); 80d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley len++; 81d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley va_end(va); 82d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 83d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Allocate and do the sprintf() 84d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley ret = xmalloc(len); 85d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley vsnprintf(ret, len, format, va2); 86d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley va_end(va2); 87d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 88d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return ret; 89d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 90d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 91d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xprintf(char *format, ...) 92d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 93d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley va_list va; 94d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley va_start(va, format); 95d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 96d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley vprintf(format, va); 97d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (ferror(stdout)) perror_exit("write"); 98d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 99d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 100d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xputs(char *s) 101d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 102d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (EOF == puts(s) || fflush(stdout)) perror_exit("write"); 103d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 104d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 105d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xputc(char c) 106d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 107d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (EOF == fputc(c, stdout) || fflush(stdout)) perror_exit("write"); 108d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 109d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 110d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xflush(void) 111d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 112d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (fflush(stdout)) perror_exit("write");; 113d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 114d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 11572756670274dac9562b869761c50c59ed57b7295Rob Landley// Call xexec with a chunk of optargs, starting at skip. (You can't just 11672756670274dac9562b869761c50c59ed57b7295Rob Landley// call xexec() directly because toy_init() frees optargs.) 11772756670274dac9562b869761c50c59ed57b7295Rob Landleyvoid xexec_optargs(int skip) 11872756670274dac9562b869761c50c59ed57b7295Rob Landley{ 11972756670274dac9562b869761c50c59ed57b7295Rob Landley char **s = toys.optargs; 12072756670274dac9562b869761c50c59ed57b7295Rob Landley 12172756670274dac9562b869761c50c59ed57b7295Rob Landley toys.optargs = 0; 12272756670274dac9562b869761c50c59ed57b7295Rob Landley xexec(s+skip); 12372756670274dac9562b869761c50c59ed57b7295Rob Landley} 12472756670274dac9562b869761c50c59ed57b7295Rob Landley 12572756670274dac9562b869761c50c59ed57b7295Rob Landley 126d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can exec argv[] (or run builtin command). Note that anything 127d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// with a path isn't a builtin, so /bin/sh won't match the builtin sh. 128d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xexec(char **argv) 129d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 130d04dc1feb92a279e27e4487c502944f454d43837Rob Landley if (CFG_TOYBOX) toy_exec(argv); 131d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley execvp(argv[0], argv); 132d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 133d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley perror_exit("exec %s", argv[0]); 134d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 135d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 136d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xaccess(char *path, int flags) 137d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 138d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (access(path, flags)) perror_exit("Can't access '%s'", path); 139d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 140d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 141d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can delete a file. (File must exist to be deleted.) 142d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xunlink(char *path) 143d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 144d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (unlink(path)) perror_exit("unlink '%s'", path); 145d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 146d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 147d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can open/create a file, returning file descriptor. 148d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyint xcreate(char *path, int flags, int mode) 149d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 150d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley int fd = open(path, flags, mode); 151d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (fd == -1) perror_exit("%s", path); 152d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return fd; 153d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 154d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 155d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can open a file, returning file descriptor. 156d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyint xopen(char *path, int flags) 157d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 158d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return xcreate(path, flags, 0); 159d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 160d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 161d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xclose(int fd) 162d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 163d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (close(fd)) perror_exit("xclose"); 164d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 165d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 166d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyint xdup(int fd) 167d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 168d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (fd != -1) { 169d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley fd = dup(fd); 170d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (fd == -1) perror_exit("xdup"); 171d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 172d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return fd; 173d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 174d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 1751aa75118c46c8fbe0eeead18974d25e5f13274d5Rob LandleyFILE *xfdopen(int fd, char *mode) 1761aa75118c46c8fbe0eeead18974d25e5f13274d5Rob Landley{ 1771aa75118c46c8fbe0eeead18974d25e5f13274d5Rob Landley FILE *f = fdopen(fd, mode); 1781aa75118c46c8fbe0eeead18974d25e5f13274d5Rob Landley 1791aa75118c46c8fbe0eeead18974d25e5f13274d5Rob Landley if (!f) perror_exit("xfdopen"); 1801aa75118c46c8fbe0eeead18974d25e5f13274d5Rob Landley 1811aa75118c46c8fbe0eeead18974d25e5f13274d5Rob Landley return f; 1821aa75118c46c8fbe0eeead18974d25e5f13274d5Rob Landley} 1831aa75118c46c8fbe0eeead18974d25e5f13274d5Rob Landley 184d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die unless we can open/create a file, returning FILE *. 185d390493d76c4cda76c1c6d21897b0f246857e588Rob LandleyFILE *xfopen(char *path, char *mode) 186d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 187d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley FILE *f = fopen(path, mode); 188d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (!f) perror_exit("No file %s", path); 189d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return f; 190d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 191d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 192d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die if there's an error other than EOF. 193d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleysize_t xread(int fd, void *buf, size_t len) 194d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 195d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley ssize_t ret = read(fd, buf, len); 196d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (ret < 0) perror_exit("xread"); 197d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 198d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return ret; 199d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 200d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 201d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xreadall(int fd, void *buf, size_t len) 202d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 203d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (len != readall(fd, buf, len)) perror_exit("xreadall"); 204d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 205d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 206d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// There's no xwriteall(), just xwrite(). When we read, there may or may not 207d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// be more data waiting. When we write, there is data and it had better go 208d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// somewhere. 209d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 210d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xwrite(int fd, void *buf, size_t len) 211d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 212d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (len != writeall(fd, buf, len)) perror_exit("xwrite"); 213d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 214d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 215d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Die if lseek fails, probably due to being called on a pipe. 216d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 217d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyoff_t xlseek(int fd, off_t offset, int whence) 218d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 219d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley offset = lseek(fd, offset, whence); 220d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (offset<0) perror_exit("lseek"); 221d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 222d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return offset; 223d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 224d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 225d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleychar *xgetcwd(void) 226d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 227d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char *buf = getcwd(NULL, 0); 228d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (!buf) perror_exit("xgetcwd"); 229d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 230d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return buf; 231d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 232d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 233d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xstat(char *path, struct stat *st) 234d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 235d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if(stat(path, st)) perror_exit("Can't stat %s", path); 236d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 237d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 238d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Cannonicalize path, even to file with one or more missing components at end. 239d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// if exact, require last path component to exist 240d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleychar *xabspath(char *path, int exact) 241d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 242d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley struct string_list *todo, *done = 0; 243d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley int try = 9999, dirfd = open("/", 0);; 244d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char buf[4096], *ret; 245d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 246d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // If this isn't an absolute path, start with cwd. 247d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (*path != '/') { 248d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char *temp = xgetcwd(); 249d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 250d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley splitpath(path, splitpath(temp, &todo)); 251d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley free(temp); 252d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } else splitpath(path, &todo); 253d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 254d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Iterate through path components 255d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley while (todo) { 256d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley struct string_list *new = llist_pop(&todo), **tail; 257d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley ssize_t len; 258d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 259d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (!try--) { 260d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley errno = ELOOP; 261d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley goto error; 262d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 263d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 264d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Removable path componenents. 265d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (!strcmp(new->str, ".") || !strcmp(new->str, "..")) { 266d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley int x = new->str[1]; 267d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 268d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley free(new); 269d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (x) { 270d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (done) free(llist_pop(&done)); 271d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley len = 0; 272d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } else continue; 273d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 274d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Is this a symlink? 275d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } else len=readlinkat(dirfd, new->str, buf, 4096); 276d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 277d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (len>4095) goto error; 278d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (len<1) { 279d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley int fd; 280d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char *s = ".."; 281d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 282d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // For .. just move dirfd 283d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (len) { 284d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Not a symlink: add to linked list, move dirfd, fail if error 285d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if ((exact || todo) && errno != EINVAL) goto error; 286d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley new->next = done; 287d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley done = new; 288d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (errno == EINVAL && !todo) break; 289d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley s = new->str; 290d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 291d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley fd = openat(dirfd, s, 0); 292d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (fd == -1 && (exact || todo || errno != ENOENT)) goto error; 293d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley close(dirfd); 294d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley dirfd = fd; 295d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley continue; 296d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 297d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 298d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // If this symlink is to an absolute path, discard existing resolved path 299d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley buf[len] = 0; 300d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (*buf == '/') { 301d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley llist_traverse(done, free); 302d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley done=0; 303d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley close(dirfd); 304d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley dirfd = open("/", 0); 305d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 306d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley free(new); 307d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 308d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // prepend components of new path. Note symlink to "/" will leave new NULL 309d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley tail = splitpath(buf, &new); 310d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 311d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // symlink to "/" will return null and leave tail alone 312d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (new) { 313d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley *tail = todo; 314d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley todo = new; 315d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 316d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 317d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley close(dirfd); 318d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 319d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // At this point done has the path, in reverse order. Reverse list while 320d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // calculating buffer length. 321d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 322d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley try = 2; 323d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley while (done) { 324d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley struct string_list *temp = llist_pop(&done);; 325d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 326d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (todo) try++; 327d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley try += strlen(temp->str); 328d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley temp->next = todo; 329d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley todo = temp; 330d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 331d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 332d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Assemble return buffer 333d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 334d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley ret = xmalloc(try); 335d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley *ret = '/'; 336d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley ret [try = 1] = 0; 337d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley while (todo) { 338d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (try>1) ret[try++] = '/'; 339d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley try = stpcpy(ret+try, todo->str) - ret; 340d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley free(llist_pop(&todo)); 341d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 342d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 343d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return ret; 344d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 345d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyerror: 346d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley close(dirfd); 347d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley llist_traverse(todo, free); 348d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley llist_traverse(done, free); 349d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 350d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return NULL; 351d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 352d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 353d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Resolve all symlinks, returning malloc() memory. 354d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleychar *xrealpath(char *path) 355d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 356d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char *new = realpath(path, NULL); 357d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (!new) perror_exit("realpath '%s'", path); 358d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return new; 359d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 360d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 361d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xchdir(char *path) 362d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 363d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (chdir(path)) error_exit("chdir '%s'", path); 364d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 365d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 366d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Ensure entire path exists. 367d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// If mode != -1 set permissions on newly created dirs. 368d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Requires that path string be writable (for temporary null terminators). 369d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xmkpath(char *path, int mode) 370d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 371d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char *p, old; 372d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley mode_t mask; 373d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley int rc; 374d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley struct stat st; 375d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 376d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley for (p = path; ; p++) { 377d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (!*p || *p == '/') { 378d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley old = *p; 379d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley *p = rc = 0; 380d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (stat(path, &st) || !S_ISDIR(st.st_mode)) { 381d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (mode != -1) { 382d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley mask=umask(0); 383d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley rc = mkdir(path, mode); 384d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley umask(mask); 385d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } else rc = mkdir(path, 0777); 386d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 387d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley *p = old; 388d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if(rc) perror_exit("mkpath '%s'", path); 389d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 390d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (!*p) break; 391d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 392d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 393d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 394d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// setuid() can fail (for example, too many processes belonging to that user), 395d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// which opens a security hole if the process continues as the original user. 396d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 397d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xsetuid(uid_t uid) 398d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 399d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (setuid(uid)) perror_exit("xsetuid"); 400d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 401d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 402d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// This can return null (meaning file not found). It just won't return null 403d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// for memory allocation reasons. 404d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleychar *xreadlink(char *name) 405d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 406d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley int len, size = 0; 407d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char *buf = 0; 408d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 409d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Grow by 64 byte chunks until it's big enough. 410d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley for(;;) { 411d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley size +=64; 412d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley buf = xrealloc(buf, size); 413d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley len = readlink(name, buf, size); 414d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 415d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (len<0) { 416d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley free(buf); 417d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return 0; 418d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 419d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (len<size) { 420d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley buf[len]=0; 421d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return buf; 422d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 423d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 424d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 425d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 426d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleychar *xreadfile(char *name) 427d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 4288fdcfdb4479dff7a993a25a63253f0e749fd99feRob Landley char *buf = readfile(name, 0, 0); 429d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (!buf) perror_exit("xreadfile %s", name); 430d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return buf; 431d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 432d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 433d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyint xioctl(int fd, int request, void *data) 434d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 435d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley int rc; 436d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 437d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley errno = 0; 438d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley rc = ioctl(fd, request, data); 439d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (rc == -1 && errno) perror_exit("ioctl %x", request); 440d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 441d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley return rc; 442d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 443d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 444d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Open a /var/run/NAME.pid file, dying if we can't write it or if it currently 445d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// exists and is this executable. 446d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xpidfile(char *name) 447d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 448d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char pidfile[256], spid[32]; 449d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley int i, fd; 450d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley pid_t pid; 451d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 452d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley sprintf(pidfile, "/var/run/%s.pid", name); 453d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Try three times to open the sucker. 454d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley for (i=0; i<3; i++) { 455dccfb2a9c156d03b6399120ae3dd4b23ff00b43fFelix Janda <felix.janda at fd = open(pidfile, O_CREAT|O_EXCL|O_WRONLY, 0644); 456d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (fd != -1) break; 457d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 458d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // If it already existed, read it. Loop for race condition. 459d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley fd = open(pidfile, O_RDONLY); 460d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (fd == -1) continue; 461d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 462d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // Is the old program still there? 463d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley spid[xread(fd, spid, sizeof(spid)-1)] = 0; 464d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley close(fd); 465d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley pid = atoi(spid); 46646e8e1dcb3f616a675bf33c83531ee05a4dd8374Rob Landley if (pid < 1 || (kill(pid, 0) && errno == ESRCH)) unlink(pidfile); 467d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 468d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley // An else with more sanity checking might be nice here. 469d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 470d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 471d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (i == 3) error_exit("xpidfile %s", name); 472d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 473d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley xwrite(fd, spid, sprintf(spid, "%ld\n", (long)getpid())); 474d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley close(fd); 475d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 476d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 477d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley// Copy the rest of in to out and close both files. 478d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 479d390493d76c4cda76c1c6d21897b0f246857e588Rob Landleyvoid xsendfile(int in, int out) 480d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley{ 481d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley long len; 482d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley char buf[4096]; 483d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley 484d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (in<0) return; 485d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley for (;;) { 486d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley len = xread(in, buf, 4096); 487d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley if (len<1) break; 488d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley xwrite(out, buf, len); 489d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley } 490d390493d76c4cda76c1c6d21897b0f246857e588Rob Landley} 49172756670274dac9562b869761c50c59ed57b7295Rob Landley 49272756670274dac9562b869761c50c59ed57b7295Rob Landley// parse fractional seconds with optional s/m/h/d suffix 49372756670274dac9562b869761c50c59ed57b7295Rob Landleylong xparsetime(char *arg, long units, long *fraction) 49472756670274dac9562b869761c50c59ed57b7295Rob Landley{ 49572756670274dac9562b869761c50c59ed57b7295Rob Landley double d; 49672756670274dac9562b869761c50c59ed57b7295Rob Landley long l; 49772756670274dac9562b869761c50c59ed57b7295Rob Landley 49872756670274dac9562b869761c50c59ed57b7295Rob Landley if (CFG_TOYBOX_FLOAT) d = strtod(arg, &arg); 49972756670274dac9562b869761c50c59ed57b7295Rob Landley else l = strtoul(arg, &arg, 10); 50072756670274dac9562b869761c50c59ed57b7295Rob Landley 50172756670274dac9562b869761c50c59ed57b7295Rob Landley // Parse suffix 50272756670274dac9562b869761c50c59ed57b7295Rob Landley if (*arg) { 50372756670274dac9562b869761c50c59ed57b7295Rob Landley int ismhd[]={1,60,3600,86400}, i = stridx("smhd", *arg); 50472756670274dac9562b869761c50c59ed57b7295Rob Landley 50572756670274dac9562b869761c50c59ed57b7295Rob Landley if (i == -1) error_exit("Unknown suffix '%c'", *arg); 50672756670274dac9562b869761c50c59ed57b7295Rob Landley if (CFG_TOYBOX_FLOAT) d *= ismhd[i]; 50772756670274dac9562b869761c50c59ed57b7295Rob Landley else l *= ismhd[i]; 50872756670274dac9562b869761c50c59ed57b7295Rob Landley } 50972756670274dac9562b869761c50c59ed57b7295Rob Landley 51072756670274dac9562b869761c50c59ed57b7295Rob Landley if (CFG_TOYBOX_FLOAT) { 51172756670274dac9562b869761c50c59ed57b7295Rob Landley l = (long)d; 51272756670274dac9562b869761c50c59ed57b7295Rob Landley if (fraction) *fraction = units*(d-l); 51372756670274dac9562b869761c50c59ed57b7295Rob Landley } else if (fraction) *fraction = 0; 51472756670274dac9562b869761c50c59ed57b7295Rob Landley 51572756670274dac9562b869761c50c59ed57b7295Rob Landley return l; 51672756670274dac9562b869761c50c59ed57b7295Rob Landley} 517