vim-patch:8.1.0313: information about a swap file is unavailable

Problem:    Information about a swap file is unavailable.
Solution:   Add swapinfo(). (Enzo Ferber)
00f123a565
This commit is contained in:
Justin M. Keyes 2019-04-29 19:20:22 +02:00
parent a0d723db55
commit 24b7462b3c
5 changed files with 94 additions and 4 deletions

View File

@ -2321,6 +2321,7 @@ submatch({nr} [, {list}]) String or List
specific match in ":s" or substitute()
substitute({expr}, {pat}, {sub}, {flags})
String all {pat} in {expr} replaced with {sub}
swapinfo({fname}) Dict information about swap file {fname}
synID({lnum}, {col}, {trans}) Number syntax ID at {lnum} and {col}
synIDattr({synID}, {what} [, {mode}])
String attribute {what} of syntax ID {synID}
@ -7758,6 +7759,22 @@ substitute({expr}, {pat}, {sub}, {flags}) *substitute()*
|submatch()| returns. Example: >
:echo substitute(s, '\(\x\x\)', {m -> '0x' . m[1]}, 'g')
swapinfo({fname}) swapinfo()
The result is a dictionary, which holds information about the
swapfile {fname}. The available fields are:
version VIM version
user user name
host host name
fname original file name
pid PID of the VIM process that created the swap
file
mtime last modification time in seconds
inode Optional: INODE number of the file
In case of failure an "error" item is added with the reason:
Cannot open file: file not found or in accessible
Cannot read file: cannot read first block
magic number mismatch: info in first block is invalid
synID({lnum}, {col}, {trans}) *synID()*
The result is a Number, which is the syntax ID at the position
{lnum} and {col} in the current window.

View File

@ -16423,6 +16423,13 @@ static void f_substitute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
/// "swapinfo(swap_filename)" function
static void f_swapinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
tv_dict_alloc_ret(rettv);
get_b0_dict(tv_get_string(argvars), rettv->vval.v_dict);
}
/// "synID(lnum, col, trans)" function
static void f_synID(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{

View File

@ -301,6 +301,7 @@ return {
strwidth={args=1},
submatch={args={1, 2}},
substitute={args=4},
swapinfo={args={1}},
synID={args=3},
synIDattr={args={2, 3}},
synIDtrans={args=1},

View File

@ -1457,10 +1457,41 @@ static char *make_percent_swname(const char *dir, char *name)
static bool process_still_running;
#endif
/*
* Give information about an existing swap file.
* Returns timestamp (0 when unknown).
*/
/// Return information found in swapfile "fname" in dictionary "d".
/// This is used by the swapinfo() function.
void get_b0_dict(const char *fname, dict_T *d)
{
int fd;
struct block0 b0;
if ((fd = os_open(fname, O_RDONLY, 0)) >= 0) {
if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0)) {
if (b0_magic_wrong(&b0)) {
tv_dict_add_str(d, S_LEN("error"), xstrdup("magic number mismatch"));
} else {
// We have swap information.
tv_dict_add_str(d, S_LEN("version"), xstrdup((char *)b0.b0_version));
tv_dict_add_str(d, S_LEN("user"), xstrdup((char *)b0.b0_uname));
tv_dict_add_str(d, S_LEN("host"), xstrdup((char *)b0.b0_hname));
tv_dict_add_str(d, S_LEN("fname"), xstrdup((char *)b0.b0_fname));
tv_dict_add_nr(d, S_LEN("pid"), char_to_long(b0.b0_pid));
tv_dict_add_nr(d, S_LEN("mtime"), char_to_long(b0.b0_mtime));
#ifdef CHECK_INODE
tv_dict_add_nr(d, S_LEN("inode"), char_to_long(b0.b0_ino));
#endif
}
} else {
tv_dict_add_str(d, S_LEN("error"), xstrdup("Cannot read file"));
}
close(fd);
} else {
tv_dict_add_str(d, S_LEN("error"), xstrdup("Cannot open file"));
}
}
/// Give information about an existing swap file.
/// Returns timestamp (0 when unknown).
static time_t swapfile_info(char_u *fname)
{
assert(fname != NULL);

View File

@ -61,3 +61,37 @@ func Test_missing_dir()
set directory&
call delete('Xswapdir', 'rf')
endfunc
func Test_swapinfo()
new Xswapinfo
call setline(1, ['one', 'two', 'three'])
w
let fname = trim(execute('swapname'))
call assert_match('Xswapinfo', fname)
let info = swapinfo(fname)
call assert_match('8\.', info.version)
call assert_match('\w', info.user)
call assert_equal(hostname(), info.host)
call assert_match('Xswapinfo', info.fname)
call assert_equal(getpid(), info.pid)
call assert_match('^\d*$', info.mtime)
if has_key(info, 'inode')
call assert_match('\d', info.inode)
endif
bwipe!
call delete(fname)
call delete('Xswapinfo')
let info = swapinfo('doesnotexist')
call assert_equal('Cannot open file', info.error)
call writefile(['burp'], 'Xnotaswapfile')
let info = swapinfo('Xnotaswapfile')
call assert_equal('Cannot read file', info.error)
call delete('Xnotaswapfile')
call writefile([repeat('x', 10000)], 'Xnotaswapfile')
let info = swapinfo('Xnotaswapfile')
call assert_equal('magic number mismatch', info.error)
call delete('Xnotaswapfile')
endfunc