Logo Search packages:      
Sourcecode: dctc version File versions  Download package

md_crc.c

/* DCTC - a Direct Connect text clone for Linux
 * Copyright (C) 2001 Eric Prevoteau
 *
 * md_crc.c: Copyright (C) Eric Prevoteau <www@a2pb.gotdns.org>
 *
 * This program 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 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
/*
$Id: md_crc.c,v 1.3 2003/12/28 08:12:38 uid68112 Exp $
*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <string.h>
#include <ctype.h>
#ifdef WITH_GCRYPT
#include <gcrypt.h>
#define MD4_DIGEST_LENGTH 16
#define MD4_ALGO(source,len,dest)   gcry_md_hash_buffer(GCRY_MD_MD4,dest,source,len)
#else
#include <openssl/md4.h>
#define MD4_ALGO MD4
#endif
#include <glib.h>

#include "md_crc.h"

#define MD_SIZE MD4_DIGEST_LENGTH

/***********************/
/* compute level 0 CRC */
/*************************************************************************/
/* input: adr= where the data to CRC are                                 */
/*        length= size of the data in adr                                */
/* output: if NULL, an error occurs                                      */
/*        else address of a m'allocated buffer of (*l0_crc_length) bytes */
/*************************************************************************/
guint8 *l0_crc(unsigned char *adr, size_t length, unsigned int *l0_crc_length)
{
      int i;
      int nb;
      guint8 *tmp_md;

      nb=(length+PARTSIZE-1)/PARTSIZE;

      /* size of the buffer to allocate */
      *l0_crc_length=nb*MD_SIZE;

      tmp_md=malloc(nb*MD_SIZE);
      if(tmp_md==NULL)
            return NULL;

      for(i=0;i<nb;i++)
      {
            unsigned char *start=adr+i*PARTSIZE;
            size_t cur_size=MIN((length-i*PARTSIZE),PARTSIZE);

            MD4_ALGO(start,cur_size,tmp_md+i*MD_SIZE);
      }

      return tmp_md;
}

/*************************************/
/* compute the ed2k of a memory bloc */
/**********************************************************************/
/* input: adr= where the data to CRC are                              */
/*        length= size of the data in adr                             */
/*        final_md= array of MD4_DIGEST_LENGTH bytes to store the CRC */
/* output: FALSE -> error                                             */
/*         TRUE -> final_md contains the CRC                          */
/**********************************************************************/
static gboolean build_md(unsigned char *adr, size_t length, unsigned char *final_md)
{
      guint8 *l0_md;
      unsigned int l0_size;

      l0_md=l0_crc(adr,length,&l0_size);
      if(l0_md==NULL)
            return FALSE;

      MD4_ALGO(l0_md,l0_size,final_md);
      free(l0_md);

      return TRUE;
}

/*******************************************/
/* check if the given file has a valid CRC */
/********************************************************/
/* input: filename= name of a file to compare           */
/*        crc_to_compare= an array of MD4_DIGEST_LENGTH */
/*                   bytes containing the CRC to verify */
/********************************************************/
/* output: 0= CRC is valid    */
/*         1= CRC is invalid  */
/*         2= an error occurs */
/******************************/
int is_a_file_with_a_valid_crc(const char *filename, guint8 *crc_to_compare)
{
      int fd;
      unsigned char *adr;
      size_t length;
      struct stat st;
      unsigned char md[MD_SIZE];

      fd=open(filename,O_RDONLY);
      if(fd==-1)
      {
            perror("is_a_file_with_a_valid_crc: open");
            return 2;
      }

      if(fstat(fd,&st)==-1)
      {
            perror("is_a_file_with_a_valid_crc: stat");
            close(fd);
            return 2;
      }

      if(!S_ISREG(st.st_mode))
      {
            perror("is_a_file_with_a_valid_crc: not a regular file");
            close(fd);
            return 2;
      }

      length=st.st_size;
      if(length==0)
      {
            perror("is_a_file_with_a_valid_crc: empty file");
            close(fd);
            return 2;
      }

      adr=mmap(NULL,length,PROT_READ,MAP_SHARED,fd,0);
      if(adr==MAP_FAILED)
      {
            perror("is_a_file_with_a_valid_crc: mmap");
            close(fd);
            return 2;
      }

      close(fd);

      /* compute the CRC */
      if(build_md(adr,length,md)==FALSE)
      {
            munmap(adr,length);
            return 2;
      }

      if(memcmp(md,crc_to_compare,MD4_DIGEST_LENGTH))
      {
            munmap(adr,length);
            return 1;
      }
      munmap(adr,length);
      return 0;
}

/******************************/
/* compute the CRCs of a file */
/********************************************************/
/* input: filename= name of a file to compare           */
/*        g_crc=an array of MD4_DIGEST_LENGTH bytes     */
/********************************************************/
/* output: 0= CRC is valid                             */
/*         2= an error occurs                          */
/* on success, *l0_md is allocated and contains L0 CRC */
/* and *length is set to the file size                 */
/*******************************************************/
int compute_file_crcs(const char *filename, guint8 *g_crc, guint8 **l0_md, size_t *length)
{
      int fd;
      unsigned char *adr;
      struct stat st;
      unsigned int l0_size;

      fd=open(filename,O_RDONLY);
      if(fd==-1)
      {
            perror("compute_file_crcs: open");
            return 2;
      }

      if(fstat(fd,&st)==-1)
      {
            perror("compute_file_crcs: stat");
            close(fd);
            return 2;
      }

      if(!S_ISREG(st.st_mode))
      {
            perror("compute_file_crcs: not a regular file");
            close(fd);
            return 2;
      }

      (*length)=st.st_size;
      if((*length)==0)
      {
            perror("compute_file_crcs: empty file");
            close(fd);
            return 2;
      }

      adr=mmap(NULL,(*length),PROT_READ,MAP_SHARED,fd,0);
      if(adr==MAP_FAILED)
      {
            perror("compute_file_crcs: mmap");
            close(fd);
            return 2;
      }

      close(fd);

      /* compute the CRC */
      *l0_md=l0_crc(adr,(*length),&l0_size);
      if(*l0_md==NULL)
      {
            munmap(adr,(*length));
            return 2;
      }

      MD4_ALGO(*l0_md,l0_size,g_crc);

      munmap(adr,(*length));
      return 0;
}

/*************************************************************/
/* append the ASCII version of MD4 CRC to the given g_string */
/*************************************************************/
void append_MD4_to_str(GString *dest_base, guint8 *id)
{
      int i;

      for(i=0;i<MD4_DIGEST_LENGTH;i++)
      {
            g_string_sprintfa(dest_base,"%02X",((unsigned int)(id[i]))&255);
      }
}

/*
-------------------------
-------------------------
*/

static guint8 ascii1_to_hex(unsigned char v)
{
      if((v>='0')&&(v<='9'))
            return v-'0';
      else
            return toupper(v)-'A'+10;
}

/******************************************/
/* convert 2 ascii hexdigit into 1 guint8 */
/******************************************/
static guint8 ascii2_to_bin1(unsigned char *asc)
{
      return ((ascii1_to_hex(asc[0]))<<4)|(ascii1_to_hex(asc[1]));
}

/*********************************************************************/
/* convert a MD_SIZE ID from its ascii version to its binary version */
/*********************************************************************/
void id_ascii_to_bin(unsigned char *asc_id, guint8 *bin_id)
{
      int i;

      for(i=0;i<MD_SIZE;i++)
      {
            bin_id[i]=ascii2_to_bin1(asc_id+2*i);
      }
}


Generated by  Doxygen 1.6.0   Back to index