memline.c (144754B)
1 // for debugging 2 // #define CHECK(c, s) do { if (c) emsg(s); } while (0) 3 #define CHECK(c, s) do {} while (0) 4 5 // memline.c: Contains the functions for appending, deleting and changing the 6 // text lines. The memfile functions are used to store the information in 7 // blocks of memory, backed up by a file. The structure of the information is 8 // a tree. The root of the tree is a pointer block. The leaves of the tree 9 // are data blocks. In between may be several layers of pointer blocks, 10 // forming branches. 11 // 12 // Three types of blocks are used: 13 // - Block nr 0 contains information for recovery 14 // - Pointer blocks contain list of pointers to other blocks. 15 // - Data blocks contain the actual text. 16 // 17 // Block nr 0 contains the block0 structure (see below). 18 // 19 // Block nr 1 is the first pointer block. It is the root of the tree. 20 // Other pointer blocks are branches. 21 // 22 // If a line is too big to fit in a single page, the block containing that 23 // line is made big enough to hold the line. It may span several pages. 24 // Otherwise all blocks are one page. 25 // 26 // A data block that was filled when starting to edit a file and was not 27 // changed since then, can have a negative block number. This means that it 28 // has not yet been assigned a place in the file. When recovering, the lines 29 // in this data block can be read from the original file. When the block is 30 // changed (lines appended/deleted/changed) or when it is flushed it gets a 31 // positive number. Use mf_trans_del() to get the new number, before calling 32 // mf_get(). 33 // 34 // "Mom, can we get ropes?" 35 // "We have ropes at home." 36 // Ropes at home: 37 38 #include <assert.h> 39 #include <errno.h> 40 #include <fcntl.h> 41 #include <inttypes.h> 42 #include <stdbool.h> 43 #include <stddef.h> 44 #include <stdio.h> 45 #include <string.h> 46 #include <time.h> 47 #include <uv.h> 48 49 #include "auto/config.h" 50 #include "klib/kvec.h" 51 #include "nvim/ascii_defs.h" 52 #include "nvim/autocmd.h" 53 #include "nvim/autocmd_defs.h" 54 #include "nvim/buffer.h" 55 #include "nvim/buffer_defs.h" 56 #include "nvim/change.h" 57 #include "nvim/cursor.h" 58 #include "nvim/drawscreen.h" 59 #include "nvim/eval/typval.h" 60 #include "nvim/eval/vars.h" 61 #include "nvim/ex_cmds_defs.h" 62 #include "nvim/fileio.h" 63 #include "nvim/getchar.h" 64 #include "nvim/gettext_defs.h" 65 #include "nvim/globals.h" 66 #include "nvim/highlight_defs.h" 67 #include "nvim/input.h" 68 #include "nvim/macros_defs.h" 69 #include "nvim/main.h" 70 #include "nvim/map_defs.h" 71 #include "nvim/mark.h" 72 #include "nvim/mbyte.h" 73 #include "nvim/memfile.h" 74 #include "nvim/memfile_defs.h" 75 #include "nvim/memline.h" 76 #include "nvim/memory.h" 77 #include "nvim/message.h" 78 #include "nvim/option.h" 79 #include "nvim/option_defs.h" 80 #include "nvim/option_vars.h" 81 #include "nvim/os/fs.h" 82 #include "nvim/os/fs_defs.h" 83 #include "nvim/os/input.h" 84 #include "nvim/os/os.h" 85 #include "nvim/os/os_defs.h" 86 #include "nvim/os/proc.h" 87 #include "nvim/os/time.h" 88 #include "nvim/os/time_defs.h" 89 #include "nvim/path.h" 90 #include "nvim/pos_defs.h" 91 #include "nvim/spell.h" 92 #include "nvim/statusline.h" 93 #include "nvim/strings.h" 94 #include "nvim/ui.h" 95 #include "nvim/undo.h" 96 #include "nvim/version.h" 97 #include "nvim/vim_defs.h" 98 99 #ifndef UNIX // it's in os/unix_defs.h for Unix 100 # include <time.h> 101 #endif 102 103 enum { 104 DATA_ID = (('d' << 8) + 'a'), // data block id 105 PTR_ID = (('p' << 8) + 't'), // pointer block id 106 BLOCK0_ID0 = 'b', // block 0 id 0 107 BLOCK0_ID1 = '0', // block 0 id 1 108 }; 109 110 // pointer to a block, used in a pointer block 111 typedef struct { 112 blocknr_T pe_bnum; // block number 113 linenr_T pe_line_count; // number of lines in this branch 114 linenr_T pe_old_lnum; // lnum for this block (for recovery) 115 int pe_page_count; // number of pages in block pe_bnum 116 } PointerEntry; 117 118 // A pointer block contains a list of branches in the tree. 119 typedef struct { 120 uint16_t pb_id; // ID for pointer block: PTR_ID 121 uint16_t pb_count; // number of pointers in this block 122 uint16_t pb_count_max; // maximum value for pb_count 123 PointerEntry pb_pointer[]; // list of pointers to blocks 124 // followed by empty space until end of page 125 } PointerBlock; 126 127 // Value for pb_count_max. 128 #define PB_COUNT_MAX(mfp) \ 129 (uint16_t)((mfp->mf_page_size - offsetof(PointerBlock, pb_pointer)) / sizeof(PointerEntry)) 130 131 // A data block is a leaf in the tree. 132 // 133 // The text of the lines is at the end of the block. The text of the first line 134 // in the block is put at the end, the text of the second line in front of it, 135 // etc. Thus the order of the lines is the opposite of the line number. 136 typedef struct { 137 uint16_t db_id; // ID for data block: DATA_ID 138 unsigned db_free; // free space available 139 unsigned db_txt_start; // byte where text starts 140 unsigned db_txt_end; // byte just after data block 141 // linenr_T db_line_count; 142 long db_line_count; // number of lines in this block 143 unsigned db_index[]; // index for start of line 144 // followed by empty space up to db_txt_start 145 // followed by the text in the lines until 146 // end of page 147 } DataBlock; 148 149 // The low bits of db_index hold the actual index. The topmost bit is 150 // used for the global command to be able to mark a line. 151 // This method is not clean, but otherwise there would be at least one extra 152 // byte used for each line. 153 // The mark has to be in this place to keep it with the correct line when other 154 // lines are inserted or deleted. 155 #define DB_MARKED ((unsigned)1 << ((sizeof(unsigned) * 8) - 1)) 156 #define DB_INDEX_MASK (~DB_MARKED) 157 158 #define INDEX_SIZE (sizeof(unsigned)) // size of one db_index entry 159 #define HEADER_SIZE (offsetof(DataBlock, db_index)) // size of data block header 160 161 enum { 162 B0_FNAME_SIZE_ORG = 900, // what it was in older versions 163 B0_FNAME_SIZE_NOCRYPT = 898, // 2 bytes used for other things 164 B0_FNAME_SIZE_CRYPT = 890, // 10 bytes used for other things 165 B0_UNAME_SIZE = 40, 166 B0_HNAME_SIZE = 40, 167 }; 168 // Restrict the numbers to 32 bits, otherwise most compilers will complain. 169 // This won't detect a 64 bit machine that only swaps a byte in the top 32 170 // bits, but that is crazy anyway. 171 enum { 172 B0_MAGIC_LONG = 0x30313233, 173 B0_MAGIC_INT = 0x20212223, 174 B0_MAGIC_SHORT = 0x10111213, 175 B0_MAGIC_CHAR = 0x55, 176 }; 177 178 /// Block zero holds all info about the swapfile. This is the first block in the file. 179 /// 180 /// NOTE: DEFINITION OF BLOCK 0 SHOULD NOT CHANGE! It would make all existing swapfiles unusable! 181 /// 182 /// If size of block0 changes anyway, adjust MIN_SWAP_PAGE_SIZE in memfile.h!! 183 /// 184 /// This block is built up of single bytes, to make it portable across 185 /// different machines. b0_magic_* is used to check the byte order and size of 186 /// variables, because the rest of the swapfile is not portable. 187 typedef struct { 188 char b0_id[2]; ///< ID for block 0: BLOCK0_ID0 and BLOCK0_ID1. 189 char b0_version[10]; ///< Vim version string 190 char b0_page_size[4]; ///< number of bytes per page 191 char b0_mtime[4]; ///< last modification time of file 192 char b0_ino[4]; ///< inode of b0_fname 193 char b0_pid[4]; ///< process id of creator (or 0) 194 char b0_uname[B0_UNAME_SIZE]; ///< name of user (uid if no name) 195 char b0_hname[B0_HNAME_SIZE]; ///< host name (if it has a name) 196 char b0_fname[B0_FNAME_SIZE_ORG]; ///< name of file being edited 197 long b0_magic_long; ///< check for byte order of long 198 int b0_magic_int; ///< check for byte order of int 199 int16_t b0_magic_short; ///< check for byte order of short 200 char b0_magic_char; ///< check for last char 201 } ZeroBlock; 202 203 // Note: b0_dirty and b0_flags are put at the end of the file name. For very 204 // long file names in older versions of Vim they are invalid. 205 // The 'fileencoding' comes before b0_flags, with a NUL in front. But only 206 // when there is room, for very long file names it's omitted. 207 #define B0_DIRTY 0x55 208 #define b0_dirty b0_fname[B0_FNAME_SIZE_ORG - 1] 209 210 // The b0_flags field is new in Vim 7.0. 211 #define b0_flags b0_fname[B0_FNAME_SIZE_ORG - 2] 212 213 // The lowest two bits contain the fileformat. Zero means it's not set 214 // (compatible with Vim 6.x), otherwise it's EOL_UNIX + 1, EOL_DOS + 1 or 215 // EOL_MAC + 1. 216 #define B0_FF_MASK 3 217 218 // Swapfile is in directory of edited file. Used to find the file from different mount points. 219 #define B0_SAME_DIR 4 220 221 // The 'fileencoding' is at the end of b0_fname[], with a NUL in front of it. 222 // When empty there is only the NUL. 223 #define B0_HAS_FENC 8 224 225 #define STACK_INCR 5 // nr of entries added to ml_stack at a time 226 227 // The line number where the first mark may be is remembered. 228 // If it is 0 there are no marks at all. 229 // (always used for the current buffer only, no buffer change possible while 230 // executing a global command). 231 static linenr_T lowest_marked = 0; 232 233 // arguments for ml_find_line() 234 enum { 235 ML_DELETE = 0x11, // delete line 236 ML_INSERT = 0x12, // insert line 237 ML_FIND = 0x13, // just find the line 238 ML_FLUSH = 0x02, // flush locked block 239 }; 240 #define ML_SIMPLE(x) ((x) & 0x10) // DEL, INS or FIND 241 242 // argument for ml_upd_block0() 243 typedef enum { 244 UB_FNAME = 0, // update timestamp and filename 245 UB_SAME_DIR, // update the B0_SAME_DIR flag 246 } upd_block0_T; 247 248 typedef enum { 249 SEA_CHOICE_NONE = 0, 250 SEA_CHOICE_READONLY = 1, 251 SEA_CHOICE_EDIT = 2, 252 SEA_CHOICE_RECOVER = 3, 253 SEA_CHOICE_DELETE = 4, 254 SEA_CHOICE_QUIT = 5, 255 SEA_CHOICE_ABORT = 6, 256 } sea_choice_T; 257 258 #include "memline.c.generated.h" 259 260 static const char e_ml_get_invalid_lnum_nr[] 261 = N_("E315: ml_get: Invalid lnum: %" PRId64); 262 static const char e_ml_get_cannot_find_line_nr_in_buffer_nr_str[] 263 = N_("E316: ml_get: Cannot find line %" PRId64 "in buffer %d %s"); 264 static const char e_pointer_block_id_wrong[] 265 = N_("E317: Pointer block id wrong"); 266 static const char e_pointer_block_id_wrong_two[] 267 = N_("E317: Pointer block id wrong 2"); 268 static const char e_pointer_block_id_wrong_three[] 269 = N_("E317: Pointer block id wrong 3"); 270 static const char e_pointer_block_id_wrong_four[] 271 = N_("E317: Pointer block id wrong 4"); 272 static const char e_line_number_out_of_range_nr_past_the_end[] 273 = N_("E322: Line number out of range: %" PRId64 " past the end"); 274 static const char e_line_count_wrong_in_block_nr[] 275 = N_("E323: Line count wrong in block %" PRId64); 276 static const char e_warning_pointer_block_corrupted[] 277 = N_("E1364: Warning: Pointer block corrupted"); 278 279 #if __has_feature(address_sanitizer) 280 # define ML_GET_ALLOC_LINES 281 #endif 282 283 /// Open a new memline for "buf". 284 /// 285 /// @return FAIL for failure, OK otherwise. 286 int ml_open(buf_T *buf) 287 { 288 // init fields in memline struct 289 buf->b_ml.ml_stack_size = 0; // no stack yet 290 buf->b_ml.ml_stack = NULL; // no stack yet 291 buf->b_ml.ml_stack_top = 0; // nothing in the stack 292 buf->b_ml.ml_locked = NULL; // no cached block 293 buf->b_ml.ml_line_lnum = 0; // no cached line 294 buf->b_ml.ml_line_offset = 0; 295 buf->b_ml.ml_chunksize = NULL; 296 buf->b_ml.ml_usedchunks = 0; 297 298 if (cmdmod.cmod_flags & CMOD_NOSWAPFILE) { 299 buf->b_p_swf = false; 300 } 301 302 // When 'updatecount' is non-zero swapfile may be opened later. 303 if (!buf->terminal && p_uc && buf->b_p_swf) { 304 buf->b_may_swap = true; 305 } else { 306 buf->b_may_swap = false; 307 } 308 309 // Open the memfile. No swapfile is created yet. 310 memfile_T *mfp = mf_open(NULL, 0); 311 if (mfp == NULL) { 312 goto error; 313 } 314 315 buf->b_ml.ml_mfp = mfp; 316 buf->b_ml.ml_flags = ML_EMPTY; 317 buf->b_ml.ml_line_count = 1; 318 319 // fill block0 struct and write page 0 320 bhdr_T *hp = mf_new(mfp, false, 1); 321 if (hp->bh_bnum != 0) { 322 iemsg(_("E298: Didn't get block nr 0?")); 323 goto error; 324 } 325 ZeroBlock *b0p = hp->bh_data; 326 327 b0p->b0_id[0] = BLOCK0_ID0; 328 b0p->b0_id[1] = BLOCK0_ID1; 329 b0p->b0_magic_long = B0_MAGIC_LONG; 330 b0p->b0_magic_int = B0_MAGIC_INT; 331 b0p->b0_magic_short = (int16_t)B0_MAGIC_SHORT; 332 b0p->b0_magic_char = B0_MAGIC_CHAR; 333 xstrlcpy(xstpcpy(b0p->b0_version, "VIM "), Versions[0], 6); 334 long_to_char((long)mfp->mf_page_size, b0p->b0_page_size); 335 336 if (!buf->b_spell) { 337 b0p->b0_dirty = buf->b_changed ? B0_DIRTY : 0; 338 b0p->b0_flags = (char)(get_fileformat(buf) + 1); 339 set_b0_fname(b0p, buf); 340 os_get_username(b0p->b0_uname, B0_UNAME_SIZE); 341 b0p->b0_uname[B0_UNAME_SIZE - 1] = NUL; 342 os_get_hostname(b0p->b0_hname, B0_HNAME_SIZE); 343 b0p->b0_hname[B0_HNAME_SIZE - 1] = NUL; 344 long_to_char((long)os_get_pid(), b0p->b0_pid); 345 } 346 347 // Always sync block number 0 to disk, so we can check the file name in 348 // the swapfile in findswapname(). Don't do this for a help files or 349 // a spell buffer though. 350 // Only works when there's a swapfile, otherwise it's done when the file 351 // is created. 352 mf_put(mfp, hp, true, false); 353 if (!buf->b_help && !buf->b_spell) { 354 mf_sync(mfp, 0); 355 } 356 357 // Fill in root pointer block and write page 1. 358 hp = ml_new_ptr(mfp); 359 assert(hp != NULL); 360 if (hp->bh_bnum != 1) { 361 iemsg(_("E298: Didn't get block nr 1?")); 362 goto error; 363 } 364 PointerBlock *pp = hp->bh_data; 365 pp->pb_count = 1; 366 pp->pb_pointer[0].pe_bnum = 2; 367 pp->pb_pointer[0].pe_page_count = 1; 368 pp->pb_pointer[0].pe_old_lnum = 1; 369 pp->pb_pointer[0].pe_line_count = 1; // line count after insertion 370 mf_put(mfp, hp, true, false); 371 372 // Allocate first data block and create an empty line 1. 373 hp = ml_new_data(mfp, false, 1); 374 if (hp->bh_bnum != 2) { 375 iemsg(_("E298: Didn't get block nr 2?")); 376 goto error; 377 } 378 379 DataBlock *dp = hp->bh_data; 380 dp->db_index[0] = --dp->db_txt_start; // at end of block 381 dp->db_free -= 1 + (unsigned)INDEX_SIZE; 382 dp->db_line_count = 1; 383 *((char *)dp + dp->db_txt_start) = NUL; // empty line 384 385 return OK; 386 387 error: 388 if (mfp != NULL) { 389 if (hp) { 390 mf_put(mfp, hp, false, false); 391 } 392 mf_close(mfp, true); // will also xfree(mfp->mf_fname) 393 } 394 buf->b_ml.ml_mfp = NULL; 395 return FAIL; 396 } 397 398 /// ml_setname() is called when the file name of "buf" has been changed. 399 /// It may rename the swapfile. 400 void ml_setname(buf_T *buf) 401 { 402 bool success = false; 403 404 memfile_T *mfp = buf->b_ml.ml_mfp; 405 if (mfp->mf_fd < 0) { // there is no swapfile yet 406 // When 'updatecount' is 0 and 'noswapfile' there is no swapfile. 407 // For help files we will make a swapfile now. 408 if (p_uc != 0 && (cmdmod.cmod_flags & CMOD_NOSWAPFILE) == 0) { 409 ml_open_file(buf); // create a swapfile 410 } 411 return; 412 } 413 414 // Try all directories in the 'directory' option. 415 char *dirp = p_dir; 416 bool found_existing_dir = false; 417 while (true) { 418 if (*dirp == NUL) { // tried all directories, fail 419 break; 420 } 421 char *fname = findswapname(buf, &dirp, mfp->mf_fname, &found_existing_dir); 422 // alloc's fname 423 if (dirp == NULL) { // out of memory 424 break; 425 } 426 if (fname == NULL) { // no file name found for this dir 427 continue; 428 } 429 430 // if the file name is the same we don't have to do anything 431 if (path_fnamecmp(fname, mfp->mf_fname) == 0) { 432 xfree(fname); 433 success = true; 434 break; 435 } 436 // need to close the swapfile before renaming 437 if (mfp->mf_fd >= 0) { 438 close(mfp->mf_fd); 439 mfp->mf_fd = -1; 440 } 441 442 // try to rename the swapfile 443 if (vim_rename(mfp->mf_fname, fname) == 0) { 444 success = true; 445 mf_free_fnames(mfp); 446 mf_set_fnames(mfp, fname); 447 ml_upd_block0(buf, UB_SAME_DIR); 448 break; 449 } 450 xfree(fname); // this fname didn't work, try another 451 } 452 453 if (mfp->mf_fd == -1) { // need to (re)open the swapfile 454 mfp->mf_fd = os_open(mfp->mf_fname, O_RDWR, 0); 455 if (mfp->mf_fd < 0) { 456 // could not (re)open the swapfile, what can we do???? 457 emsg(_("E301: Oops, lost the swap file!!!")); 458 return; 459 } 460 os_set_cloexec(mfp->mf_fd); 461 } 462 if (!success) { 463 emsg(_("E302: Could not rename swap file")); 464 } 465 } 466 467 /// Open a file for the memfile for all buffers that are not readonly or have 468 /// been modified. 469 /// Used when 'updatecount' changes from zero to non-zero. 470 void ml_open_files(void) 471 { 472 FOR_ALL_BUFFERS(buf) { 473 if (!buf->b_p_ro || buf->b_changed) { 474 ml_open_file(buf); 475 } 476 } 477 } 478 479 /// Open a swapfile for an existing memfile, if there is no swapfile yet. 480 /// If we are unable to find a file name, mf_fname will be NULL 481 /// and the memfile will be in memory only (no recovery possible). 482 void ml_open_file(buf_T *buf) 483 { 484 memfile_T *mfp = buf->b_ml.ml_mfp; 485 if (mfp == NULL || mfp->mf_fd >= 0 || !buf->b_p_swf 486 || (cmdmod.cmod_flags & CMOD_NOSWAPFILE) 487 || buf->terminal) { 488 return; // nothing to do 489 } 490 491 // For a spell buffer use a temp file name. 492 if (buf->b_spell) { 493 char *fname = vim_tempname(); 494 if (fname != NULL) { 495 mf_open_file(mfp, fname); // consumes fname! 496 } 497 buf->b_may_swap = false; 498 return; 499 } 500 501 // Try all directories in 'directory' option. 502 char *dirp = p_dir; 503 bool found_existing_dir = false; 504 while (true) { 505 if (*dirp == NUL) { 506 break; 507 } 508 // There is a small chance that between choosing the swapfile name 509 // and creating it, another Vim creates the file. In that case the 510 // creation will fail and we will use another directory. 511 char *fname = findswapname(buf, &dirp, NULL, &found_existing_dir); 512 if (dirp == NULL) { 513 break; // out of memory 514 } 515 if (fname == NULL) { 516 continue; 517 } 518 if (mf_open_file(mfp, fname) == OK) { // consumes fname! 519 // don't sync yet in ml_sync_all() 520 mfp->mf_dirty = MF_DIRTY_YES_NOSYNC; 521 ml_upd_block0(buf, UB_SAME_DIR); 522 523 // Flush block zero, so others can read it 524 if (mf_sync(mfp, MFS_ZERO) == OK) { 525 // Mark all blocks that should be in the swapfile as dirty. 526 // Needed for when the 'swapfile' option was reset, so that 527 // the swapfile was deleted, and then on again. 528 mf_set_dirty(mfp); 529 break; 530 } 531 // Writing block 0 failed: close the file and try another dir 532 mf_close_file(buf, false); 533 } 534 } 535 536 if (*p_dir != NUL && mfp->mf_fname == NULL) { 537 need_wait_return = true; // call wait_return() later 538 no_wait_return++; 539 semsg(_("E303: Unable to open swap file for \"%s\", recovery impossible"), 540 buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname); 541 no_wait_return--; 542 } 543 544 // don't try to open a swapfile again 545 buf->b_may_swap = false; 546 } 547 548 /// If still need to create a swapfile, and starting to edit a not-readonly 549 /// file, or reading into an existing buffer, create a swapfile now. 550 /// 551 /// @param newfile reading file into new buffer 552 void check_need_swap(bool newfile) 553 { 554 int old_msg_silent = msg_silent; // might be reset by an E325 message 555 msg_silent = 0; // If swap dialog prompts for input, user needs to see it! 556 557 if (curbuf->b_may_swap && (!curbuf->b_p_ro || !newfile)) { 558 ml_open_file(curbuf); 559 } 560 561 msg_silent = old_msg_silent; 562 } 563 564 /// Close memline for buffer 'buf'. 565 /// 566 /// @param del_file if true, delete the swapfile 567 void ml_close(buf_T *buf, int del_file) 568 { 569 if (buf->b_ml.ml_mfp == NULL) { // not open 570 return; 571 } 572 mf_close(buf->b_ml.ml_mfp, del_file); // close the .swp file 573 if (buf->b_ml.ml_line_lnum != 0 574 && (buf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED))) { 575 xfree(buf->b_ml.ml_line_ptr); 576 } 577 xfree(buf->b_ml.ml_stack); 578 XFREE_CLEAR(buf->b_ml.ml_chunksize); 579 buf->b_ml.ml_mfp = NULL; 580 581 // Reset the "recovered" flag, give the ATTENTION prompt the next time 582 // this buffer is loaded. 583 buf->b_flags &= ~BF_RECOVERED; 584 } 585 586 /// Close all existing memlines and memfiles. 587 /// Only used when exiting. 588 /// 589 /// @param del_file if true, delete the memfiles. 590 void ml_close_all(bool del_file) 591 { 592 FOR_ALL_BUFFERS(buf) { 593 ml_close(buf, del_file); 594 } 595 spell_delete_wordlist(); // delete the internal wordlist 596 vim_deltempdir(); // delete created temp directory 597 } 598 599 /// Close all memfiles for not modified buffers. 600 /// Only use just before exiting! 601 void ml_close_notmod(void) 602 { 603 FOR_ALL_BUFFERS(buf) { 604 if (!bufIsChanged(buf)) { 605 ml_close(buf, true); // close all not-modified buffers 606 } 607 } 608 } 609 610 /// Update the timestamp in the .swp file. 611 /// Used when the file has been written. 612 void ml_timestamp(buf_T *buf) 613 { 614 ml_upd_block0(buf, UB_FNAME); 615 } 616 617 /// Checks whether the IDs in b0 are valid. 618 static bool ml_check_b0_id(ZeroBlock *b0p) 619 FUNC_ATTR_NONNULL_ALL 620 { 621 return b0p->b0_id[0] == BLOCK0_ID0 && b0p->b0_id[1] == BLOCK0_ID1; 622 } 623 624 /// Checks whether all strings in b0 are valid (i.e. nul-terminated). 625 static bool ml_check_b0_strings(ZeroBlock *b0p) 626 FUNC_ATTR_NONNULL_ALL 627 { 628 return (memchr(b0p->b0_version, NUL, 10) 629 && memchr(b0p->b0_uname, NUL, B0_UNAME_SIZE) 630 && memchr(b0p->b0_hname, NUL, B0_HNAME_SIZE) 631 && memchr(b0p->b0_fname, NUL, B0_FNAME_SIZE_CRYPT)); 632 } 633 634 /// Update the timestamp or the B0_SAME_DIR flag of the .swp file. 635 static void ml_upd_block0(buf_T *buf, upd_block0_T what) 636 { 637 bhdr_T *hp; 638 639 memfile_T *mfp = buf->b_ml.ml_mfp; 640 if (mfp == NULL || (hp = mf_get(mfp, 0, 1)) == NULL) { 641 return; 642 } 643 ZeroBlock *b0p = hp->bh_data; 644 if (ml_check_b0_id(b0p) == FAIL) { 645 iemsg(_("E304: ml_upd_block0(): Didn't get block 0??")); 646 } else { 647 if (what == UB_FNAME) { 648 set_b0_fname(b0p, buf); 649 } else { // what == UB_SAME_DIR 650 set_b0_dir_flag(b0p, buf); 651 } 652 } 653 mf_put(mfp, hp, true, false); 654 } 655 656 /// Write file name and timestamp into block 0 of a swapfile. 657 /// Also set buf->b_mtime. 658 /// Don't use NameBuff[]!!! 659 static void set_b0_fname(ZeroBlock *b0p, buf_T *buf) 660 { 661 if (buf->b_ffname == NULL) { 662 b0p->b0_fname[0] = NUL; 663 } else { 664 char uname[B0_UNAME_SIZE]; 665 666 // For a file under the home directory of the current user, we try to 667 // replace the home directory path with "~user". This helps when 668 // editing the same file on different machines over a network. 669 // First replace home dir path with "~/" with home_replace(). 670 // Then insert the user name to get "~user/". 671 home_replace(NULL, buf->b_ffname, b0p->b0_fname, 672 B0_FNAME_SIZE_CRYPT, true); 673 if (b0p->b0_fname[0] == '~') { 674 // If there is no user name or it is too long, don't use "~/" 675 int retval = os_get_username(uname, B0_UNAME_SIZE); 676 size_t ulen = strlen(uname); 677 size_t flen = strlen(b0p->b0_fname); 678 if (retval == FAIL || ulen + flen > B0_FNAME_SIZE_CRYPT - 1) { 679 xstrlcpy(b0p->b0_fname, buf->b_ffname, B0_FNAME_SIZE_CRYPT); 680 } else { 681 memmove(b0p->b0_fname + ulen + 1, b0p->b0_fname + 1, flen); 682 memmove(b0p->b0_fname + 1, uname, ulen); 683 } 684 } 685 FileInfo file_info; 686 if (os_fileinfo(buf->b_ffname, &file_info)) { 687 long_to_char(file_info.stat.st_mtim.tv_sec, b0p->b0_mtime); 688 long_to_char((long)os_fileinfo_inode(&file_info), b0p->b0_ino); 689 buf_store_file_info(buf, &file_info); 690 buf->b_mtime_read = buf->b_mtime; 691 buf->b_mtime_read_ns = buf->b_mtime_ns; 692 } else { 693 long_to_char(0, b0p->b0_mtime); 694 long_to_char(0, b0p->b0_ino); 695 buf->b_mtime = 0; 696 buf->b_mtime_ns = 0; 697 buf->b_mtime_read = 0; 698 buf->b_mtime_read_ns = 0; 699 buf->b_orig_size = 0; 700 buf->b_orig_mode = 0; 701 } 702 } 703 704 // Also add the 'fileencoding' if there is room. 705 add_b0_fenc(b0p, curbuf); 706 } 707 708 /// Update the B0_SAME_DIR flag of the swapfile. It's set if the file and the 709 /// swapfile for "buf" are in the same directory. 710 /// This is fail safe: if we are not sure the directories are equal the flag is 711 /// not set. 712 static void set_b0_dir_flag(ZeroBlock *b0p, buf_T *buf) 713 { 714 if (same_directory(buf->b_ml.ml_mfp->mf_fname, buf->b_ffname)) { 715 b0p->b0_flags |= B0_SAME_DIR; 716 } else { 717 b0p->b0_flags = (char)(b0p->b0_flags & ~B0_SAME_DIR); 718 } 719 } 720 721 /// When there is room, add the 'fileencoding' to block zero. 722 static void add_b0_fenc(ZeroBlock *b0p, buf_T *buf) 723 { 724 const int size = B0_FNAME_SIZE_NOCRYPT; 725 726 int n = (int)strlen(buf->b_p_fenc); 727 if ((int)strlen(b0p->b0_fname) + n + 1 > size) { 728 b0p->b0_flags = (char)(b0p->b0_flags & ~B0_HAS_FENC); 729 } else { 730 memmove(b0p->b0_fname + size - n, 731 buf->b_p_fenc, (size_t)n); 732 *(b0p->b0_fname + size - n - 1) = NUL; 733 b0p->b0_flags |= B0_HAS_FENC; 734 } 735 } 736 737 /// Returns the PID of the process that owns the swapfile, if it is running. 738 /// 739 /// @param b0p swapfile data 740 /// @param swap_fname Name of the swapfile. If it's from before a reboot, the result is 0. 741 /// 742 /// @return PID, or 0 if process is not running or the swapfile is from before a reboot. 743 static int swapfile_proc_running(const ZeroBlock *b0p, const char *swap_fname) 744 { 745 FileInfo st; 746 double uptime; 747 // If the system rebooted after when the swapfile was written then the 748 // process can't be running now. 749 if (os_fileinfo(swap_fname, &st) 750 && uv_uptime(&uptime) == 0 751 && (Timestamp)st.stat.st_mtim.tv_sec < os_time() - (Timestamp)uptime) { 752 return 0; 753 } 754 int pid = (int)char_to_long(b0p->b0_pid); 755 return os_proc_running(pid) ? pid : 0; 756 } 757 758 /// Try to recover curbuf from the .swp file. 759 /// 760 /// @param checkext if true, check the extension and detect whether it is a swapfile. 761 void ml_recover(bool checkext) 762 { 763 buf_T *buf = NULL; 764 memfile_T *mfp = NULL; 765 char *fname_used = NULL; 766 bhdr_T *hp = NULL; 767 char *b0_fenc = NULL; 768 infoptr_T *ip; 769 bool directly; 770 bool serious_error = true; 771 int orig_file_status = NOTDONE; 772 773 recoverymode = true; 774 int called_from_main = (curbuf->b_ml.ml_mfp == NULL); 775 776 // If the file name ends in ".s[a-w][a-z]" we assume this is the swapfile. 777 // Otherwise a search is done to find the swapfile(s). 778 char *fname = curbuf->b_fname; 779 if (fname == NULL) { // When there is no file name 780 fname = ""; 781 } 782 int len = (int)strlen(fname); 783 if (checkext && len >= 4 784 && STRNICMP(fname + len - 4, ".s", 2) == 0 785 && vim_strchr("abcdefghijklmnopqrstuvw", TOLOWER_ASC((uint8_t)fname[len - 2])) != NULL 786 && ASCII_ISALPHA(fname[len - 1])) { 787 directly = true; 788 fname_used = xstrdup(fname); // make a copy for mf_open() 789 } else { 790 directly = false; 791 792 // count the number of matching swapfiles 793 len = recover_names(fname, false, NULL, 0, NULL); 794 if (len == 0) { // no swapfiles found 795 semsg(_("E305: No swap file found for %s"), fname); 796 goto theend; 797 } 798 int i; 799 if (len == 1) { // one swapfile found, use it 800 i = 1; 801 } else { // several swapfiles found, choose 802 // list the names of the swapfiles 803 recover_names(fname, true, NULL, 0, NULL); 804 msg_putchar('\n'); 805 i = prompt_for_input(_("Enter number of swap file to use (0 to quit): "), 0, false, NULL); 806 if (i < 1 || i > len) { 807 goto theend; 808 } 809 } 810 // get the swapfile name that will be used 811 recover_names(fname, false, NULL, i, &fname_used); 812 } 813 if (fname_used == NULL) { 814 goto theend; // user chose invalid number. 815 } 816 // When called from main() still need to initialize storage structure 817 if (called_from_main && ml_open(curbuf) == FAIL) { 818 getout(1); 819 } 820 821 // Allocate a buffer structure for the swapfile that is used for recovery. 822 // Only the memline in it is really used. 823 buf = xmalloc(sizeof(buf_T)); 824 825 // init fields in memline struct 826 buf->b_ml.ml_stack_size = 0; // no stack yet 827 buf->b_ml.ml_stack = NULL; // no stack yet 828 buf->b_ml.ml_stack_top = 0; // nothing in the stack 829 buf->b_ml.ml_line_lnum = 0; // no cached line 830 buf->b_ml.ml_line_offset = 0; 831 buf->b_ml.ml_locked = NULL; // no locked block 832 buf->b_ml.ml_flags = 0; 833 834 // open the memfile from the old swapfile 835 char *p = xstrdup(fname_used); // save "fname_used" for the message: 836 // mf_open() will consume "fname_used"! 837 mfp = mf_open(fname_used, O_RDONLY); 838 fname_used = p; 839 if (mfp == NULL || mfp->mf_fd < 0) { 840 semsg(_("E306: Cannot open %s"), fname_used); 841 goto theend; 842 } 843 buf->b_ml.ml_mfp = mfp; 844 845 // The page size set in mf_open() might be different from the page size 846 // used in the swapfile, we must get it from block 0. But to read block 847 // 0 we need a page size. Use the minimal size for block 0 here, it will 848 // be set to the real value below. 849 mfp->mf_page_size = MIN_SWAP_PAGE_SIZE; 850 851 int hl_id = HLF_E; 852 // try to read block 0 853 if ((hp = mf_get(mfp, 0, 1)) == NULL) { 854 msg_start(); 855 msg_puts_hl(_("Unable to read block 0 from "), hl_id, true); 856 msg_outtrans(mfp->mf_fname, hl_id, true); 857 msg_puts_hl(_("\nMaybe no changes were made or Nvim did not update the swap file."), hl_id, 858 true); 859 msg_end(); 860 goto theend; 861 } 862 ZeroBlock *b0p = hp->bh_data; 863 if (strncmp(b0p->b0_version, "VIM 3.0", 7) == 0) { 864 msg_start(); 865 msg_outtrans(mfp->mf_fname, 0, true); 866 msg_puts_hl(_(" cannot be used with this version of Nvim.\n"), 0, true); 867 msg_puts_hl(_("Use Vim version 3.0.\n"), 0, true); 868 msg_end(); 869 goto theend; 870 } 871 if (ml_check_b0_id(b0p) == FAIL) { 872 semsg(_("E307: %s does not look like a Nvim swap file"), mfp->mf_fname); 873 goto theend; 874 } 875 if (b0_magic_wrong(b0p)) { 876 msg_start(); 877 msg_outtrans(mfp->mf_fname, hl_id, true); 878 msg_puts_hl(_(" cannot be used on this computer.\n"), hl_id, true); 879 msg_puts_hl(_("The file was created on "), hl_id, true); 880 // avoid going past the end of a corrupted hostname 881 b0p->b0_fname[0] = NUL; 882 msg_puts_hl(b0p->b0_hname, hl_id, true); 883 msg_puts_hl(_(",\nor the file has been damaged."), hl_id, true); 884 msg_end(); 885 goto theend; 886 } 887 888 // If we guessed the wrong page size, we have to recalculate the 889 // highest block number in the file. 890 if (mfp->mf_page_size != (unsigned)char_to_long(b0p->b0_page_size)) { 891 unsigned previous_page_size = mfp->mf_page_size; 892 893 mf_new_page_size(mfp, (unsigned)char_to_long(b0p->b0_page_size)); 894 if (mfp->mf_page_size < previous_page_size) { 895 msg_start(); 896 msg_outtrans(mfp->mf_fname, hl_id, true); 897 msg_puts_hl(_(" has been damaged (page size is smaller than minimum value).\n"), hl_id, true); 898 msg_end(); 899 goto theend; 900 } 901 off_T size = vim_lseek(mfp->mf_fd, 0, SEEK_END); 902 // 0 means no file or empty file 903 mfp->mf_blocknr_max = size <= 0 ? 0 : size / mfp->mf_page_size; 904 mfp->mf_infile_count = mfp->mf_blocknr_max; 905 906 // need to reallocate the memory used to store the data 907 p = xmalloc(mfp->mf_page_size); 908 memmove(p, hp->bh_data, previous_page_size); 909 xfree(hp->bh_data); 910 hp->bh_data = p; 911 b0p = hp->bh_data; 912 } 913 914 // If .swp file name given directly, use name from swapfile for buffer. 915 if (directly) { 916 expand_env(b0p->b0_fname, NameBuff, MAXPATHL); 917 if (setfname(curbuf, NameBuff, NULL, true) == FAIL) { 918 goto theend; 919 } 920 } 921 922 home_replace(NULL, mfp->mf_fname, NameBuff, MAXPATHL, true); 923 smsg(0, _("Using swap file \"%s\""), NameBuff); 924 925 if (buf_spname(curbuf) != NULL) { 926 xstrlcpy(NameBuff, buf_spname(curbuf), MAXPATHL); 927 } else { 928 home_replace(NULL, curbuf->b_ffname, NameBuff, MAXPATHL, true); 929 } 930 smsg(0, _("Original file \"%s\""), NameBuff); 931 msg_putchar('\n'); 932 933 // check date of swapfile and original file 934 FileInfo org_file_info; 935 FileInfo swp_file_info; 936 int mtime = (int)char_to_long(b0p->b0_mtime); 937 if (curbuf->b_ffname != NULL 938 && os_fileinfo(curbuf->b_ffname, &org_file_info) 939 && ((os_fileinfo(mfp->mf_fname, &swp_file_info) 940 && org_file_info.stat.st_mtim.tv_sec 941 > swp_file_info.stat.st_mtim.tv_sec) 942 || org_file_info.stat.st_mtim.tv_sec != mtime)) { 943 emsg(_("E308: Warning: Original file may have been changed")); 944 } 945 ui_flush(); 946 947 // Get the 'fileformat' and 'fileencoding' from block zero. 948 int b0_ff = (b0p->b0_flags & B0_FF_MASK); 949 if (b0p->b0_flags & B0_HAS_FENC) { 950 int fnsize = B0_FNAME_SIZE_NOCRYPT; 951 952 for (p = b0p->b0_fname + fnsize; p > b0p->b0_fname && p[-1] != NUL; p--) {} 953 b0_fenc = xstrnsave(p, (size_t)(b0p->b0_fname + fnsize - p)); 954 } 955 956 mf_put(mfp, hp, false, false); // release block 0 957 hp = NULL; 958 959 // Now that we are sure that the file is going to be recovered, clear the 960 // contents of the current buffer. 961 while (!(curbuf->b_ml.ml_flags & ML_EMPTY)) { 962 ml_delete(1); 963 } 964 965 // Try reading the original file to obtain the values of 'fileformat', 966 // 'fileencoding', etc. Ignore errors. The text itself is not used. 967 if (curbuf->b_ffname != NULL) { 968 orig_file_status = readfile(curbuf->b_ffname, NULL, 0, 969 0, MAXLNUM, NULL, READ_NEW, false); 970 } 971 972 // Use the 'fileformat' and 'fileencoding' as stored in the swapfile. 973 if (b0_ff != 0) { 974 set_fileformat(b0_ff - 1, OPT_LOCAL); 975 } 976 if (b0_fenc != NULL) { 977 set_option_value_give_err(kOptFileencoding, CSTR_AS_OPTVAL(b0_fenc), OPT_LOCAL); 978 xfree(b0_fenc); 979 } 980 unchanged(curbuf, true, true); 981 982 blocknr_T bnum = 1; // start with block 1 983 unsigned page_count = 1; // which is 1 page 984 linenr_T lnum = 0; // append after line 0 in curbuf 985 linenr_T line_count = 0; 986 int idx = 0; // start with first index in block 1 987 int error = 0; 988 buf->b_ml.ml_stack_top = 0; 989 buf->b_ml.ml_stack = NULL; 990 buf->b_ml.ml_stack_size = 0; 991 992 bool cannot_open = (curbuf->b_ffname == NULL); 993 994 serious_error = false; 995 for (; !got_int; line_breakcheck()) { 996 if (hp != NULL) { 997 mf_put(mfp, hp, false, false); // release previous block 998 } 999 // get block 1000 if ((hp = mf_get(mfp, bnum, page_count)) == NULL) { 1001 if (bnum == 1) { 1002 semsg(_("E309: Unable to read block 1 from %s"), mfp->mf_fname); 1003 goto theend; 1004 } 1005 error++; 1006 ml_append(lnum++, _("???MANY LINES MISSING"), 0, true); 1007 } else { // there is a block 1008 PointerBlock *pp = hp->bh_data; 1009 if (pp->pb_id == PTR_ID) { // it is a pointer block 1010 bool ptr_block_error = false; 1011 if (pp->pb_count_max != PB_COUNT_MAX(mfp)) { 1012 ptr_block_error = true; 1013 pp->pb_count_max = PB_COUNT_MAX(mfp); 1014 } 1015 if (pp->pb_count > pp->pb_count_max) { 1016 ptr_block_error = true; 1017 pp->pb_count = pp->pb_count_max; 1018 } 1019 if (ptr_block_error) { 1020 emsg(_(e_warning_pointer_block_corrupted)); 1021 } 1022 1023 // check line count when using pointer block first time 1024 if (idx == 0 && line_count != 0) { 1025 for (int i = 0; i < (int)pp->pb_count; i++) { 1026 line_count -= pp->pb_pointer[i].pe_line_count; 1027 } 1028 if (line_count != 0) { 1029 error++; 1030 ml_append(lnum++, _("???LINE COUNT WRONG"), 0, true); 1031 } 1032 } 1033 1034 if (pp->pb_count == 0) { 1035 ml_append(lnum++, _("???EMPTY BLOCK"), 0, true); 1036 error++; 1037 } else if (idx < (int)pp->pb_count) { // go a block deeper 1038 if (pp->pb_pointer[idx].pe_bnum < 0) { 1039 // Data block with negative block number. 1040 // Try to read lines from the original file. 1041 // This is slow, but it works. 1042 if (!cannot_open) { 1043 line_count = pp->pb_pointer[idx].pe_line_count; 1044 linenr_T pe_old_lnum = pp->pb_pointer[idx].pe_old_lnum; 1045 // Validate pe_line_count and pe_old_lnum from the 1046 // untrusted swap file before passing to readfile(). 1047 if (line_count <= 0 || pe_old_lnum < 1 1048 || readfile(curbuf->b_ffname, NULL, lnum, pe_old_lnum - 1, 1049 line_count, NULL, 0, false) != OK) { 1050 cannot_open = true; 1051 } else { 1052 lnum += line_count; 1053 } 1054 } 1055 if (cannot_open) { 1056 error++; 1057 ml_append(lnum++, _("???LINES MISSING"), 0, true); 1058 } 1059 idx++; // get same block again for next index 1060 continue; 1061 } 1062 1063 // going one block deeper in the tree 1064 int top = ml_add_stack(buf); // new entry in stack 1065 ip = &(buf->b_ml.ml_stack[top]); 1066 ip->ip_bnum = bnum; 1067 ip->ip_index = idx; 1068 1069 bnum = pp->pb_pointer[idx].pe_bnum; 1070 line_count = pp->pb_pointer[idx].pe_line_count; 1071 page_count = (unsigned)pp->pb_pointer[idx].pe_page_count; 1072 // Validate pe_bnum and pe_page_count from the untrusted 1073 // swap file before passing to mf_get(), which uses 1074 // page_count to calculate allocation size. A bogus value 1075 // (e.g. 0x40000000) would cause a multi-GB allocation. 1076 // pe_page_count must be >= 1 and bnum + page_count must 1077 // not exceed the number of pages in the swap file. 1078 if (page_count < 1 || bnum + page_count > mfp->mf_blocknr_max + 1) { 1079 error++; 1080 ml_append(lnum++, _("???ILLEGAL BLOCK NUMBER"), (colnr_T)0, true); 1081 // Skip this entry and pop back up the stack to keep 1082 // recovering whatever else we can. 1083 idx = ip->ip_index + 1; 1084 bnum = ip->ip_bnum; 1085 page_count = 1; 1086 buf->b_ml.ml_stack_top--; 1087 continue; 1088 } 1089 idx = 0; 1090 continue; 1091 } 1092 } else { // not a pointer block 1093 DataBlock *dp = hp->bh_data; 1094 if (dp->db_id != DATA_ID) { // block id wrong 1095 if (bnum == 1) { 1096 semsg(_("E310: Block 1 ID wrong (%s not a .swp file?)"), 1097 mfp->mf_fname); 1098 goto theend; 1099 } 1100 error++; 1101 ml_append(lnum++, _("???BLOCK MISSING"), 0, true); 1102 } else { 1103 // It is a data block. 1104 // Append all the lines in this block. 1105 bool has_error = false; 1106 1107 // Check the length of the block. 1108 // If wrong, use the length given in the pointer block. 1109 if (page_count * mfp->mf_page_size != dp->db_txt_end) { 1110 ml_append(lnum++, 1111 _("??? from here until ???END lines" " may be messed up"), 1112 0, true); 1113 error++; 1114 has_error = true; 1115 dp->db_txt_end = page_count * mfp->mf_page_size; 1116 } 1117 1118 // Make sure there is a NUL at the end of the block so we 1119 // don't go over the end when copying text. 1120 *((char *)dp + dp->db_txt_end - 1) = NUL; 1121 1122 // Check the number of lines in the block. 1123 // If wrong, use the count in the data block. 1124 if (line_count != dp->db_line_count) { 1125 ml_append(lnum++, 1126 _("??? from here until ???END lines" 1127 " may have been inserted/deleted"), 1128 0, true); 1129 error++; 1130 has_error = true; 1131 } 1132 1133 bool did_questions = false; 1134 for (int i = 0; i < dp->db_line_count; i++) { 1135 if ((char *)&(dp->db_index[i]) >= (char *)dp + dp->db_txt_start) { 1136 // line count must be wrong 1137 error++; 1138 ml_append(lnum++, _("??? lines may be missing"), 0, true); 1139 break; 1140 } 1141 1142 int txt_start = (dp->db_index[i] & DB_INDEX_MASK); 1143 if (txt_start <= (int)HEADER_SIZE 1144 || txt_start >= (int)dp->db_txt_end) { 1145 error++; 1146 // avoid lots of lines with "???" 1147 if (did_questions) { 1148 continue; 1149 } 1150 did_questions = true; 1151 p = "???"; 1152 } else { 1153 did_questions = false; 1154 p = (char *)dp + txt_start; 1155 } 1156 ml_append(lnum++, p, 0, true); 1157 } 1158 if (has_error) { 1159 ml_append(lnum++, _("???END"), 0, true); 1160 } 1161 } 1162 } 1163 } 1164 1165 if (buf->b_ml.ml_stack_top == 0) { // finished 1166 break; 1167 } 1168 1169 // go one block up in the tree 1170 ip = &(buf->b_ml.ml_stack[--(buf->b_ml.ml_stack_top)]); 1171 bnum = ip->ip_bnum; 1172 idx = ip->ip_index + 1; // go to next index 1173 page_count = 1; 1174 } 1175 1176 // Compare the buffer contents with the original file. When they differ 1177 // set the 'modified' flag. 1178 // Lines 1 - lnum are the new contents. 1179 // Lines lnum + 1 to ml_line_count are the original contents. 1180 // Line ml_line_count + 1 in the dummy empty line. 1181 if (orig_file_status != OK || curbuf->b_ml.ml_line_count != lnum * 2 + 1) { 1182 // Recovering an empty file results in two lines and the first line is 1183 // empty. Don't set the modified flag then. 1184 if (!(curbuf->b_ml.ml_line_count == 2 && *ml_get(1) == NUL)) { 1185 changed_internal(curbuf); 1186 buf_inc_changedtick(curbuf); 1187 } 1188 } else { 1189 for (idx = 1; idx <= lnum; idx++) { 1190 // Need to copy one line, fetching the other one may flush it. 1191 p = xstrnsave(ml_get(idx), (size_t)ml_get_len(idx)); 1192 int i = strcmp(p, ml_get(idx + lnum)); 1193 xfree(p); 1194 if (i != 0) { 1195 changed_internal(curbuf); 1196 buf_inc_changedtick(curbuf); 1197 break; 1198 } 1199 } 1200 } 1201 1202 // Delete the lines from the original file and the dummy line from the 1203 // empty buffer. These will now be after the last line in the buffer. 1204 while (curbuf->b_ml.ml_line_count > lnum 1205 && !(curbuf->b_ml.ml_flags & ML_EMPTY)) { 1206 ml_delete(curbuf->b_ml.ml_line_count); 1207 } 1208 curbuf->b_flags |= BF_RECOVERED; 1209 check_cursor(curwin); 1210 1211 recoverymode = false; 1212 if (got_int) { 1213 emsg(_("E311: Recovery Interrupted")); 1214 } else if (error) { 1215 no_wait_return++; 1216 msg(">>>>>>>>>>>>>", 0); 1217 emsg(_("E312: Errors detected while recovering; look for lines starting with ???")); 1218 no_wait_return--; 1219 msg(_("See \":help E312\" for more information."), 0); 1220 msg(">>>>>>>>>>>>>", 0); 1221 } else { 1222 if (curbuf->b_changed) { 1223 msg(_("Recovery completed. You should check if everything is OK."), 0); 1224 msg_puts(_("\n(You might want to write out this file under another name\n")); 1225 msg_puts(_("and run diff with the original file to check for changes)")); 1226 } else { 1227 msg(_("Recovery completed. Buffer contents equals file contents."), 0); 1228 } 1229 msg_puts(_("\nYou may want to delete the .swp file now.")); 1230 if (swapfile_proc_running(b0p, fname_used)) { 1231 // Warn there could be an active Vim on the same file, the user may 1232 // want to kill it. 1233 msg_puts(_("\nNote: process STILL RUNNING: ")); 1234 msg_outnum((int)char_to_long(b0p->b0_pid)); 1235 } 1236 msg_puts("\n\n"); 1237 cmdline_row = msg_row; 1238 } 1239 redraw_curbuf_later(UPD_NOT_VALID); 1240 1241 theend: 1242 xfree(fname_used); 1243 recoverymode = false; 1244 if (mfp != NULL) { 1245 if (hp != NULL) { 1246 mf_put(mfp, hp, false, false); 1247 } 1248 mf_close(mfp, false); // will also xfree(mfp->mf_fname) 1249 } 1250 if (buf != NULL) { // may be NULL if swapfile not found. 1251 xfree(buf->b_ml.ml_stack); 1252 xfree(buf); 1253 } 1254 if (serious_error && called_from_main) { 1255 ml_close(curbuf, true); 1256 } else { 1257 apply_autocmds(EVENT_BUFREADPOST, NULL, curbuf->b_fname, false, curbuf); 1258 apply_autocmds(EVENT_BUFWINENTER, NULL, curbuf->b_fname, false, curbuf); 1259 } 1260 } 1261 1262 /// Find the names of swapfiles in current directory and the directory given 1263 /// with the 'directory' option. 1264 /// 1265 /// Used to: 1266 /// - list the swapfiles for "nvim -r" 1267 /// - count the number of swapfiles when recovering 1268 /// - list the swapfiles when recovering 1269 /// - list the swapfiles for swapfilelist() 1270 /// - find the name of the n'th swapfile when recovering 1271 /// 1272 /// @param fname base for swapfile name 1273 /// @param do_list when true, list the swapfile names 1274 /// @param ret_list when not NULL add file names to it 1275 /// @param nr when non-zero, return nr'th swapfile name 1276 /// @param fname_out result when "nr" > 0 1277 int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fname_out) 1278 { 1279 int num_names; 1280 char *(names[6]); 1281 char *tail; 1282 char *p; 1283 int file_count = 0; 1284 char **files; 1285 char *fname_res = NULL; 1286 #ifdef HAVE_READLINK 1287 char fname_buf[MAXPATHL]; 1288 #endif 1289 1290 if (fname != NULL) { 1291 #ifdef HAVE_READLINK 1292 // Expand symlink in the file name, because the swapfile is created 1293 // with the actual file instead of with the symlink. 1294 fname_res = (resolve_symlink(fname, fname_buf) == OK) ? fname_buf : fname; 1295 #else 1296 fname_res = fname; 1297 #endif 1298 } 1299 1300 if (do_list) { 1301 // use msg() to start the scrolling properly 1302 msg(_("Swap files found:"), 0); 1303 msg_putchar('\n'); 1304 } 1305 1306 // Do the loop for every directory in 'directory'. 1307 // First allocate some memory to put the directory name in. 1308 char *dir_name = xmalloc(strlen(p_dir) + 1); 1309 char *dirp = p_dir; 1310 while (*dirp) { 1311 // Isolate a directory name from *dirp and put it in dir_name (we know 1312 // it is large enough, so use 31000 for length). 1313 // Advance dirp to next directory name. 1314 copy_option_part(&dirp, dir_name, 31000, ","); 1315 1316 if (dir_name[0] == '.' && dir_name[1] == NUL) { // check current dir 1317 if (fname == NULL) { 1318 names[0] = xstrdup("*.sw?"); 1319 // For Unix names starting with a dot are special. MS-Windows 1320 // supports this too, on some file systems. 1321 names[1] = xstrdup(".*.sw?"); 1322 names[2] = xstrdup(".sw?"); 1323 num_names = 3; 1324 } else { 1325 num_names = recov_file_names(names, fname_res, true); 1326 } 1327 } else { // check directory dir_name 1328 if (fname == NULL) { 1329 names[0] = concat_fnames(dir_name, "*.sw?", true); 1330 // For Unix names starting with a dot are special. MS-Windows 1331 // supports this too, on some file systems. 1332 names[1] = concat_fnames(dir_name, ".*.sw?", true); 1333 names[2] = concat_fnames(dir_name, ".sw?", true); 1334 num_names = 3; 1335 } else { 1336 int len = (int)strlen(dir_name); 1337 p = dir_name + len; 1338 if (after_pathsep(dir_name, p) && len > 1 && p[-1] == p[-2]) { 1339 // Ends with '//', Use Full path for swap name 1340 tail = make_percent_swname(dir_name, p, fname_res); 1341 } else { 1342 tail = path_tail(fname_res); 1343 tail = concat_fnames(dir_name, tail, true); 1344 } 1345 num_names = recov_file_names(names, tail, false); 1346 xfree(tail); 1347 } 1348 } 1349 1350 int num_files; 1351 if (num_names == 0) { 1352 num_files = 0; 1353 } else if (expand_wildcards(num_names, names, &num_files, &files, 1354 EW_KEEPALL|EW_FILE|EW_SILENT) == FAIL) { 1355 num_files = 0; 1356 } 1357 1358 // When no swapfile found, wildcard expansion might have failed (e.g. 1359 // not able to execute the shell). 1360 // Try finding a swapfile by simply adding ".swp" to the file name. 1361 if (*dirp == NUL && file_count + num_files == 0 && fname != NULL) { 1362 char *swapname = modname(fname_res, ".swp", true); 1363 if (swapname != NULL) { 1364 if (os_path_exists(swapname)) { 1365 files = xmalloc(sizeof(char *)); 1366 files[0] = swapname; 1367 swapname = NULL; 1368 num_files = 1; 1369 } 1370 xfree(swapname); 1371 } 1372 } 1373 1374 // Remove swapfile name of the current buffer, it must be ignored. 1375 // But keep it for swapfilelist(). 1376 if (curbuf->b_ml.ml_mfp != NULL 1377 && (p = curbuf->b_ml.ml_mfp->mf_fname) != NULL 1378 && ret_list == NULL) { 1379 for (int i = 0; i < num_files; i++) { 1380 // Do not expand wildcards, on Windows would try to expand 1381 // "%tmp%" in "%tmp%file" 1382 if (path_full_compare(p, files[i], true, false) & kEqualFiles) { 1383 // Remove the name from files[i]. Move further entries 1384 // down. When the array becomes empty free it here, since 1385 // FreeWild() won't be called below. 1386 xfree(files[i]); 1387 if (--num_files == 0) { 1388 xfree(files); 1389 } else { 1390 for (; i < num_files; i++) { 1391 files[i] = files[i + 1]; 1392 } 1393 } 1394 } 1395 } 1396 } 1397 if (nr > 0) { 1398 file_count += num_files; 1399 if (nr <= file_count) { 1400 *fname_out = xstrdup(files[nr - 1 + num_files - file_count]); 1401 dirp = ""; // stop searching 1402 } 1403 } else if (do_list) { 1404 if (dir_name[0] == '.' && dir_name[1] == NUL) { 1405 if (fname == NULL) { 1406 msg_puts(_(" In current directory:\n")); 1407 } else { 1408 msg_puts(_(" Using specified name:\n")); 1409 } 1410 } else { 1411 msg_puts(_(" In directory ")); 1412 msg_home_replace(dir_name); 1413 msg_puts(":\n"); 1414 } 1415 1416 if (num_files) { 1417 for (int i = 0; i < num_files; i++) { 1418 // print the swapfile name 1419 msg_outnum(++file_count); 1420 msg_puts(". "); 1421 msg_puts(path_tail(files[i])); 1422 msg_putchar('\n'); 1423 StringBuilder msg = KV_INITIAL_VALUE; 1424 kv_resize(msg, IOSIZE); 1425 swapfile_info(files[i], &msg); 1426 bool need_clear = false; 1427 msg_multiline(cbuf_as_string(msg.items, msg.size), 0, false, false, &need_clear); 1428 kv_destroy(msg); 1429 } 1430 } else { 1431 msg_puts(_(" -- none --\n")); 1432 } 1433 ui_flush(); 1434 } else if (ret_list != NULL) { 1435 for (int i = 0; i < num_files; i++) { 1436 char *name = concat_fnames(dir_name, files[i], true); 1437 tv_list_append_allocated_string(ret_list, name); 1438 } 1439 } else { 1440 file_count += num_files; 1441 } 1442 1443 for (int i = 0; i < num_names; i++) { 1444 xfree(names[i]); 1445 } 1446 if (num_files > 0) { 1447 FreeWild(num_files, files); 1448 } 1449 } 1450 xfree(dir_name); 1451 return file_count; 1452 } 1453 1454 /// Append the full path to name with path separators made into percent 1455 /// signs, to dir. An unnamed buffer is handled as "" (<currentdir>/"") 1456 /// signs, to "dir". An unnamed buffer is handled as "" (<currentdir>/"") 1457 /// The last character in "dir" must be an extra slash or backslash, it is 1458 /// removed. 1459 char *make_percent_swname(char *dir, char *dir_end, const char *name) 1460 FUNC_ATTR_NONNULL_ARG(1, 2) 1461 { 1462 char *d = NULL; 1463 char *f = fix_fname(name != NULL ? name : ""); 1464 if (f == NULL) { 1465 return NULL; 1466 } 1467 1468 char *s = xstrdup(f); 1469 for (d = s; *d != NUL; MB_PTR_ADV(d)) { 1470 if (vim_ispathsep(*d)) { 1471 *d = '%'; 1472 } 1473 } 1474 1475 dir_end[-1] = NUL; // remove one trailing slash 1476 d = concat_fnames(dir, s, true); 1477 xfree(s); 1478 xfree(f); 1479 return d; 1480 } 1481 1482 // PID of swapfile owner, or zero if not running. 1483 static int proc_running; 1484 1485 /// For Vimscript "swapinfo()". 1486 /// 1487 /// @return information found in swapfile "fname" in dictionary "d". 1488 void swapfile_dict(const char *fname, dict_T *d) 1489 { 1490 int fd; 1491 ZeroBlock b0; 1492 1493 if ((fd = os_open(fname, O_RDONLY, 0)) >= 0) { 1494 if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0)) { 1495 if (ml_check_b0_id(&b0) == FAIL) { 1496 tv_dict_add_str(d, S_LEN("error"), "Not a swap file"); 1497 } else if (b0_magic_wrong(&b0)) { 1498 tv_dict_add_str(d, S_LEN("error"), "Magic number mismatch"); 1499 } else { 1500 // We have swap information. 1501 tv_dict_add_str_len(d, S_LEN("version"), b0.b0_version, 10); 1502 tv_dict_add_str_len(d, S_LEN("user"), b0.b0_uname, 1503 B0_UNAME_SIZE); 1504 tv_dict_add_str_len(d, S_LEN("host"), b0.b0_hname, 1505 B0_HNAME_SIZE); 1506 tv_dict_add_str_len(d, S_LEN("fname"), b0.b0_fname, 1507 B0_FNAME_SIZE_ORG); 1508 1509 tv_dict_add_nr(d, S_LEN("pid"), swapfile_proc_running(&b0, fname)); 1510 tv_dict_add_nr(d, S_LEN("mtime"), char_to_long(b0.b0_mtime)); 1511 tv_dict_add_nr(d, S_LEN("dirty"), b0.b0_dirty ? 1 : 0); 1512 tv_dict_add_nr(d, S_LEN("inode"), char_to_long(b0.b0_ino)); 1513 } 1514 } else { 1515 tv_dict_add_str(d, S_LEN("error"), "Cannot read file"); 1516 } 1517 close(fd); 1518 } else { 1519 tv_dict_add_str(d, S_LEN("error"), "Cannot open file"); 1520 } 1521 } 1522 1523 /// Loads info from swapfile `fname`, and displays it to the user. 1524 /// 1525 /// @return timestamp (0 when unknown). 1526 static time_t swapfile_info(char *fname, StringBuilder *msg) 1527 { 1528 assert(fname != NULL); 1529 ZeroBlock b0; 1530 time_t x = (time_t)0; 1531 #ifdef UNIX 1532 char uname[B0_UNAME_SIZE]; 1533 #endif 1534 1535 // print the swapfile date 1536 FileInfo file_info; 1537 if (os_fileinfo(fname, &file_info)) { 1538 #ifdef UNIX 1539 // print name of owner of the file 1540 if (os_get_uname((uv_uid_t)file_info.stat.st_uid, uname, B0_UNAME_SIZE) == OK) { 1541 kv_printf(*msg, "%s%s", _(" owned by: "), uname); 1542 kv_printf(*msg, _(" dated: ")); 1543 } else { 1544 kv_printf(*msg, _(" dated: ")); 1545 } 1546 #else 1547 msg_puts(_(" dated: ")); 1548 #endif 1549 x = file_info.stat.st_mtim.tv_sec; 1550 char ctime_buf[100]; // hopefully enough for every language 1551 kv_printf(*msg, "%s", os_ctime_r(&x, ctime_buf, sizeof(ctime_buf), true)); 1552 } 1553 1554 // print the original file name 1555 int fd = os_open(fname, O_RDONLY, 0); 1556 if (fd >= 0) { 1557 if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0)) { 1558 if (strncmp(b0.b0_version, "VIM 3.0", 7) == 0) { 1559 kv_printf(*msg, _(" [from Vim version 3.0]")); 1560 } else if (ml_check_b0_id(&b0) == FAIL) { 1561 kv_printf(*msg, _(" [does not look like a Nvim swap file]")); 1562 } else if (!ml_check_b0_strings(&b0)) { 1563 kv_printf(*msg, _(" [garbled strings (not nul terminated)]")); 1564 } else { 1565 kv_printf(*msg, _(" file name: ")); 1566 if (b0.b0_fname[0] == NUL) { 1567 kv_printf(*msg, _("[No Name]")); 1568 } else { 1569 kv_printf(*msg, "%s", b0.b0_fname); 1570 } 1571 1572 kv_printf(*msg, _("\n modified: ")); 1573 kv_printf(*msg, b0.b0_dirty ? _("YES") : _("no")); 1574 1575 if (*(b0.b0_uname) != NUL) { 1576 kv_printf(*msg, _("\n user name: ")); 1577 kv_printf(*msg, "%s", b0.b0_uname); 1578 } 1579 1580 if (*(b0.b0_hname) != NUL) { 1581 if (*(b0.b0_uname) != NUL) { 1582 kv_printf(*msg, _(" host name: ")); 1583 } else { 1584 kv_printf(*msg, _("\n host name: ")); 1585 } 1586 kv_printf(*msg, "%s", b0.b0_hname); 1587 } 1588 1589 if (char_to_long(b0.b0_pid) != 0) { 1590 kv_printf(*msg, _("\n process ID: ")); 1591 kv_printf(*msg, "%d", (int)char_to_long(b0.b0_pid)); 1592 if ((proc_running = swapfile_proc_running(&b0, fname))) { 1593 kv_printf(*msg, _(" (STILL RUNNING)")); 1594 } 1595 } 1596 1597 if (b0_magic_wrong(&b0)) { 1598 kv_printf(*msg, _("\n [not usable on this computer]")); 1599 } 1600 } 1601 } else { 1602 kv_printf(*msg, _(" [cannot be read]")); 1603 } 1604 close(fd); 1605 } else { 1606 kv_printf(*msg, _(" [cannot be opened]")); 1607 } 1608 kv_printf(*msg, "\n"); 1609 1610 return x; 1611 } 1612 1613 /// @return true if the swapfile looks OK and there are no changes, thus it can be safely deleted. 1614 static bool swapfile_unchanged(char *fname) 1615 { 1616 ZeroBlock b0; 1617 1618 // Swapfile must exist. 1619 if (!os_path_exists(fname)) { 1620 return false; 1621 } 1622 1623 // must be able to read the first block 1624 int fd = os_open(fname, O_RDONLY, 0); 1625 if (fd < 0) { 1626 return false; 1627 } 1628 if (read_eintr(fd, &b0, sizeof(b0)) != sizeof(b0)) { 1629 close(fd); 1630 return false; 1631 } 1632 1633 bool ret = true; 1634 1635 // the ID and magic number must be correct 1636 if (ml_check_b0_id(&b0) == FAIL || b0_magic_wrong(&b0)) { 1637 ret = false; 1638 } 1639 1640 // must be unchanged 1641 if (b0.b0_dirty) { 1642 ret = false; 1643 } 1644 1645 // Host name must be known and must equal the current host name, otherwise 1646 // comparing pid is meaningless. 1647 if (*(b0.b0_hname) == NUL) { 1648 ret = false; 1649 } else { 1650 char hostname[B0_HNAME_SIZE]; 1651 os_get_hostname(hostname, B0_HNAME_SIZE); 1652 hostname[B0_HNAME_SIZE - 1] = NUL; 1653 b0.b0_hname[B0_HNAME_SIZE - 1] = NUL; // in case of corruption 1654 if (STRICMP(b0.b0_hname, hostname) != 0) { 1655 ret = false; 1656 } 1657 } 1658 1659 // process must be known and not running. 1660 if (char_to_long(b0.b0_pid) == 0 || swapfile_proc_running(&b0, fname)) { 1661 ret = false; 1662 } 1663 1664 // We do not check the user, it should be irrelevant for whether the swap 1665 // file is still useful. 1666 1667 close(fd); 1668 return ret; 1669 } 1670 1671 static int recov_file_names(char **names, char *path, bool prepend_dot) 1672 FUNC_ATTR_NONNULL_ALL 1673 { 1674 int num_names = 0; 1675 1676 // May also add the file name with a dot prepended, for swapfile in same 1677 // dir as original file. 1678 if (prepend_dot) { 1679 names[num_names] = modname(path, ".sw?", true); 1680 if (names[num_names] == NULL) { 1681 return num_names; 1682 } 1683 num_names++; 1684 } 1685 1686 // Form the normal swapfile name pattern by appending ".sw?". 1687 names[num_names] = concat_fnames(path, ".sw?", false); 1688 if (num_names >= 1) { // check if we have the same name twice 1689 char *p = names[num_names - 1]; 1690 int i = (int)strlen(names[num_names - 1]) - (int)strlen(names[num_names]); 1691 if (i > 0) { 1692 p += i; // file name has been expanded to full path 1693 } 1694 if (strcmp(p, names[num_names]) != 0) { 1695 num_names++; 1696 } else { 1697 xfree(names[num_names]); 1698 } 1699 } else { 1700 num_names++; 1701 } 1702 1703 return num_names; 1704 } 1705 1706 /// sync all memlines 1707 /// 1708 /// @param check_file if true, check if original file exists and was not changed. 1709 /// @param check_char if true, stop syncing when character becomes available, but 1710 /// 1711 /// always sync at least one block. 1712 void ml_sync_all(int check_file, int check_char, bool do_fsync) 1713 { 1714 FOR_ALL_BUFFERS(buf) { 1715 if (buf->b_ml.ml_mfp == NULL || buf->b_ml.ml_mfp->mf_fname == NULL) { 1716 continue; // no file 1717 } 1718 ml_flush_line(buf, false); // flush buffered line 1719 // flush locked block 1720 ml_find_line(buf, 0, ML_FLUSH); 1721 if (bufIsChanged(buf) && check_file && mf_need_trans(buf->b_ml.ml_mfp) 1722 && buf->b_ffname != NULL) { 1723 // If the original file does not exist anymore or has been changed 1724 // call ml_preserve() to get rid of all negative numbered blocks. 1725 FileInfo file_info; 1726 if (!os_fileinfo(buf->b_ffname, &file_info) 1727 || file_info.stat.st_mtim.tv_sec != buf->b_mtime_read 1728 || file_info.stat.st_mtim.tv_nsec != buf->b_mtime_read_ns 1729 || os_fileinfo_size(&file_info) != buf->b_orig_size) { 1730 ml_preserve(buf, false, do_fsync); 1731 did_check_timestamps = false; 1732 need_check_timestamps = true; // give message later 1733 } 1734 } 1735 if (buf->b_ml.ml_mfp->mf_dirty == MF_DIRTY_YES) { 1736 mf_sync(buf->b_ml.ml_mfp, (check_char ? MFS_STOP : 0) 1737 | (do_fsync && bufIsChanged(buf) ? MFS_FLUSH : 0)); 1738 if (check_char && os_char_avail()) { // character available now 1739 break; 1740 } 1741 } 1742 } 1743 } 1744 1745 /// sync one buffer, including negative blocks 1746 /// 1747 /// after this all the blocks are in the swapfile 1748 /// 1749 /// Used for the :preserve command and when the original file has been 1750 /// changed or deleted. 1751 /// 1752 /// @param message if true, the success of preserving is reported. 1753 void ml_preserve(buf_T *buf, bool message, bool do_fsync) 1754 { 1755 memfile_T *mfp = buf->b_ml.ml_mfp; 1756 int got_int_save = got_int; 1757 1758 if (mfp == NULL || mfp->mf_fname == NULL) { 1759 if (message) { 1760 emsg(_("E313: Cannot preserve, there is no swap file")); 1761 } 1762 return; 1763 } 1764 1765 // We only want to stop when interrupted here, not when interrupted 1766 // before. 1767 got_int = false; 1768 1769 ml_flush_line(buf, false); // flush buffered line 1770 ml_find_line(buf, 0, ML_FLUSH); // flush locked block 1771 int status = mf_sync(mfp, MFS_ALL | (do_fsync ? MFS_FLUSH : 0)); 1772 1773 // stack is invalid after mf_sync(.., MFS_ALL) 1774 buf->b_ml.ml_stack_top = 0; 1775 1776 // Some of the data blocks may have been changed from negative to 1777 // positive block number. In that case the pointer blocks need to be 1778 // updated. 1779 // 1780 // We don't know in which pointer block the references are, so we visit 1781 // all data blocks until there are no more translations to be done (or 1782 // we hit the end of the file, which can only happen in case a write fails, 1783 // e.g. when file system if full). 1784 // ml_find_line() does the work by translating the negative block numbers 1785 // when getting the first line of each data block. 1786 if (mf_need_trans(mfp) && !got_int) { 1787 linenr_T lnum = 1; 1788 while (mf_need_trans(mfp) && lnum <= buf->b_ml.ml_line_count) { 1789 bhdr_T *hp = ml_find_line(buf, lnum, ML_FIND); 1790 if (hp == NULL) { 1791 status = FAIL; 1792 goto theend; 1793 } 1794 CHECK(buf->b_ml.ml_locked_low != lnum, "low != lnum"); 1795 lnum = buf->b_ml.ml_locked_high + 1; 1796 } 1797 ml_find_line(buf, 0, ML_FLUSH); // flush locked block 1798 // sync the updated pointer blocks 1799 if (mf_sync(mfp, MFS_ALL | (do_fsync ? MFS_FLUSH : 0)) == FAIL) { 1800 status = FAIL; 1801 } 1802 buf->b_ml.ml_stack_top = 0; // stack is invalid now 1803 } 1804 theend: 1805 got_int |= got_int_save; 1806 1807 if (message) { 1808 if (status == OK) { 1809 msg(_("File preserved"), 0); 1810 } else { 1811 emsg(_("E314: Preserve failed")); 1812 } 1813 } 1814 } 1815 1816 // NOTE: The pointer returned by the ml_get_*() functions only remains valid 1817 // until the next call! 1818 // line1 = ml_get(1); 1819 // line2 = ml_get(2); // line1 is now invalid! 1820 // Make a copy of the line if necessary. 1821 1822 /// @return a pointer to a (read-only copy of a) line in curbuf. 1823 /// 1824 /// On failure an error message is given and IObuff is returned (to avoid 1825 /// having to check for error everywhere). 1826 char *ml_get(linenr_T lnum) 1827 FUNC_ATTR_NONNULL_RET 1828 { 1829 return ml_get_buf_impl(curbuf, lnum, false); 1830 } 1831 1832 /// @return a pointer to a (read-only copy of a) line. 1833 /// 1834 /// This is the same as ml_get(), but taking in the buffer 1835 /// as an argument. 1836 char *ml_get_buf(buf_T *buf, linenr_T lnum) 1837 FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET 1838 { 1839 return ml_get_buf_impl(buf, lnum, false); 1840 } 1841 1842 /// Like `ml_get_buf`, but allow the line to be mutated in place. 1843 /// 1844 /// This is very limited. Generally ml_replace_buf() 1845 /// should be used to modify a line. 1846 /// 1847 /// @return a pointer to a line in the buffer 1848 char *ml_get_buf_mut(buf_T *buf, linenr_T lnum) 1849 FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET 1850 { 1851 return ml_get_buf_impl(buf, lnum, true); 1852 } 1853 1854 /// @return pointer to position "pos". 1855 char *ml_get_pos(const pos_T *pos) 1856 FUNC_ATTR_NONNULL_ALL 1857 { 1858 return ml_get_buf(curbuf, pos->lnum) + pos->col; 1859 } 1860 1861 /// @return length (excluding the NUL) of the given line. 1862 colnr_T ml_get_len(linenr_T lnum) 1863 { 1864 return ml_get_buf_len(curbuf, lnum); 1865 } 1866 1867 /// @return length (excluding the NUL) of the text after position "pos". 1868 colnr_T ml_get_pos_len(pos_T *pos) 1869 { 1870 return ml_get_buf_len(curbuf, pos->lnum) - pos->col; 1871 } 1872 1873 /// @return length (excluding the NUL) of the given line in the given buffer. 1874 colnr_T ml_get_buf_len(buf_T *buf, linenr_T lnum) 1875 { 1876 const char *line = ml_get_buf(buf, lnum); 1877 1878 if (*line == NUL) { 1879 return 0; 1880 } 1881 1882 assert(buf->b_ml.ml_line_textlen > 0); 1883 return buf->b_ml.ml_line_textlen - 1; 1884 } 1885 1886 /// @return codepoint at pos. pos must be either valid or have col set to MAXCOL! 1887 int gchar_pos(pos_T *pos) 1888 FUNC_ATTR_NONNULL_ARG(1) 1889 { 1890 // When searching columns is sometimes put at the end of a line. 1891 if (pos->col == MAXCOL || pos->col > ml_get_len(pos->lnum)) { 1892 return NUL; 1893 } 1894 return utf_ptr2char(ml_get_pos(pos)); 1895 } 1896 1897 /// @param will_change true mark the buffer dirty (chars in the line will be changed) 1898 /// 1899 /// @return a pointer to a line in a specific buffer 1900 static char *ml_get_buf_impl(buf_T *buf, linenr_T lnum, bool will_change) 1901 FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET 1902 { 1903 static int recursive = 0; 1904 static char questions[4]; 1905 1906 if (buf->b_ml.ml_mfp == NULL) { // there are no lines 1907 buf->b_ml.ml_line_textlen = 1; 1908 return ""; 1909 } 1910 1911 if (lnum > buf->b_ml.ml_line_count) { // invalid line number 1912 if (recursive == 0) { 1913 // Avoid giving this message for a recursive call, may happen when 1914 // the GUI redraws part of the text. 1915 recursive++; 1916 siemsg(_(e_ml_get_invalid_lnum_nr), (int64_t)lnum); 1917 recursive--; 1918 } 1919 ml_flush_line(buf, false); 1920 errorret: 1921 STRCPY(questions, "???"); 1922 buf->b_ml.ml_line_textlen = 4; 1923 buf->b_ml.ml_line_lnum = lnum; 1924 return questions; 1925 } 1926 lnum = MAX(lnum, 1); // pretend line 0 is line 1 1927 1928 // See if it is the same line as requested last time. 1929 // Otherwise may need to flush last used line. 1930 // Don't use the last used line when 'swapfile' is reset, need to load all 1931 // blocks. 1932 if (buf->b_ml.ml_line_lnum != lnum) { 1933 ml_flush_line(buf, false); 1934 1935 // Find the data block containing the line. 1936 // This also fills the stack with the blocks from the root to the data 1937 // block and releases any locked block. 1938 bhdr_T *hp; 1939 if ((hp = ml_find_line(buf, lnum, ML_FIND)) == NULL) { 1940 if (recursive == 0) { 1941 // Avoid giving this message for a recursive call, may happen 1942 // when the GUI redraws part of the text. 1943 recursive++; 1944 get_trans_bufname(buf); 1945 shorten_dir(NameBuff); 1946 siemsg(_(e_ml_get_cannot_find_line_nr_in_buffer_nr_str), 1947 (int64_t)lnum, buf->b_fnum, NameBuff); 1948 recursive--; 1949 } 1950 goto errorret; 1951 } 1952 1953 DataBlock *dp = hp->bh_data; 1954 1955 int idx = lnum - buf->b_ml.ml_locked_low; 1956 unsigned start = (dp->db_index[idx] & DB_INDEX_MASK); 1957 // The text ends where the previous line starts. The first line ends 1958 // at the end of the block. 1959 unsigned end = idx == 0 ? dp->db_txt_end : (dp->db_index[idx - 1] & DB_INDEX_MASK); 1960 1961 buf->b_ml.ml_line_ptr = (char *)dp + start; 1962 buf->b_ml.ml_line_textlen = (colnr_T)(end - start); 1963 buf->b_ml.ml_line_lnum = lnum; 1964 buf->b_ml.ml_flags &= ~(ML_LINE_DIRTY | ML_ALLOCATED); 1965 } 1966 if (will_change) { 1967 buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS); 1968 #ifdef ML_GET_ALLOC_LINES 1969 if (buf->b_ml.ml_flags & ML_ALLOCATED) { 1970 // can't make the change in the data block 1971 buf->b_ml.ml_flags |= ML_LINE_DIRTY; 1972 } 1973 #endif 1974 ml_add_deleted_len_buf(buf, buf->b_ml.ml_line_ptr, -1); 1975 } 1976 1977 #ifdef ML_GET_ALLOC_LINES 1978 if ((buf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED)) == 0) { 1979 // make sure the text is in allocated memory 1980 buf->b_ml.ml_line_ptr = xmemdup(buf->b_ml.ml_line_ptr, 1981 (size_t)buf->b_ml.ml_line_textlen); 1982 buf->b_ml.ml_flags |= ML_ALLOCATED; 1983 if (will_change) { 1984 // can't make the change in the data block 1985 buf->b_ml.ml_flags |= ML_LINE_DIRTY; 1986 } 1987 } 1988 #endif 1989 return buf->b_ml.ml_line_ptr; 1990 } 1991 1992 /// Check if a line that was just obtained by a call to ml_get 1993 /// is in allocated memory. 1994 /// This ignores ML_ALLOCATED to get the same behavior as without ML_GET_ALLOC_LINES. 1995 int ml_line_alloced(void) 1996 { 1997 return curbuf->b_ml.ml_flags & ML_LINE_DIRTY; 1998 } 1999 2000 /// @param lnum append after this line (can be 0) 2001 /// @param line_arg text of the new line 2002 /// @param len_arg length of line, including NUL, or 0 2003 /// @param flags ML_APPEND_ flags 2004 /// 2005 /// @return FAIL for failure, OK otherwise 2006 static int ml_append_int(buf_T *buf, linenr_T lnum, char *line_arg, colnr_T len_arg, int flags) 2007 FUNC_ATTR_NONNULL_ARG(1) 2008 { 2009 char *line = line_arg; 2010 colnr_T len = len_arg; 2011 2012 if (lnum > buf->b_ml.ml_line_count || buf->b_ml.ml_mfp == NULL) { 2013 return FAIL; // lnum out of range 2014 } 2015 2016 if (lowest_marked && lowest_marked > lnum) { 2017 lowest_marked = lnum + 1; 2018 } 2019 2020 if (len == 0) { 2021 len = (colnr_T)strlen(line) + 1; // space needed for the text 2022 } 2023 int64_t space_needed = len + (int64_t)INDEX_SIZE; // space needed for text + index 2024 2025 memfile_T *mfp = buf->b_ml.ml_mfp; 2026 int64_t page_size = mfp->mf_page_size; 2027 2028 // find the data block containing the previous line 2029 // This also fills the stack with the blocks from the root to the data block 2030 // This also releases any locked block. 2031 int ret = FAIL; 2032 bhdr_T *hp; 2033 if ((hp = ml_find_line(buf, lnum == 0 ? 1 : lnum, 2034 ML_INSERT)) == NULL) { 2035 goto theend; 2036 } 2037 2038 buf->b_ml.ml_flags &= ~ML_EMPTY; 2039 2040 int db_idx; // index for lnum in data block 2041 if (lnum == 0) { // got line one instead, correct db_idx 2042 db_idx = -1; // careful, it is negative! 2043 } else { 2044 db_idx = lnum - buf->b_ml.ml_locked_low; 2045 } 2046 // get line count (number of indexes in current block) before the insertion 2047 int line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low; 2048 2049 DataBlock *dp = hp->bh_data; 2050 2051 // If 2052 // - there is not enough room in the current block 2053 // - appending to the last line in the block 2054 // - not appending to the last line in the file 2055 // insert in front of the next block. 2056 if ((int64_t)dp->db_free < space_needed && db_idx == line_count - 1 2057 && lnum < buf->b_ml.ml_line_count) { 2058 // Now that the line is not going to be inserted in the block that we 2059 // expected, the line count has to be adjusted in the pointer blocks 2060 // by using ml_locked_lineadd. 2061 (buf->b_ml.ml_locked_lineadd)--; 2062 (buf->b_ml.ml_locked_high)--; 2063 if ((hp = ml_find_line(buf, lnum + 1, ML_INSERT)) == NULL) { 2064 goto theend; 2065 } 2066 2067 db_idx = -1; // careful, it is negative! 2068 // get line count before the insertion 2069 line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low; 2070 CHECK(buf->b_ml.ml_locked_low != lnum + 1, "locked_low != lnum + 1"); 2071 2072 dp = hp->bh_data; 2073 } 2074 2075 if (buf->b_prev_line_count == 0) { 2076 buf->b_prev_line_count = buf->b_ml.ml_line_count; 2077 } 2078 buf->b_ml.ml_line_count++; 2079 2080 if ((int64_t)dp->db_free >= space_needed) { // enough room in data block 2081 // Insert the new line in an existing data block, or in the data block 2082 // allocated above. 2083 dp->db_txt_start -= (unsigned)len; 2084 dp->db_free -= (unsigned)space_needed; 2085 dp->db_line_count++; 2086 2087 // move the text of the lines that follow to the front 2088 // adjust the indexes of the lines that follow 2089 if (line_count > db_idx + 1) { // if there are following lines 2090 // Offset is the start of the previous line. 2091 // This will become the character just after the new line. 2092 int offset = db_idx < 0 ? (int)dp->db_txt_end 2093 : (int)((dp->db_index[db_idx]) & DB_INDEX_MASK); 2094 memmove((char *)dp + dp->db_txt_start, 2095 (char *)dp + dp->db_txt_start + len, 2096 (size_t)offset - (dp->db_txt_start + (size_t)len)); 2097 for (int i = line_count - 1; i > db_idx; i--) { 2098 dp->db_index[i + 1] = dp->db_index[i] - (unsigned)len; 2099 } 2100 dp->db_index[db_idx + 1] = (unsigned)(offset - len); 2101 } else { 2102 // add line at the end (which is the start of the text) 2103 dp->db_index[db_idx + 1] = dp->db_txt_start; 2104 } 2105 2106 // copy the text into the block 2107 memmove((char *)dp + dp->db_index[db_idx + 1], line, (size_t)len); 2108 if (flags & ML_APPEND_MARK) { 2109 dp->db_index[db_idx + 1] |= DB_MARKED; 2110 } 2111 2112 // Mark the block dirty. 2113 buf->b_ml.ml_flags |= ML_LOCKED_DIRTY; 2114 if (!(flags & ML_APPEND_NEW)) { 2115 buf->b_ml.ml_flags |= ML_LOCKED_POS; 2116 } 2117 } else { // not enough space in data block 2118 int line_count_left, line_count_right; 2119 int page_count_left, page_count_right; 2120 bhdr_T *hp_left; 2121 bhdr_T *hp_right; 2122 bhdr_T *hp_new; 2123 int lines_moved; 2124 int data_moved = 0; // init to shut up gcc 2125 int total_moved = 0; // init to shut up gcc 2126 int stack_idx; 2127 bool in_left; 2128 linenr_T lnum_left, lnum_right; 2129 PointerBlock *pp_new; 2130 2131 // There is not enough room, we have to create a new data block and 2132 // copy some lines into it. 2133 // Then we have to insert an entry in the pointer block. 2134 // If this pointer block also is full, we go up another block, and so 2135 // on, up to the root if necessary. 2136 // The line counts in the pointer blocks have already been adjusted by 2137 // ml_find_line(). 2138 // 2139 // We are going to allocate a new data block. Depending on the 2140 // situation it will be put to the left or right of the existing 2141 // block. If possible we put the new line in the left block and move 2142 // the lines after it to the right block. Otherwise the new line is 2143 // also put in the right block. This method is more efficient when 2144 // inserting a lot of lines at one place. 2145 if (db_idx < 0) { // left block is new, right block is existing 2146 lines_moved = 0; 2147 in_left = true; 2148 // space_needed does not change 2149 } else { // left block is existing, right block is new 2150 lines_moved = line_count - db_idx - 1; 2151 if (lines_moved == 0) { 2152 in_left = false; // put new line in right block 2153 // space_needed does not change 2154 } else { 2155 data_moved = (int)(((dp->db_index[db_idx]) & DB_INDEX_MASK) - 2156 dp->db_txt_start); 2157 total_moved = data_moved + lines_moved * (int)INDEX_SIZE; 2158 if ((int64_t)dp->db_free + total_moved >= space_needed) { 2159 in_left = true; // put new line in left block 2160 space_needed = total_moved; 2161 } else { 2162 in_left = false; // put new line in right block 2163 space_needed += total_moved; 2164 } 2165 } 2166 } 2167 2168 int64_t page_count = ((space_needed + (int64_t)HEADER_SIZE) + page_size - 1) / page_size; 2169 hp_new = ml_new_data(mfp, flags & ML_APPEND_NEW, page_count); 2170 if (db_idx < 0) { // left block is new 2171 hp_left = hp_new; 2172 hp_right = hp; 2173 line_count_left = 0; 2174 line_count_right = line_count; 2175 } else { // right block is new 2176 hp_left = hp; 2177 hp_right = hp_new; 2178 line_count_left = line_count; 2179 line_count_right = 0; 2180 } 2181 DataBlock *dp_right = hp_right->bh_data; 2182 DataBlock *dp_left = hp_left->bh_data; 2183 blocknr_T bnum_left = hp_left->bh_bnum; 2184 blocknr_T bnum_right = hp_right->bh_bnum; 2185 page_count_left = (int)hp_left->bh_page_count; 2186 page_count_right = (int)hp_right->bh_page_count; 2187 2188 // May move the new line into the right/new block. 2189 if (!in_left) { 2190 dp_right->db_txt_start -= (unsigned)len; 2191 dp_right->db_free -= (unsigned)len + (unsigned)INDEX_SIZE; 2192 dp_right->db_index[0] = dp_right->db_txt_start; 2193 if (flags & ML_APPEND_MARK) { 2194 dp_right->db_index[0] |= DB_MARKED; 2195 } 2196 2197 memmove((char *)dp_right + dp_right->db_txt_start, 2198 line, (size_t)len); 2199 line_count_right++; 2200 } 2201 // may move lines from the left/old block to the right/new one. 2202 if (lines_moved) { 2203 dp_right->db_txt_start -= (unsigned)data_moved; 2204 dp_right->db_free -= (unsigned)total_moved; 2205 memmove((char *)dp_right + dp_right->db_txt_start, 2206 (char *)dp_left + dp_left->db_txt_start, 2207 (size_t)data_moved); 2208 int offset = (int)(dp_right->db_txt_start - dp_left->db_txt_start); 2209 dp_left->db_txt_start += (unsigned)data_moved; 2210 dp_left->db_free += (unsigned)total_moved; 2211 2212 // update indexes in the new block 2213 for (int to = line_count_right, from = db_idx + 1; 2214 from < line_count_left; from++, to++) { 2215 dp_right->db_index[to] = dp->db_index[from] + (unsigned)offset; 2216 } 2217 line_count_right += lines_moved; 2218 line_count_left -= lines_moved; 2219 } 2220 2221 // May move the new line into the left (old or new) block. 2222 if (in_left) { 2223 dp_left->db_txt_start -= (unsigned)len; 2224 dp_left->db_free -= (unsigned)len + (unsigned)INDEX_SIZE; 2225 dp_left->db_index[line_count_left] = dp_left->db_txt_start; 2226 if (flags & ML_APPEND_MARK) { 2227 dp_left->db_index[line_count_left] |= DB_MARKED; 2228 } 2229 memmove((char *)dp_left + dp_left->db_txt_start, 2230 line, (size_t)len); 2231 line_count_left++; 2232 } 2233 2234 if (db_idx < 0) { // left block is new 2235 lnum_left = lnum + 1; 2236 lnum_right = 0; 2237 } else { // right block is new 2238 lnum_left = 0; 2239 if (in_left) { 2240 lnum_right = lnum + 2; 2241 } else { 2242 lnum_right = lnum + 1; 2243 } 2244 } 2245 dp_left->db_line_count = line_count_left; 2246 dp_right->db_line_count = line_count_right; 2247 2248 // release the two data blocks 2249 // The new one (hp_new) already has a correct blocknumber. 2250 // The old one (hp, in ml_locked) gets a positive blocknumber if 2251 // we changed it and we are not editing a new file. 2252 if (lines_moved || in_left) { 2253 buf->b_ml.ml_flags |= ML_LOCKED_DIRTY; 2254 } 2255 if (!(flags & ML_APPEND_NEW) && db_idx >= 0 && in_left) { 2256 buf->b_ml.ml_flags |= ML_LOCKED_POS; 2257 } 2258 mf_put(mfp, hp_new, true, false); 2259 2260 // flush the old data block 2261 // set ml_locked_lineadd to 0, because the updating of the 2262 // pointer blocks is done below 2263 int lineadd = buf->b_ml.ml_locked_lineadd; 2264 buf->b_ml.ml_locked_lineadd = 0; 2265 ml_find_line(buf, 0, ML_FLUSH); // flush data block 2266 2267 // update pointer blocks for the new data block 2268 for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; stack_idx--) { 2269 infoptr_T *ip = &(buf->b_ml.ml_stack[stack_idx]); 2270 int pb_idx = ip->ip_index; 2271 if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL) { 2272 goto theend; 2273 } 2274 PointerBlock *pp = hp->bh_data; // must be pointer block 2275 if (pp->pb_id != PTR_ID) { 2276 iemsg(_(e_pointer_block_id_wrong_three)); 2277 mf_put(mfp, hp, false, false); 2278 goto theend; 2279 } 2280 // TODO(vim): If the pointer block is full and we are adding at the end 2281 // try to insert in front of the next block 2282 // block not full, add one entry 2283 if (pp->pb_count < pp->pb_count_max) { 2284 if (pb_idx + 1 < (int)pp->pb_count) { 2285 memmove(&pp->pb_pointer[pb_idx + 2], 2286 &pp->pb_pointer[pb_idx + 1], 2287 (size_t)(pp->pb_count - pb_idx - 1) * sizeof(PointerEntry)); 2288 } 2289 pp->pb_count++; 2290 pp->pb_pointer[pb_idx].pe_line_count = line_count_left; 2291 pp->pb_pointer[pb_idx].pe_bnum = bnum_left; 2292 pp->pb_pointer[pb_idx].pe_page_count = page_count_left; 2293 pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right; 2294 pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right; 2295 pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right; 2296 2297 if (lnum_left != 0) { 2298 pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left; 2299 } 2300 if (lnum_right != 0) { 2301 pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right; 2302 } 2303 2304 mf_put(mfp, hp, true, false); 2305 buf->b_ml.ml_stack_top = stack_idx + 1; // truncate stack 2306 2307 if (lineadd) { 2308 (buf->b_ml.ml_stack_top)--; 2309 // fix line count for rest of blocks in the stack 2310 ml_lineadd(buf, lineadd); 2311 // fix stack itself 2312 buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high += lineadd; 2313 (buf->b_ml.ml_stack_top)++; 2314 } 2315 2316 // We are finished, break the loop here. 2317 break; 2318 } 2319 // pointer block full 2320 // 2321 // split the pointer block 2322 // allocate a new pointer block 2323 // move some of the pointer into the new block 2324 // prepare for updating the parent block 2325 while (true) { // do this twice when splitting block 1 2326 hp_new = ml_new_ptr(mfp); 2327 if (hp_new == NULL) { // TODO(vim): try to fix tree 2328 goto theend; 2329 } 2330 pp_new = hp_new->bh_data; 2331 2332 if (hp->bh_bnum != 1) { 2333 break; 2334 } 2335 2336 // if block 1 becomes full the tree is given an extra level 2337 // The pointers from block 1 are moved into the new block. 2338 // block 1 is updated to point to the new block 2339 // then continue to split the new block 2340 memmove(pp_new, pp, (size_t)page_size); 2341 pp->pb_count = 1; 2342 pp->pb_pointer[0].pe_bnum = hp_new->bh_bnum; 2343 pp->pb_pointer[0].pe_line_count = buf->b_ml.ml_line_count; 2344 pp->pb_pointer[0].pe_old_lnum = 1; 2345 pp->pb_pointer[0].pe_page_count = 1; 2346 mf_put(mfp, hp, true, false); // release block 1 2347 hp = hp_new; // new block is to be split 2348 pp = pp_new; 2349 CHECK(stack_idx != 0, _("stack_idx should be 0")); 2350 ip->ip_index = 0; 2351 stack_idx++; // do block 1 again later 2352 } 2353 // move the pointers after the current one to the new block 2354 // If there are none, the new entry will be in the new block. 2355 total_moved = pp->pb_count - pb_idx - 1; 2356 if (total_moved) { 2357 memmove(&pp_new->pb_pointer[0], 2358 &pp->pb_pointer[pb_idx + 1], 2359 (size_t)(total_moved) * sizeof(PointerEntry)); 2360 pp_new->pb_count = (uint16_t)total_moved; 2361 pp->pb_count = (uint16_t)(pp->pb_count - (total_moved - 1)); 2362 pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right; 2363 pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right; 2364 pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right; 2365 if (lnum_right) { 2366 pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right; 2367 } 2368 } else { 2369 pp_new->pb_count = 1; 2370 pp_new->pb_pointer[0].pe_bnum = bnum_right; 2371 pp_new->pb_pointer[0].pe_line_count = line_count_right; 2372 pp_new->pb_pointer[0].pe_page_count = page_count_right; 2373 pp_new->pb_pointer[0].pe_old_lnum = lnum_right; 2374 } 2375 pp->pb_pointer[pb_idx].pe_bnum = bnum_left; 2376 pp->pb_pointer[pb_idx].pe_line_count = line_count_left; 2377 pp->pb_pointer[pb_idx].pe_page_count = page_count_left; 2378 if (lnum_left) { 2379 pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left; 2380 } 2381 lnum_left = 0; 2382 lnum_right = 0; 2383 2384 // recompute line counts 2385 line_count_right = 0; 2386 for (int i = 0; i < (int)pp_new->pb_count; i++) { 2387 line_count_right += pp_new->pb_pointer[i].pe_line_count; 2388 } 2389 line_count_left = 0; 2390 for (int i = 0; i < (int)pp->pb_count; i++) { 2391 line_count_left += pp->pb_pointer[i].pe_line_count; 2392 } 2393 2394 bnum_left = hp->bh_bnum; 2395 bnum_right = hp_new->bh_bnum; 2396 page_count_left = 1; 2397 page_count_right = 1; 2398 mf_put(mfp, hp, true, false); 2399 mf_put(mfp, hp_new, true, false); 2400 } 2401 2402 // Safety check: fallen out of for loop? 2403 if (stack_idx < 0) { 2404 iemsg(_("E318: Updated too many blocks?")); 2405 buf->b_ml.ml_stack_top = 0; // invalidate stack 2406 } 2407 } 2408 2409 // The line was inserted below 'lnum' 2410 ml_updatechunk(buf, lnum + 1, len, ML_CHNK_ADDLINE); 2411 ret = OK; 2412 2413 theend: 2414 return ret; 2415 } 2416 2417 /// Flush any pending change and call ml_append_int() 2418 /// 2419 /// @param buf 2420 /// @param lnum append after this line (can be 0) 2421 /// @param line text of the new line 2422 /// @param len length of line, including NUL, or 0 2423 /// @param flags ML_APPEND_ flags 2424 /// 2425 /// @return FAIL for failure, OK otherwise 2426 static int ml_append_flush(buf_T *buf, linenr_T lnum, char *line, colnr_T len, int flags) 2427 FUNC_ATTR_NONNULL_ARG(1) 2428 { 2429 if (lnum > buf->b_ml.ml_line_count) { 2430 return FAIL; // lnum out of range 2431 } 2432 if (buf->b_ml.ml_line_lnum != 0) { 2433 // This may also invoke ml_append_int(). 2434 ml_flush_line(buf, false); 2435 } 2436 2437 return ml_append_int(buf, lnum, line, len, flags); 2438 } 2439 2440 /// Append a line after lnum (may be 0 to insert a line in front of the file). 2441 /// "line" does not need to be allocated, but can't be another line in a 2442 /// buffer, unlocking may make it invalid. 2443 /// 2444 /// "newfile": true when starting to edit a new file, meaning that pe_old_lnum 2445 /// will be set for recovery 2446 /// Check: The caller of this function should probably also call 2447 /// appended_lines(). 2448 /// 2449 /// @param lnum append after this line (can be 0) 2450 /// @param line text of the new line 2451 /// @param len length of new line, including NUL, or 0 2452 /// @param newfile flag, see above 2453 /// 2454 /// @return FAIL for failure, OK otherwise 2455 int ml_append(linenr_T lnum, char *line, colnr_T len, bool newfile) 2456 { 2457 return ml_append_flags(lnum, line, len, newfile ? ML_APPEND_NEW : 0); 2458 } 2459 2460 /// @param lnum append after this line (can be 0) 2461 /// @param line text of the new line 2462 /// @param len length of new line, including nul, or 0 2463 /// @param flags ML_APPEND_ values 2464 /// 2465 /// @return FAIL for failure, OK otherwise 2466 int ml_append_flags(linenr_T lnum, char *line, colnr_T len, int flags) 2467 { 2468 // When starting up, we might still need to create the memfile 2469 if (curbuf->b_ml.ml_mfp == NULL && open_buffer(false, NULL, 0) == FAIL) { 2470 return FAIL; 2471 } 2472 2473 return ml_append_flush(curbuf, lnum, line, len, flags); 2474 } 2475 2476 /// Like ml_append() but for an arbitrary buffer. The buffer must already have 2477 /// a memline. 2478 /// 2479 /// @param lnum append after this line (can be 0) 2480 /// @param line text of the new line 2481 /// @param len length of new line, including NUL, or 0 2482 /// @param newfile flag, see above 2483 int ml_append_buf(buf_T *buf, linenr_T lnum, char *line, colnr_T len, bool newfile) 2484 FUNC_ATTR_NONNULL_ARG(1) 2485 { 2486 if (buf->b_ml.ml_mfp == NULL) { 2487 return FAIL; 2488 } 2489 2490 return ml_append_flush(buf, lnum, line, len, newfile ? ML_APPEND_NEW : 0); 2491 } 2492 2493 void ml_add_deleted_len(char *ptr, ssize_t len) 2494 { 2495 ml_add_deleted_len_buf(curbuf, ptr, len); 2496 } 2497 2498 void ml_add_deleted_len_buf(buf_T *buf, char *ptr, ssize_t len) 2499 { 2500 if (inhibit_delete_count) { 2501 return; 2502 } 2503 ssize_t maxlen = (ssize_t)strlen(ptr); 2504 if (len == -1 || len > maxlen) { 2505 len = maxlen; 2506 } 2507 buf->deleted_bytes += (size_t)len + 1; 2508 buf->deleted_bytes2 += (size_t)len + 1; 2509 if (buf->update_need_codepoints) { 2510 mb_utflen(ptr, (size_t)len, &buf->deleted_codepoints, 2511 &buf->deleted_codeunits); 2512 buf->deleted_codepoints++; // NL char 2513 buf->deleted_codeunits++; 2514 } 2515 } 2516 2517 /// Replace line "lnum", with buffering, in current buffer. 2518 int ml_replace(linenr_T lnum, char *line, bool copy) 2519 { 2520 return ml_replace_buf(curbuf, lnum, line, copy, false); 2521 } 2522 2523 /// Replace a line for the current buffer. Like ml_replace() with: 2524 /// "len" is the length of the text, excluding NUL. 2525 int ml_replace_len(linenr_T lnum, char *line, size_t len, bool copy) 2526 { 2527 return ml_replace_buf_len(curbuf, lnum, line, len, copy, false); 2528 } 2529 2530 int ml_replace_buf(buf_T *buf, linenr_T lnum, char *line, bool copy, bool noalloc) 2531 FUNC_ATTR_NONNULL_ARG(1) 2532 { 2533 size_t len = line != NULL ? strlen(line) : (size_t)-1; 2534 return ml_replace_buf_len(buf, lnum, line, len, copy, noalloc); 2535 } 2536 2537 /// Replace line "lnum", with buffering. 2538 /// 2539 /// @param copy if true, make a copy of the line, otherwise the line has been 2540 /// copied to allocated memory already. 2541 /// if false, the "line" may be freed to add text properties! 2542 /// @param len_arg length of the text, excluding NUL 2543 /// 2544 /// Do not use it after calling ml_replace(). 2545 /// 2546 /// Check: The caller of this function should probably also call 2547 /// changed_lines(), unless update_screen(UPD_NOT_VALID) is used. 2548 /// 2549 /// @return FAIL for failure, OK otherwise 2550 int ml_replace_buf_len(buf_T *buf, linenr_T lnum, char *line_arg, size_t len_arg, bool copy, 2551 bool noalloc) 2552 FUNC_ATTR_NONNULL_ARG(1) 2553 { 2554 char *line = line_arg; 2555 2556 if (line == NULL) { // just checking... 2557 return FAIL; 2558 } 2559 2560 // When starting up, we might still need to create the memfile 2561 if (buf->b_ml.ml_mfp == NULL && open_buffer(false, NULL, 0) == FAIL) { 2562 return FAIL; 2563 } 2564 2565 if (copy) { 2566 assert(!noalloc); 2567 line = xmemdupz(line, len_arg); 2568 } 2569 2570 if (buf->b_ml.ml_line_lnum != lnum) { 2571 // another line is buffered, flush it 2572 ml_flush_line(buf, false); 2573 } 2574 2575 if (kv_size(buf->update_callbacks)) { 2576 ml_add_deleted_len_buf(buf, ml_get_buf(buf, lnum), -1); 2577 } 2578 2579 if (buf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED)) { 2580 xfree(buf->b_ml.ml_line_ptr); // free allocated line 2581 } 2582 2583 buf->b_ml.ml_line_ptr = line; 2584 buf->b_ml.ml_line_textlen = (colnr_T)len_arg + 1; 2585 buf->b_ml.ml_line_lnum = lnum; 2586 buf->b_ml.ml_flags = (buf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY; 2587 if (noalloc) { 2588 // TODO(bfredl): this is a bit of a hack. but replacing lines in a loop is really common, 2589 // and allocating a separate scratch buffer for each line which is immediately freed adds 2590 // a lot of noise. A more general refactor could be to use a _fixed_ scratch buffer for 2591 // all lines up to $REASONABLE_SIZE . 2592 ml_flush_line(buf, true); 2593 } 2594 2595 return OK; 2596 } 2597 2598 /// Delete line `lnum` in buffer 2599 /// 2600 /// @note The caller of this function should probably also call changed_lines() after this. 2601 /// 2602 /// @param message Show "--No lines in buffer--" message. 2603 /// 2604 /// @return FAIL for failure, OK otherwise 2605 int ml_delete_buf(buf_T *buf, linenr_T lnum, bool message) 2606 FUNC_ATTR_NONNULL_ALL 2607 { 2608 ml_flush_line(buf, false); 2609 return ml_delete_int(buf, lnum, message ? ML_DEL_MESSAGE : 0); 2610 } 2611 2612 /// Delete line `lnum` in the current buffer. 2613 /// 2614 /// @param flags ML_DEL_MESSAGE may give a "No lines in buffer" message. 2615 /// ML_DEL_UNDO this is called from undo. 2616 /// 2617 /// @return FAIL for failure, OK otherwise 2618 static int ml_delete_int(buf_T *buf, linenr_T lnum, int flags) 2619 FUNC_ATTR_NONNULL_ALL 2620 { 2621 if (lowest_marked && lowest_marked > lnum) { 2622 lowest_marked--; 2623 } 2624 2625 // If the file becomes empty the last line is replaced by an empty line. 2626 if (buf->b_ml.ml_line_count == 1) { // file becomes empty 2627 if (flags & ML_DEL_MESSAGE) { 2628 set_keep_msg(_(no_lines_msg), 0); 2629 } 2630 2631 int i = ml_replace_buf(buf, 1, "", true, false); 2632 buf->b_ml.ml_flags |= ML_EMPTY; 2633 2634 return i; 2635 } 2636 2637 // Find the data block containing the line. 2638 // This also fills the stack with the blocks from the root to the data block. 2639 // This also releases any locked block. 2640 memfile_T *mfp = buf->b_ml.ml_mfp; 2641 if (mfp == NULL) { 2642 return FAIL; 2643 } 2644 2645 bhdr_T *hp; 2646 if ((hp = ml_find_line(buf, lnum, ML_DELETE)) == NULL) { 2647 return FAIL; 2648 } 2649 2650 DataBlock *dp = hp->bh_data; 2651 // compute line count (number of entries in block) before the delete 2652 int count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 2; 2653 int idx = lnum - buf->b_ml.ml_locked_low; 2654 2655 if (buf->b_prev_line_count == 0) { 2656 buf->b_prev_line_count = buf->b_ml.ml_line_count; 2657 } 2658 buf->b_ml.ml_line_count--; 2659 2660 int line_start = ((dp->db_index[idx]) & DB_INDEX_MASK); 2661 int line_size; 2662 if (idx == 0) { // first line in block, text at the end 2663 line_size = (int)(dp->db_txt_end - (unsigned)line_start); 2664 } else { 2665 line_size = (int)(((dp->db_index[idx - 1]) & DB_INDEX_MASK) - (unsigned)line_start); 2666 } 2667 2668 // Line should always have an NL char internally (represented as NUL), 2669 // even if 'noeol' is set. 2670 assert(line_size >= 1); 2671 ml_add_deleted_len_buf(buf, (char *)dp + line_start, line_size - 1); 2672 2673 // special case: If there is only one line in the data block it becomes empty. 2674 // Then we have to remove the entry, pointing to this data block, from the 2675 // pointer block. If this pointer block also becomes empty, we go up another 2676 // block, and so on, up to the root if necessary. 2677 // The line counts in the pointer blocks have already been adjusted by 2678 // ml_find_line(). 2679 int ret = FAIL; 2680 if (count == 1) { 2681 mf_free(mfp, hp); // free the data block 2682 buf->b_ml.ml_locked = NULL; 2683 2684 for (int stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; stack_idx--) { 2685 buf->b_ml.ml_stack_top = 0; // stack is invalid when failing 2686 infoptr_T *ip = &(buf->b_ml.ml_stack[stack_idx]); 2687 idx = ip->ip_index; 2688 if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL) { 2689 goto theend; 2690 } 2691 PointerBlock *pp = hp->bh_data; // must be pointer block 2692 if (pp->pb_id != PTR_ID) { 2693 iemsg(_(e_pointer_block_id_wrong_four)); 2694 mf_put(mfp, hp, false, false); 2695 goto theend; 2696 } 2697 count = --(pp->pb_count); 2698 if (count == 0) { // the pointer block becomes empty! 2699 mf_free(mfp, hp); 2700 } else { 2701 if (count != idx) { // move entries after the deleted one 2702 memmove(&pp->pb_pointer[idx], &pp->pb_pointer[idx + 1], 2703 (size_t)(count - idx) * sizeof(PointerEntry)); 2704 } 2705 mf_put(mfp, hp, true, false); 2706 2707 buf->b_ml.ml_stack_top = stack_idx; // truncate stack 2708 // fix line count for rest of blocks in the stack 2709 if (buf->b_ml.ml_locked_lineadd != 0) { 2710 ml_lineadd(buf, buf->b_ml.ml_locked_lineadd); 2711 buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high += 2712 buf->b_ml.ml_locked_lineadd; 2713 } 2714 (buf->b_ml.ml_stack_top)++; 2715 2716 break; 2717 } 2718 } 2719 CHECK(stack_idx < 0, _("deleted block 1?")); 2720 } else { 2721 // delete the text by moving the next lines forwards 2722 int text_start = (int)dp->db_txt_start; 2723 memmove((char *)dp + text_start + line_size, 2724 (char *)dp + text_start, (size_t)(line_start - text_start)); 2725 2726 // delete the index by moving the next indexes backwards 2727 // Adjust the indexes for the text movement. 2728 for (int i = idx; i < count - 1; i++) { 2729 dp->db_index[i] = dp->db_index[i + 1] + (unsigned)line_size; 2730 } 2731 2732 dp->db_free += (unsigned)line_size + (unsigned)INDEX_SIZE; 2733 dp->db_txt_start += (unsigned)line_size; 2734 dp->db_line_count--; 2735 2736 // mark the block dirty and make sure it is in the file (for recovery) 2737 buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS); 2738 } 2739 2740 ml_updatechunk(buf, lnum, line_size, ML_CHNK_DELLINE); 2741 ret = OK; 2742 2743 theend: 2744 return ret; 2745 } 2746 2747 /// Delete line "lnum" in the current buffer. 2748 /// 2749 /// @note The caller of this function should probably also call 2750 /// deleted_lines() after this. 2751 /// 2752 /// @return FAIL for failure, OK otherwise 2753 int ml_delete(linenr_T lnum) 2754 { 2755 return ml_delete_flags(lnum, 0); 2756 } 2757 2758 /// Like ml_delete() but using flags (see ml_delete_int()). 2759 /// 2760 /// @return FAIL for failure, OK otherwise 2761 int ml_delete_flags(linenr_T lnum, int flags) 2762 { 2763 ml_flush_line(curbuf, false); 2764 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) { 2765 return FAIL; 2766 } 2767 2768 return ml_delete_int(curbuf, lnum, flags); 2769 } 2770 2771 /// set the DB_MARKED flag for line 'lnum' 2772 void ml_setmarked(linenr_T lnum) 2773 { 2774 // invalid line number 2775 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count 2776 || curbuf->b_ml.ml_mfp == NULL) { 2777 return; // give error message? 2778 } 2779 if (lowest_marked == 0 || lowest_marked > lnum) { 2780 lowest_marked = lnum; 2781 } 2782 2783 // find the data block containing the line 2784 // This also fills the stack with the blocks from the root to the data block 2785 // This also releases any locked block. 2786 bhdr_T *hp; 2787 if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL) { 2788 return; // give error message? 2789 } 2790 DataBlock *dp = hp->bh_data; 2791 dp->db_index[lnum - curbuf->b_ml.ml_locked_low] |= DB_MARKED; 2792 curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY; 2793 } 2794 2795 /// find the first line with its DB_MARKED flag set 2796 linenr_T ml_firstmarked(void) 2797 { 2798 if (curbuf->b_ml.ml_mfp == NULL) { 2799 return 0; 2800 } 2801 2802 // The search starts with lowest_marked line. This is the last line where 2803 // a mark was found, adjusted by inserting/deleting lines. 2804 for (linenr_T lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count;) { 2805 // Find the data block containing the line. 2806 // This also fills the stack with the blocks from the root to the data 2807 // block This also releases any locked block. 2808 bhdr_T *hp; 2809 if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL) { 2810 return 0; // give error message? 2811 } 2812 DataBlock *dp = hp->bh_data; 2813 2814 for (int i = lnum - curbuf->b_ml.ml_locked_low; 2815 lnum <= curbuf->b_ml.ml_locked_high; i++, lnum++) { 2816 if ((dp->db_index[i]) & DB_MARKED) { 2817 (dp->db_index[i]) &= DB_INDEX_MASK; 2818 curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY; 2819 lowest_marked = lnum + 1; 2820 return lnum; 2821 } 2822 } 2823 } 2824 2825 return 0; 2826 } 2827 2828 /// clear all DB_MARKED flags 2829 void ml_clearmarked(void) 2830 { 2831 if (curbuf->b_ml.ml_mfp == NULL) { // nothing to do 2832 return; 2833 } 2834 2835 // The search starts with line lowest_marked. 2836 for (linenr_T lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count;) { 2837 // Find the data block containing the line. 2838 // This also fills the stack with the blocks from the root to the data 2839 // block and releases any locked block. 2840 bhdr_T *hp; 2841 if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL) { 2842 return; // give error message? 2843 } 2844 DataBlock *dp = hp->bh_data; 2845 2846 for (int i = lnum - curbuf->b_ml.ml_locked_low; 2847 lnum <= curbuf->b_ml.ml_locked_high; i++, lnum++) { 2848 if ((dp->db_index[i]) & DB_MARKED) { 2849 (dp->db_index[i]) &= DB_INDEX_MASK; 2850 curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY; 2851 } 2852 } 2853 } 2854 2855 lowest_marked = 0; 2856 } 2857 2858 size_t ml_flush_deleted_bytes(buf_T *buf, size_t *codepoints, size_t *codeunits) 2859 { 2860 size_t ret = buf->deleted_bytes; 2861 *codepoints = buf->deleted_codepoints; 2862 *codeunits = buf->deleted_codeunits; 2863 buf->deleted_bytes = 0; 2864 buf->deleted_codepoints = 0; 2865 buf->deleted_codeunits = 0; 2866 return ret; 2867 } 2868 2869 /// flush ml_line if necessary 2870 static void ml_flush_line(buf_T *buf, bool noalloc) 2871 { 2872 static bool entered = false; 2873 2874 if (buf->b_ml.ml_line_lnum == 0 || buf->b_ml.ml_mfp == NULL) { 2875 return; // nothing to do 2876 } 2877 if (buf->b_ml.ml_flags & ML_LINE_DIRTY) { 2878 // This code doesn't work recursively. 2879 if (entered) { 2880 return; 2881 } 2882 entered = true; 2883 2884 buf->flush_count++; 2885 2886 linenr_T lnum = buf->b_ml.ml_line_lnum; 2887 char *new_line = buf->b_ml.ml_line_ptr; 2888 2889 bhdr_T *hp = ml_find_line(buf, lnum, ML_FIND); 2890 if (hp == NULL) { 2891 siemsg(_("E320: Cannot find line %" PRId64), (int64_t)lnum); 2892 } else { 2893 DataBlock *dp = hp->bh_data; 2894 int idx = lnum - buf->b_ml.ml_locked_low; 2895 int start = ((dp->db_index[idx]) & DB_INDEX_MASK); 2896 char *old_line = (char *)dp + start; 2897 int old_len; 2898 if (idx == 0) { // line is last in block 2899 old_len = (int)dp->db_txt_end - start; 2900 } else { // text of previous line follows 2901 old_len = (int)(dp->db_index[idx - 1] & DB_INDEX_MASK) - start; 2902 } 2903 colnr_T new_len = buf->b_ml.ml_line_textlen; 2904 int extra = new_len - old_len; // negative if lines gets smaller 2905 2906 // if new line fits in data block, replace directly 2907 if ((int)dp->db_free >= extra) { 2908 // if the length changes and there are following lines 2909 int count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1; 2910 if (extra != 0 && idx < count - 1) { 2911 // move text of following lines 2912 memmove((char *)dp + dp->db_txt_start - extra, 2913 (char *)dp + dp->db_txt_start, 2914 (size_t)(start - (int)dp->db_txt_start)); 2915 2916 // adjust pointers of this and following lines 2917 for (int i = idx + 1; i < count; i++) { 2918 dp->db_index[i] -= (unsigned)extra; 2919 } 2920 } 2921 dp->db_index[idx] -= (unsigned)extra; 2922 2923 // adjust free space 2924 dp->db_free -= (unsigned)extra; 2925 dp->db_txt_start -= (unsigned)extra; 2926 2927 // copy new line into the data block 2928 memmove(old_line - extra, new_line, (size_t)new_len); 2929 buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS); 2930 // The else case is already covered by the insert and delete 2931 if (extra != 0) { 2932 ml_updatechunk(buf, lnum, extra, ML_CHNK_UPDLINE); 2933 } 2934 } else { 2935 // Cannot do it in one data block: Delete and append. 2936 // Append first, because ml_delete_int() cannot delete the 2937 // last line in a buffer, which causes trouble for a buffer 2938 // that has only one line. 2939 // Don't forget to copy the mark! 2940 // How about handling errors??? 2941 (void)ml_append_int(buf, lnum, new_line, new_len, 2942 (dp->db_index[idx] & DB_MARKED) ? ML_APPEND_MARK : 0); 2943 (void)ml_delete_int(buf, lnum, 0); 2944 } 2945 } 2946 if (!noalloc) { 2947 xfree(new_line); 2948 } 2949 2950 entered = false; 2951 } else if (buf->b_ml.ml_flags & ML_ALLOCATED) { 2952 assert(!noalloc); // caller must set ML_LINE_DIRTY with noalloc, handled above 2953 xfree(buf->b_ml.ml_line_ptr); 2954 } 2955 2956 buf->b_ml.ml_flags &= ~(ML_LINE_DIRTY | ML_ALLOCATED); 2957 buf->b_ml.ml_line_lnum = 0; 2958 buf->b_ml.ml_line_offset = 0; 2959 } 2960 2961 /// create a new, empty, data block 2962 static bhdr_T *ml_new_data(memfile_T *mfp, bool negative, int64_t page_count) 2963 { 2964 assert(page_count >= 0); 2965 bhdr_T *hp = mf_new(mfp, negative, (unsigned)page_count); 2966 DataBlock *dp = hp->bh_data; 2967 dp->db_id = DATA_ID; 2968 dp->db_txt_start = dp->db_txt_end = (unsigned)page_count * mfp->mf_page_size; 2969 dp->db_free = dp->db_txt_start - (unsigned)HEADER_SIZE; 2970 dp->db_line_count = 0; 2971 2972 return hp; 2973 } 2974 2975 /// create a new, empty, pointer block 2976 static bhdr_T *ml_new_ptr(memfile_T *mfp) 2977 { 2978 bhdr_T *hp = mf_new(mfp, false, 1); 2979 PointerBlock *pp = hp->bh_data; 2980 pp->pb_id = PTR_ID; 2981 pp->pb_count = 0; 2982 pp->pb_count_max = PB_COUNT_MAX(mfp); 2983 2984 return hp; 2985 } 2986 2987 /// Lookup line 'lnum' in a memline. 2988 /// 2989 /// @param action: if ML_DELETE or ML_INSERT the line count is updated while searching 2990 /// if ML_FLUSH only flush a locked block 2991 /// if ML_FIND just find the line 2992 /// 2993 /// If the block was found it is locked and put in ml_locked. 2994 /// The stack is updated to lead to the locked block. The ip_high field in 2995 /// the stack is updated to reflect the last line in the block AFTER the 2996 /// insert or delete, also if the pointer block has not been updated yet. But 2997 /// if ml_locked != NULL ml_locked_lineadd must be added to ip_high. 2998 /// 2999 /// @return NULL for failure, pointer to block header otherwise 3000 static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action) 3001 { 3002 bhdr_T *hp; 3003 int top; 3004 3005 memfile_T *mfp = buf->b_ml.ml_mfp; 3006 3007 // If there is a locked block check if the wanted line is in it. 3008 // If not, flush and release the locked block. 3009 // Don't do this for ML_INSERT_SAME, because the stack need to be updated. 3010 // Don't do this for ML_FLUSH, because we want to flush the locked block. 3011 // Don't do this when 'swapfile' is reset, we want to load all the blocks. 3012 if (buf->b_ml.ml_locked) { 3013 if (ML_SIMPLE(action) 3014 && buf->b_ml.ml_locked_low <= lnum 3015 && buf->b_ml.ml_locked_high >= lnum) { 3016 // remember to update pointer blocks and stack later 3017 if (action == ML_INSERT) { 3018 (buf->b_ml.ml_locked_lineadd)++; 3019 (buf->b_ml.ml_locked_high)++; 3020 } else if (action == ML_DELETE) { 3021 (buf->b_ml.ml_locked_lineadd)--; 3022 (buf->b_ml.ml_locked_high)--; 3023 } 3024 return buf->b_ml.ml_locked; 3025 } 3026 3027 mf_put(mfp, buf->b_ml.ml_locked, buf->b_ml.ml_flags & ML_LOCKED_DIRTY, 3028 buf->b_ml.ml_flags & ML_LOCKED_POS); 3029 buf->b_ml.ml_locked = NULL; 3030 3031 // If lines have been added or deleted in the locked block, need to 3032 // update the line count in pointer blocks. 3033 if (buf->b_ml.ml_locked_lineadd != 0) { 3034 ml_lineadd(buf, buf->b_ml.ml_locked_lineadd); 3035 } 3036 } 3037 3038 if (action == ML_FLUSH) { // nothing else to do 3039 return NULL; 3040 } 3041 3042 blocknr_T bnum = 1; // start at the root of the tree 3043 blocknr_T bnum2; 3044 int page_count = 1; 3045 linenr_T low = 1; 3046 linenr_T high = buf->b_ml.ml_line_count; 3047 3048 if (action == ML_FIND) { // first try stack entries 3049 for (top = buf->b_ml.ml_stack_top - 1; top >= 0; top--) { 3050 infoptr_T *ip = &(buf->b_ml.ml_stack[top]); 3051 if (ip->ip_low <= lnum && ip->ip_high >= lnum) { 3052 bnum = ip->ip_bnum; 3053 low = ip->ip_low; 3054 high = ip->ip_high; 3055 buf->b_ml.ml_stack_top = top; // truncate stack at prev entry 3056 break; 3057 } 3058 } 3059 if (top < 0) { 3060 buf->b_ml.ml_stack_top = 0; // not found, start at the root 3061 } 3062 } else { // ML_DELETE or ML_INSERT 3063 buf->b_ml.ml_stack_top = 0; // start at the root 3064 } 3065 // search downwards in the tree until a data block is found 3066 while (true) { 3067 if ((hp = mf_get(mfp, bnum, (unsigned)page_count)) == NULL) { 3068 goto error_noblock; 3069 } 3070 3071 // update high for insert/delete 3072 if (action == ML_INSERT) { 3073 high++; 3074 } else if (action == ML_DELETE) { 3075 high--; 3076 } 3077 3078 DataBlock *dp = hp->bh_data; 3079 if (dp->db_id == DATA_ID) { // data block 3080 buf->b_ml.ml_locked = hp; 3081 buf->b_ml.ml_locked_low = low; 3082 buf->b_ml.ml_locked_high = high; 3083 buf->b_ml.ml_locked_lineadd = 0; 3084 buf->b_ml.ml_flags &= ~(ML_LOCKED_DIRTY | ML_LOCKED_POS); 3085 return hp; 3086 } 3087 3088 PointerBlock *pp = (PointerBlock *)(dp); // must be pointer block 3089 if (pp->pb_id != PTR_ID) { 3090 iemsg(_(e_pointer_block_id_wrong)); 3091 goto error_block; 3092 } 3093 3094 top = ml_add_stack(buf); // add new entry to stack 3095 infoptr_T *ip = &(buf->b_ml.ml_stack[top]); 3096 ip->ip_bnum = bnum; 3097 ip->ip_low = low; 3098 ip->ip_high = high; 3099 ip->ip_index = -1; // index not known yet 3100 3101 bool dirty = false; 3102 int idx; 3103 for (idx = 0; idx < (int)pp->pb_count; idx++) { 3104 linenr_T t = pp->pb_pointer[idx].pe_line_count; 3105 CHECK(t == 0, _("pe_line_count is zero")); 3106 if ((low += t) > lnum) { 3107 ip->ip_index = idx; 3108 bnum = pp->pb_pointer[idx].pe_bnum; 3109 page_count = pp->pb_pointer[idx].pe_page_count; 3110 high = low - 1; 3111 low -= t; 3112 3113 // a negative block number may have been changed 3114 if (bnum < 0) { 3115 bnum2 = mf_trans_del(mfp, bnum); 3116 if (bnum != bnum2) { 3117 bnum = bnum2; 3118 pp->pb_pointer[idx].pe_bnum = bnum; 3119 dirty = true; 3120 } 3121 } 3122 3123 break; 3124 } 3125 } 3126 if (idx >= (int)pp->pb_count) { // past the end: something wrong! 3127 if (lnum > buf->b_ml.ml_line_count) { 3128 siemsg(_(e_line_number_out_of_range_nr_past_the_end), 3129 (int64_t)lnum - buf->b_ml.ml_line_count); 3130 } else { 3131 siemsg(_(e_line_count_wrong_in_block_nr), bnum); 3132 } 3133 goto error_block; 3134 } 3135 if (action == ML_DELETE) { 3136 pp->pb_pointer[idx].pe_line_count--; 3137 dirty = true; 3138 } else if (action == ML_INSERT) { 3139 pp->pb_pointer[idx].pe_line_count++; 3140 dirty = true; 3141 } 3142 mf_put(mfp, hp, dirty, false); 3143 } 3144 3145 error_block: 3146 mf_put(mfp, hp, false, false); 3147 error_noblock: 3148 // If action is ML_DELETE or ML_INSERT we have to correct the tree for 3149 // the incremented/decremented line counts, because there won't be a line 3150 // inserted/deleted after all. 3151 if (action == ML_DELETE) { 3152 ml_lineadd(buf, 1); 3153 } else if (action == ML_INSERT) { 3154 ml_lineadd(buf, -1); 3155 } 3156 buf->b_ml.ml_stack_top = 0; 3157 return NULL; 3158 } 3159 3160 /// add an entry to the info pointer stack 3161 /// 3162 /// @return number of the new entry 3163 static int ml_add_stack(buf_T *buf) 3164 { 3165 int top = buf->b_ml.ml_stack_top; 3166 3167 // may have to increase the stack size 3168 if (top == buf->b_ml.ml_stack_size) { 3169 CHECK(top > 0, _("Stack size increases")); // more than 5 levels??? 3170 3171 buf->b_ml.ml_stack_size += STACK_INCR; 3172 size_t new_size = sizeof(infoptr_T) * (size_t)buf->b_ml.ml_stack_size; 3173 buf->b_ml.ml_stack = xrealloc(buf->b_ml.ml_stack, new_size); 3174 } 3175 3176 buf->b_ml.ml_stack_top++; 3177 return top; 3178 } 3179 3180 /// Update the pointer blocks on the stack for inserted/deleted lines. 3181 /// The stack itself is also updated. 3182 /// 3183 /// When an insert/delete line action fails, the line is not inserted/deleted, 3184 /// but the pointer blocks have already been updated. That is fixed here by 3185 /// walking through the stack. 3186 /// 3187 /// Count is the number of lines added, negative if lines have been deleted. 3188 static void ml_lineadd(buf_T *buf, int count) 3189 { 3190 memfile_T *mfp = buf->b_ml.ml_mfp; 3191 3192 for (int idx = buf->b_ml.ml_stack_top - 1; idx >= 0; idx--) { 3193 infoptr_T *ip = &(buf->b_ml.ml_stack[idx]); 3194 bhdr_T *hp; 3195 if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL) { 3196 break; 3197 } 3198 PointerBlock *pp = hp->bh_data; // must be pointer block 3199 if (pp->pb_id != PTR_ID) { 3200 mf_put(mfp, hp, false, false); 3201 iemsg(_(e_pointer_block_id_wrong_two)); 3202 break; 3203 } 3204 pp->pb_pointer[ip->ip_index].pe_line_count += count; 3205 ip->ip_high += count; 3206 mf_put(mfp, hp, true, false); 3207 } 3208 } 3209 3210 #if defined(HAVE_READLINK) 3211 3212 /// Resolve a symlink in the last component of a file name. 3213 /// Note that f_resolve() does it for every part of the path, we don't do that 3214 /// here. 3215 /// 3216 /// @return OK if it worked and the resolved link in "buf[MAXPATHL]", 3217 /// FAIL otherwise 3218 int resolve_symlink(const char *fname, char *buf) 3219 { 3220 char tmp[MAXPATHL]; 3221 int depth = 0; 3222 3223 if (fname == NULL) { 3224 return FAIL; 3225 } 3226 3227 // Put the result so far in tmp[], starting with the original name. 3228 xstrlcpy(tmp, fname, MAXPATHL); 3229 3230 while (true) { 3231 // Limit symlink depth to 100, catch recursive loops. 3232 if (++depth == 100) { 3233 semsg(_("E773: Symlink loop for \"%s\""), fname); 3234 return FAIL; 3235 } 3236 3237 int ret = (int)readlink(tmp, buf, MAXPATHL - 1); 3238 if (ret <= 0) { 3239 if (errno == EINVAL || errno == ENOENT) { 3240 // Found non-symlink or not existing file, stop here. 3241 // When at the first level use the unmodified name, skip the 3242 // call to vim_FullName(). 3243 if (depth == 1) { 3244 return FAIL; 3245 } 3246 3247 // Use the resolved name in tmp[]. 3248 break; 3249 } 3250 3251 // There must be some error reading links, use original name. 3252 return FAIL; 3253 } 3254 buf[ret] = NUL; 3255 3256 // Check whether the symlink is relative or absolute. 3257 // If it's relative, build a new path based on the directory 3258 // portion of the filename (if any) and the path the symlink 3259 // points to. 3260 if (path_is_absolute(buf)) { 3261 STRCPY(tmp, buf); 3262 } else { 3263 char *tail = path_tail(tmp); 3264 if (strlen(tail) + strlen(buf) >= MAXPATHL) { 3265 return FAIL; 3266 } 3267 STRCPY(tail, buf); 3268 } 3269 } 3270 3271 // Try to resolve the full name of the file so that the swapfile name will 3272 // be consistent even when opening a relative symlink from different 3273 // working directories. 3274 return vim_FullName(tmp, buf, MAXPATHL, true); 3275 } 3276 #endif 3277 3278 /// Make swapfile name out of the file name and a directory name. 3279 /// 3280 /// @return pointer to allocated memory or NULL. 3281 char *makeswapname(char *fname, char *ffname, buf_T *buf, char *dir_name) 3282 { 3283 char *fname_res = fname; 3284 #ifdef HAVE_READLINK 3285 char fname_buf[MAXPATHL]; 3286 3287 // Expand symlink in the file name, so that we put the swapfile with the 3288 // actual file instead of with the symlink. 3289 if (resolve_symlink(fname, fname_buf) == OK) { 3290 fname_res = fname_buf; 3291 } 3292 #endif 3293 int len = (int)strlen(dir_name); 3294 3295 char *s = dir_name + len; 3296 if (after_pathsep(dir_name, s) && len > 1 && s[-1] == s[-2]) { 3297 // Ends with '//', Use Full path 3298 char *r = NULL; 3299 s = make_percent_swname(dir_name, s, fname_res); 3300 if (s != NULL) { 3301 r = modname(s, ".swp", false); 3302 xfree(s); 3303 } 3304 return r; 3305 } 3306 3307 // Prepend a '.' to the swapfile name for the current directory. 3308 char *r = modname(fname_res, ".swp", 3309 dir_name[0] == '.' && dir_name[1] == NUL); 3310 if (r == NULL) { // out of memory 3311 return NULL; 3312 } 3313 3314 s = get_file_in_dir(r, dir_name); 3315 xfree(r); 3316 return s; 3317 } 3318 3319 /// Get file name to use for swapfile or backup file. 3320 /// Use the name of the edited file "fname" and an entry in the 'dir' or 'bdir' option "dname". 3321 /// - If "dname" is ".", return "fname" (swapfile in dir of file). 3322 /// - If "dname" starts with "./", insert "dname" in "fname" (swapfile relative to dir of file). 3323 /// - Otherwise, prepend "dname" to the tail of "fname" (swapfile in specific dir). 3324 /// 3325 /// The return value is an allocated string and can be NULL. 3326 /// 3327 /// @param dname don't use "dirname", it is a global for Alpha 3328 char *get_file_in_dir(char *fname, char *dname) 3329 { 3330 char *retval; 3331 3332 char *tail = path_tail(fname); 3333 3334 if (dname[0] == '.' && dname[1] == NUL) { 3335 retval = xstrdup(fname); 3336 } else if (dname[0] == '.' && vim_ispathsep(dname[1])) { 3337 if (tail == fname) { // no path before file name 3338 retval = concat_fnames(dname + 2, tail, true); 3339 } else { 3340 char save_char = *tail; 3341 *tail = NUL; 3342 char *t = concat_fnames(fname, dname + 2, true); 3343 *tail = save_char; 3344 retval = concat_fnames(t, tail, true); 3345 xfree(t); 3346 } 3347 } else { 3348 retval = concat_fnames(dname, tail, true); 3349 } 3350 3351 return retval; 3352 } 3353 3354 /// Build the ATTENTION message: info about an existing swapfile. 3355 /// 3356 /// @param buf buffer being edited 3357 /// @param fname swapfile name 3358 /// @param fhname swapfile name, home replaced 3359 /// @param msg string buffer, emitted as either a regular or confirm message 3360 static void attention_message(buf_T *buf, char *fname, char *fhname, StringBuilder *msg) 3361 { 3362 assert(buf->b_fname != NULL); 3363 3364 emsg(_("E325: ATTENTION")); 3365 kv_printf(*msg, _("Found a swap file by the name \"")); 3366 kv_printf(*msg, "%s\"\n", fhname); 3367 const time_t swap_mtime = swapfile_info(fname, msg); 3368 kv_printf(*msg, (_("While opening file \""))); 3369 kv_printf(*msg, "%s\"\n", buf->b_fname); 3370 FileInfo file_info; 3371 if (!os_fileinfo(buf->b_fname, &file_info)) { 3372 kv_printf(*msg, _(" CANNOT BE FOUND")); 3373 } else { 3374 kv_printf(*msg, _(" dated: ")); 3375 time_t x = file_info.stat.st_mtim.tv_sec; 3376 char ctime_buf[50]; 3377 kv_printf(*msg, "%s", os_ctime_r(&x, ctime_buf, sizeof(ctime_buf), true)); 3378 if (swap_mtime != 0 && x > swap_mtime) { 3379 kv_printf(*msg, _(" NEWER than swap file!\n")); 3380 } 3381 } 3382 // Some of these messages are long to allow translation to 3383 // other languages. 3384 kv_printf(*msg, _("\n(1) Another program may be editing the same file. If this is" 3385 " the case,\n be careful not to end up with two different" 3386 " instances of the same\n file when making changes." 3387 " Quit, or continue with caution.\n")); 3388 kv_printf(*msg, _("(2) An edit session for this file crashed.\n")); 3389 kv_printf(*msg, _(" If this is the case, use \":recover\" or \"nvim -r ")); 3390 kv_printf(*msg, "%s", buf->b_fname); 3391 kv_printf(*msg, (_("\"\n to recover the changes (see \":help recovery\").\n"))); 3392 kv_printf(*msg, _(" If you did this already, delete the swap file \"")); 3393 kv_printf(*msg, "%s", fname); 3394 kv_printf(*msg, _("\"\n to avoid this message.\n")); 3395 } 3396 3397 /// Trigger the SwapExists autocommands. 3398 /// 3399 /// @return a value for equivalent to do_dialog(). 3400 static sea_choice_T do_swapexists(buf_T *buf, char *fname) 3401 { 3402 set_vim_var_string(VV_SWAPNAME, fname, -1); 3403 set_vim_var_string(VV_SWAPCHOICE, NULL, -1); 3404 3405 // Trigger SwapExists autocommands with <afile> set to the file being 3406 // edited. Disallow changing directory here. 3407 allbuf_lock++; 3408 apply_autocmds(EVENT_SWAPEXISTS, buf->b_fname, NULL, false, NULL); 3409 allbuf_lock--; 3410 3411 set_vim_var_string(VV_SWAPNAME, NULL, -1); 3412 3413 switch (*get_vim_var_str(VV_SWAPCHOICE)) { 3414 case 'o': 3415 return SEA_CHOICE_READONLY; 3416 case 'e': 3417 return SEA_CHOICE_EDIT; 3418 case 'r': 3419 return SEA_CHOICE_RECOVER; 3420 case 'd': 3421 return SEA_CHOICE_DELETE; 3422 case 'q': 3423 return SEA_CHOICE_QUIT; 3424 case 'a': 3425 return SEA_CHOICE_ABORT; 3426 } 3427 3428 return SEA_CHOICE_NONE; 3429 } 3430 3431 /// Find out what name to use for the swapfile for buffer 'buf'. 3432 /// 3433 /// Several names are tried to find one that does not exist. Last directory in 3434 /// option is automatically created. 3435 /// 3436 /// @note If BASENAMELEN is not correct, you will get error messages for 3437 /// not being able to open the swap or undo file. 3438 /// @note May trigger SwapExists autocmd, pointers may change! 3439 /// 3440 /// @param[in] buf Buffer for which swapfile names needs to be found. 3441 /// @param[in,out] dirp Pointer to a list of directories. When out of memory, 3442 /// is set to NULL. Is advanced to the next directory in 3443 /// the list otherwise. 3444 /// @param[in] old_fname Allowed existing swapfile name. Except for this 3445 /// case, name of the non-existing file is used. 3446 /// @param[in,out] found_existing_dir If points to true, then new directory 3447 /// for swapfile is not created. At first 3448 /// findswapname() call this argument must 3449 /// point to false. This parameter may only 3450 /// be set to true by this function, it is 3451 /// never set to false. 3452 /// 3453 /// @return [allocated] Name of the swapfile. 3454 static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_existing_dir) 3455 FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1, 2, 4) 3456 { 3457 char *buf_fname = buf->b_fname; 3458 3459 // Isolate a directory name from *dirp and put it in dir_name. 3460 // First allocate some memory to put the directory name in. 3461 const size_t dir_len = strlen(*dirp) + 1; 3462 char *dir_name = xmalloc(dir_len); 3463 copy_option_part(dirp, dir_name, dir_len, ","); 3464 3465 // We try different swapfile names until we find one that does not exist yet. 3466 char *fname = makeswapname(buf_fname, buf->b_ffname, buf, dir_name); 3467 3468 while (true) { 3469 size_t n; 3470 if (fname == NULL) { // must be out of memory 3471 break; 3472 } 3473 if ((n = strlen(fname)) == 0) { // safety check 3474 XFREE_CLEAR(fname); 3475 break; 3476 } 3477 // check if the swapfile already exists 3478 // Extra security check: When a swapfile is a symbolic link, this 3479 // is most likely a symlink attack. 3480 FileInfo file_info; 3481 bool file_or_link_found = os_fileinfo_link(fname, &file_info); 3482 if (!file_or_link_found) { 3483 break; 3484 } 3485 3486 // A file name equal to old_fname is OK to use. 3487 if (old_fname != NULL && path_fnamecmp(fname, old_fname) == 0) { 3488 break; 3489 } 3490 3491 // get here when file already exists 3492 if (fname[n - 2] == 'w' && fname[n - 1] == 'p') { // first try 3493 // If we get here the ".swp" file really exists. 3494 // Give an error message, unless recovering, no file name, we are 3495 // viewing a help file or when the path of the file is different 3496 // (happens when all .swp files are in one directory). 3497 if (!recoverymode && buf_fname != NULL && !buf->b_help && !(buf->b_flags & BF_DUMMY)) { 3498 int fd; 3499 ZeroBlock b0; 3500 bool differ = false; 3501 3502 // Try to read block 0 from the swapfile to get the original file name (and inode number). 3503 fd = os_open(fname, O_RDONLY, 0); 3504 if (fd >= 0) { 3505 if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0)) { 3506 proc_running = swapfile_proc_running(&b0, fname); 3507 3508 // If the swapfile has the same directory as the 3509 // buffer don't compare the directory names, they can 3510 // have a different mountpoint. 3511 if (b0.b0_flags & B0_SAME_DIR) { 3512 if (path_fnamecmp(path_tail(buf->b_ffname), 3513 path_tail(b0.b0_fname)) != 0 3514 || !same_directory(fname, buf->b_ffname)) { 3515 // Symlinks may point to the same file even 3516 // when the name differs, need to check the 3517 // inode too. 3518 expand_env(b0.b0_fname, NameBuff, MAXPATHL); 3519 if (fnamecmp_ino(buf->b_ffname, NameBuff, 3520 char_to_long(b0.b0_ino))) { 3521 differ = true; 3522 } 3523 } 3524 } else { 3525 // The name in the swapfile may be "~user/path/file". Expand it first. 3526 expand_env(b0.b0_fname, NameBuff, MAXPATHL); 3527 if (fnamecmp_ino(buf->b_ffname, NameBuff, 3528 char_to_long(b0.b0_ino))) { 3529 differ = true; 3530 } 3531 } 3532 } 3533 close(fd); 3534 } 3535 3536 // Show the ATTENTION message when: 3537 // - there is an old swapfile for the current file 3538 // - the buffer was not recovered 3539 if (!differ && !(curbuf->b_flags & BF_RECOVERED) 3540 && vim_strchr(p_shm, SHM_ATTENTION) == NULL) { 3541 sea_choice_T choice = SEA_CHOICE_NONE; 3542 3543 // It's safe to delete the swapfile if all these are true: 3544 // - the edited file exists 3545 // - the swapfile has no changes and looks OK 3546 if (os_path_exists(buf->b_fname) && swapfile_unchanged(fname)) { 3547 choice = SEA_CHOICE_DELETE; 3548 if (p_verbose > 0) { 3549 verb_msg(_("Found a swap file that is not useful, deleting it")); 3550 } 3551 } 3552 3553 // If there is a SwapExists autocommand and we can handle the 3554 // response, trigger it. It may return 0 to ask the user anyway. 3555 if (choice == SEA_CHOICE_NONE 3556 && swap_exists_action != SEA_NONE 3557 && has_autocmd(EVENT_SWAPEXISTS, buf_fname, buf)) { 3558 choice = do_swapexists(buf, fname); 3559 } 3560 3561 if (choice == SEA_CHOICE_NONE && swap_exists_action == SEA_READONLY) { 3562 // always open readonly. 3563 choice = SEA_CHOICE_READONLY; 3564 } 3565 3566 proc_running = 0; // Set by attention_message..swapfile_info. 3567 if (choice == SEA_CHOICE_NONE) { 3568 no_wait_return++; 3569 // Show info about the existing swapfile. 3570 StringBuilder msg = KV_INITIAL_VALUE; 3571 kv_resize(msg, IOSIZE); 3572 char *fhname = home_replace_save(NULL, fname); 3573 attention_message(buf, fname, fhname, &msg); 3574 3575 // We don't want a 'q' typed at the more-prompt 3576 // interrupt loading a file. 3577 got_int = false; 3578 3579 // If vimrc has "simalt ~x" we don't want it to 3580 // interfere with the prompt here. 3581 flush_buffers(FLUSH_TYPEAHEAD); 3582 3583 if (swap_exists_action != SEA_NONE) { 3584 kv_printf(msg, _("Swap file \"")); 3585 kv_printf(msg, "%s", fhname); 3586 kv_printf(msg, _("\" already exists!")); 3587 char *run_but = _("&Open Read-Only\n&Edit anyway\n&Recover\n&Quit\n&Abort"); 3588 char *but = _("&Open Read-Only\n&Edit anyway\n&Recover\n&Delete it\n&Quit\n&Abort"); 3589 choice = (sea_choice_T)do_dialog(VIM_WARNING, _("VIM - ATTENTION"), msg.items, 3590 proc_running ? run_but : but, 1, NULL, false); 3591 3592 // compensate for missing "Delete it" button 3593 choice += proc_running && choice >= 4; 3594 // pretend screen didn't scroll, need redraw anyway 3595 msg_reset_scroll(); 3596 } else { 3597 bool need_clear = false; 3598 msg_multiline(cbuf_as_string(msg.items, msg.size), 0, false, false, &need_clear); 3599 } 3600 no_wait_return--; 3601 kv_destroy(msg); 3602 xfree(fhname); 3603 } 3604 3605 switch (choice) { 3606 case SEA_CHOICE_READONLY: // "Open Read-Only" 3607 buf->b_p_ro = true; 3608 break; 3609 case SEA_CHOICE_EDIT: // "Edit anyway" 3610 break; 3611 case SEA_CHOICE_RECOVER: // "Recover" 3612 swap_exists_action = SEA_RECOVER; 3613 break; 3614 case SEA_CHOICE_DELETE: // "Delete it" 3615 os_remove(fname); 3616 break; 3617 case SEA_CHOICE_QUIT: // "Quit" 3618 swap_exists_action = SEA_QUIT; 3619 break; 3620 case SEA_CHOICE_ABORT: // "Abort" 3621 swap_exists_action = SEA_QUIT; 3622 got_int = true; 3623 break; 3624 case SEA_CHOICE_NONE: 3625 msg_puts("\n"); 3626 if (msg_silent == 0) { 3627 // call wait_return() later 3628 need_wait_return = true; 3629 } 3630 break; 3631 } 3632 3633 // If the swapfile was deleted this `fname` can be used. 3634 if (choice != SEA_CHOICE_NONE && !os_path_exists(fname)) { 3635 break; 3636 } 3637 } 3638 } 3639 } 3640 3641 // Permute the ".swp" extension to find a unique swapfile name. 3642 // First decrement the last char: ".swo", ".swn", etc. 3643 // If that still isn't enough decrement the last but one char: ".svz" 3644 // Can happen when many Nvim instances are editing the same file (including "No Name" buffers). 3645 if (fname[n - 1] == 'a') { // ".s?a" 3646 if (fname[n - 2] == 'a') { // ".saa": tried enough, give up 3647 emsg(_("E326: Too many swap files found")); 3648 XFREE_CLEAR(fname); 3649 break; 3650 } 3651 fname[n - 2]--; // ".svz", ".suz", etc. 3652 fname[n - 1] = 'z' + 1; 3653 } 3654 fname[n - 1]--; // ".swo", ".swn", etc. 3655 } 3656 3657 if (os_isdir(dir_name)) { 3658 *found_existing_dir = true; 3659 } else if (!*found_existing_dir && **dirp == NUL) { 3660 int ret; 3661 char *failed_dir; 3662 if ((ret = os_mkdir_recurse(dir_name, 0755, &failed_dir, NULL)) != 0) { 3663 semsg(_("E303: Unable to create directory \"%s\" for swap file, " 3664 "recovery impossible: %s"), 3665 failed_dir, os_strerror(ret)); 3666 xfree(failed_dir); 3667 } 3668 } 3669 3670 xfree(dir_name); 3671 return fname; 3672 } 3673 3674 static int b0_magic_wrong(ZeroBlock *b0p) 3675 { 3676 return b0p->b0_magic_long != B0_MAGIC_LONG 3677 || b0p->b0_magic_int != B0_MAGIC_INT 3678 || b0p->b0_magic_short != (int16_t)B0_MAGIC_SHORT 3679 || b0p->b0_magic_char != B0_MAGIC_CHAR; 3680 } 3681 3682 /// Compare current file name with file name from swapfile. 3683 /// Try to use inode numbers when possible. 3684 /// Return non-zero when files are different. 3685 /// 3686 /// When comparing file names a few things have to be taken into consideration: 3687 /// - When working over a network the full path of a file depends on the host. 3688 /// We check the inode number if possible. It is not 100% reliable though, 3689 /// because the device number cannot be used over a network. 3690 /// - When a file does not exist yet (editing a new file) there is no inode 3691 /// number. 3692 /// - The file name in a swapfile may not be valid on the current host. The 3693 /// "~user" form is used whenever possible to avoid this. 3694 /// 3695 /// This is getting complicated, let's make a table: 3696 /// 3697 /// ino_c ino_s fname_c fname_s differ = 3698 /// 3699 /// both files exist -> compare inode numbers: 3700 /// != 0 != 0 X X ino_c != ino_s 3701 /// 3702 /// inode number(s) unknown, file names available -> compare file names 3703 /// == 0 X OK OK fname_c != fname_s 3704 /// X == 0 OK OK fname_c != fname_s 3705 /// 3706 /// current file doesn't exist, file for swapfile exist, file name(s) not 3707 /// available -> probably different 3708 /// == 0 != 0 FAIL X true 3709 /// == 0 != 0 X FAIL true 3710 /// 3711 /// current file exists, inode for swap unknown, file name(s) not 3712 /// available -> probably different 3713 /// != 0 == 0 FAIL X true 3714 /// != 0 == 0 X FAIL true 3715 /// 3716 /// current file doesn't exist, inode for swap unknown, one file name not 3717 /// available -> probably different 3718 /// == 0 == 0 FAIL OK true 3719 /// == 0 == 0 OK FAIL true 3720 /// 3721 /// current file doesn't exist, inode for swap unknown, both file names not 3722 /// available -> compare file names 3723 /// == 0 == 0 FAIL FAIL fname_c != fname_s 3724 /// 3725 /// Only the last 32 bits of the inode will be used. This can't be changed 3726 /// without making the block 0 incompatible with 32 bit versions. 3727 /// 3728 /// @param fname_c current file name 3729 /// @param fname_s file name from swapfile 3730 static bool fnamecmp_ino(char *fname_c, char *fname_s, long ino_block0) 3731 { 3732 uint64_t ino_c = 0; // ino of current file 3733 uint64_t ino_s; // ino of file from swapfile 3734 char buf_c[MAXPATHL]; // full path of fname_c 3735 char buf_s[MAXPATHL]; // full path of fname_s 3736 int retval_c; // flag: buf_c valid 3737 int retval_s; // flag: buf_s valid 3738 3739 FileInfo file_info; 3740 if (os_fileinfo(fname_c, &file_info)) { 3741 ino_c = os_fileinfo_inode(&file_info); 3742 } 3743 3744 // First we try to get the inode from the file name, because the inode in 3745 // the swapfile may be outdated. If that fails (e.g. this path is not 3746 // valid on this machine), use the inode from block 0. 3747 if (os_fileinfo(fname_s, &file_info)) { 3748 ino_s = os_fileinfo_inode(&file_info); 3749 } else { 3750 ino_s = (uint64_t)ino_block0; 3751 } 3752 3753 if (ino_c && ino_s) { 3754 return ino_c != ino_s; 3755 } 3756 3757 // One of the inode numbers is unknown, try a forced vim_FullName() and 3758 // compare the file names. 3759 retval_c = vim_FullName(fname_c, buf_c, MAXPATHL, true); 3760 retval_s = vim_FullName(fname_s, buf_s, MAXPATHL, true); 3761 if (retval_c == OK && retval_s == OK) { 3762 return strcmp(buf_c, buf_s) != 0; 3763 } 3764 3765 // Can't compare inodes or file names, guess that the files are different, 3766 // unless both appear not to exist at all, then compare with the file name 3767 // in the swapfile. 3768 if (ino_s == 0 && ino_c == 0 && retval_c == FAIL && retval_s == FAIL) { 3769 return strcmp(fname_c, fname_s) != 0; 3770 } 3771 return true; 3772 } 3773 3774 /// Move a long integer into a four byte character array. 3775 /// Used for machine independency in block zero. 3776 static void long_to_char(long n, char *s_in) 3777 { 3778 uint8_t *s = (uint8_t *)s_in; 3779 s[0] = (uint8_t)(n & 0xff); 3780 n = (unsigned)n >> 8; 3781 s[1] = (uint8_t)(n & 0xff); 3782 n = (unsigned)n >> 8; 3783 s[2] = (uint8_t)(n & 0xff); 3784 n = (unsigned)n >> 8; 3785 s[3] = (uint8_t)(n & 0xff); 3786 } 3787 3788 static long char_to_long(const char *s_in) 3789 { 3790 const uint8_t *s = (uint8_t *)s_in; 3791 3792 long retval = s[3]; 3793 retval <<= 8; 3794 retval |= s[2]; 3795 retval <<= 8; 3796 retval |= s[1]; 3797 retval <<= 8; 3798 retval |= s[0]; 3799 3800 return retval; 3801 } 3802 3803 /// Set the flags in the first block of the swapfile: 3804 /// - file is modified or not: buf->b_changed 3805 /// - 'fileformat' 3806 /// - 'fileencoding' 3807 void ml_setflags(buf_T *buf) 3808 { 3809 if (!buf->b_ml.ml_mfp) { 3810 return; 3811 } 3812 bhdr_T *hp = pmap_get(int64_t)(&buf->b_ml.ml_mfp->mf_hash, 0); 3813 if (hp) { 3814 ZeroBlock *b0p = hp->bh_data; 3815 b0p->b0_dirty = buf->b_changed ? B0_DIRTY : 0; 3816 b0p->b0_flags = (char)((b0p->b0_flags & ~B0_FF_MASK) | (uint8_t)(get_fileformat(buf) + 1)); 3817 add_b0_fenc(b0p, buf); 3818 hp->bh_flags |= BH_DIRTY; 3819 mf_sync(buf->b_ml.ml_mfp, MFS_ZERO); 3820 } 3821 } 3822 3823 enum { 3824 MLCS_MAXL = 800, // max no of lines in chunk 3825 MLCS_MINL = 400, // should be half of MLCS_MAXL 3826 }; 3827 3828 /// Keep information for finding byte offset of a line 3829 /// 3830 /// @param updtype may be one of: 3831 /// ML_CHNK_ADDLINE: Add len to parent chunk, possibly splitting it 3832 /// Careful: ML_CHNK_ADDLINE may cause ml_find_line() to be called. 3833 /// ML_CHNK_DELLINE: Subtract len from parent chunk, possibly deleting it 3834 /// ML_CHNK_UPDLINE: Add len to parent chunk, as a signed entity. 3835 static void ml_updatechunk(buf_T *buf, linenr_T line, int len, int updtype) 3836 { 3837 static buf_T *ml_upd_lastbuf = NULL; 3838 static linenr_T ml_upd_lastline; 3839 static linenr_T ml_upd_lastcurline; 3840 static int ml_upd_lastcurix; 3841 3842 linenr_T curline = ml_upd_lastcurline; 3843 int curix = ml_upd_lastcurix; 3844 bhdr_T *hp; 3845 3846 if (buf->b_ml.ml_usedchunks == -1 || len == 0) { 3847 return; 3848 } 3849 if (buf->b_ml.ml_chunksize == NULL) { 3850 buf->b_ml.ml_chunksize = xmalloc(sizeof(chunksize_T) * 100); 3851 buf->b_ml.ml_numchunks = 100; 3852 buf->b_ml.ml_usedchunks = 1; 3853 buf->b_ml.ml_chunksize[0].mlcs_numlines = 1; 3854 buf->b_ml.ml_chunksize[0].mlcs_totalsize = 1; 3855 } 3856 3857 if (updtype == ML_CHNK_UPDLINE && buf->b_ml.ml_line_count == 1) { 3858 // First line in empty buffer from ml_flush_line() -- reset 3859 buf->b_ml.ml_usedchunks = 1; 3860 buf->b_ml.ml_chunksize[0].mlcs_numlines = 1; 3861 buf->b_ml.ml_chunksize[0].mlcs_totalsize = buf->b_ml.ml_line_textlen; 3862 return; 3863 } 3864 3865 // Find chunk that our line belongs to, curline will be at start of the 3866 // chunk. 3867 if (buf != ml_upd_lastbuf || line != ml_upd_lastline + 1 3868 || updtype != ML_CHNK_ADDLINE) { 3869 for (curline = 1, curix = 0; 3870 curix < buf->b_ml.ml_usedchunks - 1 3871 && line >= curline + 3872 buf->b_ml.ml_chunksize[curix].mlcs_numlines; 3873 curix++) { 3874 curline += buf->b_ml.ml_chunksize[curix].mlcs_numlines; 3875 } 3876 } else if (curix < buf->b_ml.ml_usedchunks - 1 3877 && line >= curline + buf->b_ml.ml_chunksize[curix].mlcs_numlines) { 3878 // Adjust cached curix & curline 3879 curline += buf->b_ml.ml_chunksize[curix].mlcs_numlines; 3880 curix++; 3881 } 3882 chunksize_T *curchnk = buf->b_ml.ml_chunksize + curix; 3883 3884 if (updtype == ML_CHNK_DELLINE) { 3885 len = -len; 3886 } 3887 curchnk->mlcs_totalsize += len; 3888 if (updtype == ML_CHNK_ADDLINE) { 3889 int rest; 3890 DataBlock *dp; 3891 curchnk->mlcs_numlines++; 3892 3893 // May resize here so we don't have to do it in both cases below 3894 if (buf->b_ml.ml_usedchunks + 1 >= buf->b_ml.ml_numchunks) { 3895 buf->b_ml.ml_numchunks = buf->b_ml.ml_numchunks * 3 / 2; 3896 buf->b_ml.ml_chunksize = xrealloc(buf->b_ml.ml_chunksize, 3897 sizeof(chunksize_T) * (size_t)buf->b_ml.ml_numchunks); 3898 } 3899 3900 if (buf->b_ml.ml_chunksize[curix].mlcs_numlines >= MLCS_MAXL) { 3901 int end_idx; 3902 int text_end; 3903 3904 memmove(buf->b_ml.ml_chunksize + curix + 1, 3905 buf->b_ml.ml_chunksize + curix, 3906 (size_t)(buf->b_ml.ml_usedchunks - curix) * sizeof(chunksize_T)); 3907 // Compute length of first half of lines in the split chunk 3908 int size = 0; 3909 int linecnt = 0; 3910 while (curline < buf->b_ml.ml_line_count 3911 && linecnt < MLCS_MINL) { 3912 if ((hp = ml_find_line(buf, curline, ML_FIND)) == NULL) { 3913 buf->b_ml.ml_usedchunks = -1; 3914 return; 3915 } 3916 dp = hp->bh_data; 3917 int count 3918 = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1; // number of entries in block 3919 int idx = curline - buf->b_ml.ml_locked_low; 3920 curline = buf->b_ml.ml_locked_high + 1; 3921 // compute index of last line to use in this MEMLINE 3922 rest = count - idx; 3923 if (linecnt + rest > MLCS_MINL) { 3924 end_idx = idx + MLCS_MINL - linecnt - 1; 3925 linecnt = MLCS_MINL; 3926 } else { 3927 end_idx = count - 1; 3928 linecnt += rest; 3929 } 3930 if (idx == 0) { // first line in block, text at the end 3931 text_end = (int)dp->db_txt_end; 3932 } else { 3933 text_end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK); 3934 } 3935 size += text_end - (int)((dp->db_index[end_idx]) & DB_INDEX_MASK); 3936 } 3937 buf->b_ml.ml_chunksize[curix].mlcs_numlines = linecnt; 3938 buf->b_ml.ml_chunksize[curix + 1].mlcs_numlines -= linecnt; 3939 buf->b_ml.ml_chunksize[curix].mlcs_totalsize = size; 3940 buf->b_ml.ml_chunksize[curix + 1].mlcs_totalsize -= size; 3941 buf->b_ml.ml_usedchunks++; 3942 ml_upd_lastbuf = NULL; // Force recalc of curix & curline 3943 return; 3944 } else if (buf->b_ml.ml_chunksize[curix].mlcs_numlines >= MLCS_MINL 3945 && curix == buf->b_ml.ml_usedchunks - 1 3946 && buf->b_ml.ml_line_count - line <= 1) { 3947 // We are in the last chunk and it is cheap to create a new one 3948 // after this. Do it now to avoid the loop above later on 3949 curchnk = buf->b_ml.ml_chunksize + curix + 1; 3950 buf->b_ml.ml_usedchunks++; 3951 if (line == buf->b_ml.ml_line_count) { 3952 curchnk->mlcs_numlines = 0; 3953 curchnk->mlcs_totalsize = 0; 3954 } else { 3955 // Line is just prior to last, move count for last 3956 // This is the common case when loading a new file 3957 hp = ml_find_line(buf, buf->b_ml.ml_line_count, ML_FIND); 3958 if (hp == NULL) { 3959 buf->b_ml.ml_usedchunks = -1; 3960 return; 3961 } 3962 dp = hp->bh_data; 3963 if (dp->db_line_count == 1) { 3964 rest = (int)(dp->db_txt_end - dp->db_txt_start); 3965 } else { 3966 rest = (int)((dp->db_index[dp->db_line_count - 2]) & DB_INDEX_MASK) 3967 - (int)dp->db_txt_start; 3968 } 3969 curchnk->mlcs_totalsize = rest; 3970 curchnk->mlcs_numlines = 1; 3971 curchnk[-1].mlcs_totalsize -= rest; 3972 curchnk[-1].mlcs_numlines -= 1; 3973 } 3974 } 3975 } else if (updtype == ML_CHNK_DELLINE) { 3976 curchnk->mlcs_numlines--; 3977 ml_upd_lastbuf = NULL; // Force recalc of curix & curline 3978 if (curix < (buf->b_ml.ml_usedchunks - 1) 3979 && (curchnk->mlcs_numlines + curchnk[1].mlcs_numlines) 3980 <= MLCS_MINL) { 3981 curix++; 3982 curchnk = buf->b_ml.ml_chunksize + curix; 3983 } else if (curix == 0 && curchnk->mlcs_numlines <= 0) { 3984 buf->b_ml.ml_usedchunks--; 3985 memmove(buf->b_ml.ml_chunksize, buf->b_ml.ml_chunksize + 1, 3986 (size_t)buf->b_ml.ml_usedchunks * sizeof(chunksize_T)); 3987 return; 3988 } else if (curix == 0 || (curchnk->mlcs_numlines > 10 3989 && (curchnk->mlcs_numlines + 3990 curchnk[-1].mlcs_numlines) 3991 > MLCS_MINL)) { 3992 return; 3993 } 3994 3995 // Collapse chunks 3996 curchnk[-1].mlcs_numlines += curchnk->mlcs_numlines; 3997 curchnk[-1].mlcs_totalsize += curchnk->mlcs_totalsize; 3998 buf->b_ml.ml_usedchunks--; 3999 if (curix < buf->b_ml.ml_usedchunks) { 4000 memmove(buf->b_ml.ml_chunksize + curix, 4001 buf->b_ml.ml_chunksize + curix + 1, 4002 (size_t)(buf->b_ml.ml_usedchunks - curix) * sizeof(chunksize_T)); 4003 } 4004 return; 4005 } 4006 ml_upd_lastbuf = buf; 4007 ml_upd_lastline = line; 4008 ml_upd_lastcurline = curline; 4009 ml_upd_lastcurix = curix; 4010 } 4011 4012 /// Find offset for line or line with offset. 4013 /// 4014 /// @param buf buffer to use 4015 /// @param lnum if > 0, find offset of lnum, return offset 4016 /// if == 0, return line with offset *offp 4017 /// @param offp offset to use to find line, store remaining column offset 4018 /// Should be NULL when getting offset of line 4019 /// @param no_ff ignore 'fileformat' option, always use one byte for NL. 4020 /// 4021 /// @return -1 if information is not available 4022 int ml_find_line_or_offset(buf_T *buf, linenr_T lnum, int *offp, bool no_ff) 4023 { 4024 bhdr_T *hp; 4025 int text_end; 4026 int offset; 4027 int ffdos = !no_ff && (get_fileformat(buf) == EOL_DOS); 4028 int extra = 0; 4029 4030 // take care of cached line first. Only needed if the cached line is before 4031 // the requested line. Additionally cache the value for the cached line. 4032 // This is used by the extmark code which needs the byte offset of the edited 4033 // line. So when doing multiple small edits on the same line the value is 4034 // only calculated once. 4035 // 4036 // NB: caching doesn't work with 'fileformat'. This is not a problem for 4037 // bytetracking, as bytetracking ignores 'fileformat' option. But calling 4038 // line2byte() will invalidate the cache for the time being (this function 4039 // was never cached to start with anyway). 4040 bool can_cache = (lnum != 0 && !ffdos && buf->b_ml.ml_line_lnum == lnum); 4041 if (lnum == 0 || buf->b_ml.ml_line_lnum < lnum || !no_ff) { 4042 ml_flush_line(curbuf, false); 4043 } else if (can_cache && buf->b_ml.ml_line_offset > 0) { 4044 return (int)buf->b_ml.ml_line_offset; 4045 } 4046 4047 if (buf->b_ml.ml_usedchunks == -1 4048 || buf->b_ml.ml_chunksize == NULL 4049 || lnum < 0) { 4050 // memline is currently empty. Although if it is loaded, 4051 // it behaves like there is one empty line. 4052 if (no_ff && buf->b_ml.ml_mfp && (lnum == 1 || lnum == 2)) { 4053 return lnum - 1; 4054 } 4055 return -1; 4056 } 4057 4058 if (offp == NULL) { 4059 offset = 0; 4060 } else { 4061 offset = *offp; 4062 } 4063 if (lnum == 0 && offset <= 0) { 4064 return 1; // Not a "find offset" and offset 0 _must_ be in line 1 4065 } 4066 // Find the last chunk before the one containing our line. Last chunk is 4067 // special because it will never qualify. 4068 linenr_T curline = 1; 4069 int curix = 0; 4070 int size = 0; 4071 while (curix < buf->b_ml.ml_usedchunks - 1 4072 && ((lnum != 0 4073 && lnum >= curline + buf->b_ml.ml_chunksize[curix].mlcs_numlines) 4074 || (offset != 0 4075 && offset > size + 4076 buf->b_ml.ml_chunksize[curix].mlcs_totalsize 4077 + ffdos * buf->b_ml.ml_chunksize[curix].mlcs_numlines))) { 4078 curline += buf->b_ml.ml_chunksize[curix].mlcs_numlines; 4079 size += buf->b_ml.ml_chunksize[curix].mlcs_totalsize; 4080 if (offset && ffdos) { 4081 size += buf->b_ml.ml_chunksize[curix].mlcs_numlines; 4082 } 4083 curix++; 4084 } 4085 4086 while ((lnum != 0 && curline < lnum) || (offset != 0 && size < offset)) { 4087 if (curline > buf->b_ml.ml_line_count 4088 || (hp = ml_find_line(buf, curline, ML_FIND)) == NULL) { 4089 return -1; 4090 } 4091 DataBlock *dp = hp->bh_data; 4092 int count 4093 = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1; // number of entries in block 4094 int idx; 4095 int start_idx = idx = curline - buf->b_ml.ml_locked_low; 4096 if (idx == 0) { // first line in block, text at the end 4097 text_end = (int)dp->db_txt_end; 4098 } else { 4099 text_end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK); 4100 } 4101 // Compute index of last line to use in this MEMLINE 4102 if (lnum != 0) { 4103 if (curline + (count - idx) >= lnum) { 4104 idx += lnum - curline - 1; 4105 } else { 4106 idx = count - 1; 4107 } 4108 } else { 4109 extra = 0; 4110 while (true) { 4111 if (!(offset >= size 4112 + text_end - (int)((dp->db_index[idx]) & DB_INDEX_MASK) 4113 + ffdos)) { 4114 break; 4115 } 4116 if (ffdos) { 4117 size++; 4118 } 4119 if (idx == count - 1) { 4120 extra = 1; 4121 break; 4122 } 4123 idx++; 4124 } 4125 } 4126 int len = text_end - (int)((dp->db_index[idx]) & DB_INDEX_MASK); 4127 size += len; 4128 if (offset != 0 && size >= offset) { 4129 if (size + ffdos == offset) { 4130 *offp = 0; 4131 } else if (idx == start_idx) { 4132 *offp = offset - size + len; 4133 } else { 4134 *offp = offset - size + len 4135 - (text_end - (int)((dp->db_index[idx - 1]) & DB_INDEX_MASK)); 4136 } 4137 curline += idx - start_idx + extra; 4138 if (curline > buf->b_ml.ml_line_count) { 4139 return -1; // exactly one byte beyond the end 4140 } 4141 return curline; 4142 } 4143 curline = buf->b_ml.ml_locked_high + 1; 4144 } 4145 4146 if (lnum != 0) { 4147 // Count extra CR characters. 4148 if (ffdos) { 4149 size += lnum - 1; 4150 } 4151 4152 // Don't count the last line break if 'noeol' and ('bin' or 4153 // 'nofixeol'). 4154 if ((!buf->b_p_fixeol || buf->b_p_bin) && !buf->b_p_eol 4155 && lnum > buf->b_ml.ml_line_count) { 4156 size -= ffdos + 1; 4157 } 4158 } 4159 4160 if (can_cache && size > 0) { 4161 buf->b_ml.ml_line_offset = (size_t)size; 4162 } 4163 4164 return size; 4165 } 4166 4167 /// Goto byte in buffer with offset 'cnt'. 4168 void goto_byte(int cnt) 4169 { 4170 int boff = cnt; 4171 4172 ml_flush_line(curbuf, false); // cached line may be dirty 4173 setpcmark(); 4174 if (boff) { 4175 boff--; 4176 } 4177 linenr_T lnum = (linenr_T)ml_find_line_or_offset(curbuf, 0, &boff, false); 4178 if (lnum < 1) { // past the end 4179 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; 4180 curwin->w_curswant = MAXCOL; 4181 coladvance(curwin, MAXCOL); 4182 } else { 4183 curwin->w_cursor.lnum = lnum; 4184 curwin->w_cursor.col = (colnr_T)boff; 4185 curwin->w_cursor.coladd = 0; 4186 curwin->w_set_curswant = true; 4187 } 4188 check_cursor(curwin); 4189 4190 // Make sure the cursor is on the first byte of a multi-byte char. 4191 mb_adjust_cursor(); 4192 } 4193 4194 /// Increment the line pointer "lp" crossing line boundaries as necessary. 4195 /// 4196 /// @return 1 when going to the next line. 4197 /// 2 when moving forward onto a NUL at the end of the line). 4198 /// -1 when at the end of file. 4199 /// 0 otherwise. 4200 int inc(pos_T *lp) 4201 { 4202 // when searching position may be set to end of a line 4203 if (lp->col != MAXCOL) { 4204 const char *const p = ml_get_pos(lp); 4205 if (*p != NUL) { // still within line, move to next char (may be NUL) 4206 const int l = utfc_ptr2len(p); 4207 4208 lp->col += l; 4209 return ((p[l] != NUL) ? 0 : 2); 4210 } 4211 } 4212 if (lp->lnum != curbuf->b_ml.ml_line_count) { // there is a next line 4213 lp->col = 0; 4214 lp->lnum++; 4215 lp->coladd = 0; 4216 return 1; 4217 } 4218 return -1; 4219 } 4220 4221 /// Same as inc(), but skip NUL at the end of non-empty lines. 4222 int incl(pos_T *lp) 4223 { 4224 int r; 4225 4226 if ((r = inc(lp)) >= 1 && lp->col) { 4227 r = inc(lp); 4228 } 4229 return r; 4230 } 4231 4232 int dec(pos_T *lp) 4233 { 4234 lp->coladd = 0; 4235 if (lp->col == MAXCOL) { 4236 // past end of line 4237 char *p = ml_get(lp->lnum); 4238 lp->col = ml_get_len(lp->lnum); 4239 lp->col -= utf_head_off(p, p + lp->col); 4240 return 0; 4241 } 4242 4243 if (lp->col > 0) { 4244 // still within line 4245 lp->col--; 4246 char *p = ml_get(lp->lnum); 4247 lp->col -= utf_head_off(p, p + lp->col); 4248 return 0; 4249 } 4250 if (lp->lnum > 1) { 4251 // there is a prior line 4252 lp->lnum--; 4253 char *p = ml_get(lp->lnum); 4254 lp->col = ml_get_len(lp->lnum); 4255 lp->col -= utf_head_off(p, p + lp->col); 4256 return 1; 4257 } 4258 4259 // at start of file 4260 return -1; 4261 } 4262 4263 /// Same as dec(), but skip NUL at the end of non-empty lines. 4264 int decl(pos_T *lp) 4265 { 4266 int r; 4267 4268 if ((r = dec(lp)) == 1 && lp->col) { 4269 r = dec(lp); 4270 } 4271 return r; 4272 }