comparison src/filepath.c @ 30150:0fe61fa4e5d1 v9.0.0411

patch 9.0.0411: only created files can be cleaned up with one call Commit: https://github.com/vim/vim/commit/6f14da15ac900589f2f413d77898b9bff3b31ece Author: Bram Moolenaar <Bram@vim.org> Date: Wed Sep 7 21:30:44 2022 +0100 patch 9.0.0411: only created files can be cleaned up with one call Problem: Only created files can be cleaned up with one call. Solution: Add flags to mkdir() to delete with a deferred function. Expand the writefile() name to a full path to handle changing directory.
author Bram Moolenaar <Bram@vim.org>
date Wed, 07 Sep 2022 22:45:04 +0200
parents a542dfb1c1a2
children b3de17181c19
comparison
equal deleted inserted replaced
30149:58dd17222e56 30150:0fe61fa4e5d1
1426 } 1426 }
1427 1427
1428 /* 1428 /*
1429 * Create the directory in which "dir" is located, and higher levels when 1429 * Create the directory in which "dir" is located, and higher levels when
1430 * needed. 1430 * needed.
1431 * Set "created" to the full name of the first created directory. It will be
1432 * NULL until that happens.
1431 * Return OK or FAIL. 1433 * Return OK or FAIL.
1432 */ 1434 */
1433 static int 1435 static int
1434 mkdir_recurse(char_u *dir, int prot) 1436 mkdir_recurse(char_u *dir, int prot, char_u **created)
1435 { 1437 {
1436 char_u *p; 1438 char_u *p;
1437 char_u *updir; 1439 char_u *updir;
1438 int r = FAIL; 1440 int r = FAIL;
1439 1441
1447 updir = vim_strnsave(dir, p - dir); 1449 updir = vim_strnsave(dir, p - dir);
1448 if (updir == NULL) 1450 if (updir == NULL)
1449 return FAIL; 1451 return FAIL;
1450 if (mch_isdir(updir)) 1452 if (mch_isdir(updir))
1451 r = OK; 1453 r = OK;
1452 else if (mkdir_recurse(updir, prot) == OK) 1454 else if (mkdir_recurse(updir, prot, created) == OK)
1455 {
1453 r = vim_mkdir_emsg(updir, prot); 1456 r = vim_mkdir_emsg(updir, prot);
1457 if (r == OK && created != NULL && *created == NULL)
1458 *created = FullName_save(updir, FALSE);
1459 }
1454 vim_free(updir); 1460 vim_free(updir);
1455 return r; 1461 return r;
1456 } 1462 }
1457 1463
1458 /* 1464 /*
1462 f_mkdir(typval_T *argvars, typval_T *rettv) 1468 f_mkdir(typval_T *argvars, typval_T *rettv)
1463 { 1469 {
1464 char_u *dir; 1470 char_u *dir;
1465 char_u buf[NUMBUFLEN]; 1471 char_u buf[NUMBUFLEN];
1466 int prot = 0755; 1472 int prot = 0755;
1473 int defer = FALSE;
1474 int defer_recurse = FALSE;
1475 char_u *created = NULL;
1467 1476
1468 rettv->vval.v_number = FAIL; 1477 rettv->vval.v_number = FAIL;
1469 if (check_restricted() || check_secure()) 1478 if (check_restricted() || check_secure())
1470 return; 1479 return;
1471 1480
1484 // remove trailing slashes 1493 // remove trailing slashes
1485 *gettail_sep(dir) = NUL; 1494 *gettail_sep(dir) = NUL;
1486 1495
1487 if (argvars[1].v_type != VAR_UNKNOWN) 1496 if (argvars[1].v_type != VAR_UNKNOWN)
1488 { 1497 {
1498 char_u *arg2;
1499
1489 if (argvars[2].v_type != VAR_UNKNOWN) 1500 if (argvars[2].v_type != VAR_UNKNOWN)
1490 { 1501 {
1491 prot = (int)tv_get_number_chk(&argvars[2], NULL); 1502 prot = (int)tv_get_number_chk(&argvars[2], NULL);
1492 if (prot == -1) 1503 if (prot == -1)
1493 return; 1504 return;
1494 } 1505 }
1495 if (STRCMP(tv_get_string(&argvars[1]), "p") == 0) 1506 arg2 = tv_get_string(&argvars[1]);
1507 defer = vim_strchr(arg2, 'D') != NULL;
1508 defer_recurse = vim_strchr(arg2, 'R') != NULL;
1509 if ((defer || defer_recurse) && !can_add_defer())
1510 return;
1511
1512 if (vim_strchr(arg2, 'p') != NULL)
1496 { 1513 {
1497 if (mch_isdir(dir)) 1514 if (mch_isdir(dir))
1498 { 1515 {
1499 // With the "p" flag it's OK if the dir already exists. 1516 // With the "p" flag it's OK if the dir already exists.
1500 rettv->vval.v_number = OK; 1517 rettv->vval.v_number = OK;
1501 return; 1518 return;
1502 } 1519 }
1503 mkdir_recurse(dir, prot); 1520 mkdir_recurse(dir, prot, defer || defer_recurse ? &created : NULL);
1504 } 1521 }
1505 } 1522 }
1506 rettv->vval.v_number = vim_mkdir_emsg(dir, prot); 1523 rettv->vval.v_number = vim_mkdir_emsg(dir, prot);
1524
1525 // Handle "D" and "R": deferred deletion of the created directory.
1526 if (rettv->vval.v_number == OK
1527 && created == NULL && (defer || defer_recurse))
1528 created = FullName_save(dir, FALSE);
1529 if (created != NULL)
1530 {
1531 typval_T tv[2];
1532
1533 tv[0].v_type = VAR_STRING;
1534 tv[0].v_lock = 0;
1535 tv[0].vval.v_string = created;
1536 tv[1].v_type = VAR_STRING;
1537 tv[1].v_lock = 0;
1538 tv[1].vval.v_string = vim_strsave(
1539 (char_u *)(defer_recurse ? "rf" : "d"));
1540 if (tv[0].vval.v_string == NULL || tv[1].vval.v_string == NULL
1541 || add_defer((char_u *)"delete", 2, tv) == FAIL)
1542 {
1543 vim_free(tv[0].vval.v_string);
1544 vim_free(tv[1].vval.v_string);
1545 }
1546 }
1507 } 1547 }
1508 1548
1509 /* 1549 /*
1510 * "pathshorten()" function 1550 * "pathshorten()" function
1511 */ 1551 */
2298 2338
2299 fname = tv_get_string_chk(&argvars[1]); 2339 fname = tv_get_string_chk(&argvars[1]);
2300 if (fname == NULL) 2340 if (fname == NULL)
2301 return; 2341 return;
2302 2342
2303 if (defer && !in_def_function() && get_current_funccal() == NULL) 2343 if (defer && !can_add_defer())
2304 { 2344 return;
2305 semsg(_(e_str_not_inside_function), "defer");
2306 return;
2307 }
2308 2345
2309 // Always open the file in binary mode, library functions have a mind of 2346 // Always open the file in binary mode, library functions have a mind of
2310 // their own about CR-LF conversion. 2347 // their own about CR-LF conversion.
2311 if (*fname == NUL || (fd = mch_fopen((char *)fname, 2348 if (*fname == NUL || (fd = mch_fopen((char *)fname,
2312 append ? APPENDBIN : WRITEBIN)) == NULL) 2349 append ? APPENDBIN : WRITEBIN)) == NULL)
2321 { 2358 {
2322 typval_T tv; 2359 typval_T tv;
2323 2360
2324 tv.v_type = VAR_STRING; 2361 tv.v_type = VAR_STRING;
2325 tv.v_lock = 0; 2362 tv.v_lock = 0;
2326 tv.vval.v_string = vim_strsave(fname); 2363 tv.vval.v_string = FullName_save(fname, FALSE);
2327 if (tv.vval.v_string == NULL 2364 if (tv.vval.v_string == NULL
2328 || add_defer((char_u *)"delete", 1, &tv) == FAIL) 2365 || add_defer((char_u *)"delete", 1, &tv) == FAIL)
2329 { 2366 {
2330 ret = -1; 2367 ret = -1;
2331 fclose(fd); 2368 fclose(fd);