style fixes, no code changes
[oweals/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 /*** fmt_ptime.c ***/
65
66 void fmt_ptime30nul(char *s, struct taia *ta) {
67         struct tm *t;
68         unsigned long u;
69
70         if (ta->sec.x < 4611686018427387914ULL)
71                 return; /* impossible? */
72         u = ta->sec.x -4611686018427387914ULL;
73         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') */
95 }
96
97 unsigned fmt_taia25(char *s, struct taia *t) {
98         static char pack[TAIA_PACK];
99
100         taia_pack(pack, t);
101         *s++ = '@';
102         bin2hex(s, pack, 12);
103         return 25;
104 }
105
106
107 /*** tai_pack.c ***/
108
109 static /* as it isn't used anywhere else */
110 void 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
126 #ifdef UNUSED
127 /*** tai_sub.c ***/
128
129 void tai_sub(struct tai *t, const struct tai *u, const struct tai *v)
130 {
131         t->x = u->x - v->x;
132 }
133 #endif
134
135
136 /*** tai_unpack.c ***/
137
138 void 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
156 void 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
172 /*** taia_less.c ***/
173
174 int taia_less(const struct taia *t, const struct taia *u)
175 {
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
186 void taia_now(struct taia *t)
187 {
188         struct timeval now;
189         gettimeofday(&now, NULL);
190         tai_unix(&t->sec, now.tv_sec);
191         t->nano = 1000 * now.tv_usec + 500;
192         t->atto = 0;
193 }
194
195
196 /*** taia_pack.c ***/
197
198 void taia_pack(char *s, const struct taia *t)
199 {
200         unsigned long x;
201
202         tai_pack(s, &t->sec);
203         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
220 void taia_sub(struct taia *t, const struct taia *u, const struct taia *v)
221 {
222         unsigned long unano = u->nano;
223         unsigned long uatto = u->atto;
224
225         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
243 void taia_uint(struct taia *t, unsigned s)
244 {
245         t->sec.x = s;
246         t->nano = 0;
247         t->atto = 0;
248 }
249
250
251 /*** iopause.c ***/
252
253 static
254 uint64_t taia2millisec(const struct taia *t)
255 {
256         return (t->sec.x * 1000) + (t->nano / 1000000);
257 }
258
259
260 void iopause(iopause_fd *x, unsigned len, struct taia *deadline, struct taia *stamp)
261 {
262         int millisecs;
263         int i;
264
265         if (taia_less(deadline, stamp))
266                 millisecs = 0;
267         else {
268                 uint64_t m;
269                 struct taia t;
270                 t = *stamp;
271                 taia_sub(&t, deadline, &t);
272                 millisecs = m = taia2millisec(&t);
273                 if (m > 1000) millisecs = 1000;
274                 millisecs += 20;
275         }
276
277         for (i = 0; i < len; ++i)
278                 x[i].revents = 0;
279
280         poll(x, len, millisecs);
281         /* 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
289 int lock_ex(int fd)
290 {
291         return flock(fd,LOCK_EX);
292 }
293
294
295 /*** lock_exnb.c ***/
296
297 int lock_exnb(int fd)
298 {
299         return flock(fd,LOCK_EX | LOCK_NB);
300 }
301
302
303 /*** open_append.c ***/
304
305 int open_append(const char *fn)
306 {
307         return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
308 }
309
310
311 /*** open_read.c ***/
312
313 int open_read(const char *fn)
314 {
315         return open(fn, O_RDONLY|O_NDELAY);
316 }
317
318
319 /*** open_trunc.c ***/
320
321 int 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
329 int open_write(const char *fn)
330 {
331         return open(fn, O_WRONLY|O_NDELAY);
332 }
333
334
335 /*** pmatch.c ***/
336
337 unsigned 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
378 #ifdef UNUSED
379 /*** seek_set.c ***/
380
381 int seek_set(int fd,seek_pos pos)
382 {
383         if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; return 0;
384 }
385 #endif
386
387
388 /*** str_chr.c ***/
389
390 // strchrnul?
391 unsigned str_chr(const char *s,int c)
392 {
393         char ch;
394         const char *t;
395
396         ch = c;
397         t = s;
398         for (;;) {
399                 if (!*t) break;
400                 if (*t == ch) break;
401                 ++t;
402         }
403         return t - s;
404 }