blob: f33619d28fc22dc62c8c67095a4c53b7ba3a988d [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
Denis Vlasenkod18f52b2008-03-02 12:53:15 +000028/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
Denis Vlasenko83ea6432006-11-16 02:27:24 +000029/* 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 +000037unsigned byte_chr(char *s,unsigned n,int c)
38{
39 char ch;
40 char *t;
41
42 ch = c;
43 t = s;
44 for (;;) {
Denis Vlasenko8c783952007-01-27 22:21:52 +000045 if (!n) break;
46 if (*t == ch) break;
47 ++t;
48 --n;
Denis Vlasenko83ea6432006-11-16 02:27:24 +000049 }
50 return t - s;
51}
52
Denis Vlasenko45946f82007-08-20 17:27:40 +000053#ifdef UNUSED
Denis Vlasenko8c783952007-01-27 22:21:52 +000054static /* as it isn't used anywhere else */
Denis Vlasenko45946f82007-08-20 17:27:40 +000055void tai_pack(char *s, const struct tai *t)
Denis Vlasenko83ea6432006-11-16 02:27:24 +000056{
57 uint64_t x;
58
59 x = t->x;
60 s[7] = x & 255; x >>= 8;
61 s[6] = x & 255; x >>= 8;
62 s[5] = x & 255; x >>= 8;
63 s[4] = x & 255; x >>= 8;
64 s[3] = x & 255; x >>= 8;
65 s[2] = x & 255; x >>= 8;
66 s[1] = x & 255; x >>= 8;
67 s[0] = x;
68}
69
Denis Vlasenko83ea6432006-11-16 02:27:24 +000070void tai_unpack(const char *s,struct tai *t)
71{
72 uint64_t x;
73
74 x = (unsigned char) s[0];
75 x <<= 8; x += (unsigned char) s[1];
76 x <<= 8; x += (unsigned char) s[2];
77 x <<= 8; x += (unsigned char) s[3];
78 x <<= 8; x += (unsigned char) s[4];
79 x <<= 8; x += (unsigned char) s[5];
80 x <<= 8; x += (unsigned char) s[6];
81 x <<= 8; x += (unsigned char) s[7];
82 t->x = x;
83}
84
85
Denis Vlasenko83ea6432006-11-16 02:27:24 +000086void taia_add(struct taia *t,const struct taia *u,const struct taia *v)
87{
88 t->sec.x = u->sec.x + v->sec.x;
89 t->nano = u->nano + v->nano;
90 t->atto = u->atto + v->atto;
91 if (t->atto > 999999999UL) {
92 t->atto -= 1000000000UL;
93 ++t->nano;
94 }
95 if (t->nano > 999999999UL) {
96 t->nano -= 1000000000UL;
97 ++t->sec.x;
98 }
99}
100
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000101int taia_less(const struct taia *t, const struct taia *u)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000102{
103 if (t->sec.x < u->sec.x) return 1;
104 if (t->sec.x > u->sec.x) return 0;
105 if (t->nano < u->nano) return 1;
106 if (t->nano > u->nano) return 0;
107 return t->atto < u->atto;
108}
109
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000110void taia_now(struct taia *t)
111{
112 struct timeval now;
Denis Vlasenko8c783952007-01-27 22:21:52 +0000113 gettimeofday(&now, NULL);
114 tai_unix(&t->sec, now.tv_sec);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000115 t->nano = 1000 * now.tv_usec + 500;
116 t->atto = 0;
117}
118
Denis Vlasenko45946f82007-08-20 17:27:40 +0000119/* UNUSED
Denis Vlasenko8c783952007-01-27 22:21:52 +0000120void taia_pack(char *s, const struct taia *t)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000121{
122 unsigned long x;
123
Denis Vlasenko8c783952007-01-27 22:21:52 +0000124 tai_pack(s, &t->sec);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000125 s += 8;
126
127 x = t->atto;
128 s[7] = x & 255; x >>= 8;
129 s[6] = x & 255; x >>= 8;
130 s[5] = x & 255; x >>= 8;
131 s[4] = x;
132 x = t->nano;
133 s[3] = x & 255; x >>= 8;
134 s[2] = x & 255; x >>= 8;
135 s[1] = x & 255; x >>= 8;
136 s[0] = x;
137}
Denis Vlasenko45946f82007-08-20 17:27:40 +0000138*/
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000139
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000140void taia_sub(struct taia *t, const struct taia *u, const struct taia *v)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000141{
142 unsigned long unano = u->nano;
143 unsigned long uatto = u->atto;
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000144
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000145 t->sec.x = u->sec.x - v->sec.x;
146 t->nano = unano - v->nano;
147 t->atto = uatto - v->atto;
148 if (t->atto > uatto) {
149 t->atto += 1000000000UL;
150 --t->nano;
151 }
152 if (t->nano > unano) {
153 t->nano += 1000000000UL;
154 --t->sec.x;
155 }
156}
157
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000158/* XXX: breaks tai encapsulation */
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000159void taia_uint(struct taia *t, unsigned s)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000160{
161 t->sec.x = s;
162 t->nano = 0;
163 t->atto = 0;
164}
165
Denis Vlasenkobde74b62007-01-27 22:22:53 +0000166static
167uint64_t taia2millisec(const struct taia *t)
168{
169 return (t->sec.x * 1000) + (t->nano / 1000000);
170}
171
Denis Vlasenkoca549c52007-01-27 22:24:59 +0000172void iopause(iopause_fd *x, unsigned len, struct taia *deadline, struct taia *stamp)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000173{
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000174 int millisecs;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000175 int i;
176
Denis Vlasenkoca549c52007-01-27 22:24:59 +0000177 if (taia_less(deadline, stamp))
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000178 millisecs = 0;
179 else {
Denis Vlasenko8c783952007-01-27 22:21:52 +0000180 uint64_t m;
181 struct taia t;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000182 t = *stamp;
Denis Vlasenko8c783952007-01-27 22:21:52 +0000183 taia_sub(&t, deadline, &t);
184 millisecs = m = taia2millisec(&t);
185 if (m > 1000) millisecs = 1000;
186 millisecs += 20;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000187 }
188
Denis Vlasenko8c783952007-01-27 22:21:52 +0000189 for (i = 0; i < len; ++i)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000190 x[i].revents = 0;
191
Denis Vlasenko8c783952007-01-27 22:21:52 +0000192 poll(x, len, millisecs);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000193 /* XXX: some kernels apparently need x[0] even if len is 0 */
194 /* XXX: how to handle EAGAIN? are kernels really this dumb? */
195 /* XXX: how to handle EINVAL? when exactly can this happen? */
196}
Denis Vlasenko45946f82007-08-20 17:27:40 +0000197#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000198
199int lock_ex(int fd)
200{
201 return flock(fd,LOCK_EX);
202}
203
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000204int lock_exnb(int fd)
205{
206 return flock(fd,LOCK_EX | LOCK_NB);
207}
208
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000209int open_append(const char *fn)
210{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000211 return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000212}
213
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000214int open_read(const char *fn)
215{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000216 return open(fn, O_RDONLY|O_NDELAY);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000217}
218
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000219int open_trunc(const char *fn)
220{
221 return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);
222}
223
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000224int open_write(const char *fn)
225{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000226 return open(fn, O_WRONLY|O_NDELAY);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000227}
228
Denis Vlasenko45946f82007-08-20 17:27:40 +0000229unsigned pmatch(const char *p, const char *s, unsigned len)
230{
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000231 for (;;) {
232 char c = *p++;
233 if (!c) return !len;
234 switch (c) {
235 case '*':
Denis Vlasenko6bef3d12007-11-06 03:05:54 +0000236 c = *p;
237 if (!c) return 1;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000238 for (;;) {
239 if (!len) return 0;
240 if (*s == c) break;
Denis Vlasenko6bef3d12007-11-06 03:05:54 +0000241 ++s;
242 --len;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000243 }
244 continue;
245 case '+':
Denis Vlasenko6bef3d12007-11-06 03:05:54 +0000246 c = *p++;
247 if (c != *s) return 0;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000248 for (;;) {
249 if (!len) return 1;
250 if (*s != c) break;
Denis Vlasenko6bef3d12007-11-06 03:05:54 +0000251 ++s;
252 --len;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000253 }
254 continue;
255 /*
256 case '?':
257 if (*p == '?') {
258 if (*s != '?') return 0;
259 ++p;
260 }
261 ++s; --len;
262 continue;
263 */
264 default:
265 if (!len) return 0;
266 if (*s != c) return 0;
Denis Vlasenko6bef3d12007-11-06 03:05:54 +0000267 ++s;
268 --len;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000269 continue;
270 }
271 }
272 return 0;
273}