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;