Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- tagbkup - mp3 tag backup and restore
- Copyright (c) 2004 Peter G. Bennett
- This file is part of Jampal.
- Jampal is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Jampal is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Jampal. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #ifndef OS_Linux
- #include <io.h>
- #endif
- #ifdef OS_Linux
- #include <unistd.h>
- #include <sys/types.h>
- #endif
- #include <fcntl.h>
- #include <sys/stat.h>
- #ifdef __CYGWIN32__
- #include <sys/cygwin.h>
- #endif
- #ifdef _MSC_VER
- #include <direct.h>
- #define strcasecmp stricmp
- #define strncasecmp strnicmp
- #define ftruncate chsize
- #endif
- #include <time.h>
- //#include <windows.h>
- //#include "MP3Info.h"
- #include "mp3info_u.h"
- const size_t BufSize = 16384;
- const int MaxFName = 260;
- int FileProcCount = 0;
- int IsBkupGlob = 0;
- int IsRestGlob = 0;
- int IsCopyGlob = 0;
- int IsTestGlob = 0;
- int IsOutFileGlob=0;
- int IsVerbose = 0;
- int IsCopyV1 = 0;
- int IsCopyV2 = 0;
- int IsCopyMp3 = 0;
- int ReportUpdates = 0;
- int OverwriteBkup = 1;
- char *pRestDir = 0;
- char *pFileSpec = 0;
- char *pBkupDir = 0;
- FILE *fpLog;
- FILE *std_err = stderr;
- unsigned int (*pSignatureList)[2] = 0;
- int countSignature=0;
- int Instruct=0;
- int bypassErrs = 0;
- int signatureOnFront = 0;
- int tagSubdirs = 0;
- int GetFileSignature(char *pFoundName, unsigned int *pSig, size_t *pData_start);
- int getDataStart(char *pFoundName, size_t *pDataStart);
- int CopyTag(char *pOutputFile, char *pInputFile);
- int CompareTag(char *pOutputFile, char *pInputFile);
- int AppendMP3Data(char *pOutputFile, char *pInputFile, size_t data_start);
- int GetTagSize(FILE *fpIn, size_t *pTagSize);
- // int UpdateTagV1(char *pFile);
- int openBackupLog();
- int ProcessFile(char *pMP3FileName);
- void mkdir_f(char *fileName);
- int AppendTagV1(char *pOutFile,char *pInFile);
- int countV1Tags(FILE *fpIn, int &v1tags, off_t &dataEnd);
- // a useful macro
- #define IsID3Tag(s) (s[0] == 'T' && s[1] == 'A' && s[2] == 'G')
- extern int nullMp3[];
- extern size_t nullMp3size;
- int main(int argc, char *argv[], char * /*envp*/ []) {
- int IsOK=1;
- int i;
- char fileName[512];
- fprintf(stderr,"tagbkup Version **UNSTABLE** (c) 2004-2010 Peter G. Bennett\n");
- #ifdef __CYGWIN32__
- fprintf(stderr,"Cygwin version, ");
- #endif
- #ifdef _MSC_VER
- fprintf(stderr,"Win32 version, ");
- #endif
- #ifdef OS_Linux
- fprintf(stderr,"Linux version, ");
- #endif
- #ifdef CPU_x86_64
- fprintf(stderr,"64 bit.\n");
- #else
- fprintf(stderr,"32 bit.\n");
- #endif
- // Last parameter is backup dir
- pBkupDir = argv[argc-1];
- if (argc < 3 || *pBkupDir == '-'){
- Instruct = 1;
- IsOK=0;
- }
- struct stat fileStat;
- int ret;
- if (IsOK) {
- fileStat.st_mode=0;
- ret=stat(pBkupDir,&fileStat);
- if (ret!=0) {
- char *p=strrchr(pBkupDir,'.');
- if (p && strcasecmp(p,".mp3")==0)
- IsOutFileGlob=1;
- else {
- #ifdef _MSC_VER
- mkdir(pBkupDir);
- #else
- mkdir(pBkupDir,S_IRWXU|S_IRWXG|S_IRWXO);
- #endif
- ret=stat(pBkupDir,&fileStat);
- }
- }
- if (ret==0) {
- if (fileStat.st_mode & S_IFDIR)
- IsOutFileGlob=0;
- else
- IsOutFileGlob=1;
- }
- pSignatureList = new unsigned int [50000][2];
- }
- for (i=1;i<argc-1 && IsOK;i++) {
- if (strcmp(argv[i],"-b") == 0) {
- IsBkupGlob = 1;
- fprintf(stderr,"Backup tags to directory %s\n",pBkupDir);
- if (IsOutFileGlob)
- IsOK=0;
- }
- else if (strcmp(argv[i],"-r") == 0) {
- IsRestGlob = 1;
- fprintf(stderr,"Restore tags from directory %s\n",pBkupDir);
- if (IsOutFileGlob)
- IsOK=0;
- }
- else if (strcmp(argv[i],"-c") == 0) {
- IsCopyGlob = 1;
- if (IsOutFileGlob)
- fprintf(stderr,"Copy tags from mp3 file to mp3 file %s\n",pBkupDir);
- else
- fprintf(stderr,"Copy tags from mp3 file to mp3 files in directory %s\n",pBkupDir);
- }
- else if (strcmp(argv[i],"-c1") == 0) {
- IsCopyV1 = 1;
- fprintf(stderr,"Copy V1 tags\n");
- }
- else if (strcmp(argv[i],"-c2") == 0) {
- IsCopyV2 = 1;
- fprintf(stderr,"Copy V2 tags\n");
- }
- else if (strcmp(argv[i],"-cm") == 0) {
- IsCopyMp3 = 1;
- fprintf(stderr,"Copy mp3 data\n");
- }
- else if (strcmp(argv[i],"-t") == 0) {
- IsTestGlob = 1;
- fprintf(stderr,"Test run - nothing will be written\n");
- }
- else if (strcmp(argv[i],"-v") == 0)
- IsVerbose = 1;
- else if (strcmp(argv[i],"-u") == 0)
- ReportUpdates = 1;
- else if (strcmp(argv[i],"-n") == 0)
- OverwriteBkup = 0;
- else if (strcmp(argv[i],"-d") == 0) {
- if (i<argc-2 && argv[i+1][0]!='-')
- pRestDir=argv[++i];
- else {
- IsOK=0;
- Instruct=1;
- }
- }
- else if (strcmp(argv[i],"-f") == 0) {
- if (IsOutFileGlob) {
- fprintf(std_err,"Output is a file name(%s), cannot use -f option\n",pBkupDir);
- IsOK=0;
- Instruct=1;
- }
- if (IsOK && i<argc-2 && argv[i+1][0]!='-') {
- char *pListFile=argv[++i];
- // Process list from a file
- FILE *fpList=0;
- IsOK=openBackupLog();
- if (IsOK) {
- // 2010/10/11 change from rb to r
- fpList = fopen(pListFile,"r");
- if (fpList==0) {
- fprintf(std_err,"Unable to open list file %s\n",pListFile);
- IsOK=0;
- }
- }
- if (IsOK) {
- char *pRet;
- for(;;) {
- pRet=fgets(fileName, sizeof fileName, fpList);
- if (pRet==0)
- break;
- pRet=strchr(fileName,'\n');
- if (pRet)
- *pRet=0;
- IsOK=ProcessFile(fileName);
- }
- }
- if (fpList)
- fclose(fpList);
- }
- else {
- IsOK=0;
- Instruct=1;
- }
- }
- else if (strcmp(argv[i],"-y") == 0) {
- bypassErrs=1;
- }
- else if (strcmp(argv[i],"-s") == 0) {
- signatureOnFront=1;
- }
- else if (strcmp(argv[i],"-x") == 0) {
- tagSubdirs=1;
- }
- else if (argv[i][0] == '-') {
- IsOK=0;
- Instruct=1;
- }
- else {
- if (IsOutFileGlob) {
- int j;
- for (j=i+1;j<argc-1;j++) {
- if (argv[j][0] != '-') {
- fprintf(std_err,"Output is a file name(%s), cannot use more that 1 input file\n",pBkupDir);
- IsOK=0;
- Instruct=1;
- }
- }
- }
- else
- openBackupLog();
- if (IsOK)
- IsOK=ProcessFile(argv[i]);
- }
- if (!IsOK && !IsOutFileGlob) {
- if (bypassErrs) {
- fprintf(std_err,"Error - Continuing with other files\n");
- IsOK=true;
- }
- else {
- int ans=0;
- while (ans != 'y'&& ans != 'Y'&&ans!='n'&&ans!='N') {
- fprintf(std_err,"Errors - do you wish to continue? (y/n)\n");
- ans = getchar();
- if (ans == 'y'|| ans == 'Y')
- IsOK=true;
- }
- }
- }
- }
- if (Instruct) {
- fprintf(stderr,"Usage: tagbkup [options] filename ... backupdir\n");
- fprintf(stderr,"\n");
- fprintf(stderr,"Backs up and restores mp3 id3v1 and id3v2 tags\n");
- fprintf(stderr,"\n");
- fprintf(stderr,"Options (-b, -r or -c is required):\n");
- fprintf(stderr,"-b Backup tags from mp3 files to directory\n");
- fprintf(stderr,"-r Restore tags from directory to mp3 files\n");
- fprintf(stderr,"-c Copy tags from mp3 files to like named mp3 files in backupdir\n");
- fprintf(stderr," or copy tags from an mp3 file to another mp3 file, where the\n");
- fprintf(stderr," output mp3 file name is supplied instead of backupdir\n");
- fprintf(stderr,"-c1 Append ID3V1 tag from mp3 file to output file\n");
- fprintf(stderr,"-c2 Copy ID3V2 tag from mp3 file to output file, overwriting existing file\n");
- fprintf(stderr,"-cm Append mp3 data without tags from mp3 file to output file\n");
- fprintf(stderr,"-d dir Copy restored mp3 files to this directory\n");
- fprintf(stderr,"-t Test - no copying of data\n");
- fprintf(stderr,"-v Verbose\n");
- fprintf(stderr,"-u Report updates done\n");
- fprintf(stderr,"-n No overwriting of backup files, append log file\n");
- fprintf(stderr,"-f fn Input filename list is in file fn\n");
- fprintf(stderr,"-y Continue if there are errors, skipping failed files\n");
- fprintf(stderr,"-s File signature based on front part of file instead of end\n");
- fprintf(stderr,"-x Tags in 256 subdirectories\n");
- }
- if (pSignatureList)
- delete [] pSignatureList;
- if (fpLog)
- fclose(fpLog);
- fprintf(stderr,"Number of files processed = %d\n",FileProcCount);
- return !IsOK;
- }
- int openBackupLog() {
- int IsOK=1;
- char logFile[256];
- if (IsBkupGlob) {
- if (fpLog==0) {
- strcpy(logFile,pBkupDir);
- strcat(logFile,"/");
- strcat(logFile,"tagbkup.log");
- fprintf(stderr,"Log file %s\n",logFile);
- char *mode = "ab";
- if (OverwriteBkup)
- mode="wb";
- fpLog=fopen(logFile,mode);
- if (fpLog==0) {
- fprintf(stderr,"Unable to open log file %s\n",logFile);
- IsOK=0;
- }
- }
- }
- return IsOK;
- }
- // Make the directory for a file
- void mkdir_f(char *fileName) {
- char dirName[512];
- char *pIn=fileName;
- char *pOut=dirName;
- memset(dirName,0,sizeof dirName);
- for(;*pIn;pIn++,pOut++) {
- if (pOut !=dirName) {
- if (*pIn == '/' || *pIn == '\\') {
- #ifdef _MSC_VER
- mkdir(dirName);
- #else
- mkdir(dirName,S_IRWXU|S_IRWXG|S_IRWXO);
- #endif
- }
- }
- *pOut=*pIn;
- }
- }
- int ProcessFile(char *pMP3FileName) {
- char szBkupName[512];
- char szRestName[512];
- char szFinalRestName[512];
- char *pFinalRestName;
- char Signature[20];
- unsigned int sig[2];
- static time_t notifyTime = 0;
- // 5/30/2010 - progress reporting
- if (notifyTime == 0)
- notifyTime = time(0);
- else {
- time_t now = time(0);
- if (difftime(now, notifyTime) >= 60.0) {
- notifyTime = now;
- fprintf(stderr,"Number of files processed so far = %d\n",FileProcCount);
- }
- }
- int IsOK=1;
- int ret;
- int copyOpts = 0;
- if (IsCopyV1 || IsCopyV2 || IsCopyMp3)
- copyOpts = 1;
- if (IsBkupGlob + IsRestGlob + IsCopyGlob + copyOpts != 1){
- IsOK=0;
- Instruct=1;
- }
- if (IsBkupGlob)
- pRestDir=0;
- char *p=strrchr(pMP3FileName,'.');
- size_t data_start=0;
- if (p && strcasecmp(p,".mp3")==0
- && strncasecmp(pMP3FileName,"tag_",4)!=0
- && IsOK) {
- int seq;
- if (IsBkupGlob || IsRestGlob) {
- IsOK=GetFileSignature(pMP3FileName,sig,&data_start);
- if (IsOK) {
- sprintf(Signature,"%8.8x%8.8x",sig[0],sig[1]);
- FileProcCount++;
- }
- }
- else
- IsOK=getDataStart(pMP3FileName,&data_start);
- for (seq=0;IsOK;) {
- int i;
- if (IsBkupGlob || IsRestGlob) {
- for (i=0;i<countSignature;i++){
- if (sig[0]==pSignatureList[i][0]
- && sig[1]==pSignatureList[i][1]) {
- seq++;
- }
- }
- if (tagSubdirs)
- sprintf(szBkupName,"%s/%2.2s/tag_%s_%3.3d.mp3",pBkupDir,Signature,Signature,seq);
- else
- sprintf(szBkupName,"%s/tag_%s_%3.3d.mp3",pBkupDir,Signature,seq);
- pSignatureList[countSignature][0]=sig[0];
- pSignatureList[countSignature++][1]=sig[1];
- }
- if (IsBkupGlob){
- ret=CopyTag(szBkupName,pMP3FileName);
- switch (ret) {
- case -1:
- // Duplicate file found with different data
- IsOK=AppendMP3Data(szBkupName,0,0);
- if (IsOK)
- IsOK=AppendTagV1(szBkupName,pMP3FileName);
- if (!IsOK) {
- fprintf(stderr,"%s --> %s - Error\n",pMP3FileName,szBkupName);
- break;
- }
- if (IsVerbose || ReportUpdates)
- fprintf(stderr,"%s --> %s - data updated\n",
- pMP3FileName,szBkupName);
- break;
- case 0:
- // Copied OK
- IsOK=AppendMP3Data(szBkupName,0,0);
- if (IsOK)
- IsOK=AppendTagV1(szBkupName,pMP3FileName);
- if (IsOK) {
- if (IsVerbose || ReportUpdates)
- fprintf(stderr,"%s --> %s - copied OK\n",
- pMP3FileName,szBkupName);
- }
- else
- fprintf(stderr,"%s --> %s - Error\n",pMP3FileName,szBkupName);
- break;
- case 1:
- // Duplicate file found with same data
- // OK
- if (IsVerbose)
- fprintf(stderr,"%s --> %s - up to date\n",pMP3FileName,szBkupName);
- break;
- case 2:
- // error copying tag
- fprintf(stderr,"%s --> %s - Error\n",pMP3FileName,szBkupName);
- IsOK=0;
- break;
- case 3:
- // Duplicate file, different data not copied
- fprintf(stderr,"%s --> %s - already exists for a different source - retry\n",
- pMP3FileName,szBkupName);
- continue;
- }
- if (fpLog)
- fprintf(fpLog,"%s_%3.3d %s\n",Signature,seq,pMP3FileName);
- break;
- }
- if (IsRestGlob) {
- if (pRestDir) {
- strcpy(szRestName,pRestDir);
- char Last = *(strchr(szRestName,0)-1);
- if (Last != '/' && Last != '\\')
- strcat(szRestName,"/");
- if (*pMP3FileName == '/' || *pMP3FileName == '\\')
- strcat(szRestName,pMP3FileName+1);
- else if (pMP3FileName[1] == ':') {
- if (pMP3FileName[2] == '\\')
- strcat(szRestName,pMP3FileName+3);
- else
- strcat(szRestName,pMP3FileName+2);
- }
- else
- strcat(szRestName,pMP3FileName);
- mkdir_f(szRestName);
- pFinalRestName=szRestName;
- }
- else {
- ret = CompareTag(pMP3FileName,szBkupName);
- if (ret==1) {
- if (IsVerbose) {
- fprintf(stderr,"%s --> %s",szBkupName,pMP3FileName);
- fprintf(stderr," - file already exists with correct data\n");
- }
- break;
- }
- if (ret==2) {
- IsOK=0;
- break;
- }
- strcpy(szRestName,pMP3FileName);
- strcat(szRestName,"rest");
- pFinalRestName=pMP3FileName;
- }
- remove(szRestName);
- ret=CopyTag(szRestName,szBkupName);
- // if (ret==-1)
- if (ret!=0){
- fprintf(stderr,"%s --> %s\n",szBkupName,pFinalRestName);
- // error copying tag
- fprintf(std_err,"Error Copying tag to %s\n",szRestName);
- IsOK=0;
- break;
- }
- IsOK=AppendMP3Data(szRestName,pMP3FileName,data_start);
- if (!IsOK)
- break;
- IsOK=AppendTagV1(szRestName,szBkupName);
- // IsOK=UpdateTagV1(szRestName);
- if (!IsOK)
- break;
- if (!IsTestGlob && !pRestDir)
- IsOK=(remove(pMP3FileName)==0);
- if (!IsOK) {
- fprintf(stderr,"%s --> %s\n",szBkupName,pFinalRestName);
- fprintf(std_err,"Error - Unable to delete file %s\n",pMP3FileName);
- break;
- }
- if (!IsTestGlob && !pRestDir)
- IsOK=(rename(szRestName,pMP3FileName)==0);
- if (!IsOK) {
- fprintf(stderr,"%s --> %s\n",szBkupName,pFinalRestName);
- fprintf(std_err,"Error - Unable to rename file %s to %s\n",szRestName,pMP3FileName);
- break;
- }
- if (IsVerbose || ReportUpdates) {
- fprintf(stderr,"%s --> %s",szBkupName,pFinalRestName);
- fprintf(stderr," - tag restored\n");
- }
- }
- if (IsCopyGlob) {
- if (IsOutFileGlob) {
- if (FileProcCount > 1) {
- IsOK=0;
- fprintf(std_err,"Error - When copying to a file only one input file can be used.");
- break;
- }
- strcpy(szRestName,pBkupDir);
- }
- else {
- strcpy(szRestName,pBkupDir);
- char *pFileName = strrchr(pMP3FileName,'/');
- if (pFileName==0)
- pFileName = strrchr(pMP3FileName,'\\');
- if (pFileName==0)
- pFileName = strrchr(pMP3FileName,':');
- if (pFileName==0)
- pFileName=pMP3FileName;
- else
- pFileName++;
- strcat(szRestName,"/");
- strcat(szRestName,pFileName);
- }
- FileProcCount++;
- strcpy(szFinalRestName,szRestName);
- strcat(szRestName,"copy");
- remove(szRestName);
- ret=CompareTag(szFinalRestName, pMP3FileName);
- if (ret==1) {
- if (IsVerbose) {
- fprintf(stderr,"%s --> %s",pMP3FileName,szFinalRestName);
- fprintf(stderr," - file already exists with correct data\n");
- }
- break;
- }
- if (ret==2) {
- IsOK=0;
- break;
- }
- int outputFileExists = 1;
- if (ret==0)
- outputFileExists = 0;
- ret=CopyTag(szRestName,pMP3FileName);
- // if (ret==-1)
- if (ret!=0){
- fprintf(stderr,"%s --> %s\n",pMP3FileName,szFinalRestName);
- // error copying tag
- fprintf(std_err,"Error Copying tag to %s\n",szRestName);
- IsOK=0;
- break;
- }
- if (outputFileExists)
- IsOK=AppendMP3Data(szRestName,szFinalRestName,data_start);
- else
- IsOK=AppendMP3Data(szRestName,0,0);
- if (!IsOK)
- break;
- IsOK=AppendTagV1(szRestName,pMP3FileName);
- // IsOK=UpdateTagV1(szRestName);
- if (!IsOK)
- break;
- if (!IsTestGlob && outputFileExists)
- IsOK=(remove(szFinalRestName)==0);
- if (!IsOK) {
- fprintf(stderr,"%s --> %s\n",pMP3FileName,szFinalRestName);
- fprintf(std_err,"Error - Unable to delete file %s\n",szFinalRestName);
- break;
- }
- if (!IsTestGlob)
- IsOK=(rename(szRestName,szFinalRestName)==0);
- if (!IsOK) {
- fprintf(stderr,"%s --> %s\n",pMP3FileName,szFinalRestName);
- fprintf(std_err,"Error - Unable to rename file %s to %s\n",szRestName,szFinalRestName);
- break;
- }
- if (IsVerbose || ReportUpdates) {
- fprintf(stderr,"%s --> %s",pMP3FileName,szFinalRestName);
- fprintf(stderr," - tag copied\n");
- }
- }
- if (IsCopyV2){
- if (IsOutFileGlob) {
- strcpy(szRestName,pBkupDir);
- }
- else {
- fprintf(stderr,"%s --> %s\n",pMP3FileName,szRestName);
- // error copying tag
- fprintf(std_err,"Copy tag V2 requires output file name not directory\n");
- IsOK=0;
- break;
- }
- FileProcCount++;
- remove(szRestName);
- ret=CopyTag(szRestName,pMP3FileName);
- if (ret!=0){
- fprintf(stderr,"%s --> %s\n",pMP3FileName,szRestName);
- // error copying tag
- fprintf(std_err,"Error %d Copying tag to %s\n",ret,szRestName);
- IsOK=0;
- break;
- }
- }
- if (IsCopyMp3){
- if (IsOutFileGlob) {
- strcpy(szRestName,pBkupDir);
- }
- else {
- fprintf(stderr,"%s --> %s\n",pMP3FileName,szRestName);
- // error copying tag
- fprintf(std_err,"Copy Mp3 data requires output file name not directory\n");
- IsOK=0;
- break;
- }
- FileProcCount++;
- IsOK=AppendMP3Data(szRestName,pMP3FileName,data_start);
- }
- if (IsCopyV1){
- if (IsOutFileGlob) {
- strcpy(szRestName,pBkupDir);
- }
- else {
- fprintf(stderr,"%s --> %s\n",pMP3FileName,szRestName);
- // error copying tag
- fprintf(std_err,"Copy Tag V1 requires output file name not directory\n");
- IsOK=0;
- break;
- }
- FileProcCount++;
- IsOK=AppendTagV1(szRestName,pMP3FileName);
- }
- // No need to try another seq value if we got here
- break;
- }
- }
- return IsOK;
- }
- // Create a signature for the music.
- int GetFileSignature(char *pFoundName, unsigned int *pSig, size_t *pData_start) {
- FILE *fpIn;
- int IsOK=1;
- fpIn=fopen(pFoundName,"rb");
- if (fpIn==0) {
- fprintf(std_err,"Error - Unable to open file %s\n",pFoundName);
- IsOK=0;
- }
- // The ID3v2 tag header, which should be the first information in the
- // file, is 10 bytes as follows:
- //
- // ID3v2/file identifier "ID3"
- // ID3v2 version $03 00
- // ID3v2 flags %abc00000
- // ID3v2 size 4 * %0xxxxxxx
- // The ID3v2 tag size is encoded with four bytes where the most
- // significant bit (bit 7) is set to zero in every byte, making a total
- // of 28 bits. The zeroed bits are ignored, so a 257 bytes long tag is
- // represented as $00 00 02 01.
- // The ID3v2 tag size is the size of the complete tag after
- // unsychronisation, including padding, excluding the header but not
- // excluding the extended header (total tag size - 10). Only 28 bits
- // (representing up to 256MB) are used in the size description to avoid
- // the introducuction of 'false syncsignals'.
- // An ID3v2 tag can be detected with the following pattern:
- // I D 3
- // $49 44 33 yy yy xx zz zz zz zz
- // 0 1 2 3 4 5 6 7 8 9
- // Where yy is less than $FF, xx is the 'flags' byte and zz is less than
- // $80.
- mp3info mp3i;
- *pData_start=0;
- struct stat fileStat;
- if (IsOK) {
- int ret=fstat (fileno(fpIn),&fileStat);
- if (ret!=0) {
- fprintf(std_err,"Error calling fstat on file %s\n",pFoundName);
- IsOK=0;
- }
- }
- size_t tagSize = 0;
- if (IsOK) {
- IsOK=GetTagSize(fpIn,&tagSize);
- memset(&mp3i,0,sizeof(mp3info));
- mp3i.filename=pFoundName;
- mp3i.file=fpIn;
- mp3i.datasize=fileStat.st_size;
- if(get_first_header(&mp3i,tagSize)) {
- // if(get_first_header(&mp3i,0))
- *pData_start=ftell(fpIn);
- }
- else {
- fprintf(std_err,"Unable to access mp3 frame in file %s\n",pFoundName);
- IsOK=0;
- }
- // fprintf(stderr,"tagsize = %d\n",tagSize);
- // fprintf(stderr,"pData_start = %d\n",*pData_start);
- }
- unsigned int sig[2]={0,0};
- unsigned int buf[2]={0,0};
- off_t numread = 2048; // approx 1 second
- off_t start;
- int count;
- int i;
- off_t dataEnd;
- int v1tags;
- if (IsOK) {
- if (signatureOnFront) {
- start = (*pData_start)+16*1024*15; // approx 15 seconds
- if (fileStat.st_size < start + ((off_t)sizeof buf) * numread + 512)
- start = *pData_start;
- }
- else {
- // off_t dataEnd = fileStat.st_size;
- // int v1tags=0;
- // for (;;) {
- // IsOK=(fseek(fpIn,dataEnd-128,SEEK_SET)==0);
- // if (IsOK) {
- // count=fread(v1tag,1,sizeof v1tag,fpIn);
- // if (count!=3)
- // IsOK=0;
- // }
- // if (IsOK) {
- // if (IsID3Tag(v1tag)) {
- // dataEnd-=128;
- // v1tags++;
- // }
- // else
- // break;
- // }
- // }
- IsOK=countV1Tags(fpIn, v1tags, dataEnd);
- if (IsOK) {
- if (v1tags==0)
- fprintf(std_err,"Warning - No ID3v1 tag on file %s\n",pFoundName);
- else if (v1tags!=1)
- fprintf(std_err,"Warning - %d ID3v1 tags on file %s\n",v1tags,pFoundName);
- start = dataEnd - (((off_t)sizeof buf) * numread) - 16*1024*30; // approx 30 seconds
- if (start < (off_t)*pData_start) {
- start = dataEnd - (((off_t)sizeof buf) * numread) - 16*1024*10; // approx 10 seconds
- }
- if (start < (off_t)*pData_start) {
- start = dataEnd - (((off_t)sizeof buf) * numread) - 16*1024*5; // approx 5 seconds
- }
- if (start < (off_t)*pData_start) {
- fprintf(std_err,"Error - file is too small %s\n",pFoundName);
- IsOK=0;
- }
- }
- }
- }
- if (IsOK)
- IsOK=(fseek(fpIn,start,SEEK_SET)==0);
- for (i=0;i<numread&&IsOK;i++) {
- count=fread(buf,1,sizeof buf,fpIn);
- if (count != sizeof sig)
- break;
- sig[0]^=buf[0];
- sig[1]^=buf[1];
- }
- if (fpIn)
- fclose(fpIn);
- pSig[0]=sig[0];
- pSig[1]=sig[1];
- return IsOK;
- }
- int countV1Tags(FILE *fpIn, int &v1tags, off_t &dataEnd) {
- int IsOK=1;
- char v1tag[3];
- v1tags=0;
- dataEnd=0;
- int count;
- IsOK=(fseek(fpIn,0,SEEK_END)==0);
- if (IsOK)
- dataEnd = ftell(fpIn);
- for (;IsOK;) {
- IsOK=(fseek(fpIn,dataEnd-128,SEEK_SET)==0);
- if (IsOK) {
- count=fread(v1tag,1,sizeof v1tag,fpIn);
- if (count!=3)
- IsOK=0;
- }
- if (IsOK) {
- if (IsID3Tag(v1tag)) {
- dataEnd-=128;
- v1tags++;
- }
- else
- break;
- }
- }
- if (!IsOK)
- fprintf(std_err,"Error calculating number of v1 tags\n");
- return IsOK;
- }
- int getDataStart(char *pFoundName, size_t *pDataStart) {
- FILE *fpIn;
- int IsOK=1;
- fpIn=fopen(pFoundName,"rb");
- if (fpIn==0) {
- fprintf(std_err,"Error - Unable to open file %s\n",pFoundName);
- IsOK=0;
- }
- struct stat fileStat;
- if (IsOK) {
- int ret=fstat (fileno(fpIn),&fileStat);
- if (ret!=0) {
- fprintf(std_err,"Error calling fstat on file %s\n",pFoundName);
- IsOK=0;
- }
- }
- mp3info mp3i;
- size_t tagSize = 0;
- *pDataStart = 0;
- if (IsOK) {
- IsOK=GetTagSize(fpIn,&tagSize);
- memset(&mp3i,0,sizeof(mp3info));
- mp3i.filename=pFoundName;
- mp3i.file=fpIn;
- mp3i.datasize=fileStat.st_size;
- if(get_first_header(&mp3i,tagSize)) {
- *pDataStart=ftell(fpIn);
- }
- else {
- fprintf(std_err,"Unable to access mp3 frame in file %s\n",pFoundName);
- IsOK=0;
- }
- }
- if (fpIn)
- fclose(fpIn);
- return IsOK;
- }
- // return code
- // -1 Duplicate file found with different data, copied
- // 0 Data copied
- // 1 File found with same data
- // 2 Error
- // 3 Duplicate File found with different data not copied
- int CopyTag(char *pOutputFile, char *pInputFile) {
- FILE *fpIn=0;
- FILE *fpOut=0;
- int IsOK=1;
- size_t tagsize;
- char *pInputBuff=0;
- size_t count;
- size_t count2;
- int result=0;
- pInputBuff=new char[BufSize];
- size_t readlen;
- // check if the output file exists and
- // has the same contents
- if (IsOK) {
- result=CompareTag(pOutputFile, pInputFile);
- if (result==2)
- IsOK=0;
- }
- if (result == -1 && !OverwriteBkup)
- result=3;
- if (result<=0 && IsOK) {
- fpIn=fopen(pInputFile,"rb");
- if (fpIn==0) {
- fprintf(std_err,"Error opening input file %s\n",pInputFile);
- IsOK=0;
- }
- }
- if (result<=0 && IsOK)
- IsOK=GetTagSize(fpIn,&tagsize);
- if (tagsize == 0)
- fprintf(std_err,"Warning - no tag on file %s\n",pInputFile);
- if (result<=0 && IsOK) {
- fseek(fpIn,0,SEEK_SET);
- if (!IsTestGlob) {
- fpOut=fopen(pOutputFile,"wb");
- if (fpOut==0 && tagSubdirs) {
- // Check if directory does not exist - create it
- mkdir_f(pOutputFile);
- fpOut=fopen(pOutputFile,"wb");
- }
- if (fpOut==0) {
- fprintf(std_err,"Error opening output file %s\n",pOutputFile);
- IsOK=0;
- }
- }
- }
- if (result<=0 && IsOK) {
- size_t remains=tagsize;
- while(remains>0) {
- readlen=remains;
- if (readlen>BufSize)
- readlen=BufSize;
- count = fread(pInputBuff,1,readlen,fpIn);
- if (count != readlen) {
- IsOK=0;
- fprintf(std_err,"Error reading file %s\n",pInputFile);
- break;
- }
- if (!IsTestGlob) {
- count2 = fwrite(pInputBuff,1,count,fpOut);
- if (count2 != count) {
- IsOK=0;
- fprintf(std_err,"Error writing file %s\n",pOutputFile);
- break;
- }
- }
- remains-=readlen;
- }
- }
- if (pInputBuff) {
- delete [] pInputBuff;
- pInputBuff=0;
- }
- if (fpIn)
- fclose(fpIn);
- if (fpOut)
- fclose(fpOut);
- if (!IsOK)
- result=2;
- return result;
- }
- // return code
- // -1 different data
- // 0 No output file
- // 1 same data
- // 2 Error
- int CompareTag(char *pOutputFile, char *pInputFile) {
- FILE *fpIn=0;
- FILE *fpOut=0;
- int IsOK = 1;
- size_t tagsize;
- char *pInputBuff=0;
- char *pOutputBuff=0;
- size_t count;
- int result=0;
- fpIn=fopen(pInputFile,"rb");
- if (fpIn==0) {
- fprintf(std_err,"Error opening input file %s\n",pInputFile);
- IsOK=0;
- }
- if (IsOK)
- IsOK=GetTagSize(fpIn,&tagsize);
- pInputBuff=new char[BufSize];
- size_t readlen;
- // check if the output file exists and
- // has the same contents
- if (IsOK) {
- fseek(fpIn,0,SEEK_SET);
- fpOut=fopen(pOutputFile,"rb");
- if (fpOut!=0) {
- size_t tagoutsize;
- IsOK=GetTagSize(fpOut,&tagoutsize);
- fseek(fpOut,0,SEEK_SET);
- result=1; // assume data will be the same
- if (IsOK) {
- if (tagsize!=tagoutsize)
- // file exists with incorrect data
- result=-1;
- pOutputBuff=new char[BufSize];
- size_t remains=tagsize;
- while(remains>0 && result==1) {
- readlen=remains;
- if (readlen>BufSize)
- readlen=BufSize;
- count = fread(pInputBuff,1,readlen,fpIn);
- if (count != readlen) {
- IsOK=0;
- fprintf(std_err,"Error reading file %s\n",pInputFile);
- break;
- }
- count = fread(pOutputBuff,1,readlen,fpOut);
- if (count == readlen) {
- if (memcmp(pInputBuff,pOutputBuff,readlen)!=0) {
- // file exists with incorrect data
- result=-1;
- break;
- }
- }
- else {
- // file is short - means wrong data
- result=-1;
- break;
- }
- remains-=readlen;
- }
- }
- }
- }
- if (pInputBuff) {
- delete [] pInputBuff;
- pInputBuff=0;
- }
- if (pOutputBuff) {
- delete [] pOutputBuff;
- pOutputBuff=0;
- }
- if (fpIn)
- fclose(fpIn);
- if (fpOut)
- fclose(fpOut);
- if (!IsOK)
- result=2;
- return result;
- }
- int AppendMP3Data(char *pOutputFile, char *pInputFile, size_t data_start) {
- FILE *fpIn=0;
- FILE *fpOut=0;
- int IsOK=1;
- // size_t tagsize;
- char *pInputBuff=0;
- size_t count;
- off_t dataEnd;
- int v1tags;
- if (pInputFile) {
- fpIn=fopen(pInputFile,"rb");
- if (fpIn==0) {
- fprintf(std_err,"Error opening input file %s\n",pInputFile);
- IsOK=0;
- }
- // if (IsOK)
- // IsOK=GetTagSize(fpIn,&tagsize);
- pInputBuff=new char[BufSize];
- if (IsOK) {
- IsOK=countV1Tags(fpIn, v1tags, dataEnd);
- IsOK=(fseek(fpIn,data_start,SEEK_SET)==0);
- if (!IsOK)
- fprintf(std_err,"Error seeking on file %s\n",pInputFile);
- }
- }
- size_t readlen;
- if (IsOK && !IsTestGlob) {
- fpOut=fopen(pOutputFile,"ab");
- if (fpOut==0) {
- fprintf(std_err,"Error opening output file %s\n",pOutputFile);
- IsOK=0;
- }
- }
- if (IsOK) {
- if (pInputFile) {
- off_t pos = data_start;
- while(!feof(fpIn) && pos < dataEnd) {
- size_t maxReadLen = dataEnd - pos;
- if (maxReadLen > BufSize)
- maxReadLen = BufSize;
- readlen = fread(pInputBuff,1,maxReadLen,fpIn);
- if (ferror(fpIn)) {
- IsOK=0;
- fprintf(std_err,"Error reading file %s\n",pInputFile);
- break;
- }
- pos += readlen;
- if (!IsTestGlob) {
- count = fwrite(pInputBuff,1,readlen,fpOut);
- if (count != readlen) {
- IsOK=0;
- fprintf(std_err,"Error writing file %s\n",pOutputFile);
- break;
- }
- }
- }
- }
- else {
- if (!IsTestGlob) {
- count = fwrite(nullMp3,1,nullMp3size,fpOut);
- if (count != nullMp3size) {
- IsOK=0;
- fprintf(std_err,"Error writing file %s\n",pOutputFile);
- }
- }
- }
- }
- if (pInputBuff) {
- delete [] pInputBuff;
- pInputBuff=0;
- }
- if (fpIn)
- fclose(fpIn);
- if (fpOut)
- fclose(fpOut);
- return IsOK;
- }
- int GetTagSize(FILE *fpIn, size_t *pTagSize) {
- *pTagSize=0;
- unsigned char work[20];
- int IsOK=1;
- size_t count;
- if (IsOK){
- count=fread(work,1,10,fpIn);
- if (count != 10) {
- fprintf(std_err,"Error reading file\n");
- IsOK=0;
- }
- }
- if (memcmp(work,"ID3",3)==0
- && work[3] != 255
- && work[4] != 255
- && work[6] < 128
- && work[7] < 128
- && work[8] < 128
- && work[9] < 128) {
- // We have a tag
- *pTagSize = (size_t) work[9]
- + (size_t) work[8] * 128
- + (size_t) work[7] * 128 * 128
- + (size_t) work[6] * 128 * 128 * 128 + 10;
- }
- return IsOK;
- }
- // If 2 or more V1 tags replace them all
- int AppendTagV1(char *pOutFile,char *pInFile) {
- FILE *fpIn=0;
- FILE *fpOut=0;
- int ret;
- int IsOK=1;
- char newtag[128];
- int count;
- off_t dataEnd;
- int v1tags;
- if (!IsTestGlob) {
- if (IsOK) {
- fpOut=fopen(pOutFile,"r+b");
- if (fpOut==0) {
- fprintf(std_err,"Error opening r+b file %s\n",pOutFile);
- IsOK=0;
- }
- }
- if (IsOK) {
- IsOK=countV1Tags(fpOut, v1tags, dataEnd);
- if (!IsOK) {
- fprintf(std_err,"Error counting v1 tags on %s\n",pOutFile);
- }
- }
- if (IsOK) {
- ret=fseek(fpOut,dataEnd,SEEK_SET);
- if (ret!=0) {
- fprintf(std_err,"Error seeking dataEnd on %s\n",pOutFile);
- IsOK=0;
- }
- }
- }
- if (IsOK) {
- fpIn=fopen(pInFile,"rb");
- if (fpIn==0) {
- fprintf(std_err,"Error opening r+b file %s\n",pInFile);
- IsOK=0;
- }
- }
- if (IsOK) {
- IsOK=countV1Tags(fpIn, v1tags, dataEnd);
- if (!IsOK) {
- fprintf(std_err,"Error counting v1 tag on %s\n",pInFile);
- }
- }
- if (IsOK) {
- if (v1tags > 1)
- fprintf(std_err,"Warning - %d id3v1 tags on %s\n",v1tags,pInFile);
- if (v1tags < 1)
- fprintf(std_err,"Warning - no id3v1 tags on %s\n",pInFile);
- ret=fseek(fpIn,-128,SEEK_END);
- if (ret!=0) {
- fprintf(std_err,"Error seeking end-128 on %s\n",pInFile);
- IsOK=0;
- }
- }
- if (IsOK && v1tags >= 1) {
- count=fread(newtag,1,128,fpIn);
- if (count != 128) {
- fprintf(std_err,"Error reading file %s\n",pInFile);
- IsOK=0;
- }
- if (IsOK && !IsTestGlob) {
- if (IsID3Tag(newtag)) {
- // fprintf(stderr,"debug id3v1 = %s\n",newtag);
- count = fwrite(newtag,1,128,fpOut);
- if (count != 128) {
- IsOK=0;
- fprintf(std_err,"Error writing file %s\n",pOutFile);
- }
- }
- }
- }
- if (IsOK && !IsTestGlob) {
- ret=ftruncate(fileno(fpOut),ftell(fpOut));
- if (ret != 0) {
- fprintf(std_err,"Error truncating %s\n",pOutFile);
- IsOK=0;
- }
- }
- if (fpIn)
- fclose(fpIn);
- if (fpOut)
- fclose(fpOut);
- return IsOK;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement