2 Copyright (c) 2001-2006, Gerrit Pape
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 1. Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 /* Busyboxed by Denis Vlasenko <vda.linux@googlemail.com> */
29 /* Collected into one file from runit's many tiny files */
30 /* TODO: review, eliminate unneeded stuff, move good stuff to libbb */
35 #include "runit_lib.h"
39 unsigned byte_chr(char *s,unsigned n,int c)
60 return fcntl(fd,F_SETFD,FD_CLOEXEC);
66 int fd_copy(int to,int from)
70 if (fcntl(from,F_GETFL,0) == -1)
73 if (fcntl(from,F_DUPFD,to) == -1)
81 int fd_move(int to,int from)
85 if (fd_copy(to,from) == -1)
94 void fmt_ptime30nul(char *s, struct taia *ta) {
98 if (ta->sec.x < 4611686018427387914ULL)
99 return; /* impossible? */
100 u = ta->sec.x -4611686018427387914ULL;
101 t = gmtime((time_t*)&u);
104 //fmt_ulong(s, 1900 + t->tm_year);
105 //s[4] = '-'; fmt_uint0(&s[5], t->tm_mon+1, 2);
106 //s[7] = '-'; fmt_uint0(&s[8], t->tm_mday, 2);
107 //s[10] = '_'; fmt_uint0(&s[11], t->tm_hour, 2);
108 //s[13] = ':'; fmt_uint0(&s[14], t->tm_min, 2);
109 //s[16] = ':'; fmt_uint0(&s[17], t->tm_sec, 2);
110 //s[19] = '.'; fmt_uint0(&s[20], ta->nano, 9);
111 sprintf(s, "%04u-%02u-%02u_%02u:%02u:%02u.%09u",
112 (unsigned)(1900 + t->tm_year),
113 (unsigned)(t->tm_mon+1),
114 (unsigned)(t->tm_mday),
115 (unsigned)(t->tm_hour),
116 (unsigned)(t->tm_min),
117 (unsigned)(t->tm_sec),
120 /* 4+1 + 2+1 + 2+1 + 2+1 + 2+1 + 2+1 + 9 = */
121 /* 5 + 3 + 3 + 3 + 3 + 3 + 9 = */
122 /* 20 (up to '.' inclusive) + 9 (not including '\0') */
126 unsigned fmt_taia25(char *s, struct taia *t) {
127 static char pack[TAIA_PACK];
131 bin2hex(s, pack, 12);
138 static /* as it isn't used anywhere else */
139 void tai_pack(char *s,const struct tai *t)
144 s[7] = x & 255; x >>= 8;
145 s[6] = x & 255; x >>= 8;
146 s[5] = x & 255; x >>= 8;
147 s[4] = x & 255; x >>= 8;
148 s[3] = x & 255; x >>= 8;
149 s[2] = x & 255; x >>= 8;
150 s[1] = x & 255; x >>= 8;
158 void tai_sub(struct tai *t, const struct tai *u, const struct tai *v)
165 /*** tai_unpack.c ***/
167 void tai_unpack(const char *s,struct tai *t)
171 x = (unsigned char) s[0];
172 x <<= 8; x += (unsigned char) s[1];
173 x <<= 8; x += (unsigned char) s[2];
174 x <<= 8; x += (unsigned char) s[3];
175 x <<= 8; x += (unsigned char) s[4];
176 x <<= 8; x += (unsigned char) s[5];
177 x <<= 8; x += (unsigned char) s[6];
178 x <<= 8; x += (unsigned char) s[7];
185 void taia_add(struct taia *t,const struct taia *u,const struct taia *v)
187 t->sec.x = u->sec.x + v->sec.x;
188 t->nano = u->nano + v->nano;
189 t->atto = u->atto + v->atto;
190 if (t->atto > 999999999UL) {
191 t->atto -= 1000000000UL;
194 if (t->nano > 999999999UL) {
195 t->nano -= 1000000000UL;
201 /*** taia_less.c ***/
203 int taia_less(const struct taia *t, const struct taia *u)
205 if (t->sec.x < u->sec.x) return 1;
206 if (t->sec.x > u->sec.x) return 0;
207 if (t->nano < u->nano) return 1;
208 if (t->nano > u->nano) return 0;
209 return t->atto < u->atto;
215 void taia_now(struct taia *t)
218 gettimeofday(&now, NULL);
219 tai_unix(&t->sec, now.tv_sec);
220 t->nano = 1000 * now.tv_usec + 500;
225 /*** taia_pack.c ***/
227 void taia_pack(char *s, const struct taia *t)
231 tai_pack(s, &t->sec);
235 s[7] = x & 255; x >>= 8;
236 s[6] = x & 255; x >>= 8;
237 s[5] = x & 255; x >>= 8;
240 s[3] = x & 255; x >>= 8;
241 s[2] = x & 255; x >>= 8;
242 s[1] = x & 255; x >>= 8;
249 void taia_sub(struct taia *t, const struct taia *u, const struct taia *v)
251 unsigned long unano = u->nano;
252 unsigned long uatto = u->atto;
254 t->sec.x = u->sec.x - v->sec.x;
255 t->nano = unano - v->nano;
256 t->atto = uatto - v->atto;
257 if (t->atto > uatto) {
258 t->atto += 1000000000UL;
261 if (t->nano > unano) {
262 t->nano += 1000000000UL;
268 /*** taia_uint.c ***/
270 /* XXX: breaks tai encapsulation */
272 void taia_uint(struct taia *t, unsigned s)
283 uint64_t taia2millisec(const struct taia *t)
285 return (t->sec.x * 1000) + (t->nano / 1000000);
289 void iopause(iopause_fd *x,unsigned len,struct taia *deadline,struct taia *stamp)
294 if (taia_less(deadline,stamp))
300 taia_sub(&t, deadline, &t);
301 millisecs = m = taia2millisec(&t);
302 if (m > 1000) millisecs = 1000;
306 for (i = 0; i < len; ++i)
309 poll(x, len, millisecs);
310 /* XXX: some kernels apparently need x[0] even if len is 0 */
311 /* XXX: how to handle EAGAIN? are kernels really this dumb? */
312 /* XXX: how to handle EINVAL? when exactly can this happen? */
320 return flock(fd,LOCK_EX);
324 /*** lock_exnb.c ***/
326 int lock_exnb(int fd)
328 return flock(fd,LOCK_EX | LOCK_NB);
332 /*** open_append.c ***/
334 int open_append(const char *fn)
336 return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
340 /*** open_read.c ***/
342 int open_read(const char *fn)
344 return open(fn, O_RDONLY|O_NDELAY);
348 /*** open_trunc.c ***/
350 int open_trunc(const char *fn)
352 return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);
356 /*** open_write.c ***/
358 int open_write(const char *fn)
360 return open(fn, O_WRONLY|O_NDELAY);
366 unsigned pmatch(const char *p, const char *s, unsigned len) {
372 if (!(c = *p)) return 1;
380 if ((c = *p++) != *s) return 0;
390 if (*s != '?') return 0;
398 if (*s != c) return 0;
410 int seek_set(int fd,seek_pos pos)
412 if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; return 0;
417 /*** sig_block.c ***/
419 void sig_block(int sig)
424 sigprocmask(SIG_BLOCK, &ss, NULL);
427 void sig_unblock(int sig)
432 sigprocmask(SIG_UNBLOCK, &ss, NULL);
435 void sig_blocknone(void)
439 sigprocmask(SIG_SETMASK, &ss, NULL);
443 /*** sig_catch.c ***/
445 void sig_catch(int sig,void (*f)(int))
450 sigemptyset(&sa.sa_mask);
451 sigaction(sig,&sa, NULL);
455 /*** sig_pause.c ***/
467 unsigned str_chr(const char *s,int c)
483 /*** wait_nohang.c ***/
485 int wait_nohang(int *wstat)
487 return waitpid(-1, wstat, WNOHANG);
493 int wait_pid(int *wstat, int pid)
498 r = waitpid(pid, wstat, 0);
499 while ((r == -1) && (errno == EINTR));