SASC
DVBSoftCAM

tools.cpp File Reference

#include "include/vdr/tools.h"
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/vfs.h>
#include <time.h>
#include <unistd.h>
#include "include/vdr/i18n.h"
#include "include/vdr/thread.h"

Go to the source code of this file.

Defines

#define MAXSYSLOGBUF   256
#define LOCKFILENAME   ".lock-vdr"
#define LOCKFILESTALETIME   600

Functions

void syslog_with_tid (int priority, const char *format,...)
int BCD2INT (int x)
ssize_t safe_read (int filedes, void *buffer, size_t size)
ssize_t safe_write (int filedes, const void *buffer, size_t size)
void writechar (int filedes, char c)
int WriteAllOrNothing (int fd, const uchar *Data, int Length, int TimeoutMs, int RetryMs)
char * strcpyrealloc (char *dest, const char *src)
char * strn0cpy (char *dest, const char *src, size_t n)
char * strreplace (char *s, char c1, char c2)
char * strreplace (char *s, const char *s1, const char *s2)
 re-allocates 's' and deletes the original string if necessary!
char * skipspace (const char *s)
char * stripspace (char *s)
char * compactspace (char *s)
cString strescape (const char *s, const char *chars)
bool startswith (const char *s, const char *p)
bool endswith (const char *s, const char *p)
bool isempty (const char *s)
int numdigits (int n)
bool isnumber (const char *s)
cString AddDirectory (const char *DirName, const char *FileName)
cString itoa (int n)
int FreeDiskSpaceMB (const char *Directory, int *UsedMB)
bool DirectoryOk (const char *DirName, bool LogErrors)
bool MakeDirs (const char *FileName, bool IsDirectory)
bool RemoveFileOrDir (const char *FileName, bool FollowSymlinks)
bool RemoveEmptyDirectories (const char *DirName, bool RemoveThis)
char * ReadLink (const char *FileName)
 returns a new string allocated on the heap, which the caller must delete (or NULL in case of an error)
bool SpinUpDisk (const char *FileName)
time_t LastModifiedTime (const char *FileName)
cString WeekDayName (int WeekDay)
cString WeekDayName (time_t t)
cString DayDateTime (time_t t)
cString TimeToString (time_t t)
cString DateString (time_t t)
cString TimeString (time_t t)
static int CompareListObjects (const void *a, const void *b)

Variables

int SysLogLevel = 3

Define Documentation

#define LOCKFILENAME   ".lock-vdr"

Definition at line 847 of file tools.cpp.

Referenced by cLockFile::cLockFile().

#define LOCKFILESTALETIME   600

Definition at line 848 of file tools.cpp.

Referenced by cLockFile::Lock().

#define MAXSYSLOGBUF   256

Definition at line 25 of file tools.cpp.

Referenced by syslog_with_tid().


Function Documentation

cString AddDirectory ( const char *  DirName,
const char *  FileName 
)

Definition at line 263 of file tools.cpp.

Referenced by DllsLoad(), cScDlls::Load(), and cStructLoader::SetCfgDir().

{
  char *buf;
  asprintf(&buf, "%s/%s", DirName && *DirName ? DirName : ".", FileName);
  return cString(buf, true);
}
int BCD2INT ( int  x)

Definition at line 37 of file tools.cpp.

References BCDCHARTOINT.

Referenced by process_cam().

{
  return ((1000000 * BCDCHARTOINT((x >> 24) & 0xFF)) +
            (10000 * BCDCHARTOINT((x >> 16) & 0xFF)) +
              (100 * BCDCHARTOINT((x >>  8) & 0xFF)) +
                     BCDCHARTOINT( x        & 0xFF));
}
char* compactspace ( char *  s)

Definition at line 179 of file tools.cpp.

References skipspace(), and stripspace().

{
  if (s && *s) {
     char *t = stripspace(skipspace(s));
     char *p = t;
     while (p && *p) {
           char *q = skipspace(p);
           if (q - p > 1)
              memmove(p + 1, q, strlen(q) + 1);
           p++;
           }
     if (t != s)
        memmove(s, t, strlen(t) + 1);
     }
  return s;
}
static int CompareListObjects ( const void *  a,
const void *  b 
) [static]

Definition at line 1060 of file tools.cpp.

References cListObject::Compare().

Referenced by cListBase::Sort().

{
  const cListObject *la = *(const cListObject **)a;
  const cListObject *lb = *(const cListObject **)b;
  return la->Compare(*lb);
}
cString DateString ( time_t  t)

Definition at line 597 of file tools.cpp.

References WeekDayName().

{
  char buf[32];
  struct tm tm_r;
  tm *tm = localtime_r(&t, &tm_r);
  char *p = stpcpy(buf, WeekDayName(tm->tm_wday));
  *p++ = ' ';
  strftime(p, sizeof(buf) - (p - buf), "%d.%m.%Y", tm);
  return buf;
}
cString DayDateTime ( time_t  t)

Definition at line 576 of file tools.cpp.

References WeekDayName().

{
  char buffer[32];
  if (t == 0)
     time(&t);
  struct tm tm_r;
  tm *tm = localtime_r(&t, &tm_r);
  snprintf(buffer, sizeof(buffer), "%s %2d.%02d %02d:%02d", *WeekDayName(tm->tm_wday), tm->tm_mday, tm->tm_mon + 1, tm->tm_hour, tm->tm_min);
  return buffer;
}
bool DirectoryOk ( const char *  DirName,
bool  LogErrors 
)

Definition at line 294 of file tools.cpp.

References esyslog, and LOG_ERROR_STR.

Referenced by cLockFile::cLockFile(), and SpinUpDisk().

{
  struct stat ds;
  if (stat(DirName, &ds) == 0) {
     if (S_ISDIR(ds.st_mode)) {
        if (access(DirName, R_OK | W_OK | X_OK) == 0)
           return true;
        else if (LogErrors)
           esyslog("ERROR: can't access %s", DirName);
        }
     else if (LogErrors)
        esyslog("ERROR: %s is not a directory", DirName);
     }
  else if (LogErrors)
     LOG_ERROR_STR(DirName);
  return false;
}
bool endswith ( const char *  s,
const char *  p 
)

Definition at line 228 of file tools.cpp.

{
  const char *se = s + strlen(s) - 1;
  const char *pe = p + strlen(p) - 1;
  while (pe >= p) {
        if (*pe-- != *se-- || (se < s && pe >= p))
           return false;
        }
  return true;
}
int FreeDiskSpaceMB ( const char *  Directory,
int *  UsedMB 
)

Definition at line 277 of file tools.cpp.

References LOG_ERROR_STR.

{
  if (UsedMB)
     *UsedMB = 0;
  int Free = 0;
  struct statfs statFs;
  if (statfs(Directory, &statFs) == 0) {
     double blocksPerMeg = 1024.0 * 1024.0 / statFs.f_bsize;
     if (UsedMB)
        *UsedMB = int((statFs.f_blocks - statFs.f_bfree) / blocksPerMeg);
     Free = int(statFs.f_bavail / blocksPerMeg);
     }
  else
     LOG_ERROR_STR(Directory);
  return Free;
}
bool isempty ( const char *  s)

Definition at line 239 of file tools.cpp.

References skipspace().

Referenced by cConfig< cTimer >::Load(), cValidityRange::Parse2(), and cChannel::ShortName().

{
  return !(s && *skipspace(s));
}
bool isnumber ( const char *  s)

Definition at line 251 of file tools.cpp.

{
  if (!*s)
     return false;
  while (*s) {
        if (!isdigit(*s))
           return false;
        s++;
        }
  return true;
}
cString itoa ( int  n)

Definition at line 270 of file tools.cpp.

{
  char buf[16];
  snprintf(buf, sizeof(buf), "%d", n);
  return buf;
}
time_t LastModifiedTime ( const char *  FileName)

Definition at line 491 of file tools.cpp.

{
  struct stat fs;
  if (stat(FileName, &fs) == 0)
     return fs.st_mtime;
  return 0;
}
bool MakeDirs ( const char *  FileName,
bool  IsDirectory 
)

Definition at line 312 of file tools.cpp.

References dsyslog, free, LOG_ERROR_STR, and NULL.

{
  bool result = true;
  char *s = strdup(FileName);
  char *p = s;
  if (*p == '/')
     p++;
  while ((p = strchr(p, '/')) != NULL || IsDirectory) {
        if (p)
           *p = 0;
        struct stat fs;
        if (stat(s, &fs) != 0 || !S_ISDIR(fs.st_mode)) {
           dsyslog("creating directory %s", s);
           if (mkdir(s, ACCESSPERMS) == -1) {
              LOG_ERROR_STR(s);
              result = false;
              break;
              }
           }
        if (p)
           *p++ = '/';
        else
           break;
        }
  free(s);
  return result;
}
int numdigits ( int  n)

Definition at line 244 of file tools.cpp.

{
  char buf[16];
  snprintf(buf, sizeof(buf), "%d", n);
  return strlen(buf);
}
char* ReadLink ( const char *  FileName)

returns a new string allocated on the heap, which the caller must delete (or NULL in case of an error)

Definition at line 436 of file tools.cpp.

References esyslog, LOG_ERROR_STR, and NULL.

Referenced by cSafeFile::cSafeFile().

{
  char RealName[PATH_MAX];
  const char *TargetName = NULL;
  int n = readlink(FileName, RealName, sizeof(RealName) - 1);
  if (n < 0) {
     if (errno == ENOENT || errno == EINVAL) // file doesn't exist or is not a symlink
        TargetName = FileName;
     else // some other error occurred
        LOG_ERROR_STR(FileName);
     }
  else if (n < int(sizeof(RealName))) { // got it!
     RealName[n] = 0;
     TargetName = RealName;
     }
  else
     esyslog("ERROR: symlink's target name too long: %s", FileName);
  return TargetName ? strdup(TargetName) : NULL;
}
bool RemoveEmptyDirectories ( const char *  DirName,
bool  RemoveThis 
)

Definition at line 395 of file tools.cpp.

References dsyslog, free, LOG_ERROR_STR, cReadDir::Next(), NULL, cReadDir::Ok(), and RemoveEmptyDirectories().

Referenced by RemoveEmptyDirectories().

{
  cReadDir d(DirName);
  if (d.Ok()) {
     bool empty = true;
     struct dirent *e;
     while ((e = d.Next()) != NULL) {
           if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..") && strcmp(e->d_name, "lost+found")) {
              char *buffer;
              asprintf(&buffer, "%s/%s", DirName, e->d_name);
              struct stat st;
              if (stat(buffer, &st) == 0) {
                 if (S_ISDIR(st.st_mode)) {
                    if (!RemoveEmptyDirectories(buffer, true))
                       empty = false;
                    }
                 else
                    empty = false;
                 }
              else {
                 LOG_ERROR_STR(buffer);
                 free(buffer);
                 return false;
                 }
              free(buffer);
              }
           }
     if (RemoveThis && empty) {
        dsyslog("removing %s", DirName);
        if (remove(DirName) < 0) {
           LOG_ERROR_STR(DirName);
           return false;
           }
        }
     return empty;
     }
  else
     LOG_ERROR_STR(DirName);
  return false;
}
bool RemoveFileOrDir ( const char *  FileName,
bool  FollowSymlinks 
)

Definition at line 340 of file tools.cpp.

References dsyslog, esyslog, free, LOG_ERROR_STR, MALLOC, cReadDir::Next(), NULL, and cReadDir::Ok().

{
  struct stat st;
  if (stat(FileName, &st) == 0) {
     if (S_ISDIR(st.st_mode)) {
        cReadDir d(FileName);
        if (d.Ok()) {
           struct dirent *e;
           while ((e = d.Next()) != NULL) {
                 if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) {
                    char *buffer;
                    asprintf(&buffer, "%s/%s", FileName, e->d_name);
                    if (FollowSymlinks) {
                       int size = strlen(buffer) * 2; // should be large enough
                       char *l = MALLOC(char, size);
                       int n = readlink(buffer, l, size);
                       if (n < 0) {
                          if (errno != EINVAL)
                             LOG_ERROR_STR(buffer);
                          }
                       else if (n < size) {
                          l[n] = 0;
                          dsyslog("removing %s", l);
                          if (remove(l) < 0)
                             LOG_ERROR_STR(l);
                          }
                       else
                          esyslog("ERROR: symlink name length (%d) exceeded anticipated buffer size (%d)", n, size);
                       free(l);
                       }
                    dsyslog("removing %s", buffer);
                    if (remove(buffer) < 0)
                       LOG_ERROR_STR(buffer);
                    free(buffer);
                    }
                 }
           }
        else {
           LOG_ERROR_STR(FileName);
           return false;
           }
        }
     dsyslog("removing %s", FileName);
     if (remove(FileName) < 0) {
        LOG_ERROR_STR(FileName);
        return false;
        }
     }
  else if (errno != ENOENT) {
     LOG_ERROR_STR(FileName);
     return false;
     }
  return true;
}
ssize_t safe_read ( int  filedes,
void *  buffer,
size_t  size 
)

