mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
Crypt the swapfile.
This commit is contained in:
parent
191e0a2bc7
commit
a8ffcbbf5d
@ -1332,10 +1332,12 @@ There are a few things to remember when editing binary files:
|
|||||||
Vim is able to write files encrypted, and read them back. The encrypted text
|
Vim is able to write files encrypted, and read them back. The encrypted text
|
||||||
cannot be read without the right key.
|
cannot be read without the right key.
|
||||||
|
|
||||||
Note: The swapfile and text in memory is not encrypted. A system
|
The text in the swap file and the undo file is also encrypted.
|
||||||
administrator will be able to see your text while you are editing it.
|
|
||||||
When filtering text with ":!filter" or using ":w !command" the text is not
|
Note: The text in memory is not encrypted. A system administrator may be able
|
||||||
encrypted, this may reveal it to others.
|
to see your text while you are editing it. When filtering text with
|
||||||
|
":!filter" or using ":w !command" the text is not encrypted, this may reveal
|
||||||
|
it to others. The 'viminfo' file is not encrypted.
|
||||||
|
|
||||||
WARNING: If you make a typo when entering the key and then write the file and
|
WARNING: If you make a typo when entering the key and then write the file and
|
||||||
exit, the text will be lost!
|
exit, the text will be lost!
|
||||||
|
@ -119,9 +119,9 @@ Help on help files *helphelp*
|
|||||||
*:lh* *:lhelpgrep*
|
*:lh* *:lhelpgrep*
|
||||||
:lh[elpgrep] {pattern}[@xx]
|
:lh[elpgrep] {pattern}[@xx]
|
||||||
Same as ":helpgrep", except the location list is used
|
Same as ":helpgrep", except the location list is used
|
||||||
instead of the quickfix list. If the help window is
|
instead of the quickfix list. If the help window is
|
||||||
already opened, then the location list for that window
|
already opened, then the location list for that window
|
||||||
is used. Otherwise, a new help window is opened and
|
is used. Otherwise, a new help window is opened and
|
||||||
the location list for that window is set. The
|
the location list for that window is set. The
|
||||||
location list for the current window is not changed.
|
location list for the current window is not changed.
|
||||||
|
|
||||||
@ -281,9 +281,9 @@ The first line in a help file should have the following format:
|
|||||||
|
|
||||||
*helpfile_name.txt* For Vim version 7.3 Last change: 2010 June 4
|
*helpfile_name.txt* For Vim version 7.3 Last change: 2010 June 4
|
||||||
|
|
||||||
The first field is a link to the help file name. The second field describes
|
The first field is a link to the help file name. The second field describes
|
||||||
the applicable Vim version. The last field specifies the last modification
|
the applicable Vim version. The last field specifies the last modification
|
||||||
date of the file. Each field is separated by a tab.
|
date of the file. Each field is separated by a tab.
|
||||||
|
|
||||||
At the bottom of the help file, place a Vim modeline to set the 'textwidth'
|
At the bottom of the help file, place a Vim modeline to set the 'textwidth'
|
||||||
and 'tabstop' options and the 'filetype' to 'help'. Never set a global option
|
and 'tabstop' options and the 'filetype' to 'help'. Never set a global option
|
||||||
@ -295,30 +295,30 @@ TAGS
|
|||||||
|
|
||||||
To define a help tag, place the name between asterisks (*tag-name*). The
|
To define a help tag, place the name between asterisks (*tag-name*). The
|
||||||
tag-name should be different from all the Vim help tag names and ideally
|
tag-name should be different from all the Vim help tag names and ideally
|
||||||
should begin with the name of the Vim plugin. The tag name is usually right
|
should begin with the name of the Vim plugin. The tag name is usually right
|
||||||
aligned on a line.
|
aligned on a line.
|
||||||
|
|
||||||
When referring to an existing help tag and to create a hot-link, place the
|
When referring to an existing help tag and to create a hot-link, place the
|
||||||
name between two bars (|) eg. |help-writing|.
|
name between two bars (|) eg. |help-writing|.
|
||||||
|
|
||||||
When referring to a Vim option in the help file, place the option name between
|
When referring to a Vim option in the help file, place the option name between
|
||||||
two single quotes. eg. 'statusline'
|
two single quotes, eg. 'statusline'
|
||||||
|
|
||||||
|
|
||||||
HIGHLIGHTING
|
HIGHLIGHTING
|
||||||
|
|
||||||
To define a column heading, use a tilde character at the end of the line. This
|
To define a column heading, use a tilde character at the end of the line.
|
||||||
will highlight the column heading in a different color. E.g.
|
This will highlight the column heading in a different color. E.g.
|
||||||
|
|
||||||
Column heading~
|
Column heading~
|
||||||
|
|
||||||
To separate sections in a help file, place a series of '=' characters in a
|
To separate sections in a help file, place a series of '=' characters in a
|
||||||
line starting from the first column. The section separator line is highlighted
|
line starting from the first column. The section separator line is highlighted
|
||||||
differently.
|
differently.
|
||||||
|
|
||||||
To quote a block of ex-commands verbatim, place a greater than (>) character
|
To quote a block of ex-commands verbatim, place a greater than (>) character
|
||||||
at the end of the line before the block and a less than (<) character as the
|
at the end of the line before the block and a less than (<) character as the
|
||||||
first non-blank on a line following the block. Any line starting in column 1
|
first non-blank on a line following the block. Any line starting in column 1
|
||||||
also implicitly stops the block of ex-commands before it. E.g. >
|
also implicitly stops the block of ex-commands before it. E.g. >
|
||||||
function Example_Func()
|
function Example_Func()
|
||||||
echo "Example"
|
echo "Example"
|
||||||
|
@ -188,4 +188,43 @@ will continue to get warning messages that the ".swp" file already exists.
|
|||||||
|
|
||||||
{Vi: recovers in another way and sends mail if there is something to recover}
|
{Vi: recovers in another way and sends mail if there is something to recover}
|
||||||
|
|
||||||
|
|
||||||
|
ENCRYPTION AND THE SWAP FILE *:recover-crypt*
|
||||||
|
|
||||||
|
When the text file is encrypted the swap file is encrypted as well. This
|
||||||
|
makes recovery a bit more complicated. When recovering from a swap file and
|
||||||
|
encryption has been used, you will be asked to enter one or two crypt keys.
|
||||||
|
|
||||||
|
If the text file does not exist you will only be asked to enter the crypt key
|
||||||
|
for the swap file.
|
||||||
|
|
||||||
|
If the text file does exist, it may be encrypted in a different way than the
|
||||||
|
swap file. You will be asked for the crypt key twice:
|
||||||
|
|
||||||
|
Need encryption key for "/tmp/tt" ~
|
||||||
|
Enter encryption key: ****** ~
|
||||||
|
"/tmp/tt" [crypted] 23200L, 522129C ~
|
||||||
|
Using swap file "/tmp/.tt.swp" ~
|
||||||
|
Original file "/tmp/tt" ~
|
||||||
|
Swap file is encrypted: "/tmp/.tt.swp" ~
|
||||||
|
If you entered a new crypt key but did not write the text file, ~
|
||||||
|
enter the new crypt key. ~
|
||||||
|
If you wrote the text file after changing the crypt key press enter ~
|
||||||
|
to use the same key for text file and swap file ~
|
||||||
|
Enter encryption key: ~
|
||||||
|
|
||||||
|
You can be in one of these two situations:
|
||||||
|
|
||||||
|
1. The encryption key was not changed, or after changing the key the text file
|
||||||
|
was written. You will be prompted for the crypt key twice. The second
|
||||||
|
time you can simply press Enter. That means the same key is used for the
|
||||||
|
text file and the swap file.
|
||||||
|
2. You entered a new encryption key, but did not save the text file. Vim will
|
||||||
|
then use the new key for the swap file, and the text file will still be
|
||||||
|
encrypted with the old key. At the second prompt enter the new key.
|
||||||
|
|
||||||
|
Note that after recovery the key of the swap file will be used for the text
|
||||||
|
file. Thus if you write the text file, you need to use that new key.
|
||||||
|
|
||||||
|
|
||||||
vim:tw=78:ts=8:ft=help:norl:
|
vim:tw=78:ts=8:ft=help:norl:
|
||||||
|
@ -2577,6 +2577,7 @@ $VIMRUNTIME starting.txt /*$VIMRUNTIME*
|
|||||||
:read! insert.txt /*:read!*
|
:read! insert.txt /*:read!*
|
||||||
:rec recover.txt /*:rec*
|
:rec recover.txt /*:rec*
|
||||||
:recover recover.txt /*:recover*
|
:recover recover.txt /*:recover*
|
||||||
|
:recover-crypt recover.txt /*:recover-crypt*
|
||||||
:red undo.txt /*:red*
|
:red undo.txt /*:red*
|
||||||
:redi various.txt /*:redi*
|
:redi various.txt /*:redi*
|
||||||
:redir various.txt /*:redir*
|
:redir various.txt /*:redir*
|
||||||
@ -6914,7 +6915,6 @@ os_unix.txt os_unix.txt /*os_unix.txt*
|
|||||||
os_vms.txt os_vms.txt /*os_vms.txt*
|
os_vms.txt os_vms.txt /*os_vms.txt*
|
||||||
os_win32.txt os_win32.txt /*os_win32.txt*
|
os_win32.txt os_win32.txt /*os_win32.txt*
|
||||||
other-features vi_diff.txt /*other-features*
|
other-features vi_diff.txt /*other-features*
|
||||||
ownsyntax eval.txt /*ownsyntax*
|
|
||||||
p change.txt /*p*
|
p change.txt /*p*
|
||||||
page-down intro.txt /*page-down*
|
page-down intro.txt /*page-down*
|
||||||
page-up intro.txt /*page-up*
|
page-up intro.txt /*page-up*
|
||||||
@ -8220,7 +8220,7 @@ vt100-cursor-keys term.txt /*vt100-cursor-keys*
|
|||||||
vt100-function-keys term.txt /*vt100-function-keys*
|
vt100-function-keys term.txt /*vt100-function-keys*
|
||||||
w motion.txt /*w*
|
w motion.txt /*w*
|
||||||
w32-clientserver remote.txt /*w32-clientserver*
|
w32-clientserver remote.txt /*w32-clientserver*
|
||||||
w:ownsyntax-variable eval.txt /*w:ownsyntax-variable*
|
w:current_syntax syntax.txt /*w:current_syntax*
|
||||||
w:var eval.txt /*w:var*
|
w:var eval.txt /*w:var*
|
||||||
warningmsg-variable eval.txt /*warningmsg-variable*
|
warningmsg-variable eval.txt /*warningmsg-variable*
|
||||||
white-space pattern.txt /*white-space*
|
white-space pattern.txt /*white-space*
|
||||||
|
@ -1088,18 +1088,16 @@ Vim 7.3:
|
|||||||
- using NSIS 2.46: install on Windows 7 works, but no "Edit with Vim" menu.
|
- using NSIS 2.46: install on Windows 7 works, but no "Edit with Vim" menu.
|
||||||
Use register_shell_extension()? (George Reilly, 2010 May 26)
|
Use register_shell_extension()? (George Reilly, 2010 May 26)
|
||||||
Ron's version: http://dev.ronware.org/p/vim/finfo?name=gvim.nsi
|
Ron's version: http://dev.ronware.org/p/vim/finfo?name=gvim.nsi
|
||||||
- Also crypt the swap file, each block separately. Change mf_write() and
|
- Also crypt the swap file, each block separately:
|
||||||
mf_read().
|
- When changing the password or 'cryptmethod' need to read back with the
|
||||||
- How to get b_p_key to these functions? -> Store buf_T pointer in mfp.
|
old password and write again with the new one.
|
||||||
- Generate a salt and seed for the swapfile, put it in block 0.
|
Problem: when the file is not written, key differs between text file and
|
||||||
- For each block, use password + seed + byte offset to crypt/decrypt.
|
swap file!
|
||||||
- When changing the password need to read back with the old password and
|
- Patch for :ownsyntax completion (Dominique Pelle, 2010 Jun 20)
|
||||||
write again with the new one.
|
|
||||||
- Fill the gaps in the block with random bytes, otherwise it's easy to
|
|
||||||
check for correct password by finding NUL bytes.
|
|
||||||
- Verify recovery works.
|
|
||||||
- Patch for conceal feature and 'foldcolumn'. (Dominique Pelle, 2010 Jun 10,
|
- Patch for conceal feature and 'foldcolumn'. (Dominique Pelle, 2010 Jun 10,
|
||||||
second patch)
|
second patch)
|
||||||
|
Also patch from Vince, 2010 Jun 15. And another June 16.
|
||||||
|
However: more generic patch on the way.
|
||||||
- patch for conceal feature and 'modifiable'. (Dominique Pelle, 2010 Jun 9)
|
- patch for conceal feature and 'modifiable'. (Dominique Pelle, 2010 Jun 9)
|
||||||
- undofile: keep markers where the file was written/read, so that it's easy to
|
- undofile: keep markers where the file was written/read, so that it's easy to
|
||||||
go back to a saved version of the file: ":earlier 1f" (f for file)?
|
go back to a saved version of the file: ":earlier 1f" (f for file)?
|
||||||
@ -1110,6 +1108,7 @@ Vim 7.3:
|
|||||||
dictionary: {'nr': 2, 'time': 1234, 'saved': 1}
|
dictionary: {'nr': 2, 'time': 1234, 'saved': 1}
|
||||||
- Remove support for GTK 1? Patch by James Vega, Jun 11.
|
- Remove support for GTK 1? Patch by James Vega, Jun 11.
|
||||||
Patches to include:
|
Patches to include:
|
||||||
|
- Patch for X clibboard CurrentTime, (Fries, 2010 Jun 20)
|
||||||
- Patch for Lisp support with ECL (Mikael Jansson, 2008 Oct 25)
|
- Patch for Lisp support with ECL (Mikael Jansson, 2008 Oct 25)
|
||||||
- Minor patches from Dominique Pelle, 2010 May 15
|
- Minor patches from Dominique Pelle, 2010 May 15
|
||||||
- Gvimext patch to support wide file names. (Szabolcs Horvat 2008 Sep 10)
|
- Gvimext patch to support wide file names. (Szabolcs Horvat 2008 Sep 10)
|
||||||
@ -1117,8 +1116,9 @@ Patches to include:
|
|||||||
- Patch to support clipboard for Mac terminal. (Jjgod Jiang, 2009 Aug 1)
|
- Patch to support clipboard for Mac terminal. (Jjgod Jiang, 2009 Aug 1)
|
||||||
- Patch to support :browse for more commands. (Lech Lorens, 2009 Jul 18)
|
- Patch to support :browse for more commands. (Lech Lorens, 2009 Jul 18)
|
||||||
- Patch to improve javascript indenting. (Hari Kumar G, 2010 May 22)
|
- Patch to improve javascript indenting. (Hari Kumar G, 2010 May 22)
|
||||||
|
- Patch to use return value of 'formatexpr'. (James Vega, 2010 Jun 16)
|
||||||
- Patch to make CTRL-L work better with 'ignorecase' and 'smarcase'. (Martin
|
- Patch to make CTRL-L work better with 'ignorecase' and 'smarcase'. (Martin
|
||||||
Toft, 2010 Jun 8)
|
Toft, 2010 Jun 8, Jun 16)
|
||||||
- Patch to add diff functionality to 2html.vim. (Christian Brabandt, 2009 Dec
|
- Patch to add diff functionality to 2html.vim. (Christian Brabandt, 2009 Dec
|
||||||
15)
|
15)
|
||||||
- Win32: patch for better font scaling. (George Reilly, 2009 Mar 26)
|
- Win32: patch for better font scaling. (George Reilly, 2009 Mar 26)
|
||||||
|
@ -283,6 +283,8 @@ machines. Therefore, don't rely on Vim always warning you.
|
|||||||
If you really don't want to see this message, you can add the 'A' flag to the
|
If you really don't want to see this message, you can add the 'A' flag to the
|
||||||
'shortmess' option. But it's very unusual that you need this.
|
'shortmess' option. But it's very unusual that you need this.
|
||||||
|
|
||||||
|
For remarks about encryption and the swap file, see |:recover-crypt|.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
*11.4* Further reading
|
*11.4* Further reading
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ if !exists("c_no_c99") " ISO C99
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
" Accept %: for # (C99)
|
" Accept %: for # (C99)
|
||||||
syn region cPreCondit start="^\s*\(%:\|#\)\s*\(if\|ifdef\|ifndef\|elif\)\>" skip="\\$" end="$" contains=cComment,cCommentL,cCppString,cCharacter,cCppParen,cParenError,cNumbers,cCommentError,cSpaceError
|
syn region cPreCondit start="^\s*\(%:\|#\)\s*\(if\|ifdef\|ifndef\|elif\)\>" skip="\\$" end="$" keepend contains=cComment,cCommentL,cCppString,cCharacter,cCppParen,cParenError,cNumbers,cCommentError,cSpaceError
|
||||||
syn match cPreCondit display "^\s*\(%:\|#\)\s*\(else\|endif\)\>"
|
syn match cPreCondit display "^\s*\(%:\|#\)\s*\(else\|endif\)\>"
|
||||||
if !exists("c_no_if0")
|
if !exists("c_no_if0")
|
||||||
if !exists("c_no_if0_fold")
|
if !exists("c_no_if0_fold")
|
||||||
|
@ -436,13 +436,7 @@ bf_key_init(password, salt, salt_len)
|
|||||||
key[i] = j;
|
key[i] = j;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 256; ++i)
|
mch_memmove(sbx, sbi, 4 * 4 * 256);
|
||||||
{
|
|
||||||
sbx[0][i] = sbi[0][i];
|
|
||||||
sbx[1][i] = sbi[1][i];
|
|
||||||
sbx[2][i] = sbi[2][i];
|
|
||||||
sbx[3][i] = sbi[3][i];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 18; ++i)
|
for (i = 0; i < 18; ++i)
|
||||||
{
|
{
|
||||||
@ -655,6 +649,40 @@ bf_crypt_init_keys(passwd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int save_randbyte_offset;
|
||||||
|
static int save_update_offset;
|
||||||
|
static char_u save_ofb_buffer[BF_OFB_LEN];
|
||||||
|
static UINT32_T save_pax[18];
|
||||||
|
static UINT32_T save_sbx[4][256];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save the current crypt state. Can only be used once before
|
||||||
|
* bf_crypt_restore().
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
bf_crypt_save()
|
||||||
|
{
|
||||||
|
save_randbyte_offset = randbyte_offset;
|
||||||
|
save_update_offset = update_offset;
|
||||||
|
mch_memmove(save_ofb_buffer, ofb_buffer, BF_OFB_LEN);
|
||||||
|
mch_memmove(save_pax, pax, 4 * 18);
|
||||||
|
mch_memmove(save_sbx, sbx, 4 * 4 * 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restore the current crypt state. Can only be used after
|
||||||
|
* bf_crypt_save().
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
bf_crypt_restore()
|
||||||
|
{
|
||||||
|
randbyte_offset = save_randbyte_offset;
|
||||||
|
update_offset = save_update_offset;
|
||||||
|
mch_memmove(ofb_buffer, save_ofb_buffer, BF_OFB_LEN);
|
||||||
|
mch_memmove(pax, save_pax, 4 * 18);
|
||||||
|
mch_memmove(sbx, save_sbx, 4 * 4 * 256);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Run a test to check if the encryption works as expected.
|
* Run a test to check if the encryption works as expected.
|
||||||
* Give an error and return FAIL when not.
|
* Give an error and return FAIL when not.
|
||||||
|
43
src/fileio.c
43
src/fileio.c
@ -64,7 +64,7 @@ static void check_marks_read __ARGS((void));
|
|||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_CRYPT
|
#ifdef FEAT_CRYPT
|
||||||
static int get_crypt_method __ARGS((char *ptr, int len));
|
static int get_crypt_method __ARGS((char *ptr, int len));
|
||||||
static char_u *check_for_cryptkey __ARGS((char_u *cryptkey, char_u *ptr, long *sizep, off_t *filesizep, int newfile, int *did_ask));
|
static char_u *check_for_cryptkey __ARGS((char_u *cryptkey, char_u *ptr, long *sizep, off_t *filesizep, int newfile, char_u *fname, int *did_ask));
|
||||||
#endif
|
#endif
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
static void set_file_time __ARGS((char_u *fname, time_t atime, time_t mtime));
|
static void set_file_time __ARGS((char_u *fname, time_t atime, time_t mtime));
|
||||||
@ -995,6 +995,13 @@ retry:
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
if (cryptkey != NULL)
|
||||||
|
/* Need to reset the state, but keep the key, don't want to ask for it
|
||||||
|
* again. */
|
||||||
|
crypt_pop_state();
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When retrying with another "fenc" and the first time "fileformat"
|
* When retrying with another "fenc" and the first time "fileformat"
|
||||||
* will be reset.
|
* will be reset.
|
||||||
@ -1426,7 +1433,8 @@ retry:
|
|||||||
*/
|
*/
|
||||||
if (filesize == 0)
|
if (filesize == 0)
|
||||||
cryptkey = check_for_cryptkey(cryptkey, ptr, &size,
|
cryptkey = check_for_cryptkey(cryptkey, ptr, &size,
|
||||||
&filesize, newfile, &did_ask_for_key);
|
&filesize, newfile, sfname,
|
||||||
|
&did_ask_for_key);
|
||||||
/*
|
/*
|
||||||
* Decrypt the read bytes.
|
* Decrypt the read bytes.
|
||||||
*/
|
*/
|
||||||
@ -2277,8 +2285,14 @@ failed:
|
|||||||
save_file_ff(curbuf); /* remember the current file format */
|
save_file_ff(curbuf); /* remember the current file format */
|
||||||
|
|
||||||
#ifdef FEAT_CRYPT
|
#ifdef FEAT_CRYPT
|
||||||
if (cryptkey != curbuf->b_p_key)
|
if (cryptkey != NULL)
|
||||||
free_crypt_key(cryptkey);
|
{
|
||||||
|
crypt_pop_state();
|
||||||
|
if (cryptkey != curbuf->b_p_key)
|
||||||
|
free_crypt_key(cryptkey);
|
||||||
|
/* don't set cryptkey to NULL, it's used below as a flag that
|
||||||
|
* encryption was used */
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FEAT_MBYTE
|
#ifdef FEAT_MBYTE
|
||||||
@ -2869,12 +2883,13 @@ get_crypt_method(ptr, len)
|
|||||||
* Return the (new) encryption key, NULL for no encryption.
|
* Return the (new) encryption key, NULL for no encryption.
|
||||||
*/
|
*/
|
||||||
static char_u *
|
static char_u *
|
||||||
check_for_cryptkey(cryptkey, ptr, sizep, filesizep, newfile, did_ask)
|
check_for_cryptkey(cryptkey, ptr, sizep, filesizep, newfile, fname, did_ask)
|
||||||
char_u *cryptkey; /* previous encryption key or NULL */
|
char_u *cryptkey; /* previous encryption key or NULL */
|
||||||
char_u *ptr; /* pointer to read bytes */
|
char_u *ptr; /* pointer to read bytes */
|
||||||
long *sizep; /* length of read bytes */
|
long *sizep; /* length of read bytes */
|
||||||
off_t *filesizep; /* nr of bytes used from file */
|
off_t *filesizep; /* nr of bytes used from file */
|
||||||
int newfile; /* editing a new buffer */
|
int newfile; /* editing a new buffer */
|
||||||
|
char_u *fname; /* file name to display */
|
||||||
int *did_ask; /* flag: whether already asked for key */
|
int *did_ask; /* flag: whether already asked for key */
|
||||||
{
|
{
|
||||||
int method = get_crypt_method((char *)ptr, *sizep);
|
int method = get_crypt_method((char *)ptr, *sizep);
|
||||||
@ -2882,7 +2897,6 @@ check_for_cryptkey(cryptkey, ptr, sizep, filesizep, newfile, did_ask)
|
|||||||
if (method >= 0)
|
if (method >= 0)
|
||||||
{
|
{
|
||||||
curbuf->b_p_cm = method;
|
curbuf->b_p_cm = method;
|
||||||
use_crypt_method = method;
|
|
||||||
if (method > 0)
|
if (method > 0)
|
||||||
(void)blowfish_self_test();
|
(void)blowfish_self_test();
|
||||||
if (cryptkey == NULL && !*did_ask)
|
if (cryptkey == NULL && !*did_ask)
|
||||||
@ -2895,6 +2909,8 @@ check_for_cryptkey(cryptkey, ptr, sizep, filesizep, newfile, did_ask)
|
|||||||
* option and don't free it. bf needs hash of the key saved.
|
* option and don't free it. bf needs hash of the key saved.
|
||||||
* Don't ask for the key again when first time Enter was hit.
|
* Don't ask for the key again when first time Enter was hit.
|
||||||
* Happens when retrying to detect encoding. */
|
* Happens when retrying to detect encoding. */
|
||||||
|
smsg((char_u *)_(need_key_msg), fname);
|
||||||
|
msg_scroll = TRUE;
|
||||||
cryptkey = get_crypt_key(newfile, FALSE);
|
cryptkey = get_crypt_key(newfile, FALSE);
|
||||||
*did_ask = TRUE;
|
*did_ask = TRUE;
|
||||||
|
|
||||||
@ -2913,6 +2929,8 @@ check_for_cryptkey(cryptkey, ptr, sizep, filesizep, newfile, did_ask)
|
|||||||
int seed_len = crypt_seed_len[method];
|
int seed_len = crypt_seed_len[method];
|
||||||
int salt_len = crypt_salt_len[method];
|
int salt_len = crypt_salt_len[method];
|
||||||
|
|
||||||
|
crypt_push_state();
|
||||||
|
use_crypt_method = method;
|
||||||
if (method == 0)
|
if (method == 0)
|
||||||
crypt_init_keys(cryptkey);
|
crypt_init_keys(cryptkey);
|
||||||
else
|
else
|
||||||
@ -2924,7 +2942,8 @@ check_for_cryptkey(cryptkey, ptr, sizep, filesizep, newfile, did_ask)
|
|||||||
/* Remove magic number from the text */
|
/* Remove magic number from the text */
|
||||||
*filesizep += CRYPT_MAGIC_LEN + salt_len + seed_len;
|
*filesizep += CRYPT_MAGIC_LEN + salt_len + seed_len;
|
||||||
*sizep -= CRYPT_MAGIC_LEN + salt_len + seed_len;
|
*sizep -= CRYPT_MAGIC_LEN + salt_len + seed_len;
|
||||||
mch_memmove(ptr, ptr + CRYPT_MAGIC_LEN + salt_len + seed_len, (size_t)*sizep);
|
mch_memmove(ptr, ptr + CRYPT_MAGIC_LEN + salt_len + seed_len,
|
||||||
|
(size_t)*sizep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* When starting to edit a new file which does not have encryption, clear
|
/* When starting to edit a new file which does not have encryption, clear
|
||||||
@ -2956,6 +2975,7 @@ prepare_crypt_read(fp)
|
|||||||
if (method < 0 || method != curbuf->b_p_cm)
|
if (method < 0 || method != curbuf->b_p_cm)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
|
crypt_push_state();
|
||||||
if (method == 0)
|
if (method == 0)
|
||||||
crypt_init_keys(curbuf->b_p_key);
|
crypt_init_keys(curbuf->b_p_key);
|
||||||
else
|
else
|
||||||
@ -2974,6 +2994,8 @@ prepare_crypt_read(fp)
|
|||||||
/*
|
/*
|
||||||
* Prepare for writing encrypted bytes for buffer "buf".
|
* Prepare for writing encrypted bytes for buffer "buf".
|
||||||
* Returns a pointer to an allocated header of length "*lenp".
|
* Returns a pointer to an allocated header of length "*lenp".
|
||||||
|
* When out of memory returns NULL.
|
||||||
|
* Otherwise calls crypt_push_state(), call crypt_pop_state() later.
|
||||||
*/
|
*/
|
||||||
char_u *
|
char_u *
|
||||||
prepare_crypt_write(buf, lenp)
|
prepare_crypt_write(buf, lenp)
|
||||||
@ -2990,6 +3012,7 @@ prepare_crypt_write(buf, lenp)
|
|||||||
+ CRYPT_SEED_LEN_MAX + 2);
|
+ CRYPT_SEED_LEN_MAX + 2);
|
||||||
if (header != NULL)
|
if (header != NULL)
|
||||||
{
|
{
|
||||||
|
crypt_push_state();
|
||||||
use_crypt_method = buf->b_p_cm; /* select pkzip or blowfish */
|
use_crypt_method = buf->b_p_cm; /* select pkzip or blowfish */
|
||||||
vim_strncpy(header, (char_u *)crypt_magic[use_crypt_method],
|
vim_strncpy(header, (char_u *)crypt_magic[use_crypt_method],
|
||||||
CRYPT_MAGIC_LEN);
|
CRYPT_MAGIC_LEN);
|
||||||
@ -4404,7 +4427,7 @@ restore_backup:
|
|||||||
write_info.bw_fd = fd;
|
write_info.bw_fd = fd;
|
||||||
|
|
||||||
#ifdef FEAT_CRYPT
|
#ifdef FEAT_CRYPT
|
||||||
if (*buf->b_p_key && !filtering)
|
if (*buf->b_p_key != NUL && !filtering)
|
||||||
{
|
{
|
||||||
char_u *header;
|
char_u *header;
|
||||||
int header_len;
|
int header_len;
|
||||||
@ -4674,6 +4697,10 @@ restore_backup:
|
|||||||
if (!backup_copy)
|
if (!backup_copy)
|
||||||
mch_set_acl(wfname, acl);
|
mch_set_acl(wfname, acl);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
if (wb_flags & FIO_ENCRYPTED)
|
||||||
|
crypt_pop_state();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined(FEAT_MBYTE) && defined(FEAT_EVAL)
|
#if defined(FEAT_MBYTE) && defined(FEAT_EVAL)
|
||||||
|
@ -1564,6 +1564,10 @@ EXTERN short disallow_gui INIT(= FALSE);
|
|||||||
EXTERN char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM"));
|
EXTERN char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM"));
|
||||||
EXTERN char bot_top_msg[] INIT(= N_("search hit BOTTOM, continuing at TOP"));
|
EXTERN char bot_top_msg[] INIT(= N_("search hit BOTTOM, continuing at TOP"));
|
||||||
|
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
EXTERN char need_key_msg[] INIT(= N_("Need encryption key for \"%s\""));
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Comms. with the session manager (XSMP)
|
* Comms. with the session manager (XSMP)
|
||||||
*/
|
*/
|
||||||
|
@ -595,7 +595,7 @@ main
|
|||||||
*/
|
*/
|
||||||
if (recoverymode && fname == NULL)
|
if (recoverymode && fname == NULL)
|
||||||
{
|
{
|
||||||
recover_names(NULL, TRUE, 0);
|
recover_names(NULL, TRUE, 0, NULL);
|
||||||
mch_exit(0);
|
mch_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ static void mf_ins_free __ARGS((memfile_T *, bhdr_T *));
|
|||||||
static bhdr_T *mf_rem_free __ARGS((memfile_T *));
|
static bhdr_T *mf_rem_free __ARGS((memfile_T *));
|
||||||
static int mf_read __ARGS((memfile_T *, bhdr_T *));
|
static int mf_read __ARGS((memfile_T *, bhdr_T *));
|
||||||
static int mf_write __ARGS((memfile_T *, bhdr_T *));
|
static int mf_write __ARGS((memfile_T *, bhdr_T *));
|
||||||
|
static int mf_write_block __ARGS((memfile_T *mfp, bhdr_T *hp, off_t offset, unsigned size));
|
||||||
static int mf_trans_add __ARGS((memfile_T *, bhdr_T *));
|
static int mf_trans_add __ARGS((memfile_T *, bhdr_T *));
|
||||||
static void mf_do_open __ARGS((memfile_T *, char_u *, int));
|
static void mf_do_open __ARGS((memfile_T *, char_u *, int));
|
||||||
|
|
||||||
@ -161,6 +162,9 @@ mf_open(fname, flags)
|
|||||||
mfp->mf_trans[i] = NULL; /* trans lists are empty */
|
mfp->mf_trans[i] = NULL; /* trans lists are empty */
|
||||||
}
|
}
|
||||||
mfp->mf_page_size = MEMFILE_PAGE_SIZE;
|
mfp->mf_page_size = MEMFILE_PAGE_SIZE;
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
mfp->mf_old_key = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_FSTATFS
|
#ifdef USE_FSTATFS
|
||||||
/*
|
/*
|
||||||
@ -422,7 +426,7 @@ mf_new(mfp, negative, page_count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get existing block 'nr' with 'page_count' pages
|
* Get existing block "nr" with "page_count" pages.
|
||||||
*
|
*
|
||||||
* Note: The caller should first check a negative nr with mf_trans_del()
|
* Note: The caller should first check a negative nr with mf_trans_del()
|
||||||
*/
|
*/
|
||||||
@ -1050,6 +1054,13 @@ mf_read(mfp, hp)
|
|||||||
PERROR(_("E295: Read error in swap file"));
|
PERROR(_("E295: Read error in swap file"));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
/* Decrypt if 'key' is set and this is a data block. */
|
||||||
|
if (*mfp->mf_buffer->b_p_key != NUL)
|
||||||
|
ml_decrypt_data(mfp, hp->bh_data, offset, size);
|
||||||
|
#endif
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1107,8 +1118,7 @@ mf_write(mfp, hp)
|
|||||||
else
|
else
|
||||||
page_count = hp2->bh_page_count;
|
page_count = hp2->bh_page_count;
|
||||||
size = page_size * page_count;
|
size = page_size * page_count;
|
||||||
if ((unsigned)vim_write(mfp->mf_fd,
|
if (mf_write_block(mfp, hp2 == NULL ? hp : hp2, offset, size) == FAIL)
|
||||||
(hp2 == NULL ? hp : hp2)->bh_data, size) != size)
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Avoid repeating the error message, this mostly happens when the
|
* Avoid repeating the error message, this mostly happens when the
|
||||||
@ -1133,6 +1143,42 @@ mf_write(mfp, hp)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write block "hp" with data size "size" to file "mfp->mf_fd".
|
||||||
|
* Takes care of encryption.
|
||||||
|
* Return FAIL or OK.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
mf_write_block(mfp, hp, offset, size)
|
||||||
|
memfile_T *mfp;
|
||||||
|
bhdr_T *hp;
|
||||||
|
off_t offset UNUSED;
|
||||||
|
unsigned size;
|
||||||
|
{
|
||||||
|
char_u *data = hp->bh_data;
|
||||||
|
int result = OK;
|
||||||
|
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
/* Encrypt if 'key' is set and this is a data block. */
|
||||||
|
if (*mfp->mf_buffer->b_p_key != NUL)
|
||||||
|
{
|
||||||
|
data = ml_encrypt_data(mfp, data, offset, size);
|
||||||
|
if (data == NULL)
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((unsigned)vim_write(mfp->mf_fd, data, size) != size)
|
||||||
|
result = FAIL;
|
||||||
|
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
if (data != hp->bh_data)
|
||||||
|
vim_free(data);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make block number for *hp positive and add it to the translation list
|
* Make block number for *hp positive and add it to the translation list
|
||||||
*
|
*
|
||||||
@ -1156,7 +1202,7 @@ mf_trans_add(mfp, hp)
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get a new number for the block.
|
* Get a new number for the block.
|
||||||
* If the first item in the free list has sufficient pages, use its number
|
* If the first item in the free list has sufficient pages, use its number
|
||||||
* Otherwise use mf_blocknr_max.
|
* Otherwise use mf_blocknr_max.
|
||||||
*/
|
*/
|
||||||
|
599
src/memline.c
599
src/memline.c
@ -65,10 +65,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 data_block DATA_BL; /* contents of a data block */
|
||||||
typedef struct pointer_entry PTR_EN; /* block/line-count pair */
|
typedef struct pointer_entry PTR_EN; /* block/line-count pair */
|
||||||
|
|
||||||
#define DATA_ID (('d' << 8) + 'a') /* data block id */
|
#define DATA_ID (('d' << 8) + 'a') /* data block id */
|
||||||
#define PTR_ID (('p' << 8) + 't') /* pointer block id */
|
#define PTR_ID (('p' << 8) + 't') /* pointer block id */
|
||||||
#define BLOCK0_ID0 'b' /* block 0 id 0 */
|
#define BLOCK0_ID0 'b' /* block 0 id 0 */
|
||||||
#define BLOCK0_ID1 '0' /* block 0 id 1 */
|
#define BLOCK0_ID1 '0' /* block 0 id 1 */
|
||||||
|
#define BLOCK0_ID1_C0 'c' /* block 0 id 1 'cm' 0 */
|
||||||
|
#define BLOCK0_ID1_C1 'C' /* block 0 id 1 'cm' 1 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pointer to a block, used in a pointer block
|
* pointer to a block, used in a pointer block
|
||||||
@ -128,7 +130,8 @@ struct data_block
|
|||||||
#define HEADER_SIZE (sizeof(DATA_BL) - INDEX_SIZE) /* size of data block header */
|
#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_ORG 900 /* what it was in older versions */
|
||||||
#define B0_FNAME_SIZE 898
|
#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_UNAME_SIZE 40
|
||||||
#define B0_HNAME_SIZE 40
|
#define B0_HNAME_SIZE 40
|
||||||
/*
|
/*
|
||||||
@ -155,7 +158,8 @@ struct data_block
|
|||||||
*/
|
*/
|
||||||
struct block0
|
struct block0
|
||||||
{
|
{
|
||||||
char_u b0_id[2]; /* id for block 0: BLOCK0_ID0 and BLOCK0_ID1 */
|
char_u b0_id[2]; /* id for block 0: BLOCK0_ID0 and BLOCK0_ID1,
|
||||||
|
* BLOCK0_ID1_C0, BLOCK0_ID1_C1 */
|
||||||
char_u b0_version[10]; /* Vim version string */
|
char_u b0_version[10]; /* Vim version string */
|
||||||
char_u b0_page_size[4];/* number of bytes per page */
|
char_u b0_page_size[4];/* number of bytes per page */
|
||||||
char_u b0_mtime[4]; /* last modification time of file */
|
char_u b0_mtime[4]; /* last modification time of file */
|
||||||
@ -177,12 +181,18 @@ struct block0
|
|||||||
* when there is room, for very long file names it's omitted.
|
* when there is room, for very long file names it's omitted.
|
||||||
*/
|
*/
|
||||||
#define B0_DIRTY 0x55
|
#define B0_DIRTY 0x55
|
||||||
#define b0_dirty b0_fname[B0_FNAME_SIZE_ORG-1]
|
#define b0_dirty b0_fname[B0_FNAME_SIZE_ORG - 1]
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The b0_flags field is new in Vim 7.0.
|
* The b0_flags field is new in Vim 7.0.
|
||||||
*/
|
*/
|
||||||
#define b0_flags b0_fname[B0_FNAME_SIZE_ORG-2]
|
#define b0_flags b0_fname[B0_FNAME_SIZE_ORG - 2]
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Crypt seed goes here, 8 bytes. New in Vim 7.3.
|
||||||
|
* Without encryption these bytes may be used for 'fenc'.
|
||||||
|
*/
|
||||||
|
#define b0_seed b0_fname[B0_FNAME_SIZE_ORG - 2 - MF_SEED_LEN]
|
||||||
|
|
||||||
/* The lowest two bits contain the fileformat. Zero means it's not set
|
/* The lowest two bits contain the fileformat. Zero means it's not set
|
||||||
* (compatible with Vim 6.x), otherwise it's EOL_UNIX + 1, EOL_DOS + 1 or
|
* (compatible with Vim 6.x), otherwise it's EOL_UNIX + 1, EOL_DOS + 1 or
|
||||||
@ -216,7 +226,18 @@ static linenr_T lowest_marked = 0;
|
|||||||
#define ML_FLUSH 0x02 /* flush locked block */
|
#define ML_FLUSH 0x02 /* flush locked block */
|
||||||
#define ML_SIMPLE(x) (x & 0x10) /* DEL, INS or FIND */
|
#define ML_SIMPLE(x) (x & 0x10) /* DEL, INS or FIND */
|
||||||
|
|
||||||
static void ml_upd_block0 __ARGS((buf_T *buf, int set_fname));
|
/* argument for ml_upd_block0() */
|
||||||
|
typedef enum {
|
||||||
|
UB_FNAME = 0 /* update timestamp and filename */
|
||||||
|
, UB_SAME_DIR /* update the B0_SAME_DIR flag */
|
||||||
|
, UB_CRYPT /* update crypt key */
|
||||||
|
} upd_block0_T;
|
||||||
|
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
static void ml_set_b0_crypt __ARGS((buf_T *buf, ZERO_BL *b0p));
|
||||||
|
#endif
|
||||||
|
static int ml_check_b0_id __ARGS((ZERO_BL *b0p));
|
||||||
|
static void ml_upd_block0 __ARGS((buf_T *buf, upd_block0_T what));
|
||||||
static void set_b0_fname __ARGS((ZERO_BL *, buf_T *buf));
|
static void set_b0_fname __ARGS((ZERO_BL *, buf_T *buf));
|
||||||
static void set_b0_dir_flag __ARGS((ZERO_BL *b0p, buf_T *buf));
|
static void set_b0_dir_flag __ARGS((ZERO_BL *b0p, buf_T *buf));
|
||||||
#ifdef FEAT_MBYTE
|
#ifdef FEAT_MBYTE
|
||||||
@ -242,6 +263,9 @@ static long char_to_long __ARGS((char_u *));
|
|||||||
#if defined(UNIX) || defined(WIN3264)
|
#if defined(UNIX) || defined(WIN3264)
|
||||||
static char_u *make_percent_swname __ARGS((char_u *dir, char_u *name));
|
static char_u *make_percent_swname __ARGS((char_u *dir, char_u *name));
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
static void ml_crypt_prepare __ARGS((memfile_T *mfp, off_t offset, int reading));
|
||||||
|
#endif
|
||||||
#ifdef FEAT_BYTEOFF
|
#ifdef FEAT_BYTEOFF
|
||||||
static void ml_updatechunk __ARGS((buf_T *buf, long line, long len, int updtype));
|
static void ml_updatechunk __ARGS((buf_T *buf, long line, long len, int updtype));
|
||||||
#endif
|
#endif
|
||||||
@ -264,7 +288,7 @@ ml_open(buf)
|
|||||||
/*
|
/*
|
||||||
* init fields in memline struct
|
* init fields in memline struct
|
||||||
*/
|
*/
|
||||||
buf->b_ml.ml_stack_size = 0; /* no stack yet */
|
buf->b_ml.ml_stack_size = 0; /* no stack yet */
|
||||||
buf->b_ml.ml_stack = NULL; /* no stack yet */
|
buf->b_ml.ml_stack = NULL; /* no stack yet */
|
||||||
buf->b_ml.ml_stack_top = 0; /* nothing in the stack */
|
buf->b_ml.ml_stack_top = 0; /* nothing in the stack */
|
||||||
buf->b_ml.ml_locked = NULL; /* no cached block */
|
buf->b_ml.ml_locked = NULL; /* no cached block */
|
||||||
@ -289,6 +313,9 @@ ml_open(buf)
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
buf->b_ml.ml_mfp = mfp;
|
buf->b_ml.ml_mfp = mfp;
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
mfp->mf_buffer = buf;
|
||||||
|
#endif
|
||||||
buf->b_ml.ml_flags = ML_EMPTY;
|
buf->b_ml.ml_flags = ML_EMPTY;
|
||||||
buf->b_ml.ml_line_count = 1;
|
buf->b_ml.ml_line_count = 1;
|
||||||
#ifdef FEAT_LINEBREAK
|
#ifdef FEAT_LINEBREAK
|
||||||
@ -336,12 +363,16 @@ ml_open(buf)
|
|||||||
mch_get_host_name(b0p->b0_hname, B0_HNAME_SIZE);
|
mch_get_host_name(b0p->b0_hname, B0_HNAME_SIZE);
|
||||||
b0p->b0_hname[B0_HNAME_SIZE - 1] = NUL;
|
b0p->b0_hname[B0_HNAME_SIZE - 1] = NUL;
|
||||||
long_to_char(mch_get_pid(), b0p->b0_pid);
|
long_to_char(mch_get_pid(), b0p->b0_pid);
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
if (*buf->b_p_key != NUL)
|
||||||
|
ml_set_b0_crypt(buf, b0p);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Always sync block number 0 to disk, so we can check the file name in
|
* Always sync block number 0 to disk, so we can check the file name in
|
||||||
* the swap file in findswapname(). Don't do this for help files though
|
* the swap file in findswapname(). Don't do this for a help files or
|
||||||
* and spell buffer though.
|
* a spell buffer though.
|
||||||
* Only works when there's a swapfile, otherwise it's done when the file
|
* Only works when there's a swapfile, otherwise it's done when the file
|
||||||
* is created.
|
* is created.
|
||||||
*/
|
*/
|
||||||
@ -397,6 +428,165 @@ error:
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(FEAT_CRYPT) || defined(PROTO)
|
||||||
|
/*
|
||||||
|
* Prepare encryption for "buf" with block 0 "b0p".
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ml_set_b0_crypt(buf, b0p)
|
||||||
|
buf_T *buf;
|
||||||
|
ZERO_BL *b0p;
|
||||||
|
{
|
||||||
|
if (*buf->b_p_key == NUL)
|
||||||
|
b0p->b0_id[1] = BLOCK0_ID1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (buf->b_p_cm == 0)
|
||||||
|
b0p->b0_id[1] = BLOCK0_ID1_C0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
b0p->b0_id[1] = BLOCK0_ID1_C1;
|
||||||
|
/* Generate a seed and store it in block 0 and in the memfile. */
|
||||||
|
sha2_seed(&b0p->b0_seed, MF_SEED_LEN, NULL, 0);
|
||||||
|
mch_memmove(buf->b_ml.ml_mfp->mf_seed, &b0p->b0_seed, MF_SEED_LEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called after the crypt key or 'cryptmethod' was changed for "buf".
|
||||||
|
* Will apply this to the swapfile.
|
||||||
|
* "old_key" is the previous key. It is equal to buf->b_p_key when
|
||||||
|
* 'cryptmethod' is changed.
|
||||||
|
* "old_cm" is the previous 'cryptmethod'. It is equal to buf->b_p_cm when
|
||||||
|
* 'key' is changed.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ml_set_crypt_key(buf, old_key, old_cm)
|
||||||
|
buf_T *buf;
|
||||||
|
char_u *old_key;
|
||||||
|
int old_cm;
|
||||||
|
{
|
||||||
|
memfile_T *mfp = buf->b_ml.ml_mfp;
|
||||||
|
bhdr_T *hp;
|
||||||
|
int page_count;
|
||||||
|
int idx;
|
||||||
|
long error;
|
||||||
|
infoptr_T *ip;
|
||||||
|
PTR_BL *pp;
|
||||||
|
DATA_BL *dp;
|
||||||
|
blocknr_T bnum;
|
||||||
|
int top;
|
||||||
|
|
||||||
|
if (mfp == NULL || mfp->mf_fd < 0)
|
||||||
|
return; /* no memfile yet, nothing to do */
|
||||||
|
|
||||||
|
/* Set the key, method and seed to be used for reading, these must be the
|
||||||
|
* old values. */
|
||||||
|
mfp->mf_old_key = old_key;
|
||||||
|
mfp->mf_old_cm = old_cm;
|
||||||
|
if (old_cm > 0)
|
||||||
|
mch_memmove(mfp->mf_old_seed, mfp->mf_seed, MF_SEED_LEN);
|
||||||
|
|
||||||
|
/* Update block 0 with the crypt flag and may set a new seed. */
|
||||||
|
ml_upd_block0(buf, UB_CRYPT);
|
||||||
|
|
||||||
|
if (mfp->mf_infile_count > 2)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Need to read back all data blocks from disk, decrypt them with the
|
||||||
|
* old key/method and mark them to be written. The algorithm is
|
||||||
|
* similar to what happens in ml_recover(), but we skip negative block
|
||||||
|
* numbers.
|
||||||
|
*/
|
||||||
|
ml_flush_line(buf); /* flush buffered line */
|
||||||
|
(void)ml_find_line(buf, (linenr_T)0, ML_FLUSH); /* flush locked block */
|
||||||
|
|
||||||
|
hp = NULL;
|
||||||
|
bnum = 1; /* start with block 1 */
|
||||||
|
page_count = 1; /* which is 1 page */
|
||||||
|
idx = 0; /* start with first index in block 1 */
|
||||||
|
error = 0;
|
||||||
|
buf->b_ml.ml_stack_top = 0;
|
||||||
|
buf->b_ml.ml_stack = NULL;
|
||||||
|
buf->b_ml.ml_stack_size = 0; /* no stack yet */
|
||||||
|
|
||||||
|
for ( ; !got_int; line_breakcheck())
|
||||||
|
{
|
||||||
|
if (hp != NULL)
|
||||||
|
mf_put(mfp, hp, FALSE, FALSE); /* release previous block */
|
||||||
|
|
||||||
|
/* get the block (pointer or data) */
|
||||||
|
if ((hp = mf_get(mfp, (blocknr_T)bnum, page_count)) == NULL)
|
||||||
|
{
|
||||||
|
if (bnum == 1)
|
||||||
|
break;
|
||||||
|
++error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pp = (PTR_BL *)(hp->bh_data);
|
||||||
|
if (pp->pb_id == PTR_ID) /* it is a pointer block */
|
||||||
|
{
|
||||||
|
if (pp->pb_count == 0)
|
||||||
|
{
|
||||||
|
/* empty block? */
|
||||||
|
++error;
|
||||||
|
}
|
||||||
|
else if (idx < (int)pp->pb_count) /* go a block deeper */
|
||||||
|
{
|
||||||
|
if (pp->pb_pointer[idx].pe_bnum < 0)
|
||||||
|
{
|
||||||
|
/* Skip data block with negative block number. */
|
||||||
|
++idx; /* get same block again for next index */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* going one block deeper in the tree, new entry in
|
||||||
|
* stack */
|
||||||
|
if ((top = ml_add_stack(buf)) < 0)
|
||||||
|
{
|
||||||
|
++error;
|
||||||
|
break; /* out of memory */
|
||||||
|
}
|
||||||
|
ip = &(buf->b_ml.ml_stack[top]);
|
||||||
|
ip->ip_bnum = bnum;
|
||||||
|
ip->ip_index = idx;
|
||||||
|
|
||||||
|
bnum = pp->pb_pointer[idx].pe_bnum;
|
||||||
|
page_count = pp->pb_pointer[idx].pe_page_count;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* not a pointer block */
|
||||||
|
{
|
||||||
|
dp = (DATA_BL *)(hp->bh_data);
|
||||||
|
if (dp->db_id != DATA_ID) /* block id wrong */
|
||||||
|
++error;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* It is a data block, need to write it back to disk. */
|
||||||
|
mf_put(mfp, hp, TRUE, FALSE);
|
||||||
|
hp = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf->b_ml.ml_stack_top == 0) /* finished */
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* go one block up in the tree */
|
||||||
|
ip = &(buf->b_ml.ml_stack[--(buf->b_ml.ml_stack_top)]);
|
||||||
|
bnum = ip->ip_bnum;
|
||||||
|
idx = ip->ip_index + 1; /* go to next index */
|
||||||
|
page_count = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mfp->mf_old_key = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ml_setname() is called when the file name of "buf" has been changed.
|
* ml_setname() is called when the file name of "buf" has been changed.
|
||||||
* It may rename the swap file.
|
* It may rename the swap file.
|
||||||
@ -475,7 +665,7 @@ ml_setname(buf)
|
|||||||
#else
|
#else
|
||||||
mf_set_ffname(mfp);
|
mf_set_ffname(mfp);
|
||||||
#endif
|
#endif
|
||||||
ml_upd_block0(buf, FALSE);
|
ml_upd_block0(buf, UB_SAME_DIR);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
vim_free(fname); /* this fname didn't work, try another */
|
vim_free(fname); /* this fname didn't work, try another */
|
||||||
@ -569,7 +759,7 @@ ml_open_file(buf)
|
|||||||
*/
|
*/
|
||||||
mf_fullname(mfp);
|
mf_fullname(mfp);
|
||||||
#endif
|
#endif
|
||||||
ml_upd_block0(buf, FALSE);
|
ml_upd_block0(buf, UB_SAME_DIR);
|
||||||
|
|
||||||
/* Flush block zero, so others can read it */
|
/* Flush block zero, so others can read it */
|
||||||
if (mf_sync(mfp, MFS_ZERO) == OK)
|
if (mf_sync(mfp, MFS_ZERO) == OK)
|
||||||
@ -680,16 +870,32 @@ ml_close_notmod()
|
|||||||
ml_timestamp(buf)
|
ml_timestamp(buf)
|
||||||
buf_T *buf;
|
buf_T *buf;
|
||||||
{
|
{
|
||||||
ml_upd_block0(buf, TRUE);
|
ml_upd_block0(buf, UB_FNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return FAIL when the ID of "b0p" is wrong.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ml_check_b0_id(b0p)
|
||||||
|
ZERO_BL *b0p;
|
||||||
|
{
|
||||||
|
if (b0p->b0_id[0] != BLOCK0_ID0
|
||||||
|
|| (b0p->b0_id[1] != BLOCK0_ID1
|
||||||
|
&& b0p->b0_id[1] != BLOCK0_ID1_C0
|
||||||
|
&& b0p->b0_id[1] != BLOCK0_ID1_C1)
|
||||||
|
)
|
||||||
|
return FAIL;
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update the timestamp or the B0_SAME_DIR flag of the .swp file.
|
* Update the timestamp or the B0_SAME_DIR flag of the .swp file.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
ml_upd_block0(buf, set_fname)
|
ml_upd_block0(buf, what)
|
||||||
buf_T *buf;
|
buf_T *buf;
|
||||||
int set_fname;
|
upd_block0_T what;
|
||||||
{
|
{
|
||||||
memfile_T *mfp;
|
memfile_T *mfp;
|
||||||
bhdr_T *hp;
|
bhdr_T *hp;
|
||||||
@ -699,13 +905,17 @@ ml_upd_block0(buf, set_fname)
|
|||||||
if (mfp == NULL || (hp = mf_get(mfp, (blocknr_T)0, 1)) == NULL)
|
if (mfp == NULL || (hp = mf_get(mfp, (blocknr_T)0, 1)) == NULL)
|
||||||
return;
|
return;
|
||||||
b0p = (ZERO_BL *)(hp->bh_data);
|
b0p = (ZERO_BL *)(hp->bh_data);
|
||||||
if (b0p->b0_id[0] != BLOCK0_ID0 || b0p->b0_id[1] != BLOCK0_ID1)
|
if (ml_check_b0_id(b0p) == FAIL)
|
||||||
EMSG(_("E304: ml_upd_block0(): Didn't get block 0??"));
|
EMSG(_("E304: ml_upd_block0(): Didn't get block 0??"));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (set_fname)
|
if (what == UB_FNAME)
|
||||||
set_b0_fname(b0p, buf);
|
set_b0_fname(b0p, buf);
|
||||||
else
|
#ifdef FEAT_CRYPT
|
||||||
|
else if (what == UB_CRYPT)
|
||||||
|
ml_set_b0_crypt(buf, b0p);
|
||||||
|
#endif
|
||||||
|
else /* what == UB_SAME_DIR */
|
||||||
set_b0_dir_flag(b0p, buf);
|
set_b0_dir_flag(b0p, buf);
|
||||||
}
|
}
|
||||||
mf_put(mfp, hp, TRUE, FALSE);
|
mf_put(mfp, hp, TRUE, FALSE);
|
||||||
@ -731,7 +941,7 @@ set_b0_fname(b0p, buf)
|
|||||||
/* Systems that cannot translate "~user" back into a path: copy the
|
/* Systems that cannot translate "~user" back into a path: copy the
|
||||||
* file name unmodified. Do use slashes instead of backslashes for
|
* file name unmodified. Do use slashes instead of backslashes for
|
||||||
* portability. */
|
* portability. */
|
||||||
vim_strncpy(b0p->b0_fname, buf->b_ffname, B0_FNAME_SIZE - 1);
|
vim_strncpy(b0p->b0_fname, buf->b_ffname, B0_FNAME_SIZE_CRYPT - 1);
|
||||||
# ifdef BACKSLASH_IN_FILENAME
|
# ifdef BACKSLASH_IN_FILENAME
|
||||||
forward_slash(b0p->b0_fname);
|
forward_slash(b0p->b0_fname);
|
||||||
# endif
|
# endif
|
||||||
@ -746,14 +956,16 @@ set_b0_fname(b0p, buf)
|
|||||||
* First replace home dir path with "~/" with home_replace().
|
* First replace home dir path with "~/" with home_replace().
|
||||||
* Then insert the user name to get "~user/".
|
* Then insert the user name to get "~user/".
|
||||||
*/
|
*/
|
||||||
home_replace(NULL, buf->b_ffname, b0p->b0_fname, B0_FNAME_SIZE, TRUE);
|
home_replace(NULL, buf->b_ffname, b0p->b0_fname,
|
||||||
|
B0_FNAME_SIZE_CRYPT, TRUE);
|
||||||
if (b0p->b0_fname[0] == '~')
|
if (b0p->b0_fname[0] == '~')
|
||||||
{
|
{
|
||||||
flen = STRLEN(b0p->b0_fname);
|
flen = STRLEN(b0p->b0_fname);
|
||||||
/* If there is no user name or it is too long, don't use "~/" */
|
/* If there is no user name or it is too long, don't use "~/" */
|
||||||
if (get_user_name(uname, B0_UNAME_SIZE) == FAIL
|
if (get_user_name(uname, B0_UNAME_SIZE) == FAIL
|
||||||
|| (ulen = STRLEN(uname)) + flen > B0_FNAME_SIZE - 1)
|
|| (ulen = STRLEN(uname)) + flen > B0_FNAME_SIZE_CRYPT - 1)
|
||||||
vim_strncpy(b0p->b0_fname, buf->b_ffname, B0_FNAME_SIZE - 1);
|
vim_strncpy(b0p->b0_fname, buf->b_ffname,
|
||||||
|
B0_FNAME_SIZE_CRYPT - 1);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mch_memmove(b0p->b0_fname + ulen + 1, b0p->b0_fname + 1, flen);
|
mch_memmove(b0p->b0_fname + ulen + 1, b0p->b0_fname + 1, flen);
|
||||||
@ -816,15 +1028,24 @@ add_b0_fenc(b0p, buf)
|
|||||||
buf_T *buf;
|
buf_T *buf;
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
int size = B0_FNAME_SIZE_NOCRYPT;
|
||||||
|
|
||||||
|
# ifdef FEAT_CRYPT
|
||||||
|
/* Without encryption use the same offset as in Vim 7.2 to be compatible.
|
||||||
|
* With encryption it's OK to move elsewhere, the swap file is not
|
||||||
|
* compatible anyway. */
|
||||||
|
if (*buf->b_p_key != NUL)
|
||||||
|
size = B0_FNAME_SIZE_CRYPT;
|
||||||
|
# endif
|
||||||
|
|
||||||
n = (int)STRLEN(buf->b_p_fenc);
|
n = (int)STRLEN(buf->b_p_fenc);
|
||||||
if (STRLEN(b0p->b0_fname) + n + 1 > B0_FNAME_SIZE)
|
if ((int)STRLEN(b0p->b0_fname) + n + 1 > size)
|
||||||
b0p->b0_flags &= ~B0_HAS_FENC;
|
b0p->b0_flags &= ~B0_HAS_FENC;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mch_memmove((char *)b0p->b0_fname + B0_FNAME_SIZE - n,
|
mch_memmove((char *)b0p->b0_fname + size - n,
|
||||||
(char *)buf->b_p_fenc, (size_t)n);
|
(char *)buf->b_p_fenc, (size_t)n);
|
||||||
*(b0p->b0_fname + B0_FNAME_SIZE - n - 1) = NUL;
|
*(b0p->b0_fname + size - n - 1) = NUL;
|
||||||
b0p->b0_flags |= B0_HAS_FENC;
|
b0p->b0_flags |= B0_HAS_FENC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -832,7 +1053,7 @@ add_b0_fenc(b0p, buf)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* try to recover curbuf from the .swp file
|
* Try to recover curbuf from the .swp file.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ml_recover()
|
ml_recover()
|
||||||
@ -840,10 +1061,14 @@ ml_recover()
|
|||||||
buf_T *buf = NULL;
|
buf_T *buf = NULL;
|
||||||
memfile_T *mfp = NULL;
|
memfile_T *mfp = NULL;
|
||||||
char_u *fname;
|
char_u *fname;
|
||||||
|
char_u *fname_used = NULL;
|
||||||
bhdr_T *hp = NULL;
|
bhdr_T *hp = NULL;
|
||||||
ZERO_BL *b0p;
|
ZERO_BL *b0p;
|
||||||
int b0_ff;
|
int b0_ff;
|
||||||
char_u *b0_fenc = NULL;
|
char_u *b0_fenc = NULL;
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
int b0_cm = -1;
|
||||||
|
#endif
|
||||||
PTR_BL *pp;
|
PTR_BL *pp;
|
||||||
DATA_BL *dp;
|
DATA_BL *dp;
|
||||||
infoptr_T *ip;
|
infoptr_T *ip;
|
||||||
@ -892,14 +1117,14 @@ ml_recover()
|
|||||||
&& ASCII_ISALPHA(fname[len - 1]))
|
&& ASCII_ISALPHA(fname[len - 1]))
|
||||||
{
|
{
|
||||||
directly = TRUE;
|
directly = TRUE;
|
||||||
fname = vim_strsave(fname); /* make a copy for mf_open() */
|
fname_used = vim_strsave(fname); /* make a copy for mf_open() */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
directly = FALSE;
|
directly = FALSE;
|
||||||
|
|
||||||
/* count the number of matching swap files */
|
/* count the number of matching swap files */
|
||||||
len = recover_names(&fname, FALSE, 0);
|
len = recover_names(fname, FALSE, 0, NULL);
|
||||||
if (len == 0) /* no swap files found */
|
if (len == 0) /* no swap files found */
|
||||||
{
|
{
|
||||||
EMSG2(_("E305: No swap file found for %s"), fname);
|
EMSG2(_("E305: No swap file found for %s"), fname);
|
||||||
@ -910,7 +1135,7 @@ ml_recover()
|
|||||||
else /* several swap files found, choose */
|
else /* several swap files found, choose */
|
||||||
{
|
{
|
||||||
/* list the names of the swap files */
|
/* list the names of the swap files */
|
||||||
(void)recover_names(&fname, TRUE, 0);
|
(void)recover_names(fname, TRUE, 0, NULL);
|
||||||
msg_putchar('\n');
|
msg_putchar('\n');
|
||||||
MSG_PUTS(_("Enter number of swap file to use (0 to quit): "));
|
MSG_PUTS(_("Enter number of swap file to use (0 to quit): "));
|
||||||
i = get_number(FALSE, NULL);
|
i = get_number(FALSE, NULL);
|
||||||
@ -918,28 +1143,26 @@ ml_recover()
|
|||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
/* get the swap file name that will be used */
|
/* get the swap file name that will be used */
|
||||||
(void)recover_names(&fname, FALSE, i);
|
(void)recover_names(fname, FALSE, i, &fname_used);
|
||||||
}
|
}
|
||||||
if (fname == NULL)
|
if (fname_used == NULL)
|
||||||
goto theend; /* out of memory */
|
goto theend; /* out of memory */
|
||||||
|
|
||||||
/* When called from main() still need to initialize storage structure */
|
/* When called from main() still need to initialize storage structure */
|
||||||
if (called_from_main && ml_open(curbuf) == FAIL)
|
if (called_from_main && ml_open(curbuf) == FAIL)
|
||||||
getout(1);
|
getout(1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* allocate a buffer structure (only the memline in it is really used)
|
* Allocate a buffer structure for the swap file that is used for recovery.
|
||||||
*/
|
* Only the memline in it is really used.
|
||||||
|
*/
|
||||||
buf = (buf_T *)alloc((unsigned)sizeof(buf_T));
|
buf = (buf_T *)alloc((unsigned)sizeof(buf_T));
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
{
|
|
||||||
vim_free(fname);
|
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* init fields in memline struct
|
* init fields in memline struct
|
||||||
*/
|
*/
|
||||||
buf->b_ml.ml_stack_size = 0; /* no stack yet */
|
buf->b_ml.ml_stack_size = 0; /* no stack yet */
|
||||||
buf->b_ml.ml_stack = NULL; /* no stack yet */
|
buf->b_ml.ml_stack = NULL; /* no stack yet */
|
||||||
buf->b_ml.ml_stack_top = 0; /* nothing in the stack */
|
buf->b_ml.ml_stack_top = 0; /* nothing in the stack */
|
||||||
@ -947,23 +1170,24 @@ ml_recover()
|
|||||||
buf->b_ml.ml_locked = NULL; /* no locked block */
|
buf->b_ml.ml_locked = NULL; /* no locked block */
|
||||||
buf->b_ml.ml_flags = 0;
|
buf->b_ml.ml_flags = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* open the memfile from the old swap file
|
* open the memfile from the old swap file
|
||||||
*/
|
*/
|
||||||
p = vim_strsave(fname); /* save fname for the message
|
p = vim_strsave(fname_used); /* save "fname_used" for the message:
|
||||||
(mf_open() may free fname) */
|
mf_open() will consume "fname_used"! */
|
||||||
mfp = mf_open(fname, O_RDONLY); /* consumes fname! */
|
mfp = mf_open(fname_used, O_RDONLY);
|
||||||
|
fname_used = p;
|
||||||
if (mfp == NULL || mfp->mf_fd < 0)
|
if (mfp == NULL || mfp->mf_fd < 0)
|
||||||
{
|
{
|
||||||
if (p != NULL)
|
if (fname_used != NULL)
|
||||||
{
|
EMSG2(_("E306: Cannot open %s"), fname_used);
|
||||||
EMSG2(_("E306: Cannot open %s"), p);
|
|
||||||
vim_free(p);
|
|
||||||
}
|
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
vim_free(p);
|
|
||||||
buf->b_ml.ml_mfp = mfp;
|
buf->b_ml.ml_mfp = mfp;
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
mfp->mf_buffer = buf;
|
||||||
|
buf->b_p_key = empty_option;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The page size set in mf_open() might be different from the page size
|
* The page size set in mf_open() might be different from the page size
|
||||||
@ -973,16 +1197,15 @@ ml_recover()
|
|||||||
*/
|
*/
|
||||||
mfp->mf_page_size = MIN_SWAP_PAGE_SIZE;
|
mfp->mf_page_size = MIN_SWAP_PAGE_SIZE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* try to read block 0
|
* try to read block 0
|
||||||
*/
|
*/
|
||||||
if ((hp = mf_get(mfp, (blocknr_T)0, 1)) == NULL)
|
if ((hp = mf_get(mfp, (blocknr_T)0, 1)) == NULL)
|
||||||
{
|
{
|
||||||
msg_start();
|
msg_start();
|
||||||
MSG_PUTS_ATTR(_("Unable to read block 0 from "), attr | MSG_HIST);
|
MSG_PUTS_ATTR(_("Unable to read block 0 from "), attr | MSG_HIST);
|
||||||
msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST);
|
msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST);
|
||||||
MSG_PUTS_ATTR(
|
MSG_PUTS_ATTR(_("\nMaybe no changes were made or Vim did not update the swap file."),
|
||||||
_("\nMaybe no changes were made or Vim did not update the swap file."),
|
|
||||||
attr | MSG_HIST);
|
attr | MSG_HIST);
|
||||||
msg_end();
|
msg_end();
|
||||||
goto theend;
|
goto theend;
|
||||||
@ -998,7 +1221,7 @@ ml_recover()
|
|||||||
msg_end();
|
msg_end();
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
if (b0p->b0_id[0] != BLOCK0_ID0 || b0p->b0_id[1] != BLOCK0_ID1)
|
if (ml_check_b0_id(b0p) == FAIL)
|
||||||
{
|
{
|
||||||
EMSG2(_("E307: %s does not look like a Vim swap file"), mfp->mf_fname);
|
EMSG2(_("E307: %s does not look like a Vim swap file"), mfp->mf_fname);
|
||||||
goto theend;
|
goto theend;
|
||||||
@ -1024,6 +1247,22 @@ ml_recover()
|
|||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
if (b0p->b0_id[1] == BLOCK0_ID1_C0)
|
||||||
|
buf->b_p_cm = b0_cm = 0;
|
||||||
|
else if (b0p->b0_id[1] == BLOCK0_ID1_C1)
|
||||||
|
{
|
||||||
|
buf->b_p_cm = b0_cm = 1;
|
||||||
|
mch_memmove(mfp->mf_seed, &b0p->b0_seed, MF_SEED_LEN);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (b0p->b0_id[1] != BLOCK0_ID1)
|
||||||
|
{
|
||||||
|
EMSG2(_("E000: %s is encrypted and this version of Vim does not support encryption"), mfp->mf_fname);
|
||||||
|
goto theend;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we guessed the wrong page size, we have to recalculate the
|
* If we guessed the wrong page size, we have to recalculate the
|
||||||
* highest block number in the file.
|
* highest block number in the file.
|
||||||
@ -1058,9 +1297,9 @@ ml_recover()
|
|||||||
b0p = (ZERO_BL *)(hp->bh_data);
|
b0p = (ZERO_BL *)(hp->bh_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If .swp file name given directly, use name from swap file for buffer.
|
* If .swp file name given directly, use name from swap file for buffer.
|
||||||
*/
|
*/
|
||||||
if (directly)
|
if (directly)
|
||||||
{
|
{
|
||||||
expand_env(b0p->b0_fname, NameBuff, MAXPATHL);
|
expand_env(b0p->b0_fname, NameBuff, MAXPATHL);
|
||||||
@ -1078,9 +1317,9 @@ ml_recover()
|
|||||||
smsg((char_u *)_("Original file \"%s\""), NameBuff);
|
smsg((char_u *)_("Original file \"%s\""), NameBuff);
|
||||||
msg_putchar('\n');
|
msg_putchar('\n');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* check date of swap file and original file
|
* check date of swap file and original file
|
||||||
*/
|
*/
|
||||||
mtime = char_to_long(b0p->b0_mtime);
|
mtime = char_to_long(b0p->b0_mtime);
|
||||||
if (curbuf->b_ffname != NULL
|
if (curbuf->b_ffname != NULL
|
||||||
&& mch_stat((char *)curbuf->b_ffname, &org_stat) != -1
|
&& mch_stat((char *)curbuf->b_ffname, &org_stat) != -1
|
||||||
@ -1096,10 +1335,16 @@ ml_recover()
|
|||||||
b0_ff = (b0p->b0_flags & B0_FF_MASK);
|
b0_ff = (b0p->b0_flags & B0_FF_MASK);
|
||||||
if (b0p->b0_flags & B0_HAS_FENC)
|
if (b0p->b0_flags & B0_HAS_FENC)
|
||||||
{
|
{
|
||||||
for (p = b0p->b0_fname + B0_FNAME_SIZE;
|
int size = B0_FNAME_SIZE_NOCRYPT;
|
||||||
p > b0p->b0_fname && p[-1] != NUL; --p)
|
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
/* Use the same size as in add_b0_fenc(). */
|
||||||
|
if (b0p->b0_id[1] != BLOCK0_ID1)
|
||||||
|
size = B0_FNAME_SIZE_CRYPT;
|
||||||
|
#endif
|
||||||
|
for (p = b0p->b0_fname + size; p > b0p->b0_fname && p[-1] != NUL; --p)
|
||||||
;
|
;
|
||||||
b0_fenc = vim_strnsave(p, (int)(b0p->b0_fname + B0_FNAME_SIZE - p));
|
b0_fenc = vim_strnsave(p, (int)(b0p->b0_fname + size - p));
|
||||||
}
|
}
|
||||||
|
|
||||||
mf_put(mfp, hp, FALSE, FALSE); /* release block 0 */
|
mf_put(mfp, hp, FALSE, FALSE); /* release block 0 */
|
||||||
@ -1115,11 +1360,40 @@ ml_recover()
|
|||||||
/*
|
/*
|
||||||
* Try reading the original file to obtain the values of 'fileformat',
|
* Try reading the original file to obtain the values of 'fileformat',
|
||||||
* 'fileencoding', etc. Ignore errors. The text itself is not used.
|
* 'fileencoding', etc. Ignore errors. The text itself is not used.
|
||||||
|
* When the file is encrypted the user is asked to enter the key.
|
||||||
*/
|
*/
|
||||||
if (curbuf->b_ffname != NULL)
|
if (curbuf->b_ffname != NULL)
|
||||||
orig_file_status = readfile(curbuf->b_ffname, NULL, (linenr_T)0,
|
orig_file_status = readfile(curbuf->b_ffname, NULL, (linenr_T)0,
|
||||||
(linenr_T)0, (linenr_T)MAXLNUM, NULL, READ_NEW);
|
(linenr_T)0, (linenr_T)MAXLNUM, NULL, READ_NEW);
|
||||||
|
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
if (b0_cm >= 0)
|
||||||
|
{
|
||||||
|
/* Need to ask the user for the crypt key. If this fails we continue
|
||||||
|
* without a key, will probably get garbage text. */
|
||||||
|
if (*curbuf->b_p_key != NUL)
|
||||||
|
{
|
||||||
|
smsg((char_u *)_("Swap file is encrypted: \"%s\""), fname_used);
|
||||||
|
MSG_PUTS(_("\nIf you entered a new crypt key but did not write the text file,"));
|
||||||
|
MSG_PUTS(_("\nenter the new crypt key."));
|
||||||
|
MSG_PUTS(_("\nIf you wrote the text file after changing the crypt key press enter"));
|
||||||
|
MSG_PUTS(_("\nto use the same key for text file and swap file"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
smsg((char_u *)_(need_key_msg), fname_used);
|
||||||
|
buf->b_p_key = get_crypt_key(FALSE, FALSE);
|
||||||
|
if (buf->b_p_key == NULL)
|
||||||
|
buf->b_p_key = curbuf->b_p_key;
|
||||||
|
else if (*buf->b_p_key == NUL)
|
||||||
|
{
|
||||||
|
vim_free(buf->b_p_key);
|
||||||
|
buf->b_p_key = curbuf->b_p_key;
|
||||||
|
}
|
||||||
|
if (buf->b_p_key == NULL)
|
||||||
|
buf->b_p_key = empty_option;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Use the 'fileformat' and 'fileencoding' as stored in the swap file. */
|
/* Use the 'fileformat' and 'fileencoding' as stored in the swap file. */
|
||||||
if (b0_ff != 0)
|
if (b0_ff != 0)
|
||||||
set_fileformat(b0_ff - 1, OPT_LOCAL);
|
set_fileformat(b0_ff - 1, OPT_LOCAL);
|
||||||
@ -1386,9 +1660,17 @@ ml_recover()
|
|||||||
MSG_PUTS(_("\nYou may want to delete the .swp file now.\n\n"));
|
MSG_PUTS(_("\nYou may want to delete the .swp file now.\n\n"));
|
||||||
cmdline_row = msg_row;
|
cmdline_row = msg_row;
|
||||||
}
|
}
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
if (*buf->b_p_key != NUL && STRCMP(curbuf->b_p_key, buf->b_p_key) != 0)
|
||||||
|
{
|
||||||
|
MSG_PUTS(_("Using crypt key from swap file for the text file.\n"));
|
||||||
|
set_option_value((char_u *)"key", 0L, buf->b_p_key, OPT_LOCAL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
redraw_curbuf_later(NOT_VALID);
|
redraw_curbuf_later(NOT_VALID);
|
||||||
|
|
||||||
theend:
|
theend:
|
||||||
|
vim_free(fname_used);
|
||||||
recoverymode = FALSE;
|
recoverymode = FALSE;
|
||||||
if (mfp != NULL)
|
if (mfp != NULL)
|
||||||
{
|
{
|
||||||
@ -1398,6 +1680,10 @@ theend:
|
|||||||
}
|
}
|
||||||
if (buf != NULL)
|
if (buf != NULL)
|
||||||
{
|
{
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
if (buf->b_p_key != curbuf->b_p_key)
|
||||||
|
free_string_option(buf->b_p_key);
|
||||||
|
#endif
|
||||||
vim_free(buf->b_ml.ml_stack);
|
vim_free(buf->b_ml.ml_stack);
|
||||||
vim_free(buf);
|
vim_free(buf);
|
||||||
}
|
}
|
||||||
@ -1424,10 +1710,11 @@ theend:
|
|||||||
* - find the name of the n'th swap file when recovering
|
* - find the name of the n'th swap file when recovering
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
recover_names(fname, list, nr)
|
recover_names(fname, list, nr, fname_out)
|
||||||
char_u **fname; /* base for swap file name */
|
char_u *fname; /* base for swap file name */
|
||||||
int list; /* when TRUE, list the swap file names */
|
int list; /* when TRUE, list the swap file names */
|
||||||
int nr; /* when non-zero, return nr'th swap file name */
|
int nr; /* when non-zero, return nr'th swap file name */
|
||||||
|
char_u **fname_out; /* result when "nr" > 0 */
|
||||||
{
|
{
|
||||||
int num_names;
|
int num_names;
|
||||||
char_u *(names[6]);
|
char_u *(names[6]);
|
||||||
@ -1447,13 +1734,13 @@ recover_names(fname, list, nr)
|
|||||||
if (fname != NULL)
|
if (fname != NULL)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_READLINK
|
#ifdef HAVE_READLINK
|
||||||
/* Expand symlink in the file name, because the swap file is created with
|
/* Expand symlink in the file name, because the swap file is created
|
||||||
* the actual file instead of with the symlink. */
|
* with the actual file instead of with the symlink. */
|
||||||
if (resolve_symlink(*fname, fname_buf) == OK)
|
if (resolve_symlink(fname, fname_buf) == OK)
|
||||||
fname_res = fname_buf;
|
fname_res = fname_buf;
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
fname_res = *fname;
|
fname_res = fname;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list)
|
if (list)
|
||||||
@ -1480,7 +1767,7 @@ recover_names(fname, list, nr)
|
|||||||
|
|
||||||
if (dir_name[0] == '.' && dir_name[1] == NUL) /* check current dir */
|
if (dir_name[0] == '.' && dir_name[1] == NUL) /* check current dir */
|
||||||
{
|
{
|
||||||
if (fname == NULL || *fname == NULL)
|
if (fname == NULL)
|
||||||
{
|
{
|
||||||
#ifdef VMS
|
#ifdef VMS
|
||||||
names[0] = vim_strsave((char_u *)"*_sw%");
|
names[0] = vim_strsave((char_u *)"*_sw%");
|
||||||
@ -1511,7 +1798,7 @@ recover_names(fname, list, nr)
|
|||||||
}
|
}
|
||||||
else /* check directory dir_name */
|
else /* check directory dir_name */
|
||||||
{
|
{
|
||||||
if (fname == NULL || *fname == NULL)
|
if (fname == NULL)
|
||||||
{
|
{
|
||||||
#ifdef VMS
|
#ifdef VMS
|
||||||
names[0] = concat_fnames(dir_name, (char_u *)"*_sw%", TRUE);
|
names[0] = concat_fnames(dir_name, (char_u *)"*_sw%", TRUE);
|
||||||
@ -1583,8 +1870,7 @@ recover_names(fname, list, nr)
|
|||||||
* not able to execute the shell).
|
* not able to execute the shell).
|
||||||
* Try finding a swap file by simply adding ".swp" to the file name.
|
* Try finding a swap file by simply adding ".swp" to the file name.
|
||||||
*/
|
*/
|
||||||
if (*dirp == NUL && file_count + num_files == 0
|
if (*dirp == NUL && file_count + num_files == 0 && fname != NULL)
|
||||||
&& fname != NULL && *fname != NULL)
|
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char_u *swapname;
|
char_u *swapname;
|
||||||
@ -1637,7 +1923,8 @@ recover_names(fname, list, nr)
|
|||||||
file_count += num_files;
|
file_count += num_files;
|
||||||
if (nr <= file_count)
|
if (nr <= file_count)
|
||||||
{
|
{
|
||||||
*fname = vim_strsave(files[nr - 1 + num_files - file_count]);
|
*fname_out = vim_strsave(
|
||||||
|
files[nr - 1 + num_files - file_count]);
|
||||||
dirp = (char_u *)""; /* stop searching */
|
dirp = (char_u *)""; /* stop searching */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1645,7 +1932,7 @@ recover_names(fname, list, nr)
|
|||||||
{
|
{
|
||||||
if (dir_name[0] == '.' && dir_name[1] == NUL)
|
if (dir_name[0] == '.' && dir_name[1] == NUL)
|
||||||
{
|
{
|
||||||
if (fname == NULL || *fname == NULL)
|
if (fname == NULL)
|
||||||
MSG_PUTS(_(" In current directory:\n"));
|
MSG_PUTS(_(" In current directory:\n"));
|
||||||
else
|
else
|
||||||
MSG_PUTS(_(" Using specified name:\n"));
|
MSG_PUTS(_(" Using specified name:\n"));
|
||||||
@ -1772,7 +2059,7 @@ swapfile_info(fname)
|
|||||||
{
|
{
|
||||||
MSG_PUTS(_(" [from Vim version 3.0]"));
|
MSG_PUTS(_(" [from Vim version 3.0]"));
|
||||||
}
|
}
|
||||||
else if (b0.b0_id[0] != BLOCK0_ID0 || b0.b0_id[1] != BLOCK0_ID1)
|
else if (ml_check_b0_id(&b0) == FAIL)
|
||||||
{
|
{
|
||||||
MSG_PUTS(_(" [does not look like a Vim swap file]"));
|
MSG_PUTS(_(" [does not look like a Vim swap file]"));
|
||||||
}
|
}
|
||||||
@ -3478,11 +3765,11 @@ ml_find_line(buf, lnum, action)
|
|||||||
error_block:
|
error_block:
|
||||||
mf_put(mfp, hp, FALSE, FALSE);
|
mf_put(mfp, hp, FALSE, FALSE);
|
||||||
error_noblock:
|
error_noblock:
|
||||||
/*
|
/*
|
||||||
* If action is ML_DELETE or ML_INSERT we have to correct the tree for
|
* If action is ML_DELETE or ML_INSERT we have to correct the tree for
|
||||||
* the incremented/decremented line counts, because there won't be a line
|
* the incremented/decremented line counts, because there won't be a line
|
||||||
* inserted/deleted after all.
|
* inserted/deleted after all.
|
||||||
*/
|
*/
|
||||||
if (action == ML_DELETE)
|
if (action == ML_DELETE)
|
||||||
ml_lineadd(buf, 1);
|
ml_lineadd(buf, 1);
|
||||||
else if (action == ML_INSERT)
|
else if (action == ML_INSERT)
|
||||||
@ -3505,10 +3792,10 @@ ml_add_stack(buf)
|
|||||||
|
|
||||||
top = buf->b_ml.ml_stack_top;
|
top = buf->b_ml.ml_stack_top;
|
||||||
|
|
||||||
/* may have to increase the stack size */
|
/* may have to increase the stack size */
|
||||||
if (top == buf->b_ml.ml_stack_size)
|
if (top == buf->b_ml.ml_stack_size)
|
||||||
{
|
{
|
||||||
CHECK(top > 0, _("Stack size increases")); /* more than 5 levels??? */
|
CHECK(top > 0, _("Stack size increases")); /* more than 5 levels??? */
|
||||||
|
|
||||||
newstack = (infoptr_T *)alloc((unsigned)sizeof(infoptr_T) *
|
newstack = (infoptr_T *)alloc((unsigned)sizeof(infoptr_T) *
|
||||||
(buf->b_ml.ml_stack_size + STACK_INCR));
|
(buf->b_ml.ml_stack_size + STACK_INCR));
|
||||||
@ -4518,6 +4805,132 @@ ml_setflags(buf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(FEAT_CRYPT) || defined(PROTO)
|
||||||
|
/*
|
||||||
|
* If "data" points to a data block encrypt the text in it and return a copy
|
||||||
|
* in allocated memory. Return NULL when out of memory.
|
||||||
|
* Otherwise return "data".
|
||||||
|
*/
|
||||||
|
char_u *
|
||||||
|
ml_encrypt_data(mfp, data, offset, size)
|
||||||
|
memfile_T *mfp;
|
||||||
|
char_u *data;
|
||||||
|
off_t offset;
|
||||||
|
unsigned size;
|
||||||
|
{
|
||||||
|
DATA_BL *dp = (DATA_BL *)data;
|
||||||
|
char_u *head_end;
|
||||||
|
char_u *text_start;
|
||||||
|
char_u *new_data;
|
||||||
|
int text_len;
|
||||||
|
|
||||||
|
if (dp->db_id != DATA_ID)
|
||||||
|
return data;
|
||||||
|
|
||||||
|
new_data = (char_u *)alloc(size);
|
||||||
|
if (new_data == NULL)
|
||||||
|
return NULL;
|
||||||
|
head_end = (char_u *)(&dp->db_index[dp->db_line_count]);
|
||||||
|
text_start = (char_u *)dp + dp->db_txt_start;
|
||||||
|
text_len = size - dp->db_txt_start;
|
||||||
|
|
||||||
|
/* Copy the header and the text. */
|
||||||
|
mch_memmove(new_data, dp, head_end - (char_u *)dp);
|
||||||
|
|
||||||
|
/* Encrypt the text. */
|
||||||
|
crypt_push_state();
|
||||||
|
ml_crypt_prepare(mfp, offset, FALSE);
|
||||||
|
crypt_encode(text_start, text_len, new_data + dp->db_txt_start);
|
||||||
|
crypt_pop_state();
|
||||||
|
|
||||||
|
/* Clear the gap. */
|
||||||
|
if (head_end < text_start)
|
||||||
|
vim_memset(new_data + (head_end - data), 0, text_start - head_end);
|
||||||
|
|
||||||
|
return new_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decrypt the text in "data" if it points to a data block.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ml_decrypt_data(mfp, data, offset, size)
|
||||||
|
memfile_T *mfp;
|
||||||
|
char_u *data;
|
||||||
|
off_t offset;
|
||||||
|
unsigned size;
|
||||||
|
{
|
||||||
|
DATA_BL *dp = (DATA_BL *)data;
|
||||||
|
char_u *head_end;
|
||||||
|
char_u *text_start;
|
||||||
|
int text_len;
|
||||||
|
|
||||||
|
if (dp->db_id == DATA_ID)
|
||||||
|
{
|
||||||
|
head_end = (char_u *)(&dp->db_index[dp->db_line_count]);
|
||||||
|
text_start = (char_u *)dp + dp->db_txt_start;
|
||||||
|
text_len = dp->db_txt_end - dp->db_txt_start;
|
||||||
|
|
||||||
|
if (head_end > text_start || dp->db_txt_start > size
|
||||||
|
|| dp->db_txt_end > size)
|
||||||
|
return; /* data was messed up */
|
||||||
|
|
||||||
|
/* Decrypt the text in place. */
|
||||||
|
crypt_push_state();
|
||||||
|
ml_crypt_prepare(mfp, offset, TRUE);
|
||||||
|
crypt_decode(text_start, text_len);
|
||||||
|
crypt_pop_state();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare for encryption/decryption, using the key, seed and offset.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ml_crypt_prepare(mfp, offset, reading)
|
||||||
|
memfile_T *mfp;
|
||||||
|
off_t offset;
|
||||||
|
int reading;
|
||||||
|
{
|
||||||
|
buf_T *buf = mfp->mf_buffer;
|
||||||
|
char_u salt[50];
|
||||||
|
int method;
|
||||||
|
char_u *key;
|
||||||
|
char_u *seed;
|
||||||
|
|
||||||
|
if (reading && mfp->mf_old_key != NULL)
|
||||||
|
{
|
||||||
|
/* Reading back blocks with the previous key/method/seed. */
|
||||||
|
method = mfp->mf_old_cm;
|
||||||
|
key = mfp->mf_old_key;
|
||||||
|
seed = mfp->mf_old_seed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
method = buf->b_p_cm;
|
||||||
|
key = buf->b_p_key;
|
||||||
|
seed = mfp->mf_seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
use_crypt_method = method; /* select pkzip or blowfish */
|
||||||
|
if (method == 0)
|
||||||
|
{
|
||||||
|
vim_snprintf((char *)salt, sizeof(salt), "%s%ld", key, (long)offset);
|
||||||
|
crypt_init_keys(salt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Using blowfish, add salt and seed. We use the byte offset of the
|
||||||
|
* block for the salt. */
|
||||||
|
vim_snprintf((char *)salt, sizeof(salt), "%ld", (long)offset);
|
||||||
|
bf_key_init(key, salt, STRLEN(salt));
|
||||||
|
bf_ofb_init(seed, MF_SEED_LEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined(FEAT_BYTEOFF) || defined(PROTO)
|
#if defined(FEAT_BYTEOFF) || defined(PROTO)
|
||||||
|
|
||||||
#define MLCS_MAXL 800 /* max no of lines in chunk */
|
#define MLCS_MAXL 800 /* max no of lines in chunk */
|
||||||
|
55
src/misc2.c
55
src/misc2.c
@ -3746,6 +3746,59 @@ static ulg keys[3]; /* keys defining the pseudo-random sequence */
|
|||||||
keys[2] = CRC32(keys[2], (int)(keys[1] >> 24)); \
|
keys[2] = CRC32(keys[2], (int)(keys[1] >> 24)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int crypt_busy = 0;
|
||||||
|
static ulg saved_keys[3];
|
||||||
|
static int saved_crypt_method;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare for initializing encryption. If already doing encryption then save
|
||||||
|
* the state.
|
||||||
|
* Must always be called symmetrycally with crypt_pop_state().
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
crypt_push_state()
|
||||||
|
{
|
||||||
|
if (crypt_busy == 1)
|
||||||
|
{
|
||||||
|
/* save the state */
|
||||||
|
if (use_crypt_method == 0)
|
||||||
|
{
|
||||||
|
saved_keys[0] = keys[0];
|
||||||
|
saved_keys[1] = keys[1];
|
||||||
|
saved_keys[2] = keys[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
bf_crypt_save();
|
||||||
|
saved_crypt_method = use_crypt_method;
|
||||||
|
}
|
||||||
|
else if (crypt_busy > 1)
|
||||||
|
EMSG2(_(e_intern2), "crypt_push_state()");
|
||||||
|
++crypt_busy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* End encryption. If doing encryption before crypt_push_state() then restore
|
||||||
|
* the saved state.
|
||||||
|
* Must always be called symmetrycally with crypt_push_state().
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
crypt_pop_state()
|
||||||
|
{
|
||||||
|
--crypt_busy;
|
||||||
|
if (crypt_busy == 1)
|
||||||
|
{
|
||||||
|
use_crypt_method = saved_crypt_method;
|
||||||
|
if (use_crypt_method == 0)
|
||||||
|
{
|
||||||
|
keys[0] = saved_keys[0];
|
||||||
|
keys[1] = saved_keys[1];
|
||||||
|
keys[2] = saved_keys[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
bf_crypt_restore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Encrypt "from[len]" into "to[len]".
|
* Encrypt "from[len]" into "to[len]".
|
||||||
* "from" and "to" can be equal to encrypt in place.
|
* "from" and "to" can be equal to encrypt in place.
|
||||||
@ -3894,6 +3947,8 @@ get_crypt_key(store, twice)
|
|||||||
|
|
||||||
/* since the user typed this, no need to wait for return */
|
/* since the user typed this, no need to wait for return */
|
||||||
need_wait_return = FALSE;
|
need_wait_return = FALSE;
|
||||||
|
if (msg_didout)
|
||||||
|
msg_putchar('\n');
|
||||||
msg_didout = FALSE;
|
msg_didout = FALSE;
|
||||||
|
|
||||||
free_crypt_key(p2);
|
free_crypt_key(p2);
|
||||||
|
17
src/option.c
17
src/option.c
@ -5969,13 +5969,18 @@ did_set_string_option(opt_idx, varp, new_value_alloced, oldval, errbuf,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(FEAT_CRYPT) && defined(FEAT_CMDHIST)
|
#if defined(FEAT_CRYPT)
|
||||||
/* 'cryptkey' */
|
/* 'cryptkey' */
|
||||||
else if (gvarp == &p_key)
|
else if (gvarp == &p_key)
|
||||||
{
|
{
|
||||||
|
# if defined(FEAT_CMDHIST)
|
||||||
/* Make sure the ":set" command doesn't show the new value in the
|
/* Make sure the ":set" command doesn't show the new value in the
|
||||||
* history. */
|
* history. */
|
||||||
remove_key_from_history();
|
remove_key_from_history();
|
||||||
|
# endif
|
||||||
|
if (STRCMP(curbuf->b_p_key, oldval) != 0)
|
||||||
|
/* Need to update the swapfile. */
|
||||||
|
ml_set_crypt_key(curbuf, oldval, curbuf->b_p_cm);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -7941,15 +7946,19 @@ set_num_option(opt_idx, varp, value, errbuf, errbuflen, opt_flags)
|
|||||||
if (curbuf->b_p_cm < 0)
|
if (curbuf->b_p_cm < 0)
|
||||||
{
|
{
|
||||||
errmsg = e_positive;
|
errmsg = e_positive;
|
||||||
curbuf->b_p_cm = 0;
|
curbuf->b_p_cm = old_value;
|
||||||
}
|
}
|
||||||
if (curbuf->b_p_cm > 1)
|
if (curbuf->b_p_cm > 1)
|
||||||
{
|
{
|
||||||
errmsg = e_invarg;
|
errmsg = e_invarg;
|
||||||
curbuf->b_p_cm = 1;
|
curbuf->b_p_cm = old_value;
|
||||||
}
|
}
|
||||||
if (curbuf->b_p_cm > 0 && blowfish_self_test() == FAIL)
|
if (curbuf->b_p_cm > 0 && blowfish_self_test() == FAIL)
|
||||||
curbuf->b_p_cm = 0;
|
curbuf->b_p_cm = old_value;
|
||||||
|
|
||||||
|
if (curbuf->b_p_cm != old_value && *curbuf->b_p_key != NUL)
|
||||||
|
/* Need to update the swapfile. */
|
||||||
|
ml_set_crypt_key(curbuf, curbuf->b_p_key, old_value);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -4,5 +4,7 @@ void bf_ofb_init __ARGS((char_u *iv, int iv_len));
|
|||||||
void bf_crypt_encode __ARGS((char_u *from, size_t len, char_u *to));
|
void bf_crypt_encode __ARGS((char_u *from, size_t len, char_u *to));
|
||||||
void bf_crypt_decode __ARGS((char_u *ptr, long len));
|
void bf_crypt_decode __ARGS((char_u *ptr, long len));
|
||||||
void bf_crypt_init_keys __ARGS((char_u *passwd));
|
void bf_crypt_init_keys __ARGS((char_u *passwd));
|
||||||
|
void bf_crypt_save __ARGS((void));
|
||||||
|
void bf_crypt_restore __ARGS((void));
|
||||||
int blowfish_self_test __ARGS((void));
|
int blowfish_self_test __ARGS((void));
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* memline.c */
|
/* memline.c */
|
||||||
int ml_open __ARGS((buf_T *buf));
|
int ml_open __ARGS((buf_T *buf));
|
||||||
|
void ml_set_crypt_key __ARGS((buf_T *buf, char_u *old_key, int old_cm));
|
||||||
void ml_setname __ARGS((buf_T *buf));
|
void ml_setname __ARGS((buf_T *buf));
|
||||||
void ml_open_files __ARGS((void));
|
void ml_open_files __ARGS((void));
|
||||||
void ml_open_file __ARGS((buf_T *buf));
|
void ml_open_file __ARGS((buf_T *buf));
|
||||||
@ -9,7 +10,7 @@ void ml_close_all __ARGS((int del_file));
|
|||||||
void ml_close_notmod __ARGS((void));
|
void ml_close_notmod __ARGS((void));
|
||||||
void ml_timestamp __ARGS((buf_T *buf));
|
void ml_timestamp __ARGS((buf_T *buf));
|
||||||
void ml_recover __ARGS((void));
|
void ml_recover __ARGS((void));
|
||||||
int recover_names __ARGS((char_u **fname, int list, int nr));
|
int recover_names __ARGS((char_u *fname, int list, int nr, char_u **fname_out));
|
||||||
void ml_sync_all __ARGS((int check_file, int check_char));
|
void ml_sync_all __ARGS((int check_file, int check_char));
|
||||||
void ml_preserve __ARGS((buf_T *buf, int message));
|
void ml_preserve __ARGS((buf_T *buf, int message));
|
||||||
char_u *ml_get __ARGS((linenr_T lnum));
|
char_u *ml_get __ARGS((linenr_T lnum));
|
||||||
@ -29,6 +30,8 @@ int resolve_symlink __ARGS((char_u *fname, char_u *buf));
|
|||||||
char_u *makeswapname __ARGS((char_u *fname, char_u *ffname, buf_T *buf, char_u *dir_name));
|
char_u *makeswapname __ARGS((char_u *fname, char_u *ffname, buf_T *buf, char_u *dir_name));
|
||||||
char_u *get_file_in_dir __ARGS((char_u *fname, char_u *dname));
|
char_u *get_file_in_dir __ARGS((char_u *fname, char_u *dname));
|
||||||
void ml_setflags __ARGS((buf_T *buf));
|
void ml_setflags __ARGS((buf_T *buf));
|
||||||
|
char_u *ml_encrypt_data __ARGS((memfile_T *mfp, char_u *data, off_t offset, unsigned size));
|
||||||
|
void ml_decrypt_data __ARGS((memfile_T *mfp, char_u *data, off_t offset, unsigned size));
|
||||||
long ml_find_line_or_offset __ARGS((buf_T *buf, linenr_T lnum, long *offp));
|
long ml_find_line_or_offset __ARGS((buf_T *buf, linenr_T lnum, long *offp));
|
||||||
void goto_byte __ARGS((long cnt));
|
void goto_byte __ARGS((long cnt));
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@ -80,6 +80,8 @@ int illegal_slash __ARGS((char *name));
|
|||||||
char_u *parse_shape_opt __ARGS((int what));
|
char_u *parse_shape_opt __ARGS((int what));
|
||||||
int get_shape_idx __ARGS((int mouse));
|
int get_shape_idx __ARGS((int mouse));
|
||||||
void update_mouseshape __ARGS((int shape_idx));
|
void update_mouseshape __ARGS((int shape_idx));
|
||||||
|
void crypt_push_state __ARGS((void));
|
||||||
|
void crypt_pop_state __ARGS((void));
|
||||||
void crypt_encode __ARGS((char_u *from, size_t len, char_u *to));
|
void crypt_encode __ARGS((char_u *from, size_t len, char_u *to));
|
||||||
void crypt_decode __ARGS((char_u *ptr, long len));
|
void crypt_decode __ARGS((char_u *ptr, long len));
|
||||||
void crypt_init_keys __ARGS((char_u *passwd));
|
void crypt_init_keys __ARGS((char_u *passwd));
|
||||||
|
@ -402,7 +402,8 @@ get_some_time()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set header = sha2_seed(random_data);
|
* Fill "header[header_len]" with random_data.
|
||||||
|
* Also "salt[salt_len]" when "salt" is not NULL.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
sha2_seed(header, header_len, salt, salt_len)
|
sha2_seed(header, header_len, salt, salt_len)
|
||||||
@ -429,8 +430,9 @@ sha2_seed(header, header_len, salt, salt_len)
|
|||||||
header[i] = sha256sum[i % sizeof(sha256sum)];
|
header[i] = sha256sum[i % sizeof(sha256sum)];
|
||||||
|
|
||||||
/* put remaining block into salt. */
|
/* put remaining block into salt. */
|
||||||
for (i = 0; i < salt_len; i++)
|
if (salt != NULL)
|
||||||
salt[i] = sha256sum[(i + header_len) % sizeof(sha256sum)];
|
for (i = 0; i < salt_len; i++)
|
||||||
|
salt[i] = sha256sum[(i + header_len) % sizeof(sha256sum)];
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* FEAT_CRYPT */
|
#endif /* FEAT_CRYPT */
|
||||||
|
@ -392,7 +392,7 @@ struct block_hdr
|
|||||||
bhdr_T *bh_prev; /* previous block_hdr in used list */
|
bhdr_T *bh_prev; /* previous block_hdr in used list */
|
||||||
bhdr_T *bh_hash_next; /* next block_hdr in hash list */
|
bhdr_T *bh_hash_next; /* next block_hdr in hash list */
|
||||||
bhdr_T *bh_hash_prev; /* previous block_hdr in hash list */
|
bhdr_T *bh_hash_prev; /* previous block_hdr in hash list */
|
||||||
blocknr_T bh_bnum; /* block number */
|
blocknr_T bh_bnum; /* block number */
|
||||||
char_u *bh_data; /* pointer to memory (for used block) */
|
char_u *bh_data; /* pointer to memory (for used block) */
|
||||||
int bh_page_count; /* number of pages in this block */
|
int bh_page_count; /* number of pages in this block */
|
||||||
|
|
||||||
@ -491,12 +491,15 @@ typedef struct
|
|||||||
# endif
|
# endif
|
||||||
} cmdmod_T;
|
} cmdmod_T;
|
||||||
|
|
||||||
|
typedef struct file_buffer buf_T; /* forward declaration */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Simplistic hashing scheme to quickly locate the blocks in the used list.
|
* Simplistic hashing scheme to quickly locate the blocks in the used list.
|
||||||
* 64 blocks are found directly (64 * 4K = 256K, most files are smaller).
|
* 64 blocks are found directly (64 * 4K = 256K, most files are smaller).
|
||||||
*/
|
*/
|
||||||
#define MEMHASHSIZE 64
|
#define MEMHASHSIZE 64
|
||||||
#define MEMHASH(nr) ((nr) & (MEMHASHSIZE - 1))
|
#define MEMHASH(nr) ((nr) & (MEMHASHSIZE - 1))
|
||||||
|
#define MF_SEED_LEN 8
|
||||||
|
|
||||||
struct memfile
|
struct memfile
|
||||||
{
|
{
|
||||||
@ -516,6 +519,16 @@ struct memfile
|
|||||||
blocknr_T mf_infile_count; /* number of pages in the file */
|
blocknr_T mf_infile_count; /* number of pages in the file */
|
||||||
unsigned mf_page_size; /* number of bytes in a page */
|
unsigned mf_page_size; /* number of bytes in a page */
|
||||||
int mf_dirty; /* TRUE if there are dirty blocks */
|
int mf_dirty; /* TRUE if there are dirty blocks */
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
buf_T *mf_buffer; /* bufer this memfile is for */
|
||||||
|
char_u mf_seed[MF_SEED_LEN]; /* seed for encryption */
|
||||||
|
|
||||||
|
/* Values for key, method and seed used for reading data blocks when
|
||||||
|
* updating for a newly set key or method. Only when mf_old_key != NULL. */
|
||||||
|
char_u *mf_old_key;
|
||||||
|
int mf_old_cm;
|
||||||
|
char_u mf_old_seed[MF_SEED_LEN];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1229,8 +1242,6 @@ typedef struct {
|
|||||||
* A buffer is new if the associated file has never been loaded yet.
|
* A buffer is new if the associated file has never been loaded yet.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct file_buffer buf_T;
|
|
||||||
|
|
||||||
struct file_buffer
|
struct file_buffer
|
||||||
{
|
{
|
||||||
memline_T b_ml; /* associated memline (also contains line
|
memline_T b_ml; /* associated memline (also contains line
|
||||||
|
@ -6,7 +6,7 @@ STARTTEST
|
|||||||
:so small.vim
|
:so small.vim
|
||||||
:"
|
:"
|
||||||
:" Test 'undofile': first a simple one-line change.
|
:" Test 'undofile': first a simple one-line change.
|
||||||
:set nocp ul=100 undofile
|
:set nocp ul=100 undofile nomore
|
||||||
:e! Xtestfile
|
:e! Xtestfile
|
||||||
ggdGithis is one line:set ul=100
|
ggdGithis is one line:set ul=100
|
||||||
:s/one/ONE/
|
:s/one/ONE/
|
||||||
|
22
src/undo.c
22
src/undo.c
@ -886,7 +886,10 @@ serialize_header(fp, buf, hash)
|
|||||||
len = (int)fwrite(header, (size_t)header_len, (size_t)1, fp);
|
len = (int)fwrite(header, (size_t)header_len, (size_t)1, fp);
|
||||||
vim_free(header);
|
vim_free(header);
|
||||||
if (len != 1)
|
if (len != 1)
|
||||||
|
{
|
||||||
|
crypt_pop_state();
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -1240,6 +1243,9 @@ u_write_undo(name, forceit, buf, hash)
|
|||||||
struct stat st_old;
|
struct stat st_old;
|
||||||
struct stat st_new;
|
struct stat st_new;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
int do_crypt = FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
{
|
{
|
||||||
@ -1397,6 +1403,10 @@ u_write_undo(name, forceit, buf, hash)
|
|||||||
*/
|
*/
|
||||||
if (serialize_header(fp, buf, hash) == FAIL)
|
if (serialize_header(fp, buf, hash) == FAIL)
|
||||||
goto write_error;
|
goto write_error;
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
if (*buf->b_p_key)
|
||||||
|
do_crypt = TRUE;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iteratively serialize UHPs and their UEPs from the top down.
|
* Iteratively serialize UHPs and their UEPs from the top down.
|
||||||
@ -1462,6 +1472,10 @@ write_error:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
theend:
|
theend:
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
if (do_crypt)
|
||||||
|
crypt_pop_state();
|
||||||
|
#endif
|
||||||
if (file_name != name)
|
if (file_name != name)
|
||||||
vim_free(file_name);
|
vim_free(file_name);
|
||||||
}
|
}
|
||||||
@ -1505,6 +1519,9 @@ u_read_undo(name, hash, orig_name)
|
|||||||
struct stat st_orig;
|
struct stat st_orig;
|
||||||
struct stat st_undo;
|
struct stat st_undo;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
int do_decrypt = FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
{
|
{
|
||||||
@ -1572,6 +1589,7 @@ u_read_undo(name, hash, orig_name)
|
|||||||
EMSG2(_("E826: Undo file decryption failed: %s"), file_name);
|
EMSG2(_("E826: Undo file decryption failed: %s"), file_name);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
do_decrypt = TRUE;
|
||||||
#else
|
#else
|
||||||
EMSG2(_("E827: Undo file is encrypted: %s"), file_name);
|
EMSG2(_("E827: Undo file is encrypted: %s"), file_name);
|
||||||
goto error;
|
goto error;
|
||||||
@ -1776,6 +1794,10 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
theend:
|
theend:
|
||||||
|
#ifdef FEAT_CRYPT
|
||||||
|
if (do_decrypt)
|
||||||
|
crypt_pop_state();
|
||||||
|
#endif
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
if (file_name != name)
|
if (file_name != name)
|
||||||
|
@ -1304,13 +1304,15 @@ load_window(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifdef FEAT_WINDOWS
|
||||||
/* buf is in a window */
|
/* buf is in a window */
|
||||||
if (win != curwin)
|
if (win != curwin)
|
||||||
{
|
{
|
||||||
win_enter(win, False);
|
win_enter(win, False);
|
||||||
/* wsdebug("load_window: window endter %s\n",
|
/* wsdebug("load_window: window enter %s\n",
|
||||||
win->w_buffer->b_sfname); */
|
win->w_buffer->b_sfname); */
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (lnum > 0 && win->w_cursor.lnum != lnum)
|
if (lnum > 0 && win->w_cursor.lnum != lnum)
|
||||||
{
|
{
|
||||||
warp_to_pc(lnum);
|
warp_to_pc(lnum);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user