vmd5sum.c
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:9k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /* ====================================================================
  2.  * The Vovida Software License, Version 1.0 
  3.  * 
  4.  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in
  15.  *    the documentation and/or other materials provided with the
  16.  *    distribution.
  17.  * 
  18.  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
  19.  *    and "Vovida Open Communication Application Library (VOCAL)" must
  20.  *    not be used to endorse or promote products derived from this
  21.  *    software without prior written permission. For written
  22.  *    permission, please contact vocal@vovida.org.
  23.  *
  24.  * 4. Products derived from this software may not be called "VOCAL", nor
  25.  *    may "VOCAL" appear in their name, without prior written
  26.  *    permission of Vovida Networks, Inc.
  27.  * 
  28.  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
  29.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
  31.  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
  32.  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
  33.  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
  34.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  35.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  36.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  37.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  38.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  39.  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  40.  * DAMAGE.
  41.  * 
  42.  * ====================================================================
  43.  * 
  44.  * This software consists of voluntary contributions made by Vovida
  45.  * Networks, Inc. and many individuals on behalf of Vovida Networks,
  46.  * Inc.  For more information on Vovida Networks, Inc., please see
  47.  * <http://www.vovida.org/>.
  48.  *
  49.  */
  50. static const char* const vmd5sum_c_Version =
  51.     "$Id: vmd5sum.c,v 1.1 2001/03/26 10:35:31 icahoon Exp $";
  52. /*
  53.  * md5sum.c - Generate/check MD5 Message Digests
  54.  *
  55.  * Compile and link with md5.c.  If you don't have getopt() in your library
  56.  * also include getopt.c.  For MSDOS you can also link with the wildcard
  57.  * initialization function (wildargs.obj for Turbo C and setargv.obj for MSC)
  58.  * so that you can use wildcards on the commandline.
  59.  *
  60.  * Written March 1993 by Branko Lankester
  61.  * Modified June 1993 by Colin Plumb for altered md5.c.
  62.  * Modified Feburary 1995 by Ian Jackson for use with Colin Plumb's md5.c.
  63.  * Hacked (modified is too nice a word) January 1997 by Galen Hazelwood
  64.  *   to support GNU gettext.
  65.  * This file is in the public domain.
  66.  */
  67. #include <stdlib.h>
  68. #include <stdio.h>
  69. #include <string.h>
  70. #ifdef __linux__
  71. #include <getopt.h>
  72. #endif
  73. /* #include "config.h" */
  74. #include "vmd5.h"
  75. /* Take care of NLS matters.  */
  76. #if HAVE_LOCALE_H
  77. # include < locale.h > 
  78. #endif
  79. #if !HAVE_SETLOCALE
  80. # define setlocale(Category, Locale) /* empty */
  81. #endif
  82. #if ENABLE_NLS
  83. # include < libintl.h > 
  84. # define _(Text) gettext (Text)
  85. #else
  86. # undef bindtextdomain
  87. # define bindtextdomain(Domain, Directory) /* empty */
  88. # undef textdomain
  89. # define textdomain(Domain) /* empty */
  90. # define _(Text) Text
  91. #endif
  92. #ifdef UNIX
  93. #define FOPRTXT "r"
  94. #define FOPRBIN "r"
  95. #else
  96. #ifdef VMS
  97. #define FOPRTXT "r","ctx=stm"
  98. #define FOPRBIN "rb","ctx=stm"
  99. #else
  100. #define FOPRTXT "r"
  101. #define FOPRBIN "rb"
  102. #endif
  103. #endif
  104. extern char *optarg;
  105. extern int optind;
  106. void usage(void);
  107. void print_digest(unsigned char *p);
  108. int mdfile(FILE *fp, unsigned char *digest);
  109. int do_check(FILE *chkf);
  110. int hex_digit(int c);
  111. int get_md5_line(FILE *fp, unsigned char *digest, char *file);
  112. char *progname;
  113. int verbose = 0;
  114. int bin_mode = 0;
  115. void
  116. main(int argc, char **argv)
  117. {
  118.     int opt, rc = 0;
  119.     int check = 0;
  120.     FILE *fp = NULL;
  121.     unsigned char digest[16];
  122.     setlocale(LC_ALL, "");
  123.     bindtextdomain(PACKAGE, LOCALEDIR);
  124.     textdomain(PACKAGE);
  125.     progname = *argv;
  126.     while ((opt = getopt(argc, argv, "cbvp:h")) != EOF)
  127.     {
  128.         switch (opt)
  129.         {
  130.             case 'c':
  131.             check = 1;
  132.             break;
  133.             case 'v':
  134.             verbose = 1;
  135.             break;
  136.             case 'b':
  137.             bin_mode = 1;
  138.             break;
  139.             default:
  140.             usage();
  141.         }
  142.     }
  143.     argc -= optind;
  144.     argv += optind;
  145.     if (check)
  146.     {
  147.         switch (argc)
  148.         {
  149.             case 0:
  150.             fp = stdin;
  151.             break;
  152.             case 1:
  153.             if ((fp = fopen(*argv, FOPRTXT)) == NULL)
  154.             {
  155.                 perror(*argv);
  156.                 exit(2);
  157.             }
  158.             break;
  159.             default:
  160.             usage();
  161.         }
  162.         exit(do_check(fp));
  163.     }
  164.     if (argc == 0)
  165.     {
  166.         if (mdfile(stdin, digest))
  167.         {
  168.             fprintf(stderr, _("%s: read error on stdinn"), progname);
  169.             exit(2);
  170.         }
  171.         print_digest(digest);
  172.         printf("n");
  173.         exit(0);
  174.     }
  175.     for ( ; argc > 0; --argc, ++argv)
  176.     {
  177.         if (bin_mode)
  178.             fp = fopen(*argv, FOPRBIN);
  179.         else
  180.             fp = fopen(*argv, FOPRTXT);
  181.         if (fp == NULL)
  182.         {
  183.             perror(*argv);
  184.             rc = 2;
  185.             continue;
  186.         }
  187.         if (mdfile(fp, digest))
  188.         {
  189.             fprintf(stderr, _("%s: error reading %sn"), progname, *argv);
  190.             rc = 2;
  191.         }
  192.         else
  193.         {
  194.             print_digest(digest);
  195.             printf(" %c%sn", bin_mode ? '*' : ' ', *argv);
  196.         }
  197.         fclose(fp);
  198.     }
  199.     exit(rc);
  200. }
  201. void
  202. usage()
  203. {
  204.     fputs(_("usage: md5sum [-bv] [-c [file]] | [file...]n
  205.     Generates or checks MD5 Message Digestsn
  206.     -c  check message digests (default is generate)n
  207.     -v  verbose, print file names when checkingn
  208.     -b  read files in binary moden
  209.     The input for -c should be the list of message digests and file namesn
  210.     that is printed on stdout by this program when it generates digests.n"), stderr);
  211.     exit(2);
  212. }
  213. int
  214. mdfile(FILE *fp, unsigned char *digest)
  215. {
  216.     unsigned char buf[1024];
  217.     struct MD5Context ctx;
  218.     int n;
  219.     MD5Init(&ctx);
  220.     while ((n = fread(buf, 1, sizeof(buf), fp)) > 0)
  221.         MD5Update(&ctx, buf, n);
  222.     MD5Final(digest, &ctx);
  223.     if (ferror(fp))
  224.         return -1;
  225.     return 0;
  226. }
  227. void
  228. print_digest(unsigned char *p)
  229. {
  230.     int i;
  231.     for (i = 0; i < 16; ++i)
  232.         printf("%02x", *p++);
  233. }
  234. int
  235. hex_digit(int c)
  236. {
  237.     if (c >= '0' && c <= '9')
  238.         return c - '0';
  239.     if (c >= 'a' && c <= 'f')
  240.         return c - 'a' + 10;
  241.     return -1;
  242. }
  243. int
  244. get_md5_line(FILE *fp, unsigned char *digest, char *file)
  245. {
  246.     char buf[1024];
  247.     int i, d1, d2, rc;
  248.     char *p = buf;
  249.     if (fgets(buf, sizeof(buf), fp) == NULL)
  250.         return -1;
  251.     for (i = 0; i < 16; ++i)
  252.     {
  253.         if ((d1 = hex_digit(*p++)) == -1)
  254.             return 0;
  255.         if ((d2 = hex_digit(*p++)) == -1)
  256.             return 0;
  257.         *digest++ = d1 * 16 + d2;
  258.     }
  259.     if (*p++ != ' ')
  260.         return 0;
  261.     /*
  262.      * next char is an attribute char, space means text file
  263.      * if it's a '*' the file should be checked in binary mode.
  264.      */
  265.     if (*p == ' ')
  266.         rc = 1;
  267.     else if (*p == '*')
  268.         rc = 2;
  269.     else
  270.     {
  271.         fprintf(stderr, _("%s: unrecognized line: %s"), progname, buf);
  272.         return 0;
  273.     }
  274.     ++p;
  275.     i = strlen(p);
  276.     if (i < 2 || i > 255)
  277.         return 0;
  278.     p[i - 1] = '';
  279.     strcpy(file, p);
  280.     return rc;
  281. }
  282. int
  283. do_check(FILE *chkf)
  284. {
  285.     int rc, ex = 0, failed = 0, checked = 0;
  286.     unsigned char chk_digest[16], file_digest[16];
  287.     char filename[256];
  288.     FILE *fp;
  289.     int flen = 14;
  290.     while ((rc = get_md5_line(chkf, chk_digest, filename)) >= 0)
  291.     {
  292.         if (rc == 0) /* not an md5 line */
  293.             continue;
  294.         if (verbose)
  295.         {
  296.             if (strlen(filename) > flen)
  297.                 flen = strlen(filename);
  298.             fprintf(stderr, "%-*s ", flen, filename);
  299.         }
  300.         if (bin_mode || rc == 2)
  301.             fp = fopen(filename, FOPRBIN);
  302.         else
  303.             fp = fopen(filename, FOPRTXT);
  304.         if (fp == NULL)
  305.         {
  306.             fprintf(stderr, _("%s: can't open %sn"), progname, filename);
  307.             ex = 2;
  308.             continue;
  309.         }
  310.         if (mdfile(fp, file_digest))
  311.         {
  312.             fprintf(stderr, _("%s: error reading %sn"), progname, filename);
  313.             ex = 2;
  314.             fclose(fp);
  315.             continue;
  316.         }
  317.         fclose(fp);
  318.         if (memcmp(chk_digest, file_digest, 16) != 0)
  319.         {
  320.             if (verbose)
  321.                 fprintf(stderr, _("FAILEDn"));
  322.             else
  323.                 fprintf(stderr, _("%s: MD5 check failed for '%s'n"), progname, filename);
  324.             ++failed;
  325.         }
  326.         else if (verbose)
  327.             fprintf(stderr, _("OKn"));
  328.         ++checked;
  329.     }
  330.     if (verbose && failed)
  331.         fprintf(stderr, _("%s: %d of %d file(s) failed MD5 checkn"), progname, failed, checked);
  332.     if (!checked)
  333.     {
  334.         fprintf(stderr, _("%s: no files checkedn"), progname);
  335.         return 3;
  336.     }
  337.     if (!ex && failed)
  338.         ex = 1;
  339.     return ex;
  340. }