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