1 /*
2 * Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
3 * Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)
4 * Copyright (c) 2010 Andreas Öman
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <limits.h>
21 #include <string.h>
22 #include <assert.h>
23 #include <openssl/md5.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <dirent.h>
27 #include <unistd.h>
28 #include <ctype.h>
29 #include <net/if.h>
30
31 #include <openssl/sha.h>
32
33 #include "tvheadend.h"
34 #include "tvh_endian.h"
35
36 /**
37 * CRC32
38 */
39 static uint32_t crc_tab[256] = {
40 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
41 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
42 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
43 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
44 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
45 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
46 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
47 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
48 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
49 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
50 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
51 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
52 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
53 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
54 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
55 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
56 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
57 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
58 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
59 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
60 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
61 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
62 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
63 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
64 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
65 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
66 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
67 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
68 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
69 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
70 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
71 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
72 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
73 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
74 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
75 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
76 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
77 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
78 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
79 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
80 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
81 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
82 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
83 };
84
85 uint32_t
tvh_crc32(const uint8_t * data,size_t datalen,uint32_t crc)86 tvh_crc32(const uint8_t *data, size_t datalen, uint32_t crc)
87 {
88 while(datalen--)
89 crc = (crc << 8) ^ crc_tab[((crc >> 24) ^ *data++) & 0xff];
90
91 return crc;
92 }
93
94
95 /**
96 *
97 */
98 static const int sample_rates[16] = {
99 96000, 88200, 64000, 48000,
100 44100, 32000, 24000, 22050,
101 16000, 12000, 11025, 8000,
102 7350, 0, 0, 0
103 };
104
105 /**
106 *
107 */
108 int
sri_to_rate(int sri)109 sri_to_rate(int sri)
110 {
111 return sample_rates[sri & 0xf];
112 }
113
114
115 /**
116 *
117 */
118 int
rate_to_sri(int rate)119 rate_to_sri(int rate)
120 {
121 int i;
122 for(i = 0; i < 16; i++)
123 if(sample_rates[i] == rate)
124 return i;
125 return -1;
126 }
127
128
129 /**
130 *
131 */
132 #define HEXDUMP_WIDTH 16
133 void
hexdump(const char * pfx,const uint8_t * data,int len)134 hexdump(const char *pfx, const uint8_t *data, int len)
135 {
136 int i, j=0, l;
137 char str[HEXDUMP_WIDTH+1];
138 l = ((len+(HEXDUMP_WIDTH-1))/HEXDUMP_WIDTH)*HEXDUMP_WIDTH;
139 str[0] = 0;
140 for (i = 0; i < l; i++) {
141 if (!j) printf("%s: ", pfx);
142 if (i < len) {
143 printf("%02X ", data[i]);
144 str[j] = data[i];
145 if (str[j] < ' ' || str[j] > '~') str[j] = '.';
146 } else {
147 printf(" ");
148 str[j] = ' ';
149 }
150 j++;
151 if (j == HEXDUMP_WIDTH) {
152 str[j] = 0;
153 printf("%s\n", str);
154 str[0] = 0;
155 j = 0;
156 }
157 }
158 }
159
160 /**
161 * @file
162 * @brief Base64 encode/decode
163 * @author Ryan Martell <rdm4@martellventures.com> (with lots of Michael)
164 */
165
166
167 /* ---------------- private code */
168 static const uint8_t map2[] =
169 {
170 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36,
171 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff,
172 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01,
173 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
174 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
175 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
176 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b,
177 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
178 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
179 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33
180 };
181
182 int
base64_decode(uint8_t * out,const char * in,int out_size)183 base64_decode(uint8_t *out, const char *in, int out_size)
184 {
185 int i, v;
186 uint8_t *dst = out;
187
188 v = 0;
189 for (i = 0; in[i] && in[i] != '='; i++) {
190 unsigned int index= in[i]-43;
191 if (index >= sizeof(map2) || map2[index] == 0xff)
192 return -1;
193 v = (v << 6) + map2[index];
194 if (i & 3) {
195 if (dst - out < out_size) {
196 *dst++ = v >> (6 - 2 * (i & 3));
197 }
198 }
199 }
200
201 return dst - out;
202 }
203
204 /*
205 * b64_encode: Stolen from VLC's http.c.
206 * Simplified by Michael.
207 * Fixed edge cases and made it work from data (vs. strings) by Ryan.
208 */
209
base64_encode(char * out,int out_size,const uint8_t * in,int in_size)210 char *base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
211 {
212 static const char b64[] =
213 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
214 char *ret, *dst;
215 unsigned i_bits = 0;
216 int i_shift = 0;
217 int bytes_remaining = in_size;
218
219 if (in_size >= UINT_MAX / 4 ||
220 out_size < BASE64_SIZE(in_size))
221 return NULL;
222 ret = dst = out;
223 while (bytes_remaining) {
224 i_bits = (i_bits << 8) + *in++;
225 bytes_remaining--;
226 i_shift += 8;
227
228 do {
229 *dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f];
230 i_shift -= 6;
231 } while (i_shift > 6 || (bytes_remaining == 0 && i_shift > 0));
232 }
233 while ((dst - ret) & 3)
234 *dst++ = '=';
235 *dst = '\0';
236
237 return ret;
238 }
239
240 /**
241 *
242 */
243 int
put_utf8(char * out,int c)244 put_utf8(char *out, int c)
245 {
246 if(c == 0xfffe || c == 0xffff || (c >= 0xD800 && c < 0xE000))
247 return 0;
248
249 if (c < 0x80) {
250 *out = c;
251 return 1;
252 }
253
254 if(c < 0x800) {
255 *out++ = 0xc0 | (0x1f & (c >> 6));
256 *out = 0x80 | (0x3f & c);
257 return 2;
258 }
259
260 if(c < 0x10000) {
261 *out++ = 0xe0 | (0x0f & (c >> 12));
262 *out++ = 0x80 | (0x3f & (c >> 6));
263 *out = 0x80 | (0x3f & c);
264 return 3;
265 }
266
267 if(c < 0x200000) {
268 *out++ = 0xf0 | (0x07 & (c >> 18));
269 *out++ = 0x80 | (0x3f & (c >> 12));
270 *out++ = 0x80 | (0x3f & (c >> 6));
271 *out = 0x80 | (0x3f & c);
272 return 4;
273 }
274
275 if(c < 0x4000000) {
276 *out++ = 0xf8 | (0x03 & (c >> 24));
277 *out++ = 0x80 | (0x3f & (c >> 18));
278 *out++ = 0x80 | (0x3f & (c >> 12));
279 *out++ = 0x80 | (0x3f & (c >> 6));
280 *out++ = 0x80 | (0x3f & c);
281 return 5;
282 }
283
284 *out++ = 0xfc | (0x01 & (c >> 30));
285 *out++ = 0x80 | (0x3f & (c >> 24));
286 *out++ = 0x80 | (0x3f & (c >> 18));
287 *out++ = 0x80 | (0x3f & (c >> 12));
288 *out++ = 0x80 | (0x3f & (c >> 6));
289 *out++ = 0x80 | (0x3f & c);
290 return 6;
291 }
292
utf8_lowercase_inplace(char * s)293 char *utf8_lowercase_inplace(char *s)
294 {
295 char *r = s;
296 uint8_t c;
297
298 for ( ; *s; s++) {
299 /* FIXME: this is really wrong version of lowercase for utf-8 */
300 /* but it's a deep issue with the different locale handling */
301 c = (uint8_t)*s;
302 if (c & 0x80) {
303 if ((c & 0xe0) == 0xc0) {
304 s++;
305 continue;
306 } else if ((c & 0xf0) == 0xe0) {
307 s++;
308 if (*s) s++;
309 } else if ((c & 0xf8) == 0xf0) {
310 s++;
311 if (*s) s++;
312 if (*s) s++;
313 }
314 }
315 if (c >= 'A' && c <= 'Z')
316 *(char *)s = c - 'A' + 'a';
317 }
318 return r;
319 }
320
321 /**
322 *
323 */
324
325 static void
sbuf_alloc_fail(int len)326 sbuf_alloc_fail(int len)
327 {
328 fprintf(stderr, "Unable to allocate %d bytes\n", len);
329 abort();
330 }
331
332 void
sbuf_init(sbuf_t * sb)333 sbuf_init(sbuf_t *sb)
334 {
335 memset(sb, 0, sizeof(sbuf_t));
336 }
337
338 void
sbuf_init_fixed(sbuf_t * sb,int len)339 sbuf_init_fixed(sbuf_t *sb, int len)
340 {
341 memset(sb, 0, sizeof(sbuf_t));
342 sb->sb_data = malloc(len);
343 if (sb->sb_data == NULL)
344 sbuf_alloc_fail(len);
345 sb->sb_size = len;
346 }
347
348 void
sbuf_free(sbuf_t * sb)349 sbuf_free(sbuf_t *sb)
350 {
351 free(sb->sb_data);
352 sb->sb_size = sb->sb_ptr = sb->sb_err = 0;
353 sb->sb_data = NULL;
354 }
355
356 void
sbuf_reset(sbuf_t * sb,int max_len)357 sbuf_reset(sbuf_t *sb, int max_len)
358 {
359 sb->sb_ptr = sb->sb_err = 0;
360 if (sb->sb_size > max_len) {
361 void *n = realloc(sb->sb_data, max_len);
362 if (n) {
363 sb->sb_data = n;
364 sb->sb_size = max_len;
365 }
366 }
367 }
368
369 void
sbuf_reset_and_alloc(sbuf_t * sb,int len)370 sbuf_reset_and_alloc(sbuf_t *sb, int len)
371 {
372 sbuf_realloc(sb, len);
373 sb->sb_ptr = sb->sb_err = 0;
374 }
375
376 void
sbuf_alloc_(sbuf_t * sb,int len)377 sbuf_alloc_(sbuf_t *sb, int len)
378 {
379 if(sb->sb_data == NULL) {
380 sb->sb_size = len * 4 > 4000 ? len * 4 : 4000;
381 sb->sb_data = malloc(sb->sb_size);
382 return;
383 } else {
384 sb->sb_size += len * 4;
385 sb->sb_data = realloc(sb->sb_data, sb->sb_size);
386 }
387
388 if(sb->sb_data == NULL)
389 sbuf_alloc_fail(sb->sb_size);
390 }
391
392 void
sbuf_realloc(sbuf_t * sb,int len)393 sbuf_realloc(sbuf_t *sb, int len)
394 {
395 if (sb->sb_data) {
396 if (len != sb->sb_size) {
397 void *n = realloc(sb->sb_data, len);
398 if (n) {
399 sb->sb_data = n;
400 sb->sb_size = len;
401 }
402 }
403 } else {
404 sb->sb_data = malloc(len);
405 sb->sb_size = len;
406 }
407 if (sb->sb_data == NULL)
408 sbuf_alloc_fail(len);
409 }
410
411 void
sbuf_append(sbuf_t * sb,const void * data,int len)412 sbuf_append(sbuf_t *sb, const void *data, int len)
413 {
414 sbuf_alloc(sb, len);
415 memcpy(sb->sb_data + sb->sb_ptr, data, len);
416 sb->sb_ptr += len;
417 }
418
419 void
sbuf_put_be32(sbuf_t * sb,uint32_t u32)420 sbuf_put_be32(sbuf_t *sb, uint32_t u32)
421 {
422 u32 = htonl(u32);
423 sbuf_append(sb, &u32, 4);
424 }
425
426 void
sbuf_put_be16(sbuf_t * sb,uint16_t u16)427 sbuf_put_be16(sbuf_t *sb, uint16_t u16)
428 {
429 u16 = htons(u16);
430 sbuf_append(sb, &u16, 2);
431 }
432
433 void
sbuf_put_byte(sbuf_t * sb,uint8_t u8)434 sbuf_put_byte(sbuf_t *sb, uint8_t u8)
435 {
436 sbuf_append(sb, &u8, 1);
437 }
438
sbuf_peek_u16(sbuf_t * sb,int off)439 uint16_t sbuf_peek_u16(sbuf_t *sb, int off)
440 {
441 uint8_t *p = sb->sb_data + off;
442 if (ENDIAN_SWAP_COND(sb->sb_bswap))
443 return p[0] | (((uint16_t)p[1]) << 8);
444 else
445 return (((uint16_t)p[0]) << 8) | p[1];
446 }
447
sbuf_peek_u16le(sbuf_t * sb,int off)448 uint16_t sbuf_peek_u16le(sbuf_t *sb, int off)
449 {
450 uint8_t *p = sb->sb_data + off;
451 return p[0] | (((uint16_t)p[1]) << 8);
452 }
453
sbuf_peek_u16be(sbuf_t * sb,int off)454 uint16_t sbuf_peek_u16be(sbuf_t *sb, int off)
455 {
456 uint8_t *p = sb->sb_data + off;
457 return (((uint16_t)p[0]) << 8) | p[1];
458 }
459
sbuf_peek_u32(sbuf_t * sb,int off)460 uint32_t sbuf_peek_u32(sbuf_t *sb, int off)
461 {
462 uint8_t *p = sb->sb_data + off;
463 if (ENDIAN_SWAP_COND(sb->sb_bswap))
464 return p[0] | (((uint32_t)p[1]) << 8) |
465 (((uint32_t)p[2]) << 16) | (((uint32_t)p[3]) << 24);
466 else
467 return (((uint16_t)p[0]) << 24) | (((uint16_t)p[1]) << 16) |
468 (((uint16_t)p[2]) << 8) | p[3];
469 }
470
sbuf_peek_u32le(sbuf_t * sb,int off)471 uint32_t sbuf_peek_u32le(sbuf_t *sb, int off)
472 {
473 uint8_t *p = sb->sb_data + off;
474 return p[0] | (((uint32_t)p[1]) << 8) |
475 (((uint32_t)p[2]) << 16) | (((uint32_t)p[3]) << 24);
476 }
477
sbuf_peek_u32be(sbuf_t * sb,int off)478 uint32_t sbuf_peek_u32be(sbuf_t *sb, int off)
479 {
480 uint8_t *p = sb->sb_data + off;
481 return (((uint16_t)p[0]) << 24) | (((uint16_t)p[1]) << 16) |
482 (((uint16_t)p[2]) << 8) | p[3];
483 }
484
485 void
sbuf_cut(sbuf_t * sb,int off)486 sbuf_cut(sbuf_t *sb, int off)
487 {
488 assert(off <= sb->sb_ptr);
489 sb->sb_ptr = sb->sb_ptr - off;
490 memmove(sb->sb_data, sb->sb_data + off, sb->sb_ptr);
491 }
492
493 ssize_t
sbuf_read(sbuf_t * sb,int fd)494 sbuf_read(sbuf_t *sb, int fd)
495 {
496 ssize_t n = read(fd, sb->sb_data + sb->sb_ptr, sb->sb_size - sb->sb_ptr);
497 if (n > 0)
498 sb->sb_ptr += n;
499 return n;
500 }
501
502 char *
md5sum(const char * str,int lowercase)503 md5sum ( const char *str, int lowercase )
504 {
505 uint8_t md5[MD5_DIGEST_LENGTH];
506 char *ret = malloc((MD5_DIGEST_LENGTH * 2) + 1);
507 int i;
508
509 MD5((const unsigned char*)str, strlen(str), md5);
510 for (i = 0; i < MD5_DIGEST_LENGTH; i++)
511 sprintf(&ret[i*2], lowercase ? "%02x" : "%02X", md5[i]);
512 ret[MD5_DIGEST_LENGTH*2] = '\0';
513 return ret;
514 }
515
516 #define FILE_MODE_BITS(x) (x&(S_IRWXU|S_IRWXG|S_IRWXO))
517
518 int
makedirs(int subsys,const char * inpath,int mode,int mstrict,gid_t gid,uid_t uid)519 makedirs ( int subsys, const char *inpath, int mode,
520 int mstrict, gid_t gid, uid_t uid )
521 {
522 int err, ok;
523 size_t x;
524 struct stat st;
525 char *path;
526
527 if (!inpath || !*inpath) return -1;
528
529 x = 1;
530 ok = 1;
531 path = alloca(strlen(inpath) + 1);
532 strcpy(path, inpath);
533 while(ok) {
534 ok = path[x];
535 if (path[x] == '/' || !path[x]) {
536 path[x] = 0;
537 if (stat(path, &st)) {
538 err = mkdir(path, mode);
539 if (!err && gid != -1 && uid != -1)
540 err = chown(path, uid, gid);
541 if (!err && !stat(path, &st) &&
542 FILE_MODE_BITS(mode) != FILE_MODE_BITS(st.st_mode)) {
543 err = chmod(path, mode); /* override umode */
544 if (!mstrict) {
545 err = 0;
546 tvhwarn(subsys, "Unable to change directory permissions "
547 "to \"%o\" for \"%s\" (keeping \"%o\")",
548 mode, path, FILE_MODE_BITS(st.st_mode));
549 mode = FILE_MODE_BITS(st.st_mode);
550 }
551 }
552 tvhtrace(subsys, "Creating directory \"%s\" with octal permissions "
553 "\"%o\" gid %d uid %d", path, mode, gid, uid);
554 } else {
555 err = S_ISDIR(st.st_mode) ? 0 : 1;
556 errno = ENOTDIR;
557 }
558 if (err) {
559 tvhalert(subsys, "Unable to create dir \"%s\": %s",
560 path, strerror(errno));
561 return -1;
562 }
563 path[x] = '/';
564 }
565 x++;
566 }
567 return 0;
568 }
569
570 int
rmtree(const char * path)571 rmtree ( const char *path )
572 {
573 int err = 0;
574 struct dirent de, *der;
575 struct stat st;
576 char buf[PATH_MAX];
577 DIR *dir = opendir(path);
578 if (!dir) return -1;
579 while (!readdir_r(dir, &de, &der) && der) {
580 if (!strcmp("..", de.d_name) || !strcmp(".", de.d_name))
581 continue;
582 snprintf(buf, sizeof(buf), "%s/%s", path, de.d_name);
583 err = stat(buf, &st);
584 if (err) break;
585 if (S_ISDIR(st.st_mode))
586 err = rmtree(buf);
587 else
588 err = unlink(buf);
589 if (err) break;
590 }
591 closedir(dir);
592 if (!err)
593 err = rmdir(path);
594 return err;
595 }
596
597 char *
regexp_escape(const char * str)598 regexp_escape(const char* str)
599 {
600 const char *a;
601 char *tmp, *b;
602 if (!str)
603 return NULL;
604 a = str;
605 b = tmp = malloc(strlen(str) * 2);
606 while (*a) {
607 switch (*a) {
608 case '?':
609 case '+':
610 case '.':
611 case '(':
612 case ')':
613 case '[':
614 case ']':
615 case '*':
616 case '^':
617 *b = '\\';
618 b++;
619 /* -fallthrough */
620 default:
621 break;
622 }
623 *b = *a;
624 b++;
625 a++;
626 }
627 *b = 0;
628 return tmp;
629 }
630
631 /* Converts an integer value to its hex character
632 http://www.geekhideout.com/urlcode.shtml */
to_hex(char code)633 char to_hex(char code) {
634 static char hex[] = "0123456789abcdef";
635 return hex[code & 15];
636 }
637
638 /* Returns a url-encoded version of str
639 IMPORTANT: be sure to free() the returned string after use
640 http://www.geekhideout.com/urlcode.shtml */
url_encode(const char * str)641 char *url_encode(const char *str)
642 {
643 char *buf = malloc(strlen(str) * 3 + 1), *pbuf = buf;
644 while (*str) {
645 if (isalnum(*str) || *str == '-' || *str == '_' || *str == '.' || *str == '~')
646 *pbuf++ = *str;
647 /*else if (*str == ' ')
648 *pbuf++ = '+';*/
649 else
650 *pbuf++ = '%', *pbuf++ = to_hex(*str >> 4), *pbuf++ = to_hex(*str & 15);
651 str++;
652 }
653 *pbuf = '\0';
654 return buf;
655 }
656
657 /**
658 * De-escape HTTP URL
659 */
660 void
http_deescape(char * s)661 http_deescape(char *s)
662 {
663 char v, *d = s;
664
665 while(*s) {
666 if(*s == '+') {
667 *d++ = ' ';
668 s++;
669 } else if(*s == '%') {
670 s++;
671 switch(*s) {
672 case '0' ... '9':
673 v = (*s - '0') << 4;
674 break;
675 case 'a' ... 'f':
676 v = (*s - 'a' + 10) << 4;
677 break;
678 case 'A' ... 'F':
679 v = (*s - 'A' + 10) << 4;
680 break;
681 default:
682 *d = 0;
683 return;
684 }
685 s++;
686 switch(*s) {
687 case '0' ... '9':
688 v |= (*s - '0');
689 break;
690 case 'a' ... 'f':
691 v |= (*s - 'a' + 10);
692 break;
693 case 'A' ... 'F':
694 v |= (*s - 'A' + 10);
695 break;
696 default:
697 *d = 0;
698 return;
699 }
700 s++;
701
702 *d++ = v;
703 } else {
704 *d++ = *s++;
705 }
706 }
707 *d = 0;
708 }
709
710 /*
711 *
712 */
713
mpegts_word32(const uint8_t * tsb)714 static inline uint32_t mpegts_word32( const uint8_t *tsb )
715 {
716 //assert(((intptr_t)tsb & 3) == 0);
717 return *(uint32_t *)tsb;
718 }
719
720 int
mpegts_word_count(const uint8_t * tsb,int len,uint32_t mask)721 mpegts_word_count ( const uint8_t *tsb, int len, uint32_t mask )
722 {
723 uint32_t val;
724 int r = 0;
725
726 #if BYTE_ORDER == LITTLE_ENDIAN
727 mask = bswap_32(mask);
728 #endif
729
730 val = mpegts_word32(tsb) & mask;
731
732 while (len >= 188) {
733 if (len >= 4*188 &&
734 (mpegts_word32(tsb+0*188) & mask) == val &&
735 (mpegts_word32(tsb+1*188) & mask) == val &&
736 (mpegts_word32(tsb+2*188) & mask) == val &&
737 (mpegts_word32(tsb+3*188) & mask) == val) {
738 r += 4*188;
739 len -= 4*188;
740 tsb += 4*188;
741 } else if ((mpegts_word32(tsb) & mask) == val) {
742 r += 188;
743 len -= 188;
744 tsb += 188;
745 } else {
746 break;
747 }
748 }
749
750 return r;
751 }
752
753 static void
deferred_unlink_cb(void * s,int dearmed)754 deferred_unlink_cb(void *s, int dearmed)
755 {
756 if (unlink((const char *)s))
757 tvherror(LS_MAIN, "unable to remove file '%s'", (const char *)s);
758 free(s);
759 }
760
761 typedef struct {
762 char *filename;
763 char *rootdir;
764 } deferred_unlink_t;
765
766 static void
deferred_unlink_dir_cb(void * s,int dearmed)767 deferred_unlink_dir_cb(void *s, int dearmed)
768 {
769 deferred_unlink_t *du = s;
770 char *p;
771 int l;
772
773 if (unlink((const char *)du->filename))
774 tvherror(LS_MAIN, "unable to remove file '%s'", (const char *)du->filename);
775
776 /* Remove all directories up to rootdir */
777
778 l = strlen(du->filename) - 1;
779 p = du->filename;
780
781 for(; l >= 0; l--) {
782 if(p[l] == '/') {
783 p[l] = 0;
784 if(strncmp(p, du->rootdir, l) == 0)
785 break;
786 if(rmdir(p) == -1)
787 break;
788 }
789 }
790
791 free(du->filename);
792 free(du->rootdir);
793 free(du);
794 }
795
796 int
deferred_unlink(const char * filename,const char * rootdir)797 deferred_unlink(const char *filename, const char *rootdir)
798 {
799 deferred_unlink_t *du;
800 char *s, *p;
801 size_t l;
802 int r;
803 long max;
804
805 l = strlen(filename);
806 s = malloc(l + 9 + 1);
807 if (s == NULL)
808 return -ENOMEM;
809 max = pathconf(filename, _PC_NAME_MAX);
810 strcpy(s, filename);
811 if (l + 10 < max) {
812 p = strrchr(s, '/');
813 if (p && p[1])
814 p[1] = '.';
815 strcpy(s + l, ".removing");
816 } else {
817 p = strrchr(s, '/');
818 p = p && p[1] ? p + 1 : s;
819 memcpy(p, ".rm.", 4);
820 }
821 r = rename(filename, s);
822 if (r) {
823 r = -errno;
824 free(s);
825 return r;
826 }
827 if (rootdir == NULL)
828 tasklet_arm_alloc(deferred_unlink_cb, s);
829 else {
830 du = calloc(1, sizeof(*du));
831 if (du == NULL) {
832 free(s);
833 return -ENOMEM;
834 }
835 du->filename = s;
836 du->rootdir = strdup(rootdir);
837 tasklet_arm_alloc(deferred_unlink_dir_cb, du);
838 }
839 return 0;
840 }
841
842 void
sha1_calc(uint8_t * dst,const uint8_t * d1,size_t d1_len,const uint8_t * d2,size_t d2_len)843 sha1_calc(uint8_t *dst,
844 const uint8_t *d1, size_t d1_len,
845 const uint8_t *d2, size_t d2_len)
846 {
847 SHA_CTX shactx;
848
849 SHA1_Init(&shactx);
850 if (d1)
851 SHA1_Update(&shactx, d1, d1_len);
852 if (d2)
853 SHA1_Update(&shactx, d2, d2_len);
854 SHA1_Final(dst, &shactx);
855 }
856
857 uint32_t
gcdU32(uint32_t a,uint32_t b)858 gcdU32(uint32_t a, uint32_t b)
859 {
860 uint32_t r;
861 if (a < b) {
862 while((r = b % a) != 0) {
863 b = a;
864 a = r;
865 }
866 return a;
867 } else {
868 while((r = a % b) != 0) {
869 a = b;
870 b = r;
871 }
872 return b;
873 }
874 }
875
network_interfaces_enum(void * obj,const char * lang)876 htsmsg_t *network_interfaces_enum(void *obj, const char *lang)
877 {
878 #if ENABLE_IFNAMES
879 htsmsg_t *list = htsmsg_create_list();
880 struct if_nameindex *ifnames = if_nameindex();
881
882 if (ifnames) {
883 struct if_nameindex *ifname;
884 for (ifname = ifnames; ifname->if_name; ifname++)
885 htsmsg_add_msg(list, NULL, htsmsg_create_key_val(ifname->if_name, ifname->if_name));
886 if_freenameindex(ifnames);
887 }
888
889 return list;
890 #else
891 return NULL;
892 #endif
893 }
894
895 const char *
gmtime2local(time_t gmt,char * buf,size_t buflen)896 gmtime2local(time_t gmt, char *buf, size_t buflen)
897 {
898 struct tm tm;
899 localtime_r(&gmt, &tm);
900 strftime(buf, buflen, "%F;%T(%z)", &tm);
901 return buf;
902 }
903