Filesystem hierachy standard patch needs review.

Message ID 50421255.3050204@tvdr.de
State New
Headers

Commit Message

Klaus Schmidinger Sept. 1, 2012, 1:49 p.m. UTC
  On 09.05.2012 16:36, Manuel Reimer wrote:
> Hello,
>
> what is the current status in this topic? Anyone working on this?

Attached is a revised version of the patch, as I intend to adopt
it in version 1.7.30.

Please try it and let me know if it works as expected.

Klaus
  

Comments

Christopher Reimer Sept. 3, 2012, 11:44 a.m. UTC | #1
2012/9/1 Klaus Schmidinger <Klaus.Schmidinger@tvdr.de>:
> Please try it and let me know if it works as expected.

I have patched my vdr and I cannot see any problems with this changes.

I works with and without USE_FHS=1 as expected.
  
Ludwig Nussel Sept. 3, 2012, 1:42 p.m. UTC | #2
Klaus Schmidinger wrote:
> On 09.05.2012 16:36, Manuel Reimer wrote:
>> what is the current status in this topic? Anyone working on this?
> 
> Attached is a revised version of the patch, as I intend to adopt it
> in version 1.7.30.

Looks like I missed the discussion when this patch was posted
originally. Here are my 2¢'s:

+VIDEODIR     = /srv/vdr/video

Using /srv is fishy and some distros like Fedora even disallow
packages to put anything there. Recordings are automatically created
and potentially also automatically deleted. Some of them you want to
keep and some you delete after watching. So IMHO they are some kind
of spool file where either the machine or a human decides about
their fate. So nine years ago when I started packaging vdr for SUSE
I decided to use /var/spool/video (could have been /var/spool/vdr
too). The second best candidate would be /var/lib/vdr/something I
think.

+CONFDIR      = /var/lib/vdr

Even though vdr may update some of the files there itself I still
think they belong to /etc to make sure they are included in backups by
default.

What's missing is a directory for include files to be able to build
plugins separate from vdr.

cu
Ludwig
  
Klaus Schmidinger Sept. 3, 2012, 2:03 p.m. UTC | #3
On 03.09.2012 15:42, Ludwig Nussel wrote:
> Klaus Schmidinger wrote:
>> On 09.05.2012 16:36, Manuel Reimer wrote:
>>> what is the current status in this topic? Anyone working on this?
>>
>> Attached is a revised version of the patch, as I intend to adopt it
>> in version 1.7.30.
>
> Looks like I missed the discussion when this patch was posted
> originally. Here are my 2¢'s:
>
> +VIDEODIR     = /srv/vdr/video
>
> Using /srv is fishy and some distros like Fedora even disallow
> packages to put anything there. Recordings are automatically created
> and potentially also automatically deleted. Some of them you want to
> keep and some you delete after watching. So IMHO they are some kind
> of spool file where either the machine or a human decides about
> their fate. So nine years ago when I started packaging vdr for SUSE
> I decided to use /var/spool/video (could have been /var/spool/vdr
> too). The second best candidate would be /var/lib/vdr/something I
> think.
>
> +CONFDIR      = /var/lib/vdr
>
> Even though vdr may update some of the files there itself I still
> think they belong to /etc to make sure they are included in backups by
> default.

Since I myself only use the "one single /video directory mode", I absolutely
don't care what paths are used in FHS mode. Therefore I'll put in there
whatever the community agrees upon (although I doub't that there will ever
be an agreement ;-).

So anybody who feels like it, please post the necessary patch here,
and let me know whether or not it should go into the VDR source.

> What's missing is a directory for include files to be able to build
> plugins separate from vdr.

Makefile: INCDIR?

Klaus
  
Christopher Reimer Sept. 3, 2012, 6:41 p.m. UTC | #4
2012/9/3 Ludwig Nussel <ludwig.nussel@suse.de>:
> Klaus Schmidinger wrote:
>> On 09.05.2012 16:36, Manuel Reimer wrote:
>>> what is the current status in this topic? Anyone working on this?
>>
>> Attached is a revised version of the patch, as I intend to adopt it
>> in version 1.7.30.
>
> Looks like I missed the discussion when this patch was posted
> originally. Here are my 2¢'s:
>
> +VIDEODIR     = /srv/vdr/video
>
> Using /srv is fishy and some distros like Fedora even disallow
> packages to put anything there. Recordings are automatically created
> and potentially also automatically deleted. Some of them you want to
> keep and some you delete after watching. So IMHO they are some kind
> of spool file where either the machine or a human decides about
> their fate. So nine years ago when I started packaging vdr for SUSE
> I decided to use /var/spool/video (could have been /var/spool/vdr
> too). The second best candidate would be /var/lib/vdr/something I
> think.
>

FHS 2.3 (http://www.pathname.com/fhs/pub/fhs-2.3.pdf) says:

/var/spool contains data which is awaiting some kind of later
processing. Data in /var/spool represents
work to be done in the future (by a program, user, or administrator);
often data is deleted after it has been
processed.

I don't think that this applies to recordings.

> +CONFDIR      = /var/lib/vdr
>
> Even though vdr may update some of the files there itself I still
> think they belong to /etc to make sure they are included in backups by
> default.
>

Some people mount their /etc read-only. This would break VDR's
functionality. Nevertheless we already talked about this and most
people agree with /var/lib/vdr

> What's missing is a directory for include files to be able to build
> plugins separate from vdr.

Christopher
  
Ludwig Nussel Sept. 4, 2012, 7:38 a.m. UTC | #5
Christopher Reimer wrote:
> 2012/9/3 Ludwig Nussel <ludwig.nussel@suse.de>:
>> Klaus Schmidinger wrote:
>>> On 09.05.2012 16:36, Manuel Reimer wrote:
>>>> what is the current status in this topic? Anyone working on this?
>>>
>>> Attached is a revised version of the patch, as I intend to adopt it
>>> in version 1.7.30.
>>
>> Looks like I missed the discussion when this patch was posted
>> originally. Here are my 2¢'s:
>>
>> +VIDEODIR     = /srv/vdr/video
>>
>> Using /srv is fishy and some distros like Fedora even disallow
>> packages to put anything there. Recordings are automatically created
>> and potentially also automatically deleted. Some of them you want to
>> keep and some you delete after watching. So IMHO they are some kind
>> of spool file where either the machine or a human decides about
>> their fate. So nine years ago when I started packaging vdr for SUSE
>> I decided to use /var/spool/video (could have been /var/spool/vdr
>> too). The second best candidate would be /var/lib/vdr/something I
>> think.
>>
> 
> FHS 2.3 (http://www.pathname.com/fhs/pub/fhs-2.3.pdf) says:
> 
> /var/spool contains data which is awaiting some kind of later
> processing. Data in /var/spool represents
> work to be done in the future (by a program, user, or administrator);
> often data is deleted after it has been
> processed.
> 
> I don't think that this applies to recordings.

Well, after you've recorded something you do something with it. Like
watching the recording, deleting it or let vdr delete it when it needs
more free space. If you think of time shifting this matches a spool
directory even more. Of course if your use case mostly is to record
stuff to keep it forever then it doesn't quite match. But then such
recordings should probably be moved to some kind of archive. In any case
using /srv is odd for sure. Better use /var/lib/vdr/... rather than /srv.

>> +CONFDIR      = /var/lib/vdr
>>
>> Even though vdr may update some of the files there itself I still
>> think they belong to /etc to make sure they are included in backups by
>> default.
>>
> 
> Some people mount their /etc read-only. This would break VDR's
> functionality. Nevertheless we already talked about this and most
> people agree with /var/lib/vdr

Currently that might be true. Nevertheless it would be good to enhance
vdr to make it friendlier in that regard though. E.g treating short
lived data like a one shot timer or automatically detected stations
differently than actual configuration like the ordering of stations.

cu
Ludwig
  
geronimo Sept. 4, 2012, 8:50 a.m. UTC | #6
On Monday 03 September 2012 - 15:42:04, Ludwig Nussel wrote:
> So nine years ago when I started packaging vdr for SUSE ...

Sorry, but Suse is not known for doing things right :(
... and they don't care much about system quality.

> Even though vdr may update some of the files there itself I still
> think they belong to /etc to make sure they are included in backups by
> default.

FHS says about /etc:
"The /etc hierarchy contains configuration files. A "configuration file" is a 
local file used to control the operation of a program; it must be static and 
cannot be an executable binary."

Keep you eyes on "it must be static"!

You could learn from debian systems, where the stuff in /etc is really static. 
Even with vdr.
Vdr's databases reside in /var/lib/vdr where they are changeable by intention.
The databases are linked to /etc.
So the content from /etc (the links to vdr-databases) is static, but the 
content of the databases is not.
Its not that good as if the vdr would have divided the setup into static and 
non-static configuration, but it obeys the rules.
See http://wiki.debian.org/ReadonlyRoot for advantages of that aproach.

Regarding backup:
If you allow your backup application to follow links and save the original, 
the databases will be saved.

But even better:
Teach your SUSE-users to save /var/lib 
I believe, from backup point of view, /var/lib has the same or even higher 
importance to get saved, than /etc

> I decided to use /var/spool/video (could have been /var/spool/vdr
> too).

That's a good point!

Lots of VDR-users use VDR as a standalone system and for those systems 
/var/spool might be more appropriate than /srv

/srv is right, if the VDR-machine offers the recordings like a NAS or 
MediaServer, so in case the VDR is a backend machine, it might be better to 
symlink /var/spool/video to /srv/video or the like.


kind regards

Gero
  
Christopher Reimer Sept. 4, 2012, 10:32 a.m. UTC | #7
2012/9/4 Gero <geronimo013@gmx.de>:
>> I decided to use /var/spool/video (could have been /var/spool/vdr
>> too).
>
> That's a good point!
>
> Lots of VDR-users use VDR as a standalone system and for those systems
> /var/spool might be more appropriate than /srv
>
> /srv is right, if the VDR-machine offers the recordings like a NAS or
> MediaServer, so in case the VDR is a backend machine, it might be better to
> symlink /var/spool/video to /srv/video or the like.

The FHS gives further examples for /var/spool

"Printer spool directory"
"Outgoing mail queue"

I cannot see how a recording directory is comparable with a printer or
outgoing mail queue.


Christopher
  
VDRU VDRU Sept. 4, 2012, 2:55 p.m. UTC | #8
On Tue, Sep 4, 2012 at 12:38 AM, Ludwig Nussel <ludwig.nussel@suse.de> wrote:
> Currently that might be true. Nevertheless it would be good to enhance
> vdr to make it friendlier in that regard though. E.g treating short
> lived data like a one shot timer or automatically detected stations
> differently than actual configuration like the ordering of stations.

Why would you assume single timer recordings, or any recordings at all
are short-lived? If anything users tend to record shows and watch them
at some point in the non-immediate future -- the weekend for example,
when they're more likely to have time sitting around watching tv. I
know several people who record entire series and don't even start
watching them until all the episodes are recorded so they don't have
the irritating wait of a week+ between them. Then there are houses,
like mine, where one person will watch a recording one day, then
somebody else will watch the same thing some days later.

By now you should get the point that assuming recordings are
short-lived is bad, automatically deleting them is bad, etc. Typical
user behavior from my observation certainly isn't record something,
watch it immediately, then delete it.
  
Manuel Reimer Sept. 4, 2012, 8:29 p.m. UTC | #9
Gero wrote:
> Vdr's databases reside in /var/lib/vdr where they are changeable by intention.
> The databases are linked to /etc.
> So the content from /etc (the links to vdr-databases) is static, but the
> content of the databases is not.
> Its not that good as if the vdr would have divided the setup into static and
> non-static configuration, but it obeys the rules.
> See http://wiki.debian.org/ReadonlyRoot for advantages of that aproach.

It's useless to separate between static and non-static configuration files in 
VDR, as in my opinion, VDR doesn't really have files that should be static.

For example the file "diseqc.conf" should be editable via OSD, in my opinion. If 
I pre-setup an VDR system for someone, then it should be possible to just hand 
over the system to him and he should be able to just connect the wires and do 
anything, still required, using his remote control.

So for me it seems to be useless to try to strictly separate VDR's configuration 
files between "static" and "dynamic". They all should be dynamic and maybe at 
any time they could get dynamic, if Klaus improves the OSD setup possibilities.

Just place them all to /var/lib/vdr and you are done.

> Lots of VDR-users use VDR as a standalone system and for those systems
> /var/spool might be more appropriate than /srv

/var/spool is definitively wrong, as this applies to "queue-like" things.

> /srv is right, if the VDR-machine offers the recordings like a NAS or
> MediaServer,

FHS says:

|  /srv : Data for services provided by this system

So as VDR is the primary service of such a box, /srv seems to be OK for me. And 
many distributions share the recordings via FTP or Samba anyways.



For me the discussion about the default setting seems to be useless. The current 
default seems to match the FHS definitions pretty well and any distribution is 
able to easily add own settings via make parameters or via Make.config. So feel 
free to override the default and use your own settings.

The main topic in this "sub-thread" is testing the new patch, which will add API 
functions for the plugins for the first time, allowing plugins to place their 
resources to wherever the distributor decided to put them. No longer abuse of 
"ConfigDirectory" for static resources! No more plugin patching! No more ugly 
symlinks between /var/lib/vdr/... and /usr/share/vdr/...!

Yours

Manuel
  
Manuel Reimer Sept. 4, 2012, 8:32 p.m. UTC | #10
Ludwig Nussel wrote:
[Readonly /etc]
> Currently that might be true. Nevertheless it would be good to enhance
> vdr to make it friendlier in that regard though. E.g treating short
> lived data like a one shot timer or automatically detected stations
> differently than actual configuration like the ordering of stations.

So you talk about "timers.conf" and "channels.conf"? They are both dynamic in 
the same way. VDR heavily modifies "channels.conf". Names, PIDs, .... are 
modified and even new channels are added completely automatically! If I move 
channels, add channels, ... via OSD, then VDR also modifies this file to store 
my changes.

Yours

Manuel
  
Klaus Schmidinger Sept. 5, 2012, 8:23 a.m. UTC | #11
On 04.09.2012 22:29, Manuel Reimer wrote:
> ...
> For example the file "diseqc.conf" should be editable via OSD, in my opinion. If I pre-setup an VDR system for someone, then it should be possible to just hand over the system to him and he should be able to just connect the wires and do anything, still required, using his remote control.
>
> So for me it seems to be useless to try to strictly separate VDR's configuration files between "static" and "dynamic". They all should be dynamic and maybe at any time they could get dynamic, if Klaus improves the OSD setup possibilities.

Feel free to contribute some code that implements an interactive
DiSEqC setup menu ;-)
The DiSEqC setup with all its possibilities is rather complex,
and setting it up via a config file is simple enough for me,
that's why I never bothered even trying to write a full-fledged
setup page for it. But I'll gladly adopt a patch that does this
in a useful way ;-)

Klaus
  
Ludwig Nussel Sept. 6, 2012, 3:34 p.m. UTC | #12
Manuel Reimer wrote:
> So for me it seems to be useless to try to strictly separate VDR's
> configuration files between "static" and "dynamic". They all should be
> dynamic and maybe at any time they could get dynamic, if Klaus
> improves the OSD setup possibilities.

I'd still consider a file that is only modified if the user
intentionally does so via the remote control static. There's no
difference between that and using an editor except for the user
interface.

>> Lots of VDR-users use VDR as a standalone system and for those systems
>> /var/spool might be more appropriate than /srv
> 
> /var/spool is definitively wrong, as this applies to "queue-like" things.

Well, that's your opinion.

>> /srv is right, if the VDR-machine offers the recordings like a NAS or
>> MediaServer,
> 
> FHS says:
> 
> |  /srv : Data for services provided by this system
> 
> So as VDR is the primary service of such a box, /srv seems to be OK
> for me. And many distributions share the recordings via FTP or Samba

/srv in theory is taboo for distros (and it is in fact for Fedora)
so distros will be forced to patch vdr to use something else. It's
fine to use for a self compiled vdr but it's not for a distro
package.
 
> For me the discussion about the default setting seems to be
> useless. The current default seems to match the FHS definitions
> pretty well and any distribution is able to easily add own
> settings via make parameters or via Make.config. So feel free to
> override the default and use your own settings.

We are forced to do that already anyways. If vdr changes anything wrt
fs layout I'd really like to see something acceptable for distros to
end the ranting about the different locations of /video.

Where are the vdr package maintainers of other distros hiding anyways?

cu
Ludwig
  
Christopher Reimer Sept. 6, 2012, 4:21 p.m. UTC | #13
2012/9/6 Ludwig Nussel <ludwig.nussel@suse.de>:
> Manuel Reimer wrote:
>> So for me it seems to be useless to try to strictly separate VDR's
>> configuration files between "static" and "dynamic". They all should be
>> dynamic and maybe at any time they could get dynamic, if Klaus
>> improves the OSD setup possibilities.
>
> I'd still consider a file that is only modified if the user
> intentionally does so via the remote control static. There's no
> difference between that and using an editor except for the user
> interface.
>
>>> Lots of VDR-users use VDR as a standalone system and for those systems
>>> /var/spool might be more appropriate than /srv
>>
>> /var/spool is definitively wrong, as this applies to "queue-like" things.
>
> Well, that's your opinion.
>

It's also my opinion. And the opinion of many others e.g. yaVDR Maintainers.
OK timeshift recordings could be saved to /var/spool, but for most
people the recording directory is more like an archive.

>>> /srv is right, if the VDR-machine offers the recordings like a NAS or
>>> MediaServer,
>>
>> FHS says:
>>
>> |  /srv : Data for services provided by this system
>>
>> So as VDR is the primary service of such a box, /srv seems to be OK
>> for me. And many distributions share the recordings via FTP or Samba
>
> /srv in theory is taboo for distros (and it is in fact for Fedora)
> so distros will be forced to patch vdr to use something else. It's
> fine to use for a self compiled vdr but it's not for a distro
> package.

I maintain build scripts for Archlinux (No, not ArchVDR) and there
it's only "taboo" to install files there.
A good example in Archlinux is httpd, nothing is installed to /srv but
httpd is configured to search for website data there.

>
>> For me the discussion about the default setting seems to be
>> useless. The current default seems to match the FHS definitions
>> pretty well and any distribution is able to easily add own
>> settings via make parameters or via Make.config. So feel free to
>> override the default and use your own settings.
>
> We are forced to do that already anyways. If vdr changes anything wrt
> fs layout I'd really like to see something acceptable for distros to
> end the ranting about the different locations of /video.
>
> Where are the vdr package maintainers of other distros hiding anyways?
>

There is a thread about FHS in the German forum VDR-Portal
(http://www.vdr-portal.de/board60-linux/board14-betriebssystem/111165-vdr-verzeichnisse-nach-filesystem-hierarchy-standard-fhs-richtig-ablegen/)
  
Manuel Reimer Sept. 6, 2012, 7 p.m. UTC | #14
Ludwig Nussel wrote:
> I'd still consider a file that is only modified if the user
> intentionally does so via the remote control static. There's no
> difference between that and using an editor except for the user
> interface.

The difference is, that /etc is mounted readonly on some distributions (like 
Debian)! This is OK if you only do changes in very rare cases. In this cases, 
you just remount /etc with writing enabled for that short time.

This doesn't work with VDR. Especially as there doesn't have to be user 
interaction for the files to be modified. VDR changes channels.conf pretty often 
even without the user knowing about that. If you use "epgsearch", then 
"timers.conf" is modified regularly depending on the channels EPG data, ...

This is why such stuff should go below /var/lib.

> /srv in theory is taboo for distros (and it is in fact for Fedora)
> so distros will be forced to patch vdr to use something else.

No need to patch anything. Just prepare your own "Make.config" and place into 
the source directory before you start building VDR.

> It's
> fine to use for a self compiled vdr but it's not for a distro
> package.

I searched the web and for me it seems like even OpenSuSE uses /srv/www to store 
the "service relevant" data for the Apache webserver. So why is this OK for 
Apache but bad for VDR?

VDR does not *install* files to the VIDEODIR, by default. It just uses it to 
store recordings.

Yours

Manuel
  
Manuel Reimer Sept. 6, 2012, 7:09 p.m. UTC | #15
Klaus Schmidinger wrote:
> Attached is a revised version of the patch, as I intend to adopt
> it in version 1.7.30.

Didn't try it, so far, but I had a look at it and maybe, I've found a small problem:

+# By default VDR requires only one single directory to operate:
  VIDEODIR = /video
-CONFDIR  = $(VIDEODIR)
+# See Make.config.template if you want to build VDR according to the FHS ("File 
system Hierarchy Standard")

[...]

+
+install-conf:
+	@cp *.conf $(DESTDIR)$(CONFDIR)


For me this seems like "install-conf" does not longer work if FHS is *not* used, 
as "CONFDIR" is not defined without the FHS mode enabled?

Yours

Manuel
  

Patch

diff -u -b -r2.13 ./INSTALL
--- ./INSTALL	2012/06/03 09:24:21	2.13
+++ ./INSTALL	2012/09/01 10:35:08
@@ -386,6 +386,15 @@ 
 VDR archive into your video directory (or into your config directory,
 respectively, in case you have redirected it with the -c option).
 
+If you prefer to have your system set up according to the FHS
+("File system Hierarchy Standard") and thus have your files spread
+all over the place ;-), you can do this by copying the file Make.config.template
+to Make.config in the VDR source directory, and activating the line
+
+#USEFHS = 1
+
+in that file.
+
 Setting up DiSEqC:
 ------------------
 
diff -u -b -r2.8 ./Make.config.template
--- ./Make.config.template	2012/03/20 11:20:13	2.8
+++ ./Make.config.template	2012/09/01 10:31:33
@@ -28,11 +28,22 @@ 
 MANDIR   = $(PREFIX)/man
 BINDIR   = $(PREFIX)/bin
 
+# By default locale and plugin files are built under the source directory:
 LOCDIR       = ./locale
 PLUGINDIR    = ./PLUGINS
 PLUGINLIBDIR = $(PLUGINDIR)/lib
+# By default VDR requires only one single directory to operate:
 VIDEODIR     = /video
-CONFDIR      = $(VIDEODIR)
+# Activate the following line to build VDR according to the FHS ("File system Hierarchy Standard"):
+#USEFHS = 1
+ifdef USEFHS
+VIDEODIR     = /srv/vdr/video
+CONFDIR      = /var/lib/vdr
+CACHEDIR     = /var/cache/vdr
+RESDIR       = $(PREFIX)/share/vdr
+LOCDIR       = $(PREFIX)/share/locale
+PLUGINLIBDIR = $(PREFIX)/lib/vdr
+endif
 
 ### The remote control:
 
diff -u -b -r2.27 ./Makefile
--- ./Makefile	2012/04/15 13:21:31	2.27
+++ ./Makefile	2012/09/01 13:22:33
@@ -27,8 +27,9 @@ 
 PLUGINDIR= ./PLUGINS
 PLUGINLIBDIR= $(PLUGINDIR)/lib
 
+# By default VDR requires only one single directory to operate:
 VIDEODIR = /video
-CONFDIR  = $(VIDEODIR)
+# See Make.config.template if you want to build VDR according to the FHS ("File system Hierarchy Standard")
 
 DOXYGEN ?= /usr/bin/doxygen
 DOXYFILE = Doxyfile
@@ -70,6 +71,8 @@ 
 
 DEFINES += -DVIDEODIR=\"$(VIDEODIR)\"
 DEFINES += -DCONFDIR=\"$(CONFDIR)\"
+DEFINES += -DCACHEDIR=\"$(CACHEDIR)\"
+DEFINES += -DRESDIR=\"$(RESDIR)\"
 DEFINES += -DPLUGINDIR=\"$(PLUGINLIBDIR)\"
 DEFINES += -DLOCDIR=\"$(LOCDIR)\"
 
@@ -111,6 +114,8 @@ 
 	@echo "includedir=$(INCDIR)" >> $@
 	@echo "configdir=$(CONFDIR)" >> $@
 	@echo "videodir=$(VIDEODIR)" >> $@
+	@echo "cachedir=$(CACHEDIR)" >> $@
+	@echo "resdir=$(RESDIR)" >> $@
 	@echo "plugindir=$(PLUGINLIBDIR)" >> $@
 	@echo "localedir=$(LOCDIR)" >> $@
 	@echo "apiversion=$(APIVERSION)" >> $@
@@ -183,7 +188,7 @@ 
 
 # Install the files:
 
-install: install-bin install-conf install-doc install-plugins install-i18n install-includes install-pc
+install: install-bin install-dirs install-conf install-doc install-plugins install-i18n install-includes install-pc
 
 # VDR binary:
 
@@ -193,12 +198,15 @@ 
 
 # Configuration files:
 
-install-conf:
+install-dirs:
 	@mkdir -p $(DESTDIR)$(VIDEODIR)
-	@if [ ! -d $(DESTDIR)$(CONFDIR) ]; then\
-	    mkdir -p $(DESTDIR)$(CONFDIR);\
-	    cp *.conf $(DESTDIR)$(CONFDIR);\
-	    fi
+	@mkdir -p $(DESTDIR)$(CONFDIR)
+	@mkdir -p $(DESTDIR)$(CACHEDIR)
+	@mkdir -p $(DESTDIR)$(RESDIR)
+
+install-conf:
+	@cp *.conf $(DESTDIR)$(CONFDIR)
+
 
 # Documentation:
 
diff -u -b -r2.15 ./PLUGINS.html
--- ./PLUGINS.html	2012/08/26 13:09:01	2.15
+++ ./PLUGINS.html	2012/08/31 12:46:07
@@ -82,7 +82,7 @@ 
 <li><a href="#Wakeup">Wakeup</a>
 <li><a href="#Setup parameters">Setup parameters</a>
 <li><a href="#The Setup menu">The Setup menu</a>
-<li><a href="#Configuration files">Configuration files</a>
+<li><modified><a href="#Additional files">Additional files</modified></a>
 <li><a href="#Internationalization">Internationalization</a>
 <li><a href="#Custom services">Custom services</a>
 <li><a href="#SVDRP commands">SVDRP commands</a>
@@ -885,39 +885,70 @@ 
 your setup parameters and use that one to copy all parameters with one single statement
 (like VDR does with its cSetup class).
 
-<hr><h2><a name="Configuration files">Configuration files</a></h2>
+<hr><h2><modified><a name="Additional files">Additional files</a></modified></h2>
 
 <div class="blurb">I want my own stuff!</div><p>
 
-There may be situations where a plugin requires configuration files of its own, maybe
-for data that can't be stored in the simple <a href="#Setup parameters">setup parameters</a>
-of VDR, or maybe because it needs to launch other programs that simply need a separate
-configuration file. While the plugin is free to store such files anywhere it
-sees fit, it might be a good idea to put them in a common place, preferably
-where other configuration data already exists. VDR provides the function
+<modified>
+There may be situations where a plugin requires files of its own. While the plugin is
+free to store such files anywhere it sees fit, it might be a good idea to put them in a common
+place, preferably where such data already exists.
+</modified>
+<p>
+<modified>
+<i>configuration files</i>, maybe for data that can't be stored in the simple
+<a href="#Setup parameters">setup parameters</a> of VDR, or maybe because it needs to
+launch other programs that simply need a separate configuration file.
+</modified>
+<p>
+<modified>
+<i>cache files</i>, to store data so that future requests for that data can be served faster. The data
+that is stored within a cache might be values that have been computed earlier or duplicates of
+original values that are stored elsewhere.
+</modified>
+<p>
+<modified>
+<i>resource files</i>, for providing additional files, like pictures, movie clips or channel logos.
+</modified>
+<p>
+<modified>
+Threfore VDR provides the functions
 
 <p><table><tr><td class="code"><pre>
+<modified>
 const char *ConfigDirectory(const char *PluginName = NULL);
+const char *CacheDirectory(const char *PluginName = NULL);
+const char *ResourceDirectory(const char *PluginName = NULL);
+</modified>
 </pre></td></tr></table><p>
 
-which returns a string containing the directory that VDR uses for its own configuration
-files (defined through the <tt><b>-c</b></tt> option in the call to VDR), extended by
+<modified>
+each of which returns a string containing the directory that VDR uses for its own
+files (defined through the options in the call to VDR), extended by
+</modified>
 <tt>"/plugins"</tt>. So assuming the VDR configuration directory is <tt>/video</tt>
 (the default if no <tt><b>-c</b></tt> or <tt><b>-v</b></tt> option is given),
 a call to <tt>ConfigDirectory()</tt> will return <tt>/video/plugins</tt>. The first
 call to <tt>ConfigDirectory()</tt> will automatically make sure that the <tt>plugins</tt>
 subdirectory will exist. If, for some reason, this cannot be achieved, <tt>NULL</tt>
 will be returned.
+<modified>
+The behavoir of <tt>CacheDirectory()</tt> and <tt>ResourceDirectory()</tt> is similar.
+</modified>
 <p>
 The additional <tt>plugins</tt> directory is used to keep files from plugins apart
 from those of VDR itself, making sure there will be no name clashes. If a plugin
-needs only one extra configuration file, it is suggested that this file be named
-<tt>name.conf</tt>, where <i>name</i> shall be the name of the plugin.
+<modified>
+needs only one extra file, it is suggested that this file be named <tt>name.*</tt>,
+where <i>name</i> shall be the name of the plugin.
+</modified>
 <p>
 If a plugin needs more than one such file, it is suggested that the plugin stores
 these in a subdirectory of its own, named after the plugin. To easily get such a name
-the <tt>ConfigDirectory()</tt> function can be given an additional string that will
-be appended to the returned directory name, as in
+<modified>
+the functions can be given an additional string that will be appended to the returned
+directory name, as in
+</modified>
 
 <p><table><tr><td class="code"><pre>
 const char *MyConfigDir = ConfigDirectory(Name());
@@ -928,13 +959,16 @@ 
 (or return <tt>NULL</tt> in case of an error).
 <p>
 <b>
-The returned string is statically allocated and will be overwritten by subsequent
-calls to ConfigDirectory()!
+<modified>
+The returned strings are statically allocated and will be overwritten by subsequent calls!
+</modified>
 </b>
 <p>
-The <tt>ConfigDirectory()</tt> function is a static member function of the <tt>cPlugin</tt>
-class. This allows it to be called even from outside any member function of the derived
-plugin class, by writing
+<modified>
+The <tt>ConfigDirectory()</tt>, <tt>CacheDirectory()</tt> and <tt>ResourceDirectory()</tt>
+functions are static member functions of the <tt>cPlugin</tt> class. This allows them to be
+called even from outside any member function of the derived plugin class, by writing
+</modified>
 
 <p><table><tr><td class="code"><pre>
 const char *MyConfigDir = cPlugin::ConfigDirectory();
diff -u -b -r2.4 ./i18n.c
--- ./i18n.c	2011/08/15 10:01:45	2.4
+++ ./i18n.c	2012/09/01 10:53:43
@@ -63,7 +63,7 @@ 
   NULL
   };
 
-static const char *I18nLocaleDir = LOCDIR;
+static cString I18nLocaleDir;
 
 static cStringList LanguageLocales;
 static cStringList LanguageNames;
@@ -102,7 +102,6 @@ 
 
 void I18nInitialize(const char *LocaleDir)
 {
-  if (LocaleDir)
      I18nLocaleDir = LocaleDir;
   LanguageLocales.Append(strdup(I18N_DEFAULT_LOCALE));
   LanguageNames.Append(strdup(SkipContext(LanguageName)));
@@ -113,7 +112,7 @@ 
   if (Locales.Size() > 0) {
      char *OldLocale = strdup(setlocale(LC_MESSAGES, NULL));
      for (int i = 0; i < Locales.Size(); i++) {
-         cString FileName = cString::sprintf("%s/%s/LC_MESSAGES/vdr.mo", I18nLocaleDir, Locales[i]);
+         cString FileName = cString::sprintf("%s/%s/LC_MESSAGES/vdr.mo", *I18nLocaleDir, Locales[i]);
          if (access(FileName, F_OK) == 0) { // found a locale with VDR texts
             if (NumLocales < I18N_MAX_LANGUAGES - 1) {
                SetEnvLanguage(Locales[i]);
@@ -142,7 +141,7 @@ 
          }
      SetEnvLanguage(LanguageLocales[CurrentLanguage]);
      free(OldLocale);
-     dsyslog("found %d locales in %s", NumLocales - 1, I18nLocaleDir);
+     dsyslog("found %d locales in %s", NumLocales - 1, *I18nLocaleDir);
      }
   // Prepare any known language codes for which there was no locale:
   for (const char **lc = LanguageCodeList; *lc; lc++) {
diff -u -b -r2.3 ./plugin.c
--- ./plugin.c	2012/03/11 13:56:02	2.3
+++ ./plugin.c	2012/09/01 13:10:27
@@ -25,7 +25,9 @@ 
 
 // --- cPlugin ---------------------------------------------------------------
 
-char *cPlugin::configDirectory = NULL;
+cString cPlugin::configDirectory;
+cString cPlugin::cacheDirectory;
+cString cPlugin::resourceDirectory;
 
 cPlugin::cPlugin(void)
 {
@@ -132,8 +134,7 @@ 
 
 void cPlugin::SetConfigDirectory(const char *Dir)
 {
-  free(configDirectory);
-  configDirectory = strdup(Dir);
+  configDirectory = Dir;
 }
 
 const char *cPlugin::ConfigDirectory(const char *PluginName)
@@ -141,7 +142,35 @@ 
   static cString buffer;
   if (!cThread::IsMainThread())
      esyslog("ERROR: plugin '%s' called cPlugin::ConfigDirectory(), which is not thread safe!", PluginName ? PluginName : "<no name given>");
-  buffer = cString::sprintf("%s/plugins%s%s", configDirectory, PluginName ? "/" : "", PluginName ? PluginName : "");
+  buffer = cString::sprintf("%s/plugins%s%s", *configDirectory, PluginName ? "/" : "", PluginName ? PluginName : "");
+  return MakeDirs(buffer, true) ? *buffer : NULL;
+}
+
+void cPlugin::SetCacheDirectory(const char *Dir)
+{
+  cacheDirectory = Dir;
+}
+
+const char *cPlugin::CacheDirectory(const char *PluginName)
+{
+  static cString buffer;
+  if (!cThread::IsMainThread())
+     esyslog("ERROR: plugin '%s' called cPlugin::CacheDirectory(), which is not thread safe!", PluginName ? PluginName : "<no name given>");
+  buffer = cString::sprintf("%s/plugins%s%s", *cacheDirectory, PluginName ? "/" : "", PluginName ? PluginName : "");
+  return MakeDirs(buffer, true) ? *buffer : NULL;
+}
+
+void cPlugin::SetResourceDirectory(const char *Dir)
+{
+  resourceDirectory = Dir;
+}
+
+const char *cPlugin::ResourceDirectory(const char *PluginName)
+{
+  static cString buffer;
+  if (!cThread::IsMainThread())
+     esyslog("ERROR: plugin '%s' called cPlugin::ResourceDirectory(), which is not thread safe!", PluginName ? PluginName : "<no name given>");
+  buffer = cString::sprintf("%s/plugins%s%s", *resourceDirectory, PluginName ? "/" : "", PluginName ? PluginName : "");
   return MakeDirs(buffer, true) ? *buffer : NULL;
 }
 
diff -u -b -r2.1 ./plugin.h
--- ./plugin.h	2012/03/11 13:55:56	2.1
+++ ./plugin.h	2012/09/01 13:08:54
@@ -21,7 +21,9 @@ 
   friend class cDll;
   friend class cPluginManager;
 private:
-  static char *configDirectory;
+  static cString configDirectory;
+  static cString cacheDirectory;
+  static cString resourceDirectory;
   const char *name;
   bool started;
   void SetName(const char *s);
@@ -57,6 +59,10 @@ 
 
   static void SetConfigDirectory(const char *Dir);
   static const char *ConfigDirectory(const char *PluginName = NULL);
+  static void SetCacheDirectory(const char *Dir);
+  static const char *CacheDirectory(const char *PluginName = NULL);
+  static void SetResourceDirectory(const char *Dir);
+  static const char *ResourceDirectory(const char *PluginName = NULL);
   };
 
 class cDll : public cListObject {
diff -u -b -r2.8 ./vdr.1
--- ./vdr.1	2012/02/27 11:01:17	2.8
+++ ./vdr.1	2012/09/01 13:40:49
@@ -42,6 +42,10 @@ 
 .BI \-a\  cmd ,\ \-\-audio= cmd
 Send Dolby Digital audio to stdin of command \fIcmd\fR.
 .TP
+.BI \-\-cachedir= dir
+save cache files in \fIdir\fR
+(default is to save them in the video directory).
+.TP
 .BI \-c\  dir ,\ \-\-config= dir
 Read config files from directory \fIdir\fR
 (default is to read them from the video directory).
@@ -157,6 +161,10 @@ 
 Call \fIcmd\fR before and after a recording. See the file \fIINSTALL\fR for
 more information.
 .TP
+.BI \-\-resdir= dir
+read resource files from \fIdir\fR
+(default is to read them from the config directory).
+.TP
 .BI \-s\  cmd ,\ \-\-shutdown= cmd
 Call \fIcmd\fR to shutdown the computer. See the file \fIINSTALL\fR for more
 information.
diff -u -b -r2.37 ./vdr.c
--- ./vdr.c	2012/06/13 11:28:41	2.37
+++ ./vdr.c	2012/09/01 13:30:19
@@ -178,10 +178,15 @@ 
 
   // Command line options:
 
+#define dd(a, b) (*a ? a : b)
 #define DEFAULTSVDRPPORT 6419
 #define DEFAULTWATCHDOG     0 // seconds
-#define DEFAULTCONFDIR CONFDIR
+#define DEFAULTVIDEODIR VIDEODIR
+#define DEFAULTCONFDIR dd(CONFDIR, VideoDirectory)
+#define DEFAULTCACHEDIR dd(CACHEDIR, VideoDirectory)
+#define DEFAULTRESDIR dd(RESDIR, ConfigDirectory)
 #define DEFAULTPLUGINDIR PLUGINDIR
+#define DEFAULTLOCDIR LOCDIR
 #define DEFAULTEPGDATAFILENAME "epg.data"
 
   bool StartedAsRoot = false;
@@ -189,7 +194,11 @@ 
   bool UserDump = false;
   int SVDRPport = DEFAULTSVDRPPORT;
   const char *AudioCommand = NULL;
+  const char *VideoDirectory = DEFAULTVIDEODIR;
   const char *ConfigDirectory = NULL;
+  const char *CacheDirectory = NULL;
+  const char *ResourceDirectory = NULL;
+  const char *LocaleDirectory = DEFAULTLOCDIR;
   const char *EpgDataFileName = DEFAULTEPGDATAFILENAME;
   bool DisplayHelp = false;
   bool DisplayVersion = false;
@@ -198,7 +207,6 @@ 
   bool MuteAudio = false;
   int WatchdogTimeout = DEFAULTWATCHDOG;
   const char *Terminal = NULL;
-  const char *LocaleDir = NULL;
 
   bool UseKbd = true;
   const char *LircDevice = NULL;
@@ -216,6 +224,7 @@ 
 
   static struct option long_options[] = {
       { "audio",    required_argument, NULL, 'a' },
+      { "cachedir", required_argument, NULL, 'c' | 0x100 },
       { "config",   required_argument, NULL, 'c' },
       { "daemon",   no_argument,       NULL, 'd' },
       { "device",   required_argument, NULL, 'D' },
@@ -235,6 +244,7 @@ 
       { "plugin",   required_argument, NULL, 'P' },
       { "port",     required_argument, NULL, 'p' },
       { "record",   required_argument, NULL, 'r' },
+      { "resdir",   required_argument, NULL, 'r' | 0x100 },
       { "shutdown", required_argument, NULL, 's' },
       { "split",    no_argument,       NULL, 's' | 0x100 },
       { "terminal", required_argument, NULL, 't' },
@@ -252,6 +262,9 @@ 
         switch (c) {
           case 'a': AudioCommand = optarg;
                     break;
+          case 'c' | 0x100:
+                    CacheDirectory = optarg;
+                    break;
           case 'c': ConfigDirectory = optarg;
                     break;
           case 'd': DaemonMode = true; break;
@@ -327,7 +340,7 @@ 
                     break;
           case 'l' | 0x200:
                     if (access(optarg, R_OK | X_OK) == 0)
-                       LocaleDir = optarg;
+                       LocaleDirectory = optarg;
                     else {
                        fprintf(stderr, "vdr: can't access locale directory: %s\n", optarg);
                        return 2;
@@ -349,6 +362,9 @@ 
                     break;
           case 'r': cRecordingUserCommand::SetCommand(optarg);
                     break;
+          case 'r' | 0x100:
+                    ResourceDirectory = optarg;
+                    break;
           case 's': ShutdownHandler.SetShutdownCommand(optarg);
                     break;
           case 's' | 0x100:
@@ -414,6 +430,7 @@ 
      if (DisplayHelp) {
         printf("Usage: vdr [OPTIONS]\n\n"          // for easier orientation, this is column 80|
                "  -a CMD,   --audio=CMD    send Dolby Digital audio to stdin of command CMD\n"
+               "            --cachedir=DIR save cache files in DIR (default: %s)\n"
                "  -c DIR,   --config=DIR   read config files from DIR (default: %s)\n"
                "  -d,       --daemon       run in daemon mode\n"
                "  -D NUM,   --device=NUM   use only the given DVB device (NUM = 0, 1, 2...)\n"
@@ -450,6 +467,7 @@ 
                "                           0 turns off SVDRP\n"
                "  -P OPT,   --plugin=OPT   load a plugin defined by the given options\n"
                "  -r CMD,   --record=CMD   call CMD before and after a recording\n"
+               "            --resdir=DIR   read resource files from DIR (default: %s)\n"
                "  -s CMD,   --shutdown=CMD call CMD to shutdown the computer\n"
                "            --split        split edited files at the editing marks (only\n"
                "                           useful in conjunction with --edit)\n"
@@ -464,14 +482,16 @@ 
                "  -w SEC,   --watchdog=SEC activate the watchdog timer with a timeout of SEC\n"
                "                           seconds (default: %d); '0' disables the watchdog\n"
                "\n",
+               DEFAULTCACHEDIR,
                DEFAULTCONFDIR,
                DEFAULTEPGDATAFILENAME,
                MAXVIDEOFILESIZEDEFAULT,
                DEFAULTPLUGINDIR,
                LIRC_DEVICE,
-               LOCDIR,
+               DEFAULTLOCDIR,
                DEFAULTSVDRPPORT,
-               VideoDirectory,
+               DEFAULTRESDIR,
+               DEFAULTVIDEODIR,
                DEFAULTWATCHDOG
                );
         }
@@ -555,7 +575,7 @@ 
 
   // Initialize internationalization:
 
-  I18nInitialize(LocaleDir);
+  I18nInitialize(LocaleDirectory);
 
   // Main program loop variables - need to be here to have them initialized before any EXIT():
 
@@ -577,14 +597,22 @@ 
   if (!PluginManager.LoadPlugins(true))
      EXIT(2);
 
-  // Configuration data:
+  // Directories:
 
+  SetVideoDirectory(VideoDirectory);
   if (!ConfigDirectory)
      ConfigDirectory = DEFAULTCONFDIR;
-
   cPlugin::SetConfigDirectory(ConfigDirectory);
+  if (!CacheDirectory)
+     CacheDirectory = DEFAULTCACHEDIR;
+  cPlugin::SetCacheDirectory(CacheDirectory);
+  if (!ResourceDirectory)
+     ResourceDirectory = DEFAULTRESDIR;
+  cPlugin::SetResourceDirectory(ResourceDirectory);
   cThemes::SetThemesDirectory(AddDirectory(ConfigDirectory, "themes"));
 
+  // Configuration data:
+
   Setup.Load(AddDirectory(ConfigDirectory, "setup.conf"));
   Sources.Load(AddDirectory(ConfigDirectory, "sources.conf"), true, true);
   Diseqcs.Load(AddDirectory(ConfigDirectory, "diseqc.conf"), true, Setup.DiSEqC);
@@ -618,7 +646,7 @@ 
         EpgDataFileName = DEFAULTEPGDATAFILENAME;
         }
      else if (*EpgDataFileName != '/' && *EpgDataFileName != '.')
-        EpgDirectory = VideoDirectory;
+        EpgDirectory = CacheDirectory;
      if (EpgDirectory)
         cSchedules::SetEpgDataFileName(AddDirectory(EpgDirectory, EpgDataFileName));
      else
diff -u -b -r2.2 ./videodir.c
--- ./videodir.c	2012/06/10 13:45:21	2.2
+++ ./videodir.c	2012/09/01 10:57:44
@@ -21,6 +21,11 @@ 
 
 const char *VideoDirectory = VIDEODIR;
 
+void SetVideoDirectory(const char *Directory)
+{
+  VideoDirectory = strdup(Directory);
+}
+
 class cVideoDirectory {
 private:
   char *name, *stored, *adjusted;
diff -u -b -r2.1 ./videodir.h
--- ./videodir.h	2012/04/22 15:07:56	2.1
+++ ./videodir.h	2012/09/01 10:57:07
@@ -15,6 +15,7 @@ 
 
 extern const char *VideoDirectory;
 
+void SetVideoDirectory(const char *Directory);
 cUnbufferedFile *OpenVideoFile(const char *FileName, int Flags);
 int CloseVideoFile(cUnbufferedFile *File);
 bool RenameVideoFile(const char *OldName, const char *NewName);