73b02a4a2c
Solves FS#9539 Change-Id: I5278fa0fbb8347314ef6fb41e707b3832f1dd8cd
277 lines
7.5 KiB
C
277 lines
7.5 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2008 Antoine Cellerier <dionoea -at- videolan -dot- 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "plugin.h"
|
|
#include "lib/md5.h"
|
|
|
|
|
|
|
|
#define BUFFERSIZE 16384
|
|
|
|
static int count = 0;
|
|
static int done = 0;
|
|
static bool quit = false;
|
|
|
|
static int hash( char *string, const char *path )
|
|
{
|
|
static char buffer[BUFFERSIZE];
|
|
ssize_t len;
|
|
struct md5_s md5;
|
|
int in = rb->open( path, O_RDONLY );
|
|
if( in < 0 ) return -1;
|
|
|
|
InitMD5( &md5 );
|
|
while( !quit && ( len = rb->read( in, buffer, sizeof(buffer) ) ) > 0 )
|
|
{
|
|
AddMD5( &md5, buffer, len );
|
|
|
|
if( rb->get_action(CONTEXT_STD, TIMEOUT_NOBLOCK) == ACTION_STD_CANCEL )
|
|
quit = true;
|
|
}
|
|
|
|
EndMD5( &md5 );
|
|
|
|
psz_md5_hash( string, &md5 );
|
|
|
|
rb->close( in );
|
|
return 0;
|
|
}
|
|
|
|
static void hash_file( int out, const char *path )
|
|
{
|
|
if( out < 0 )
|
|
count++;
|
|
else
|
|
{
|
|
char string[MD5_STRING_LENGTH+1];
|
|
int status;
|
|
done++;
|
|
rb->splashf( 0, "%d / %d : %s", done, count, path );
|
|
status = hash( string, path );
|
|
|
|
if( quit )
|
|
return;
|
|
|
|
if( status )
|
|
rb->write( out, "error", 5 );
|
|
else
|
|
rb->write( out, string, MD5_STRING_LENGTH );
|
|
rb->write( out, " ", 2 );
|
|
rb->write( out, path, rb->strlen( path ) );
|
|
rb->write( out, "\n", 1 );
|
|
|
|
rb->yield();
|
|
}
|
|
}
|
|
|
|
static void hash_dir( int out, const char *path )
|
|
{
|
|
DIR *dir;
|
|
struct dirent *entry;
|
|
|
|
dir = rb->opendir( path );
|
|
if( dir )
|
|
{
|
|
while( !quit && ( entry = rb->readdir( dir ) ) )
|
|
{
|
|
char childpath[MAX_PATH];
|
|
rb->snprintf( childpath, MAX_PATH, "%s/%s",
|
|
rb->strcmp( path, "/" ) ? path : "", entry->d_name );
|
|
|
|
struct dirinfo info = rb->dir_get_info(dir, entry);
|
|
if (info.attribute & ATTR_DIRECTORY)
|
|
{
|
|
if( rb->strcmp( entry->d_name, "." )
|
|
&& rb->strcmp( entry->d_name, ".." ) )
|
|
{
|
|
/* Got a sub directory */
|
|
hash_dir( out, childpath );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Got a file */
|
|
hash_file( out, childpath );
|
|
}
|
|
}
|
|
rb->closedir( dir );
|
|
}
|
|
}
|
|
|
|
static void hash_list( int out, const char *path )
|
|
{
|
|
int list = rb->open( path, O_RDONLY );
|
|
char newpath[MAX_PATH];
|
|
if( list < 0 ) return;
|
|
|
|
while( !quit && rb->read_line( list, newpath, MAX_PATH ) > 0 )
|
|
{
|
|
DIR *dir = rb->opendir( newpath );
|
|
if( dir )
|
|
{
|
|
rb->closedir( dir );
|
|
hash_dir( out, newpath );
|
|
}
|
|
else
|
|
{
|
|
hash_file( out, newpath );
|
|
}
|
|
}
|
|
|
|
rb->close( list );
|
|
}
|
|
|
|
static void hash_check( int out, const char *path )
|
|
{
|
|
int list = rb->open( path, O_RDONLY );
|
|
char line[MD5_STRING_LENGTH+1+MAX_PATH+1];
|
|
int len;
|
|
if( list < 0 ) return;
|
|
|
|
while( !quit && ( len = rb->read_line( list, line, MD5_STRING_LENGTH+1+MAX_PATH+1 ) ) > 0 )
|
|
{
|
|
if( out < 0 )
|
|
count++;
|
|
else
|
|
{
|
|
const char *filename = rb->strchr( line, ' ' );
|
|
done++;
|
|
rb->splashf( 0, "%d / %d : %s", done, count, filename );
|
|
if( !filename || len < MD5_STRING_LENGTH + 2 )
|
|
{
|
|
const char error[] = "Malformed input line ... skipping";
|
|
rb->write( out, error, rb->strlen( error ) );
|
|
}
|
|
else
|
|
{
|
|
char string[MD5_STRING_LENGTH+1];
|
|
while( *filename == ' ' )
|
|
filename++;
|
|
rb->write( out, filename, rb->strlen( filename ) );
|
|
rb->write( out, ": ", 2 );
|
|
if( hash( string, filename ) )
|
|
rb->write( out, "FAILED open or read", 19 );
|
|
else if( rb->strncasecmp( line, string, MD5_STRING_LENGTH ) )
|
|
rb->write( out, "FAILED", 6 );
|
|
else
|
|
rb->write( out, "OK", 2 );
|
|
}
|
|
rb->write( out, "\n", 1 );
|
|
}
|
|
}
|
|
|
|
rb->close( list );
|
|
}
|
|
|
|
enum plugin_status plugin_start(const void* parameter)
|
|
{
|
|
const char *arg = (const char *)parameter; /* input file path, if any */
|
|
char temp[MAX_PATH]; /* input file name */
|
|
char *basename=temp;
|
|
int out = -1; /* output file descriptor */
|
|
char filename[MAX_PATH]; /* output file name */
|
|
int isdir=0; /*flag if input file is a directory */
|
|
|
|
void (*action)( int, const char * ) = NULL;
|
|
|
|
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
|
rb->cpu_boost( true );
|
|
#endif
|
|
|
|
if( arg && *arg )
|
|
{
|
|
const char *ext = rb->strrchr( arg, '.' );
|
|
DIR *dir;
|
|
rb->snprintf( filename, MAX_PATH, "%s.md5sum", arg );
|
|
|
|
if( ext )
|
|
{
|
|
if( !rb->strcmp( ext, ".md5" ) || !rb->strcmp( ext, ".md5sum" ) )
|
|
{
|
|
rb->snprintf( filename + ( ext - arg ),
|
|
MAX_PATH + rb->strlen( ext ) - rb->strlen( arg ),
|
|
".md5check" );
|
|
/* Lets check the sums */
|
|
action = hash_check;
|
|
}
|
|
else if( !rb->strcmp( ext, ".md5list" ) ) /* ugly */
|
|
{
|
|
/* Hash listed files */
|
|
action = hash_list;
|
|
}
|
|
}
|
|
|
|
if( !action )
|
|
{
|
|
dir = rb->opendir( arg );
|
|
if( dir )
|
|
{
|
|
rb->closedir( dir );
|
|
|
|
/* Hash the directory's content recursively */
|
|
action = hash_dir;
|
|
}
|
|
else
|
|
{
|
|
/* Hash the file */
|
|
action = hash_file;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rb->snprintf( filename, MAX_PATH, "/everything.md5sum" );
|
|
/* Hash the whole filesystem */
|
|
action = hash_dir;
|
|
arg = "/";
|
|
}
|
|
rb->strcpy(temp, arg);
|
|
if (temp[(rb->strlen(temp) - 1)] == '/')
|
|
{
|
|
temp[(rb->strlen(temp) - 1)] = '\0';
|
|
isdir=1;
|
|
}
|
|
if(rb->strrchr(temp, '/'))
|
|
basename =(rb->strrchr(temp, '/')+1);
|
|
|
|
if(isdir)
|
|
temp[(rb->strlen(temp))] = '/';
|
|
|
|
rb->lcd_putsf( 0, 1, "Hashing %s", basename );
|
|
rb->lcd_puts( 0, 2, rb->str(LANG_ACTION_STD_CANCEL) );
|
|
|
|
rb->lcd_puts( 0, 3, "Output file:" );
|
|
rb->lcd_puts( 0, 4, filename );
|
|
|
|
rb->lcd_update();
|
|
count = 0;
|
|
done = 0;
|
|
action( out, arg );
|
|
|
|
out = rb->open( filename, O_WRONLY|O_CREAT|O_TRUNC , 0666);
|
|
if( out < 0 ) return PLUGIN_ERROR;
|
|
action( out, arg );
|
|
rb->close( out );
|
|
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
|
rb->cpu_boost( false );
|
|
#endif
|
|
return PLUGIN_OK;
|
|
}
|