]> granicus.if.org Git - vim/commitdiff
patch 8.1.0313: information about a swap file is unavailable v8.1.0313
authorBram Moolenaar <Bram@vim.org>
Tue, 21 Aug 2018 18:28:54 +0000 (20:28 +0200)
committerBram Moolenaar <Bram@vim.org>
Tue, 21 Aug 2018 18:28:54 +0000 (20:28 +0200)
Problem:    Information about a swap file is unavailable.
Solution:   Add swapinfo(). (Enzo Ferber)

runtime/doc/eval.txt
src/evalfunc.c
src/memline.c
src/proto/memline.pro
src/testdir/test_swap.vim
src/version.c

index 821cbbca9ba547d9a5caf3277e7c73f98b70fbcd..a9d0dc0151e9f72ee67068fbda8b015f359d31d3 100644 (file)
@@ -2409,6 +2409,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}
@@ -8001,6 +8002,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.
index 5e7c013979e7a0ee4b34cd8de20efd3a714cf946..3c6421206102a474582b3f0f3688c5a0bbeea2ab 100644 (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_submatch(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_synIDattr(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},
     {"submatch",       1, 2, f_submatch},
     {"substitute",     4, 4, f_substitute},
+    {"swapinfo",       1, 1, f_swapinfo},
     {"synID",          3, 3, f_synID},
     {"synIDattr",      2, 3, f_synIDattr},
     {"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);
 }
 
+/*
+ * "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
  */
index fbdd8a372c0fe24319fbf2689116cb7ec994484d..660e89c111d95acc4dbfbab18d0cc6d72cc77d3f 100644 (file)
@@ -2041,6 +2041,49 @@ make_percent_swname(char_u *dir, char_u *name)
 static int process_still_running;
 #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.
  * Returns timestamp (0 when unknown).
index 727b24cc3077251d5771b461a65e16d2fa435c2d..d18ede37b65b19e8dfdd48d351c1b79dfe8ad683 100644 (file)
@@ -11,6 +11,8 @@ void ml_close_notmod(void);
 void ml_timestamp(buf_T *buf);
 void ml_recover(void);
 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_preserve(buf_T *buf, int message);
 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);
 long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp);
 void goto_byte(long cnt);
-char_u *make_percent_swname (char_u *dir, char_u *name);
 /* vim: set ft=c : */
index da5da2dbbdeddc8dd9dfb8f5ea67273271126715..b0e2ec9aa584dd3429450cfd5de38680a2c54645 100644 (file)
@@ -97,3 +97,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
index d752d04ff48f606665a9cb2f315053cfafcfd382..d0052fa3318cf095d67add39f025d475bef49a37 100644 (file)
@@ -794,6 +794,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    313,
 /**/
     312,
 /**/