Skip to content

Commit 00f123a

Browse files
committed
patch 8.1.0313: information about a swap file is unavailable
Problem: Information about a swap file is unavailable. Solution: Add swapinfo(). (Enzo Ferber)
1 parent 8e82c05 commit 00f123a

6 files changed

Lines changed: 110 additions & 1 deletion

File tree

runtime/doc/eval.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2409,6 +2409,7 @@ submatch({nr} [, {list}]) String or List
24092409
specific match in ":s" or substitute()
24102410
substitute({expr}, {pat}, {sub}, {flags})
24112411
String all {pat} in {expr} replaced with {sub}
2412+
swapinfo({fname}) Dict information about swap file {fname}
24122413
synID({lnum}, {col}, {trans}) Number syntax ID at {lnum} and {col}
24132414
synIDattr({synID}, {what} [, {mode}])
24142415
String attribute {what} of syntax ID {synID}
@@ -8001,6 +8002,22 @@ substitute({expr}, {pat}, {sub}, {flags}) *substitute()*
80018002
|submatch()| returns. Example: >
80028003
:echo substitute(s, '%\(\x\x\)', {m -> '0x' . m[1]}, 'g')
80038004
8005+
swapinfo({fname}) swapinfo()
8006+
The result is a dictionary, which holds information about the
8007+
swapfile {fname}. The available fields are:
8008+
version VIM version
8009+
user user name
8010+
host host name
8011+
fname original file name
8012+
pid PID of the VIM process that created the swap
8013+
file
8014+
mtime last modification time in seconds
8015+
inode Optional: INODE number of the file
8016+
In case of failure an "error" item is added with the reason:
8017+
Cannot open file: file not found or in accessible
8018+
Cannot read file: cannot read first block
8019+
magic number mismatch: info in first block is invalid
8020+
80048021
synID({lnum}, {col}, {trans}) *synID()*
80058022
The result is a Number, which is the syntax ID at the position
80068023
{lnum} and {col} in the current window.

src/evalfunc.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv);
398398
static void f_strwidth(typval_T *argvars, typval_T *rettv);
399399
static void f_submatch(typval_T *argvars, typval_T *rettv);
400400
static void f_substitute(typval_T *argvars, typval_T *rettv);
401+
static void f_swapinfo(typval_T *argvars, typval_T *rettv);
401402
static void f_synID(typval_T *argvars, typval_T *rettv);
402403
static void f_synIDattr(typval_T *argvars, typval_T *rettv);
403404
static void f_synIDtrans(typval_T *argvars, typval_T *rettv);
@@ -859,6 +860,7 @@ static struct fst
859860
{"strwidth", 1, 1, f_strwidth},
860861
{"submatch", 1, 2, f_submatch},
861862
{"substitute", 4, 4, f_substitute},
863+
{"swapinfo", 1, 1, f_swapinfo},
862864
{"synID", 3, 3, f_synID},
863865
{"synIDattr", 2, 3, f_synIDattr},
864866
{"synIDtrans", 1, 1, f_synIDtrans},
@@ -12313,6 +12315,16 @@ f_substitute(typval_T *argvars, typval_T *rettv)
1231312315
rettv->vval.v_string = do_string_sub(str, pat, sub, expr, flg);
1231412316
}
1231512317

12318+
/*
12319+
* "swapinfo(swap_filename)" function
12320+
*/
12321+
static void
12322+
f_swapinfo(typval_T *argvars, typval_T *rettv)
12323+
{
12324+
if (rettv_dict_alloc(rettv) == OK)
12325+
get_b0_dict(get_tv_string(argvars), rettv->vval.v_dict);
12326+
}
12327+
1231612328
/*
1231712329
* "synID(lnum, col, trans)" function
1231812330
*/

src/memline.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2041,6 +2041,49 @@ make_percent_swname(char_u *dir, char_u *name)
20412041
static int process_still_running;
20422042
#endif
20432043

