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 |
}
|