32 #define MAXSYSLOGBUF 256
40 vsyslog(priority, fmt, ap);
52 ssize_t
safe_read(
int filedes,
void *buffer,
size_t size)
55 ssize_t p = read(filedes, buffer, size);
56 if (p < 0 && errno == EINTR) {
57 dsyslog(
"EINTR while reading from file handle %d - retrying", filedes);
64 ssize_t
safe_write(
int filedes,
const void *buffer,
size_t size)
67 ssize_t written = size;
68 const unsigned char *ptr = (
const unsigned char *)buffer;
70 p = write(filedes, ptr, size);
73 dsyslog(
"EINTR while writing to file handle %d - retrying", filedes);
81 return p < 0 ? p : written;
93 int w = write(fd, Data + written, Length);
102 Poller.
Poll(RetryMs);
103 if (TimeoutMs > 0 && (TimeoutMs -= t.
Elapsed()) <= 0)
116 int l =
max(dest ? strlen(dest) : 0, strlen(src)) + 1;
117 dest = (
char *)realloc(dest, l);
121 esyslog(
"ERROR: out of memory");
130 char *
strn0cpy(
char *dest,
const char *src,
size_t n)
133 for ( ; --n && (*dest = *src) != 0; dest++, src++) ;
153 char *p = strstr(s, s1);
160 if (
char *NewBuffer = (
char *)realloc(s, l + l2 - l1 + 1))
163 esyslog(
"ERROR: out of memory");
169 memmove(sof + l2, sof + l1, l - of - l1 + 1);
170 strncpy(sof, s2, l2);
178 for (
char *p = s + strlen(s) - 1; p >= s; p--) {
195 memmove(p + 1, q, strlen(q) + 1);
199 memmove(s, t, strlen(t) + 1);
210 if (strchr(chars, *p)) {
212 buffer =
MALLOC(
char, 2 * strlen(s) + 1);
213 t = buffer + (p - s);
214 s = strcpy(buffer, s);
238 const char *se = s + strlen(s) - 1;
239 const char *pe = p + strlen(p) - 1;
241 if (*pe-- != *se-- || (se < s && pe >= p))
276 int64_t n = strtoll(s, &t, 10);
292 if (strcmp(*a, s) == 0)
302 return cString::sprintf(
"%s/%s", DirName && *DirName ? DirName :
".", FileName);
308 snprintf(buf,
sizeof(buf),
"%d", n);
315 if (stat(File1, &st) == 0) {
316 dev_t dev1 = st.st_dev;
317 if (stat(File2, &st) == 0)
318 return st.st_dev == dev1;
332 struct statfs statFs;
333 if (statfs(Directory, &statFs) == 0) {
334 double blocksPerMeg = 1024.0 * 1024.0 / statFs.f_bsize;
336 *UsedMB = int((statFs.f_blocks - statFs.f_bfree) / blocksPerMeg);
337 Free = int(statFs.f_bavail / blocksPerMeg);
347 if (stat(DirName, &ds) == 0) {
348 if (S_ISDIR(ds.st_mode)) {
349 if (access(DirName, R_OK | W_OK | X_OK) == 0)
352 esyslog(
"ERROR: can't access %s", DirName);
355 esyslog(
"ERROR: %s is not a directory", DirName);
362 bool MakeDirs(
const char *FileName,
bool IsDirectory)
365 char *s = strdup(FileName);
369 while ((p = strchr(p,
'/')) != NULL || IsDirectory) {
373 if (stat(s, &fs) != 0 || !S_ISDIR(fs.st_mode)) {
374 dsyslog(
"creating directory %s", s);
375 if (mkdir(s, ACCESSPERMS) == -1) {
393 if (stat(FileName, &st) == 0) {
394 if (S_ISDIR(st.st_mode)) {
398 while ((e = d.
Next()) != NULL) {
400 if (FollowSymlinks) {
402 if (lstat(buffer, &st2) == 0) {
403 if (S_ISLNK(st2.st_mode)) {
404 int size = st2.st_size + 1;
405 char *l =
MALLOC(
char, size);
406 int n = readlink(buffer, l, size - 1);
420 else if (errno != ENOENT) {
425 dsyslog(
"removing %s", *buffer);
426 if (
remove(buffer) < 0)
435 dsyslog(
"removing %s", FileName);
436 if (
remove(FileName) < 0) {
441 else if (errno != ENOENT) {
450 bool HasIgnoredFiles =
false;
455 while ((e = d.
Next()) != NULL) {
456 if (strcmp(e->d_name,
"lost+found")) {
459 if (stat(buffer, &st) == 0) {
460 if (S_ISDIR(st.st_mode)) {
464 else if (RemoveThis && IgnoreFiles &&
StrInArray(IgnoreFiles, e->d_name))
465 HasIgnoredFiles =
true;
475 if (RemoveThis && empty) {
476 if (HasIgnoredFiles) {
477 while (*IgnoreFiles) {
479 if (access(buffer, F_OK) == 0) {
480 dsyslog(
"removing %s", *buffer);
481 if (
remove(buffer) < 0) {
489 dsyslog(
"removing %s", DirName);
490 if (
remove(DirName) < 0) {
508 while (size >= 0 && (e = d.
Next()) != NULL) {
511 if (stat(buffer, &st) == 0) {
512 if (S_ISDIR(st.st_mode)) {
538 char *TargetName = canonicalize_file_name(FileName);
541 TargetName = strdup(FileName);
550 for (
int n = 0; n < 10; n++) {
556 if (access(buf, F_OK) != 0) {
558 gettimeofday(&tp1, NULL);
559 int f = open(buf, O_WRONLY | O_CREAT, DEFFILEMODE);
562 if (fdatasync(f) < 0)
566 gettimeofday(&tp2, NULL);
567 double seconds = (((
long long)tp2.tv_sec * 1000000 + tp2.tv_usec) - ((
long long)tp1.tv_sec * 1000000 + tp1.tv_usec)) / 1000000.0;
569 dsyslog(
"SpinUpDisk took %.2f seconds", seconds);
576 esyslog(
"ERROR: SpinUpDisk failed");
582 if (utime(FileName, NULL) == -1 && errno != ENOENT)
589 if (stat(FileName, &fs) == 0)
597 if (stat(FileName, &fs) == 0)
614 #if _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK)
615 #define MIN_RESOLUTION 5 // ms
616 static bool initialized =
false;
617 static bool monotonic =
false;
621 if (clock_getres(CLOCK_MONOTONIC, &tp) == 0) {
622 long Resolution = tp.tv_nsec;
624 if (tp.tv_sec == 0 && tp.tv_nsec <= MIN_RESOLUTION * 1000000) {
625 if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
626 dsyslog(
"cTimeMs: using monotonic clock (resolution is %ld ns)", Resolution);
630 esyslog(
"cTimeMs: clock_gettime(CLOCK_MONOTONIC) failed");
633 dsyslog(
"cTimeMs: not using monotonic clock - resolution is too bad (%ld s %ld ns)", tp.tv_sec, tp.tv_nsec);
636 esyslog(
"cTimeMs: clock_getres(CLOCK_MONOTONIC) failed");
640 if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
641 return (uint64_t(tp.tv_sec)) * 1000 + tp.tv_nsec / 1000000;
642 esyslog(
"cTimeMs: clock_gettime(CLOCK_MONOTONIC) failed");
647 # warning Posix monotonic clock not available
650 if (gettimeofday(&t, NULL) == 0)
651 return (uint64_t(t.tv_sec)) * 1000 + t.tv_usec / 1000;
678 #define MT(s, m, v) ((*(s) & (m)) == (v)) // Mask Test
679 if (
MT(s, 0xE0, 0xC0) &&
MT(s + 1, 0xC0, 0x80))
681 if (
MT(s, 0xF0, 0xE0) &&
MT(s + 1, 0xC0, 0x80) &&
MT(s + 2, 0xC0, 0x80))
683 if (
MT(s, 0xF8, 0xF0) &&
MT(s + 1, 0xC0, 0x80) &&
MT(s + 2, 0xC0, 0x80) &&
MT(s + 3, 0xC0, 0x80))
695 case 2:
return ((*s & 0x1F) << 6) | (*(s + 1) & 0x3F);
696 case 3:
return ((*s & 0x0F) << 12) | ((*(s + 1) & 0x3F) << 6) | (*(s + 2) & 0x3F);
697 case 4:
return ((*s & 0x07) << 18) | ((*(s + 1) & 0x3F) << 12) | ((*(s + 2) & 0x3F) << 6) | (*(s + 3) & 0x3F);
712 *s++ = ((c >> 6) & 0x1F) | 0xC0;
713 *s = (c & 0x3F) | 0x80;
719 *s++ = ((c >> 12) & 0x0F) | 0xE0;
720 *s++ = ((c >> 6) & 0x3F) | 0x80;
721 *s = (c & 0x3F) | 0x80;
727 *s++ = ((c >> 18) & 0x07) | 0xF0;
728 *s++ = ((c >> 12) & 0x3F) | 0x80;
729 *s++ = ((c >> 6) & 0x3F) | 0x80;
730 *s = (c & 0x3F) | 0x80;
742 while (*s && Symbols--) {
784 while (*s && --Size > 0) {
786 *a++ = (
uchar)(*s++);
803 while (*a && NumChars < Size) {
804 if (Max >= 0 && NumSyms++ >= Max)
812 if (NumChars + sl <= Size) {
837 cd = iconv_open(ToCode, FromCode);
852 if (!strcasestr(CharacterTable,
"UTF-8")) {
855 for (
int i = 0; i < 128; i++)
859 const char *s = csc.
Convert(buf);
873 if (
cd != (iconv_t)-1 && From && *From) {
874 char *FromPtr = (
char *)From;
875 size_t FromLength = strlen(From);
878 int NewLength =
max(
length, FromLength * 2);
879 if (
char *NewBuffer = (
char *)realloc(
result, NewLength)) {
884 esyslog(
"ERROR: out of memory");
893 char *Converted = ToPtr;
894 while (FromLength > 0) {
895 if (iconv(
cd, &FromPtr, &FromLength, &ToPtr, &ToLength) ==
size_t(-1)) {
896 if (errno == E2BIG || errno == EILSEQ && ToLength < 1) {
900 size_t d = ToPtr -
result;
902 int NewLength =
length + r;
903 if (
char *NewBuffer = (
char *)realloc(result, NewLength)) {
905 Converted = result = NewBuffer;
908 esyslog(
"ERROR: out of memory");
914 if (errno == EILSEQ) {
921 else if (errno != E2BIG)
935 s = TakePointer ? (
char *)S : S ? strdup(S) : NULL;
940 s = String.
s ? strdup(String.
s) : NULL;
953 s = String.
s ? strdup(String.
s) : NULL;
962 s = String ? strdup(String) : NULL;
971 if (Index >= 0 && Index < l)
981 if (!fmt || vasprintf(&buffer, fmt, ap) < 0) {
982 esyslog(
"error in vasprintf('%s', ...)", fmt);
983 buffer = strdup(
"???");
992 if (!fmt || vasprintf(&buffer, fmt, ap) < 0) {
993 esyslog(
"error in vasprintf('%s', ...)", fmt);
994 buffer = strdup(
"???");
1002 WeekDay = WeekDay == 0 ? 6 : WeekDay - 1;
1003 if (0 <= WeekDay && WeekDay <= 6) {
1005 const char *day =
tr(
"MonTueWedThuFriSatSun");
1017 return WeekDayName(localtime_r(&t, &tm_r)->tm_wday);
1022 WeekDay = WeekDay == 0 ? 6 : WeekDay - 1;
1024 case 0:
return tr(
"Monday");
1025 case 1:
return tr(
"Tuesday");
1026 case 2:
return tr(
"Wednesday");
1027 case 3:
return tr(
"Thursday");
1028 case 4:
return tr(
"Friday");
1029 case 5:
return tr(
"Saturday");
1030 case 6:
return tr(
"Sunday");
1031 default:
return "???";
1047 tm *tm = localtime_r(&t, &tm_r);
1048 snprintf(buffer,
sizeof(buffer),
"%s %02d.%02d. %02d:%02d", *
WeekDayName(tm->tm_wday), tm->tm_mday, tm->tm_mon + 1, tm->tm_hour, tm->tm_min);
1055 if (ctime_r(&t, buffer)) {
1056 buffer[strlen(buffer) - 1] = 0;
1066 tm *tm = localtime_r(&t, &tm_r);
1069 strftime(p,
sizeof(buf) - (p - buf),
"%d.%m.%Y", tm);
1077 tm *tm = localtime_r(&t, &tm_r);
1078 strftime(buf,
sizeof(buf),
"%d.%m.%y", tm);
1086 strftime(buf,
sizeof(buf),
"%R", localtime_r(&t, &tm_r));
1092 #define JPEGCOMPRESSMEM 500000
1112 int Used = jcd->
size;
1114 if (
uchar *NewBuffer = (
uchar *)realloc(jcd->
mem, NewSize)) {
1115 jcd->
size = NewSize;
1116 jcd->
mem = NewBuffer;
1119 esyslog(
"ERROR: out of memory");
1123 cinfo->dest->next_output_byte = jcd->
mem + Used;
1124 cinfo->dest->free_in_buffer = jcd->
size - Used;
1135 int Used = cinfo->dest->next_output_byte - jcd->
mem;
1136 if (Used < jcd->size) {
1139 jcd->
mem = NewBuffer;
1142 esyslog(
"ERROR: out of memory");
1151 else if (Quality > 100)
1154 jpeg_destination_mgr jdm;
1160 struct jpeg_compress_struct cinfo;
1161 struct jpeg_error_mgr jerr;
1162 cinfo.err = jpeg_std_error(&jerr);
1163 jpeg_create_compress(&cinfo);
1166 cinfo.client_data = &jcd;
1167 cinfo.image_width = Width;
1168 cinfo.image_height = Height;
1169 cinfo.input_components = 3;
1170 cinfo.in_color_space = JCS_RGB;
1172 jpeg_set_defaults(&cinfo);
1173 jpeg_set_quality(&cinfo, Quality,
true);
1174 jpeg_start_compress(&cinfo,
true);
1177 JSAMPROW rp[Height];
1178 for (
int k = 0; k < Height; k++)
1179 rp[k] = &Mem[rs * k];
1180 jpeg_write_scanlines(&cinfo, rp, Height);
1181 jpeg_finish_compress(&cinfo);
1182 jpeg_destroy_compress(&cinfo);
1190 const char *
cBase64Encoder::b64 =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1213 c |= (
data[
i] >> 4) & 0x0F;
1216 c = (
data[
i] << 2) & 0x3F;
1218 c |= (
data[
i] >> 6) & 0x03;
1317 Add(FileHandle, Out);
1322 if (FileHandle >= 0) {
1324 if (
pfd[i].fd == FileHandle &&
pfd[i].events == (Out ? POLLOUT : POLLIN))
1334 esyslog(
"ERROR: too many file handles in cPoller");
1366 if (strcmp(
result->d_name,
".") && strcmp(
result->d_name,
".."))
1382 for (
int i = 0; i <
Size(); i++) {
1383 if (!strcmp(s,
At(i)))
1391 for (
int i = 0; i <
Size(); i++)
1401 Load(Directory, DirsOnly);
1411 while ((e = d.
Next()) != NULL) {
1414 if (stat(
AddDirectory(Directory, e->d_name), &ds) == 0) {
1415 if (!S_ISDIR(ds.st_mode))
1419 Append(strdup(e->d_name));
1448 return Open(open(FileName, Flags, Mode));
1449 esyslog(
"ERROR: attempt to re-open %s", FileName);
1459 if (
f < FD_SETSIZE) {
1465 esyslog(
"ERROR: file descriptor %d already in files[]", f);
1469 esyslog(
"ERROR: file descriptor %d is larger than FD_SETSIZE (%d)",
f, FD_SETSIZE);
1473 esyslog(
"ERROR: attempt to re-open file descriptor %d", FileDes);
1496 for (
int i = 0; i <
maxFiles; i++) {
1500 if (0 <= FileDes && FileDes < FD_SETSIZE && !
files[FileDes])
1501 FD_SET(FileDes, &
set);
1504 struct timeval timeout;
1505 timeout.tv_sec = TimeoutMs / 1000;
1506 timeout.tv_usec = (TimeoutMs % 1000) * 1000;
1507 return select(FD_SETSIZE, &
set, NULL, NULL, &timeout) > 0 && (FileDes < 0 || FD_ISSET(FileDes, &
set));
1513 struct timeval timeout;
1515 FD_SET(FileDes, &
set);
1516 if (TimeoutMs >= 0) {
1517 if (TimeoutMs < 100)
1519 timeout.tv_sec = TimeoutMs / 1000;
1520 timeout.tv_usec = (TimeoutMs % 1000) * 1000;
1522 return select(FD_SETSIZE, &
set, NULL, NULL, (TimeoutMs >= 0) ? &timeout : NULL) > 0 && FD_ISSET(FileDes, &
set);
1528 struct timeval timeout;
1530 FD_SET(FileDes, &
set);
1531 if (TimeoutMs < 100)
1534 timeout.tv_usec = TimeoutMs * 1000;
1535 return select(FD_SETSIZE, NULL, &
set, NULL, &timeout) > 0 && FD_ISSET(FileDes, &
set);
1572 if (ferror(
f) != 0) {
1578 if (fclose(
f) < 0) {
1597 #define WRITE_BUFFER KILOBYTE(800)
1612 fd = open(FileName, Flags, Mode);
1622 posix_fadvise(
fd, 0, 0, POSIX_FADV_RANDOM);
1633 posix_fadvise(
fd, 0, 0, POSIX_FADV_DONTNEED);
1637 return close(OldFd);
1648 #define FADVGRAN KILOBYTE(4) // AKA fadvise-chunk-size; PAGE_SIZE or getpagesize(2) would also work.
1649 #define READCHUNK MEGABYTE(8)
1659 return posix_fadvise(
fd, Offset - (
FADVGRAN - 1), Len + (
FADVGRAN - 1) * 2, POSIX_FADV_DONTNEED);
1664 if (Whence == SEEK_SET && Offset ==
curpos)
1666 curpos = lseek(
fd, Offset, Whence);
1684 if (bytesRead > 0) {
1691 if (jumped >= 0 && jumped <= (off_t)
readahead) {
1696 posix_fadvise(
fd,
curpos, readahead, POSIX_FADV_WILLNEED);
1700 if (readahead < Size * 32) {
1701 readahead = Size * 32;
1733 if (bytesWritten > 0) {
1774 return bytesWritten;
1782 if (File->
Open(FileName, Flags, Mode) < 0) {
1791 #define LOCKFILENAME ".lock-vdr"
1792 #define LOCKFILESTALETIME 600 // seconds before considering a lock file "stale"
1811 time_t Timeout = time(NULL) + WaitSeconds;
1813 f = open(
fileName, O_WRONLY | O_CREAT | O_EXCL, DEFFILEMODE);
1815 if (errno == EEXIST) {
1827 else if (errno != ENOENT) {
1839 }
while (
f < 0 && time(NULL) < Timeout);
1867 Object->
prev =
this;
1873 Object->
next =
this;
1928 if (Before && Before !=
objects) {
1961 if (From && To && From != To) {
1999 while (
object && Index-- > 0)
2000 object =
object->
Next();
2017 while (
object && i < n) {
2019 object =
object->
Next();
2023 for (i = 0; i < n; i++) {
2046 unsigned int hash =
hashfn(Id);
2057 if (hob->object == Object) {
2067 for (
int i = 0; i <
size; i++) {