0830314df59638d65c085d61a6879e18625c5faf
[platform/upstream/busybox.git] / runit / runit_lib.c
1 /*
2 Copyright (c) 2001-2006, Gerrit Pape
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, 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
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.
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
37 /*** byte_chr.c ***/
38
39 unsigned byte_chr(char *s,unsigned n,int c)
40 {
41         char ch;
42         char *t;
43
44         ch = c;
45         t = s;
46         for (;;) {
47                 if (!n) break;
48                 if (*t == ch) break;
49                 ++t;
50                 --n;
51         }
52         return t - s;
53 }
54
55
56 /*** coe.c ***/
57
58 int coe(int fd)
59 {
60         return fcntl(fd,F_SETFD,FD_CLOEXEC);
61 }
62
63
64 /*** fd_copy.c ***/
65
66 int fd_copy(int to,int from)
67 {
68         if (to == from)
69                 return 0;
70         if (fcntl(from,F_GETFL,0) == -1)
71                 return -1;
72         close(to);
73         if (fcntl(from,F_DUPFD,to) == -1)
74                 return -1;
75         return 0;
76 }
77
78
79 /*** fd_move.c ***/
80
81 int fd_move(int to,int from)
82 {
83         if (to == from)
84                 return 0;
85         if (fd_copy(to,from) == -1)
86                 return -1;
87         close(from);
88         return 0;
89 }
90
91
92 /*** fmt_ptime.c ***/
93
94 void fmt_ptime30nul(char *s, struct taia *ta) {
95         struct tm *t;
96         unsigned long u;
97
98         if (ta->sec.x < 4611686018427387914ULL)
99                 return; /* impossible? */
100         u = ta->sec.x -4611686018427387914ULL;
101         t = gmtime((time_t*)&u);
102         if (!t)
103                 return; /* huh? */
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),
118                 (unsigned)(ta->nano)
119         );
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') */
123 }
124
125 unsigned fmt_taia25(char *s, struct taia *t) {
126         static char pack[TAIA_PACK];
127
128         taia_pack(pack, t);
129         *s++ = '@';
130         bin2hex(s, pack, 12);
131         return 25;
132 }
133
134
135 /*** tai_pack.c ***/
136
137 static /* as it isn't used anywhere else */
138 void tai_pack(char *s,const struct tai *t)
139 {
140         uint64_t x;
141
142         x = t->x;
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;
150         s[0] = x;
151 }
152
153
154 #ifdef UNUSED
155 /*** tai_sub.c ***/
156
157 void tai_sub(struct tai *t, const struct tai *u, const struct tai *v)
158 {
159         t->x = u->x - v->x;
160 }
161 #endif
162
163
164 /*** tai_unpack.c ***/
165
166 void tai_unpack(const char *s,struct tai *t)
167 {
168         uint64_t x;
169
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];
178         t->x = x;
179 }
180
181
182 /*** taia_add.c ***/
183
184 void taia_add(struct taia *t,const struct taia *u,const struct taia *v)
185 {
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;
191                 ++t->nano;
192         }
193         if (t->nano > 999999999UL) {
194                 t->nano -= 1000000000UL;
195                 ++t->sec.x;
196         }
197 }
198
199
200 /*** taia_less.c ***/
201
202 int taia_less(const struct taia *t, const struct taia *u)
203 {
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;
209 }
210
211
212 /*** taia_now.c ***/
213
214 void taia_now(struct taia *t)
215 {
216         struct timeval now;
217         gettimeofday(&now, NULL);
218         tai_unix(&t->sec, now.tv_sec);
219         t->nano = 1000 * now.tv_usec + 500;
220         t->atto = 0;
221 }
222
223
224 /*** taia_pack.c ***/
225
226 void taia_pack(char *s, const struct taia *t)
227 {
228         unsigned long x;
229
230         tai_pack(s, &t->sec);
231         s += 8;
232
233         x = t->atto;
234         s[7] = x & 255; x >>= 8;
235         s[6] = x & 255; x >>= 8;
236         s[5] = x & 255; x >>= 8;
237         s[4] = x;
238         x = t->nano;
239         s[3] = x & 255; x >>= 8;
240         s[2] = x & 255; x >>= 8;
241         s[1] = x & 255; x >>= 8;
242         s[0] = x;
243 }
244
245
246 /*** taia_sub.c ***/
247
248 void taia_sub(struct taia *t, const struct taia *u, const struct taia *v)
249 {
250         unsigned long unano = u->nano;
251         unsigned long uatto = u->atto;
252
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;
258                 --t->nano;
259         }
260         if (t->nano > unano) {
261                 t->nano += 1000000000UL;
262                 --t->sec.x;
263         }
264 }
265
266
267 /*** taia_uint.c ***/
268
269 /* XXX: breaks tai encapsulation */
270
271 void taia_uint(struct taia *t, unsigned s)
272 {
273         t->sec.x = s;
274         t->nano = 0;
275         t->atto = 0;
276 }
277
278
279 /*** iopause.c ***/
280
281 static
282 uint64_t taia2millisec(const struct taia *t)
283 {
284         return (t->sec.x * 1000) + (t->nano / 1000000);
285 }
286
287
288 void iopause(iopause_fd *x, unsigned len, struct taia *deadline, struct taia *stamp)
289 {
290         int millisecs;
291         int i;
292
293         if (taia_less(deadline, stamp))
294                 millisecs = 0;
295         else {
296                 uint64_t m;
297                 struct taia t;
298                 t = *stamp;
299                 taia_sub(&t, deadline, &t);
300                 millisecs = m = taia2millisec(&t);
301                 if (m > 1000) millisecs = 1000;
302                 millisecs += 20;
303         }
304
305         for (i = 0; i < len; ++i)
306                 x[i].revents = 0;
307
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? */
312 }
313
314
315 /*** lock_ex.c ***/
316
317 int lock_ex(int fd)
318 {
319         return flock(fd,LOCK_EX);
320 }
321
322
323 /*** lock_exnb.c ***/
324
325 int lock_exnb(int fd)
326 {
327         return flock(fd,LOCK_EX | LOCK_NB);
328 }
329
330
331 /*** open_append.c ***/
332
333 int open_append(const char *fn)
334 {
335         return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
336 }
337
338
339 /*** open_read.c ***/
340
341 int open_read(const char *fn)
342 {
343         return open(fn, O_RDONLY|O_NDELAY);
344 }
345
346
347 /*** open_trunc.c ***/
348
349 int open_trunc(const char *fn)
350 {
351         return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);
352 }
353
354
355 /*** open_write.c ***/
356
357 int open_write(const char *fn)
358 {
359         return open(fn, O_WRONLY|O_NDELAY);
360 }
361
362
363 /*** pmatch.c ***/
364
365 unsigned pmatch(const char *p, const char *s, unsigned len) {
366         for (;;) {
367                 char c = *p++;
368                 if (!c) return !len;
369                 switch (c) {
370                 case '*':
371                         if (!(c = *p)) return 1;
372                         for (;;) {
373                                 if (!len) return 0;
374                                 if (*s == c) break;
375                                 ++s; --len;
376                         }
377                         continue;
378                 case '+':
379                         if ((c = *p++) != *s) return 0;
380                         for (;;) {
381                                 if (!len) return 1;
382                                 if (*s != c) break;
383                                 ++s; --len;
384                         }
385                         continue;
386                         /*
387                 case '?':
388                         if (*p == '?') {
389                                 if (*s != '?') return 0;
390                                 ++p;
391                         }
392                         ++s; --len;
393                         continue;
394                         */
395                 default:
396                         if (!len) return 0;
397                         if (*s != c) return 0;
398                         ++s; --len;
399                         continue;
400                 }
401         }
402         return 0;
403 }
404
405
406 #ifdef UNUSED
407 /*** seek_set.c ***/
408
409 int seek_set(int fd,seek_pos pos)
410 {
411         if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; return 0;
412 }
413 #endif
414
415
416 /*** sig_block.c ***/
417
418 void sig_block(int sig)
419 {
420         sigset_t ss;
421         sigemptyset(&ss);
422         sigaddset(&ss, sig);
423         sigprocmask(SIG_BLOCK, &ss, NULL);
424 }
425
426 void sig_unblock(int sig)
427 {
428         sigset_t ss;
429         sigemptyset(&ss);
430         sigaddset(&ss, sig);
431         sigprocmask(SIG_UNBLOCK, &ss, NULL);
432 }
433
434 void sig_blocknone(void)
435 {
436         sigset_t ss;
437         sigemptyset(&ss);
438         sigprocmask(SIG_SETMASK, &ss, NULL);
439 }
440
441
442 /*** sig_catch.c ***/
443
444 void sig_catch(int sig,void (*f)(int))
445 {
446         struct sigaction sa;
447         sa.sa_handler = f;
448         sa.sa_flags = 0;
449         sigemptyset(&sa.sa_mask);
450         sigaction(sig,&sa, NULL);
451 }
452
453
454 /*** sig_pause.c ***/
455
456 void sig_pause(void)
457 {
458         sigset_t ss;
459         sigemptyset(&ss);
460         sigsuspend(&ss);
461 }
462
463
464 /*** str_chr.c ***/
465
466 unsigned str_chr(const char *s,int c)
467 {
468         char ch;
469         const char *t;
470
471         ch = c;
472         t = s;
473         for (;;) {
474                 if (!*t) break;
475                 if (*t == ch) break;
476                 ++t;
477         }
478         return t - s;
479 }
480
481
482 /*** wait_nohang.c ***/
483
484 int wait_nohang(int *wstat)
485 {
486         return waitpid(-1, wstat, WNOHANG);
487 }
488
489
490 /*** wait_pid.c ***/
491
492 int wait_pid(int *wstat, int pid)
493 {
494         int r;
495
496         do
497                 r = waitpid(pid, wstat, 0);
498         while ((r == -1) && (errno == EINTR));
499         return r;
500 }