⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 data.c

📁 VDR softcam plugin 0.9.1
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Softcam plugin to VDR (C++) * * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Or, point your browser to http://www.gnu.org/copyleft/gpl.html */#include <ctype.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <sys/mman.h>#include <sys/stat.h>#include "data.h"#include "misc.h"#include "scsetup.h"#include "log-core.h"#include "i18n.h"#define KEY_FILE     "SoftCam.Key"#define EXT_AU_INT   (15*60*1000) // ms interval for external AU#define EXT_AU_MIN   ( 2*60*1000) // ms min. interval for external AU// -- cFileMap -----------------------------------------------------------------cFileMap::cFileMap(const char *Filename, bool Rw){  filename=strdup(Filename);  rw=Rw;  fd=-1; count=len=0; addr=0; failed=false;}cFileMap::~cFileMap(){  Clean();  free(filename);}bool cFileMap::IsFileMap(const char *Name, bool Rw){  return (!strcmp(Name,filename) && (!Rw || rw));}void cFileMap::Clean(void){  if(addr) { munmap(addr,len); addr=0; len=0; }  if(fd>=0) { close(fd); fd=-1; }}bool cFileMap::Map(void){  cMutexLock lock(this);  if(addr) { count++; return true; }  if(!failed) {    struct stat64 ds;    if(!stat64(filename,&ds)) {      if(S_ISREG(ds.st_mode)) {        fd=open(filename,rw ? O_RDWR : O_RDONLY);        if(fd>=0) {          unsigned char *map=(unsigned char *)mmap(0,ds.st_size,rw ? (PROT_READ|PROT_WRITE):(PROT_READ),MAP_SHARED,fd,0);          if(map!=MAP_FAILED) {            addr=map; len=ds.st_size; count=1;            return true;            }          else PRINTF(L_GEN_ERROR,"mapping failed on %s: %s",filename,strerror(errno));          close(fd); fd=-1;          }        else PRINTF(L_GEN_ERROR,"error opening filemap %s: %s",filename,strerror(errno));        }      else PRINTF(L_GEN_ERROR,"filemap %s is not a regular file",filename);      }    else PRINTF(L_GEN_ERROR,"can't stat filemap %s: %s",filename,strerror(errno));    failed=true; // don't try this one over and over again    }  return false;}bool cFileMap::Unmap(void){  cMutexLock lock(this);  if(addr) {    if(!(--count)) { Clean(); return true; }    else Sync();    }  return false;}void cFileMap::Sync(void){  cMutexLock lock(this);  if(addr) msync(addr,len,MS_ASYNC);}// -- cFileMaps ----------------------------------------------------------------cFileMaps filemaps;cFileMaps::cFileMaps(void){  cfgDir=0;}cFileMaps::~cFileMaps(){  Clear();  free(cfgDir);}void cFileMaps::SetCfgDir(const char *CfgDir){  free(cfgDir);  cfgDir=strdup(CfgDir);}cFileMap *cFileMaps::GetFileMap(const char *name, const char *domain, bool rw){  cMutexLock lock(this);  char path[256];  snprintf(path,sizeof(path),"%s/%s/%s",cfgDir,domain,name);  cFileMap *fm=First();  while(fm) {    if(fm->IsFileMap(path,rw)) return fm;    fm=Next(fm);    }  fm=new cFileMap(path,rw);  Add(fm);  return fm;  }// -- cStructItem --------------------------------------------------------------cStructItem::cStructItem(void){  comment=0; deleted=special=false;}cStructItem::~cStructItem(){  free(comment);}void cStructItem::SetComment(const char *com){  free(comment);  comment=com ? strdup(com):0;}bool cStructItem::Save(FILE *f){  fprintf(f,"%s%s\n",*ToString(false),comment?comment:"");  return ferror(f)==0;}// -- cCommentItem -------------------------------------------------------------class cCommentItem : public cStructItem {public:  cCommentItem(void);  };cCommentItem::cCommentItem(void){  SetSpecial();}// -- cStructLoader ------------------------------------------------------------cStructLoader::cStructLoader(const char *Type, const char *Filename, int Flags):lock(true){  path=0; mtime=0;  type=Type; filename=Filename; flags=Flags&SL_CUSTOMMASK;  cStructLoaders::Register(this);}cStructLoader::~cStructLoader(){  free(path);}void cStructLoader::AddItem(cStructItem *n, const char *com, cStructItem *ref){  n->SetComment(com);  ListLock(true);  cStructItem *a=0;  if(ref) { // insert before reference    for(a=First(); a; a=Next(a))      if(Next(a)==ref) break;    }  if(!a) { // insert before first non-special    for(a=First(); a;) {      cStructItem *nn=Next(a);      if(nn && !nn->Special()) break;      a=nn;      }    }  Add(n,a);  Modified();  ListUnlock();}void cStructLoader::DelItem(cStructItem *d, bool keep){  if(d) {    d->Delete();    if(keep) {      cStructItem *n=new cCommentItem;      n->SetComment(cString::sprintf(";%s%s",*d->ToString(false),d->Comment()?d->Comment():""));      ListLock(true);      Add(n,d);      ListUnlock();      }    Modified();    }}cStructItem *cStructLoader::NextValid(cStructItem *it) const{  while(it && !it->Valid()) it=Next(it);  return it;}void cStructLoader::SetCfgDir(const char *cfgdir){  free(path);  path=strdup(AddDirectory(cfgdir,filename));}time_t cStructLoader::MTime(bool log){  struct stat64 st;  if(stat64(path,&st)!=0) {    if(log) {      PRINTF(L_GEN_ERROR,"failed fstat %s: %s",path,strerror(errno));      PRINTF(L_GEN_WARN,"automatic reload of %s disabled",path);      }    st.st_mtime=0;    }  return st.st_mtime;}void cStructLoader::CheckAccess(void){  if(access(path,R_OK|W_OK)!=0) {    if(errno!=EACCES)      PRINTF(L_GEN_ERROR,"failed access %s: %s",path,strerror(errno));    PRINTF(L_GEN_WARN,"no write permission on %s. Changes will not be saved!",path);    SL_SETFLAG(SL_NOACCESS);    }  else SL_CLRFLAG(SL_NOACCESS);}bool cStructLoader::CheckUnmodified(void){  time_t curr_mtime=MTime(false);  if(mtime && mtime<curr_mtime && SL_TSTFLAG(SL_WATCH)) {     PRINTF(L_CORE_LOAD,"abort save as file %s has been changed externaly",path);     return false;     }  return true;}bool cStructLoader::CheckDoSave(void){  return !SL_TSTFLAG(SL_DISABLED) && SL_TSTFLAG(SL_READWRITE)         && !SL_TSTFLAG(SL_NOACCESS) && SL_TSTFLAG(SL_LOADED)         && IsModified() && CheckUnmodified();}void cStructLoader::LoadFinished(void){  SL_CLRFLAG(SL_SHUTUP);  if(!SL_TSTFLAG(SL_LOADED))    PRINTF(L_CORE_LOAD,"loading %s terminated with error. Changes will not be saved!",path);}void cStructLoader::OpenFailed(void){  if(SL_TSTFLAG(SL_VERBOSE) && !SL_TSTFLAG(SL_SHUTUP)) {    PRINTF(L_GEN_ERROR,"failed open %s: %s",path,strerror(errno));    SL_SETFLAG(SL_SHUTUP);    }  if(SL_TSTFLAG(SL_MISSINGOK)) SL_SETFLAG(SL_LOADED);  else SL_CLRFLAG(SL_LOADED);}void cStructLoader::Load(bool reload){  if(SL_TSTFLAG(SL_DISABLED) || (reload && !SL_TSTFLAG(SL_WATCH))) return;  FILE *f=fopen(path,"r");  if(f) {    int curr_mtime=MTime(true);    ListLock(true);    bool doload=false;    if(!reload) {      Clear(); Modified(false);      mtime=curr_mtime;      doload=true;      }    else if(mtime<curr_mtime) {      PRINTF(L_CORE_LOAD,"detected change of %s",path);      if(IsModified())        PRINTF(L_CORE_LOAD,"discarding in-memory changes");      for(cStructItem *a=First(); a; a=Next(a)) DelItem(a);      Modified(false);      mtime=curr_mtime;      doload=true;      }    if(doload) {      SL_SETFLAG(SL_LOADED);      PRINTF(L_GEN_INFO,"loading %s from %s",type,path);      CheckAccess();      int lineNum=0, num=0;      char buff[4096];      while(fgets(buff,sizeof(buff),f)) {        lineNum++;        if(!index(buff,'\n') && !feof(f)) {          PRINTF(L_GEN_ERROR,"file %s readbuffer overflow line#%d",path,lineNum);          SL_CLRFLAG(SL_LOADED);          break;          }        strreplace(buff,'\n',0); strreplace(buff,'\r',0); // chomp        bool hasContent=false;        char *ls;        for(ls=buff; *ls; ls++) {          if(*ls==';' || *ls=='#') {		  // comment            if(hasContent)              while(ls>buff && ls[-1]<=' ') ls--; // search back to non-whitespace            break;            }          if(*ls>' ') hasContent=true;		  // line contains something usefull          }        cStructItem *it=0;        if(hasContent) {          char save=*ls;          *ls=0; it=ParseLine(skipspace(buff)); *ls=save;          if(!it) {            PRINTF(L_GEN_ERROR,"file %s has error in line #%d",path,lineNum);            ls=buff;            }          else num++;          }        else ls=buff;        if(!it) it=new cCommentItem;        if(it) {          it->SetComment(ls);          Add(it);          }        else {          PRINTF(L_GEN_ERROR,"out of memory loading file %s",path);          SL_CLRFLAG(SL_LOADED);          break;          }        }      ListUnlock();      PRINTF(L_CORE_LOAD,"loaded %d %s from %s",num,type,path);      PostLoad();      }    else ListUnlock();    fclose(f);    LoadFinished();    }  else    OpenFailed();}void cStructLoader::Purge(void){  if(!SL_TSTFLAG(SL_DISABLED) && !SL_TSTFLAG(SL_NOPURGE)) {    ListLock(true);    for(cStructItem *it=First(); it;) {      cStructItem *n=Next(it);      if(it->Deleted()) Del(it);      it=n;      }    ListUnlock();    }}void cStructLoader::Save(void){  if(CheckDoSave()) {    cSafeFile f(path);    if(f.Open()) {      ListLock(false);      for(cStructItem *it=First(); it; it=Next(it))        if(!it->Deleted() && !it->Save(f)) break;      f.Close();      mtime=MTime(true);      Modified(false);      ListUnlock();      PRINTF(L_CORE_LOAD,"saved %s to %s",type,path);      }    }}// -- cStructLoaderPlain -------------------------------------------------------cStructLoaderPlain::cStructLoaderPlain(const char *Type, const char *Filename, int Flags):cStructLoader(Type,Filename,Flags){}void cStructLoaderPlain::PreLoad(void){  ListLock(true);  Clear(); Modified(false);  ListUnlock();}void cStructLoaderPlain::Load(bool reload){  if(SL_TSTFLAG(SL_DISABLED) || reload) return;  FILE *f=fopen(path,"r");  if(f) {    PreLoad();    ListLock(true);    SL_SETFLAG(SL_LOADED);    PRINTF(L_GEN_INFO,"loading %s from %s",type,path);    CheckAccess();    int lineNum=0;    char buff[4096];    while(fgets(buff,sizeof(buff),f)) {      lineNum++;      if(!index(buff,'\n') && !feof(f)) {        PRINTF(L_GEN_ERROR,"file %s readbuffer overflow line#%d",path,lineNum);        SL_CLRFLAG(SL_LOADED);        break;        }      strreplace(buff,'\n',0); strreplace(buff,'\r',0); // chomp      bool hasContent=false;      char *ls;      for(ls=buff; *ls; ls++) {        if(*ls==';' || *ls=='#') break;        if(*ls>' ') hasContent=true;        }      if(hasContent) {        *ls=0;        if(!ParseLinePlain(skipspace(buff)))          PRINTF(L_GEN_ERROR,"file %s has error in line #%d",path,lineNum);        }      }    ListUnlock();    PostLoad();    fclose(f);    LoadFinished();    }  else    OpenFailed();}void cStructLoaderPlain::PreSave(FILE *f){  fprintf(f,"## This is a generated file. DO NOT EDIT!!\n"            "## This file will be OVERWRITTEN WITHOUT WARNING!!\n");}void cStructLoaderPlain::Save(void){  if(CheckDoSave()) {    cSafeFile f(path);    if(f.Open()) {      ListLock(false);      PreSave(f);      for(cStructItem *it=First(); it; it=Next(it))        if(!it->Deleted() && !it->Save(f)) break;      PostSave(f);      f.Close();      Modified(false);      ListUnlock();      PRINTF(L_CORE_LOAD,"saved %s to %s",type,path);      }    }}// -- cStructLoaders -----------------------------------------------------------#define RELOAD_TIMEOUT  20300 // ms#define PURGE_TIMEOUT   60700 // ms#define SAVE_TIMEOUT     5000 // ms

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -