data.c
author nathan
Sat, 29 Dec 2007 14:58:47 +0100
branchtrunk
changeset 11 7f424cf3f798
parent 6 111ef8181229
child 22 93aaf15c145a
permissions -rw-r--r--
use po2i18n for non-locale vdr
nathan@0
     1
/*
nathan@0
     2
 * MP3/MPlayer plugin to VDR (C++)
nathan@0
     3
 *
nathan@0
     4
 * (C) 2001-2006 Stefan Huelswitt <s.huelswitt@gmx.de>
nathan@0
     5
 *
nathan@0
     6
 * This code is free software; you can redistribute it and/or
nathan@0
     7
 * modify it under the terms of the GNU General Public License
nathan@0
     8
 * as published by the Free Software Foundation; either version 2
nathan@0
     9
 * of the License, or (at your option) any later version.
nathan@0
    10
 *
nathan@0
    11
 * This code is distributed in the hope that it will be useful,
nathan@0
    12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nathan@0
    13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nathan@0
    14
 * GNU General Public License for more details.
nathan@0
    15
 *
nathan@0
    16
 * You should have received a copy of the GNU General Public License
nathan@0
    17
 * along with this program; if not, write to the Free Software
nathan@0
    18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
nathan@0
    19
 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
nathan@0
    20
 */
nathan@0
    21
nathan@0
    22
#include <ctype.h>
nathan@0
    23
#include <dirent.h>
nathan@0
    24
#include <stdlib.h>
nathan@0
    25
#include <stdio.h>
nathan@0
    26
#include <errno.h>
nathan@0
    27
#include <sys/stat.h>
nathan@0
    28
#include <sys/types.h>
nathan@0
    29
#include <unistd.h>
nathan@0
    30
#include <dirent.h>
nathan@0
    31
#include <fnmatch.h>
nathan@0
    32
nathan@0
    33
#include <vdr/tools.h>
nathan@0
    34
nathan@0
    35
#include "common.h"
nathan@0
    36
#include "data.h"
nathan@0
    37
#include "data-src.h"
nathan@0
    38
nathan@0
    39
// ----------------------------------------------------------------
nathan@0
    40
nathan@0
    41
const char *mountscript = "mount.sh";
nathan@0
    42
nathan@0
    43
char *Quote(const char *str)
nathan@0
    44
{
nathan@0
    45
  char *nstr=MALLOC(char,strlen(str)*2);
nathan@0
    46
  char *p=nstr;
nathan@0
    47
  while(*str) {
nathan@0
    48
    switch(*str) {
nathan@0
    49
      case '$':  // dollar
nathan@0
    50
      case '\\': // backslash
nathan@0
    51
      case '\"': // double quote
nathan@0
    52
      case '`':  // back tick
nathan@0
    53
                 *p++='\\'; break;
nathan@0
    54
      }
nathan@0
    55
    *p++=*str++;
nathan@0
    56
    }
nathan@0
    57
  *p=0;
nathan@0
    58
  return nstr;
nathan@0
    59
}
nathan@0
    60
nathan@0
    61
char *AddPath(const char *dir, const char *filename)
nathan@0
    62
{
nathan@0
    63
  char *name=0;
nathan@0
    64
  asprintf(&name,"%s/%s",dir,filename);
nathan@0
    65
  return name;
nathan@0
    66
}
nathan@0
    67
nathan@0
    68
bool CheckVDRVersion(int Version, int Major, int Minor, const char *text)
nathan@0
    69
{
nathan@0
    70
  static char vv[] = VDRVERSION;
nathan@0
    71
  int version, major, minor;
nathan@0
    72
  if(sscanf(vv,"%d.%d.%d",&version,&major,&minor)==3) {
nathan@0
    73
    if(version<Version ||
nathan@0
    74
       (version==Version && major<Major) ||
nathan@0
    75
       (version==Version && major==Major && minor<Minor)) {
nathan@0
    76
      if(text) {
nathan@0
    77
        esyslog("ERROR: %s plugin needs at least VDR version %d.%d.%d",text,Version,Major,Minor);
nathan@0
    78
        fprintf(stderr,"%s plugin needs at least VDR version %d.%d.%d\n",text,Version,Major,Minor);
nathan@0
    79
        }
nathan@0
    80
      return false;
nathan@0
    81
      }
nathan@0
    82
    }
nathan@0
    83
  else esyslog("ERROR: cannot parse VDR version string '%s'",vv);
nathan@0
    84
  return true;
nathan@0
    85
}
nathan@0
    86
nathan@0
    87
// -- cScanDir --------------------------------------------------------------
nathan@0
    88
nathan@0
    89
bool cScanDir::ScanDir(cFileSource *src, const char *subdir, eScanType type, const char * const *spec, const char * const *excl, bool recursiv)
nathan@0
    90
{
nathan@0
    91
  bool res=true;
nathan@0
    92
  char *dir, *f=0;
nathan@0
    93
  asprintf(&dir,subdir ? "%s/%s":"%s",src->BaseDir(),subdir);
nathan@0
    94
  DIR *d=opendir(dir);
nathan@0
    95
  if(d) {
nathan@0
    96
    struct dirent64 *e;
nathan@0
    97
    while((e=readdir64(d))) {
nathan@0
    98
      if(!strcmp(e->d_name,".") || !strcmp(e->d_name,"..")) continue;
nathan@0
    99
      free(f);
nathan@0
   100
      if(!(f=AddPath(dir,e->d_name))) continue;
nathan@0
   101
      struct stat64 st;
nathan@0
   102
      if(stat64(f,&st)<0) {
nathan@0
   103
        esyslog("ERROR: stat(1) %s: %s",f,strerror(errno));
nathan@0
   104
        continue;
nathan@0
   105
        }
nathan@0
   106
      if(S_ISLNK(st.st_mode)) {
nathan@0
   107
        char *of=f; f=ReadLink(of); free(of);
nathan@0
   108
        if(!f) continue;
nathan@0
   109
        if(stat64(f,&st)<0) {
nathan@0
   110
          esyslog("ERROR: stat(2) %s: %s",f,strerror(errno));
nathan@0
   111
          continue;
nathan@0
   112
          }
nathan@0
   113
        }
nathan@0
   114
      if(S_ISDIR(st.st_mode)) {
nathan@0
   115
        if(type==stFile && recursiv) {
nathan@0
   116
          char *s;
nathan@0
   117
          asprintf(&s,subdir ? "%2$s/%1$s":"%s",e->d_name,subdir);
nathan@0
   118
          res=ScanDir(src,s,type,spec,excl,recursiv);
nathan@0
   119
          free(s);
nathan@0
   120
          if(!res) break;
nathan@0
   121
          continue;
nathan@0
   122
          }
nathan@0
   123
        if(type!=stDir) continue;
nathan@0
   124
        }
nathan@0
   125
      if(S_ISREG(st.st_mode)) {
nathan@0
   126
        if(type!=stFile) continue;
nathan@0
   127
        if(spec) {
nathan@0
   128
          bool ok=false;
nathan@0
   129
          for(const char * const *m=spec; *m; m++) {
nathan@0
   130
            int n=fnmatch(*m,e->d_name,FNM_CASEFOLD);
nathan@0
   131
            if(n==0) { ok=true; break; }
nathan@0
   132
            if(n!=FNM_NOMATCH) esyslog("ERROR: fnmatch(1) %s: %s",*m,strerror(errno));
nathan@0
   133
            }
nathan@0
   134
          if(!ok) continue;
nathan@0
   135
          }
nathan@0
   136
        if(excl) {
nathan@0
   137
          bool ok=true;
nathan@0
   138
          for(const char * const *m=excl; *m; m++) {
nathan@0
   139
            int n=fnmatch(*m,e->d_name,FNM_CASEFOLD);
nathan@0
   140
            if(n==0) { ok=false; break; }
nathan@0
   141
            if(n!=FNM_NOMATCH) esyslog("ERROR: fnmatch(2) %s: %s",*m,strerror(errno));
nathan@0
   142
            }
nathan@0
   143
          if(!ok) continue;
nathan@0
   144
          }
nathan@0
   145
        }
nathan@0
   146
      DoItem(src,subdir,e->d_name);
nathan@0
   147
      }
nathan@0
   148
    closedir(d);
nathan@0
   149
    }
nathan@0
   150
  else {
nathan@0
   151
    esyslog("ERROR: opendir %s: %s",dir,strerror(errno));
nathan@0
   152
    res=false;
nathan@0
   153
    }
nathan@0
   154
  free(dir); free(f);
nathan@0
   155
  return res;
nathan@0
   156
}
nathan@0
   157
nathan@0
   158
// -- cFileObj --------------------------------------------------------------
nathan@0
   159
nathan@0
   160
cFileObj::cFileObj(cFileSource *Source, const char *Subdir, const char *Name, const eObjType Type)
nathan@0
   161
{
nathan@0
   162
  path=fpath=0;
nathan@0
   163
  source=Source;
nathan@0
   164
  subdir=Subdir ? strdup(Subdir):0;
nathan@0
   165
  name=Name ? strdup(Name):0;
nathan@0
   166
  type=Type;
nathan@0
   167
  Set();
nathan@0
   168
}
nathan@0
   169
nathan@0
   170
cFileObj::cFileObj(const cFileObj *obj)
nathan@0
   171
{
nathan@0
   172
  path=fpath=0;
nathan@0
   173
  source=obj->source;
nathan@0
   174
  subdir=obj->subdir ? strdup(obj->subdir):0;
nathan@0
   175
  name=obj->name ? strdup(obj->name):0;
nathan@0
   176
  type=obj->type;
nathan@0
   177
  Set();
nathan@0
   178
}
nathan@0
   179
nathan@0
   180
cFileObj::~cFileObj()
nathan@0
   181
{
nathan@0
   182
  free(name);
nathan@0
   183
  free(subdir);
nathan@0
   184
  free(path);
nathan@0
   185
  free(fpath);
nathan@0
   186
}
nathan@0
   187
nathan@0
   188
#if APIVERSNUM >= 10315
nathan@0
   189
int cFileObj::Compare(const cListObject &ListObject) const
nathan@0
   190
{
nathan@0
   191
  cFileObj *obj=(cFileObj *)&ListObject;
nathan@0
   192
  if(type==otParent) return obj->type==otParent ? 0:-1;
nathan@0
   193
  if(obj->type==otParent) return 1;
nathan@0
   194
  if(type==otBase) return obj->type==otBase ? 0:1;
nathan@0
   195
  if(obj->type==otBase) return -1;
nathan@0
   196
  if(type!=obj->type) {
nathan@0
   197
    if(type==otFile) return 1;
nathan@0
   198
    return -1;
nathan@0
   199
    }
nathan@0
   200
  return strcasecmp(path,obj->path);
nathan@0
   201
}
nathan@0
   202
#else
nathan@0
   203
bool cFileObj::operator<(const cListObject &ListObject)
nathan@0
   204
{
nathan@0
   205
  cFileObj *obj=(cFileObj *)&ListObject;
nathan@0
   206
  if(type==otParent) return obj->type==otParent ? false:true;
nathan@0
   207
  if(obj->type==otParent) return false;
nathan@0
   208
  if(type==otBase) return false;
nathan@0
   209
  if(obj->type==otBase) return true;
nathan@0
   210
  if(type!=obj->type) {
nathan@0
   211
    if(type==otFile) return false;
nathan@0
   212
    return true;
nathan@0
   213
    }
nathan@0
   214
  return strcasecmp(path,obj->path)<0;
nathan@0
   215
}
nathan@0
   216
#endif
nathan@0
   217
nathan@0
   218
void cFileObj::SplitAndSet(const char *Path)
nathan@0
   219
{
nathan@0
   220
  free(subdir); subdir=0;
nathan@0
   221
  const char *p=Path;
nathan@0
   222
  if(Path[0]=='/') {
nathan@0
   223
    int l=strlen(source->BaseDir());
nathan@0
   224
    if(!strncasecmp(Path,source->BaseDir(),l)) p+=l+1;
nathan@0
   225
    else {
nathan@0
   226
      l=strlen(source->RealBaseDir());
nathan@0
   227
      if(!strncasecmp(Path,source->RealBaseDir(),l)) p+=l+1;
nathan@0
   228
      else {
nathan@0
   229
        char buff[strlen(Path)+5];
nathan@0
   230
        strcpy(buff,"/");
nathan@0
   231
        p++;
nathan@0
   232
        while(1) {
nathan@0
   233
          char real[PATH_MAX+1];
nathan@0
   234
          if(!realpath(buff,real)) {
nathan@0
   235
            if(errno!=ENOENT && errno!=ENOTDIR)
nathan@0
   236
              esyslog("ERROR: realpath: %s: %s",buff,strerror(errno));
nathan@0
   237
            p=Path+1;
nathan@0
   238
            break;
nathan@0
   239
            }
nathan@0
   240
          if(!strncasecmp(real,source->RealBaseDir(),l))
nathan@0
   241
            break;
nathan@0
   242
          const char *r=index(p,'/');
nathan@0
   243
          if(!r) {
nathan@0
   244
            esyslog("ERROR: can't find source basedir in '%s'. Outside source?",Path);
nathan@0
   245
            p=Path+1;
nathan@0
   246
            break;
nathan@0
   247
            }
nathan@0
   248
          strn0cpy(buff,Path,r-Path+1);
nathan@0
   249
          p=r+1;
nathan@0
   250
          }
nathan@0
   251
        }
nathan@0
   252
      }
nathan@0
   253
    }
nathan@0
   254
nathan@0
   255
  const char *s=rindex(p,'/');
nathan@0
   256
  if(s) {
nathan@0
   257
    const int l=s-p+1;
nathan@0
   258
    subdir=MALLOC(char,l);
nathan@0
   259
    if(subdir) strn0cpy(subdir,p,l);
nathan@0
   260
    SetName(s+1);
nathan@0
   261
    }
nathan@0
   262
  else
nathan@0
   263
    SetName(p);
nathan@0
   264
}
nathan@0
   265
nathan@0
   266
void cFileObj::SetName(const char *Name)
nathan@0
   267
{
nathan@0
   268
  free(name);
nathan@0
   269
  name=Name ? strdup(Name):0;
nathan@0
   270
  Set();
nathan@0
   271
}
nathan@0
   272
nathan@0
   273
void cFileObj::Set(void)
nathan@0
   274
{
nathan@0
   275
  free(path); path=0;
nathan@0
   276
  asprintf(&path,subdir ? "%2$s/%1$s":"%s",name,subdir);
nathan@0
   277
  free(fpath); fpath=0;
nathan@0
   278
  MakeFullName(&fpath,name);
nathan@0
   279
}
nathan@0
   280
nathan@0
   281
void cFileObj::MakeFullName(char **fp, const char *Name)
nathan@0
   282
{
nathan@0
   283
  asprintf(fp,subdir ? "%1$s/%3$s/%2$s":"%s/%s",source->BaseDir(),Name,subdir);
nathan@0
   284
}
nathan@0
   285
nathan@0
   286
bool cFileObj::GuessType(void)
nathan@0
   287
{
nathan@0
   288
  struct stat64 ds;
nathan@0
   289
  if(!stat64(fpath,&ds)) {
nathan@0
   290
    if(S_ISREG(ds.st_mode))      type=otFile;
nathan@0
   291
    else if(S_ISDIR(ds.st_mode)) type=subdir ? otDir:otBase;
nathan@0
   292
    else return false;
nathan@0
   293
    return true;
nathan@0
   294
    }
nathan@0
   295
  return false;
nathan@0
   296
}
nathan@0
   297
nathan@0
   298
bool cFileObj::Exists(void)
nathan@0
   299
{
nathan@0
   300
  if(type==otFile) {
nathan@0
   301
    struct stat64 ds;
nathan@0
   302
    if(!stat64(fpath,&ds) &&
nathan@0
   303
       S_ISREG(ds.st_mode) &&
nathan@0
   304
       !access(fpath,R_OK)) return true;
nathan@0
   305
    }
nathan@0
   306
  return false;
nathan@0
   307
}
nathan@0
   308
nathan@0
   309
bool cFileObj::TestName(const char *newName)
nathan@0
   310
{
nathan@0
   311
  bool r=false;
nathan@0
   312
  if(type==otFile) {
nathan@0
   313
    char *fname;
nathan@0
   314
    MakeFullName(&fname,newName);
nathan@0
   315
    if(access(fname,F_OK)==0) r=true;
nathan@0
   316
    free(fname);
nathan@0
   317
    }
nathan@0
   318
  return r;
nathan@0
   319
}
nathan@0
   320
nathan@0
   321
bool cFileObj::Rename(const char *newName)
nathan@0
   322
{
nathan@0
   323
  bool r=false;
nathan@0
   324
  if(type==otFile) {
nathan@0
   325
    char *fname;
nathan@0
   326
    MakeFullName(&fname,newName);
nathan@0
   327
    if(access(fname,F_OK) && (!rename(fpath,fname))) {
nathan@0
   328
      SetName(newName);
nathan@0
   329
      r=true;
nathan@0
   330
      }
nathan@0
   331
    free(fname);
nathan@0
   332
    }
nathan@0
   333
  return r;
nathan@0
   334
}
nathan@0
   335
nathan@0
   336
bool cFileObj::Create(const char *newName)
nathan@0
   337
{
nathan@0
   338
  bool r=false;
nathan@0
   339
  if(type==otFile) {
nathan@0
   340
    char *fname;
nathan@0
   341
    MakeFullName(&fname,newName);
nathan@0
   342
    FILE *newf;
nathan@0
   343
    if(access(fname,F_OK) && (newf=fopen(fname,"w"))) {
nathan@0
   344
      fclose(newf);
nathan@0
   345
      SetName(newName);
nathan@0
   346
      r=true;
nathan@0
   347
      }
nathan@0
   348
    free(fname);
nathan@0
   349
    }
nathan@0
   350
  return r;
nathan@0
   351
}
nathan@0
   352
nathan@0
   353
bool cFileObj::Delete(void)
nathan@0
   354
{
nathan@0
   355
  if(type==otFile && !unlink(fpath)) return true;
nathan@0
   356
  return false;
nathan@0
   357
}
nathan@0
   358
nathan@0
   359
// -- cDirList --------------------------------------------------------------
nathan@0
   360
nathan@0
   361
bool cDirList::Load(cFileSource *src, const char *subdir, const char * const *excl)
nathan@0
   362
{
nathan@0
   363
  static const char *excl_s[] = { ".*",0 };
nathan@0
   364
nathan@0
   365
  bool res=false;
nathan@0
   366
  Clear();
nathan@0
   367
  if(subdir) Add(new cFileObj(src,subdir,"..",otParent));
nathan@0
   368
  otype=otDir;
nathan@0
   369
  if(ScanDir(src,subdir,stDir,0,0,false)) {
nathan@0
   370
    otype=otFile;
nathan@0
   371
    if(!excl) excl=excl_s;
nathan@0
   372
    if(ScanDir(src,subdir,stFile,src->Include(),excl,false)) res=true;
nathan@0
   373
    }
nathan@0
   374
  Sort();
nathan@0
   375
  return res;
nathan@0
   376
}
nathan@0
   377
nathan@0
   378
void cDirList::DoItem(cFileSource *src, const char *subdir, const char *name)
nathan@0
   379
{
nathan@0
   380
  Add(new cFileObj(src,subdir,name,otype));
nathan@0
   381
}
nathan@0
   382
nathan@0
   383
// -- cFileSource --------------------------------------------------------------
nathan@0
   384
nathan@0
   385
cFileSource::cFileSource(void)
nathan@0
   386
{
nathan@0
   387
  browsedir=browseparent=0;
nathan@0
   388
  basedir=realbasedir=description=0; useCount=0;
nathan@0
   389
  needsmount=false;
nathan@0
   390
  include=0; incCount=0;
nathan@0
   391
}
nathan@0
   392
nathan@0
   393
cFileSource::cFileSource(const char *Basedir, const char *Description, const bool NeedsMount, const char *Include)
nathan@0
   394
{
nathan@0
   395
  browsedir=browseparent=0;
nathan@0
   396
  basedir=realbasedir=description=0; useCount=0;
nathan@0
   397
  include=0; incCount=0;
nathan@0
   398
  Set(Basedir,Description,NeedsMount,Include);
nathan@0
   399
}
nathan@0
   400
nathan@0
   401
cFileSource::~cFileSource()
nathan@0
   402
{
nathan@0
   403
  ClearRemember();
nathan@0
   404
  Clear();
nathan@0
   405
}
nathan@0
   406
nathan@0
   407
void cFileSource::Clear(void)
nathan@0
   408
{
nathan@0
   409
  free(basedir); basedir=0;
nathan@0
   410
  free(realbasedir); realbasedir=0;
nathan@0
   411
  free(description); description=0;
nathan@0
   412
  for(int i=0; i<incCount; i++) free(include[i]);
nathan@0
   413
  free(include); include=0; incCount=0;
nathan@0
   414
}
nathan@0
   415
nathan@0
   416
void cFileSource::Set(const char *Basedir, const char *Description, const bool NeedsMount, const char *Include)
nathan@0
   417
{
nathan@0
   418
  Clear();
nathan@0
   419
  basedir=strdup(Basedir);
nathan@0
   420
  description=strdup(Description);
nathan@0
   421
  if(Include) {
nathan@0
   422
    do {
nathan@0
   423
      char *s=index(Include,'/');
nathan@0
   424
      int l=s ? s-Include : strlen(Include);
nathan@0
   425
      if(l) {
nathan@0
   426
        char **s=(char **)realloc(include,(incCount+2)*sizeof(char *));
nathan@0
   427
        if(s) {
nathan@0
   428
          include=s;
nathan@0
   429
          include[incCount]=strndup(Include,l);
nathan@0
   430
          incCount++;
nathan@0
   431
          include[incCount]=0;
nathan@0
   432
          }
nathan@0
   433
        }
nathan@0
   434
      Include+=l+(s ? 1:0);
nathan@0
   435
      } while(*Include>0);
nathan@0
   436
    }
nathan@0
   437
#ifdef DEBUG
nathan@0
   438
  if(include) {
nathan@0
   439
    printf("sources: filesource %s includes (count=%d):",basedir,incCount);
nathan@0
   440
    for(int i=0; i<incCount; i++) printf(" '%s'",include[i]);
nathan@0
   441
    printf("\n");
nathan@0
   442
    }
nathan@0
   443
  else
nathan@0
   444
    printf("sources: filesource %s has no includes set\n",basedir);
nathan@0
   445
#endif
nathan@0
   446
  needsmount=NeedsMount;
nathan@0
   447
nathan@0
   448
  realbasedir=MALLOC(char,PATH_MAX+1);
nathan@0
   449
  if(realpath(basedir,realbasedir)) {
nathan@0
   450
    if(strcmp(basedir,realbasedir)) { esyslog("WARNING: source base %s expands to %s",basedir,realbasedir); }
nathan@0
   451
    }
nathan@0
   452
  else {
nathan@0
   453
    switch(errno) {
nathan@0
   454
      case EACCES:  esyslog("ERROR: source base %s permission denied",basedir); break;
nathan@0
   455
      case ENOENT:  esyslog("ERROR: source base %s not found",basedir); break;
nathan@0
   456
      case ENOTDIR: esyslog("ERROR: source base %s has invalid path",basedir); break;
nathan@0
   457
      default:      esyslog("ERROR: source base %s realpath: %s",basedir,strerror(errno)); break;
nathan@0
   458
      }
nathan@0
   459
    strn0cpy(realbasedir,basedir,PATH_MAX);
nathan@0
   460
    }
nathan@0
   461
}
nathan@0
   462
nathan@0
   463
void cFileSource::SetRemember(const char *dir, const char *parent)
nathan@0
   464
{
nathan@0
   465
  ClearRemember();
nathan@0
   466
  if(dir) browsedir=strdup(dir);
nathan@0
   467
  if(parent) browseparent=strdup(parent);
nathan@0
   468
}
nathan@0
   469
nathan@0
   470
void cFileSource::ClearRemember(void)
nathan@0
   471
{
nathan@0
   472
  free(browsedir); browsedir=0;
nathan@0
   473
  free(browseparent); browseparent=0;
nathan@0
   474
}
nathan@0
   475
nathan@0
   476
bool cFileSource::GetRemember(char * &dir, char * &parent)
nathan@0
   477
{
nathan@0
   478
  dir=parent=0;
nathan@0
   479
  if(browsedir) {
nathan@0
   480
    if(browseparent) parent=strdup(browseparent);
nathan@0
   481
    dir=strdup(browsedir);
nathan@0
   482
    return true;
nathan@0
   483
    }
nathan@0
   484
  return false;
nathan@0
   485
}
nathan@0
   486
nathan@0
   487
bool cFileSource::Parse(char *s)
nathan@0
   488
{
nathan@0
   489
  char base[256], des[256], incl[256];
nathan@0
   490
  int needsmount, n;
nathan@0
   491
  if((n=sscanf(s,"%255[^;];%255[^;];%d;%255[^;]",base,des,&needsmount,incl))>=3) {
nathan@0
   492
    char *base2=skipspace(stripspace(base));
nathan@0
   493
    int l=strlen(base2);
nathan@0
   494
    while(l>0 && base2[l-1]=='/') {
nathan@0
   495
      esyslog("WARNING: removing trailing '/' from base %s",base2);
nathan@0
   496
      base2[l-1]=0;
nathan@0
   497
      l--;
nathan@0
   498
      }
nathan@0
   499
    Set(base2,skipspace(stripspace(des)),needsmount!=0,n>3?skipspace(stripspace(incl)):0);
nathan@0
   500
nathan@0
   501
    // do some checking of the basedir and issue a warning if apropriate
nathan@0
   502
    if(access(realbasedir,R_OK)) { esyslog("WARNING: source base %s not found/permission denied",realbasedir); }
nathan@0
   503
    else {
nathan@0
   504
      struct stat64 ds;
nathan@0
   505
      if(lstat64(realbasedir,&ds)) { esyslog("WARNING: can't stat source base %s",realbasedir); }
nathan@0
   506
      else if(!S_ISDIR(ds.st_mode)) { esyslog("WARNING: source base %s is not a directory",realbasedir); }
nathan@0
   507
      }
nathan@0
   508
    return true;
nathan@0
   509
    }
nathan@0
   510
  return false;
nathan@0
   511
}
nathan@0
   512
nathan@0
   513
bool cFileSource::Action(eAction act)
nathan@0
   514
{
nathan@6
   515
  static const char *str[] = { "mount","unmount","eject","status" };
nathan@0
   516
  
nathan@0
   517
  char *cmd=0;
nathan@0
   518
  asprintf(&cmd,"%s %s %s",mountscript,str[act],basedir);
nathan@0
   519
  bool res=(system(cmd)==0);
nathan@0
   520
  free(cmd);
nathan@0
   521
  return res;
nathan@0
   522
}
nathan@0
   523
nathan@0
   524
bool cFileSource::Mount(void)
nathan@0
   525
{
nathan@0
   526
  bool res=false;
nathan@0
   527
  if(needsmount && (res=Action(acMount))) ClearRemember();
nathan@0
   528
  return res;
nathan@0
   529
}
nathan@0
   530
nathan@0
   531
bool cFileSource::Unmount(void)
nathan@0
   532
{
nathan@0
   533
  bool res=false;
nathan@0
   534
  if(needsmount) {
nathan@0
   535
    if(!useCount && (res=Action(acUnmount))) ClearRemember();
nathan@0
   536
    }
nathan@0
   537
  return res;
nathan@0
   538
}
nathan@0
   539
nathan@0
   540
bool cFileSource::Eject(void)
nathan@0
   541
{
nathan@0
   542
  bool res=false;
nathan@0
   543
  if(needsmount) {
nathan@0
   544
    if(!useCount && (res=Action(acEject))) ClearRemember();
nathan@0
   545
    }
nathan@0
   546
  return res;
nathan@0
   547
}
nathan@0
   548
nathan@0
   549
bool cFileSource::Status(void)
nathan@0
   550
{
nathan@0
   551
  if(needsmount) return Action(acStatus);
nathan@0
   552
  return true;
nathan@0
   553
}
nathan@0
   554
nathan@0
   555
// -- cFileSources --------------------------------------------------------------
nathan@0
   556
nathan@0
   557
bool cFileSources::Load(const char *filename, bool dummy)
nathan@0
   558
{
nathan@0
   559
  if(cConfig<cFileSource>::Load(filename,true)) {
nathan@0
   560
    SetSource(First());
nathan@0
   561
    return true;
nathan@0
   562
    }
nathan@0
   563
  return false;
nathan@0
   564
}
nathan@0
   565
nathan@0
   566
cFileSource *cFileSources::FindSource(const char *filename)
nathan@0
   567
{
nathan@0
   568
  cFileSource *src=First();
nathan@0
   569
  while(src) {
nathan@0
   570
    if(startswith(filename,src->RealBaseDir())) return src;
nathan@0
   571
    src=Next(src);
nathan@0
   572
    }
nathan@0
   573
  return 0;
nathan@0
   574
}