|
4 | 4 |
|
5 | 5 | #include "../config.h" |
6 | 6 |
|
| 7 | +#include <assert.h> |
| 8 | +#include <dos.h> |
7 | 9 | #include <io.h> |
| 10 | +#include <stdio.h> |
| 11 | +#include <stdlib.h> |
| 12 | +#include <string.h> |
| 13 | + |
| 14 | +#include "suppl.h" |
| 15 | +#include "dfn.h" |
8 | 16 |
|
9 | 17 | #include "../include/command.h" |
10 | 18 | #include "../include/misc.h" |
11 | 19 | #include "../include/lfnfuncs.h" |
| 20 | +#include "../err_fcts.h" |
| 21 | +#include "../strings.h" |
12 | 22 |
|
13 | | -int recursive_rmdir(const char * path, int optRecursiveMode, int optQuiet) |
| 23 | +#ifdef FEATURE_LONG_FILENAMES |
| 24 | +#define abspath( x, y ) abspath( getshortfilename( x ), y ) |
| 25 | +#endif |
| 26 | + |
| 27 | +/* recursively delete subdirs and files */ |
| 28 | +int rmdir_withfiles(char * path, int maxlen) |
14 | 29 | { |
15 | | - /* optQuiet effects parsing showing errors, but no effect on recursive call */ |
16 | | - (void) optQuiet; |
| 30 | + struct dos_ffblk f; |
| 31 | + int len = strlen(path); /* Warning: we assume path is a buffer is large enough for longest file path */ |
| 32 | + char *p = path+len; |
| 33 | + |
| 34 | + /* ensure ends with \ */ |
| 35 | + if (p[-1] != '\\') |
| 36 | + *p++ = '\\'; |
| 37 | + *p = '\0'; |
17 | 38 |
|
| 39 | + dprintf(("rmdir(%s)\n", path)); |
| 40 | + |
| 41 | + /* cycle through removing directories first */ |
| 42 | + stpcpy(p, "*.*"); |
| 43 | + if (!dos_findfirst(path, &f, FA_DIREC)) { |
| 44 | + int ret = 0; |
| 45 | + do { |
| 46 | + /* skip . and .. directory entries */ |
| 47 | + if ((strcmp(f.ff_name, ".")==0) || |
| 48 | + (strcmp(f.ff_name, "..")==0)) |
| 49 | + continue; |
| 50 | + |
| 51 | + if (f.ff_attrib & FA_DIREC) { |
| 52 | + dprintf(("name=%s\n", f.ff_name)); |
| 53 | + /* avoid overflowing our buffer */ |
| 54 | + if((len + strlen(f.ff_name)) > maxlen) { |
| 55 | + error_filename_too_long(p); |
| 56 | + return E_Other; |
| 57 | + } |
| 58 | + |
| 59 | + strcpy(p, f.ff_name); /* Make the full path */ |
| 60 | + /* recursively delete subdirectory */ |
| 61 | + ret = rmdir_withfiles(path, maxlen); |
| 62 | + } |
| 63 | + } while (!ret && (dos_findnext(&f) == 0)); |
| 64 | + dos_findclose(&f); |
| 65 | + /* return early on error */ |
| 66 | + if (ret) return ret; |
| 67 | + } |
| 68 | + |
| 69 | + /* remove any files in current directory */ |
| 70 | + stpcpy(p, "*.*"); |
| 71 | + if (!dos_findfirst(path, &f, FA_NORMAL)) { |
| 72 | + do { |
| 73 | + /* avoid overflowing our buffer */ |
| 74 | + if((len + strlen(f.ff_name)) > maxlen) { |
| 75 | + error_filename_too_long(p); |
| 76 | + return E_Other; |
| 77 | + } |
| 78 | + |
| 79 | + strcpy(p, f.ff_name); /* Make the full path */ |
| 80 | + dprintf(("deleting [%s]\n", path)); |
| 81 | + /* try to delete the file */ |
| 82 | + if(unlink(path) != 0) |
| 83 | + myperror(path); /* notify the user */ |
| 84 | + } while (dos_findnext(&f) == 0); |
| 85 | + dos_findclose(&f); |
| 86 | + } |
| 87 | + |
| 88 | + /* finally actually remove the directory */ |
| 89 | + *p = '\0'; |
| 90 | + return rmdir(path); |
| 91 | +} |
| 92 | + |
| 93 | +int recursive_rmdir(const char * path, int optRecursiveMode, int optQuiet) |
| 94 | +{ |
18 | 95 | if (optRecursiveMode) { |
19 | | - return 0; |
| 96 | + struct dos_ffblk f; |
| 97 | + char fullname[MAXPATH + sizeof(f.ff_name) + 2], *p; |
| 98 | + int len; |
| 99 | + /* Get the pattern fully-qualified */ |
| 100 | + /* Note: An absolute path always contains: |
| 101 | + A:\\ |
| 102 | + --> It's always three bytes long at minimum |
| 103 | + and always contains a backslash */ |
| 104 | + p = abspath(path, 1); |
| 105 | + if(!p) |
| 106 | + return E_Other; |
| 107 | + assert(strlen(p) >= 3); |
| 108 | + |
| 109 | + if((len = strlen(p)) >= MAXPATH) { |
| 110 | + error_filename_too_long(p); |
| 111 | + free(p); |
| 112 | + return E_Other; |
| 113 | + } |
| 114 | + strcpy(fullname, p); |
| 115 | + free(p); |
| 116 | + p = fullname + len; |
| 117 | + |
| 118 | + /* validate path exists and is a directory */ |
| 119 | + if(!(dfnstat(fullname) & DFN_DIRECTORY)) { |
| 120 | + /* not a directory */ |
| 121 | + return E_Other; |
| 122 | + } |
| 123 | + |
| 124 | + /* ensure ends with \ */ |
| 125 | + if (p[-1] != '\\') |
| 126 | + *p++ = '\\'; |
| 127 | + *p = 0; |
| 128 | + |
| 129 | + /* prompt user if they are sure, regardless if files or not */ |
| 130 | + if (!optQuiet) { |
| 131 | + int r; |
| 132 | + r = userprompt(PROMPT_DELETE_ALL, fullname); /* Are you sure? TODO fix me */ |
| 133 | + |
| 134 | + if (r != 1) { |
| 135 | + return E_Other; |
| 136 | + } |
| 137 | + } |
| 138 | + |
| 139 | + return rmdir_withfiles(fullname, sizeof(fullname)); |
20 | 140 | } else { |
21 | 141 | return rmdir(path); |
22 | 142 | } |
|
0 commit comments