Definition at line 45 of file tools.cpp.

References dsyslog.

{
  for (;;) {
      ssize_t p = read(filedes, buffer, size);
      if (p < 0 && errno == EINTR) {
         dsyslog("EINTR while reading from file handle %d - retrying", filedes);
         continue;
         }
      return p;
      }
}
ssize_t safe_write ( int  filedes,
const void *  buffer,
size_t  size 
)

Definition at line 57 of file tools.cpp.

References dsyslog.

Referenced by writechar().

{
  ssize_t p = 0;
  ssize_t written = size;
  const unsigned char *ptr = (const unsigned char *)buffer;
  while (size > 0) {
        p = write(filedes, ptr, size);
        if (p < 0) {
           if (errno == EINTR) {
              dsyslog("EINTR while writing to file handle %d - retrying", filedes);
              continue;
              }
           break;
           }
        ptr  += p;
        size -= p;
        }
  return p < 0 ? p : written;
}
bool SpinUpDisk ( const char *  FileName)

Definition at line 456 of file tools.cpp.

References DirectoryOk(), dsyslog, esyslog, free, LOG_ERROR_STR, NULL, and open().

{
  char *buf = NULL;
  for (int n = 0; n < 10; n++) {
      free(buf);
      if (DirectoryOk(FileName))
         asprintf(&buf, "%s/vdr-%06d", *FileName ? FileName : ".", n);
      else
         asprintf(&buf, "%s.vdr-%06d", FileName, n);
      if (access(buf, F_OK) != 0) { // the file does not exist
         timeval tp1, tp2;
         gettimeofday(&tp1, NULL);
         int f = open(buf, O_WRONLY | O_CREAT, DEFFILEMODE);
         // O_SYNC doesn't work on all file systems
         if (f >= 0) {
            if (fdatasync(f) < 0)
               LOG_ERROR_STR(buf);
            close(f);
            remove(buf);
            gettimeofday(&tp2, NULL);
            double seconds = (((long long)tp2.tv_sec * 1000000 + tp2.tv_usec) - ((long long)tp1.tv_sec * 1000000 + tp1.tv_usec)) / 1000000.0;
            if (seconds > 0.5)
               dsyslog("SpinUpDisk took %.2f seconds\n", seconds);
            free(buf);
            return true;
            }
         else
            LOG_ERROR_STR(buf);
         }
      }
  free(buf);
  esyslog("ERROR: SpinUpDisk failed");
  return false;
}
bool startswith ( const char *  s,
const char *  p 
)

Definition at line 219 of file tools.cpp.

{
  while (*p) {
        if (*p++ != *s++)
           return false;
        }
  return true;
}
char* strcpyrealloc ( char *  dest,
const char *  src 
)

Definition at line 106 of file tools.cpp.

References esyslog, free, max(), and NULL.

{
  if (src) {
     int l = max(dest ? strlen(dest) : 0, strlen(src)) + 1; // don't let the block get smaller!
     dest = (char *)realloc(dest, l);
     if (dest)
        strcpy(dest, src);
     else
        esyslog("ERROR: out of memory");
     }
  else {
     free(dest);
     dest = NULL;
     }
  return dest;
}
cString strescape ( const char *  s,
const char *  chars 
)

Definition at line 196 of file tools.cpp.

References MALLOC, and NULL.

{
  char *buffer;
  const char *p = s;
  char *t = NULL;
  while (*p) {
        if (strchr(chars, *p)) {
           if (!t) {
              buffer = MALLOC(char, 2 * strlen(s) + 1);
              t = buffer + (p - s);
              s = strcpy(buffer, s);
              }
           *t++ = '\\';
           }
        if (t)
           *t++ = *p;
        p++;
        }
  if (t)
     *t = 0;
  return cString(s, t != NULL);
}
char* stripspace ( char *  s)

Definition at line 167 of file tools.cpp.

Referenced by cPlainKeys::Action(), compactspace(), cConfig< cTimer >::Load(), cPlainKeyDummy::Parse(), cSystemCardClient::ProcessECM(), cTransponderTime::Set(), and cScPlugin::SVDRPCommand().