2044+
/*
2045+
* Return information found in swapfile "fname" in dictionary "d".
2046+
* This is used by the swapinfo() function.
2047+
*/
2048+
void
2049+
get_b0_dict(char_u *fname, dict_T *d)
2050+
{
2051+
int fd;
2052+
struct block0 b0;
2053+
2054+
if ((fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) >= 0)
2055+
{
2056+
if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0))
2057+
{
2058+
if (b0_magic_wrong(&b0))
2059+
{
2060+
dict_add_string(d, "error",
2061+
vim_strsave((char_u *)"magic number mismatch"));
2062+
}
2063+
else
2064+
{
2065+
/* we have swap information */
2066+
dict_add_string(d, "version", vim_strsave(b0.b0_version));
2067+
dict_add_string(d, "user", vim_strsave(b0.b0_uname));
2068+
dict_add_string(d, "host", vim_strsave(b0.b0_hname));
2069+
dict_add_string(d, "fname", vim_strsave(b0.b0_fname));
2070+
2071+
dict_add_number(d, "pid", char_to_long(b0.b0_pid));
2072+
dict_add_number(d, "mtime", char_to_long(b0.b0_mtime));
2073+
#ifdef CHECK_INODE
2074+
dict_add_number(d, "inode", char_to_long(b0.b0_ino));
2075+
#endif
2076+
}
2077+
}
2078+
else
2079+
dict_add_string(d, "error",
2080+
vim_strsave((char_u *)"Cannot read file"));
2081+
close(fd);
2082+
}
2083+
else
2084+
dict_add_string(d, "error", vim_strsave((char_u *)"Cannot open file"));
2085+
}
2086+
20442087
/*
20452088
* Give information about an existing swap file.
20462089
* Returns timestamp (0 when unknown).

src/proto/memline.pro

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ void ml_close_notmod(void);
1111
void ml_timestamp(buf_T *buf);
1212
void ml_recover(void);
1313
int recover_names(char_u *fname, int list, int nr, char_u **fname_out);
14+
char_u *make_percent_swname(char_u *dir, char_u *name);
15+
void get_b0_dict(char_u *fname, dict_T *d);
1416
void ml_sync_all(int check_file, int check_char);
1517
void ml_preserve(buf_T *buf, int message);
1618
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
3436
void ml_decrypt_data(memfile_T *mfp, char_u *data, off_T offset, unsigned size);
3537
long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp);
3638
void goto_byte(long cnt);
37-
char_u *make_percent_swname (char_u *dir, char_u *name);
3839
/* vim: set ft=c : */

src/testdir/test_swap.vim

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,37 @@ func Test_missing_dir()
9797
set directory&
9898
call delete('Xswapdir', 'rf')
9999
endfunc
100+
101+
func Test_swapinfo()
102+
new Xswapinfo
103+
call setline(1, ['one', 'two', 'three'])
104+
w
105+
let fname = trim(execute('swapname'))
106+
call assert_match('Xswapinfo', fname)
107+
let info = swapinfo(fname)
108+
call assert_match('8\.', info.version)
109+
call assert_match('\w', info.user)
110+
call assert_equal(hostname(), info.host)
111+
call assert_match('Xswapinfo', info.fname)
112+
call assert_equal(getpid(), info.pid)
113+
call assert_match('^\d*$', info.mtime)
114+
if has_key(info, 'inode')
115+
call assert_match('\d', info.inode)
116+
endif
117+
bwipe!
118+
call delete(fname)
119+
call delete('Xswapinfo')
120+
121+
let info = swapinfo('doesnotexist')
122+
call assert_equal('Cannot open file', info.error)
123+
124+
call writefile(['burp'], 'Xnotaswapfile')
125+
let info = swapinfo('Xnotaswapfile')
126+
call assert_equal('Cannot read file', info.error)
127+
call delete('Xnotaswapfile')
128+
129+
call writefile([repeat('x', 10000)], 'Xnotaswapfile')
130+
let info = swapinfo('Xnotaswapfile')
131+
call assert_equal('magic number mismatch', info.error)
132+
call delete('Xnotaswapfile')
133+
endfunc

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,8 @@ static char *(features[]) =
794794

795795
static int included_patches[] =
796796
{ /* Add new patch number below this line */
797+
/**/
798+
313,
797799
/**/
798800
312,
799801
/**/

0 commit comments

Comments
 (0)