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