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