{
  if (s && *s) {
     for (char *p = s + strlen(s) - 1; p >= s; p--) {
         if (!isspace(*p))
            break;
         *p = 0;
         }
     }
  return s;
}
char* strn0cpy ( char *  dest,
const char *  src,
size_t  n 
)
char* strreplace ( char *  s,
char  c1,
char  c2 
)

Definition at line 131 of file tools.cpp.

Referenced by cStructLoaderPlain::Load(), and cStructLoader::Load().

{
  char *p = s;

  while (p && *p) {
        if (*p == c1)
           *p = c2;
        p++;
        }
  return s;
}
char* strreplace ( char *  s,
const char *  s1,
const char *  s2 
)

re-allocates 's' and deletes the original string if necessary!

Definition at line 143 of file tools.cpp.

{
  char *p = strstr(s, s1);
  if (p) {
     int of = p - s;
     int l  = strlen(s);
     int l1 = strlen(s1);
     int l2 = strlen(s2);
     if (l2 > l1)
        s = (char *)realloc(s, strlen(s) + l2 - l1 + 1);
     if (l2 != l1)
        memmove(s + of + l2, s + of + l1, l - of - l1 + 1);
     strncpy(s + of, s2, l2);
     }
  return s;
}
void syslog_with_tid ( int  priority,
const char *  format,
  ... 
)

Definition at line 27 of file tools.cpp.

References MAXSYSLOGBUF, and cThread::ThreadId().

{
  va_list ap;
  char fmt[MAXSYSLOGBUF];
  snprintf(fmt, sizeof(fmt), "[%d] %s", cThread::ThreadId(), format);
  va_start(ap, format);
  vsyslog(priority, fmt, ap);
  va_end(ap);
}
cString TimeString ( time_t  t)

Definition at line 608 of file tools.cpp.

{
  char buf[25];
  struct tm tm_r;
  strftime(buf, sizeof(buf), "%R", localtime_r(&t, &tm_r));
  return buf;
}
cString TimeToString ( time_t  t)

Definition at line 587 of file tools.cpp.

{
  char buffer[32];
  if (ctime_r(&t, buffer)) {
     buffer[strlen(buffer) - 1] = 0; // strip trailing newline
     return buffer;
     }
  return "???";
}
cString WeekDayName ( int  WeekDay)

Definition at line 556 of file tools.cpp.

References strn0cpy().

Referenced by DateString(), DayDateTime(), and WeekDayName().

{
  char buffer[4];
  WeekDay = WeekDay == 0 ? 6 : WeekDay - 1; // we start with monday==0!
  if (0 <= WeekDay && WeekDay <= 6) {
     const char *day = "MonTueWedThuFriSatSun";
     day += WeekDay * 3;
     strn0cpy(buffer, day, sizeof(buffer));
     return buffer;
     }
  else
     return "???";
}
cString WeekDayName ( time_t  t)

Definition at line 570 of file tools.cpp.

References WeekDayName().

{
  struct tm tm_r;
  return WeekDayName(localtime_r(&t, &tm_r)->tm_wday);
}
int WriteAllOrNothing ( int  fd,
const uchar *  Data,
int  Length,
int  TimeoutMs = 0,
int  RetryMs = 0 
)

Writes either all Data to the given file descriptor, or nothing at all. If TimeoutMs is greater than 0, it will only retry for that long, otherwise it will retry forever. RetryMs defines the time between two retries.

Definition at line 82 of file tools.cpp.

References cTimeMs::Elapsed(), FATALERRNO, and cPoller::Poll().

{
  int written = 0;
  while (Length > 0) {
        int w = write(fd, Data + written, Length);
        if (w > 0) {
           Length -= w;
           written += w;
           }
        else if (written > 0 && !FATALERRNO) {
           // we've started writing, so we must finish it!
           cTimeMs t;
           cPoller Poller(fd, true);
           Poller.Poll(RetryMs);
           if (TimeoutMs > 0 && (TimeoutMs -= t.Elapsed()) <= 0)
              break;
           }
        else
           // nothing written yet (or fatal error), so we can just return the error code:
           return w;
        }
  return written;
}
void writechar ( int  filedes,
char  c 
)

Definition at line 77 of file tools.cpp.

References safe_write().

{
  safe_write(filedes, &c, sizeof(c));
}

Variable Documentation

int SysLogLevel = 3

Definition at line 23 of file tools.cpp.

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines