blob: 4762096b4df66b16eab47f2411d20a007e948858 [file] [log] [blame]
Denis Vlasenko83ea6432006-11-16 02:27:24 +00001/*
2Copyright (c) 2001-2006, Gerrit Pape
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7
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.
15
16THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
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 */
31
32#include <sys/poll.h>
33#include <sys/file.h>
34#include "libbb.h"
35#include "runit_lib.h"
36
Denis Vlasenko83ea6432006-11-16 02:27:24 +000037/*** byte_chr.c ***/
38
39unsigned byte_chr(char *s,unsigned n,int c)
40{
41 char ch;
42 char *t;
43
44 ch = c;
45 t = s;
46 for (;;) {
Denis Vlasenko8c783952007-01-27 22:21:52 +000047 if (!n) break;
48 if (*t == ch) break;
49 ++t;
50 --n;
Denis Vlasenko83ea6432006-11-16 02:27:24 +000051 }
52 return t - s;
53}
54
55
56/*** coe.c ***/
57
58int coe(int fd)
59{
60 return fcntl(fd,F_SETFD,FD_CLOEXEC);
61}
62
63
Denis Vlasenko83ea6432006-11-16 02:27:24 +000064/*** fmt_ptime.c ***/
65
Denis Vlasenko8c783952007-01-27 22:21:52 +000066void fmt_ptime30nul(char *s, struct taia *ta) {
Denis Vlasenko83ea6432006-11-16 02:27:24 +000067 struct tm *t;
68 unsigned long u;
69
Denis Vlasenko8c783952007-01-27 22:21:52 +000070 if (ta->sec.x < 4611686018427387914ULL)
71 return; /* impossible? */
Denis Vlasenko83ea6432006-11-16 02:27:24 +000072 u = ta->sec.x -4611686018427387914ULL;
Denis Vlasenko8c783952007-01-27 22:21:52 +000073 t = gmtime((time_t*)&u);
74 if (!t)
75 return; /* huh? */
76 //fmt_ulong(s, 1900 + t->tm_year);
77 //s[4] = '-'; fmt_uint0(&s[5], t->tm_mon+1, 2);
78 //s[7] = '-'; fmt_uint0(&s[8], t->tm_mday, 2);
79 //s[10] = '_'; fmt_uint0(&s[11], t->tm_hour, 2);
80 //s[13] = ':'; fmt_uint0(&s[14], t->tm_min, 2);
81 //s[16] = ':'; fmt_uint0(&s[17], t->tm_sec, 2);
82 //s[19] = '.'; fmt_uint0(&s[20], ta->nano, 9);
83 sprintf(s, "%04u-%02u-%02u_%02u:%02u:%02u.%09u",
84 (unsigned)(1900 + t->tm_year),
85 (unsigned)(t->tm_mon+1),
86 (unsigned)(t->tm_mday),
87 (unsigned)(t->tm_hour),
88 (unsigned)(t->tm_min),
89 (unsigned)(t->tm_sec),
90 (unsigned)(ta->nano)
91 );
92 /* 4+1 + 2+1 + 2+1 + 2+1 + 2+1 + 2+1 + 9 = */
93 /* 5 + 3 + 3 + 3 + 3 + 3 + 9 = */
94 /* 20 (up to '.' inclusive) + 9 (not including '\0') */
Denis Vlasenko83ea6432006-11-16 02:27:24 +000095}
96
Denis Vlasenko8c783952007-01-27 22:21:52 +000097unsigned fmt_taia25(char *s, struct taia *t) {
Denis Vlasenko83ea6432006-11-16 02:27:24 +000098 static char pack[TAIA_PACK];
Denis Vlasenko83ea6432006-11-16 02:27:24 +000099
100 taia_pack(pack, t);
Denis Vlasenko3a34d0c2007-01-12 22:10:34 +0000101 *s++ = '@';
102 bin2hex(s, pack, 12);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000103 return 25;
104}
105
106
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000107/*** tai_pack.c ***/
108
Denis Vlasenko8c783952007-01-27 22:21:52 +0000109static /* as it isn't used anywhere else */
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000110void tai_pack(char *s,const struct tai *t)
111{
112 uint64_t x;
113
114 x = t->x;
115 s[7] = x & 255; x >>= 8;
116 s[6] = x & 255; x >>= 8;
117 s[5] = x & 255; x >>= 8;
118 s[4] = x & 255; x >>= 8;
119 s[3] = x & 255; x >>= 8;
120 s[2] = x & 255; x >>= 8;
121 s[1] = x & 255; x >>= 8;
122 s[0] = x;
123}
124
125
Denis Vlasenko8c783952007-01-27 22:21:52 +0000126#ifdef UNUSED
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000127/*** tai_sub.c ***/
128
Denis Vlasenko8c783952007-01-27 22:21:52 +0000129void tai_sub(struct tai *t, const struct tai *u, const struct tai *v)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000130{
131 t->x = u->x - v->x;
132}
Denis Vlasenko8c783952007-01-27 22:21:52 +0000133#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000134
135
136/*** tai_unpack.c ***/
137
138void tai_unpack(const char *s,struct tai *t)
139{
140 uint64_t x;
141
142 x = (unsigned char) s[0];
143 x <<= 8; x += (unsigned char) s[1];
144 x <<= 8; x += (unsigned char) s[2];
145 x <<= 8; x += (unsigned char) s[3];
146 x <<= 8; x += (unsigned char) s[4];
147 x <<= 8; x += (unsigned char) s[5];
148 x <<= 8; x += (unsigned char) s[6];
149 x <<= 8; x += (unsigned char) s[7];
150 t->x = x;
151}
152
153
154/*** taia_add.c ***/
155
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000156void taia_add(struct taia *t,const struct taia *u,const struct taia *v)
157{
158 t->sec.x = u->sec.x + v->sec.x;
159 t->nano = u->nano + v->nano;
160 t->atto = u->atto + v->atto;
161 if (t->atto > 999999999UL) {
162 t->atto -= 1000000000UL;
163 ++t->nano;
164 }
165 if (t->nano > 999999999UL) {
166 t->nano -= 1000000000UL;
167 ++t->sec.x;
168 }
169}
170
171
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000172/*** taia_less.c ***/
173
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000174int taia_less(const struct taia *t, const struct taia *u)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000175{
176 if (t->sec.x < u->sec.x) return 1;
177 if (t->sec.x > u->sec.x) return 0;
178 if (t->nano < u->nano) return 1;
179 if (t->nano > u->nano) return 0;
180 return t->atto < u->atto;
181}
182
183
184/*** taia_now.c ***/
185
186void taia_now(struct taia *t)
187{
188 struct timeval now;
Denis Vlasenko8c783952007-01-27 22:21:52 +0000189 gettimeofday(&now, NULL);
190 tai_unix(&t->sec, now.tv_sec);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000191 t->nano = 1000 * now.tv_usec + 500;
192 t->atto = 0;
193}
194
195
196/*** taia_pack.c ***/
197
Denis Vlasenko8c783952007-01-27 22:21:52 +0000198void taia_pack(char *s, const struct taia *t)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000199{
200 unsigned long x;
201
Denis Vlasenko8c783952007-01-27 22:21:52 +0000202 tai_pack(s, &t->sec);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000203 s += 8;
204
205 x = t->atto;
206 s[7] = x & 255; x >>= 8;
207 s[6] = x & 255; x >>= 8;
208 s[5] = x & 255; x >>= 8;
209 s[4] = x;
210 x = t->nano;
211 s[3] = x & 255; x >>= 8;
212 s[2] = x & 255; x >>= 8;
213 s[1] = x & 255; x >>= 8;
214 s[0] = x;
215}
216
217
218/*** taia_sub.c ***/
219
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000220void taia_sub(struct taia *t, const struct taia *u, const struct taia *v)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000221{
222 unsigned long unano = u->nano;
223 unsigned long uatto = u->atto;
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000224
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000225 t->sec.x = u->sec.x - v->sec.x;
226 t->nano = unano - v->nano;
227 t->atto = uatto - v->atto;
228 if (t->atto > uatto) {
229 t->atto += 1000000000UL;
230 --t->nano;
231 }
232 if (t->nano > unano) {
233 t->nano += 1000000000UL;
234 --t->sec.x;
235 }
236}
237
238
239/*** taia_uint.c ***/
240
241/* XXX: breaks tai encapsulation */
242
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000243void taia_uint(struct taia *t, unsigned s)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000244{
245 t->sec.x = s;
246 t->nano = 0;
247 t->atto = 0;
248}
249
250
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000251/*** iopause.c ***/
252
Denis Vlasenkobde74b62007-01-27 22:22:53 +0000253static
254uint64_t taia2millisec(const struct taia *t)
255{
256 return (t->sec.x * 1000) + (t->nano / 1000000);
257}
258
259
Denis Vlasenkoca549c52007-01-27 22:24:59 +0000260void iopause(iopause_fd *x, unsigned len, struct taia *deadline, struct taia *stamp)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000261{
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000262 int millisecs;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000263 int i;
264
Denis Vlasenkoca549c52007-01-27 22:24:59 +0000265 if (taia_less(deadline, stamp))
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000266 millisecs = 0;
267 else {
Denis Vlasenko8c783952007-01-27 22:21:52 +0000268 uint64_t m;
269 struct taia t;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000270 t = *stamp;
Denis Vlasenko8c783952007-01-27 22:21:52 +0000271 taia_sub(&t, deadline, &t);
272 millisecs = m = taia2millisec(&t);
273 if (m > 1000) millisecs = 1000;
274 millisecs += 20;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000275 }
276
Denis Vlasenko8c783952007-01-27 22:21:52 +0000277 for (i = 0; i < len; ++i)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000278 x[i].revents = 0;
279
Denis Vlasenko8c783952007-01-27 22:21:52 +0000280 poll(x, len, millisecs);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000281 /* XXX: some kernels apparently need x[0] even if len is 0 */
282 /* XXX: how to handle EAGAIN? are kernels really this dumb? */
283 /* XXX: how to handle EINVAL? when exactly can this happen? */
284}
285
286
287/*** lock_ex.c ***/
288
289int lock_ex(int fd)
290{
291 return flock(fd,LOCK_EX);
292}
293
294
295/*** lock_exnb.c ***/
296
297int lock_exnb(int fd)
298{
299 return flock(fd,LOCK_EX | LOCK_NB);
300}
301
302
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000303/*** open_append.c ***/
304
305int open_append(const char *fn)
306{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000307 return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000308}
309
310
311/*** open_read.c ***/
312
313int open_read(const char *fn)
314{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000315 return open(fn, O_RDONLY|O_NDELAY);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000316}
317
318
319/*** open_trunc.c ***/
320
321int open_trunc(const char *fn)
322{
323 return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);
324}
325
326
327/*** open_write.c ***/
328
329int open_write(const char *fn)
330{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000331 return open(fn, O_WRONLY|O_NDELAY);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000332}
333
334
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000335/*** pmatch.c ***/
336
337unsigned pmatch(const char *p, const char *s, unsigned len) {
338 for (;;) {
339 char c = *p++;
340 if (!c) return !len;
341 switch (c) {
342 case '*':
343 if (!(c = *p)) return 1;
344 for (;;) {
345 if (!len) return 0;
346 if (*s == c) break;
347 ++s; --len;
348 }
349 continue;
350 case '+':
351 if ((c = *p++) != *s) return 0;
352 for (;;) {
353 if (!len) return 1;
354 if (*s != c) break;
355 ++s; --len;
356 }
357 continue;
358 /*
359 case '?':
360 if (*p == '?') {
361 if (*s != '?') return 0;
362 ++p;
363 }
364 ++s; --len;
365 continue;
366 */
367 default:
368 if (!len) return 0;
369 if (*s != c) return 0;
370 ++s; --len;
371 continue;
372 }
373 }
374 return 0;
375}
376
377
Denis Vlasenko8c783952007-01-27 22:21:52 +0000378#ifdef UNUSED
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000379/*** seek_set.c ***/
380
381int seek_set(int fd,seek_pos pos)
382{
383 if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; return 0;
384}
Denis Vlasenko8c783952007-01-27 22:21:52 +0000385#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000386
387
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000388/*** sig_block.c ***/
389
390void sig_block(int sig)
391{
392 sigset_t ss;
393 sigemptyset(&ss);
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000394 sigaddset(&ss, sig);
395 sigprocmask(SIG_BLOCK, &ss, NULL);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000396}
397
398void sig_unblock(int sig)
399{
400 sigset_t ss;
401 sigemptyset(&ss);
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000402 sigaddset(&ss, sig);
403 sigprocmask(SIG_UNBLOCK, &ss, NULL);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000404}
405
406void sig_blocknone(void)
407{
408 sigset_t ss;
409 sigemptyset(&ss);
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000410 sigprocmask(SIG_SETMASK, &ss, NULL);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000411}
412
413
414/*** sig_catch.c ***/
415
416void sig_catch(int sig,void (*f)(int))
417{
418 struct sigaction sa;
419 sa.sa_handler = f;
420 sa.sa_flags = 0;
421 sigemptyset(&sa.sa_mask);
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000422 sigaction(sig,&sa, NULL);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000423}
424
425
426/*** sig_pause.c ***/
427
428void sig_pause(void)
429{
430 sigset_t ss;
431 sigemptyset(&ss);
432 sigsuspend(&ss);
433}
434
435
436/*** str_chr.c ***/
437
438unsigned str_chr(const char *s,int c)
439{
440 char ch;
441 const char *t;
442
443 ch = c;
444 t = s;
445 for (;;) {
Denis Vlasenko8c783952007-01-27 22:21:52 +0000446 if (!*t) break;
447 if (*t == ch) break;
448 ++t;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000449 }
450 return t - s;
451}
452
453
454/*** wait_nohang.c ***/
455
456int wait_nohang(int *wstat)
457{
Denis Vlasenko8c783952007-01-27 22:21:52 +0000458 return waitpid(-1, wstat, WNOHANG);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000459}
460
461
462/*** wait_pid.c ***/
463
464int wait_pid(int *wstat, int pid)
465{
466 int r;
467
468 do
Denis Vlasenko8c783952007-01-27 22:21:52 +0000469 r = waitpid(pid, wstat, 0);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000470 while ((r == -1) && (errno == EINTR));
471 return r;
472}