Mercurial > vim
comparison src/fileio.c @ 16752:e2d8d83e6721 v8.1.1378
patch 8.1.1378: delete() can not handle a file name that looks like a pattern
commit https://github.com/vim/vim/commit/701ff0a3e53d253d7300c385e582659bbff7860d
Author: Bram Moolenaar <Bram@vim.org>
Date: Fri May 24 14:14:14 2019 +0200
patch 8.1.1378: delete() can not handle a file name that looks like a pattern
Problem: Delete() can not handle a file name that looks like a pattern.
Solution: Use readdir() instead of appending "/*" and expanding wildcards.
(Ken Takata, closes #4424, closes #696)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Fri, 24 May 2019 14:15:04 +0200 |
parents | e42e9fa83e60 |
children | 8b92f3fea477 |
comparison
equal
deleted
inserted
replaced
16751:29ae90e9f16a | 16752:e2d8d83e6721 |
---|---|
7170 curbuf->b_no_eol_lnum += offset; | 7170 curbuf->b_no_eol_lnum += offset; |
7171 } | 7171 } |
7172 | 7172 |
7173 #if defined(TEMPDIRNAMES) || defined(FEAT_EVAL) || defined(PROTO) | 7173 #if defined(TEMPDIRNAMES) || defined(FEAT_EVAL) || defined(PROTO) |
7174 /* | 7174 /* |
7175 * Core part of "readdir()" function. | |
7176 * Retrieve the list of files/directories of "path" into "gap". | |
7177 * Return OK for success, FAIL for failure. | |
7178 */ | |
7179 int | |
7180 readdir_core( | |
7181 garray_T *gap, | |
7182 char_u *path, | |
7183 void *context, | |
7184 int (*checkitem)(void *context, char_u *name)) | |
7185 { | |
7186 int failed = FALSE; | |
7187 #ifdef MSWIN | |
7188 char_u *buf, *p; | |
7189 int ok; | |
7190 HANDLE hFind = INVALID_HANDLE_VALUE; | |
7191 WIN32_FIND_DATAW wfb; | |
7192 WCHAR *wn = NULL; // UTF-16 name, NULL when not used. | |
7193 #endif | |
7194 | |
7195 ga_init2(gap, (int)sizeof(char *), 20); | |
7196 | |
7197 #ifdef MSWIN | |
7198 buf = alloc((int)MAXPATHL); | |
7199 if (buf == NULL) | |
7200 return FAIL; | |
7201 STRNCPY(buf, path, MAXPATHL-5); | |
7202 p = buf + strlen(buf); | |
7203 MB_PTR_BACK(buf, p); | |
7204 if (*p == '\\' || *p == '/') | |
7205 *p = NUL; | |
7206 STRCAT(buf, "\\*"); | |
7207 | |
7208 wn = enc_to_utf16(buf, NULL); | |
7209 if (wn != NULL) | |
7210 hFind = FindFirstFileW(wn, &wfb); | |
7211 ok = (hFind != INVALID_HANDLE_VALUE); | |
7212 if (!ok) | |
7213 { | |
7214 failed = TRUE; | |
7215 smsg(_(e_notopen), path); | |
7216 } | |
7217 else | |
7218 { | |
7219 while (ok) | |
7220 { | |
7221 int ignore; | |
7222 | |
7223 p = utf16_to_enc(wfb.cFileName, NULL); // p is allocated here | |
7224 if (p == NULL) | |
7225 break; // out of memory | |
7226 | |
7227 ignore = p[0] == '.' && (p[1] == NUL | |
7228 || (p[1] == '.' && p[2] == NUL)); | |
7229 if (!ignore && checkitem != NULL) | |
7230 { | |
7231 int r = checkitem(context, p); | |
7232 | |
7233 if (r < 0) | |
7234 { | |
7235 vim_free(p); | |
7236 break; | |
7237 } | |
7238 if (r == 0) | |
7239 ignore = TRUE; | |
7240 } | |
7241 | |
7242 if (!ignore) | |
7243 { | |
7244 if (ga_grow(gap, 1) == OK) | |
7245 ((char_u**)gap->ga_data)[gap->ga_len++] = vim_strsave(p); | |
7246 else | |
7247 { | |
7248 failed = TRUE; | |
7249 vim_free(p); | |
7250 break; | |
7251 } | |
7252 } | |
7253 | |
7254 vim_free(p); | |
7255 ok = FindNextFileW(hFind, &wfb); | |
7256 } | |
7257 FindClose(hFind); | |
7258 } | |
7259 | |
7260 vim_free(buf); | |
7261 vim_free(wn); | |
7262 #else | |
7263 DIR *dirp; | |
7264 struct dirent *dp; | |
7265 char_u *p; | |
7266 | |
7267 dirp = opendir((char *)path); | |
7268 if (dirp == NULL) | |
7269 { | |
7270 failed = TRUE; | |
7271 smsg(_(e_notopen), path); | |
7272 } | |
7273 else | |
7274 { | |
7275 for (;;) | |
7276 { | |
7277 int ignore; | |
7278 | |
7279 dp = readdir(dirp); | |
7280 if (dp == NULL) | |
7281 break; | |
7282 p = (char_u *)dp->d_name; | |
7283 | |
7284 ignore = p[0] == '.' && | |
7285 (p[1] == NUL || | |
7286 (p[1] == '.' && p[2] == NUL)); | |
7287 if (!ignore && checkitem != NULL) | |
7288 { | |
7289 int r = checkitem(context, p); | |
7290 | |
7291 if (r < 0) | |
7292 break; | |
7293 if (r == 0) | |
7294 ignore = TRUE; | |
7295 } | |
7296 | |
7297 if (!ignore) | |
7298 { | |
7299 if (ga_grow(gap, 1) == OK) | |
7300 ((char_u**)gap->ga_data)[gap->ga_len++] = vim_strsave(p); | |
7301 else | |
7302 { | |
7303 failed = TRUE; | |
7304 break; | |
7305 } | |
7306 } | |
7307 } | |
7308 | |
7309 closedir(dirp); | |
7310 } | |
7311 #endif | |
7312 | |
7313 if (!failed && gap->ga_len > 0) | |
7314 sort_strings((char_u **)gap->ga_data, gap->ga_len); | |
7315 | |
7316 return failed ? FAIL : OK; | |
7317 } | |
7318 | |
7319 /* | |
7175 * Delete "name" and everything in it, recursively. | 7320 * Delete "name" and everything in it, recursively. |
7176 * return 0 for succes, -1 if some file was not deleted. | 7321 * return 0 for success, -1 if some file was not deleted. |
7177 */ | 7322 */ |
7178 int | 7323 int |
7179 delete_recursive(char_u *name) | 7324 delete_recursive(char_u *name) |
7180 { | 7325 { |
7181 int result = 0; | 7326 int result = 0; |
7182 char_u **files; | |
7183 int file_count; | |
7184 int i; | 7327 int i; |
7185 char_u *exp; | 7328 char_u *exp; |
7186 | 7329 garray_T ga; |
7187 /* A symbolic link to a directory itself is deleted, not the directory it | 7330 |
7188 * points to. */ | 7331 // A symbolic link to a directory itself is deleted, not the directory it |
7332 // points to. | |
7189 if ( | 7333 if ( |
7190 # if defined(UNIX) || defined(MSWIN) | 7334 # if defined(UNIX) || defined(MSWIN) |
7191 mch_isrealdir(name) | 7335 mch_isrealdir(name) |
7192 # else | 7336 # else |
7193 mch_isdir(name) | 7337 mch_isdir(name) |
7194 # endif | 7338 # endif |
7195 ) | 7339 ) |
7196 { | 7340 { |
7197 vim_snprintf((char *)NameBuff, MAXPATHL, "%s/*", name); | 7341 exp = vim_strsave(name); |
7198 exp = vim_strsave(NameBuff); | |
7199 if (exp == NULL) | 7342 if (exp == NULL) |
7200 return -1; | 7343 return -1; |
7201 if (gen_expand_wildcards(1, &exp, &file_count, &files, | 7344 if (readdir_core(&ga, exp, NULL, NULL) == OK) |
7202 EW_DIR|EW_FILE|EW_SILENT|EW_ALLLINKS|EW_DODOT|EW_EMPTYOK) == OK) | 7345 { |
7203 { | 7346 for (i = 0; i < ga.ga_len; ++i) |
7204 for (i = 0; i < file_count; ++i) | 7347 { |
7205 if (delete_recursive(files[i]) != 0) | 7348 vim_snprintf((char *)NameBuff, MAXPATHL, "%s/%s", exp, |
7349 ((char_u **)ga.ga_data)[i]); | |
7350 if (delete_recursive(NameBuff) != 0) | |
7206 result = -1; | 7351 result = -1; |
7207 FreeWild(file_count, files); | 7352 } |
7353 ga_clear_strings(&ga); | |
7208 } | 7354 } |
7209 else | 7355 else |
7210 result = -1; | 7356 result = -1; |
7357 (void)mch_rmdir(exp); | |
7211 vim_free(exp); | 7358 vim_free(exp); |
7212 (void)mch_rmdir(name); | |
7213 } | 7359 } |
7214 else | 7360 else |
7215 result = mch_remove(name) == 0 ? 0 : -1; | 7361 result = mch_remove(name) == 0 ? 0 : -1; |
7216 | 7362 |
7217 return result; | 7363 return result; |