Advertisement
Gfy

tagbkup.cpp

Gfy
Dec 28th, 2011
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 41.76 KB | None | 0 0
  1. /*
  2.     tagbkup - mp3 tag backup and restore
  3.  
  4.     Copyright (c) 2004 Peter G. Bennett
  5.  
  6.     This file is part of Jampal.
  7.  
  8.     Jampal is free software: you can redistribute it and/or modify
  9.     it under the terms of the GNU General Public License as published by
  10.     the Free Software Foundation, either version 3 of the License, or
  11.     (at your option) any later version.
  12.  
  13.     Jampal is distributed in the hope that it will be useful,
  14.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.     GNU General Public License for more details.
  17.  
  18.     You should have received a copy of the GNU General Public License
  19.     along with Jampal.  If not, see <http://www.gnu.org/licenses/>.
  20. */
  21.  
  22.  
  23. #include <string.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <ctype.h>
  27. #ifndef OS_Linux
  28.     #include <io.h>
  29. #endif
  30. #ifdef OS_Linux
  31.    #include <unistd.h>
  32.    #include <sys/types.h>
  33. #endif
  34.  
  35. #include <fcntl.h>
  36. #include <sys/stat.h>
  37. #ifdef __CYGWIN32__
  38.     #include <sys/cygwin.h>
  39. #endif
  40. #ifdef _MSC_VER
  41.     #include <direct.h>
  42.     #define strcasecmp stricmp
  43.     #define strncasecmp strnicmp
  44.     #define ftruncate chsize
  45. #endif
  46.  
  47. #include <time.h>
  48.  
  49. //#include <windows.h>
  50. //#include "MP3Info.h"
  51. #include "mp3info_u.h"
  52.  
  53. const size_t BufSize = 16384;
  54. const int MaxFName = 260;
  55.  
  56. int FileProcCount = 0;
  57. int IsBkupGlob = 0;
  58. int IsRestGlob = 0;
  59. int IsCopyGlob = 0;
  60. int IsTestGlob = 0;
  61. int IsOutFileGlob=0;
  62. int IsVerbose = 0;
  63. int IsCopyV1 = 0;
  64. int IsCopyV2 = 0;
  65. int IsCopyMp3 = 0;
  66. int ReportUpdates = 0;
  67. int OverwriteBkup = 1;
  68. char *pRestDir = 0;
  69. char *pFileSpec = 0;
  70. char *pBkupDir = 0;
  71. FILE *fpLog;
  72. FILE *std_err = stderr;
  73. unsigned int (*pSignatureList)[2] = 0;
  74. int countSignature=0;
  75. int Instruct=0;
  76. int bypassErrs = 0;
  77. int signatureOnFront = 0;
  78. int tagSubdirs = 0;
  79.  
  80. int GetFileSignature(char *pFoundName, unsigned int *pSig, size_t *pData_start);
  81. int getDataStart(char *pFoundName, size_t *pDataStart);
  82. int CopyTag(char *pOutputFile, char *pInputFile);
  83. int CompareTag(char *pOutputFile, char *pInputFile);
  84. int AppendMP3Data(char *pOutputFile, char *pInputFile, size_t data_start);
  85. int GetTagSize(FILE *fpIn, size_t *pTagSize);
  86. // int UpdateTagV1(char *pFile);
  87. int openBackupLog();
  88. int ProcessFile(char *pMP3FileName);
  89. void mkdir_f(char *fileName);
  90. int AppendTagV1(char *pOutFile,char *pInFile);
  91. int countV1Tags(FILE *fpIn, int &v1tags, off_t &dataEnd);
  92.  
  93. // a useful macro
  94. #define IsID3Tag(s) (s[0] == 'T' && s[1] == 'A' && s[2] == 'G')
  95.  
  96. extern int nullMp3[];
  97. extern size_t nullMp3size;
  98.  
  99. int main(int argc, char *argv[], char * /*envp*/ []) {
  100.     int IsOK=1;
  101.     int i;      
  102.     char fileName[512];
  103.                    
  104.     fprintf(stderr,"tagbkup Version **UNSTABLE** (c) 2004-2010 Peter G. Bennett\n");
  105. #ifdef __CYGWIN32__
  106.     fprintf(stderr,"Cygwin version, ");
  107. #endif
  108. #ifdef _MSC_VER
  109.     fprintf(stderr,"Win32 version, ");
  110. #endif
  111. #ifdef OS_Linux
  112.     fprintf(stderr,"Linux version, ");
  113. #endif
  114. #ifdef CPU_x86_64
  115.     fprintf(stderr,"64 bit.\n");
  116. #else
  117.     fprintf(stderr,"32 bit.\n");
  118. #endif
  119.     // Last parameter is backup dir
  120.     pBkupDir = argv[argc-1];
  121.     if (argc < 3 || *pBkupDir == '-'){
  122.         Instruct = 1;
  123.         IsOK=0;
  124.     }
  125.  
  126.     struct stat fileStat;
  127.     int ret;
  128.     if (IsOK) {
  129.         fileStat.st_mode=0;
  130.         ret=stat(pBkupDir,&fileStat);
  131.         if (ret!=0) {
  132.             char *p=strrchr(pBkupDir,'.');
  133.             if (p && strcasecmp(p,".mp3")==0)
  134.                 IsOutFileGlob=1;
  135.             else {
  136.  
  137.                 #ifdef _MSC_VER
  138.                     mkdir(pBkupDir);
  139.                 #else
  140.                     mkdir(pBkupDir,S_IRWXU|S_IRWXG|S_IRWXO);
  141.                 #endif
  142.                     ret=stat(pBkupDir,&fileStat);
  143.             }
  144.         }
  145.         if (ret==0) {
  146.             if (fileStat.st_mode & S_IFDIR)
  147.                 IsOutFileGlob=0;
  148.             else
  149.                 IsOutFileGlob=1;
  150.         }
  151.         pSignatureList = new unsigned int [50000][2];
  152.     }
  153.  
  154.    
  155.     for (i=1;i<argc-1 && IsOK;i++) {
  156.         if (strcmp(argv[i],"-b") == 0) {
  157.             IsBkupGlob = 1;
  158.             fprintf(stderr,"Backup tags to directory %s\n",pBkupDir);
  159.             if (IsOutFileGlob)
  160.                 IsOK=0;
  161.         }
  162.         else if (strcmp(argv[i],"-r") == 0) {
  163.             IsRestGlob = 1;
  164.             fprintf(stderr,"Restore tags from directory %s\n",pBkupDir);
  165.             if (IsOutFileGlob)
  166.                 IsOK=0;
  167.         }
  168.         else if (strcmp(argv[i],"-c") == 0) {
  169.             IsCopyGlob = 1;
  170.             if (IsOutFileGlob)
  171.                 fprintf(stderr,"Copy tags from mp3 file to mp3 file %s\n",pBkupDir);
  172.             else
  173.                 fprintf(stderr,"Copy tags from mp3 file to mp3 files in directory %s\n",pBkupDir);
  174.         }
  175.         else if (strcmp(argv[i],"-c1") == 0) {
  176.             IsCopyV1 = 1;
  177.             fprintf(stderr,"Copy V1 tags\n");
  178.         }
  179.         else if (strcmp(argv[i],"-c2") == 0) {
  180.             IsCopyV2 = 1;
  181.             fprintf(stderr,"Copy V2 tags\n");
  182.         }
  183.         else if (strcmp(argv[i],"-cm") == 0) {
  184.             IsCopyMp3 = 1;
  185.             fprintf(stderr,"Copy mp3 data\n");
  186.         }
  187.         else if (strcmp(argv[i],"-t") == 0) {
  188.             IsTestGlob = 1;
  189.             fprintf(stderr,"Test run - nothing will be written\n");
  190.         }
  191.         else if (strcmp(argv[i],"-v") == 0)
  192.             IsVerbose = 1;
  193.         else if (strcmp(argv[i],"-u") == 0)
  194.             ReportUpdates = 1;
  195.         else if (strcmp(argv[i],"-n") == 0)
  196.             OverwriteBkup = 0;
  197.         else if (strcmp(argv[i],"-d") == 0) {
  198.             if (i<argc-2 && argv[i+1][0]!='-')
  199.                 pRestDir=argv[++i];
  200.             else {
  201.                 IsOK=0;
  202.                 Instruct=1;
  203.             }
  204.         }
  205.         else if (strcmp(argv[i],"-f") == 0) {
  206.             if (IsOutFileGlob) {
  207.                 fprintf(std_err,"Output is a file name(%s), cannot use -f option\n",pBkupDir);
  208.                 IsOK=0;
  209.                 Instruct=1;
  210.             }
  211.             if (IsOK && i<argc-2 && argv[i+1][0]!='-') {
  212.                 char *pListFile=argv[++i];
  213.                 // Process list from a file
  214.                 FILE *fpList=0;
  215.                 IsOK=openBackupLog();
  216.                 if (IsOK) {
  217.                     // 2010/10/11 change from rb to r
  218.                     fpList = fopen(pListFile,"r");
  219.                     if (fpList==0) {
  220.                         fprintf(std_err,"Unable to open list file %s\n",pListFile);
  221.                         IsOK=0;
  222.                     }
  223.                 }
  224.                 if (IsOK) {
  225.                     char *pRet;
  226.                     for(;;) {
  227.                         pRet=fgets(fileName, sizeof fileName, fpList);
  228.                         if (pRet==0)
  229.                             break;
  230.                         pRet=strchr(fileName,'\n');
  231.                         if (pRet)
  232.                             *pRet=0;
  233.                         IsOK=ProcessFile(fileName);
  234.                     }
  235.                 }
  236.                 if (fpList)
  237.                     fclose(fpList);
  238.             }
  239.             else {
  240.                 IsOK=0;
  241.                 Instruct=1;
  242.             }
  243.         }
  244.         else if (strcmp(argv[i],"-y") == 0) {
  245.             bypassErrs=1;
  246.         }
  247.         else if (strcmp(argv[i],"-s") == 0) {
  248.             signatureOnFront=1;
  249.         }
  250.         else if (strcmp(argv[i],"-x") == 0) {
  251.             tagSubdirs=1;
  252.         }
  253.         else if (argv[i][0] == '-') {
  254.             IsOK=0;
  255.             Instruct=1;
  256.         }
  257.         else {
  258.             if (IsOutFileGlob) {
  259.                 int j;
  260.                 for (j=i+1;j<argc-1;j++) {
  261.                     if (argv[j][0] != '-') {
  262.                         fprintf(std_err,"Output is a file name(%s), cannot use more that 1 input file\n",pBkupDir);
  263.                         IsOK=0;
  264.                         Instruct=1;
  265.                     }
  266.                 }
  267.             }
  268.             else
  269.                 openBackupLog();
  270.             if (IsOK)
  271.                 IsOK=ProcessFile(argv[i]);
  272.         }
  273.         if (!IsOK && !IsOutFileGlob) {
  274.             if (bypassErrs) {
  275.                 fprintf(std_err,"Error - Continuing with other files\n");
  276.                 IsOK=true;
  277.             }
  278.             else {
  279.                 int ans=0;
  280.                 while (ans != 'y'&& ans != 'Y'&&ans!='n'&&ans!='N') {
  281.                     fprintf(std_err,"Errors - do you wish to continue? (y/n)\n");
  282.                     ans = getchar();
  283.                     if (ans == 'y'|| ans == 'Y')
  284.                         IsOK=true;
  285.                 }
  286.             }
  287.         }
  288.     }
  289.  
  290.     if (Instruct) {
  291.         fprintf(stderr,"Usage: tagbkup [options] filename ... backupdir\n");
  292.         fprintf(stderr,"\n");
  293.         fprintf(stderr,"Backs up and restores mp3 id3v1 and id3v2 tags\n");
  294.         fprintf(stderr,"\n");
  295.         fprintf(stderr,"Options (-b, -r or -c is required):\n");
  296.         fprintf(stderr,"-b       Backup tags from mp3 files to directory\n");
  297.         fprintf(stderr,"-r       Restore tags from directory to mp3 files\n");
  298.         fprintf(stderr,"-c       Copy tags from mp3 files to like named mp3 files in backupdir\n");
  299.         fprintf(stderr,"         or copy tags from an mp3 file to another mp3 file, where the\n");
  300.         fprintf(stderr,"         output mp3 file name is supplied instead of backupdir\n");
  301.         fprintf(stderr,"-c1      Append ID3V1 tag from mp3 file to output file\n");
  302.         fprintf(stderr,"-c2      Copy ID3V2 tag from mp3 file to output file, overwriting existing file\n");
  303.         fprintf(stderr,"-cm      Append mp3 data without tags from mp3 file to output file\n");
  304.         fprintf(stderr,"-d dir   Copy restored mp3 files to this directory\n");
  305.         fprintf(stderr,"-t       Test - no copying of data\n");
  306.         fprintf(stderr,"-v       Verbose\n");
  307.         fprintf(stderr,"-u       Report updates done\n");
  308.         fprintf(stderr,"-n       No overwriting of backup files, append log file\n");
  309.         fprintf(stderr,"-f fn    Input filename list is in file fn\n");
  310.         fprintf(stderr,"-y       Continue if there are errors, skipping failed files\n");
  311.         fprintf(stderr,"-s       File signature based on front part of file instead of end\n");
  312.         fprintf(stderr,"-x       Tags in 256 subdirectories\n");
  313.     }
  314.  
  315.     if (pSignatureList)
  316.         delete [] pSignatureList;
  317.     if (fpLog)
  318.         fclose(fpLog);
  319.    
  320.     fprintf(stderr,"Number of files processed = %d\n",FileProcCount);
  321.  
  322.     return !IsOK;    
  323. }
  324.  
  325.  
  326. int openBackupLog() {
  327.     int IsOK=1;
  328.     char logFile[256];
  329.     if (IsBkupGlob) {
  330.         if (fpLog==0) {
  331.             strcpy(logFile,pBkupDir);
  332.             strcat(logFile,"/");
  333.             strcat(logFile,"tagbkup.log");
  334.             fprintf(stderr,"Log file %s\n",logFile);
  335.             char *mode = "ab";
  336.             if (OverwriteBkup)
  337.                 mode="wb";
  338.             fpLog=fopen(logFile,mode);
  339.             if (fpLog==0) {
  340.                 fprintf(stderr,"Unable to open log file %s\n",logFile);
  341.                 IsOK=0;
  342.             }
  343.         }
  344.     }
  345.     return IsOK;
  346. }
  347.  
  348. // Make the directory for a file
  349. void mkdir_f(char *fileName) {
  350.     char dirName[512];
  351.     char *pIn=fileName;
  352.     char *pOut=dirName;
  353.     memset(dirName,0,sizeof dirName);
  354.     for(;*pIn;pIn++,pOut++) {
  355.         if (pOut !=dirName) {
  356.             if (*pIn == '/' || *pIn == '\\') {
  357.                 #ifdef _MSC_VER
  358.                     mkdir(dirName);
  359.                 #else
  360.                     mkdir(dirName,S_IRWXU|S_IRWXG|S_IRWXO);
  361.                 #endif
  362.             }
  363.         }
  364.         *pOut=*pIn;
  365.     }
  366. }
  367.  
  368. int ProcessFile(char *pMP3FileName) {
  369.     char szBkupName[512];
  370.     char szRestName[512];
  371.     char szFinalRestName[512];
  372.     char *pFinalRestName;
  373.     char Signature[20];
  374.     unsigned int sig[2];
  375.     static time_t notifyTime = 0;
  376.  
  377.     // 5/30/2010 - progress reporting
  378.     if (notifyTime == 0)
  379.         notifyTime = time(0);
  380.     else {
  381.         time_t now = time(0);
  382.         if (difftime(now, notifyTime) >= 60.0) {
  383.             notifyTime = now;
  384.             fprintf(stderr,"Number of files processed so far = %d\n",FileProcCount);
  385.         }
  386.     }
  387.    
  388.     int IsOK=1;
  389.     int ret;
  390.     int copyOpts = 0;
  391.     if (IsCopyV1 || IsCopyV2 || IsCopyMp3)
  392.         copyOpts = 1;
  393.  
  394.     if (IsBkupGlob + IsRestGlob + IsCopyGlob + copyOpts != 1){
  395.         IsOK=0;
  396.         Instruct=1;
  397.     }
  398.  
  399.     if (IsBkupGlob)
  400.         pRestDir=0;
  401.  
  402.     char *p=strrchr(pMP3FileName,'.');
  403.     size_t data_start=0;
  404.     if (p && strcasecmp(p,".mp3")==0
  405.         && strncasecmp(pMP3FileName,"tag_",4)!=0
  406.         && IsOK) {
  407.         int seq;
  408.         if (IsBkupGlob || IsRestGlob) {
  409.             IsOK=GetFileSignature(pMP3FileName,sig,&data_start);
  410.             if (IsOK) {
  411.                 sprintf(Signature,"%8.8x%8.8x",sig[0],sig[1]);
  412.                 FileProcCount++;
  413.             }
  414.         }
  415.         else
  416.             IsOK=getDataStart(pMP3FileName,&data_start);
  417.         for (seq=0;IsOK;) {
  418.             int i;
  419.             if (IsBkupGlob || IsRestGlob) {
  420.                 for (i=0;i<countSignature;i++){
  421.                     if (sig[0]==pSignatureList[i][0]
  422.                         && sig[1]==pSignatureList[i][1]) {
  423.                         seq++;
  424.                     }
  425.                 }
  426.                 if (tagSubdirs)
  427.                     sprintf(szBkupName,"%s/%2.2s/tag_%s_%3.3d.mp3",pBkupDir,Signature,Signature,seq);
  428.                 else
  429.                     sprintf(szBkupName,"%s/tag_%s_%3.3d.mp3",pBkupDir,Signature,seq);
  430.                 pSignatureList[countSignature][0]=sig[0];
  431.                 pSignatureList[countSignature++][1]=sig[1];
  432.             }
  433.             if (IsBkupGlob){
  434.                 ret=CopyTag(szBkupName,pMP3FileName);
  435.                 switch (ret) {
  436.                 case -1:
  437.                     // Duplicate file found with different data
  438.                     IsOK=AppendMP3Data(szBkupName,0,0);
  439.                     if (IsOK)
  440.                         IsOK=AppendTagV1(szBkupName,pMP3FileName);
  441.                     if (!IsOK) {
  442.                         fprintf(stderr,"%s --> %s - Error\n",pMP3FileName,szBkupName);
  443.                         break;
  444.                     }
  445.                     if (IsVerbose || ReportUpdates)
  446.                         fprintf(stderr,"%s --> %s - data updated\n",
  447.                             pMP3FileName,szBkupName);
  448.                     break;
  449.                 case 0:
  450.                     // Copied OK
  451.                     IsOK=AppendMP3Data(szBkupName,0,0);
  452.                     if (IsOK)
  453.                         IsOK=AppendTagV1(szBkupName,pMP3FileName);
  454.                     if (IsOK) {
  455.                         if (IsVerbose || ReportUpdates)
  456.                             fprintf(stderr,"%s --> %s - copied OK\n",
  457.                                 pMP3FileName,szBkupName);
  458.                     }
  459.                     else
  460.                         fprintf(stderr,"%s --> %s - Error\n",pMP3FileName,szBkupName);
  461.                     break;
  462.                 case 1:
  463.                     // Duplicate file found with same data
  464.                     // OK
  465.                     if (IsVerbose)
  466.                         fprintf(stderr,"%s --> %s - up to date\n",pMP3FileName,szBkupName);
  467.                     break;
  468.                 case 2:
  469.                     // error copying tag
  470.                     fprintf(stderr,"%s --> %s - Error\n",pMP3FileName,szBkupName);
  471.                     IsOK=0;
  472.                     break;
  473.                 case 3:
  474.                     // Duplicate file, different data not copied
  475.                         fprintf(stderr,"%s --> %s - already exists for a different source - retry\n",
  476.                             pMP3FileName,szBkupName);
  477.                     continue;
  478.                 }
  479.                 if (fpLog)
  480.                     fprintf(fpLog,"%s_%3.3d %s\n",Signature,seq,pMP3FileName);
  481.  
  482.                 break;
  483.             }
  484.             if (IsRestGlob) {
  485.                 if (pRestDir) {
  486.                     strcpy(szRestName,pRestDir);
  487.                     char Last = *(strchr(szRestName,0)-1);
  488.                     if (Last != '/' && Last != '\\')
  489.                         strcat(szRestName,"/");
  490.                     if (*pMP3FileName == '/' || *pMP3FileName == '\\')
  491.                         strcat(szRestName,pMP3FileName+1);
  492.                     else if (pMP3FileName[1] == ':') {
  493.                         if (pMP3FileName[2] == '\\')
  494.                             strcat(szRestName,pMP3FileName+3);
  495.                         else
  496.                             strcat(szRestName,pMP3FileName+2);
  497.                     }
  498.                     else
  499.                         strcat(szRestName,pMP3FileName);
  500.                     mkdir_f(szRestName);
  501.                     pFinalRestName=szRestName;
  502.                 }
  503.                 else {
  504.                     ret = CompareTag(pMP3FileName,szBkupName);
  505.                     if (ret==1) {
  506.                         if (IsVerbose) {
  507.                             fprintf(stderr,"%s --> %s",szBkupName,pMP3FileName);
  508.                             fprintf(stderr," - file already exists with correct data\n");
  509.                         }
  510.                         break;
  511.                     }
  512.                     if (ret==2) {
  513.                         IsOK=0;
  514.                         break;
  515.                     }
  516.  
  517.                     strcpy(szRestName,pMP3FileName);
  518.                     strcat(szRestName,"rest");
  519.                     pFinalRestName=pMP3FileName;
  520.                 }
  521.                 remove(szRestName);
  522.                 ret=CopyTag(szRestName,szBkupName);
  523. //                if (ret==-1)
  524.                 if (ret!=0){
  525.                     fprintf(stderr,"%s --> %s\n",szBkupName,pFinalRestName);
  526.                     // error copying tag
  527.                     fprintf(std_err,"Error Copying tag to %s\n",szRestName);
  528.                     IsOK=0;
  529.                     break;
  530.                 }
  531.                 IsOK=AppendMP3Data(szRestName,pMP3FileName,data_start);
  532.                 if (!IsOK)
  533.                     break;
  534.                 IsOK=AppendTagV1(szRestName,szBkupName);
  535. //                IsOK=UpdateTagV1(szRestName);
  536.                 if (!IsOK)
  537.                     break;
  538.                 if (!IsTestGlob && !pRestDir)
  539.                     IsOK=(remove(pMP3FileName)==0);
  540.                 if (!IsOK) {
  541.                     fprintf(stderr,"%s --> %s\n",szBkupName,pFinalRestName);
  542.                     fprintf(std_err,"Error - Unable to delete file %s\n",pMP3FileName);
  543.                     break;
  544.                 }
  545.                 if (!IsTestGlob && !pRestDir)
  546.                     IsOK=(rename(szRestName,pMP3FileName)==0);
  547.                 if (!IsOK) {
  548.                     fprintf(stderr,"%s --> %s\n",szBkupName,pFinalRestName);
  549.                     fprintf(std_err,"Error - Unable to rename file %s to %s\n",szRestName,pMP3FileName);
  550.                     break;
  551.                 }
  552.                 if (IsVerbose || ReportUpdates) {
  553.                     fprintf(stderr,"%s --> %s",szBkupName,pFinalRestName);
  554.                     fprintf(stderr," - tag restored\n");
  555.                 }
  556.             }
  557.             if (IsCopyGlob) {
  558.                 if (IsOutFileGlob) {
  559.                     if (FileProcCount > 1) {
  560.                         IsOK=0;
  561.                         fprintf(std_err,"Error - When copying to a file only one input file can be used.");
  562.                         break;
  563.                     }
  564.                     strcpy(szRestName,pBkupDir);
  565.                 }
  566.                 else {
  567.                     strcpy(szRestName,pBkupDir);
  568.                     char *pFileName = strrchr(pMP3FileName,'/');
  569.                     if (pFileName==0)
  570.                         pFileName = strrchr(pMP3FileName,'\\');
  571.                     if (pFileName==0)
  572.                         pFileName = strrchr(pMP3FileName,':');
  573.                     if (pFileName==0)
  574.                         pFileName=pMP3FileName;
  575.                     else
  576.                         pFileName++;
  577.                     strcat(szRestName,"/");
  578.                     strcat(szRestName,pFileName);
  579.                 }
  580.                 FileProcCount++;
  581.                 strcpy(szFinalRestName,szRestName);
  582.                 strcat(szRestName,"copy");
  583.  
  584.                 remove(szRestName);
  585.                 ret=CompareTag(szFinalRestName, pMP3FileName);
  586.                 if (ret==1) {
  587.                     if (IsVerbose) {
  588.                         fprintf(stderr,"%s --> %s",pMP3FileName,szFinalRestName);
  589.                         fprintf(stderr," - file already exists with correct data\n");
  590.                     }
  591.                     break;
  592.                 }
  593.                 if (ret==2) {
  594.                     IsOK=0;
  595.                     break;
  596.                 }
  597.                 int outputFileExists = 1;
  598.                 if (ret==0)
  599.                     outputFileExists = 0;
  600.                 ret=CopyTag(szRestName,pMP3FileName);
  601. //                if (ret==-1)
  602.                 if (ret!=0){
  603.                     fprintf(stderr,"%s --> %s\n",pMP3FileName,szFinalRestName);
  604.                     // error copying tag
  605.                     fprintf(std_err,"Error Copying tag to %s\n",szRestName);
  606.                     IsOK=0;
  607.                     break;
  608.                 }
  609.                 if (outputFileExists)
  610.                     IsOK=AppendMP3Data(szRestName,szFinalRestName,data_start);
  611.                 else
  612.                     IsOK=AppendMP3Data(szRestName,0,0);
  613.                 if (!IsOK)
  614.                     break;
  615.                 IsOK=AppendTagV1(szRestName,pMP3FileName);
  616. //                IsOK=UpdateTagV1(szRestName);
  617.                 if (!IsOK)
  618.                     break;
  619.                 if (!IsTestGlob && outputFileExists)
  620.                     IsOK=(remove(szFinalRestName)==0);
  621.                 if (!IsOK) {
  622.                     fprintf(stderr,"%s --> %s\n",pMP3FileName,szFinalRestName);
  623.                     fprintf(std_err,"Error - Unable to delete file %s\n",szFinalRestName);
  624.                     break;
  625.                 }
  626.                 if (!IsTestGlob)
  627.                     IsOK=(rename(szRestName,szFinalRestName)==0);
  628.                 if (!IsOK) {
  629.                     fprintf(stderr,"%s --> %s\n",pMP3FileName,szFinalRestName);
  630.                     fprintf(std_err,"Error - Unable to rename file %s to %s\n",szRestName,szFinalRestName);
  631.                     break;
  632.                 }
  633.                 if (IsVerbose || ReportUpdates) {
  634.                     fprintf(stderr,"%s --> %s",pMP3FileName,szFinalRestName);
  635.                     fprintf(stderr," - tag copied\n");
  636.                 }
  637.  
  638.  
  639.             }
  640.             if (IsCopyV2){
  641.                 if (IsOutFileGlob) {
  642.                     strcpy(szRestName,pBkupDir);
  643.                 }
  644.                 else {
  645.                     fprintf(stderr,"%s --> %s\n",pMP3FileName,szRestName);
  646.                     // error copying tag
  647.                     fprintf(std_err,"Copy tag V2 requires output file name not directory\n");
  648.                     IsOK=0;
  649.                     break;
  650.                 }
  651.  
  652.                 FileProcCount++;
  653.                 remove(szRestName);
  654.                 ret=CopyTag(szRestName,pMP3FileName);
  655.                 if (ret!=0){
  656.                     fprintf(stderr,"%s --> %s\n",pMP3FileName,szRestName);
  657.                     // error copying tag
  658.                     fprintf(std_err,"Error %d Copying tag to %s\n",ret,szRestName);
  659.                     IsOK=0;
  660.                     break;
  661.                 }
  662.             }
  663.             if (IsCopyMp3){
  664.                 if (IsOutFileGlob) {
  665.                     strcpy(szRestName,pBkupDir);
  666.                 }
  667.                 else {
  668.                     fprintf(stderr,"%s --> %s\n",pMP3FileName,szRestName);
  669.                     // error copying tag
  670.                     fprintf(std_err,"Copy Mp3 data requires output file name not directory\n");
  671.                     IsOK=0;
  672.                     break;
  673.                 }
  674.                 FileProcCount++;
  675.                 IsOK=AppendMP3Data(szRestName,pMP3FileName,data_start);
  676.             }
  677.             if (IsCopyV1){
  678.                 if (IsOutFileGlob) {
  679.                     strcpy(szRestName,pBkupDir);
  680.                 }
  681.                 else {
  682.                     fprintf(stderr,"%s --> %s\n",pMP3FileName,szRestName);
  683.                     // error copying tag
  684.                     fprintf(std_err,"Copy Tag V1 requires output file name not directory\n");
  685.                     IsOK=0;
  686.                     break;
  687.                 }
  688.                 FileProcCount++;
  689.                 IsOK=AppendTagV1(szRestName,pMP3FileName);
  690.             }
  691.  
  692.             // No need to try another seq value if we got here
  693.             break;
  694.         }
  695.     }
  696.  
  697.     return IsOK;
  698. }
  699.  
  700.  
  701. // Create a signature for the music.
  702.  
  703. int GetFileSignature(char *pFoundName, unsigned int *pSig, size_t *pData_start) {
  704.     FILE *fpIn;
  705.     int IsOK=1;
  706.  
  707.     fpIn=fopen(pFoundName,"rb");
  708.     if (fpIn==0) {
  709.         fprintf(std_err,"Error - Unable to open file %s\n",pFoundName);
  710.         IsOK=0;
  711.     }  
  712.  
  713.     //   The ID3v2 tag header, which should be the first information in the
  714.     //   file, is 10 bytes as follows:
  715.     //
  716.     //     ID3v2/file identifier      "ID3"
  717.     //     ID3v2 version              $03 00
  718.     //     ID3v2 flags                %abc00000
  719.     //     ID3v2 size             4 * %0xxxxxxx
  720.  
  721.  
  722.     //     The ID3v2 tag size is encoded with four bytes where the most
  723.     //     significant bit (bit 7) is set to zero in every byte, making a total
  724.     //     of 28 bits. The zeroed bits are ignored, so a 257 bytes long tag is
  725.     //     represented as $00 00 02 01.
  726.  
  727.     //     The ID3v2 tag size is the size of the complete tag after
  728.     //     unsychronisation, including padding, excluding the header but not
  729.     //     excluding the extended header (total tag size - 10). Only 28 bits
  730.     //     (representing up to 256MB) are used in the size description to avoid
  731.     //     the introducuction of 'false syncsignals'.
  732.  
  733.    
  734.    
  735.     //   An ID3v2 tag can be detected with the following pattern:
  736.     //     I  D  3
  737.     //   $49 44 33 yy yy xx zz zz zz zz
  738.     //     0  1  2  3  4  5  6  7  8  9
  739.     //   Where yy is less than $FF, xx is the 'flags' byte and zz is less than
  740.     //   $80.
  741.    
  742.     mp3info mp3i;
  743.     *pData_start=0;
  744.  
  745.  
  746.     struct stat fileStat;
  747.     if (IsOK) {
  748.         int ret=fstat (fileno(fpIn),&fileStat);
  749.         if (ret!=0) {
  750.             fprintf(std_err,"Error calling fstat on file %s\n",pFoundName);
  751.             IsOK=0;
  752.         }
  753.     }
  754.  
  755.     size_t tagSize = 0;
  756.     if (IsOK) {
  757.         IsOK=GetTagSize(fpIn,&tagSize);
  758.         memset(&mp3i,0,sizeof(mp3info));
  759.         mp3i.filename=pFoundName;
  760.         mp3i.file=fpIn;
  761.         mp3i.datasize=fileStat.st_size;
  762.         if(get_first_header(&mp3i,tagSize)) {
  763. //        if(get_first_header(&mp3i,0))
  764.             *pData_start=ftell(fpIn);
  765.         }
  766.         else {
  767.             fprintf(std_err,"Unable to access mp3 frame in file %s\n",pFoundName);
  768.             IsOK=0;
  769.         }
  770. //        fprintf(stderr,"tagsize = %d\n",tagSize);
  771. //        fprintf(stderr,"pData_start = %d\n",*pData_start);
  772.     }
  773.  
  774.     unsigned int sig[2]={0,0};
  775.     unsigned int buf[2]={0,0};
  776.     off_t numread = 2048;       // approx 1 second
  777.     off_t start;
  778.     int count;
  779.     int i;    
  780.     off_t dataEnd;
  781.     int v1tags;
  782.  
  783.     if (IsOK) {
  784.         if (signatureOnFront) {
  785.             start = (*pData_start)+16*1024*15;  // approx 15 seconds
  786.  
  787.             if (fileStat.st_size < start + ((off_t)sizeof buf) * numread + 512)
  788.                 start = *pData_start;
  789.         }
  790.         else {
  791. //            off_t dataEnd = fileStat.st_size;
  792. //            int v1tags=0;
  793. //            for (;;) {
  794. //                IsOK=(fseek(fpIn,dataEnd-128,SEEK_SET)==0);
  795. //                if (IsOK) {
  796. //                    count=fread(v1tag,1,sizeof v1tag,fpIn);
  797. //                    if (count!=3)
  798. //                        IsOK=0;
  799. //                }
  800. //                if (IsOK) {
  801. //                    if (IsID3Tag(v1tag)) {
  802. //                        dataEnd-=128;
  803. //                        v1tags++;
  804. //                    }
  805. //                    else
  806. //                        break;
  807. //                }
  808. //            }
  809.             IsOK=countV1Tags(fpIn, v1tags, dataEnd);
  810.             if (IsOK) {
  811.                 if (v1tags==0)
  812.                     fprintf(std_err,"Warning - No ID3v1 tag on file %s\n",pFoundName);
  813.                 else if (v1tags!=1)
  814.                     fprintf(std_err,"Warning - %d ID3v1 tags on file %s\n",v1tags,pFoundName);
  815.                 start = dataEnd - (((off_t)sizeof buf) * numread) - 16*1024*30; // approx 30 seconds
  816.                 if (start < (off_t)*pData_start) {
  817.                     start = dataEnd - (((off_t)sizeof buf) * numread) - 16*1024*10; // approx 10 seconds
  818.                 }
  819.                 if (start < (off_t)*pData_start) {
  820.                     start = dataEnd - (((off_t)sizeof buf) * numread) - 16*1024*5; // approx 5 seconds
  821.                 }
  822.                 if (start < (off_t)*pData_start) {
  823.                     fprintf(std_err,"Error - file is too small %s\n",pFoundName);
  824.                     IsOK=0;
  825.                 }
  826.             }
  827.         }
  828.     }
  829.  
  830.     if (IsOK)
  831.         IsOK=(fseek(fpIn,start,SEEK_SET)==0);
  832.  
  833.     for (i=0;i<numread&&IsOK;i++) {
  834.         count=fread(buf,1,sizeof buf,fpIn);
  835.         if (count != sizeof sig)
  836.             break;
  837.         sig[0]^=buf[0];
  838.         sig[1]^=buf[1];
  839.     }
  840.  
  841.     if (fpIn)
  842.         fclose(fpIn);
  843.  
  844.     pSig[0]=sig[0];
  845.     pSig[1]=sig[1];
  846.     return IsOK;
  847. }
  848.  
  849.  
  850. int countV1Tags(FILE *fpIn, int &v1tags, off_t &dataEnd) {
  851.     int IsOK=1;
  852.     char v1tag[3];
  853.     v1tags=0;
  854.     dataEnd=0;
  855.     int count;
  856.     IsOK=(fseek(fpIn,0,SEEK_END)==0);
  857.     if (IsOK)
  858.         dataEnd = ftell(fpIn);
  859.     for (;IsOK;) {
  860.         IsOK=(fseek(fpIn,dataEnd-128,SEEK_SET)==0);
  861.         if (IsOK) {
  862.             count=fread(v1tag,1,sizeof v1tag,fpIn);
  863.             if (count!=3)
  864.                 IsOK=0;
  865.         }
  866.         if (IsOK) {
  867.             if (IsID3Tag(v1tag)) {
  868.                 dataEnd-=128;
  869.                 v1tags++;
  870.             }
  871.             else
  872.                 break;
  873.         }
  874.     }
  875.  
  876.     if (!IsOK)
  877.         fprintf(std_err,"Error calculating number of v1 tags\n");
  878.    
  879.     return IsOK;
  880. }
  881.  
  882.  
  883. int getDataStart(char *pFoundName, size_t *pDataStart) {
  884.     FILE *fpIn;
  885.     int IsOK=1;
  886.  
  887.     fpIn=fopen(pFoundName,"rb");
  888.     if (fpIn==0) {
  889.         fprintf(std_err,"Error - Unable to open file %s\n",pFoundName);
  890.         IsOK=0;
  891.     }  
  892.  
  893.     struct stat fileStat;
  894.     if (IsOK) {
  895.         int ret=fstat (fileno(fpIn),&fileStat);
  896.         if (ret!=0) {
  897.             fprintf(std_err,"Error calling fstat on file %s\n",pFoundName);
  898.             IsOK=0;
  899.         }
  900.     }
  901.                  
  902.     mp3info mp3i;
  903.     size_t tagSize = 0;
  904.     *pDataStart = 0;
  905.     if (IsOK) {
  906.         IsOK=GetTagSize(fpIn,&tagSize);
  907.         memset(&mp3i,0,sizeof(mp3info));
  908.         mp3i.filename=pFoundName;
  909.         mp3i.file=fpIn;
  910.         mp3i.datasize=fileStat.st_size;
  911.         if(get_first_header(&mp3i,tagSize)) {
  912.             *pDataStart=ftell(fpIn);
  913.         }
  914.         else {
  915.             fprintf(std_err,"Unable to access mp3 frame in file %s\n",pFoundName);
  916.             IsOK=0;
  917.         }
  918.     }
  919.     if (fpIn)
  920.         fclose(fpIn);
  921.     return IsOK;
  922. }
  923.  
  924.  
  925.  
  926. // return code
  927. // -1 Duplicate file found with different data, copied
  928. // 0  Data copied
  929. // 1  File found with same data
  930. // 2  Error
  931. // 3  Duplicate File found with different data not copied
  932.  
  933. int CopyTag(char *pOutputFile, char *pInputFile) {
  934.     FILE *fpIn=0;
  935.     FILE *fpOut=0;
  936.     int IsOK=1;
  937.     size_t tagsize;
  938.     char *pInputBuff=0;
  939.     size_t count;
  940.     size_t count2;
  941.     int result=0;
  942.     pInputBuff=new char[BufSize];
  943.     size_t readlen;
  944.  
  945.     // check if the output file exists and
  946.     // has the same contents
  947.     if (IsOK) {
  948.         result=CompareTag(pOutputFile, pInputFile);
  949.         if (result==2)
  950.             IsOK=0;
  951.     }
  952.     if (result == -1 && !OverwriteBkup)
  953.         result=3;
  954.  
  955.     if (result<=0 && IsOK) {
  956.         fpIn=fopen(pInputFile,"rb");
  957.         if (fpIn==0) {
  958.             fprintf(std_err,"Error opening input file %s\n",pInputFile);
  959.             IsOK=0;
  960.         }
  961.     }
  962.  
  963.     if (result<=0 && IsOK)
  964.         IsOK=GetTagSize(fpIn,&tagsize);
  965.  
  966.     if (tagsize == 0)
  967.         fprintf(std_err,"Warning - no tag on file %s\n",pInputFile);
  968.  
  969.     if (result<=0 && IsOK) {
  970.         fseek(fpIn,0,SEEK_SET);
  971.         if (!IsTestGlob) {
  972.             fpOut=fopen(pOutputFile,"wb");
  973.             if (fpOut==0 && tagSubdirs) {
  974.                 // Check if directory does not exist - create it
  975.                 mkdir_f(pOutputFile);
  976.                 fpOut=fopen(pOutputFile,"wb");
  977.             }
  978.             if (fpOut==0) {
  979.                 fprintf(std_err,"Error opening output file %s\n",pOutputFile);
  980.                 IsOK=0;
  981.             }
  982.         }
  983.     }
  984.     if (result<=0 && IsOK) {
  985.         size_t remains=tagsize;
  986.         while(remains>0) {
  987.             readlen=remains;
  988.             if (readlen>BufSize)
  989.                 readlen=BufSize;
  990.             count = fread(pInputBuff,1,readlen,fpIn);
  991.             if (count != readlen) {
  992.                 IsOK=0;
  993.                 fprintf(std_err,"Error reading file %s\n",pInputFile);
  994.                 break;
  995.             }
  996.             if (!IsTestGlob) {
  997.                 count2 = fwrite(pInputBuff,1,count,fpOut);
  998.                 if (count2 != count) {
  999.                     IsOK=0;
  1000.                     fprintf(std_err,"Error writing file %s\n",pOutputFile);
  1001.                     break;
  1002.                 }
  1003.             }
  1004.             remains-=readlen;
  1005.         }
  1006.     }
  1007.  
  1008.     if (pInputBuff) {
  1009.         delete [] pInputBuff;
  1010.         pInputBuff=0;
  1011.     }
  1012.    
  1013.     if (fpIn)
  1014.         fclose(fpIn);
  1015.     if (fpOut)
  1016.         fclose(fpOut);
  1017.  
  1018.     if (!IsOK)
  1019.         result=2;
  1020.  
  1021.     return result;
  1022.  
  1023. }
  1024.  
  1025.  
  1026. // return code
  1027. // -1 different data
  1028. // 0  No output file
  1029. // 1  same data
  1030. // 2  Error
  1031.  
  1032. int CompareTag(char *pOutputFile, char *pInputFile) {
  1033.     FILE *fpIn=0;
  1034.     FILE *fpOut=0;
  1035.     int IsOK = 1;
  1036.     size_t tagsize;
  1037.     char *pInputBuff=0;
  1038.     char *pOutputBuff=0;
  1039.     size_t count;
  1040.     int result=0;
  1041.  
  1042.     fpIn=fopen(pInputFile,"rb");
  1043.     if (fpIn==0) {
  1044.         fprintf(std_err,"Error opening input file %s\n",pInputFile);
  1045.         IsOK=0;
  1046.     }
  1047.     if (IsOK)
  1048.         IsOK=GetTagSize(fpIn,&tagsize);
  1049.     pInputBuff=new char[BufSize];
  1050.     size_t readlen;
  1051.     // check if the output file exists and
  1052.     // has the same contents
  1053.     if (IsOK) {
  1054.         fseek(fpIn,0,SEEK_SET);
  1055.         fpOut=fopen(pOutputFile,"rb");
  1056.         if (fpOut!=0) {
  1057.             size_t tagoutsize;
  1058.             IsOK=GetTagSize(fpOut,&tagoutsize);
  1059.             fseek(fpOut,0,SEEK_SET);
  1060.             result=1; // assume data will be the same
  1061.             if (IsOK) {
  1062.                 if (tagsize!=tagoutsize)
  1063.                     // file exists with incorrect data
  1064.                     result=-1;
  1065.                 pOutputBuff=new char[BufSize];
  1066.                 size_t remains=tagsize;
  1067.                 while(remains>0 && result==1) {
  1068.                     readlen=remains;
  1069.                     if (readlen>BufSize)
  1070.                         readlen=BufSize;
  1071.                     count = fread(pInputBuff,1,readlen,fpIn);
  1072.                     if (count != readlen) {
  1073.                         IsOK=0;
  1074.                         fprintf(std_err,"Error reading file %s\n",pInputFile);
  1075.                         break;
  1076.                     }
  1077.                     count = fread(pOutputBuff,1,readlen,fpOut);
  1078.                     if (count == readlen) {
  1079.                         if (memcmp(pInputBuff,pOutputBuff,readlen)!=0) {
  1080.                             // file exists with incorrect data
  1081.                             result=-1;
  1082.                             break;
  1083.                         }
  1084.                     }
  1085.                     else {
  1086.                         // file is short - means wrong data
  1087.                         result=-1;
  1088.                         break;
  1089.                     }
  1090.                     remains-=readlen;
  1091.                 }
  1092.             }
  1093.         }
  1094.     }
  1095.  
  1096.     if (pInputBuff) {
  1097.         delete [] pInputBuff;
  1098.         pInputBuff=0;
  1099.     }
  1100.     if (pOutputBuff) {
  1101.         delete [] pOutputBuff;
  1102.         pOutputBuff=0;
  1103.     }
  1104.    
  1105.     if (fpIn)
  1106.         fclose(fpIn);
  1107.     if (fpOut)
  1108.         fclose(fpOut);
  1109.  
  1110.     if (!IsOK)
  1111.         result=2;
  1112.  
  1113.     return result;
  1114.  
  1115. }
  1116.  
  1117.  
  1118.  
  1119.  
  1120. int AppendMP3Data(char *pOutputFile, char *pInputFile, size_t data_start) {
  1121.  
  1122.     FILE *fpIn=0;
  1123.     FILE *fpOut=0;
  1124.     int IsOK=1;
  1125. //    size_t tagsize;
  1126.     char *pInputBuff=0;
  1127.     size_t count;
  1128.     off_t dataEnd;
  1129.     int v1tags;
  1130.  
  1131.     if (pInputFile) {
  1132.         fpIn=fopen(pInputFile,"rb");
  1133.         if (fpIn==0) {
  1134.             fprintf(std_err,"Error opening input file %s\n",pInputFile);
  1135.             IsOK=0;
  1136.         }
  1137. //        if (IsOK)
  1138. //            IsOK=GetTagSize(fpIn,&tagsize);
  1139.         pInputBuff=new char[BufSize];
  1140.         if (IsOK) {
  1141.             IsOK=countV1Tags(fpIn, v1tags, dataEnd);
  1142.             IsOK=(fseek(fpIn,data_start,SEEK_SET)==0);
  1143.             if (!IsOK)
  1144.                 fprintf(std_err,"Error seeking on file %s\n",pInputFile);
  1145.         }
  1146.  
  1147.     }
  1148.     size_t readlen;
  1149.     if (IsOK && !IsTestGlob) {
  1150.         fpOut=fopen(pOutputFile,"ab");
  1151.         if (fpOut==0) {
  1152.             fprintf(std_err,"Error opening output file %s\n",pOutputFile);
  1153.             IsOK=0;
  1154.         }
  1155.     }
  1156.     if (IsOK) {
  1157.         if (pInputFile) {
  1158.             off_t pos = data_start;
  1159.  
  1160.             while(!feof(fpIn) && pos < dataEnd) {
  1161.                 size_t maxReadLen = dataEnd - pos;
  1162.                 if (maxReadLen > BufSize)
  1163.                     maxReadLen = BufSize;
  1164.                 readlen = fread(pInputBuff,1,maxReadLen,fpIn);
  1165.                 if (ferror(fpIn)) {
  1166.                     IsOK=0;
  1167.                     fprintf(std_err,"Error reading file %s\n",pInputFile);
  1168.                     break;
  1169.                 }
  1170.                 pos += readlen;
  1171.                 if (!IsTestGlob) {
  1172.                     count = fwrite(pInputBuff,1,readlen,fpOut);
  1173.                     if (count != readlen) {
  1174.                         IsOK=0;
  1175.                         fprintf(std_err,"Error writing file %s\n",pOutputFile);
  1176.                         break;
  1177.                     }
  1178.                 }
  1179.             }
  1180.         }
  1181.         else {
  1182.             if (!IsTestGlob) {
  1183.                 count = fwrite(nullMp3,1,nullMp3size,fpOut);
  1184.                 if (count != nullMp3size) {
  1185.                     IsOK=0;
  1186.                     fprintf(std_err,"Error writing file %s\n",pOutputFile);
  1187.                 }
  1188.             }
  1189.         }
  1190.     }
  1191.  
  1192.     if (pInputBuff) {
  1193.         delete [] pInputBuff;
  1194.         pInputBuff=0;
  1195.     }
  1196.    
  1197.     if (fpIn)
  1198.         fclose(fpIn);
  1199.     if (fpOut)
  1200.         fclose(fpOut);
  1201.  
  1202.     return IsOK;
  1203.  
  1204. }
  1205.  
  1206. int GetTagSize(FILE *fpIn, size_t *pTagSize) {
  1207.     *pTagSize=0;
  1208.     unsigned char work[20];
  1209.     int IsOK=1;
  1210.     size_t count;
  1211.  
  1212.     if (IsOK){
  1213.         count=fread(work,1,10,fpIn);
  1214.         if (count != 10) {
  1215.             fprintf(std_err,"Error reading file\n");
  1216.             IsOK=0;
  1217.         }
  1218.     }
  1219.  
  1220.     if (memcmp(work,"ID3",3)==0
  1221.         && work[3] != 255
  1222.         && work[4] != 255
  1223.         && work[6] < 128
  1224.         && work[7] < 128
  1225.         && work[8] < 128
  1226.         && work[9] < 128) {
  1227.         // We have a tag
  1228.         *pTagSize = (size_t) work[9]
  1229.                 + (size_t) work[8] * 128
  1230.                 + (size_t) work[7] * 128 * 128
  1231.                 + (size_t) work[6] * 128 * 128 * 128 + 10;
  1232.     }
  1233.     return IsOK;
  1234.  
  1235. }
  1236.  
  1237.  
  1238. // If 2 or more V1 tags replace them all
  1239. int AppendTagV1(char *pOutFile,char *pInFile) {
  1240.  
  1241.     FILE *fpIn=0;
  1242.     FILE *fpOut=0;
  1243.     int ret;
  1244.     int IsOK=1;
  1245.     char newtag[128];
  1246.     int count;
  1247.     off_t dataEnd;
  1248.     int v1tags;
  1249.    
  1250.  
  1251.     if (!IsTestGlob) {
  1252.         if (IsOK) {
  1253.             fpOut=fopen(pOutFile,"r+b");
  1254.             if (fpOut==0) {
  1255.                 fprintf(std_err,"Error opening r+b file %s\n",pOutFile);
  1256.                 IsOK=0;
  1257.             }
  1258.         }
  1259.  
  1260.         if (IsOK) {
  1261.             IsOK=countV1Tags(fpOut, v1tags, dataEnd);
  1262.             if (!IsOK) {
  1263.                 fprintf(std_err,"Error counting v1 tags on %s\n",pOutFile);
  1264.             }
  1265.         }
  1266.         if (IsOK) {
  1267.             ret=fseek(fpOut,dataEnd,SEEK_SET);
  1268.             if (ret!=0) {
  1269.                 fprintf(std_err,"Error seeking dataEnd on %s\n",pOutFile);
  1270.                 IsOK=0;
  1271.             }
  1272.         }
  1273.     }
  1274.  
  1275.     if (IsOK) {
  1276.         fpIn=fopen(pInFile,"rb");
  1277.         if (fpIn==0) {
  1278.             fprintf(std_err,"Error opening r+b file %s\n",pInFile);
  1279.             IsOK=0;
  1280.         }
  1281.     }
  1282.     if (IsOK) {
  1283.         IsOK=countV1Tags(fpIn, v1tags, dataEnd);
  1284.         if (!IsOK) {
  1285.             fprintf(std_err,"Error counting v1 tag on %s\n",pInFile);
  1286.         }
  1287.     }
  1288.     if (IsOK) {
  1289.         if (v1tags > 1)
  1290.             fprintf(std_err,"Warning - %d id3v1 tags on %s\n",v1tags,pInFile);
  1291.         if (v1tags < 1)
  1292.             fprintf(std_err,"Warning - no id3v1 tags on %s\n",pInFile);
  1293.         ret=fseek(fpIn,-128,SEEK_END);
  1294.         if (ret!=0) {
  1295.             fprintf(std_err,"Error seeking end-128 on %s\n",pInFile);
  1296.             IsOK=0;
  1297.         }
  1298.     }
  1299.     if (IsOK && v1tags >= 1) {
  1300.         count=fread(newtag,1,128,fpIn);
  1301.         if (count != 128) {
  1302.             fprintf(std_err,"Error reading file %s\n",pInFile);
  1303.             IsOK=0;
  1304.         }
  1305.         if (IsOK && !IsTestGlob) {
  1306.             if (IsID3Tag(newtag)) {
  1307.     //            fprintf(stderr,"debug id3v1 = %s\n",newtag);
  1308.                 count = fwrite(newtag,1,128,fpOut);
  1309.                 if (count != 128) {
  1310.                     IsOK=0;
  1311.                     fprintf(std_err,"Error writing file %s\n",pOutFile);
  1312.                 }
  1313.             }
  1314.         }
  1315.     }
  1316.     if (IsOK && !IsTestGlob) {
  1317.         ret=ftruncate(fileno(fpOut),ftell(fpOut));
  1318.         if (ret != 0) {
  1319.             fprintf(std_err,"Error truncating %s\n",pOutFile);
  1320.             IsOK=0;
  1321.         }
  1322.     }
  1323.  
  1324.     if (fpIn)
  1325.         fclose(fpIn);
  1326.     if (fpOut)
  1327.         fclose(fpOut);
  1328.  
  1329.     return IsOK;
  1330. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement