summaryrefslogtreecommitdiff
path: root/tools.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools.c')
-rw-r--r--tools.c329
1 files changed, 266 insertions, 63 deletions
diff --git a/tools.c b/tools.c
index d57bcb7..439051e 100644
--- a/tools.c
+++ b/tools.c
@@ -2,13 +2,48 @@
* See the README file for copyright information and how to reach the author.
*/
+#include <string>
+#include <fstream>
+#include <iostream>
#include <vdr/plugin.h>
#include <vdr/videodir.h>
#include <vdr/recording.h>
#include "tools.h"
#include "mymenusetup.h"
+using namespace std;
+
#define CONFIGFILE "/extrecmenu.sort.conf"
+#define BUFFERSIZE 20972 // (2*1024*1024)/100
+
+MoveBetweenFileSystems MoveThread;
+
+string myStrEscape(string S,const char *Chars)
+{
+ int i=0;
+ while(Chars[i]!=0)
+ {
+ string::size_type j=0;
+ while((j=S.find(Chars[i],j))!=string::npos)
+ {
+ S.insert(j,1,'\\');
+ j+=2;
+ }
+ i++;
+ }
+ return S;
+}
+
+string myStrReplace(string S,char C1,char C2)
+{
+ string::size_type i=0;
+ while((i=S.find(C1,i))!=string::npos)
+ {
+ S.replace(i,1,1,C2);
+ i++;
+ }
+ return S;
+}
// --- SortList ---------------------------------------------------------------
void SortList::ReadConfigFile()
@@ -50,84 +85,252 @@ bool SortList::Find(char *Path)
return false;
}
-// --- MoveRename -------------------------------------------------------------
-// creates the necassery directories and renames the given old name to the new name
-bool MoveRename(const char *OldName,const char *NewName,cRecording *Recording,bool Move)
+// --- MoveBetweenFileSystems -------------------------------------------------
+MoveBetweenFileSystems::MoveBetweenFileSystems():cThread("moving files between filesystems")
{
- char *buf=NULL;
+}
- // is OldName different to NewName
- if(!strcmp(OldName,NewName))
- return true;
+bool MoveBetweenFileSystems::Start(string OldName,string NewName,cRecording *Recording)
+{
+ oldname=OldName;
+ newname=NewName;
+ recording=Recording;
+
+ return cThread::Start();
+}
- // move/rename a recording
- if(Recording)
- {
- if(!MakeDirs(NewName,true))
+bool MoveBetweenFileSystems::IsMoving(string Path)
+{
+ if(Active())
{
- Skins.Message(mtError,tr("Creating directories failed!"));
- return false;
+ if(recording)
+ {
+ if(Path==oldname)
+ return true;
+ }
+ else
+ {
+ if(!strncmp(oldname.c_str(),Path.c_str(),oldname.length()))
+ return true;
+ }
}
- isyslog("[extrecmenu] moving %s to %s",OldName,NewName);
-
- if(rename(OldName,NewName)==-1)
+ return false;
+}
+
+bool MoveBetweenFileSystems::Move(string From,string To,cRecording *Recording)
+{
+ if(Recording)
{
- esyslog("[extrecmenu] %s",strerror(errno));
- Skins.Message(mtError,tr("Rename/Move failed!"));
- return false;
+ isyslog("[extrecmenu] moving %s to %s",From.c_str(),To.c_str());
+
+ DIR *dir;
+ struct dirent *entry;
+ dir=opendir(From.c_str());
+ while((entry=readdir(dir))!=NULL)
+ {
+ string from,to;
+ from=From+'/'+entry->d_name;
+ to=To+'/'+entry->d_name;
+
+ struct stat st;
+ stat(from.c_str(),&st);
+ if(S_ISREG(st.st_mode))
+ {
+ isyslog("[extrecmenu] moving %s",entry->d_name);
+
+ time_t copytime=time(NULL);
+
+ char buf[BUFFERSIZE];
+ int infile=-1,outfile=-1;
+ struct stat from_stat;
+ ssize_t sz,sz_read=1,sz_write;
+
+ if(stat(from.c_str(),&from_stat)!=0 ||
+ (infile=open(from.c_str(),O_RDONLY))<0 ||
+ (outfile=open(to.c_str(),O_WRONLY|O_CREAT|O_EXCL,from_stat.st_mode))<0)
+ {
+ if(infile>=0)
+ close(infile);
+ closedir(dir);
+
+ Skins.Message(mtError,strerror(errno));
+ return false;
+ }
+
+ while(sz_read>0 && (sz_read=read(infile,buf,BUFFERSIZE))>0)
+ {
+ sz_write=0;
+ do
+ {
+ if((sz=write(outfile,buf+sz_write,sz_read-sz_write))<0)
+ {
+ close(infile);
+ close(outfile);
+ closedir(dir);
+
+ Skins.Message(mtError,tr("Rename/Move failed!"));
+ esyslog("[extrecmenu] %s",strerror(errno));
+ return false;
+ }
+ sz_write+=sz;
+ }
+ while(sz_write<sz_read);
+
+ if(mysetup.LimitBandwidth)
+ usleep(10);
+ }
+ close(infile);
+ close(outfile);
+
+ copytime=time(NULL)-copytime;
+ isyslog("[extrecmenu] needed %d secs for %d bytes",(int)copytime,(int)st.st_size);
+ }
+ }
+ closedir(dir);
+
+ Recordings.AddByName(To.c_str());
+ Recording->Delete();
+ Recordings.DelByName(From.c_str());
+
+ string buf="move \"";
+ buf+=myStrEscape(From,"'\\\"$");
+ buf+="\"";
+ cRecordingUserCommand::InvokeCommand(buf.c_str(),To.c_str());
}
-
- // set user command for '-r'-option of VDR
- asprintf(&buf,"%s \"%s\"",Move?"move":"rename",*strescape(OldName,"'\\\"$"));
- cRecordingUserCommand::InvokeCommand(buf,NewName);
- free(buf);
-
- // update recordings list
- Recordings.AddByName(NewName);
- Recordings.Del(Recording);
- }
- // move/rename a directory
- else
- {
- // is the new path within the old?
- asprintf(&buf,"%s/",OldName); // we have to append a / to make sure that we search for a directory
- if(!strncmp(buf,NewName,strlen(buf)))
+ else
{
- Skins.Message(mtError,tr("Moving into own sub-directory not allowed!"));
- free(buf);
- return false;
+ string buf;
+ buf=From+'/';
+ if(!strncmp(buf.c_str(),To.c_str(),buf.length()))
+ {
+ Skins.Message(mtError,tr("Moving into own sub-directory not allowed!"));
+ return false;
+ }
+
+ myRecList *list=new myRecList();
+ for(cRecording *recording=Recordings.First();recording;recording=Recordings.Next(recording))
+ list->Add(new myRecListItem(recording));
+
+ myRecListItem *item=list->First();
+ while(item)
+ {
+ if(!strncmp(From.c_str(),item->recording->FileName(),From.length()))
+ {
+ char *buffer=NULL;
+ buffer=strdup(From.c_str()+strlen(VideoDirectory)+1);
+ buffer=ExchangeChars(buffer,false);
+
+ if(strcmp(item->recording->Name(),buffer))
+ {
+ buf=To+(item->recording->FileName()+From.length());
+ if(!MakeDirs(buf.c_str(),true))
+ {
+ Skins.Message(mtError,tr("Rename/Move failed!"));
+ esyslog("[extrecmenu] %s",strerror(errno));
+ free(buffer);
+ delete list;
+ return false;
+ }
+ if(Move(item->recording->FileName(),buf,item->recording)==false)
+ {
+ free(buffer);
+ delete list;
+ return false;
+ }
+ }
+ free(buffer);
+ }
+ item=list->Next(item);
+ }
+ delete list;
}
- free(buf);
-
- // build my own recordings list
- myRecList *list=new myRecList();
- for(cRecording *recording=Recordings.First();recording;recording=Recordings.Next(recording))
- list->Add(new myRecListItem(recording));
+ return true;
+}
+
+void MoveBetweenFileSystems::Action()
+{
+ Move(oldname,newname,recording);
+}
+
+// --- MoveRename -------------------------------------------------------------
+// creates the necassery directories and renames the given old name to the new name
+bool MoveRename(const char *OldName,const char *NewName,cRecording *Recording,bool Move)
+{
+ char *buf=NULL;
+
+ if(!strcmp(OldName,NewName))
+ return true;
- myRecListItem *item=list->First();
- while(item)
+ if(Recording)
{
- // find recordings within the path of OldName
- if(!strncmp(OldName,item->recording->FileName(),strlen(OldName)))
- {
- buf=strdup(OldName+strlen(VideoDirectory)+1);
- buf=ExchangeChars(buf,false);
-
- // exclude recordings with the same name as OldName
- if(strcmp(item->recording->Name(),buf))
+ isyslog("[extrecmenu] moving %s to %s",OldName,NewName);
+
+ if(rename(OldName,NewName)==-1)
{
- free(buf);
- asprintf(&buf,"%s%s",NewName,item->recording->FileName()+strlen(OldName));
- // move/rename the recording
- MoveRename(item->recording->FileName(),buf,item->recording,Move);
+ remove(NewName); // remove created directory
+ Skins.Message(mtError,tr("Rename/Move failed!"));
+ esyslog("[extrecmenu] %s",strerror(errno));
+ return false;
}
+
+ Recordings.AddByName(NewName);
+ Recordings.Del(Recording);
+
+ // set user command for '-r'-option of VDR
+ asprintf(&buf,"%s \"%s\"",Move?"move":"rename",*strescape(OldName,"'\\\"$"));
+ cRecordingUserCommand::InvokeCommand(buf,NewName);
free(buf);
- }
- item=list->Next(item);
}
- delete list;
- }
- return true;
+ else
+ {
+ // is the new path within the old?
+ asprintf(&buf,"%s/",OldName); // we have to append a / to make sure that we search for a directory
+ if(!strncmp(buf,NewName,strlen(buf)))
+ {
+ Skins.Message(mtError,tr("Moving into own sub-directory not allowed!"));
+ free(buf);
+ return false;
+ }
+ free(buf);
+
+ myRecList *list=new myRecList();
+ for(cRecording *recording=Recordings.First();recording;recording=Recordings.Next(recording))
+ list->Add(new myRecListItem(recording));
+
+ myRecListItem *item=list->First();
+ while(item)
+ {
+ if(!strncmp(OldName,item->recording->FileName(),strlen(OldName)))
+ {
+ buf=strdup(OldName+strlen(VideoDirectory)+1);
+ buf=ExchangeChars(buf,false);
+
+ if(strcmp(item->recording->Name(),buf))
+ {
+ free(buf);
+ asprintf(&buf,"%s%s",NewName,item->recording->FileName()+strlen(OldName));
+ if(!MakeDirs(buf,true))
+ {
+ Skins.Message(mtError,tr("Creating directories failed!"));
+ esyslog("[extrecmenu] %s",strerror(errno));
+ free(buf);
+ delete list;
+ return false;
+ }
+ if(MoveRename(item->recording->FileName(),buf,item->recording,Move)==false)
+ {
+ free(buf);
+ delete list;
+ return false;
+ }
+ }
+ free(buf);
+ }
+ item=list->Next(item);
+ }
+ delete list;
+ }
+ return true;
}
// --- myRecListItem ----------------------------------------------------------