diff options
author | William Wilgus <wilgus.william@gmail.com> | 2024-07-02 10:14:59 -0400 |
---|---|---|
committer | William Wilgus <me.theuser@yahoo.com> | 2024-07-04 12:44:04 -0400 |
commit | b0dfcde2f5fb086e7a7f54b16a47e0433661cca7 (patch) | |
tree | 7336885079c98b5d0d3f245968882187164591ae /apps/fileop.c | |
parent | 3e9ca6ec8ed5d452db482ae3cffb66e5330ec244 (diff) | |
download | rockbox-b0dfcde2f5fb086e7a7f54b16a47e0433661cca7.tar.gz rockbox-b0dfcde2f5fb086e7a7f54b16a47e0433661cca7.zip |
[Cleanup] onplay.c fileop.c
clean-up a bit more
add/correct some comments
fix some error passing
guard delete path on PATH_TOO_LONG
add some cpu_boost
Change-Id: Icf179dd727271bdc61ab78400e10847222b9f858
Diffstat (limited to 'apps/fileop.c')
-rw-r--r-- | apps/fileop.c | 344 |
1 files changed, 168 insertions, 176 deletions
diff --git a/apps/fileop.c b/apps/fileop.c index 0d2dc774b9..c4bdc5aa18 100644 --- a/apps/fileop.c +++ b/apps/fileop.c | |||
@@ -1,10 +1,10 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * __________ __ ___. | 2 | * __________ __ ___. |
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2002 Björn Stenberg | 10 | * Copyright (C) 2002 Björn Stenberg |
@@ -50,6 +50,17 @@ struct file_op_params | |||
50 | size_t append; /* Append position in 'path' for stack push */ | 50 | size_t append; /* Append position in 'path' for stack push */ |
51 | }; | 51 | }; |
52 | 52 | ||
53 | static int prompt_name(char* buf, size_t bufsz) | ||
54 | { | ||
55 | if (kbd_input(buf, bufsz, NULL) < 0) | ||
56 | return FORC_CANCELLED; | ||
57 | /* at least prevent escapes out of the base directory from keyboard- | ||
58 | entered filenames; the file code should reject other invalidities */ | ||
59 | if (*buf != '\0' && !strchr(buf, PATH_SEPCH) && !is_dotdir_name(buf)) | ||
60 | return FORC_SUCCESS; | ||
61 | return FORC_UNKNOWN_FAILURE; | ||
62 | } | ||
63 | |||
53 | static bool poll_cancel_action(const char *path, int operation, int current, int total) | 64 | static bool poll_cancel_action(const char *path, int operation, int current, int total) |
54 | { | 65 | { |
55 | const char *op_str = ""; | 66 | const char *op_str = ""; |
@@ -75,7 +86,7 @@ static bool poll_cancel_action(const char *path, int operation, int current, int | |||
75 | return ACTION_STD_CANCEL == get_action(CONTEXT_STD, TIMEOUT_NOBLOCK); | 86 | return ACTION_STD_CANCEL == get_action(CONTEXT_STD, TIMEOUT_NOBLOCK); |
76 | } | 87 | } |
77 | 88 | ||
78 | static struct file_op_params* init_file_op(struct file_op_params *param, | 89 | static void init_file_op(struct file_op_params *param, |
79 | const char *basename, | 90 | const char *basename, |
80 | const char *selected_file) | 91 | const char *selected_file) |
81 | { | 92 | { |
@@ -90,8 +101,6 @@ static struct file_op_params* init_file_op(struct file_op_params *param, | |||
90 | param->is_dir = dir_exists(param->path); | 101 | param->is_dir = dir_exists(param->path); |
91 | param->objects = 0; /* how many files and subdirectories*/ | 102 | param->objects = 0; /* how many files and subdirectories*/ |
92 | param->processed = 0; | 103 | param->processed = 0; |
93 | |||
94 | return param; | ||
95 | } | 104 | } |
96 | 105 | ||
97 | /* counts file objects, deletes file objects */ | 106 | /* counts file objects, deletes file objects */ |
@@ -144,7 +153,7 @@ static int directory_fileop(struct file_op_params *param, enum file_op_current f | |||
144 | 153 | ||
145 | if (info.attribute & ATTR_DIRECTORY) { | 154 | if (info.attribute & ATTR_DIRECTORY) { |
146 | /* remove a subdirectory */ | 155 | /* remove a subdirectory */ |
147 | rc = directory_fileop(param, fileop); | 156 | rc = directory_fileop(param, fileop); /* recursion */ |
148 | } else { | 157 | } else { |
149 | /* remove a file */ | 158 | /* remove a file */ |
150 | if (poll_cancel_action(param->path, FOC_DELETE, param->processed, param->objects)) | 159 | if (poll_cancel_action(param->path, FOC_DELETE, param->processed, param->objects)) |
@@ -165,8 +174,8 @@ static int directory_fileop(struct file_op_params *param, enum file_op_current f | |||
165 | } | 174 | } |
166 | 175 | ||
167 | if (info.attribute & ATTR_DIRECTORY) { | 176 | if (info.attribute & ATTR_DIRECTORY) { |
168 | /* remove a subdirectory */ | 177 | /* enter subdirectory */ |
169 | rc = directory_fileop(param, FOC_COUNT); | 178 | rc = directory_fileop(param, FOC_COUNT); /* recursion */ |
170 | } else { | 179 | } else { |
171 | if (poll_cancel_action(param->path, FOC_COUNT, param->objects, 0)) | 180 | if (poll_cancel_action(param->path, FOC_COUNT, param->objects, 0)) |
172 | { | 181 | { |
@@ -195,150 +204,42 @@ static int directory_fileop(struct file_op_params *param, enum file_op_current f | |||
195 | return rc; | 204 | return rc; |
196 | } | 205 | } |
197 | 206 | ||
207 | /* Walk a directory tree and count the number of objects (dirs & files) | ||
208 | * also check that enough resources exist to do an operation */ | ||
198 | static int check_count_fileobjects(struct file_op_params *param) | 209 | static int check_count_fileobjects(struct file_op_params *param) |
199 | { | 210 | { |
211 | cpu_boost(true); | ||
200 | int rc = directory_fileop(param, FOC_COUNT); | 212 | int rc = directory_fileop(param, FOC_COUNT); |
213 | cpu_boost(false); | ||
201 | DEBUGF("%s res:(%d) objects %d \n", __func__, rc, param->objects); | 214 | DEBUGF("%s res:(%d) objects %d \n", __func__, rc, param->objects); |
202 | return rc; | 215 | return rc; |
203 | } | 216 | } |
204 | 217 | ||
205 | static bool check_new_name(const char *basename) | 218 | /* Attempt to just rename a file or directory */ |
206 | { | ||
207 | /* at least prevent escapes out of the base directory from keyboard- | ||
208 | entered filenames; the file code should reject other invalidities */ | ||
209 | return *basename != '\0' && !strchr(basename, PATH_SEPCH) && | ||
210 | !is_dotdir_name(basename); | ||
211 | } | ||
212 | |||
213 | int create_dir(void) | ||
214 | { | ||
215 | int rc = FORC_UNKNOWN_FAILURE; | ||
216 | char dirname[MAX_PATH]; | ||
217 | size_t pathlen = path_append(dirname, getcwd(NULL, 0), PA_SEP_HARD, | ||
218 | sizeof (dirname)); | ||
219 | char *basename = dirname + pathlen; | ||
220 | |||
221 | if (pathlen >= sizeof (dirname)) { | ||
222 | /* Too long */ | ||
223 | } else if (kbd_input(basename, sizeof (dirname) - pathlen, NULL) < 0) { | ||
224 | rc = FORC_CANCELLED; | ||
225 | } else if (check_new_name(basename)) { | ||
226 | rc = mkdir(dirname); | ||
227 | } | ||
228 | |||
229 | return rc; | ||
230 | } | ||
231 | |||
232 | /************************************************************************************/ | ||
233 | /* share code for file and directory deletion, saves space */ | ||
234 | static int delete_file_dir(struct file_op_params *param) | ||
235 | { | ||
236 | /* Note: delete_file_dir() will happily delete whatever | ||
237 | * path is passed (after confirmation) */ | ||
238 | if (confirm_delete_yesno(param->path) != YESNO_YES) { | ||
239 | return FORC_CANCELLED; | ||
240 | } | ||
241 | |||
242 | clear_screen_buffer(true); | ||
243 | poll_cancel_action(param->path, FOC_DELETE, param->processed, param->objects); | ||
244 | |||
245 | int rc = FORC_UNKNOWN_FAILURE; | ||
246 | |||
247 | if (param->is_dir) { /* if directory */ | ||
248 | cpu_boost(true); | ||
249 | rc = directory_fileop(param, FOC_DELETE); | ||
250 | cpu_boost(false); | ||
251 | } else { | ||
252 | rc = remove(param->path); | ||
253 | } | ||
254 | |||
255 | return rc; | ||
256 | } | ||
257 | |||
258 | int delete_fileobject(const char *selected_file) | ||
259 | { | ||
260 | struct file_op_params param; | ||
261 | if (init_file_op(¶m, selected_file, NULL)->is_dir == true) | ||
262 | { | ||
263 | int rc = check_count_fileobjects(¶m); | ||
264 | DEBUGF("%s res: %d, ct: %d, %s", __func__, rc, param.objects, param.path); | ||
265 | if (rc != FORC_SUCCESS) | ||
266 | return rc; | ||
267 | } | ||
268 | |||
269 | return delete_file_dir(¶m); | ||
270 | } | ||
271 | |||
272 | int rename_file(const char *selected_file) | ||
273 | { | ||
274 | int rc = FORC_UNKNOWN_FAILURE; | ||
275 | char newname[MAX_PATH]; | ||
276 | const char *oldbase, *selection = selected_file; | ||
277 | |||
278 | path_basename(selection, &oldbase); | ||
279 | size_t pathlen = oldbase - selection; | ||
280 | char *newbase = newname + pathlen; | ||
281 | |||
282 | if (strmemccpy(newname, selection, sizeof (newname)) == NULL) { | ||
283 | /* Too long */ | ||
284 | } else if (kbd_input(newbase, sizeof (newname) - pathlen, NULL) < 0) { | ||
285 | rc = FORC_CANCELLED; | ||
286 | } else if (!strcmp(oldbase, newbase)) { | ||
287 | rc = FORC_NOOP; /* No change at all */ | ||
288 | } else if (check_new_name(newbase)) { | ||
289 | switch (relate(selection, newname)) | ||
290 | { | ||
291 | case RELATE_DIFFERENT: | ||
292 | if (file_exists(newname)) { | ||
293 | break; /* don't overwrite */ | ||
294 | } | ||
295 | /* Fall-through */ | ||
296 | case RELATE_SAME: | ||
297 | rc = rename(selection, newname); | ||
298 | break; | ||
299 | case RELATE_PREFIX: | ||
300 | default: | ||
301 | break; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | return rc; | ||
306 | } | ||
307 | |||
308 | static int move_by_rename(const char *src_path, | 219 | static int move_by_rename(const char *src_path, |
309 | const char *dst_path, | 220 | const char *dst_path, |
310 | unsigned int *pflags) | 221 | unsigned int *pflags) |
311 | { | 222 | { |
312 | unsigned int flags = *pflags; | 223 | unsigned int flags = *pflags; |
313 | int rc = FORC_UNKNOWN_FAILURE; | 224 | int rc = FORC_UNKNOWN_FAILURE; |
314 | while (!(flags & (PASTE_COPY | PASTE_EXDEV))) { | 225 | if (!(flags & (PASTE_COPY | PASTE_EXDEV))) { |
315 | if ((flags & PASTE_OVERWRITE) || !file_exists(dst_path)) { | 226 | if ((flags & PASTE_OVERWRITE) || !file_exists(dst_path)) { |
316 | /* Just try to move the directory / file */ | 227 | /* Just try to move the directory / file */ |
317 | if (poll_cancel_action(src_path, FOC_MOVE, 0 , 0)) { | 228 | if (poll_cancel_action(src_path, FOC_MOVE, 0 , 0)) { |
318 | rc = FORC_CANCELLED; | 229 | rc = FORC_CANCELLED; |
319 | } else { | 230 | } else { |
320 | rc = rename(src_path, dst_path); | 231 | rc = rename(src_path, dst_path); |
321 | } | 232 | #ifdef HAVE_MULTIVOLUME |
322 | 233 | if (rc < FORC_SUCCESS && errno == EXDEV) { | |
323 | if (rc < 0) { | 234 | /* Failed because cross volume rename doesn't work */ |
324 | int errnum = errno; | 235 | *pflags |= PASTE_EXDEV; /* force a move instead */ |
325 | if (errnum == ENOTEMPTY && (flags & PASTE_OVERWRITE)) { | ||
326 | /* Directory is not empty thus rename() will not do a quick | ||
327 | overwrite */ | ||
328 | break; | ||
329 | } | 236 | } |
330 | #ifdef HAVE_MULTIVOLUME | 237 | #endif /* HAVE_MULTIVOLUME */ |
331 | else if (errnum == EXDEV) { | 238 | /* if (errno == ENOTEMPTY && (flags & PASTE_OVERWRITE)) { |
332 | /* Failed because cross volume rename doesn't work; force | 239 | * Directory is not empty thus rename() will not do a quick overwrite */ |
333 | a move instead */ | ||
334 | *pflags |= PASTE_EXDEV; | ||
335 | break; | ||
336 | } | ||
337 | #endif /* HAVE_MULTIVOLUME */ | ||
338 | } | 240 | } |
339 | } | 241 | } |
340 | 242 | ||
341 | break; | ||
342 | } | 243 | } |
343 | return rc; | 244 | return rc; |
344 | } | 245 | } |
@@ -365,8 +266,7 @@ static int copy_move_file(const char *src_path, const char *dst_path, unsigned i | |||
365 | return FORC_NO_BUFFER_AVAIL; | 266 | return FORC_NO_BUFFER_AVAIL; |
366 | } | 267 | } |
367 | 268 | ||
368 | buffersize &= ~0x1ff; /* Round buffer size to multiple of sector | 269 | buffersize &= ~0x1ff; /* Round buffer size to multiple of sector size */ |
369 | size */ | ||
370 | 270 | ||
371 | int src_fd = open(src_path, O_RDONLY); | 271 | int src_fd = open(src_path, O_RDONLY); |
372 | if (src_fd >= 0) { | 272 | if (src_fd >= 0) { |
@@ -423,9 +323,12 @@ static int copy_move_file(const char *src_path, const char *dst_path, unsigned i | |||
423 | } | 323 | } |
424 | 324 | ||
425 | if (rc == FORC_SUCCESS) { | 325 | if (rc == FORC_SUCCESS) { |
426 | /* If overwriting, set the correct length if original was | 326 | if (total_size != src_sz) |
427 | longer */ | 327 | rc = FORC_UNKNOWN_FAILURE; |
428 | rc = ftruncate(dst_fd, total_size) * 10; | 328 | else { |
329 | /* If overwriting, set the correct length if original was longer */ | ||
330 | rc = ftruncate(dst_fd, total_size) * 10; | ||
331 | } | ||
429 | } | 332 | } |
430 | 333 | ||
431 | close(dst_fd); | 334 | close(dst_fd); |
@@ -449,20 +352,19 @@ static int copy_move_file(const char *src_path, const char *dst_path, unsigned i | |||
449 | 352 | ||
450 | /* Paste a directory */ | 353 | /* Paste a directory */ |
451 | static int copy_move_directory(struct file_op_params *src, | 354 | static int copy_move_directory(struct file_op_params *src, |
452 | struct file_op_params *dst, | 355 | struct file_op_params *dst, |
453 | unsigned int flags) | 356 | unsigned int flags) |
454 | { | 357 | { |
455 | int rc = FORC_UNKNOWN_FAILURE; | ||
456 | |||
457 | DIR *srcdir = opendir(src->path); | 358 | DIR *srcdir = opendir(src->path); |
458 | 359 | ||
459 | if (srcdir) { | 360 | if (!srcdir) |
460 | /* Make a directory to copy things to */ | 361 | return FORC_PATH_NOT_EXIST; |
461 | rc = mkdir(dst->path) * 10; | 362 | |
462 | if (rc < 0 && errno == EEXIST && (flags & PASTE_OVERWRITE)) { | 363 | /* Make a directory to copy things to */ |
463 | /* Exists and overwrite was approved */ | 364 | int rc = mkdir(dst->path) * 10; |
464 | rc = FORC_SUCCESS; | 365 | if (rc < 0 && errno == EEXIST && (flags & PASTE_OVERWRITE)) { |
465 | } | 366 | /* Exists and overwrite was approved */ |
367 | rc = FORC_SUCCESS; | ||
466 | } | 368 | } |
467 | 369 | ||
468 | size_t srcap = src->append, dstap = dst->append; | 370 | size_t srcap = src->append, dstap = dst->append; |
@@ -488,7 +390,7 @@ static int copy_move_directory(struct file_op_params *src, | |||
488 | /* Append names to current directories */ | 390 | /* Append names to current directories */ |
489 | src->append = srcap + | 391 | src->append = srcap + |
490 | path_append(&src->path[srcap], PA_SEP_HARD, entry->d_name, | 392 | path_append(&src->path[srcap], PA_SEP_HARD, entry->d_name, |
491 | sizeof(src->path) - srcap); | 393 | sizeof (src->path) - srcap); |
492 | 394 | ||
493 | dst->append = dstap + | 395 | dst->append = dstap + |
494 | path_append(&dst->path[dstap], PA_SEP_HARD, entry->d_name, | 396 | path_append(&dst->path[dstap], PA_SEP_HARD, entry->d_name, |
@@ -538,13 +440,16 @@ static int copy_move_directory(struct file_op_params *src, | |||
538 | return rc; | 440 | return rc; |
539 | } | 441 | } |
540 | 442 | ||
443 | /************************************************************************************/ | ||
444 | /* PUBLIC FUNCTIONS */ | ||
445 | /************************************************************************************/ | ||
446 | |||
447 | /* Copy or move a file or directory see: file_op_flags */ | ||
541 | int copy_move_fileobject(const char *src_path, const char *dst_path, unsigned int flags) | 448 | int copy_move_fileobject(const char *src_path, const char *dst_path, unsigned int flags) |
542 | { | 449 | { |
543 | if (!src_path[0]) | 450 | if (!src_path[0]) |
544 | return FORC_NOOP; | 451 | return FORC_NOOP; |
545 | 452 | ||
546 | int rc = FORC_UNKNOWN_FAILURE; | ||
547 | |||
548 | struct file_op_params src, dst; | 453 | struct file_op_params src, dst; |
549 | 454 | ||
550 | /* Figure out the name of the selection */ | 455 | /* Figure out the name of the selection */ |
@@ -553,40 +458,37 @@ int copy_move_fileobject(const char *src_path, const char *dst_path, unsigned in | |||
553 | 458 | ||
554 | /* Final target is current directory plus name of selection */ | 459 | /* Final target is current directory plus name of selection */ |
555 | init_file_op(&dst, dst_path, nameptr); | 460 | init_file_op(&dst, dst_path, nameptr); |
461 | if (dst.append >= sizeof (dst.path)) | ||
462 | return FORC_PATH_TOO_LONG; | ||
556 | 463 | ||
557 | switch (dst.append < sizeof (dst.path) ? | 464 | int rel = relate(src_path, dst.path); |
558 | relate(src_path, dst.path) : FORC_PATH_TOO_LONG) | 465 | if (rel == RELATE_SAME) |
559 | { | 466 | return FORC_NOOP; |
560 | case RELATE_SAME: | ||
561 | rc = FORC_NOOP; | ||
562 | break; | ||
563 | 467 | ||
564 | case RELATE_DIFFERENT: | 468 | if (rel == RELATE_DIFFERENT) { |
469 | int rc; | ||
565 | if (file_exists(dst.path)) { | 470 | if (file_exists(dst.path)) { |
566 | /* If user chooses not to overwrite, cancel */ | 471 | /* If user chooses not to overwrite, cancel */ |
567 | if (confirm_overwrite_yesno() == YESNO_NO) { | 472 | if (confirm_overwrite_yesno() == YESNO_NO) { |
568 | rc = FORC_NOOVERWRT; | 473 | return FORC_NOOVERWRT; |
569 | break; | ||
570 | } | 474 | } |
571 | 475 | ||
572 | flags |= PASTE_OVERWRITE; | 476 | flags |= PASTE_OVERWRITE; |
573 | } | 477 | } |
574 | 478 | ||
479 | init_file_op(&src, src_path, NULL); | ||
480 | if (src.append >= sizeof (src.path)) | ||
481 | return FORC_PATH_TOO_LONG; | ||
575 | /* Now figure out what we're doing */ | 482 | /* Now figure out what we're doing */ |
576 | cpu_boost(true); | 483 | cpu_boost(true); |
577 | |||
578 | init_file_op(&src, src_path, NULL); | ||
579 | |||
580 | if (src.is_dir) { | 484 | if (src.is_dir) { |
581 | /* Copy or move a subdirectory */ | 485 | /* Copy or move a subdirectory */ |
582 | 486 | /* Try renaming first */ | |
583 | if (src.append < sizeof (src.path)) { | 487 | rc = move_by_rename(src.path, dst.path, &flags); |
584 | /* Try renaming first */ | 488 | if (rc < FORC_SUCCESS) { |
585 | rc = move_by_rename(src.path, dst.path, &flags); | 489 | rc = check_count_fileobjects(&src); |
586 | if (rc != FORC_SUCCESS && rc != FORC_CANCELLED) { | 490 | if (rc == FORC_SUCCESS) { |
587 | if (check_count_fileobjects(&src) == FORC_SUCCESS) { | 491 | rc = copy_move_directory(&src, &dst, flags); |
588 | rc = copy_move_directory(&src, &dst, flags); | ||
589 | } | ||
590 | } | 492 | } |
591 | } | 493 | } |
592 | } else { | 494 | } else { |
@@ -595,12 +497,102 @@ int copy_move_fileobject(const char *src_path, const char *dst_path, unsigned in | |||
595 | } | 497 | } |
596 | 498 | ||
597 | cpu_boost(false); | 499 | cpu_boost(false); |
598 | break; | 500 | DEBUGF("%s res: %d, ct: %d/%d %s\n", |
501 | __func__, rc, src.objects, src.processed, src.path); | ||
502 | return rc; | ||
503 | } | ||
504 | |||
505 | /* Else Some other relation / failure */ | ||
506 | DEBUGF("%s res: %d, rel: %d\n", __func__, rc, rel); | ||
507 | return FORC_UNKNOWN_FAILURE; | ||
508 | } | ||
509 | |||
510 | int create_dir(void) | ||
511 | { | ||
512 | int rc; | ||
513 | char dirname[MAX_PATH]; | ||
514 | size_t pathlen = path_append(dirname, getcwd(NULL, 0), PA_SEP_HARD, | ||
515 | sizeof (dirname)); | ||
516 | char *basename = dirname + pathlen; | ||
517 | |||
518 | if (pathlen >= sizeof (dirname)) | ||
519 | return FORC_PATH_TOO_LONG; | ||
520 | |||
521 | rc = prompt_name(basename, sizeof (dirname) - pathlen); | ||
522 | if (rc == FORC_SUCCESS) | ||
523 | rc = mkdir(dirname) * 10; | ||
524 | return rc; | ||
525 | } | ||
599 | 526 | ||
600 | case RELATE_PREFIX: | 527 | /* share code for file and directory deletion, saves space */ |
601 | default: /* Some other relation / failure */ | 528 | int delete_fileobject(const char *selected_file) |
602 | break; | 529 | { |
530 | int rc; | ||
531 | struct file_op_params param; | ||
532 | init_file_op(¶m, selected_file, NULL); | ||
533 | if (param.append >= sizeof (param.path)) | ||
534 | return FORC_PATH_TOO_LONG; | ||
535 | |||
536 | if (param.is_dir) { | ||
537 | int rc = check_count_fileobjects(¶m); | ||
538 | DEBUGF("%s res: %d, ct: %d, %s", __func__, rc, param.objects, param.path); | ||
539 | if (rc != FORC_SUCCESS) | ||
540 | return rc; | ||
541 | } | ||
542 | |||
543 | /* Note: delete_fileobject() will happily delete whatever | ||
544 | * path is passed (after confirmation) */ | ||
545 | if (confirm_delete_yesno(param.path) != YESNO_YES) { | ||
546 | return FORC_CANCELLED; | ||
547 | } | ||
548 | |||
549 | clear_screen_buffer(true); | ||
550 | if (poll_cancel_action(param.path, FOC_DELETE, param.processed, param.objects)) | ||
551 | return FORC_CANCELLED; | ||
552 | |||
553 | if (param.is_dir) { /* if directory */ | ||
554 | cpu_boost(true); | ||
555 | rc = directory_fileop(¶m, FOC_DELETE); | ||
556 | cpu_boost(false); | ||
557 | } else { | ||
558 | rc = remove(param.path) * 10; | ||
603 | } | 559 | } |
604 | 560 | ||
605 | return rc; | 561 | return rc; |
606 | } | 562 | } |
563 | |||
564 | int rename_file(const char *selected_file) | ||
565 | { | ||
566 | int rc; | ||
567 | char newname[MAX_PATH]; | ||
568 | const char *oldbase, *selection = selected_file; | ||
569 | |||
570 | path_basename(selection, &oldbase); | ||
571 | size_t pathlen = oldbase - selection; | ||
572 | char *newbase = newname + pathlen; | ||
573 | |||
574 | if (strmemccpy(newname, selection, sizeof (newname)) == NULL) | ||
575 | return FORC_PATH_TOO_LONG; | ||
576 | |||
577 | rc = prompt_name(newbase, sizeof (newname) - pathlen); | ||
578 | |||
579 | if (rc != FORC_SUCCESS) | ||
580 | return rc; | ||
581 | |||
582 | if (!strcmp(oldbase, newbase)) | ||
583 | return FORC_NOOP; /* No change at all */ | ||
584 | |||
585 | int rel = relate(selection, newname); | ||
586 | if (rel == RELATE_DIFFERENT) | ||
587 | { | ||
588 | if (file_exists(newname)) { /* don't overwrite */ | ||
589 | return FORC_PATH_EXISTS; | ||
590 | } | ||
591 | return rename(selection, newname) * 10; | ||
592 | } | ||
593 | if (rel == RELATE_SAME) | ||
594 | return rename(selection, newname) * 10; | ||
595 | |||
596 | /* Else Some other relation / failure */ | ||
597 | return FORC_UNKNOWN_FAILURE; | ||
598 | } | ||