Mercurial > vim
comparison src/viminfo.c @ 18263:a5de1d88590d v8.1.2126
patch 8.1.2126: viminfo not sufficiently tested
Commit: https://github.com/vim/vim/commit/6bd1d7706766a7899904163e8fd55ea117fb1953
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Oct 9 22:01:25 2019 +0200
patch 8.1.2126: viminfo not sufficiently tested
Problem: Viminfo not sufficiently tested.
Solution: Add more test cases. Clean up comments. (Yegappan Lakshmanan,
closes #5032)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 09 Oct 2019 22:15:04 +0200 |
parents | 4d63d47d87ef |
children | 18d7337b6837 |
comparison
equal
deleted
inserted
replaced
18262:3050e95a3c73 | 18263:a5de1d88590d |
---|---|
11 * viminfo.c: viminfo related functions | 11 * viminfo.c: viminfo related functions |
12 */ | 12 */ |
13 | 13 |
14 #include "vim.h" | 14 #include "vim.h" |
15 #include "version.h" | 15 #include "version.h" |
16 | |
17 /* | |
18 * Structure used for reading from the viminfo file. | |
19 */ | |
20 typedef struct | |
21 { | |
22 char_u *vir_line; // text of the current line | |
23 FILE *vir_fd; // file descriptor | |
24 vimconv_T vir_conv; // encoding conversion | |
25 int vir_version; // viminfo version detected or -1 | |
26 garray_T vir_barlines; // lines starting with | | |
27 } vir_T; | |
16 | 28 |
17 #if defined(FEAT_VIMINFO) || defined(PROTO) | 29 #if defined(FEAT_VIMINFO) || defined(PROTO) |
18 | 30 |
19 static int viminfo_errcnt; | 31 static int viminfo_errcnt; |
20 | 32 |
820 type == HIST_INPUT ? _("Input Line") : | 832 type == HIST_INPUT ? _("Input Line") : |
821 _("Debug Line")); | 833 _("Debug Line")); |
822 if (num_saved > hislen) | 834 if (num_saved > hislen) |
823 num_saved = hislen; | 835 num_saved = hislen; |
824 | 836 |
825 /* | 837 // Merge typed and viminfo history: |
826 * Merge typed and viminfo history: | 838 // round 1: history of typed commands. |
827 * round 1: history of typed commands. | 839 // round 2: history from recently read viminfo. |
828 * round 2: history from recently read viminfo. | |
829 */ | |
830 for (round = 1; round <= 2; ++round) | 840 for (round = 1; round <= 2; ++round) |
831 { | 841 { |
832 if (round == 1) | 842 if (round == 1) |
833 // start at newest entry, somewhere in the list | 843 // start at newest entry, somewhere in the list |
834 i = *hisidx; | 844 i = *hisidx; |
2669 garray_T values; | 2679 garray_T values; |
2670 bval_T *vp; | 2680 bval_T *vp; |
2671 int i; | 2681 int i; |
2672 int read_next = TRUE; | 2682 int read_next = TRUE; |
2673 | 2683 |
2674 /* | 2684 // The format is: |{bartype},{value},... |
2675 * The format is: |{bartype},{value},... | 2685 // For a very long string: |
2676 * For a very long string: | 2686 // |{bartype},>{length of "{text}{text2}"} |
2677 * |{bartype},>{length of "{text}{text2}"} | 2687 // |<{text1} |
2678 * |<{text1} | 2688 // |<{text2},{value} |
2679 * |<{text2},{value} | 2689 // For a long line not using a string |
2680 * For a long line not using a string | 2690 // |{bartype},{lots of values},> |
2681 * |{bartype},{lots of values},> | 2691 // |<{value},{value} |
2682 * |<{value},{value} | |
2683 */ | |
2684 if (*p == '<') | 2692 if (*p == '<') |
2685 { | 2693 { |
2686 // Continuation line of an unrecognized item. | 2694 // Continuation line of an unrecognized item. |
2687 if (writing) | 2695 if (writing) |
2688 ga_add_string(&virp->vir_barlines, virp->vir_line); | 2696 ga_add_string(&virp->vir_barlines, virp->vir_line); |
3030 goto end; | 3038 goto end; |
3031 fp_out = fdopen(fd, WRITEBIN); | 3039 fp_out = fdopen(fd, WRITEBIN); |
3032 } | 3040 } |
3033 else | 3041 else |
3034 { | 3042 { |
3035 /* | 3043 // There is an existing viminfo file. Create a temporary file to |
3036 * There is an existing viminfo file. Create a temporary file to | 3044 // write the new viminfo into, in the same directory as the |
3037 * write the new viminfo into, in the same directory as the | 3045 // existing viminfo file, which will be renamed once all writing is |
3038 * existing viminfo file, which will be renamed once all writing is | 3046 // successful. |
3039 * successful. | |
3040 */ | |
3041 #ifdef UNIX | 3047 #ifdef UNIX |
3042 /* | 3048 // For Unix we check the owner of the file. It's not very nice to |
3043 * For Unix we check the owner of the file. It's not very nice to | 3049 // overwrite a user's viminfo file after a "su root", with a |
3044 * overwrite a user's viminfo file after a "su root", with a | 3050 // viminfo file that the user can't read. |
3045 * viminfo file that the user can't read. | |
3046 */ | |
3047 st_old.st_dev = (dev_t)0; | 3051 st_old.st_dev = (dev_t)0; |
3048 st_old.st_ino = 0; | 3052 st_old.st_ino = 0; |
3049 st_old.st_mode = 0600; | 3053 st_old.st_mode = 0600; |
3050 if (mch_stat((char *)fname, &st_old) == 0 | 3054 if (mch_stat((char *)fname, &st_old) == 0 |
3051 && getuid() != ROOT_UID | 3055 && getuid() != ROOT_UID |
3067 #ifdef MSWIN | 3071 #ifdef MSWIN |
3068 // Get the file attributes of the existing viminfo file. | 3072 // Get the file attributes of the existing viminfo file. |
3069 hidden = mch_ishidden(fname); | 3073 hidden = mch_ishidden(fname); |
3070 #endif | 3074 #endif |
3071 | 3075 |
3072 /* | 3076 // Make tempname, find one that does not exist yet. |
3073 * Make tempname, find one that does not exist yet. | 3077 // Beware of a race condition: If someone logs out and all Vim |
3074 * Beware of a race condition: If someone logs out and all Vim | 3078 // instances exit at the same time a temp file might be created between |
3075 * instances exit at the same time a temp file might be created between | 3079 // stat() and open(). Use mch_open() with O_EXCL to avoid that. |
3076 * stat() and open(). Use mch_open() with O_EXCL to avoid that. | 3080 // May try twice: Once normal and once with shortname set, just in |
3077 * May try twice: Once normal and once with shortname set, just in | 3081 // case somebody puts his viminfo file in an 8.3 filesystem. |
3078 * case somebody puts his viminfo file in an 8.3 filesystem. | |
3079 */ | |
3080 for (;;) | 3082 for (;;) |
3081 { | 3083 { |
3082 int next_char = 'z'; | 3084 int next_char = 'z'; |
3083 char_u *wp; | 3085 char_u *wp; |
3084 | 3086 |
3096 #endif | 3098 #endif |
3097 FALSE); | 3099 FALSE); |
3098 if (tempname == NULL) // out of memory | 3100 if (tempname == NULL) // out of memory |
3099 break; | 3101 break; |
3100 | 3102 |
3101 /* | 3103 // Try a series of names. Change one character, just before |
3102 * Try a series of names. Change one character, just before | 3104 // the extension. This should also work for an 8.3 |
3103 * the extension. This should also work for an 8.3 | 3105 // file name, when after adding the extension it still is |
3104 * file name, when after adding the extension it still is | 3106 // the same file as the original. |
3105 * the same file as the original. | |
3106 */ | |
3107 wp = tempname + STRLEN(tempname) - 5; | 3107 wp = tempname + STRLEN(tempname) - 5; |
3108 if (wp < gettail(tempname)) // empty file name? | 3108 if (wp < gettail(tempname)) // empty file name? |
3109 wp = gettail(tempname); | 3109 wp = gettail(tempname); |
3110 for (;;) | 3110 for (;;) |
3111 { | 3111 { |
3112 /* | 3112 // Check if tempfile already exists. Never overwrite an |
3113 * Check if tempfile already exists. Never overwrite an | 3113 // existing file! |
3114 * existing file! | |
3115 */ | |
3116 if (mch_stat((char *)tempname, &st_new) == 0) | 3114 if (mch_stat((char *)tempname, &st_new) == 0) |
3117 { | 3115 { |
3118 #ifdef UNIX | 3116 #ifdef UNIX |
3119 /* | 3117 // Check if tempfile is same as original file. May happen |
3120 * Check if tempfile is same as original file. May happen | 3118 // when modname() gave the same file back. E.g. silly |
3121 * when modname() gave the same file back. E.g. silly | 3119 // link, or file name-length reached. Try again with |
3122 * link, or file name-length reached. Try again with | 3120 // shortname set. |
3123 * shortname set. | |
3124 */ | |
3125 if (!shortname && st_new.st_dev == st_old.st_dev | 3121 if (!shortname && st_new.st_dev == st_old.st_dev |
3126 && st_new.st_ino == st_old.st_ino) | 3122 && st_new.st_ino == st_old.st_ino) |
3127 { | 3123 { |
3128 VIM_CLEAR(tempname); | 3124 VIM_CLEAR(tempname); |
3129 shortname = TRUE; | 3125 shortname = TRUE; |
3197 #if defined(UNIX) && defined(HAVE_FCHOWN) | 3193 #if defined(UNIX) && defined(HAVE_FCHOWN) |
3198 if (tempname != NULL && fp_out != NULL) | 3194 if (tempname != NULL && fp_out != NULL) |
3199 { | 3195 { |
3200 stat_T tmp_st; | 3196 stat_T tmp_st; |
3201 | 3197 |
3202 /* | 3198 // Make sure the original owner can read/write the tempfile and |
3203 * Make sure the original owner can read/write the tempfile and | 3199 // otherwise preserve permissions, making sure the group matches. |
3204 * otherwise preserve permissions, making sure the group matches. | |
3205 */ | |
3206 if (mch_stat((char *)tempname, &tmp_st) >= 0) | 3200 if (mch_stat((char *)tempname, &tmp_st) >= 0) |
3207 { | 3201 { |
3208 if (st_old.st_uid != tmp_st.st_uid) | 3202 if (st_old.st_uid != tmp_st.st_uid) |
3209 // Changing the owner might fail, in which case the | 3203 // Changing the owner might fail, in which case the |
3210 // file will now owned by the current user, oh well. | 3204 // file will now owned by the current user, oh well. |
3220 (void)mch_setperm(tempname, 0600); | 3214 (void)mch_setperm(tempname, 0600); |
3221 } | 3215 } |
3222 #endif | 3216 #endif |
3223 } | 3217 } |
3224 | 3218 |
3225 /* | 3219 // Check if the new viminfo file can be written to. |
3226 * Check if the new viminfo file can be written to. | |
3227 */ | |
3228 if (fp_out == NULL) | 3220 if (fp_out == NULL) |
3229 { | 3221 { |
3230 semsg(_("E138: Can't write viminfo file %s!"), | 3222 semsg(_("E138: Can't write viminfo file %s!"), |
3231 (fp_in == NULL || tempname == NULL) ? fname : tempname); | 3223 (fp_in == NULL || tempname == NULL) ? fname : tempname); |
3232 if (fp_in != NULL) | 3224 if (fp_in != NULL) |