diff options
Diffstat (limited to 'src/nvim/memline.c')
-rw-r--r-- | src/nvim/memline.c | 394 |
1 files changed, 227 insertions, 167 deletions
diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 56342942db..10a8195e7a 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -39,19 +39,31 @@ #include <fcntl.h> #include <inttypes.h> #include <stdbool.h> +#include <stdio.h> #include <string.h> +#include <time.h> +#include <uv.h> +#include "auto/config.h" +#include "klib/kvec.h" #include "nvim/ascii.h" #include "nvim/autocmd.h" #include "nvim/buffer.h" +#include "nvim/buffer_defs.h" #include "nvim/change.h" #include "nvim/cursor.h" #include "nvim/drawscreen.h" #include "nvim/eval.h" +#include "nvim/eval/typval.h" +#include "nvim/eval/typval_defs.h" +#include "nvim/ex_cmds_defs.h" #include "nvim/fileio.h" -#include "nvim/func_attr.h" #include "nvim/getchar.h" +#include "nvim/gettext.h" +#include "nvim/globals.h" +#include "nvim/highlight_defs.h" #include "nvim/input.h" +#include "nvim/macros.h" #include "nvim/main.h" #include "nvim/mark.h" #include "nvim/mbyte.h" @@ -60,19 +72,21 @@ #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/option.h" +#include "nvim/os/fs.h" #include "nvim/os/input.h" #include "nvim/os/os.h" #include "nvim/os/process.h" -#include "nvim/os_unix.h" +#include "nvim/os/time.h" #include "nvim/path.h" -#include "nvim/sha256.h" +#include "nvim/pos.h" +#include "nvim/screen.h" #include "nvim/spell.h" #include "nvim/strings.h" +#include "nvim/types.h" #include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/version.h" #include "nvim/vim.h" -#include "nvim/window.h" #ifndef UNIX // it's in os/unix_defs.h for Unix # include <time.h> @@ -83,10 +97,12 @@ typedef struct pointer_block PTR_BL; // contents of a pointer block typedef struct data_block DATA_BL; // contents of a data block typedef struct pointer_entry PTR_EN; // block/line-count pair -#define DATA_ID (('d' << 8) + 'a') // data block id -#define PTR_ID (('p' << 8) + 't') // pointer block id -#define BLOCK0_ID0 'b' // block 0 id 0 -#define BLOCK0_ID1 '0' // block 0 id 1 +enum { + DATA_ID = (('d' << 8) + 'a'), // data block id + PTR_ID = (('p' << 8) + 't'), // pointer block id + BLOCK0_ID0 = 'b', // block 0 id 0 + BLOCK0_ID1 = '0', // block 0 id 1 +}; // pointer to a block, used in a pointer block struct pointer_entry { @@ -115,7 +131,8 @@ struct data_block { unsigned db_free; // free space available unsigned db_txt_start; // byte where text starts unsigned db_txt_end; // byte just after data block - linenr_T db_line_count; // number of lines in this block + // linenr_T db_line_count; + long db_line_count; // number of lines in this block unsigned db_index[1]; // index for start of line (actually bigger) // followed by empty space up to db_txt_start // followed by the text in the lines until @@ -134,18 +151,22 @@ struct data_block { #define INDEX_SIZE (sizeof(unsigned)) // size of one db_index entry #define HEADER_SIZE (sizeof(DATA_BL) - INDEX_SIZE) // size of data block header -#define B0_FNAME_SIZE_ORG 900 // what it was in older versions -#define B0_FNAME_SIZE_NOCRYPT 898 // 2 bytes used for other things -#define B0_FNAME_SIZE_CRYPT 890 // 10 bytes used for other things -#define B0_UNAME_SIZE 40 -#define B0_HNAME_SIZE 40 +enum { + B0_FNAME_SIZE_ORG = 900, // what it was in older versions + B0_FNAME_SIZE_NOCRYPT = 898, // 2 bytes used for other things + B0_FNAME_SIZE_CRYPT = 890, // 10 bytes used for other things + B0_UNAME_SIZE = 40, + B0_HNAME_SIZE = 40, +}; // Restrict the numbers to 32 bits, otherwise most compilers will complain. // This won't detect a 64 bit machine that only swaps a byte in the top 32 // bits, but that is crazy anyway. -#define B0_MAGIC_LONG 0x30313233L -#define B0_MAGIC_INT 0x20212223L -#define B0_MAGIC_SHORT 0x10111213L -#define B0_MAGIC_CHAR 0x55 +enum { + B0_MAGIC_LONG = 0x30313233L, + B0_MAGIC_INT = 0x20212223L, + B0_MAGIC_SHORT = 0x10111213L, + B0_MAGIC_CHAR = 0x55, +}; // Block zero holds all info about the swap file. // @@ -158,19 +179,19 @@ struct data_block { // different machines. b0_magic_* is used to check the byte order and size of // variables, because the rest of the swap file is not portable. struct block0 { - char_u b0_id[2]; ///< ID for block 0: BLOCK0_ID0 and BLOCK0_ID1. - char_u b0_version[10]; // Vim version string - char_u b0_page_size[4]; // number of bytes per page - char_u b0_mtime[4]; // last modification time of file - char_u b0_ino[4]; // inode of b0_fname - char_u b0_pid[4]; // process id of creator (or 0) - char_u b0_uname[B0_UNAME_SIZE]; // name of user (uid if no name) - char_u b0_hname[B0_HNAME_SIZE]; // host name (if it has a name) - char_u b0_fname[B0_FNAME_SIZE_ORG]; // name of file being edited - long b0_magic_long; // check for byte order of long - int b0_magic_int; // check for byte order of int - short b0_magic_short; // check for byte order of short - char_u b0_magic_char; // check for last char + char_u b0_id[2]; ///< ID for block 0: BLOCK0_ID0 and BLOCK0_ID1. + char b0_version[10]; // Vim version string + char_u b0_page_size[4]; // number of bytes per page + char_u b0_mtime[4]; // last modification time of file + char_u b0_ino[4]; // inode of b0_fname + char_u b0_pid[4]; // process id of creator (or 0) + char_u b0_uname[B0_UNAME_SIZE]; // name of user (uid if no name) + char_u b0_hname[B0_HNAME_SIZE]; // host name (if it has a name) + char b0_fname[B0_FNAME_SIZE_ORG]; // name of file being edited + long b0_magic_long; // check for byte order of long + int b0_magic_int; // check for byte order of int + int16_t b0_magic_short; // check for byte order of short + char_u b0_magic_char; // check for last char }; // Note: b0_dirty and b0_flags are put at the end of the file name. For very @@ -205,10 +226,12 @@ struct block0 { static linenr_T lowest_marked = 0; // arguments for ml_find_line() -#define ML_DELETE 0x11 // delete line -#define ML_INSERT 0x12 // insert line -#define ML_FIND 0x13 // just find the line -#define ML_FLUSH 0x02 // flush locked block +enum { + ML_DELETE = 0x11, // delete line + ML_INSERT = 0x12, // insert line + ML_FIND = 0x13, // just find the line + ML_FLUSH = 0x02, // flush locked block +}; #define ML_SIMPLE(x) ((x) & 0x10) // DEL, INS or FIND // argument for ml_upd_block0() @@ -258,7 +281,6 @@ int ml_open(buf_T *buf) buf->b_ml.ml_mfp = mfp; buf->b_ml.ml_flags = ML_EMPTY; buf->b_ml.ml_line_count = 1; - curwin->w_nrwidth_line_count = 0; // fill block0 struct and write page 0 hp = mf_new(mfp, false, 1); @@ -271,15 +293,15 @@ int ml_open(buf_T *buf) b0p->b0_id[0] = BLOCK0_ID0; b0p->b0_id[1] = BLOCK0_ID1; b0p->b0_magic_long = B0_MAGIC_LONG; - b0p->b0_magic_int = (int)B0_MAGIC_INT; - b0p->b0_magic_short = (short)B0_MAGIC_SHORT; + b0p->b0_magic_int = B0_MAGIC_INT; + b0p->b0_magic_short = (int16_t)B0_MAGIC_SHORT; b0p->b0_magic_char = B0_MAGIC_CHAR; - xstrlcpy(xstpcpy((char *)b0p->b0_version, "VIM "), Version, 6); + xstrlcpy(xstpcpy(b0p->b0_version, "VIM "), Version, 6); long_to_char((long)mfp->mf_page_size, b0p->b0_page_size); if (!buf->b_spell) { b0p->b0_dirty = buf->b_changed ? B0_DIRTY : 0; - b0p->b0_flags = (uint8_t)(get_fileformat(buf) + 1); + b0p->b0_flags = (char)(get_fileformat(buf) + 1); set_b0_fname(b0p, buf); (void)os_get_username((char *)b0p->b0_uname, B0_UNAME_SIZE); b0p->b0_uname[B0_UNAME_SIZE - 1] = NUL; @@ -437,7 +459,7 @@ void ml_open_file(buf_T *buf) if (buf->b_spell) { char *fname = vim_tempname(); if (fname != NULL) { - (void)mf_open_file(mfp, (char *)fname); // consumes fname! + (void)mf_open_file(mfp, fname); // consumes fname! } buf->b_may_swap = false; return; @@ -616,9 +638,9 @@ static void set_b0_fname(ZERO_BL *b0p, buf_T *buf) // If there is no user name or it is too long, don't use "~/" int retval = os_get_username(uname, B0_UNAME_SIZE); size_t ulen = strlen(uname); - size_t flen = STRLEN(b0p->b0_fname); + size_t flen = strlen(b0p->b0_fname); if (retval == FAIL || ulen + flen > B0_FNAME_SIZE_CRYPT - 1) { - STRLCPY(b0p->b0_fname, buf->b_ffname, B0_FNAME_SIZE_CRYPT); + xstrlcpy(b0p->b0_fname, buf->b_ffname, B0_FNAME_SIZE_CRYPT); } else { memmove(b0p->b0_fname + ulen + 1, b0p->b0_fname + 1, flen); memmove(b0p->b0_fname + 1, uname, ulen); @@ -653,10 +675,10 @@ static void set_b0_fname(ZERO_BL *b0p, buf_T *buf) /// not set. static void set_b0_dir_flag(ZERO_BL *b0p, buf_T *buf) { - if (same_directory((char_u *)buf->b_ml.ml_mfp->mf_fname, (char_u *)buf->b_ffname)) { + if (same_directory(buf->b_ml.ml_mfp->mf_fname, buf->b_ffname)) { b0p->b0_flags |= B0_SAME_DIR; } else { - b0p->b0_flags &= (uint8_t) ~B0_SAME_DIR; + b0p->b0_flags = (char)(b0p->b0_flags & ~B0_SAME_DIR); } } @@ -666,8 +688,8 @@ static void add_b0_fenc(ZERO_BL *b0p, buf_T *buf) const int size = B0_FNAME_SIZE_NOCRYPT; int n = (int)strlen(buf->b_p_fenc); - if ((int)STRLEN(b0p->b0_fname) + n + 1 > size) { - b0p->b0_flags &= (uint8_t) ~B0_HAS_FENC; + if ((int)strlen(b0p->b0_fname) + n + 1 > size) { + b0p->b0_flags = (char)(b0p->b0_flags & ~B0_HAS_FENC); } else { memmove((char *)b0p->b0_fname + size - n, buf->b_p_fenc, (size_t)n); @@ -676,6 +698,23 @@ static void add_b0_fenc(ZERO_BL *b0p, buf_T *buf) } } +/// Return true if the process with number "b0p->b0_pid" is still running. +/// "swap_fname" is the name of the swap file, if it's from before a reboot then +/// the result is false; +static bool swapfile_process_running(const ZERO_BL *b0p, const char *swap_fname) +{ + FileInfo st; + double uptime; + // If the system rebooted after when the swap file was written then the + // process can't be running now. + if (os_fileinfo(swap_fname, &st) + && uv_uptime(&uptime) == 0 + && (Timestamp)st.stat.st_mtim.tv_sec < os_time() - (Timestamp)uptime) { + return false; + } + return os_proc_running((int)char_to_long(b0p->b0_pid)); +} + /// Try to recover curbuf from the .swp file. /// /// @param checkext if true, check the extension and detect whether it is a @@ -710,7 +749,7 @@ void ml_recover(bool checkext) int len = (int)strlen(fname); if (checkext && len >= 4 && STRNICMP(fname + len - 4, ".s", 2) == 0 - && vim_strchr("abcdefghijklmnopqrstuvw", TOLOWER_ASC(fname[len - 2])) != NULL + && vim_strchr("abcdefghijklmnopqrstuvw", TOLOWER_ASC((uint8_t)fname[len - 2])) != NULL && ASCII_ISALPHA(fname[len - 1])) { directly = true; fname_used = xstrdup(fname); // make a copy for mf_open() @@ -718,7 +757,7 @@ void ml_recover(bool checkext) directly = false; // count the number of matching swap files - len = recover_names((char_u *)fname, false, 0, NULL); + len = recover_names(fname, false, 0, NULL); if (len == 0) { // no swap files found semsg(_("E305: No swap file found for %s"), fname); goto theend; @@ -728,7 +767,7 @@ void ml_recover(bool checkext) i = 1; } else { // several swap files found, choose // list the names of the swap files - (void)recover_names((char_u *)fname, true, 0, NULL); + (void)recover_names(fname, true, 0, NULL); msg_putchar('\n'); msg_puts(_("Enter number of swap file to use (0 to quit): ")); i = get_number(false, NULL); @@ -737,7 +776,7 @@ void ml_recover(bool checkext) } } // get the swap file name that will be used - (void)recover_names((char_u *)fname, false, i, &fname_used); + (void)recover_names(fname, false, i, &fname_used); } if (fname_used == NULL) { goto theend; // user chose invalid number. @@ -788,7 +827,7 @@ void ml_recover(bool checkext) goto theend; } b0p = hp->bh_data; - if (STRNCMP(b0p->b0_version, "VIM 3.0", 7) == 0) { + if (strncmp(b0p->b0_version, "VIM 3.0", 7) == 0) { msg_start(); msg_outtrans_attr(mfp->mf_fname, MSG_HIST); msg_puts_attr(_(" cannot be used with this version of Vim.\n"), @@ -848,18 +887,18 @@ void ml_recover(bool checkext) // If .swp file name given directly, use name from swap file for buffer. if (directly) { expand_env((char *)b0p->b0_fname, NameBuff, MAXPATHL); - if (setfname(curbuf, (char *)NameBuff, NULL, true) == FAIL) { + if (setfname(curbuf, NameBuff, NULL, true) == FAIL) { goto theend; } } - home_replace(NULL, mfp->mf_fname, (char *)NameBuff, MAXPATHL, true); + home_replace(NULL, mfp->mf_fname, NameBuff, MAXPATHL, true); smsg(_("Using swap file \"%s\""), NameBuff); if (buf_spname(curbuf) != NULL) { - STRLCPY(NameBuff, buf_spname(curbuf), MAXPATHL); + xstrlcpy(NameBuff, buf_spname(curbuf), MAXPATHL); } else { - home_replace(NULL, curbuf->b_ffname, (char *)NameBuff, MAXPATHL, true); + home_replace(NULL, curbuf->b_ffname, NameBuff, MAXPATHL, true); } smsg(_("Original file \"%s\""), NameBuff); msg_putchar('\n'); @@ -883,8 +922,8 @@ void ml_recover(bool checkext) if (b0p->b0_flags & B0_HAS_FENC) { int fnsize = B0_FNAME_SIZE_NOCRYPT; - for (p = (char *)b0p->b0_fname + fnsize; (char_u *)p > b0p->b0_fname && p[-1] != NUL; p--) {} - b0_fenc = xstrnsave(p, (size_t)(b0p->b0_fname + fnsize - (char_u *)p)); + for (p = (char *)b0p->b0_fname + fnsize; p > b0p->b0_fname && p[-1] != NUL; p--) {} + b0_fenc = xstrnsave(p, (size_t)(b0p->b0_fname + fnsize - p)); } mf_put(mfp, hp, false, false); // release block 0 @@ -1116,7 +1155,14 @@ void ml_recover(bool checkext) } else { msg(_("Recovery completed. Buffer contents equals file contents.")); } - msg_puts(_("\nYou may want to delete the .swp file now.\n\n")); + msg_puts(_("\nYou may want to delete the .swp file now.")); + if (swapfile_process_running(b0p, fname_used)) { + // Warn there could be an active Vim on the same file, the user may + // want to kill it. + msg_puts(_("\nNote: process STILL RUNNING: ")); + msg_outnum(char_to_long(b0p->b0_pid)); + } + msg_puts("\n\n"); cmdline_row = msg_row; } redraw_curbuf_later(UPD_NOT_VALID); @@ -1155,24 +1201,24 @@ theend: /// @param list when true, list the swap file names /// @param nr when non-zero, return nr'th swap file name /// @param fname_out result when "nr" > 0 -int recover_names(char_u *fname, int list, int nr, char **fname_out) +int recover_names(char *fname, int list, int nr, char **fname_out) { int num_names; char *(names[6]); - char_u *tail; + char *tail; char *p; int file_count = 0; char **files; - char_u *fname_res = NULL; + char *fname_res = NULL; #ifdef HAVE_READLINK - char_u fname_buf[MAXPATHL]; + char fname_buf[MAXPATHL]; #endif if (fname != NULL) { #ifdef HAVE_READLINK // Expand symlink in the file name, because the swap file is created // with the actual file instead of with the symlink. - if (resolve_symlink((char *)fname, (char *)fname_buf) == OK) { + if (resolve_symlink(fname, fname_buf) == OK) { fname_res = fname_buf; } else #endif @@ -1193,7 +1239,7 @@ int recover_names(char_u *fname, int list, int nr, char **fname_out) // Isolate a directory name from *dirp and put it in dir_name (we know // it is large enough, so use 31000 for length). // Advance dirp to next directory name. - (void)copy_option_part(&dirp, (char *)dir_name, 31000, ","); + (void)copy_option_part(&dirp, dir_name, 31000, ","); if (dir_name[0] == '.' && dir_name[1] == NUL) { // check current dir if (fname == NULL) { @@ -1204,30 +1250,29 @@ int recover_names(char_u *fname, int list, int nr, char **fname_out) names[2] = xstrdup(".sw?"); num_names = 3; } else { - num_names = recov_file_names(names, (char *)fname_res, true); + num_names = recov_file_names(names, fname_res, true); } } else { // check directory dir_name if (fname == NULL) { - names[0] = concat_fnames((char *)dir_name, "*.sw?", true); + names[0] = concat_fnames(dir_name, "*.sw?", true); // For Unix names starting with a dot are special. MS-Windows // supports this too, on some file systems. - names[1] = concat_fnames((char *)dir_name, ".*.sw?", true); - names[2] = concat_fnames((char *)dir_name, ".sw?", true); + names[1] = concat_fnames(dir_name, ".*.sw?", true); + names[2] = concat_fnames(dir_name, ".sw?", true); num_names = 3; } else { - int len = (int)STRLEN(dir_name); + int len = (int)strlen(dir_name); p = dir_name + len; - if (after_pathsep((char *)dir_name, (char *)p) + if (after_pathsep(dir_name, p) && len > 1 && p[-1] == p[-2]) { // Ends with '//', Use Full path for swap name - tail = (char_u *)make_percent_swname((char *)dir_name, - (char *)fname_res); + tail = make_percent_swname(dir_name, fname_res); } else { - tail = (char_u *)path_tail((char *)fname_res); - tail = (char_u *)concat_fnames((char *)dir_name, (char *)tail, true); + tail = path_tail(fname_res); + tail = concat_fnames(dir_name, tail, true); } - num_names = recov_file_names(names, (char *)tail, false); + num_names = recov_file_names(names, tail, false); xfree(tail); } } @@ -1244,11 +1289,11 @@ int recover_names(char_u *fname, int list, int nr, char **fname_out) // not able to execute the shell). // Try finding a swap file by simply adding ".swp" to the file name. if (*dirp == NUL && file_count + num_files == 0 && fname != NULL) { - char_u *swapname = (char_u *)modname((char *)fname_res, ".swp", true); + char *swapname = modname(fname_res, ".swp", true); if (swapname != NULL) { - if (os_path_exists((char *)swapname)) { - files = xmalloc(sizeof(char_u *)); - files[0] = (char *)swapname; + if (os_path_exists(swapname)) { + files = xmalloc(sizeof(char *)); + files[0] = swapname; swapname = NULL; num_files = 1; } @@ -1262,7 +1307,7 @@ int recover_names(char_u *fname, int list, int nr, char **fname_out) for (int i = 0; i < num_files; i++) { // Do not expand wildcards, on Windows would try to expand // "%tmp%" in "%tmp%file" - if (path_full_compare((char *)p, files[i], true, false) & kEqualFiles) { + if (path_full_compare(p, files[i], true, false) & kEqualFiles) { // Remove the name from files[i]. Move further entries // down. When the array becomes empty free it here, since // FreeWild() won't be called below. @@ -1292,7 +1337,7 @@ int recover_names(char_u *fname, int list, int nr, char **fname_out) } } else { msg_puts(_(" In directory ")); - msg_home_replace((char *)dir_name); + msg_home_replace(dir_name); msg_puts(":\n"); } @@ -1303,7 +1348,7 @@ int recover_names(char_u *fname, int list, int nr, char **fname_out) msg_puts(". "); msg_puts((const char *)path_tail(files[i])); msg_putchar('\n'); - (void)swapfile_info((char_u *)files[i]); + (void)swapfile_info(files[i]); } } else { msg_puts(_(" -- none --\n")); @@ -1331,17 +1376,19 @@ char *make_percent_swname(const char *dir, const char *name) { char *d = NULL; char *f = fix_fname(name != NULL ? name : ""); - if (f != NULL) { - char *s = xstrdup(f); - for (d = s; *d != NUL; MB_PTR_ADV(d)) { - if (vim_ispathsep(*d)) { - *d = '%'; - } + if (f == NULL) { + return NULL; + } + + char *s = xstrdup(f); + for (d = s; *d != NUL; MB_PTR_ADV(d)) { + if (vim_ispathsep(*d)) { + *d = '%'; } - d = concat_fnames(dir, s, true); - xfree(s); - xfree(f); } + d = concat_fnames(dir, s, true); + xfree(s); + xfree(f); return d; } @@ -1363,7 +1410,7 @@ void get_b0_dict(const char *fname, dict_T *d) tv_dict_add_str(d, S_LEN("error"), "Magic number mismatch"); } else { // We have swap information. - tv_dict_add_str_len(d, S_LEN("version"), (char *)b0.b0_version, 10); + tv_dict_add_str_len(d, S_LEN("version"), b0.b0_version, 10); tv_dict_add_str_len(d, S_LEN("user"), (char *)b0.b0_uname, B0_UNAME_SIZE); tv_dict_add_str_len(d, S_LEN("host"), (char *)b0.b0_hname, @@ -1388,7 +1435,7 @@ void get_b0_dict(const char *fname, dict_T *d) /// Give information about an existing swap file. /// /// @return timestamp (0 when unknown). -static time_t swapfile_info(char_u *fname) +static time_t swapfile_info(char *fname) { assert(fname != NULL); int fd; @@ -1400,7 +1447,7 @@ static time_t swapfile_info(char_u *fname) // print the swap file date FileInfo file_info; - if (os_fileinfo((char *)fname, &file_info)) { + if (os_fileinfo(fname, &file_info)) { #ifdef UNIX // print name of owner of the file if (os_get_uname((uv_uid_t)file_info.stat.st_uid, uname, B0_UNAME_SIZE) == OK) { @@ -1414,15 +1461,15 @@ static time_t swapfile_info(char_u *fname) msg_puts(_(" dated: ")); #endif x = file_info.stat.st_mtim.tv_sec; - char ctime_buf[50]; - msg_puts(os_ctime_r(&x, ctime_buf, sizeof(ctime_buf))); + char ctime_buf[100]; // hopefully enough for every language + msg_puts(os_ctime_r(&x, ctime_buf, sizeof(ctime_buf), true)); } // print the original file name - fd = os_open((char *)fname, O_RDONLY, 0); + fd = os_open(fname, O_RDONLY, 0); if (fd >= 0) { if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0)) { - if (STRNCMP(b0.b0_version, "VIM 3.0", 7) == 0) { + if (strncmp(b0.b0_version, "VIM 3.0", 7) == 0) { msg_puts(_(" [from Vim version 3.0]")); } else if (ml_check_b0_id(&b0) == FAIL) { msg_puts(_(" [does not look like a Vim swap file]")); @@ -1456,7 +1503,7 @@ static time_t swapfile_info(char_u *fname) if (char_to_long(b0.b0_pid) != 0L) { msg_puts(_("\n process ID: ")); msg_outnum(char_to_long(b0.b0_pid)); - if (os_proc_running((int)char_to_long(b0.b0_pid))) { + if (swapfile_process_running(&b0, (const char *)fname)) { msg_puts(_(" (STILL RUNNING)")); process_still_running = true; } @@ -1511,14 +1558,27 @@ static bool swapfile_unchanged(char *fname) ret = false; } + // Host name must be known and must equal the current host name, otherwise + // comparing pid is meaningless. + if (*(b0.b0_hname) == NUL) { + ret = false; + } else { + char hostname[B0_HNAME_SIZE]; + os_get_hostname(hostname, B0_HNAME_SIZE); + hostname[B0_HNAME_SIZE - 1] = NUL; + b0.b0_hname[B0_HNAME_SIZE - 1] = NUL; // in case of corruption + if (STRICMP(b0.b0_hname, hostname) != 0) { + ret = false; + } + } + // process must be known and not running. - long pid = char_to_long(b0.b0_pid); - if (pid == 0L || os_proc_running((int)pid)) { + if (char_to_long(b0.b0_pid) == 0L || swapfile_process_running(&b0, fname)) { ret = false; } - // TODO(bram): Should we check if the swap file was created on the current - // system? And the current user? + // We do not check the user, it should be irrelevant for whether the swap + // file is still useful. close(fd); return ret; @@ -1543,7 +1603,7 @@ static int recov_file_names(char **names, char *path, int prepend_dot) names[num_names] = concat_fnames(path, ".sw?", false); if (num_names >= 1) { // check if we have the same name twice char *p = names[num_names - 1]; - int i = (int)STRLEN(names[num_names - 1]) - (int)STRLEN(names[num_names]); + int i = (int)strlen(names[num_names - 1]) - (int)strlen(names[num_names]); if (i > 0) { p += i; // file name has been expanded to full path } @@ -1685,10 +1745,10 @@ char *ml_get(linenr_T lnum) } /// @return pointer to position "pos". -char_u *ml_get_pos(const pos_T *pos) +char *ml_get_pos(const pos_T *pos) FUNC_ATTR_NONNULL_ALL { - return (char_u *)ml_get_buf(curbuf, pos->lnum, false) + pos->col; + return ml_get_buf(curbuf, pos->lnum, false) + pos->col; } /// @return codepoint at pos. pos must be either valid or have col set to MAXCOL! @@ -1699,7 +1759,7 @@ int gchar_pos(pos_T *pos) if (pos->col == MAXCOL) { return NUL; } - return utf_ptr2char((char *)ml_get_pos(pos)); + return utf_ptr2char(ml_get_pos(pos)); } /// @param will_change true mark the buffer dirty (chars in the line will be changed) @@ -1762,7 +1822,7 @@ errorret: DATA_BL *dp = hp->bh_data; char *ptr = (char *)dp + (dp->db_index[lnum - buf->b_ml.ml_locked_low] & DB_INDEX_MASK); - buf->b_ml.ml_line_ptr = (char_u *)ptr; + buf->b_ml.ml_line_ptr = ptr; buf->b_ml.ml_line_lnum = lnum; buf->b_ml.ml_flags &= ~ML_LINE_DIRTY; } @@ -1771,7 +1831,7 @@ errorret: ml_add_deleted_len_buf(buf, buf->b_ml.ml_line_ptr, -1); } - return (char *)buf->b_ml.ml_line_ptr; + return buf->b_ml.ml_line_ptr; } /// Check if a line that was just obtained by a call to ml_get @@ -1806,7 +1866,7 @@ int ml_append(linenr_T lnum, char *line, colnr_T len, bool newfile) if (curbuf->b_ml.ml_line_lnum != 0) { ml_flush_line(curbuf); } - return ml_append_int(curbuf, lnum, (char_u *)line, len, newfile, false); + return ml_append_int(curbuf, lnum, line, len, newfile, false); } /// Like ml_append() but for an arbitrary buffer. The buffer must already have @@ -1816,7 +1876,7 @@ int ml_append(linenr_T lnum, char *line, colnr_T len, bool newfile) /// @param line text of the new line /// @param len length of new line, including NUL, or 0 /// @param newfile flag, see above -int ml_append_buf(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, bool newfile) +int ml_append_buf(buf_T *buf, linenr_T lnum, char *line, colnr_T len, bool newfile) FUNC_ATTR_NONNULL_ARG(1) { if (buf->b_ml.ml_mfp == NULL) { @@ -1834,8 +1894,7 @@ int ml_append_buf(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, bool new /// @param len length of line, including NUL, or 0 /// @param newfile flag, see above /// @param mark mark the new line -static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, bool newfile, - int mark) +static int ml_append_int(buf_T *buf, linenr_T lnum, char *line, colnr_T len, bool newfile, int mark) { // lnum out of range if (lnum > buf->b_ml.ml_line_count || buf->b_ml.ml_mfp == NULL) { @@ -1847,7 +1906,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b } if (len == 0) { - len = (colnr_T)STRLEN(line) + 1; // space needed for the text + len = (colnr_T)strlen(line) + 1; // space needed for the text } int space_needed = len + (int)INDEX_SIZE; // space needed for text + index @@ -2135,13 +2194,13 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b buf->b_ml.ml_stack_top = stack_idx + 1; // truncate stack if (lineadd) { - --(buf->b_ml.ml_stack_top); + (buf->b_ml.ml_stack_top)--; // fix line count for rest of blocks in the stack ml_lineadd(buf, lineadd); // fix stack itself buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high += lineadd; - ++(buf->b_ml.ml_stack_top); + (buf->b_ml.ml_stack_top)++; } // We are finished, break the loop here. @@ -2244,15 +2303,15 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b void ml_add_deleted_len(char *ptr, ssize_t len) { - ml_add_deleted_len_buf(curbuf, (char_u *)ptr, len); + ml_add_deleted_len_buf(curbuf, ptr, len); } -void ml_add_deleted_len_buf(buf_T *buf, char_u *ptr, ssize_t len) +void ml_add_deleted_len_buf(buf_T *buf, char *ptr, ssize_t len) { if (inhibit_delete_count) { return; } - ssize_t maxlen = (ssize_t)STRLEN(ptr); + ssize_t maxlen = (ssize_t)strlen(ptr); if (len == -1 || len > maxlen) { len = maxlen; } @@ -2309,10 +2368,10 @@ int ml_replace_buf(buf_T *buf, linenr_T lnum, char *line, bool copy) } if (readlen && kv_size(buf->update_callbacks)) { - ml_add_deleted_len_buf(buf, (char_u *)ml_get_buf(buf, lnum, false), -1); + ml_add_deleted_len_buf(buf, ml_get_buf(buf, lnum, false), -1); } - buf->b_ml.ml_line_ptr = (char_u *)line; + buf->b_ml.ml_line_ptr = line; buf->b_ml.ml_line_lnum = lnum; buf->b_ml.ml_flags = (buf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY; @@ -2386,7 +2445,7 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message) // Line should always have an NL char internally (represented as NUL), // even if 'noeol' is set. assert(line_size >= 1); - ml_add_deleted_len_buf(buf, (char_u *)dp + line_start, line_size - 1); + ml_add_deleted_len_buf(buf, (char *)dp + line_start, line_size - 1); // special case: If there is only one line in the data block it becomes empty. // Then we have to remove the entry, pointing to this data block, from the @@ -2428,7 +2487,7 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message) buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high += buf->b_ml.ml_locked_lineadd; } - ++(buf->b_ml.ml_stack_top); + (buf->b_ml.ml_stack_top)++; break; } @@ -2574,7 +2633,7 @@ static void ml_flush_line(buf_T *buf) buf->flush_count++; linenr_T lnum = buf->b_ml.ml_line_lnum; - char_u *new_line = buf->b_ml.ml_line_ptr; + char *new_line = buf->b_ml.ml_line_ptr; bhdr_T *hp = ml_find_line(buf, lnum, ML_FIND); if (hp == NULL) { @@ -2583,14 +2642,14 @@ static void ml_flush_line(buf_T *buf) DATA_BL *dp = hp->bh_data; int idx = lnum - buf->b_ml.ml_locked_low; int start = ((dp->db_index[idx]) & DB_INDEX_MASK); - char_u *old_line = (char_u *)dp + start; + char *old_line = (char *)dp + start; int old_len; if (idx == 0) { // line is last in block old_len = (int)dp->db_txt_end - start; } else { // text of previous line follows old_len = (int)(dp->db_index[idx - 1] & DB_INDEX_MASK) - start; } - colnr_T new_len = (colnr_T)STRLEN(new_line) + 1; + colnr_T new_len = (colnr_T)strlen(new_line) + 1; int extra = new_len - old_len; // negative if lines gets smaller // if new line fits in data block, replace directly @@ -2698,11 +2757,11 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action) && buf->b_ml.ml_locked_high >= lnum) { // remember to update pointer blocks and stack later if (action == ML_INSERT) { - ++(buf->b_ml.ml_locked_lineadd); - ++(buf->b_ml.ml_locked_high); + (buf->b_ml.ml_locked_lineadd)++; + (buf->b_ml.ml_locked_high)++; } else if (action == ML_DELETE) { - --(buf->b_ml.ml_locked_lineadd); - --(buf->b_ml.ml_locked_high); + (buf->b_ml.ml_locked_lineadd)--; + (buf->b_ml.ml_locked_high)--; } return buf->b_ml.ml_locked; } @@ -2908,7 +2967,7 @@ int resolve_symlink(const char *fname, char *buf) } // Put the result so far in tmp[], starting with the original name. - STRLCPY(tmp, fname, MAXPATHL); + xstrlcpy(tmp, fname, MAXPATHL); for (;;) { // Limit symlink depth to 100, catch recursive loops. @@ -2940,11 +2999,11 @@ int resolve_symlink(const char *fname, char *buf) // If it's relative, build a new path based on the directory // portion of the filename (if any) and the path the symlink // points to. - if (path_is_absolute((char_u *)buf)) { + if (path_is_absolute(buf)) { STRCPY(tmp, buf); } else { - char_u *tail = (char_u *)path_tail(tmp); - if (STRLEN(tail) + strlen(buf) >= MAXPATHL) { + char *tail = path_tail(tmp); + if (strlen(tail) + strlen(buf) >= MAXPATHL) { return FAIL; } STRCPY(tail, buf); @@ -2961,41 +3020,41 @@ int resolve_symlink(const char *fname, char *buf) /// Make swap file name out of the file name and a directory name. /// /// @return pointer to allocated memory or NULL. -char_u *makeswapname(char_u *fname, char_u *ffname, buf_T *buf, char_u *dir_name) +char *makeswapname(char *fname, char *ffname, buf_T *buf, char *dir_name) { - char_u *fname_res = fname; + char *fname_res = fname; #ifdef HAVE_READLINK - char_u fname_buf[MAXPATHL]; + char fname_buf[MAXPATHL]; // Expand symlink in the file name, so that we put the swap file with the // actual file instead of with the symlink. - if (resolve_symlink((char *)fname, (char *)fname_buf) == OK) { + if (resolve_symlink(fname, (char *)fname_buf) == OK) { fname_res = fname_buf; } #endif - int len = (int)STRLEN(dir_name); + int len = (int)strlen(dir_name); - char_u *s = dir_name + len; - if (after_pathsep((char *)dir_name, (char *)s) + char *s = dir_name + len; + if (after_pathsep(dir_name, s) && len > 1 && s[-1] == s[-2]) { // Ends with '//', Use Full path - char_u *r = NULL; - s = (char_u *)make_percent_swname((char *)dir_name, (char *)fname_res); + char *r = NULL; + s = make_percent_swname(dir_name, fname_res); if (s != NULL) { - r = (char_u *)modname((char *)s, ".swp", false); + r = modname(s, ".swp", false); xfree(s); } return r; } // Prepend a '.' to the swap file name for the current directory. - char_u *r = (char_u *)modname((char *)fname_res, ".swp", - dir_name[0] == '.' && dir_name[1] == NUL); + char *r = modname(fname_res, ".swp", + dir_name[0] == '.' && dir_name[1] == NUL); if (r == NULL) { // out of memory return NULL; } - s = (char_u *)get_file_in_dir((char *)r, (char *)dir_name); + s = get_file_in_dir(r, dir_name); xfree(r); return s; } @@ -3042,14 +3101,14 @@ char *get_file_in_dir(char *fname, char *dname) /// /// @param buf buffer being edited /// @param fname swap file name -static void attention_message(buf_T *buf, char_u *fname) +static void attention_message(buf_T *buf, char *fname) { assert(buf->b_fname != NULL); no_wait_return++; (void)emsg(_("E325: ATTENTION")); msg_puts(_("\nFound a swap file by the name \"")); - msg_home_replace((char *)fname); + msg_home_replace(fname); msg_puts("\"\n"); const time_t swap_mtime = swapfile_info(fname); msg_puts(_("While opening file \"")); @@ -3062,7 +3121,7 @@ static void attention_message(buf_T *buf, char_u *fname) msg_puts(_(" dated: ")); time_t x = file_info.stat.st_mtim.tv_sec; char ctime_buf[50]; - msg_puts(os_ctime_r(&x, ctime_buf, sizeof(ctime_buf))); + msg_puts(os_ctime_r(&x, ctime_buf, sizeof(ctime_buf), true)); if (swap_mtime != 0 && x > swap_mtime) { msg_puts(_(" NEWER than swap file!\n")); } @@ -3078,7 +3137,7 @@ static void attention_message(buf_T *buf, char_u *fname) msg_outtrans(buf->b_fname); msg_puts(_("\"\n to recover the changes (see \":help recovery\").\n")); msg_puts(_(" If you did this already, delete the swap file \"")); - msg_outtrans((char *)fname); + msg_outtrans(fname); msg_puts(_("\"\n to avoid this message.\n")); cmdline_row = msg_row; no_wait_return--; @@ -3094,9 +3153,9 @@ static void attention_message(buf_T *buf, char_u *fname) /// 4: delete it /// 5: quit /// 6: abort -static int do_swapexists(buf_T *buf, char_u *fname) +static int do_swapexists(buf_T *buf, char *fname) { - set_vim_var_string(VV_SWAPNAME, (char *)fname, -1); + set_vim_var_string(VV_SWAPNAME, fname, -1); set_vim_var_string(VV_SWAPCHOICE, NULL, -1); // Trigger SwapExists autocommands with <afile> set to the file being @@ -3161,8 +3220,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ (void)copy_option_part(dirp, dir_name, dir_len, ","); // we try different names until we find one that does not exist yet - char *fname = (char *)makeswapname((char_u *)buf_fname, (char_u *)buf->b_ffname, buf, - (char_u *)dir_name); + char *fname = makeswapname(buf_fname, buf->b_ffname, buf, dir_name); for (;;) { if (fname == NULL) { // must be out of memory @@ -3209,7 +3267,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ if (b0.b0_flags & B0_SAME_DIR) { if (path_fnamecmp(path_tail(buf->b_ffname), path_tail((char *)b0.b0_fname)) != 0 - || !same_directory((char_u *)fname, (char_u *)buf->b_ffname)) { + || !same_directory(fname, buf->b_ffname)) { // Symlinks may point to the same file even // when the name differs, need to check the // inode too. @@ -3254,12 +3312,12 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ if (choice == 0 && swap_exists_action != SEA_NONE && has_autocmd(EVENT_SWAPEXISTS, buf_fname, buf)) { - choice = do_swapexists(buf, (char_u *)fname); + choice = do_swapexists(buf, fname); } if (choice == 0) { // Show info about the existing swap file. - attention_message(buf, (char_u *)fname); + attention_message(buf, fname); // We don't want a 'q' typed at the more-prompt // interrupt loading a file. @@ -3375,8 +3433,8 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ static int b0_magic_wrong(ZERO_BL *b0p) { return b0p->b0_magic_long != B0_MAGIC_LONG - || b0p->b0_magic_int != (int)B0_MAGIC_INT - || b0p->b0_magic_short != (short)B0_MAGIC_SHORT + || b0p->b0_magic_int != B0_MAGIC_INT + || b0p->b0_magic_short != (int16_t)B0_MAGIC_SHORT || b0p->b0_magic_char != B0_MAGIC_CHAR; } @@ -3485,7 +3543,7 @@ static void long_to_char(long n, char_u *s) s[3] = (char_u)(n & 0xff); } -static long char_to_long(char_u *s) +static long char_to_long(const char_u *s) { long retval; @@ -3516,7 +3574,7 @@ void ml_setflags(buf_T *buf) if (hp->bh_bnum == 0) { b0p = hp->bh_data; b0p->b0_dirty = buf->b_changed ? B0_DIRTY : 0; - b0p->b0_flags = (uint8_t)((b0p->b0_flags & ~B0_FF_MASK) | (uint8_t)(get_fileformat(buf) + 1)); + b0p->b0_flags = (char)((b0p->b0_flags & ~B0_FF_MASK) | (uint8_t)(get_fileformat(buf) + 1)); add_b0_fenc(b0p, buf); hp->bh_flags |= BH_DIRTY; mf_sync(buf->b_ml.ml_mfp, MFS_ZERO); @@ -3525,8 +3583,10 @@ void ml_setflags(buf_T *buf) } } -#define MLCS_MAXL 800 // max no of lines in chunk -#define MLCS_MINL 400 // should be half of MLCS_MAXL +enum { + MLCS_MAXL = 800, // max no of lines in chunk + MLCS_MINL = 400, // should be half of MLCS_MAXL +}; /// Keep information for finding byte offset of a line /// @@ -3566,7 +3626,7 @@ static void ml_updatechunk(buf_T *buf, linenr_T line, long len, int updtype) buf->b_ml.ml_usedchunks = 1; buf->b_ml.ml_chunksize[0].mlcs_numlines = 1; buf->b_ml.ml_chunksize[0].mlcs_totalsize = - (long)STRLEN(buf->b_ml.ml_line_ptr) + 1; + (long)strlen(buf->b_ml.ml_line_ptr) + 1; return; } @@ -3906,7 +3966,7 @@ int inc(pos_T *lp) { // when searching position may be set to end of a line if (lp->col != MAXCOL) { - const char_u *const p = ml_get_pos(lp); + const char *const p = ml_get_pos(lp); if (*p != NUL) { // still within line, move to next char (may be NUL) const int l = utfc_ptr2len((char *)p); |