0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 8.1.0313: information about a swap file is unavailable

Problem:    Information about a swap file is unavailable.
Solution:   Add swapinfo(). (Enzo Ferber)
This commit is contained in:
Bram Moolenaar 2018-08-21 20:28:54 +02:00
parent 8e82c057ff
commit 00f123a565
6 changed files with 110 additions and 1 deletions

View File

@ -2409,6 +2409,7 @@ submatch({nr} [, {list}]) String or List
specific match in ":s" or substitute() specific match in ":s" or substitute()
substitute({expr}, {pat}, {sub}, {flags}) substitute({expr}, {pat}, {sub}, {flags})
String all {pat} in {expr} replaced with {sub} 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} synID({lnum}, {col}, {trans}) Number syntax ID at {lnum} and {col}
synIDattr({synID}, {what} [, {mode}]) synIDattr({synID}, {what} [, {mode}])
String attribute {what} of syntax ID {synID} String attribute {what} of syntax ID {synID}
@ -8001,6 +8002,22 @@ substitute({expr}, {pat}, {sub}, {flags}) *substitute()*
|submatch()| returns. Example: > |submatch()| returns. Example: >
:echo substitute(s, '%\(\x\x\)', {m -> '0x' . m[1]}, 'g') :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()* synID({lnum}, {col}, {trans}) *synID()*
The result is a Number, which is the syntax ID at the position The result is a Number, which is the syntax ID at the position
{lnum} and {col} in the current window. {lnum} and {col} in the current window.

View File

@ -398,6 +398,7 @@ static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv);
static void f_strwidth(typval_T *argvars, typval_T *rettv); static void f_strwidth(typval_T *argvars, typval_T *rettv);
static void f_submatch(typval_T *argvars, typval_T *rettv); static void f_submatch(typval_T *argvars, typval_T *rettv);
static void f_substitute(typval_T *argvars, typval_T *rettv); static void f_substitute(typval_T *argvars, typval_T *rettv);
static void f_swapinfo(typval_T *argvars, typval_T *rettv);
static void f_synID(typval_T *argvars, typval_T *rettv); static void f_synID(typval_T *argvars, typval_T *rettv);
static void f_synIDattr(typval_T *argvars, typval_T *rettv); static void f_synIDattr(typval_T *argvars, typval_T *rettv);
static void f_synIDtrans(typval_T *argvars, typval_T *rettv); static void f_synIDtrans(typval_T *argvars, typval_T *rettv);
@ -859,6 +860,7 @@ static struct fst
{"strwidth", 1, 1, f_strwidth}, {"strwidth", 1, 1, f_strwidth},
{"submatch", 1, 2, f_submatch}, {"submatch", 1, 2, f_submatch},
{"substitute", 4, 4, f_substitute}, {"substitute", 4, 4, f_substitute},
{"swapinfo", 1, 1, f_swapinfo},
{"synID", 3, 3, f_synID}, {"synID", 3, 3, f_synID},
{"synIDattr", 2, 3, f_synIDattr}, {"synIDattr", 2, 3, f_synIDattr},
{"synIDtrans", 1, 1, f_synIDtrans}, {"synIDtrans", 1, 1, f_synIDtrans},
@ -12313,6 +12315,16 @@ f_substitute(typval_T *argvars, typval_T *rettv)
rettv->vval.v_string = do_string_sub(str, pat, sub, expr, flg); rettv->vval.v_string = do_string_sub(str, pat, sub, expr, flg);
} }
/*
* "swapinfo(swap_filename)" function
*/
static void
f_swapinfo(typval_T *argvars, typval_T *rettv)
{
if (rettv_dict_alloc(rettv) == OK)
get_b0_dict(get_tv_string(argvars), rettv->vval.v_dict);
}
/* /*
* "synID(lnum, col, trans)" function * "synID(lnum, col, trans)" function
*/ */

View File

@ -2041,6 +2041,49 @@ make_percent_swname(char_u *dir, char_u *name)
static int process_still_running; static int process_still_running;
#endif #endif
/*
* Return information found in swapfile "fname" in dictionary "d".
* This is used by the swapinfo() function.
*/
void
get_b0_dict(char_u *fname, dict_T *d)
{
int fd;
struct block0 b0;
if ((fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) >= 0)
{
if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0))
{
if (b0_magic_wrong(&b0))
{
dict_add_string(d, "error",
vim_strsave((char_u *)"magic number mismatch"));
}
else
{
/* we have swap information */
dict_add_string(d, "version", vim_strsave(b0.b0_version));
dict_add_string(d, "user", vim_strsave(b0.b0_uname));
dict_add_string(d, "host", vim_strsave(b0.b0_hname));
dict_add_string(d, "fname", vim_strsave(b0.b0_fname));
dict_add_number(d, "pid", char_to_long(b0.b0_pid));
dict_add_number(d, "mtime", char_to_long(b0.b0_mtime));
#ifdef CHECK_INODE
dict_add_number(d, "inode", char_to_long(b0.b0_ino));
#endif
}
}
else
dict_add_string(d, "error",
vim_strsave((char_u *)"Cannot read file"));
close(fd);
}
else
dict_add_string(d, "error", vim_strsave((char_u *)"Cannot open file"));
}
/* /*
* Give information about an existing swap file. * Give information about an existing swap file.
* Returns timestamp (0 when unknown). * Returns timestamp (0 when unknown).

View File

@ -11,6 +11,8 @@ void ml_close_notmod(void);
void ml_timestamp(buf_T *buf); void ml_timestamp(buf_T *buf);
void ml_recover(void); void ml_recover(void);
int recover_names(char_u *fname, int list, int nr, char_u **fname_out); int recover_names(char_u *fname, int list, int nr, char_u **fname_out);
char_u *make_percent_swname(char_u *dir, char_u *name);
void get_b0_dict(char_u *fname, dict_T *d);
void ml_sync_all(int check_file, int check_char); void ml_sync_all(int check_file, int check_char);
void ml_preserve(buf_T *buf, int message); void ml_preserve(buf_T *buf, int message);
char_u *ml_get(linenr_T lnum); char_u *ml_get(linenr_T lnum);
@ -34,5 +36,4 @@ char_u *ml_encrypt_data(memfile_T *mfp, char_u *data, off_T offset, unsigned siz
void ml_decrypt_data(memfile_T *mfp, char_u *data, off_T offset, unsigned size); void ml_decrypt_data(memfile_T *mfp, char_u *data, off_T offset, unsigned size);
long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp); long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp);
void goto_byte(long cnt); void goto_byte(long cnt);
char_u *make_percent_swname (char_u *dir, char_u *name);
/* vim: set ft=c : */ /* vim: set ft=c : */

View File

@ -97,3 +97,37 @@ func Test_missing_dir()
set directory& set directory&
call delete('Xswapdir', 'rf') call delete('Xswapdir', 'rf')
endfunc 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

View File

@ -794,6 +794,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
313,
/**/ /**/
312, 312,
/**/ /**/