home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Amiga / Workbench / Archivers / xDMS.lha / xdms / src / xdms.c < prev   
C/C++ Source or Header  |  1998-03-01  |  13KB  |  527 lines

  1.  
  2. /*
  3.  *     xDMS  v1.2  -  Portable DMS archive unpacker  -  Public Domain
  4.  *     Written by     Andre R. de la Rocha  <adlroc@usa.net>
  5.  *
  6.  */
  7.  
  8.  
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <ctype.h>
  14.  
  15. #include "cdata.h"
  16. #include "pfile.h"
  17. #include "crc_csum.h"
  18.  
  19. #ifdef UNDER_DOS
  20. #include <io.h>
  21. #include <fcntl.h>
  22. #endif
  23.  
  24.  
  25. /* Program exit codes */
  26. #define EXIT_OK 0
  27. #define EXIT_FAIL 10
  28.  
  29.  
  30. #define FNAME_MAXC 500
  31.  
  32.  
  33. static void Usage(void);
  34. static int strcmpnc(char *, char *);
  35. static void strcpymax(char *, char *, int);
  36. static void strcatmax(char *, char *, int);
  37. static void ErrMsg(USHORT, char *, char *);
  38.  
  39.  
  40.  
  41. void main(int argc, char **argv){
  42.     USHORT i, cmd=0, opt=0, ret, ext, PCRC=0, pwd=0;
  43.     char iname[FNAME_MAXC+1], oname[FNAME_MAXC+1], cmdstr[FNAME_MAXC+20], *tname, *inm, *onm, *p, *q, *destdir=NULL;
  44.  
  45.  
  46.     if (argc < 3) {
  47.         Usage();
  48.         exit(EXIT_FAIL);
  49.     }
  50.  
  51.     i = 1;
  52.  
  53.     /*  proccess options in the command line  */
  54.     while ((i<argc) && (argv[i][0] == '-')){
  55.         if (strlen(argv[i])>2) {
  56.             fprintf(stderr,"Unknown option !\n");
  57.             Usage();
  58.             exit(EXIT_FAIL);
  59.         }
  60.         switch (tolower(argv[i][1])){
  61.             case 'q' :
  62.                 opt = OPT_QUIET;
  63.                 break;
  64.             case 'v' :
  65.                 opt = OPT_VERBOSE;
  66.                 break;
  67.             case 'd' :
  68.                 if (++i == argc) {
  69.                     Usage();
  70.                     exit(EXIT_FAIL);
  71.                 }
  72.                 destdir = argv[i];
  73.                 break;
  74.             case 'p' :
  75.                 if (++i == argc) {
  76.                     Usage();
  77.                     exit(EXIT_FAIL);
  78.                 }
  79.                 PCRC = CreateCRC((UCHAR*)argv[i],(ULONG)strlen(argv[i]));
  80.                 pwd = 1;
  81.                 break;
  82.             default:
  83.                 fprintf(stderr,"Unknown option !\n");
  84.                 Usage();
  85.                 exit(EXIT_FAIL);
  86.         }
  87.         i++;
  88.     }
  89.  
  90.     if ((i == argc) || (strlen(argv[i])>1)) {
  91.         Usage();
  92.         exit(EXIT_FAIL);
  93.     }
  94.  
  95.  
  96.     switch(tolower(argv[i][0])) {
  97.         case 'u':
  98.             cmd = CMD_UNPACK;
  99.             break;
  100.         case 'z':
  101.             cmd = CMD_UNPKGZ;
  102.             break;
  103.         case 'x':
  104.             cmd = CMD_EXTRACT;
  105.             break;
  106.         case 't':
  107.             cmd = CMD_TEST;
  108.             break;
  109.         case 'v':
  110.             cmd = CMD_VIEW;
  111.             break;
  112.         case 'f':
  113.             cmd = CMD_VIEWFULL;
  114.             break;
  115.         case 'd':
  116.             cmd = CMD_SHOWDIZ;
  117.             break;
  118.         case 'b':
  119.             cmd = CMD_SHOWBANNER;
  120.             break;
  121.         default:
  122.             fprintf(stderr,"Unknown command !\n");
  123.             Usage();
  124.             exit(EXIT_FAIL);
  125.     }
  126.  
  127.     if (++i == argc) {
  128.         Usage();
  129.         exit(EXIT_FAIL);
  130.     }
  131.  
  132.     ext = EXIT_OK;
  133.  
  134.     while (i < argc) {
  135.  
  136.         if (!strcmpnc("stdin",argv[i])) {
  137.             inm = NULL;
  138.         } else {
  139.             strcpymax(iname,argv[i],FNAME_MAXC);
  140.             if ((strlen(iname)<4) || (strcmpnc(".dms",iname+strlen(iname)-4))) strcatmax(iname,".dms",FNAME_MAXC);
  141.             inm = iname;
  142.         }
  143.         i++;
  144.  
  145.  
  146.         /*  generate the output filename  */
  147.         if ((i < argc) && (argv[i][0]=='+')) {
  148.             if ((strcmpnc("stdout",argv[i]+1)==0) || (destdir && (strcmpnc("stdout",destdir)==0))) {
  149.                 strcpy(oname,"");
  150.                 onm = NULL;
  151.             } else {
  152.                 if (destdir) {
  153.                     strcpymax(oname,destdir,FNAME_MAXC-1);
  154.                     p = oname + strlen(oname) - 1;
  155.                     if (!strchr(DIR_SEPARATORS,*p)) {
  156.                         *(p+1) = DIR_CHAR;
  157.                         *(p+2) = '\0';
  158.                     }
  159.                 } else strcpy(oname,"");
  160.                 strcatmax(oname,argv[i]+1,FNAME_MAXC);
  161.                 if (((cmd == CMD_UNPACK) || (cmd == CMD_UNPKGZ)) && (strlen(oname)>0)) {
  162.                     p = oname + strlen(oname) - 1;
  163.                     if (strchr(DIR_SEPARATORS,*p)) {
  164.                         if (inm) {
  165.                             p = q = iname;
  166.                             while(*p) {
  167.                                 if (strchr(DIR_SEPARATORS,*p)) q = p+1;
  168.                                 p++;
  169.                             }
  170.                             strcatmax(oname,q,FNAME_MAXC);
  171.                             if ((strlen(oname)>4) && (strcmpnc(oname+strlen(oname)-4,".dms")==0)) {
  172.                                 if (cmd == CMD_UNPKGZ)
  173.                                     strcpy(oname+strlen(oname)-4,".adz");
  174.                                 else
  175.                                     strcpy(oname+strlen(oname)-4,".adf");
  176.                             } else {
  177.                                 if (cmd == CMD_UNPKGZ)
  178.                                     strcatmax(oname,".adz",FNAME_MAXC);
  179.                                 else
  180.                                     strcatmax(oname,".adf",FNAME_MAXC);
  181.                             }
  182.                         } else {
  183.                             if (cmd == CMD_UNPKGZ)
  184.                                 strcatmax(oname,"stdin.adz",FNAME_MAXC);
  185.                             else
  186.                                 strcatmax(oname,"stdin.adf",FNAME_MAXC);
  187.                         }
  188.  
  189.                     }
  190.                 }
  191.  
  192.                 onm = oname;
  193.             }
  194.             i++;
  195.         } else if (destdir && (strcmpnc("stdout",destdir)==0)) {
  196.             strcpy(oname,"");
  197.             onm = NULL;
  198.         } else {
  199.  
  200.             if (destdir)
  201.                 strcpymax(oname,destdir,FNAME_MAXC-1);
  202.             else
  203.                 strcpy(oname,"");
  204.  
  205.             if ((cmd == CMD_UNPACK) || (cmd == CMD_UNPKGZ)) {
  206.  
  207.                 if (strlen(oname)>0) {
  208.                     p = oname + strlen(oname) - 1;
  209.                     if (!strchr(DIR_SEPARATORS,*p)) {
  210.                         *(p+1) = DIR_CHAR;
  211.                         *(p+2) = '\0';
  212.                     }
  213.                 }
  214.  
  215.                 if (inm) {
  216.                     p = q = iname;
  217.                     while(*p) {
  218.                         if (strchr(DIR_SEPARATORS,*p)) q = p+1;
  219.                         p++;
  220.                     }
  221.                     strcatmax(oname,q,FNAME_MAXC);
  222.                     if ((strlen(oname)>4) && (strcmpnc(oname+strlen(oname)-4,".dms")==0)) {
  223.                         if (cmd == CMD_UNPKGZ)
  224.                             strcpy(oname+strlen(oname)-4,".adz");
  225.                         else
  226.                             strcpy(oname+strlen(oname)-4,".adf");
  227.                     } else {
  228.                         if (cmd == CMD_UNPKGZ)
  229.                             strcatmax(oname,".adz",FNAME_MAXC);
  230.                         else
  231.                             strcatmax(oname,".adf",FNAME_MAXC);
  232.                     }
  233.                 } else {
  234.                     if (cmd == CMD_UNPKGZ)
  235.                         strcatmax(oname,"stdin.adz",FNAME_MAXC);
  236.                     else
  237.                         strcatmax(oname,"stdin.adf",FNAME_MAXC);
  238.                 }
  239.  
  240.             }
  241.  
  242.             onm = oname;
  243.  
  244.         }
  245.  
  246.  
  247.  
  248.         if (opt == OPT_VERBOSE) {
  249.             if ((cmd == CMD_UNPACK)) {
  250.                 if (inm)
  251.                     fprintf(stderr,"Unpacking file %s to ",inm);
  252.                 else
  253.                     fprintf(stderr,"Unpacking data from stdin to ");
  254.                 if (onm)
  255.                     fprintf(stderr,"%s\n",onm);
  256.                 else
  257.                     fprintf(stderr,"stdout\n");
  258.             } else if ((cmd == CMD_EXTRACT) || (cmd == CMD_UNPKGZ)) {
  259.                 if (inm)
  260.                     fprintf(stderr,"Unpacking file %s\n",inm);
  261.                 else
  262.                     fprintf(stderr,"Unpacking data from stdin\n");
  263.             } else if (cmd == CMD_TEST) {
  264.                 if (inm)
  265.                     fprintf(stderr,"Testing file %s\n",inm);
  266.                 else
  267.                     fprintf(stderr,"Testing data from stdin\n");
  268.             } else if (cmd == CMD_SHOWDIZ) {
  269.                 if (inm)
  270.                     printf("Showing FILEID.DIZ in %s :\n",inm);
  271.                 else
  272.                     printf("Showing FILEID.DIZ in stdin :\n");
  273.             } else if (cmd == CMD_SHOWBANNER) {
  274.                 if (inm)
  275.                     printf("Showing Banner in %s :\n",inm);
  276.                 else
  277.                     printf("Showing Banner in stdin :\n");
  278.             }
  279.  
  280.         }
  281.  
  282.         #ifdef UNDER_DOS
  283.         if (!inm) setmode(fileno(stdin),O_BINARY);
  284.         if ((cmd == CMD_UNPACK) && (!onm)) setmode(fileno(stdout),O_BINARY);
  285.         #endif
  286.  
  287.         if ((cmd == CMD_UNPKGZ) || (cmd == CMD_EXTRACT)) {
  288.             tname = tmpnam(NULL);
  289.             #ifdef UNDER_DOS
  290.             p = tname;
  291.             if (p) {
  292.                 while (*p) {
  293.                     if (*p == '/') *p = '\\';
  294.                     p++;
  295.                 }
  296.             }
  297.             #endif
  298.             ret = Process_File(inm, tname, CMD_UNPACK, opt, PCRC, pwd);
  299.             if (opt != OPT_QUIET) ErrMsg(ret, inm, "Temporary file");
  300.             if (ret == NO_PROBLEM) {
  301.                 if (cmd == CMD_UNPKGZ) {
  302.                     if (opt == OPT_VERBOSE) {
  303.                         fprintf(stderr,"Repacking unpacked data with gzip\n");
  304.                     }
  305.                     if (onm)
  306.                         #ifdef UNDER_DOS
  307.                         /*  DOS sucks  */
  308.                         sprintf(cmdstr,"gzip -cfqn %s >%s",tname,onm);
  309.                         #else
  310.                         sprintf(cmdstr,"gzip -cfqn \"%s\" >\"%s\"",tname,onm);
  311.                         #endif
  312.                     else
  313.                         #ifdef UNDER_DOS
  314.                         sprintf(cmdstr,"gzip -cfqn %s",tname);
  315.                         #else
  316.                         sprintf(cmdstr,"gzip -cfqn \"%s\"",tname);
  317.                         #endif
  318.                     if (system(cmdstr)) ret = ERR_GZIP;
  319.                     if (opt != OPT_QUIET) ErrMsg(ret, inm, onm);
  320.                 } else {
  321.                     if (opt == OPT_VERBOSE) {
  322.                         fprintf(stderr,"Extracting files from unpacked data with readdisk\n");
  323.                     }
  324.                     if ((onm) && (strlen(onm)>0))
  325.                         #ifdef UNDER_DOS
  326.                         sprintf(cmdstr,"readdisk %s %s",tname,onm);
  327.                         #else
  328.                         sprintf(cmdstr,"readdisk \"%s\" \"%s\"",tname,onm);
  329.                         #endif
  330.                     else
  331.                         #ifdef UNDER_DOS
  332.                         sprintf(cmdstr,"readdisk %s",tname);
  333.                         #else
  334.                         sprintf(cmdstr,"readdisk \"%s\"",tname);
  335.                         #endif
  336.                     if (system(cmdstr)) ret = ERR_READDISK;
  337.                     if (opt != OPT_QUIET) ErrMsg(ret, inm, onm);
  338.                 }
  339.             }
  340.             remove(tname);
  341.         } else {
  342.             ret = Process_File(inm, onm, cmd, opt, PCRC, pwd);
  343.             if (opt != OPT_QUIET) ErrMsg(ret, inm, onm);
  344.         }
  345.  
  346.         if (ret != NO_PROBLEM) ext = EXIT_FAIL;
  347.  
  348.         if ((ret == NO_PROBLEM) && (opt != OPT_QUIET)) {
  349.             switch (cmd) {
  350.                 case CMD_UNPACK:
  351.                     if (inm)
  352.                         fprintf(stderr,"File %s was correctly unpacked to ",inm);
  353.                     else
  354.                         fprintf(stderr,"Data from stdin was correctly unpacked to ");
  355.                     if (onm)
  356.                         fprintf(stderr,"%s\n",onm);
  357.                     else
  358.                         fprintf(stderr,"stdout\n");
  359.                     break;
  360.                 case CMD_UNPKGZ:
  361.                     if (inm)
  362.                         fprintf(stderr,"File %s was correctly converted to ",inm);
  363.                     else
  364.                         fprintf(stderr,"Data from stdin was correctly converted to ");
  365.                     if (onm)
  366.                         fprintf(stderr,"%s\n",onm);
  367.                     else
  368.                         fprintf(stderr,"stdout\n");
  369.                     break;
  370.                 case CMD_EXTRACT:
  371.                     if (inm)
  372.                         fprintf(stderr,"The files were correctly extracted from %s\n",inm);
  373.                     else
  374.                         fprintf(stderr,"The files were correctly extracted from stdin\n");
  375.                     break;
  376.                 case CMD_TEST:
  377.                     if (inm)
  378.                         fprintf(stderr,"File %s is ok\n",inm);
  379.                     else
  380.                         fprintf(stderr,"Data from stdin is ok\n");
  381.                     break;
  382.                 default:
  383.                     break;
  384.             }
  385.         }
  386.  
  387.         if (opt != OPT_QUIET) fprintf(stderr,"\n");
  388.  
  389.     }
  390.  
  391.     exit((int)ext);
  392.  
  393. }
  394.  
  395.  
  396.  
  397. static int strcmpnc(char *s1, char *s2){
  398.     while (*s1 && (tolower(*s1)==tolower(*s2))) {s1++; s2++;}
  399.     return tolower(*s1)-tolower(*s2);
  400. }
  401.  
  402.  
  403.  
  404. static void strcpymax(char *s1, char *s2, int max){
  405.     if (strlen(s2)>max){
  406.         memcpy(s1,s2,max);
  407.         *(s1+max) = 0;
  408.     } else
  409.         strcpy(s1,s2);
  410. }
  411.  
  412.  
  413.  
  414. static void strcatmax(char *s1, char *s2, int max){
  415.     if (strlen(s1)+strlen(s2)>max){
  416.         memcpy(s1+strlen(s1),s2,max-strlen(s1));
  417.         *(s1+max) = 0;
  418.     } else
  419.         strcat(s1,s2);
  420. }
  421.  
  422.  
  423.  
  424. static void Usage(void){
  425.     printf("\n");
  426.     printf(" xDMS  v1.2  -  Portable DMS archive unpacker  -  Public Domain\n");
  427.     printf(" Written by     Andre R. de la Rocha  <adlroc@usa.net> \n\n");
  428.     printf(" Usage: xdms [options] <command> {<dms_file[.dms]> [+output]} \n\n");
  429.     printf(" Commands :\n");
  430.     printf("     t : Test DMS archives\n");
  431.     printf("     u : Unpack DMS archives to disk images\n");
  432.     printf("     z : Unpack to disk images and compress it with gzip\n");
  433.     printf("     x : Extract files inside DMS archives using readdisk\n");
  434.     printf("     v : View DMS archives information\n");
  435.     printf("     f : View full information\n");
  436.     printf("     d : Show attached FILEID.DIZ\n");
  437.     printf("     b : Show attached Banner\n\n");
  438.     printf(" Options :\n");
  439.     printf("    -q : Quiet\n");
  440.     printf("    -v : Verbose\n");
  441.     printf("    -d <destdir>  : Set destination directory\n");
  442.     printf("    -p <password> : Decrypt encrypted archives using password\n");
  443.     printf("\n");
  444. }
  445.  
  446.  
  447.  
  448. static void ErrMsg(USHORT err, char *i, char *o){
  449.  
  450.     if (!i) i = "stdin";
  451.     if (!o) o = "stdout";
  452.  
  453.     switch (err) {
  454.         case NO_PROBLEM:
  455.         case FILE_END:
  456.             return;
  457.         case ERR_NOMEMORY:
  458.             fprintf(stderr,"Not enough memory for buffers !\n");
  459.             break;
  460.         case ERR_CANTOPENIN:
  461.             fprintf(stderr,"Can't open %s for reading !\n",i);
  462.             break;
  463.         case ERR_CANTOPENOUT:
  464.             fprintf(stderr,"Can't open %s for writing !\n",o);
  465.             break;
  466.         case ERR_NOTDMS:
  467.             fprintf(stderr,"File %s is not a DMS archive !\n",i);
  468.             break;
  469.         case ERR_SREAD:
  470.             fprintf(stderr,"Error reading file %s : unexpected end of file !\n",i);
  471.             break;
  472.         case ERR_HCRC:
  473.             fprintf(stderr,"Error in file %s : header CRC error !\n",i);
  474.             break;
  475.         case ERR_NOTTRACK:
  476.             fprintf(stderr,"Error in file %s : track header not found !\n",i);
  477.             break;
  478.         case ERR_BIGTRACK:
  479.             fprintf(stderr,"Error in file %s : track too big !\n",i);
  480.             break;
  481.         case ERR_THCRC:
  482.             fprintf(stderr,"Error in file %s : track header CRC error !\n",i);
  483.             break;
  484.         case ERR_TDCRC:
  485.             fprintf(stderr,"Error in file %s : track data CRC error !\n",i);
  486.             break;
  487.         case ERR_CSUM:
  488.             fprintf(stderr,"Error in file %s : checksum error after unpacking !\n",i);
  489.             fprintf(stderr,"This file seems ok, but the unpacking failed.\n");
  490.             fprintf(stderr,"This can be caused by a bug in xDMS. Please contact the author\n");
  491.             break;
  492.         case ERR_CANTWRITE:
  493.             fprintf(stderr,"Error : can't write to file %s  !\n",o);
  494.             break;
  495.         case ERR_BADDECR:
  496.             fprintf(stderr,"Error in file %s : error unpacking !\n",i);
  497.             fprintf(stderr,"This file seems ok, but the unpacking failed.\n");
  498.             fprintf(stderr,"This can be caused by a bug in xDMS. Please contact the author\n");
  499.             break;
  500.         case ERR_UNKNMODE:
  501.             fprintf(stderr,"Error in file %s : unknown compression mode used !\n",i);
  502.             break;
  503.         case ERR_NOPASSWD:
  504.             fprintf(stderr,"Can't process file %s : file is encrypted !\n",i);
  505.             break;
  506.         case ERR_BADPASSWD:
  507.             fprintf(stderr,"Error unpacking file %s . The password is probably wrong.\n",i);
  508.             break;
  509.         case ERR_FMS:
  510.             fprintf(stderr,"Error in file %s : this file is not really a compressed disk image, but an FMS archive !\n",i);
  511.             break;
  512.         case ERR_GZIP:
  513.             fprintf(stderr,"Can't convert file %s : gzip failed !\n",i);
  514.             break;
  515.         case ERR_READDISK:
  516.             fprintf(stderr,"Can't extract files from %s : readdisk failed !\n",i);
  517.             break;
  518.         default:
  519.             fprintf(stderr,"Error while processing file  %s : internal error !\n",i);
  520.             fprintf(stderr,"This is a bug in xDMS\n");
  521.             fprintf(stderr,"Please contact the author\n");
  522.             break;
  523.     }
  524. }
  525.  
  526.  
  527.