From 36fa10802aadd187477c456cb7b736bb65a37a8a Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Thu, 30 Mar 2017 10:06:35 -0400 Subject: [PATCH] 2017-03-30 Fred Gleason * Added '--relink-audio' and '--relink-audio-move' commands to rddbcheck(8) in 'utils/rddbcheck.cpp' and 'utils/rddbcheck.h'. --- ChangeLog | 3 + docs/docbook/rddbcheck.xml | 37 ++++++++- utils/rddbcheck/rddbcheck.cpp | 136 ++++++++++++++++++++++++++++++++++ utils/rddbcheck/rddbcheck.h | 4 + 4 files changed, 177 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index c18aa90a..be33bf79 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15678,3 +15678,6 @@ 2017-03-29 Fred Gleason * Modified rddbcheck(8) so as to process a --rehash command after the inexpensive checks. +2017-03-30 Fred Gleason + * Added '--relink-audio' and '--relink-audio-move' commands to + rddbcheck(8) in 'utils/rddbcheck.cpp' and 'utils/rddbcheck.h'. diff --git a/docs/docbook/rddbcheck.xml b/docs/docbook/rddbcheck.xml index 718d71e8..3a1e8e96 100644 --- a/docs/docbook/rddbcheck.xml +++ b/docs/docbook/rddbcheck.xml @@ -6,7 +6,7 @@ rddbcheck 8 - June 2016 + March 2017 Linux Audio Manual @@ -47,7 +47,7 @@ - Options + Consistency Check Options @@ -159,9 +159,40 @@ - + Audio Recovery Options + + + + dir-name + + + + Scan the files in the directory dir-name + and copy/rename them into the Rivendell audio store if their SHA-1 + hash matches that for one or more Rivendell cuts. + + + + + + + + + + + When given along with , move the + audio data to the Rivendell audio store rather than copying it + --i.e. copy the audio data, then delete the original. + + + + + + + + See Also diff --git a/utils/rddbcheck/rddbcheck.cpp b/utils/rddbcheck/rddbcheck.cpp index e3e01056..3ced9e12 100644 --- a/utils/rddbcheck/rddbcheck.cpp +++ b/utils/rddbcheck/rddbcheck.cpp @@ -20,10 +20,13 @@ #include #include +#include +#include #include #include #include #include +#include #include #include @@ -57,6 +60,8 @@ MainObject::MainObject(QObject *parent) check_yes=false; check_no=false; QString username="user"; + relink_audio=""; + relink_audio_move=false; // // Read Command Options @@ -82,6 +87,12 @@ MainObject::MainObject(QObject *parent) if(cmd->key(i)=="--dump-cuts-dir") { dump_cuts_dir=cmd->value(i); } + if(cmd->key(i)=="--relink-audio") { + relink_audio=cmd->value(i); + } + if(cmd->key(i)=="--relink-audio-move") { + relink_audio_move=true; + } if(cmd->key(i)=="--rehash") { rehash=cmd->value(i); } @@ -174,6 +185,14 @@ MainObject::MainObject(QObject *parent) delete q; } + // + // Recover Audio + // + if(!relink_audio.isEmpty()) { + RelinkAudio(relink_audio); + exit(0); + } + // // Check for Orphaned Voice Tracks // @@ -785,6 +804,83 @@ void MainObject::RehashCut(const QString &cutnum) } +void MainObject::RelinkAudio(const QString &srcdir) +{ + QString sql; + RDSqlQuery *q; + + QDir dir(srcdir); + if(!dir.exists()) { + fprintf(stderr,"rddbcheck: --relink-audio directory does not exist\n"); + exit(256); + } + QStringList files=dir.entryList(QDir::Files|QDir::Readable|QDir::Hidden); + for(unsigned i=0;inext()) { + printf(" Recovering %06u/%03d [%s]...", + RDCut::cartNumber(q->value(0).toString()), + RDCut::cutNumber(q->value(0).toString()), + (const char *)q->value(1).toString()); + fflush(stdout); + if(relink_audio_move) { + unlink(RDCut::pathName(q->value(0).toString())); + if(link(filename,RDCut::pathName(q->value(0).toString()))<0) { + if(errno==EXDEV) { + if(firstdest.isEmpty()) { + if(CopyFile(RDCut::pathName(q->value(0).toString()),filename)) { + firstdest=RDCut::pathName(q->value(0).toString()); + } + else { + fprintf(stderr,"unable to copy file \"%s\"\n", + (const char *)filename); + delete_source=false; + } + } + else { + unlink(RDCut::pathName(q->value(0).toString())); + link(firstdest,RDCut::pathName(q->value(0).toString())); + } + } + else { + fprintf(stderr,"unable to move file \"%s\" [%s]\n", + (const char *)filename,strerror(errno)); + delete_source=false; + } + } + } + else { + if(firstdest.isEmpty()) { + if(CopyFile(RDCut::pathName(q->value(0).toString()),filename)) { + firstdest=RDCut::pathName(q->value(0).toString()); + } + else { + fprintf(stderr,"unable to copy file \"%s\"\n", + (const char *)filename); + } + } + else { + unlink(RDCut::pathName(q->value(0).toString())); + link(firstdest,RDCut::pathName(q->value(0).toString())); + } + } + printf(" done.\n"); + } + if(relink_audio_move&&delete_source) { + unlink(filename); + } + } +} + + void MainObject::SetCutLength(const QString &cutname,int len) { QString sql; @@ -883,6 +979,46 @@ bool MainObject::IsTableLinked(QSqlQuery *name_q,const QString &ext, } +bool MainObject::CopyFile(const QString &destfile,const QString &srcfile) const +{ + int src_fd=-1; + struct stat src_stat; + int dest_fd=-1; + struct stat dest_stat; + int n; + int blksize; + char *data=NULL; + + if((src_fd=open(srcfile,O_RDONLY))<0) { + return false; + } + fstat(src_fd,&src_stat); + mode_t mask=umask(S_IRWXO); + if((dest_fd=open(destfile,O_WRONLY|O_CREAT|O_TRUNC, + S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP))<0) { + close(src_fd); + return false; + } + umask(mask); + fstat(dest_fd,&dest_stat); + blksize=src_stat.st_blksize; + if(dest_stat.st_blksize