blob: 4b7950ca3e83178cbfc5490aea9bc9c7fb931715 [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 +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 Vlasenko83ea6432006-11-16 02:27:24 +000053int coe(int fd)
54{
Denis Vlasenko45946f82007-08-20 17:27:40 +000055 return fcntl(fd, F_SETFD, FD_CLOEXEC);
Denis Vlasenko83ea6432006-11-16 02:27:24 +000056}
57
Denis Vlasenko45946f82007-08-20 17:27:40 +000058#ifdef UNUSED
Denis Vlasenko8c783952007-01-27 22:21:52 +000059static /* as it isn't used anywhere else */
Denis Vlasenko45946f82007-08-20 17:27:40 +000060void tai_pack(char *s, const struct tai *t)
Denis Vlasenko83ea6432006-11-16 02:27:24 +000061{
62 uint64_t x;
63
64 x = t->x;
65 s[7] = x & 255; x >>= 8;
66 s[6] = x & 255; x >>= 8;
67 s[5] = x & 255; x >>= 8;
68 s[4] = x & 255; x >>= 8;
69 s[3] = x & 255; x >>= 8;
70 s[2] = x & 255; x >>= 8;
71 s[1] = x & 255; x >>= 8;
72 s[0] = x;
73}
74
Denis Vlasenko83ea6432006-11-16 02:27:24 +000075void tai_unpack(const char *s,struct tai *t)
76{
77 uint64_t x;
78
79 x = (unsigned char) s[0];
80 x <<= 8; x += (unsigned char) s[1];
81 x <<= 8; x += (unsigned char) s[2];
82 x <<= 8; x += (unsigned char) s[3];
83 x <<= 8; x += (unsigned char) s[4];
84 x <<= 8; x += (unsigned char) s[5];
85 x <<= 8; x += (unsigned char) s[6];
86 x <<= 8; x += (unsigned char) s[7];
87 t->x = x;
88}
89
90
Denis Vlasenko83ea6432006-11-16 02:27:24 +000091void taia_add(struct taia *t,const struct taia *u,const struct taia *v)
92{
93 t->sec.x = u->sec.x + v->sec.x;
94 t->nano = u->nano + v->nano;
95 t->atto = u->atto + v->atto;
96 if (t->atto > 999999999UL) {
97 t->atto -= 1000000000UL;
98 ++t->nano;
99 }
100 if (t->nano > 999999999UL) {
101 t->nano -= 1000000000UL;
102 ++t->sec.x;
103 }
104}
105
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000106int taia_less(const struct taia *t, const struct taia *u)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000107{
108 if (t->sec.x < u->sec.x) return 1;
109 if (t->sec.x > u->sec.x) return 0;
110 if (t->nano < u->nano) return 1;
111 if (t->nano > u->nano) return 0;
112 return t->atto < u->atto;
113}
114
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000115void taia_now(struct taia *t)
116{
117 struct timeval now;
Denis Vlasenko8c783952007-01-27 22:21:52 +0000118 gettimeofday(&now, NULL);
119 tai_unix(&t->sec, now.tv_sec);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000120 t->nano = 1000 * now.tv_usec + 500;
121 t->atto = 0;
122}
123
Denis Vlasenko45946f82007-08-20 17:27:40 +0000124/* UNUSED
Denis Vlasenko8c783952007-01-27 22:21:52 +0000125void taia_pack(char *s, const struct taia *t)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000126{
127 unsigned long x;
128
Denis Vlasenko8c783952007-01-27 22:21:52 +0000129 tai_pack(s, &t->sec);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000130 s += 8;
131
132 x = t->atto;
133 s[7] = x & 255; x >>= 8;
134 s[6] = x & 255; x >>= 8;
135 s[5] = x & 255; x >>= 8;
136 s[4] = x;
137 x = t->nano;
138 s[3] = x & 255; x >>= 8;
139 s[2] = x & 255; x >>= 8;
140 s[1] = x & 255; x >>= 8;
141 s[0] = x;
142}
Denis Vlasenko45946f82007-08-20 17:27:40 +0000143*/
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000144
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000145void taia_sub(struct taia *t, const struct taia *u, const struct taia *v)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000146{
147 unsigned long unano = u->nano;
148 unsigned long uatto = u->atto;
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000149
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000150 t->sec.x = u->sec.x - v->sec.x;
151 t->nano = unano - v->nano;
152 t->atto = uatto - v->atto;
153 if (t->atto > uatto) {
154 t->atto += 1000000000UL;
155 --t->nano;
156 }
157 if (t->nano > unano) {
158 t->nano += 1000000000UL;
159 --t->sec.x;
160 }
161}
162
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000163/* XXX: breaks tai encapsulation */
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000164void taia_uint(struct taia *t, unsigned s)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000165{
166 t->sec.x = s;
167 t->nano = 0;
168 t->atto = 0;
169}
170
Denis Vlasenkobde74b62007-01-27 22:22:53 +0000171static
172uint64_t taia2millisec(const struct taia *t)
173{
174 return (t->sec.x * 1000) + (t->nano / 1000000);
175}
176
Denis Vlasenkoca549c52007-01-27 22:24:59 +0000177void iopause(iopause_fd *x, unsigned len, struct taia *deadline, struct taia *stamp)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000178{
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000179 int millisecs;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000180 int i;
181
Denis Vlasenkoca549c52007-01-27 22:24:59 +0000182 if (taia_less(deadline, stamp))
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000183 millisecs = 0;
184 else {
Denis Vlasenko8c783952007-01-27 22:21:52 +0000185 uint64_t m;
186 struct taia t;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000187 t = *stamp;
Denis Vlasenko8c783952007-01-27 22:21:52 +0000188 taia_sub(&t, deadline, &t);
189 millisecs = m = taia2millisec(&t);
190 if (m > 1000) millisecs = 1000;
191 millisecs += 20;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000192 }
193
Denis Vlasenko8c783952007-01-27 22:21:52 +0000194 for (i = 0; i < len; ++i)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000195 x[i].revents = 0;
196
Denis Vlasenko8c783952007-01-27 22:21:52 +0000197 poll(x, len, millisecs);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000198 /* XXX: some kernels apparently need x[0] even if len is 0 */
199 /* XXX: how to handle EAGAIN? are kernels really this dumb? */
200 /* XXX: how to handle EINVAL? when exactly can this happen? */
201}
Denis Vlasenko45946f82007-08-20 17:27:40 +0000202#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000203
204int lock_ex(int fd)
205{
206 return flock(fd,LOCK_EX);
207}
208
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000209int lock_exnb(int fd)
210{
211 return flock(fd,LOCK_EX | LOCK_NB);
212}
213
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000214int open_append(const char *fn)
215{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000216 return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000217}
218
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000219int open_read(const char *fn)
220{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000221 return open(fn, O_RDONLY|O_NDELAY);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000222}
223
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000224int open_trunc(const char *fn)
225{
226 return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);
227}
228
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000229int open_write(const char *fn)
230{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000231 return open(fn, O_WRONLY|O_NDELAY);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000232}
233
Denis Vlasenko45946f82007-08-20 17:27:40 +0000234unsigned pmatch(const char *p, const char *s, unsigned len)
235{
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000236 for (;;) {
237 char c = *p++;
238 if (!c) return !len;
239 switch (c) {
240 case '*':
241 if (!(c = *p)) return 1;
242 for (;;) {
243 if (!len) return 0;
244 if (*s == c) break;
245 ++s; --len;
246 }
247 continue;
248 case '+':
249 if ((c = *p++) != *s) return 0;
250 for (;;) {
251 if (!len) return 1;
252 if (*s != c) break;
253 ++s; --len;
254 }
255 continue;
256 /*
257 case '?':
258 if (*p == '?') {
259 if (*s != '?') return 0;
260 ++p;
261 }
262 ++s; --len;
263 continue;
264 */
265 default:
266 if (!len) return 0;
267 if (*s != c) return 0;
268 ++s; --len;
269 continue;
270 }
271 }
272 return 0;
273}