summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <pamaury@rockbox.org>2010-01-20 21:24:19 +0000
committerAmaury Pouly <pamaury@rockbox.org>2010-01-20 21:24:19 +0000
commitb5d16e79e191af7c4cb34be685770166e8dfcfa6 (patch)
treec45d27b817ad85eb1fbbc18825a32db01f829ddf
parent052812d575b5a50f086e09f26a919e01536bea31 (diff)
downloadrockbox-b5d16e79e191af7c4cb34be685770166e8dfcfa6.tar.gz
rockbox-b5d16e79e191af7c4cb34be685770166e8dfcfa6.zip
FS#10738: fix disktidy plugin crash when dealing with very long file/directory names.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24300 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/disktidy.c98
1 files changed, 70 insertions, 28 deletions
diff --git a/apps/plugins/disktidy.c b/apps/plugins/disktidy.c
index ee39972f0b..3d2685f4ad 100644
--- a/apps/plugins/disktidy.c
+++ b/apps/plugins/disktidy.c
@@ -19,6 +19,7 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#include "plugin.h" 21#include "plugin.h"
22#include "errno.h"
22 23
23PLUGIN_HEADER 24PLUGIN_HEADER
24 25
@@ -172,33 +173,53 @@ void tidy_lcd_status(const char *name, int *removed)
172 rb->lcd_update(); 173 rb->lcd_update();
173} 174}
174 175
175void tidy_get_absolute_path(struct dirent *entry, char *fullname, 176int tidy_path_append_entry(char *path, struct dirent *entry, int *path_length)
176 const char* name)
177{ 177{
178 /* gets absolute path using dirent and name */ 178 int name_len = rb->strlen(entry->d_name);
179 rb->strcpy(fullname, name); 179 /* for the special case of path="/" this is one bigger but it's not a problem */
180 if (rb->strlen(name) > 1) 180 int new_length = *path_length + name_len + 1;
181
182 /* check overflow (keep space for trailing zero) */
183 if(new_length >= MAX_PATH)
184 return 0;
185
186 /* special case for path <> "/" */
187 if(rb->strcmp(path, "/") != 0)
181 { 188 {
182 rb->strcat(fullname, "/"); 189 rb->strcat(path + *path_length, "/");
190 (*path_length)++;
183 } 191 }
184 rb->strcat(fullname, entry->d_name); 192 /* strcat is unsafe but the previous check normally avoid any problem */
193 /* use path_length to optimise */
194
195 rb->strcat(path + *path_length, entry->d_name);
196 *path_length += name_len;
197
198 return 1;
185} 199}
186 200
187enum tidy_return tidy_removedir(const char *name, int *removed) 201void tidy_path_remove_entry(char *path, int old_path_length, int *path_length)
202{
203 path[old_path_length] = '\0';
204 *path_length = old_path_length;
205}
206
207/* path is assumed to be array of size MAX_PATH */
208enum tidy_return tidy_removedir(char *path, int *path_length, int *removed)
188{ 209{
189 /* delete directory */ 210 /* delete directory */
190 struct dirent *entry; 211 struct dirent *entry;
191 enum tidy_return status = TIDY_RETURN_OK; 212 enum tidy_return status = TIDY_RETURN_OK;
192 int button; 213 int button;
193 DIR *dir; 214 DIR *dir;
194 char fullname[MAX_PATH]; 215 int old_path_length = *path_length;
195 216
196 /* display status text */ 217 /* display status text */
197 tidy_lcd_status(name, removed); 218 tidy_lcd_status(path, removed);
198 219
199 rb->yield(); 220 rb->yield();
200 221
201 dir = rb->opendir(name); 222 dir = rb->opendir(path);
202 if (dir) 223 if (dir)
203 { 224 {
204 while((status == TIDY_RETURN_OK) && ((entry = rb->readdir(dir)) != 0)) 225 while((status == TIDY_RETURN_OK) && ((entry = rb->readdir(dir)) != 0))
@@ -220,7 +241,10 @@ enum tidy_return tidy_removedir(const char *name, int *removed)
220 rb->yield(); 241 rb->yield();
221 242
222 /* get absolute path */ 243 /* get absolute path */
223 tidy_get_absolute_path(entry, fullname, name); 244 /* returns an error if path is too long */
245 if(!tidy_path_append_entry(path, entry, path_length))
246 /* silent error */
247 continue;
224 248
225 if (entry->attribute & ATTR_DIRECTORY) 249 if (entry->attribute & ATTR_DIRECTORY)
226 { 250 {
@@ -228,20 +252,23 @@ enum tidy_return tidy_removedir(const char *name, int *removed)
228 if ((rb->strcmp(entry->d_name, ".") != 0) && \ 252 if ((rb->strcmp(entry->d_name, ".") != 0) && \
229 (rb->strcmp(entry->d_name, "..") != 0)) 253 (rb->strcmp(entry->d_name, "..") != 0))
230 { 254 {
231 tidy_removedir(fullname, removed); 255 tidy_removedir(path, path_length, removed);
232 } 256 }
233 } 257 }
234 else 258 else
235 { 259 {
236 /* file */ 260 /* file */
237 *removed += 1; 261 *removed += 1;
238 rb->remove(fullname); 262 rb->remove(path);
239 } 263 }
264
265 /* restore path */
266 tidy_path_remove_entry(path, old_path_length, path_length);
240 } 267 }
241 rb->closedir(dir); 268 rb->closedir(dir);
242 /* rmdir */ 269 /* rmdir */
243 *removed += 1; 270 *removed += 1;
244 rb->rmdir(name); 271 rb->rmdir(path);
245 } 272 }
246 else 273 else
247 { 274 {
@@ -250,7 +277,8 @@ enum tidy_return tidy_removedir(const char *name, int *removed)
250 return status; 277 return status;
251} 278}
252 279
253enum tidy_return tidy_clean(const char *name, int *removed) 280/* path is assumed to be array of size MAX_PATH */
281enum tidy_return tidy_clean(char *path, int *path_length, int *removed)
254{ 282{
255 /* deletes junk files and dirs left by system */ 283 /* deletes junk files and dirs left by system */
256 struct dirent *entry; 284 struct dirent *entry;
@@ -258,14 +286,14 @@ enum tidy_return tidy_clean(const char *name, int *removed)
258 int button; 286 int button;
259 int del; /* has the item been deleted */ 287 int del; /* has the item been deleted */
260 DIR *dir; 288 DIR *dir;
261 char fullname[MAX_PATH]; 289 int old_path_length = *path_length;
262 290
263 /* display status text */ 291 /* display status text */
264 tidy_lcd_status(name, removed); 292 tidy_lcd_status(path, removed);
265 293
266 rb->yield(); 294 rb->yield();
267 295
268 dir = rb->opendir(name); 296 dir = rb->opendir(path);
269 if (dir) 297 if (dir)
270 { 298 {
271 while((status == TIDY_RETURN_OK) && ((entry = rb->readdir(dir)) != 0)) 299 while((status == TIDY_RETURN_OK) && ((entry = rb->readdir(dir)) != 0))
@@ -295,20 +323,26 @@ enum tidy_return tidy_clean(const char *name, int *removed)
295 del = 0; 323 del = 0;
296 324
297 /* get absolute path */ 325 /* get absolute path */
298 tidy_get_absolute_path(entry, fullname, name); 326 /* returns an error if path is too long */
327 if(!tidy_path_append_entry(path, entry, path_length))
328 /* silent error */
329 continue;
299 330
300 if (tidy_remove_item(entry->d_name, entry->attribute)) 331 if (tidy_remove_item(entry->d_name, entry->attribute))
301 { 332 {
302 /* delete dir */ 333 /* delete dir */
303 tidy_removedir(fullname, removed); 334 tidy_removedir(path, path_length, removed);
304 del = 1; 335 del = 1;
305 } 336 }
306 337
307 if (del == 0) 338 if (del == 0)
308 { 339 {
309 /* dir not deleted so clean it */ 340 /* dir not deleted so clean it */
310 status = tidy_clean(fullname, removed); 341 status = tidy_clean(path, path_length, removed);
311 } 342 }
343
344 /* restore path */
345 tidy_path_remove_entry(path, old_path_length, path_length);
312 } 346 }
313 } 347 }
314 else 348 else
@@ -317,15 +351,19 @@ enum tidy_return tidy_clean(const char *name, int *removed)
317 del = 0; 351 del = 0;
318 if (tidy_remove_item(entry->d_name, entry->attribute)) 352 if (tidy_remove_item(entry->d_name, entry->attribute))
319 { 353 {
320 *removed += 1; /* increment removed files counter */
321
322 /* get absolute path */ 354 /* get absolute path */
323 char fullname[MAX_PATH]; 355 /* returns an error if path is too long */
324 tidy_get_absolute_path(entry, fullname, name); 356 if(!tidy_path_append_entry(path, entry, path_length))
357 /* silent error */
358 continue;
325 359
360 *removed += 1; /* increment removed files counter */
326 /* delete file */ 361 /* delete file */
327 rb->remove(fullname); 362 rb->remove(path);
328 del = 1; 363 del = 1;
364
365 /* restore path */
366 tidy_path_remove_entry(path, old_path_length, path_length);
329 } 367 }
330 } 368 }
331 } 369 }
@@ -344,12 +382,16 @@ enum tidy_return tidy_do(void)
344 int removed = 0; 382 int removed = 0;
345 enum tidy_return status; 383 enum tidy_return status;
346 char text[24]; /* "Cleaned up nnnnn items" */ 384 char text[24]; /* "Cleaned up nnnnn items" */
385 char path[MAX_PATH];
386 int path_length;
347 387
348#ifdef HAVE_ADJUSTABLE_CPU_FREQ 388#ifdef HAVE_ADJUSTABLE_CPU_FREQ
349 rb->cpu_boost(true); 389 rb->cpu_boost(true);
350#endif 390#endif
351 391
352 status = tidy_clean("/", &removed); 392 rb->strcpy(path, "/");
393 path_length = rb->strlen(path);
394 status = tidy_clean(path, &path_length, &removed);
353 395
354#ifdef HAVE_ADJUSTABLE_CPU_FREQ 396#ifdef HAVE_ADJUSTABLE_CPU_FREQ
355 rb->cpu_boost(false); 397 rb->cpu_boost(false);