diff options
Diffstat (limited to 'apps/plugins/md5sum.c')
-rw-r--r-- | apps/plugins/md5sum.c | 206 |
1 files changed, 206 insertions, 0 deletions
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 | |||
23 | PLUGIN_HEADER | ||
24 | |||
25 | static const struct plugin_api *rb; | ||
26 | |||
27 | int 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 | |||
46 | void 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 | |||
58 | void hash_dir( int out, const char *path ); | ||
59 | void 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 | |||
91 | void 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 | |||
114 | void 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 | |||
146 | enum 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 | } | ||