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') */
125 unsigned fmt_taia25(char *s, struct taia *t) {
126 static char pack[TAIA_PACK];
130 bin2hex(s, pack, 12);
137 static /* as it isn't used anywhere else */
138 void tai_pack(char *s,const struct tai *t)
143 s[7] = x & 255; x >>= 8;
144 s[6] = x & 255; x >>= 8;
145 s[5] = x & 255; x >>= 8;
146 s[4] = x & 255; x >>= 8;
147 s[3] = x & 255; x >>= 8;
148 s[2] = x & 255; x >>= 8;
149 s[1] = x & 255; x >>= 8;
157 void tai_sub(struct tai *t, const struct tai *u, const struct tai *v)
164 /*** tai_unpack.c ***/
166 void tai_unpack(const char *s,struct tai *t)
170 x = (unsigned char) s[0];
171 x <<= 8; x += (unsigned char) s[1];
172 x <<= 8; x += (unsigned char) s[2];
173 x <<= 8; x += (unsigned char) s[3];
174 x <<= 8; x += (unsigned char) s[4];
175 x <<= 8; x += (unsigned char) s[5];
176 x <<= 8; x += (unsigned char) s[6];
177 x <<= 8; x += (unsigned char) s[7];
184 void taia_add(struct taia *t,const struct taia *u,const struct taia *v)
186 t->sec.x = u->sec.x + v->sec.x;
187 t->nano = u->nano + v->nano;
188 t->atto = u->atto + v->atto;
189 if (t->atto > 999999999UL) {
190 t->atto -= 1000000000UL;
193 if (t->nano > 999999999UL) {
194 t->nano -= 1000000000UL;
200 /*** taia_less.c ***/
202 int taia_less(const struct taia *t, const struct taia *u)
204 if (t->sec.x < u->sec.x) return 1;
205 if (t->sec.x > u->sec.x) return 0;
206 if (t->nano < u->nano) return 1;
207 if (t->nano > u->nano) return 0;
208 return t->atto < u->atto;
214 void taia_now(struct taia *t)
217 gettimeofday(&now, NULL);
218 tai_unix(&t->sec, now.tv_sec);
219 t->nano = 1000 * now.tv_usec + 500;
224 /*** taia_pack.c ***/
226 void taia_pack(char *s, const struct taia *t)
230 tai_pack(s, &t->sec);
234 s[7] = x & 255; x >>= 8;
235 s[6] = x & 255; x >>= 8;
236 s[5] = x & 255; x >>= 8;
239 s[3] = x & 255; x >>= 8;
240 s[2] = x & 255; x >>= 8;
241 s[1] = x & 255; x >>= 8;
248 void taia_sub(struct taia *t, const struct taia *u, const struct taia *v)
250 unsigned long unano = u->nano;
251 unsigned long uatto = u->atto;
253 t->sec.x = u->sec.x - v->sec.x;
254 t->nano = unano - v->nano;
255 t->atto = uatto - v->atto;
256 if (t->atto > uatto) {
257 t->atto += 1000000000UL;
260 if (t->nano > unano) {
261 t->nano += 1000000000UL;
267 /*** taia_uint.c ***/
269 /* XXX: breaks tai encapsulation */
271 void taia_uint(struct taia *t, unsigned s)
282 uint64_t taia2millisec(const struct taia *t)
284 return (t->sec.x * 1000) + (t->nano / 1000000);
288 void iopause(iopause_fd *x, unsigned len, struct taia *deadline, struct taia *stamp)
293 if (taia_less(deadline, stamp))
299 taia_sub(&t, deadline, &t);
300 millisecs = m = taia2millisec(&t);
301 if (m > 1000) millisecs = 1000;
305 for (i = 0; i < len; ++i)
308 poll(x, len, millisecs);
309 /* XXX: some kernels apparently need x[0] even if len is 0 */
310 /* XXX: how to handle EAGAIN? are kernels really this dumb? */
311 /* XXX: how to handle EINVAL? when exactly can this happen? */
319 return flock(fd,LOCK_EX);
323 /*** lock_exnb.c ***/
325 int lock_exnb(int fd)
327 return flock(fd,LOCK_EX | LOCK_NB);
331 /*** open_append.c ***/
333 int open_append(const char *fn)
335 return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
339 /*** open_read.c ***/
341 int open_read(const char *fn)
343 return open(fn, O_RDONLY|O_NDELAY);
347 /*** open_trunc.c ***/
349 int open_trunc(const char *fn)
351 return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);
355 /*** open_write.c ***/
357 int open_write(const char *fn)
359 return open(fn, O_WRONLY|O_NDELAY);
365 unsigned pmatch(const char *p, const char *s, unsigned len) {
371 if (!(c = *p)) return 1;
379 if ((c = *p++) != *s) return 0;
389 if (*s != '?') return 0;
397 if (*s != c) return 0;
409 int seek_set(int fd,seek_pos pos)
411 if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; return 0;
416 /*** sig_block.c ***/
418 void sig_block(int sig)
423 sigprocmask(SIG_BLOCK, &ss, NULL);
426 void sig_unblock(int sig)
431 sigprocmask(SIG_UNBLOCK, &ss, NULL);
434 void sig_blocknone(void)
438 sigprocmask(SIG_SETMASK, &ss, NULL);
442 /*** sig_catch.c ***/
444 void sig_catch(int sig,void (*f)(int))
449 sigemptyset(&sa.sa_mask);
450 sigaction(sig,&sa, NULL);
454 /*** sig_pause.c ***/
466 unsigned str_chr(const char *s,int c)
482 /*** wait_nohang.c ***/
484 int wait_nohang(int *wstat)
486 return waitpid(-1, wstat, WNOHANG);
492 int wait_pid(int *wstat, int pid)
497 r = waitpid(pid, wstat, 0);
498 while ((r == -1) && (errno == EINTR));