summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntoine Cellerier <dionoea@videolan.org>2008-06-10 13:20:05 +0000
committerAntoine Cellerier <dionoea@videolan.org>2008-06-10 13:20:05 +0000
commit34d4165f7b8a36419c417f164ccdebbe04808247 (patch)
tree236281d7a79b46322564ba0506b0178e864a9291
parentf52696ef8a6e46b8379a0b2bc3d0661df3f9312e (diff)
downloadrockbox-34d4165f7b8a36419c417f164ccdebbe04808247.tar.gz
rockbox-34d4165f7b8a36419c417f164ccdebbe04808247.zip
New md5sum plugin. Open a file, a directory or just launch it from the plugin menu to create an md5sum of the file, the directory's contents or the whole filesystem. If the file's extension is .md5 or .md5sum, it will check the md5 sums in the file instead. If the file's extension is .md5list it will compute md5 sums for all the files listed.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17709 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/CATEGORIES1
-rw-r--r--apps/plugins/SOURCES2
-rw-r--r--apps/plugins/lib/SOURCES1
-rw-r--r--apps/plugins/lib/md5.c255
-rw-r--r--apps/plugins/lib/md5.h56
-rw-r--r--apps/plugins/md5sum.c206
-rw-r--r--apps/plugins/viewers.config1
7 files changed, 522 insertions, 0 deletions
diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES
index 6992ca3ca1..337704dfa3 100644
--- a/apps/plugins/CATEGORIES
+++ b/apps/plugins/CATEGORIES
@@ -99,3 +99,4 @@ wormlet,games
99xobox,games 99xobox,games
100zxbox,viewers 100zxbox,viewers
101lamp,apps 101lamp,apps
102md5sum,apps
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index 86d7055db2..0be7ccfaa8 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -150,3 +150,5 @@ invadrox.c
150superdom.c 150superdom.c
151#endif 151#endif
152#endif /* m:robe 500 */ 152#endif /* m:robe 500 */
153
154md5sum.c
diff --git a/apps/plugins/lib/SOURCES b/apps/plugins/lib/SOURCES
index c5c3a25e26..775db0587e 100644
--- a/apps/plugins/lib/SOURCES
+++ b/apps/plugins/lib/SOURCES
@@ -42,3 +42,4 @@ helper.c
42#ifdef HAVE_TOUCHPAD 42#ifdef HAVE_TOUCHPAD
43touchscreen.c 43touchscreen.c
44#endif 44#endif
45md5.c
diff --git a/apps/plugins/lib/md5.c b/apps/plugins/lib/md5.c
new file mode 100644
index 0000000000..97156634e5
--- /dev/null
+++ b/apps/plugins/lib/md5.c
@@ -0,0 +1,255 @@
1/*****************************************************************************
2 * md5.c: not so strong MD5 hashing
3 *****************************************************************************
4 * Copyright (C) 2004-2005 the VideoLAN team
5 * $Id: cb57f7b6522df0960a924193cfca438c03a92521 $
6 *
7 * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8 * Sam Hocevar <sam@zoy.org>
9 *
10 * Adapted to Rockbox by: Antoine Cellerier <dionoea at videolan dot org>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
26
27#include "plugin.h"
28#include "md5.h"
29
30static const struct plugin_api *rb;
31
32void md5_init( const struct plugin_api *api )
33{
34 rb = api;
35}
36
37#ifdef WORDS_BIGENDIAN
38/*****************************************************************************
39 * Reverse: reverse byte order
40 *****************************************************************************/
41static inline void Reverse( uint32_t *p_buffer, int n )
42{
43 int i;
44
45 for( i = 0; i < n; i++ )
46 {
47 p_buffer[ i ] = GetDWLE(&p_buffer[ i ]);
48 }
49}
50# define REVERSE( p, n ) Reverse( p, n )
51#else
52# define REVERSE( p, n )
53#endif
54
55#define F1( x, y, z ) ((z) ^ ((x) & ((y) ^ (z))))
56#define F2( x, y, z ) F1((z), (x), (y))
57#define F3( x, y, z ) ((x) ^ (y) ^ (z))
58#define F4( x, y, z ) ((y) ^ ((x) | ~(z)))
59
60#define MD5_DO( f, w, x, y, z, data, s ) \
61 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
62
63/*****************************************************************************
64 * DigestMD5: update the MD5 digest with 64 bytes of data
65 *****************************************************************************/
66static void DigestMD5( struct md5_s *p_md5, uint32_t *p_input )
67{
68 uint32_t a, b, c, d;
69
70 REVERSE( p_input, 16 );
71
72 a = p_md5->p_digest[ 0 ];
73 b = p_md5->p_digest[ 1 ];
74 c = p_md5->p_digest[ 2 ];
75 d = p_md5->p_digest[ 3 ];
76
77 MD5_DO( F1, a, b, c, d, p_input[ 0 ] + 0xd76aa478, 7 );
78 MD5_DO( F1, d, a, b, c, p_input[ 1 ] + 0xe8c7b756, 12 );
79 MD5_DO( F1, c, d, a, b, p_input[ 2 ] + 0x242070db, 17 );
80 MD5_DO( F1, b, c, d, a, p_input[ 3 ] + 0xc1bdceee, 22 );
81 MD5_DO( F1, a, b, c, d, p_input[ 4 ] + 0xf57c0faf, 7 );
82 MD5_DO( F1, d, a, b, c, p_input[ 5 ] + 0x4787c62a, 12 );
83 MD5_DO( F1, c, d, a, b, p_input[ 6 ] + 0xa8304613, 17 );
84 MD5_DO( F1, b, c, d, a, p_input[ 7 ] + 0xfd469501, 22 );
85 MD5_DO( F1, a, b, c, d, p_input[ 8 ] + 0x698098d8, 7 );
86 MD5_DO( F1, d, a, b, c, p_input[ 9 ] + 0x8b44f7af, 12 );
87 MD5_DO( F1, c, d, a, b, p_input[ 10 ] + 0xffff5bb1, 17 );
88 MD5_DO( F1, b, c, d, a, p_input[ 11 ] + 0x895cd7be, 22 );
89 MD5_DO( F1, a, b, c, d, p_input[ 12 ] + 0x6b901122, 7 );
90 MD5_DO( F1, d, a, b, c, p_input[ 13 ] + 0xfd987193, 12 );
91 MD5_DO( F1, c, d, a, b, p_input[ 14 ] + 0xa679438e, 17 );
92 MD5_DO( F1, b, c, d, a, p_input[ 15 ] + 0x49b40821, 22 );
93
94 MD5_DO( F2, a, b, c, d, p_input[ 1 ] + 0xf61e2562, 5 );
95 MD5_DO( F2, d, a, b, c, p_input[ 6 ] + 0xc040b340, 9 );
96 MD5_DO( F2, c, d, a, b, p_input[ 11 ] + 0x265e5a51, 14 );
97 MD5_DO( F2, b, c, d, a, p_input[ 0 ] + 0xe9b6c7aa, 20 );
98 MD5_DO( F2, a, b, c, d, p_input[ 5 ] + 0xd62f105d, 5 );
99 MD5_DO( F2, d, a, b, c, p_input[ 10 ] + 0x02441453, 9 );
100 MD5_DO( F2, c, d, a, b, p_input[ 15 ] + 0xd8a1e681, 14 );
101 MD5_DO( F2, b, c, d, a, p_input[ 4 ] + 0xe7d3fbc8, 20 );
102 MD5_DO( F2, a, b, c, d, p_input[ 9 ] + 0x21e1cde6, 5 );
103 MD5_DO( F2, d, a, b, c, p_input[ 14 ] + 0xc33707d6, 9 );
104 MD5_DO( F2, c, d, a, b, p_input[ 3 ] + 0xf4d50d87, 14 );
105 MD5_DO( F2, b, c, d, a, p_input[ 8 ] + 0x455a14ed, 20 );
106 MD5_DO( F2, a, b, c, d, p_input[ 13 ] + 0xa9e3e905, 5 );
107 MD5_DO( F2, d, a, b, c, p_input[ 2 ] + 0xfcefa3f8, 9 );
108 MD5_DO( F2, c, d, a, b, p_input[ 7 ] + 0x676f02d9, 14 );
109 MD5_DO( F2, b, c, d, a, p_input[ 12 ] + 0x8d2a4c8a, 20 );
110
111 MD5_DO( F3, a, b, c, d, p_input[ 5 ] + 0xfffa3942, 4 );
112 MD5_DO( F3, d, a, b, c, p_input[ 8 ] + 0x8771f681, 11 );
113 MD5_DO( F3, c, d, a, b, p_input[ 11 ] + 0x6d9d6122, 16 );
114 MD5_DO( F3, b, c, d, a, p_input[ 14 ] + 0xfde5380c, 23 );
115 MD5_DO( F3, a, b, c, d, p_input[ 1 ] + 0xa4beea44, 4 );
116 MD5_DO( F3, d, a, b, c, p_input[ 4 ] + 0x4bdecfa9, 11 );
117 MD5_DO( F3, c, d, a, b, p_input[ 7 ] + 0xf6bb4b60, 16 );
118 MD5_DO( F3, b, c, d, a, p_input[ 10 ] + 0xbebfbc70, 23 );
119 MD5_DO( F3, a, b, c, d, p_input[ 13 ] + 0x289b7ec6, 4 );
120 MD5_DO( F3, d, a, b, c, p_input[ 0 ] + 0xeaa127fa, 11 );
121 MD5_DO( F3, c, d, a, b, p_input[ 3 ] + 0xd4ef3085, 16 );
122 MD5_DO( F3, b, c, d, a, p_input[ 6 ] + 0x04881d05, 23 );
123 MD5_DO( F3, a, b, c, d, p_input[ 9 ] + 0xd9d4d039, 4 );
124 MD5_DO( F3, d, a, b, c, p_input[ 12 ] + 0xe6db99e5, 11 );
125 MD5_DO( F3, c, d, a, b, p_input[ 15 ] + 0x1fa27cf8, 16 );
126 MD5_DO( F3, b, c, d, a, p_input[ 2 ] + 0xc4ac5665, 23 );
127
128 MD5_DO( F4, a, b, c, d, p_input[ 0 ] + 0xf4292244, 6 );
129 MD5_DO( F4, d, a, b, c, p_input[ 7 ] + 0x432aff97, 10 );
130 MD5_DO( F4, c, d, a, b, p_input[ 14 ] + 0xab9423a7, 15 );
131 MD5_DO( F4, b, c, d, a, p_input[ 5 ] + 0xfc93a039, 21 );
132 MD5_DO( F4, a, b, c, d, p_input[ 12 ] + 0x655b59c3, 6 );
133 MD5_DO( F4, d, a, b, c, p_input[ 3 ] + 0x8f0ccc92, 10 );
134 MD5_DO( F4, c, d, a, b, p_input[ 10 ] + 0xffeff47d, 15 );
135 MD5_DO( F4, b, c, d, a, p_input[ 1 ] + 0x85845dd1, 21 );
136 MD5_DO( F4, a, b, c, d, p_input[ 8 ] + 0x6fa87e4f, 6 );
137 MD5_DO( F4, d, a, b, c, p_input[ 15 ] + 0xfe2ce6e0, 10 );
138 MD5_DO( F4, c, d, a, b, p_input[ 6 ] + 0xa3014314, 15 );
139 MD5_DO( F4, b, c, d, a, p_input[ 13 ] + 0x4e0811a1, 21 );
140 MD5_DO( F4, a, b, c, d, p_input[ 4 ] + 0xf7537e82, 6 );
141 MD5_DO( F4, d, a, b, c, p_input[ 11 ] + 0xbd3af235, 10 );
142 MD5_DO( F4, c, d, a, b, p_input[ 2 ] + 0x2ad7d2bb, 15 );
143 MD5_DO( F4, b, c, d, a, p_input[ 9 ] + 0xeb86d391, 21 );
144
145 p_md5->p_digest[ 0 ] += a;
146 p_md5->p_digest[ 1 ] += b;
147 p_md5->p_digest[ 2 ] += c;
148 p_md5->p_digest[ 3 ] += d;
149}
150
151/*****************************************************************************
152 * InitMD5: initialise an MD5 message
153 *****************************************************************************
154 * The MD5 message-digest algorithm is described in RFC 1321
155 *****************************************************************************/
156void InitMD5( struct md5_s *p_md5 )
157{
158 p_md5->p_digest[ 0 ] = 0x67452301;
159 p_md5->p_digest[ 1 ] = 0xefcdab89;
160 p_md5->p_digest[ 2 ] = 0x98badcfe;
161 p_md5->p_digest[ 3 ] = 0x10325476;
162
163 rb->memset( p_md5->p_data, 0, 64 );
164 p_md5->i_bits = 0;
165}
166
167/*****************************************************************************
168 * AddMD5: add i_len bytes to an MD5 message
169 *****************************************************************************/
170void AddMD5( struct md5_s *p_md5, const void *p_src, size_t i_len )
171{
172 unsigned int i_current; /* Current bytes in the spare buffer */
173 size_t i_offset = 0;
174
175 i_current = (p_md5->i_bits / 8) & 63;
176
177 p_md5->i_bits += 8 * i_len;
178
179 /* If we can complete our spare buffer to 64 bytes, do it and add the
180 * resulting buffer to the MD5 message */
181 if( i_len >= (64 - i_current) )
182 {
183 rb->memcpy( ((uint8_t *)p_md5->p_data) + i_current, p_src,
184 (64 - i_current) );
185 DigestMD5( p_md5, p_md5->p_data );
186
187 i_offset += (64 - i_current);
188 i_len -= (64 - i_current);
189 i_current = 0;
190 }
191
192 /* Add as many entire 64 bytes blocks as we can to the MD5 message */
193 while( i_len >= 64 )
194 {
195 uint32_t p_tmp[ 16 ];
196 rb->memcpy( p_tmp, ((const uint8_t *)p_src) + i_offset, 64 );
197 DigestMD5( p_md5, p_tmp );
198 i_offset += 64;
199 i_len -= 64;
200 }
201
202 /* Copy our remaining data to the message's spare buffer */
203 rb->memcpy( ((uint8_t *)p_md5->p_data) + i_current,
204 ((const uint8_t *)p_src) + i_offset, i_len );
205}
206
207/*****************************************************************************
208 * EndMD5: finish an MD5 message
209 *****************************************************************************
210 * This function adds adequate padding to the end of the message, and appends
211 * the bit count so that we end at a block boundary.
212 *****************************************************************************/
213void EndMD5( struct md5_s *p_md5 )
214{
215 unsigned int i_current;
216
217 i_current = (p_md5->i_bits / 8) & 63;
218
219 /* Append 0x80 to our buffer. No boundary check because the temporary
220 * buffer cannot be full, otherwise AddMD5 would have emptied it. */
221 ((uint8_t *)p_md5->p_data)[ i_current++ ] = 0x80;
222
223 /* If less than 8 bytes are available at the end of the block, complete
224 * this 64 bytes block with zeros and add it to the message. We'll add
225 * our length at the end of the next block. */
226 if( i_current > 56 )
227 {
228 rb->memset( ((uint8_t *)p_md5->p_data) + i_current, 0, (64 - i_current) );
229 DigestMD5( p_md5, p_md5->p_data );
230 i_current = 0;
231 }
232
233 /* Fill the unused space in our last block with zeroes and put the
234 * message length at the end. */
235 rb->memset( ((uint8_t *)p_md5->p_data) + i_current, 0, (56 - i_current) );
236 p_md5->p_data[ 14 ] = p_md5->i_bits & 0xffffffff;
237 p_md5->p_data[ 15 ] = (p_md5->i_bits >> 32);
238 REVERSE( &p_md5->p_data[ 14 ], 2 );
239
240 DigestMD5( p_md5, p_md5->p_data );
241}
242
243void psz_md5_hash( char *psz, struct md5_s *md5_s )
244{
245 int i;
246 for ( i = 0; i < 4; i++ )
247 {
248 rb->snprintf( &psz[8*i], 9, "%02x%02x%02x%02x",
249 md5_s->p_digest[i] & 0xff,
250 ( md5_s->p_digest[i] >> 8 ) & 0xff,
251 ( md5_s->p_digest[i] >> 16 ) & 0xff,
252 md5_s->p_digest[i] >> 24
253 );
254 }
255}
diff --git a/apps/plugins/lib/md5.h b/apps/plugins/lib/md5.h
new file mode 100644
index 0000000000..e19c749664
--- /dev/null
+++ b/apps/plugins/lib/md5.h
@@ -0,0 +1,56 @@
1/*****************************************************************************
2 * vlc_md5.h: MD5 hash
3 *****************************************************************************
4 * Copyright (C) 2004-2005 the VideoLAN team
5 * $Id: 46f10f01439edbcc8bad45673cc302039b76dd5b $
6 *
7 * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8 * Sam Hocevar <sam@zoy.org>
9 *
10 * Adapted to Rockbox by: Antoine Cellerier <dionoea at videolan dot org>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
26
27#ifndef _VLC_MD5_H
28# define _VLC_MD5_H
29
30void md5_init( const struct plugin_api * );
31
32/*****************************************************************************
33 * md5_s: MD5 message structure
34 *****************************************************************************
35 * This structure stores the static information needed to compute an MD5
36 * hash. It has an extra data buffer to allow non-aligned writes.
37 *****************************************************************************/
38struct md5_s
39{
40 uint64_t i_bits; /* Total written bits */
41 uint32_t p_digest[4]; /* The MD5 digest */
42 uint32_t p_data[16]; /* Buffer to cache non-aligned writes */
43};
44
45void InitMD5( struct md5_s * );
46void AddMD5( struct md5_s *, const void *, size_t );
47void EndMD5( struct md5_s * );
48
49/**
50 * Returns a char representation of the md5 hash, as shown by UNIX md5 or
51 * md5sum tools.
52 */
53#define MD5_STRING_LENGTH 32
54void psz_md5_hash( char *, struct md5_s * );
55
56#endif
diff --git a/apps/plugins/md5sum.c b/apps/plugins/md5sum.c
new file mode 100644
index 0000000000..6845c4c473
--- /dev/null
+++ b/apps/plugins/md5sum.c
@@ -0,0 +1,206 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2008 Antoine Cellerier <dionoea -at- videolan -dot- org>
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "plugin.h"
21#include "lib/md5.h"
22
23PLUGIN_HEADER
24
25static const struct plugin_api *rb;
26
27int hash( char *string, const char *path )
28{
29 char *buffer[512];
30 ssize_t len;
31 struct md5_s md5;
32 int in = rb->open( path, O_RDONLY );
33 if( in < 0 ) return -1;
34
35 InitMD5( &md5 );
36 while( ( len = rb->read( in, buffer, 512 ) ) > 0 )
37 AddMD5( &md5, buffer, len );
38 EndMD5( &md5 );
39
40 psz_md5_hash( string, &md5 );
41
42 rb->close( in );
43 return 0;
44}
45
46void hash_file( int out, const char *path )
47{
48 char string[MD5_STRING_LENGTH+1];
49 if( hash( string, path ) )
50 rb->write( out, "error", 5 );
51 else
52 rb->write( out, string, MD5_STRING_LENGTH );
53 rb->write( out, " ", 1 );
54 rb->write( out, path, rb->strlen( path ) );
55 rb->write( out, "\n", 1 );
56}
57
58void hash_dir( int out, const char *path );
59void hash_dir( int out, const char *path )
60{
61 DIR *dir;
62 struct dirent *entry;
63
64 dir = rb->opendir( path );
65 if( dir )
66 {
67 while( ( entry = rb->readdir( dir ) ) )
68 {
69 char childpath[MAX_PATH];
70 rb->snprintf( childpath, MAX_PATH, "%s/%s",
71 path, entry->d_name );
72 if( entry->attribute & ATTR_DIRECTORY )
73 {
74 if( rb->strcmp( entry->d_name, "." )
75 && rb->strcmp( entry->d_name, ".." ) )
76 {
77 /* Got a sub directory */
78 hash_dir( out, childpath );
79 }
80 }
81 else
82 {
83 /* Got a file */
84 hash_file( out, childpath );
85 }
86 }
87 rb->closedir( dir );
88 }
89}
90
91void hash_list( int out, const char *path )
92{
93 int list = rb->open( path, O_RDONLY );
94 char newpath[MAX_PATH];
95 if( list < 0 ) return;
96
97 while( rb->read_line( list, newpath, MAX_PATH ) > 0 )
98 {
99 DIR *dir = rb->opendir( newpath );
100 if( dir )
101 {
102 rb->closedir( dir );
103 hash_dir( out, newpath );
104 }
105 else
106 {
107 hash_file( out, newpath );
108 }
109 }
110
111 rb->close( list );
112}
113
114void hash_check( int out, const char *path )
115{
116 int list = rb->open( path, O_RDONLY );
117 char line[MD5_STRING_LENGTH+1+MAX_PATH+1];
118 int len;
119 if( list < 0 ) return;
120
121 while( ( len = rb->read_line( list, line, MD5_STRING_LENGTH+1+MAX_PATH+1 ) ) > 0 )
122 {
123 const char *filename = rb->strchr( line, ' ' );
124 if( !filename || len < MD5_STRING_LENGTH + 2 )
125 {
126 const char error[] = "Malformed input line ... skipping";
127 rb->write( out, error, rb->strlen( error ) );
128 }
129 else
130 {
131 char string[MD5_STRING_LENGTH+1];
132 filename++;
133 rb->write( out, filename, rb->strlen( filename ) );
134 rb->write( out, ": ", 2 );
135 if( hash( string, filename ) )
136 rb->write( out, "FAILED open or read", 19 );
137 else if( rb->memcmp( line, string, MD5_STRING_LENGTH ) )
138 rb->write( out, "FAILED", 6 );
139 else
140 rb->write( out, "OK", 2 );
141 }
142 rb->write( out, "\n", 1 );
143 }
144}
145
146enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
147{
148 const char *arg = (const char *)parameter; /* input file name, if any */
149 int out = -1; /* output file descriptor */
150 char filename[MAX_PATH]; /* output file name */
151
152 md5_init( api );
153 rb = api;
154
155 if( arg && *arg )
156 {
157 const char *ext = rb->strrchr( arg, '.' );
158 DIR *dir;
159 rb->snprintf( filename, MAX_PATH, "%s.md5sum", arg );
160 out = rb->open( filename, O_WRONLY|O_CREAT );
161 if( out < 0 ) return PLUGIN_ERROR;
162
163 if( ext )
164 {
165 if( !rb->strcmp( ext, ".md5" ) || !rb->strcmp( ext, ".md5sum" ) )
166 {
167 /* Lets check the sums */
168 hash_check( out, arg );
169 goto exit;
170 }
171 else if( !rb->strcmp( ext, ".md5list" ) ) /* ugly */
172 {
173 /* Hash listed files */
174 hash_list( out, arg );
175 goto exit;
176 }
177 }
178
179 dir = rb->opendir( arg );
180 if( dir )
181 {
182 api->closedir( dir );
183
184 /* Hash the directory's content recursively */
185 hash_dir( out, arg );
186 }
187 else
188 {
189 /* Hash the file */
190 hash_file( out, arg );
191 }
192 }
193 else
194 {
195 rb->snprintf( filename, MAX_PATH, "/everything.md5sum" );
196 out = rb->open( filename, O_WRONLY|O_CREAT );
197 if( out < 0 ) return PLUGIN_ERROR;
198
199 /* Hash the whole filesystem */
200 hash_dir( out, "/" );
201 }
202
203 exit:
204 rb->close( out );
205 return PLUGIN_OK;
206}
diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config
index bfb408c397..c1df1b2e71 100644
--- a/apps/plugins/viewers.config
+++ b/apps/plugins/viewers.config
@@ -41,3 +41,4 @@ colours,apps/text_editor,11
41ssg,games/superdom,- 41ssg,games/superdom,-
42link,viewers/shortcuts_view,- 42link,viewers/shortcuts_view,-
43*,viewers/shortcuts_append,- 43*,viewers/shortcuts_append,-
44*,apps/md5sum,-