cp: make "cp file /dev/node" special case; explained in comments
[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 unsigned byte_chr(char *s,unsigned n,int c)
38 {
39         char ch;
40         char *t;
41
42         ch = c;
43         t = s;
44         for (;;) {
45                 if (!n) break;
46                 if (*t == ch) break;
47                 ++t;
48                 --n;
49         }
50         return t - s;
51 }
52
53 int coe(int fd)
54 {
55         return fcntl(fd, F_SETFD, FD_CLOEXEC);
56 }
57
58 #ifdef UNUSED
59 static /* as it isn't used anywhere else */
60 void tai_pack(char *s, const struct tai *t)
61 {
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
75 void 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
91 void 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
106 int taia_less(const struct taia *t, const struct taia *u)
107 {
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
115 void taia_now(struct taia *t)
116 {
117         struct timeval now;
118         gettimeofday(&now, NULL);
119         tai_unix(&t->sec, now.tv_sec);
120         t->nano = 1000 * now.tv_usec + 500;
121         t->atto = 0;
122 }
123
124 /* UNUSED
125 void taia_pack(char *s, const struct taia *t)
126 {
127         unsigned long x;
128
129         tai_pack(s, &t->sec);
130         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 }
143 */
144
145 void taia_sub(struct taia *t, const struct taia *u, const struct taia *v)
146 {
147         unsigned long unano = u->nano;
148         unsigned long uatto = u->atto;
149
150         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
163 /* XXX: breaks tai encapsulation */
164 void taia_uint(struct taia *t, unsigned s)
165 {
166         t->sec.x = s;
167         t->nano = 0;
168         t->atto = 0;
169 }
170
171 static
172 uint64_t taia2millisec(const struct taia *t)
173 {
174         return (t->sec.x * 1000) + (t->nano / 1000000);
175 }
176
177 void iopause(iopause_fd *x, unsigned len, struct taia *deadline, struct taia *stamp)
178 {
179         int millisecs;
180         int i;
181
182         if (taia_less(deadline, stamp))
183                 millisecs = 0;
184         else {
185                 uint64_t m;
186                 struct taia t;
187                 t = *stamp;
188                 taia_sub(&t, deadline, &t);
189                 millisecs = m = taia2millisec(&t);
190                 if (m > 1000) millisecs = 1000;
191                 millisecs += 20;
192         }
193
194         for (i = 0; i < len; ++i)
195                 x[i].revents = 0;
196
197         poll(x, len, millisecs);
198         /* 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 }
202 #endif
203
204 int lock_ex(int fd)
205 {
206         return flock(fd,LOCK_EX);
207 }
208
209 int lock_exnb(int fd)
210 {
211         return flock(fd,LOCK_EX | LOCK_NB);
212 }
213
214 int open_append(const char *fn)
215 {
216         return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
217 }
218
219 int open_read(const char *fn)
220 {
221         return open(fn, O_RDONLY|O_NDELAY);
222 }
223
224 int open_trunc(const char *fn)
225 {
226         return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);
227 }
228
229 int open_write(const char *fn)
230 {
231         return open(fn, O_WRONLY|O_NDELAY);
232 }
233
234 unsigned pmatch(const char *p, const char *s, unsigned len)
235 {
236         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 }