#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#if defined linux
#include <linux/cdrom.h>
#elif defined sun
#include <sys/cdio.h>
#endif
typedef struct {
int minutos, segundos;
} TRACK_DATA;
typedef struct {
unsigned char FirstTrack;
unsigned char LastTrack;
TRACK_DATA TrackData[100];
} CDROM_TOC;
/*
Funcion:
lee_CDTOC
Parámetros:
sDispositivo: ruta del dispositivo de CD.
toc: estructura donde se almancena la tabla de contenidos del CD.
Descripción:
Esta función se encarga de guardar en la variable toc la información de la tabla de contenidos del CD ubicado en el dispostivo lector de cdrom.
*/
void lee_CDTOC(char *sDispositivo,CDROM_TOC *toc)
{
struct cdrom_tochdr tochdr;
struct cdrom_tocentry tocentry;
int nIndice, manejador;
manejador= open(sDispositivo, O_RDONLY | O_NONBLOCK);
if(manejador == -1)
{
fprintf(stderr,"No se pudo acceder al disco de la unidad de CD\n");
return;
}
if (ioctl(manejador, CDROMREADTOCHDR, &tochdr) == -1)
fprintf(stderr,"No se pudo leer el contenido del CD\n");
else
{
toc->FirstTrack=tochdr.cdth_trk0;
toc->LastTrack=tochdr.cdth_trk1;
for (nIndice = toc->FirstTrack; nIndice <= toc->LastTrack; nIndice++)
{
tocentry.cdte_track = nIndice;
tocentry.cdte_format = CDROM_MSF;
ioctl(manejador, CDROMREADTOCENTRY, &tocentry);
toc->TrackData[nIndice-1].minutos = tocentry.cdte_addr.msf.minute;
toc->TrackData[nIndice-1].segundos = tocentry.cdte_addr.msf.second;
}
tocentry.cdte_track = 0xAA;
tocentry.cdte_format = CDROM_MSF;
ioctl(manejador, CDROMREADTOCENTRY, &tocentry);
toc->TrackData[toc->LastTrack].minutos = tocentry.cdte_addr.msf.minute;
toc->TrackData[toc->LastTrack].segundos = tocentry.cdte_addr.msf.second;
}
close(manejador);
}
/*
Funcion:
lee_InfoCDDB: Devuelve una cadena con los resultados de la petición.
Parámetros:
sIDDisco: identificador único del cd.
sBuffer: buffer donde almacenar los resultados de la petición.
Descripción:
Esta función se encarga de pedir a freedb la información relacionada con un identificador de cd determinado y devolver todo el contenido de la petición.
*/
char *lee_InfoCDDB(char *sIDDisco,char *sBuffer)
{
int sock;
struct hostent *servidor;
struct sockaddr_in destino;
char sPeticion[256];
int nEnviados,nRecibidos;
if((sock=socket(PF_INET,SOCK_STREAM,0)) == -1)
fprintf(stderr,"No se pudo crear la conexion");
else
{
if((servidor=gethostbyname("freedb.freedb.org"))==NULL)
fprintf(stderr,"No se pudo obtener la IP del servidor");
else
{
destino.sin_family = AF_INET;
destino.sin_port = htons(80);
destino.sin_addr = *((struct in_addr *)servidor->h_addr_list[0]);
memset(&(destino.sin_zero), '', 8);
if(connect(sock, (struct sockaddr *)&destino, sizeof(struct sockaddr)) == -1)
fprintf(stderr,"No se pudo conectar al servidor");
else
{
sprintf(sPeticion,"GET /~cddb/cddb.cgi?cmd=cddb+read+misc+%s&hello=sistemasorp+sistemasorp.blogspot.com+testeoCDDB+1.0&proto=1 HTTP/1.0\r\n",sIDDisco);
strcat(sPeticion,"Host: freedb.freedb.org\r\n\r\n");
nEnviados=send(sock,sPeticion,strlen(sPeticion),0);
if(nEnviados == -1)
fprintf(stderr,"No se pudo enviar la peticion al servidor");
nRecibidos=0;
while(strstr(sBuffer,"\r\n.\r\n") == NULL)
{
nRecibidos+=recv(sock,sBuffer+nRecibidos,1024,0);
sBuffer[nRecibidos]='';
}
}
}
}
return sBuffer;
}
/*
Funcion:
cddb_Suma: Devuelve un número sacado a través de una suma de cifras.
Parámetros:
nDuracion: Duración en segundos de una pista.
Descripción:
Esta función se encarga de sumar todas las cifras de distinto peso entre si para posteriormente devolver el resultado.
*/
int cddb_Suma(int nDuracion)
{
int nSuma = 0;
while (nDuracion > 0) {
nSuma = nSuma + (nDuracion % 10);
nDuracion = nDuracion / 10;
}
return nSuma;
}
/*
Funcion:
cddb_IDDisco: Devuelve en número que identifica al CD inequivocamente.
Parámetros:
toc: Información de la tabla de contenidos del CD
Descripción:
Esta función se encarga de calcular el identificador único de un CD a través de su tabla de contenidos
*/
unsigned long cddb_IDDisco(CDROM_TOC *toc)
{
int nIndice=0,
nTotalTiempo = 0,
nSumatorio = 0;
int nTotalPistas;
nTotalPistas=toc->LastTrack-toc->FirstTrack+1;
while (nIndice < nTotalPistas) {
nSumatorio = nSumatorio + cddb_Suma((toc->TrackData[nIndice].minutos * 60) + toc->TrackData[nIndice].segundos);
nIndice++;
}
nTotalTiempo = ((toc->TrackData[toc->LastTrack].minutos* 60) + toc->TrackData[toc->LastTrack].segundos) -
((toc->TrackData[0].minutos * 60) + toc->TrackData[0].segundos);
return ((nSumatorio % 0xff) << 24 | nTotalTiempo << 8 | nTotalPistas);
}
int main(int argc, char *argv[ ])
{
CDROM_TOC toc;
char sIDDisco[9];
char *sBuffer;
if(argc==2)
{
memset(&toc,0,sizeof(CDROM_TOC));
lee_CDTOC(argv[1],&toc);
if(toc.LastTrack>0)
{
sprintf(sIDDisco,"%08x",cddb_IDDisco(&toc));
printf("El ID del disco es %s\n",sIDDisco);
sBuffer=(char *)malloc(4096);
if(sBuffer == NULL)
{
fprintf(stderr,"No se pudo alojar memoria");
return 1;
}
*sBuffer='';
lee_InfoCDDB(sIDDisco,sBuffer);
if(*sBuffer=='')
return 1;
printf("La información del disco es:\n%s",sBuffer);
free(sBuffer);
}
else
return 1;
}
else
{
fprintf(stderr,"La sintaxis es: %s <dispositivo de cd>\nEjemplo: %s /dev/cdrom\n",argv[0],argv[0]);
return 1;
}
return 0;
}