3
MediaTomb - http://www.mediatomb.cc/
5
tools.cc - this file is part of MediaTomb.
7
Copyright (C) 2005 Gena Batyan <bgeradz@mediatomb.cc>,
8
Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>
10
Copyright (C) 2006-2009 Gena Batyan <bgeradz@mediatomb.cc>,
11
Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>,
12
Leonhard Wimmer <leo@mediatomb.cc>
14
MediaTomb is free software; you can redistribute it and/or modify
15
it under the terms of the GNU General Public License version 2
16
as published by the Free Software Foundation.
18
MediaTomb is distributed in the hope that it will be useful,
19
but WITHOUT ANY WARRANTY; without even the implied warranty of
20
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
GNU General Public License for more details.
23
You should have received a copy of the GNU General Public License
24
version 2 along with MediaTomb; if not, write to the Free Software
25
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
27
$Id: tools.cc 2010 2009-01-11 19:10:43Z lww $
33
#include "autoconfig.h"
40
#include <sys/ioctl.h>
41
#include <sys/socket.h>
42
#include <netinet/in.h>
43
#include <arpa/inet.h>
53
#include <sys/sockio.h>
57
#include "file_io_handler.h"
58
#include "metadata_handler.h"
60
#define WHITE_SPACE " \t\r\n"
64
static const char *HEX_CHARS = "0123456789abcdef";
66
Ref<Array<StringBase> > split_string(String str, char sep, bool empty)
68
Ref<Array<StringBase> > ret(new Array<StringBase>());
69
char *data = str.c_str();
70
char *end = data + str.length();
73
char *pos = strchr(data, sep);
83
if ((data < end) && empty)
84
ret->append(String(""));
88
String part(data, pos - data);
96
Ref<Array<StringBase> > split_path(String str)
99
throw _Exception(_("invalid path given to split_path"));
100
Ref<Array<StringBase> > ret(new Array<StringBase>());
101
int pos = str.rindex(DIR_SEPARATOR);
102
const char *data = str.c_str();
105
throw _Exception(_("relative path given to split_path: ") + str);
109
/* there is only one separator at the beginning "/..." or "/" */
110
ret->append(_(_DIR_SEPARATOR));
111
String filename(data+1);
112
ret->append(filename);
116
String path(data, pos);
118
String filename(data + pos + 1);
119
ret->append(filename);
124
String trim_string(String str)
131
int len = str.length();
133
char *buf = str.c_str();
135
for (i = 0; i < len; i++)
137
if (! strchr(WHITE_SPACE, buf[i]))
145
for (i = len - 1; i >= start; i--)
147
if (! strchr(WHITE_SPACE, buf[i]))
153
return str.substring(start, end - start);
156
bool check_path(String path, bool needDir)
161
ret = stat(path.c_str(), &statbuf);
162
if (ret != 0) return false;
164
if ((needDir && (!S_ISDIR(statbuf.st_mode))) ||
165
(!needDir && (S_ISDIR(statbuf.st_mode)))) return false;
170
time_t check_path_ex(String path, bool needDir, bool existenceUnneeded,
176
if (filesize != NULL)
179
ret = stat(path.c_str(), &statbuf);
182
if (existenceUnneeded && (errno == ENOENT))
185
throw _Exception(path + " : " + errno + (int)existenceUnneeded+ " x " + mt_strerror(errno));
188
if (needDir && (!S_ISDIR(statbuf.st_mode)))
189
throw _Exception(_("Not a directory: ") + path);
191
if (!needDir && (S_ISDIR(statbuf.st_mode)))
192
throw _Exception(_("Not a file: ") + path);
194
if ((filesize != NULL) && S_ISREG(statbuf.st_mode))
195
*filesize = statbuf.st_size;
197
return statbuf.st_mtime;
200
bool is_executable(String path, int *err)
202
int ret = access(path.c_str(), R_OK | X_OK);
212
String find_in_path(String exec)
214
String PATH = String(getenv("PATH"));
215
if (!string_ok(PATH))
218
Ref<StringTokenizer> st(new StringTokenizer(PATH));
224
path = st->nextToken(_(":"));
225
next = st->nextToken(_(":"));
230
if ((next != nil) && !next.startsWith(_("/")))
232
path = path + _(":") + next;
236
String check = path + _("/") + exec;
237
if (check_path(check))
246
} while (path != nil);
251
bool string_ok(String str)
253
if ((str == nil) || (str == ""))
258
bool string_ok(Ref<StringBuffer> str)
261
if ((str == nil) || (str->length()<=0))
267
void string_ok_ex(String str)
269
if ((str == nil) || (str == ""))
270
throw _Exception(_("Empty string"));
273
String http_redirect_to(String ip, String port, String page)
275
return _("<html><head><meta http-equiv=\"Refresh\" content=\"0;URL=http://") + ip + ":" + port + "/" + page + "\"></head><body bgcolor=\"#dddddd\"></body></html>";
278
String hex_encode(void *data, int len)
280
unsigned char *chars;
282
unsigned char hi, lo;
284
Ref<StringBuffer> buf(new StringBuffer(len * 2));
286
chars = (unsigned char *)data;
287
for (i = 0; i < len; i++)
289
unsigned char c = chars[i];
292
*buf << HEX_CHARS[hi] << HEX_CHARS[lo];
294
return buf->toString();
298
String hex_decode_string(String encoded)
300
char *ptr = encoded.c_str();
301
int len = encoded.length();
303
Ref<StringBuffer> buf(new StringBuffer(len / 2));
304
for (int i = 0; i < len; i += 2)
306
char *chi = strchr(HEX_CHARS, ptr[i]);
307
char *clo = strchr(HEX_CHARS, ptr[i + 1]);
311
hi = chi - HEX_CHARS;
316
lo = clo - HEX_CHARS;
319
char ch = (char)(hi << 4 | lo);
322
return buf->toString();
330
String hex_md5(void *data, int length)
336
md5_append(&ctx, (unsigned char *)data, length);
337
md5_finish(&ctx, (unsigned char *)md5buf);
339
return hex_encode(md5buf, 16);
341
String hex_string_md5(String str)
343
return hex_md5(str.c_str(), str.length());
345
String generate_random_id()
347
struct randomizer st;
348
gettimeofday(&st.tv, NULL);
350
return hex_md5(&st, sizeof(st));
354
static const char *hex = "0123456789ABCDEF";
356
String url_escape(String str)
358
char *data = str.c_str();
359
int len = str.length();
360
Ref<StringBuffer> buf(new StringBuffer(len));
361
for (int i = 0; i < len; i++)
363
unsigned char c = (unsigned char)data[i];
364
if ((c >= '0' && c <= '9') ||
365
(c >= 'A' && c <= 'Z') ||
366
(c >= 'a' && c <= 'z') ||
376
*buf << '%' << hex[hi] << hex[lo];
379
return buf->toString();
382
String url_unescape(String str)
384
char *data = str.c_str();
385
int len = str.length();
386
Ref<StringBuffer> buf(new StringBuffer(len));
395
break; // avoid buffer overrun
396
char chi = data[i++];
397
char clo = data[i++];
402
pos = strchr(hex, chi);
408
pos = strchr(hex, clo);
414
int ascii = (hi << 4) | lo;
426
return buf->toString();
429
String mime_types_to_CSV(Ref<Array<StringBase> > mimeTypes)
431
Ref<StringBuffer> buf(new StringBuffer());
432
for (int i = 0; i < mimeTypes->size(); i++)
436
String mimeType = mimeTypes->get(i);
437
*buf << "http-get:*:" << mimeType << ":*";
440
return buf->toString();
443
String mt_strerror(int mt_errno)
445
#ifdef DONT_USE_YET_HAVE_STRERROR_R
446
char *buffer = (char *)MALLOC(512);
448
#ifdef STRERROR_R_CHAR_P
449
err_str = strerror_r(errno, buffer, 512);
453
int ret = strerror_r(errno, buffer, 512);
455
return _("cannot get error string: error while calling XSI-compliant strerror_r");
458
String errStr(err_str);
462
return String(strerror(errno));
466
String read_text_file(String path)
468
FILE *f = fopen(path.c_str(), "r");
471
throw _Exception(_("read_text_file: could not open ") +
472
path + " : " + mt_strerror(errno));
474
Ref<StringBuffer> buf(new StringBuffer());
475
char *buffer = (char *)MALLOC(1024);
477
while((bytesRead = fread(buffer, 1, 1024, f)) > 0)
479
buf->concat(buffer, bytesRead);
483
return buf->toString();
485
void write_text_file(String path, String contents)
488
FILE *f = fopen(path.c_str(), "w");
491
throw _Exception(_("write_text_file: could not open ") +
492
path + " : " + mt_strerror(errno));
495
bytesWritten = fwrite(contents.c_str(), 1, contents.length(), f);
496
if (bytesWritten < contents.length())
499
if (bytesWritten >= 0)
500
throw _Exception(_("write_text_file: incomplete write to ") +
503
throw _Exception(_("write_text_file: error writing to ") +
504
path + " : " + mt_strerror(errno));
509
void copy_file(String from, String to)
511
FILE *f = fopen(from.c_str(), "r");
514
throw _Exception(_("copy_file: could not open ") +
515
from + " for read: " + mt_strerror(errno));
517
FILE *t = fopen(to.c_str(), "w");
521
throw _Exception(_("copy_file: could not open ") +
522
to + " for write: " + mt_strerror(errno));
524
char *buffer = (char *)MALLOC(1024);
525
size_t bytesRead = 0;
526
size_t bytesWritten = 0;
527
while(bytesRead == bytesWritten && ! feof(f) && ! ferror(f) && ! ferror(t)
528
&& (bytesRead = fread(buffer, 1, 1024, f)) > 0)
530
bytesWritten = fwrite(buffer, 1, bytesRead, t);
533
if (ferror(f) || ferror(t))
535
int my_errno = errno;
538
throw _Exception(_("copy_file: error while copying ") + from + " to " +
539
to + ": " + mt_strerror(my_errno));
547
int StringBaseComparator(void *arg1, void *arg2)
549
return strcmp(((StringBase *)arg1)->data, ((StringBase *)arg2)->data);
552
static void quicksort_impl(COMPARABLE *a, int lo0, int hi0, COMPARATOR comparator)
561
// sort a two element list by swapping if necessary
562
// if (a[lo] > a[hi])
563
if (comparator(a[lo], a[hi]) > 0)
565
COMPARABLE T = a[lo];
572
// Pick a pivot and move it out of the way
573
COMPARABLE pivot = a[(lo + hi) / 2];
574
a[(lo + hi) / 2] = a[hi];
579
/* Search forward from a[lo] until an element is found that
580
is greater than the pivot or lo >= hi */
581
// while (a[lo] <= pivot && lo < hi)
582
while (comparator(a[lo], pivot) <= 0 && lo < hi)
587
/* Search backward from a[hi] until element is found that
588
is less than the pivot, or lo >= hi */
589
// while (pivot <= a[hi] && lo < hi )
590
while (comparator(pivot, a[hi]) <= 0 && lo < hi)
595
/* Swap elements a[lo] and a[hi] */
598
COMPARABLE T = a[lo];
604
/* Put the median in the "center" of the list */
609
* Recursive calls, elements a[lo0] to a[lo-1] are less than or
610
* equal to pivot, elements a[hi+1] to a[hi0] are greater than
613
quicksort_impl(a, lo0, lo-1, comparator);
614
quicksort_impl(a, hi+1, hi0, comparator);
617
void quicksort(COMPARABLE *arr, int size, COMPARATOR comparator)
619
quicksort_impl(arr, 0, size - 1, comparator);
622
String renderProtocolInfo(String mimetype, String protocol, String extend)
624
if (string_ok(mimetype) && string_ok(protocol))
626
if (string_ok(extend))
627
return protocol + ":*:" + mimetype + ":" + extend;
629
return protocol + ":*:" + mimetype + ":*";
632
return _("http-get:*:*:*");
635
String getMTFromProtocolInfo(String protocol)
637
Ref<Array<StringBase> > parts = split_string(protocol, ':');
638
if (parts->size() > 2)
639
return parts->get(2);
644
String getProtocol(String protocolInfo)
647
int pos = protocolInfo.index(':');
649
protocol = _("http-get");
651
protocol = protocolInfo.substring(0, pos);
656
String secondsToHMS(int seconds)
667
char *str = (char *)malloc(10);
668
sprintf(str, "%02d:%02d:%02d", h, m, s);
669
return String::take(str);
673
String get_mime_type(magic_set *ms, Ref<RExp> reMimetype, String file)
678
char *mt = (char *)magic_file(ms, file.c_str());
681
log_error("magic_file: %s\n", magic_error(ms));
685
String mime_type(mt);
687
Ref<Matcher> matcher = reMimetype->matcher(mime_type, 2);
689
return matcher->group(1);
691
log_warning("filemagic returned invalid mimetype for %s\n%s\n",
696
String get_mime_type_from_buffer(magic_set *ms, Ref<RExp> reMimetype,
697
void *buffer, size_t length)
702
char *mt = (char *)magic_buffer(ms, buffer, length);
705
log_error("magic_file: %s\n", magic_error(ms));
709
String mime_type(mt);
711
Ref<Matcher> matcher = reMimetype->matcher(mime_type, 2);
713
return matcher->group(1);
715
log_warning("filemagic returned invalid mimetype for the given buffer%s\n",
721
void set_jpeg_resolution_resource(Ref<CdsItem> item, int res_num)
725
Ref<IOHandler> fio_h(new FileIOHandler(item->getLocation()));
726
fio_h->open(UPNP_READ);
727
String resolution = get_jpeg_resolution(fio_h);
729
if (res_num >= item->getResourceCount())
730
throw _Exception(_("Invalid resource index"));
732
item->getResource(res_num)->addAttribute(MetadataHandler::getResAttrName(R_RESOLUTION), resolution);
740
bool check_resolution(String resolution, int *x, int *y)
748
Ref<Array<StringBase> > parts = split_string(resolution, 'x');
749
if (parts->size() != 2)
752
if (string_ok(parts->get(0)) &&
753
string_ok(parts->get(1)))
755
int _x = String(parts->get(0)->data).toInt();
756
int _y = String(parts->get(1)->data).toInt();
758
if ((_x > 0) && (_y > 0))
774
String escape(String string, char escape_char, char to_escape)
776
Ref<StringBase> stringBase(new StringBase(string.length() * 2));
777
char *str = stringBase->data;
778
int len = string.length();
780
bool possible_more_esc = true;
781
bool possible_more_char = true;
787
if (possible_more_esc)
789
next_esc = string.index(last, escape_char);
791
possible_more_esc = false;
795
if (possible_more_char)
797
next = string.index(last, to_escape);
799
possible_more_char = false;
802
if (next < 0 || (next_esc >= 0 && next_esc < next))
809
int cpLen = next - last;
812
strncpy(str, string.charPtrAt(last), cpLen);
818
*(str++) = string.charAt(next);
826
stringBase->len = strlen(stringBase->data);
827
return String(stringBase->data);
830
String unescape(String string, char escape)
832
Ref<StringBase> stringBase(new StringBase(string.length()));
833
char *str = stringBase->data;
834
int len = string.length();
839
int next = string.index(last + 1, escape);
844
int cpLen = next - last;
846
strncpy(str, string.charPtrAt(last), cpLen);
854
stringBase->len = strlen(stringBase->data);
855
return String(stringBase);
859
String xml_unescape(String string)
861
Ref<StringBuffer> buf(new StringBuffer(string.length()));
862
signed char *ptr = (signed char *)string.c_str();
867
if ((*(ptr + 1) == 'l') && (*(ptr + 2) == 't') &&
873
else if ((*(ptr + 1) == 'g') && (*(ptr + 2) == 't') &&
879
else if ((*(ptr + 1) == 'q') && (*(ptr + 2) == 'u') &&
880
(*(ptr + 3) == 'o') && (*(ptr + 4) == 't') &&
886
else if (*(ptr + 1) == 'a')
888
if ((*(ptr + 2) == 'm') && (*(ptr + 3) == 'p') &&
894
else if ((*(ptr + 2) == 'p') && (*(ptr + 3) == 'o') &&
895
(*(ptr + 4) == 's') && (*(ptr + 5) == ';'))
910
return buf->toString();
914
String unescape_amp(String string)
918
Ref<StringBase> stringBase(new StringBase(string.length()));
919
char *str = stringBase->data;
920
int len = string.length();
929
next = string.index(next + 1, '&');
930
if ((next < len) && (string.charAt(next + 1) == 'a') &&
931
(string.charAt(next + 2) == 'm') &&
932
(string.charAt(next + 3) == 'p') &&
933
(string.charAt(next + 4) == ';'))
938
while(next > 0 && skip == 0);
943
int cpLen = next - last + 1;
944
strncpy(str, string.charPtrAt(last), cpLen);
946
last = next + skip + 1;
950
stringBase->len = str - stringBase->data - 1;
951
assert(stringBase->len == (int)strlen(stringBase->data));
952
return String(stringBase);
955
String fallbackString(String first, String fallback)
962
unsigned int stringHash(String str)
964
unsigned int hash = 5381;
965
unsigned char *data = (unsigned char *)str.c_str();
967
while ((c = *data++))
968
hash = ((hash << 5) + hash) ^ c; /* (hash * 33) ^ c */
972
String intArrayToCSV(int *array, int size)
976
Ref<StringBuffer> buf(new StringBuffer());
977
for (int i = 0; i < size; i++)
978
*buf << ',' << array[i];
979
return buf->toString(1);
982
void getTimespecNow(struct timespec *ts)
985
int ret = gettimeofday(&tv, NULL);
987
throw _Exception(_("gettimeofday failed: ") + mt_strerror(errno));
989
ts->tv_sec = tv.tv_sec;
990
ts->tv_nsec = tv.tv_usec * 1000;
993
long getDeltaMillis(struct timespec *first)
996
getTimespecNow(&now);
997
return getDeltaMillis(first, &now);
1000
long getDeltaMillis(struct timespec *first, struct timespec *second)
1002
return (second->tv_sec - first->tv_sec) * 1000 + (second->tv_nsec - first->tv_nsec) / 1000000;
1005
void getTimespecAfterMillis(long delta, struct timespec *ret, struct timespec *start)
1007
struct timespec now;
1010
getTimespecNow(&now);
1013
ret->tv_sec = start->tv_sec + delta / 1000;
1014
ret->tv_nsec = (start->tv_nsec + (delta % 1000) * 1000000);
1015
if (ret->tv_nsec >= 1000000000) // >= 1 second
1018
ret->tv_nsec -= 1000000000;
1021
//log_debug("timespec: sec: %ld, nsec: %ld\n", ret->tv_sec, ret->tv_nsec);
1024
int compareTimespecs(struct timespec *a, struct timespec *b)
1026
if (a->tv_sec < b->tv_sec)
1028
if (a->tv_sec > b->tv_sec)
1030
if (a->tv_nsec < b->tv_nsec)
1032
if (a->tv_nsec > b->tv_nsec)
1037
String normalizePath(String path)
1039
log_debug("Normalizing path: %s\n", path.c_str());
1041
int length = path.length();
1043
Ref<StringBase> result(new StringBase(length));
1045
int avarageExpectedSlashes = length/5;
1046
if (avarageExpectedSlashes < 3)
1047
avarageExpectedSlashes = 3;
1048
Ref<BaseStack<int> > separatorLocations(new BaseStack<int>(avarageExpectedSlashes, -1));
1049
char *str = result->data;
1050
//int len = string.length();
1053
if (path.charAt(0) != DIR_SEPARATOR)
1055
#error !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! this function is not finished for Cygwin
1056
for (int i = 0; i < 20; i++)
1058
/// \todo this doesn't seem to be correct...
1059
if ((!path.length() > 1) && (path.charAt(1) != ':'))
1061
throw _Exception(_("Relative paths are not allowed!\n"));
1066
while (next < length && path.charAt(next) == DIR_SEPARATOR)
1071
int next_sep = path.index(next, DIR_SEPARATOR);
1074
if (next_sep == next + 1 && path.charAt(next) == '.')
1076
// "." - can be ignored
1078
else if (next_sep == next + 2 &&
1079
next + 1 < length &&
1080
path.charAt(next) == '.' &&
1081
path.charAt(next + 1) == '.')
1085
int lastSepLocation = separatorLocations->pop();
1086
if (lastSepLocation < 0)
1087
lastSepLocation = 0;
1088
str = result->data + lastSepLocation;
1093
separatorLocations->push(str - result->data);
1094
*(str++) = DIR_SEPARATOR;
1095
int cpLen = next_sep - next;
1096
strncpy(str, path.charPtrAt(next), cpLen);
1099
next = next_sep + 1;
1101
while(next < length);
1103
if (str == result->data)
1104
*(str++) = DIR_SEPARATOR;
1107
result->len = strlen(result->data);
1108
return String(result);
1111
String interfaceToIP(String interface)
1113
#if defined(__CYGWIN__)
1114
struct hostent *h=NULL;
1115
struct sockaddr_in LocalAddr;
1116
char *hostname = (char *)MALLOC(256);
1120
gethostname(hostname, 255);
1121
hostname[255] = '\0';
1122
h=gethostbyname(hostname);
1126
memcpy(&LocalAddr.sin_addr, h->h_addr_list[0],4);
1127
return String(inet_ntoa(LocalAddr.sin_addr));
1132
struct if_nameindex *iflist = NULL;
1133
struct if_nameindex *iflist_free = NULL;
1134
struct ifreq if_request;
1135
struct sockaddr_in local_address;
1138
if (!string_ok(interface))
1141
local_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
1142
if (local_socket < 0)
1144
log_error("Could not create local socket: %s\n",
1145
mt_strerror(errno).c_str());
1149
iflist = iflist_free = if_nameindex();
1152
log_error("Could not get interface list: %s\n",
1153
mt_strerror(errno).c_str());
1154
close(local_socket);
1158
while (iflist->if_index || iflist->if_name)
1160
if (interface == iflist->if_name)
1162
strncpy(if_request.ifr_name, iflist->if_name, IF_NAMESIZE);
1163
if (ioctl(local_socket, SIOCGIFADDR, &if_request) != 0)
1165
log_error("Could not determine interface address: %s\n",
1166
mt_strerror(errno).c_str());
1167
close(local_socket);
1168
if_freenameindex(iflist_free);
1172
memcpy(&local_address, &if_request.ifr_addr, sizeof(if_request.ifr_addr));
1173
String ip = String(inet_ntoa(local_address.sin_addr));
1174
if_freenameindex(iflist_free);
1175
close(local_socket);
1181
close(local_socket);
1182
if_freenameindex(iflist_free);
1187
bool validateYesNo(String value)
1189
if ((value != "yes") && (value != "no"))
1195
Ref<Array<StringBase> > parseCommandLine(String line, String in, String out)
1197
Ref<Array<StringBase> > params = split_string(line, ' ');
1198
if ((in == nil) && (out == nil))
1201
for (int i = 0; i < params->size(); i++)
1203
String param = params->get(i);
1204
String newParam = param.replace(_("%in"), in);
1205
newParam = newParam.replace(_("%out"), out);
1206
if (param != newParam)
1207
params->set(newParam, i);
1213
// The tempName() function is borrowed from gfileutils.c from the glibc package
1215
/* gfileutils.c - File utility functions
1217
* Copyright 2000 Red Hat, Inc.
1219
* GLib is free software; you can redistribute it and/or modify it
1220
* under the terms of the GNU Lesser General Public License as
1221
* published by the Free Software Foundation; either version 2 of the
1222
* License, or (at your option) any later version.
1224
* GLib is distributed in the hope that it will be useful,
1225
* but WITHOUT ANY WARRANTY; without even the implied warranty of
1226
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1227
* Lesser General Public License for more details.
1229
* You should have received a copy of the GNU Lesser General Public
1230
* License along with GLib; see the file COPYING.LIB. If not,
1231
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1232
* Boston, MA 02111-1307, USA.
1235
* create_temp_file based on the mkstemp implementation from the GNU C library.
1236
* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
1238
// tempName is based on create_temp_file, see (C) above
1239
String tempName(String leadPath, char *tmpl)
1243
static const char letters[] =
1244
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
1245
static const int NLETTERS = sizeof (letters) - 1;
1248
static int counter = 0;
1249
struct stat statbuf;
1252
/* find the last occurrence of "XXXXXX" */
1253
XXXXXX = strstr (tmpl, "XXXXXX");
1255
if (!XXXXXX || strncmp (XXXXXX, "XXXXXX", 6))
1260
/* Get some more or less random data. */
1261
gettimeofday(&tv, NULL);
1262
value = (tv.tv_usec ^ tv.tv_sec) + counter++;
1264
for (count = 0; count < 100; value += 7777, ++count)
1268
/* Fill in the random bits. */
1269
XXXXXX[0] = letters[v % NLETTERS];
1271
XXXXXX[1] = letters[v % NLETTERS];
1273
XXXXXX[2] = letters[v % NLETTERS];
1275
XXXXXX[3] = letters[v % NLETTERS];
1277
XXXXXX[4] = letters[v % NLETTERS];
1279
XXXXXX[5] = letters[v % NLETTERS];
1281
String check = leadPath + tmpl;
1282
ret = stat(check.c_str(), &statbuf);
1285
if ((errno == ENOENT) ||
1293
/* We got out of the loop because we ran out of combinations to try. */
1297
bool isTheora(String ogg_filename)
1301
f = fopen(ogg_filename.c_str(), "rb");
1305
throw _Exception(_("Error opening ") + ogg_filename + _(" : ") +
1306
mt_strerror(errno));
1309
if (fread(buffer, 1, 4, f) != 4)
1312
throw _Exception(_("Error reading ") + ogg_filename);
1315
if (memcmp(buffer, "OggS", 4) != 0)
1321
if (fseek(f, 28, SEEK_SET) != 0)
1324
throw _Exception(_("Incomplete file ") + ogg_filename);
1327
if (fread(buffer, 1, 7, f) != 7)
1330
throw _Exception(_("Error reading ") + ogg_filename);
1333
if (memcmp(buffer, "\x80theora", 7) != 0)
1343
String get_last_path(String location)
1347
int last_slash = location.rindex(DIR_SEPARATOR);
1350
path = location.substring(0, last_slash);
1351
int slash = path.rindex(DIR_SEPARATOR);
1352
if ((slash >= 0) && ((slash + 1) < path.length()))
1353
path = path.substring(slash+1);
1360
String getAVIFourCC(zmm::String avi_filename)
1362
#define FCC_OFFSET 0xbc
1364
FILE *f = fopen(avi_filename.c_str(), "rb");
1366
throw _Exception(_("could not open file ") + avi_filename + " : " +
1367
mt_strerror(errno));
1369
buffer = (char *)MALLOC(FCC_OFFSET+6);
1373
throw _Exception(_("Out of memory when allocating buffer for file ") +
1377
size_t rb = fread(buffer, 1, FCC_OFFSET+4, f);
1379
if (rb != FCC_OFFSET+4)
1382
throw _Exception(_("could not read header of ") + avi_filename +
1383
" : " + mt_strerror(errno));
1386
buffer[FCC_OFFSET+5] = '\0';
1388
if (strncmp(buffer, "RIFF", 4) != 0)
1394
if (strncmp(buffer+8, "AVI ", 4) != 0)
1400
String fourcc = String(buffer+FCC_OFFSET, 4);
1403
if (string_ok(fourcc))
1412
void profiling_thread_check(struct profiling_t *data)
1414
if (data->thread != pthread_self())
1416
log_debug("profiling_..() called from a different thread than profiling_init was called! (init: %d; this: %d) - aborting...\n", data->thread, pthread_self());
1424
void profiling_start(struct profiling_t *data)
1426
profiling_thread_check(data);
1429
log_debug("profiling_start() called on an already running profile! - aborting...\n");
1434
data->running = true;
1435
getTimespecNow(&(data->last_start));
1438
void profiling_end(struct profiling_t *data)
1440
profiling_thread_check(data);
1441
struct timespec now;
1442
getTimespecNow(&now);
1443
if (! data->running)
1445
log_debug("profiling_end() called on a not-running profile! - aborting...\n");
1450
struct timespec *sum = &(data->sum);
1451
struct timespec *last_start = &(data->last_start);
1452
sum->tv_sec += now.tv_sec - last_start->tv_sec;
1453
//log_debug("!!!!!! adding %d sec\n", now.tv_sec - last_start->tv_sec);
1454
if (now.tv_nsec >= last_start->tv_nsec)
1456
sum->tv_nsec += now.tv_nsec - last_start->tv_nsec;
1457
//log_debug("adding %ld nsec\n", now.tv_nsec - last_start->tv_nsec);
1461
sum->tv_nsec += 1000000000L - last_start->tv_nsec + now.tv_nsec;
1464
if(sum->tv_nsec >= 1000000000L)
1466
sum->tv_nsec -= 1000000000L;
1470
data->running = false;
1473
void profiling_print(struct profiling_t *data)
1477
log_debug("profiling_print() called on running profile! - aborting...\n");
1482
//log_debug("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\nPROFILING: took %ld sec %ld nsec thread %u\n", data->sum.tv_sec, data->sum.tv_nsec, pthread_self());
1483
log_debug("PROFILING: took %ld sec %ld nsec\n", data->sum.tv_sec, data->sum.tv_nsec);
1490
int find_local_port(unsigned short range_min, unsigned short range_max)
1493
int retry_count = 0;
1495
struct sockaddr_in server_addr;
1496
struct hostent *server;
1498
if (range_min > range_max)
1500
log_error("min port range > max port range!\n");
1507
port = rand () % (range_max - range_min) + range_min;
1509
fd = socket(AF_INET, SOCK_STREAM, 0);
1512
log_error("could not determine free port: "
1513
"error creating socket (%s)\n", mt_strerror(errno).c_str());
1517
server = gethostbyname("127.0.0.1");
1520
log_error("could not resolve localhost\n");
1525
memset(&server_addr, 0, sizeof(server_addr));
1526
server_addr.sin_family = AF_INET;
1527
memcpy(&server_addr.sin_addr.s_addr, server->h_addr, server->h_length);
1528
server_addr.sin_port = htons(port);
1530
if (connect(fd, (struct sockaddr *)&server_addr,
1531
sizeof(server_addr)) == -1)
1539
} while (retry_count < USHRT_MAX);
1541
log_error("Could not find free port on localhost\n");