blob: 3d3a410f9612a23e226f446f7dd0411274f55d69 [file] [log] [blame]
Bram Moolenaardefa0672019-07-21 19:25:37 +02001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * viminfo.c: viminfo related functions
12 */
13
14#include "vim.h"
15#include "version.h"
16
17#if defined(FEAT_VIMINFO) || defined(PROTO)
18
19static int viminfo_errcnt;
20
21/*
22 * Get the viminfo file name to use.
23 * If "file" is given and not empty, use it (has already been expanded by
24 * cmdline functions).
25 * Otherwise use "-i file_name", value from 'viminfo' or the default, and
26 * expand environment variables.
27 * Returns an allocated string. NULL when out of memory.
28 */
29 static char_u *
30viminfo_filename(char_u *file)
31{
32 if (file == NULL || *file == NUL)
33 {
34 if (*p_viminfofile != NUL)
35 file = p_viminfofile;
36 else if ((file = find_viminfo_parameter('n')) == NULL || *file == NUL)
37 {
38#ifdef VIMINFO_FILE2
39# ifdef VMS
40 if (mch_getenv((char_u *)"SYS$LOGIN") == NULL)
41# else
42# ifdef MSWIN
43 // Use $VIM only if $HOME is the default "C:/".
44 if (STRCMP(vim_getenv((char_u *)"HOME", NULL), "C:/") == 0
45 && mch_getenv((char_u *)"HOME") == NULL)
46# else
47 if (mch_getenv((char_u *)"HOME") == NULL)
48# endif
49# endif
50 {
51 // don't use $VIM when not available.
52 expand_env((char_u *)"$VIM", NameBuff, MAXPATHL);
53 if (STRCMP("$VIM", NameBuff) != 0) // $VIM was expanded
54 file = (char_u *)VIMINFO_FILE2;
55 else
56 file = (char_u *)VIMINFO_FILE;
57 }
58 else
59#endif
60 file = (char_u *)VIMINFO_FILE;
61 }
62 expand_env(file, NameBuff, MAXPATHL);
63 file = NameBuff;
64 }
65 return vim_strsave(file);
66}
67
68 static int
69read_viminfo_bufferlist(
70 vir_T *virp,
71 int writing)
72{
73 char_u *tab;
74 linenr_T lnum;
75 colnr_T col;
76 buf_T *buf;
77 char_u *sfname;
78 char_u *xline;
79
80 // Handle long line and escaped characters.
81 xline = viminfo_readstring(virp, 1, FALSE);
82
83 // don't read in if there are files on the command-line or if writing:
84 if (xline != NULL && !writing && ARGCOUNT == 0
85 && find_viminfo_parameter('%') != NULL)
86 {
87 // Format is: <fname> Tab <lnum> Tab <col>.
88 // Watch out for a Tab in the file name, work from the end.
89 lnum = 0;
90 col = 0;
91 tab = vim_strrchr(xline, '\t');
92 if (tab != NULL)
93 {
94 *tab++ = '\0';
95 col = (colnr_T)atoi((char *)tab);
96 tab = vim_strrchr(xline, '\t');
97 if (tab != NULL)
98 {
99 *tab++ = '\0';
100 lnum = atol((char *)tab);
101 }
102 }
103
104 // Expand "~/" in the file name at "line + 1" to a full path.
105 // Then try shortening it by comparing with the current directory
106 expand_env(xline, NameBuff, MAXPATHL);
107 sfname = shorten_fname1(NameBuff);
108
109 buf = buflist_new(NameBuff, sfname, (linenr_T)0, BLN_LISTED);
110 if (buf != NULL) // just in case...
111 {
112 buf->b_last_cursor.lnum = lnum;
113 buf->b_last_cursor.col = col;
114 buflist_setfpos(buf, curwin, lnum, col, FALSE);
115 }
116 }
117 vim_free(xline);
118
119 return viminfo_readline(virp);
120}
121
122 static void
123write_viminfo_bufferlist(FILE *fp)
124{
125 buf_T *buf;
126 win_T *win;
127 tabpage_T *tp;
128 char_u *line;
129 int max_buffers;
130
131 if (find_viminfo_parameter('%') == NULL)
132 return;
133
134 // Without a number -1 is returned: do all buffers.
135 max_buffers = get_viminfo_parameter('%');
136
137 // Allocate room for the file name, lnum and col.
138#define LINE_BUF_LEN (MAXPATHL + 40)
139 line = alloc(LINE_BUF_LEN);
140 if (line == NULL)
141 return;
142
143 FOR_ALL_TAB_WINDOWS(tp, win)
144 set_last_cursor(win);
145
146 fputs(_("\n# Buffer list:\n"), fp);
147 FOR_ALL_BUFFERS(buf)
148 {
149 if (buf->b_fname == NULL
150 || !buf->b_p_bl
151#ifdef FEAT_QUICKFIX
152 || bt_quickfix(buf)
153#endif
154#ifdef FEAT_TERMINAL
155 || bt_terminal(buf)
156#endif
157 || removable(buf->b_ffname))
158 continue;
159
160 if (max_buffers-- == 0)
161 break;
162 putc('%', fp);
163 home_replace(NULL, buf->b_ffname, line, MAXPATHL, TRUE);
164 vim_snprintf_add((char *)line, LINE_BUF_LEN, "\t%ld\t%d",
165 (long)buf->b_last_cursor.lnum,
166 buf->b_last_cursor.col);
167 viminfo_writestring(fp, line);
168 }
169 vim_free(line);
170}
171
172 static void
173write_viminfo_barlines(vir_T *virp, FILE *fp_out)
174{
175 int i;
176 garray_T *gap = &virp->vir_barlines;
177 int seen_useful = FALSE;
178 char *line;
179
180 if (gap->ga_len > 0)
181 {
182 fputs(_("\n# Bar lines, copied verbatim:\n"), fp_out);
183
184 // Skip over continuation lines until seeing a useful line.
185 for (i = 0; i < gap->ga_len; ++i)
186 {
187 line = ((char **)(gap->ga_data))[i];
188 if (seen_useful || line[1] != '<')
189 {
190 fputs(line, fp_out);
191 seen_useful = TRUE;
192 }
193 }
194 }
195}
196
197/*
198 * Parse a viminfo line starting with '|'.
199 * Add each decoded value to "values".
200 * Returns TRUE if the next line is to be read after using the parsed values.
201 */
202 static int
203barline_parse(vir_T *virp, char_u *text, garray_T *values)
204{
205 char_u *p = text;
206 char_u *nextp = NULL;
207 char_u *buf = NULL;
208 bval_T *value;
209 int i;
210 int allocated = FALSE;
211 int eof;
212 char_u *sconv;
213 int converted;
214
215 while (*p == ',')
216 {
217 ++p;
218 if (ga_grow(values, 1) == FAIL)
219 break;
220 value = (bval_T *)(values->ga_data) + values->ga_len;
221
222 if (*p == '>')
223 {
224 // Need to read a continuation line. Put strings in allocated
225 // memory, because virp->vir_line is overwritten.
226 if (!allocated)
227 {
228 for (i = 0; i < values->ga_len; ++i)
229 {
230 bval_T *vp = (bval_T *)(values->ga_data) + i;
231
232 if (vp->bv_type == BVAL_STRING && !vp->bv_allocated)
233 {
234 vp->bv_string = vim_strnsave(vp->bv_string, vp->bv_len);
235 vp->bv_allocated = TRUE;
236 }
237 }
238 allocated = TRUE;
239 }
240
241 if (vim_isdigit(p[1]))
242 {
243 size_t len;
244 size_t todo;
245 size_t n;
246
247 // String value was split into lines that are each shorter
248 // than LSIZE:
249 // |{bartype},>{length of "{text}{text2}"}
250 // |<"{text1}
251 // |<{text2}",{value}
252 // Length includes the quotes.
253 ++p;
254 len = getdigits(&p);
255 buf = alloc((int)(len + 1));
256 if (buf == NULL)
257 return TRUE;
258 p = buf;
259 for (todo = len; todo > 0; todo -= n)
260 {
261 eof = viminfo_readline(virp);
262 if (eof || virp->vir_line[0] != '|'
263 || virp->vir_line[1] != '<')
264 {
265 // File was truncated or garbled. Read another line if
266 // this one starts with '|'.
267 vim_free(buf);
268 return eof || virp->vir_line[0] == '|';
269 }
270 // Get length of text, excluding |< and NL chars.
271 n = STRLEN(virp->vir_line);
272 while (n > 0 && (virp->vir_line[n - 1] == NL
273 || virp->vir_line[n - 1] == CAR))
274 --n;
275 n -= 2;
276 if (n > todo)
277 {
278 // more values follow after the string
279 nextp = virp->vir_line + 2 + todo;
280 n = todo;
281 }
282 mch_memmove(p, virp->vir_line + 2, n);
283 p += n;
284 }
285 *p = NUL;
286 p = buf;
287 }
288 else
289 {
290 // Line ending in ">" continues in the next line:
291 // |{bartype},{lots of values},>
292 // |<{value},{value}
293 eof = viminfo_readline(virp);
294 if (eof || virp->vir_line[0] != '|'
295 || virp->vir_line[1] != '<')
296 // File was truncated or garbled. Read another line if
297 // this one starts with '|'.
298 return eof || virp->vir_line[0] == '|';
299 p = virp->vir_line + 2;
300 }
301 }
302
303 if (isdigit(*p))
304 {
305 value->bv_type = BVAL_NR;
306 value->bv_nr = getdigits(&p);
307 ++values->ga_len;
308 }
309 else if (*p == '"')
310 {
311 int len = 0;
312 char_u *s = p;
313
314 // Unescape special characters in-place.
315 ++p;
316 while (*p != '"')
317 {
318 if (*p == NL || *p == NUL)
319 return TRUE; // syntax error, drop the value
320 if (*p == '\\')
321 {
322 ++p;
323 if (*p == 'n')
324 s[len++] = '\n';
325 else
326 s[len++] = *p;
327 ++p;
328 }
329 else
330 s[len++] = *p++;
331 }
332 ++p;
333 s[len] = NUL;
334
335 converted = FALSE;
336 if (virp->vir_conv.vc_type != CONV_NONE && *s != NUL)
337 {
338 sconv = string_convert(&virp->vir_conv, s, NULL);
339 if (sconv != NULL)
340 {
341 if (s == buf)
342 vim_free(s);
343 s = sconv;
344 buf = s;
345 converted = TRUE;
346 }
347 }
348
349 // Need to copy in allocated memory if the string wasn't allocated
350 // above and we did allocate before, thus vir_line may change.
351 if (s != buf && allocated)
352 s = vim_strsave(s);
353 value->bv_string = s;
354 value->bv_type = BVAL_STRING;
355 value->bv_len = len;
356 value->bv_allocated = allocated || converted;
357 ++values->ga_len;
358 if (nextp != NULL)
359 {
360 // values following a long string
361 p = nextp;
362 nextp = NULL;
363 }
364 }
365 else if (*p == ',')
366 {
367 value->bv_type = BVAL_EMPTY;
368 ++values->ga_len;
369 }
370 else
371 break;
372 }
373 return TRUE;
374}
375
376 static int
377read_viminfo_barline(vir_T *virp, int got_encoding, int force, int writing)
378{
379 char_u *p = virp->vir_line + 1;
380 int bartype;
381 garray_T values;
382 bval_T *vp;
383 int i;
384 int read_next = TRUE;
385
386 /*
387 * The format is: |{bartype},{value},...
388 * For a very long string:
389 * |{bartype},>{length of "{text}{text2}"}
390 * |<{text1}
391 * |<{text2},{value}
392 * For a long line not using a string
393 * |{bartype},{lots of values},>
394 * |<{value},{value}
395 */
396 if (*p == '<')
397 {
398 // Continuation line of an unrecognized item.
399 if (writing)
400 ga_add_string(&virp->vir_barlines, virp->vir_line);
401 }
402 else
403 {
404 ga_init2(&values, sizeof(bval_T), 20);
405 bartype = getdigits(&p);
406 switch (bartype)
407 {
408 case BARTYPE_VERSION:
409 // Only use the version when it comes before the encoding.
410 // If it comes later it was copied by a Vim version that
411 // doesn't understand the version.
412 if (!got_encoding)
413 {
414 read_next = barline_parse(virp, p, &values);
415 vp = (bval_T *)values.ga_data;
416 if (values.ga_len > 0 && vp->bv_type == BVAL_NR)
417 virp->vir_version = vp->bv_nr;
418 }
419 break;
420
421 case BARTYPE_HISTORY:
422 read_next = barline_parse(virp, p, &values);
423 handle_viminfo_history(&values, writing);
424 break;
425
426 case BARTYPE_REGISTER:
427 read_next = barline_parse(virp, p, &values);
428 handle_viminfo_register(&values, force);
429 break;
430
431 case BARTYPE_MARK:
432 read_next = barline_parse(virp, p, &values);
433 handle_viminfo_mark(&values, force);
434 break;
435
436 default:
437 // copy unrecognized line (for future use)
438 if (writing)
439 ga_add_string(&virp->vir_barlines, virp->vir_line);
440 }
441 for (i = 0; i < values.ga_len; ++i)
442 {
443 vp = (bval_T *)values.ga_data + i;
444 if (vp->bv_type == BVAL_STRING && vp->bv_allocated)
445 vim_free(vp->bv_string);
446 }
447 ga_clear(&values);
448 }
449
450 if (read_next)
451 return viminfo_readline(virp);
452 return FALSE;
453}
454
455 static void
456write_viminfo_version(FILE *fp_out)
457{
458 fprintf(fp_out, "# Viminfo version\n|%d,%d\n\n",
459 BARTYPE_VERSION, VIMINFO_VERSION);
460}
461
462 static int
463no_viminfo(void)
464{
465 // "vim -i NONE" does not read or write a viminfo file
466 return STRCMP(p_viminfofile, "NONE") == 0;
467}
468
469/*
470 * Report an error for reading a viminfo file.
471 * Count the number of errors. When there are more than 10, return TRUE.
472 */
473 int
474viminfo_error(char *errnum, char *message, char_u *line)
475{
476 vim_snprintf((char *)IObuff, IOSIZE, _("%sviminfo: %s in line: "),
477 errnum, message);
478 STRNCAT(IObuff, line, IOSIZE - STRLEN(IObuff) - 1);
479 if (IObuff[STRLEN(IObuff) - 1] == '\n')
480 IObuff[STRLEN(IObuff) - 1] = NUL;
481 emsg((char *)IObuff);
482 if (++viminfo_errcnt >= 10)
483 {
484 emsg(_("E136: viminfo: Too many errors, skipping rest of file"));
485 return TRUE;
486 }
487 return FALSE;
488}
489
490/*
491 * Compare the 'encoding' value in the viminfo file with the current value of
492 * 'encoding'. If different and the 'c' flag is in 'viminfo', setup for
493 * conversion of text with iconv() in viminfo_readstring().
494 */
495 static int
496viminfo_encoding(vir_T *virp)
497{
498 char_u *p;
499 int i;
500
501 if (get_viminfo_parameter('c') != 0)
502 {
503 p = vim_strchr(virp->vir_line, '=');
504 if (p != NULL)
505 {
506 // remove trailing newline
507 ++p;
508 for (i = 0; vim_isprintc(p[i]); ++i)
509 ;
510 p[i] = NUL;
511
512 convert_setup(&virp->vir_conv, p, p_enc);
513 }
514 }
515 return viminfo_readline(virp);
516}
517
518#if defined(FEAT_EVAL) || defined(PROTO)
519/*
520 * Restore global vars that start with a capital from the viminfo file
521 */
522 static int
523read_viminfo_varlist(vir_T *virp, int writing)
524{
525 char_u *tab;
526 int type = VAR_NUMBER;
527 typval_T tv;
528 funccal_entry_T funccal_entry;
529
530 if (!writing && (find_viminfo_parameter('!') != NULL))
531 {
532 tab = vim_strchr(virp->vir_line + 1, '\t');
533 if (tab != NULL)
534 {
535 *tab++ = '\0'; // isolate the variable name
536 switch (*tab)
537 {
538 case 'S': type = VAR_STRING; break;
539#ifdef FEAT_FLOAT
540 case 'F': type = VAR_FLOAT; break;
541#endif
542 case 'D': type = VAR_DICT; break;
543 case 'L': type = VAR_LIST; break;
544 case 'B': type = VAR_BLOB; break;
545 case 'X': type = VAR_SPECIAL; break;
546 }
547
548 tab = vim_strchr(tab, '\t');
549 if (tab != NULL)
550 {
551 tv.v_type = type;
552 if (type == VAR_STRING || type == VAR_DICT
553 || type == VAR_LIST || type == VAR_BLOB)
554 tv.vval.v_string = viminfo_readstring(virp,
555 (int)(tab - virp->vir_line + 1), TRUE);
556#ifdef FEAT_FLOAT
557 else if (type == VAR_FLOAT)
558 (void)string2float(tab + 1, &tv.vval.v_float);
559#endif
560 else
561 tv.vval.v_number = atol((char *)tab + 1);
562 if (type == VAR_DICT || type == VAR_LIST)
563 {
564 typval_T *etv = eval_expr(tv.vval.v_string, NULL);
565
566 if (etv == NULL)
567 // Failed to parse back the dict or list, use it as a
568 // string.
569 tv.v_type = VAR_STRING;
570 else
571 {
572 vim_free(tv.vval.v_string);
573 tv = *etv;
574 vim_free(etv);
575 }
576 }
577 else if (type == VAR_BLOB)
578 {
579 blob_T *blob = string2blob(tv.vval.v_string);
580
581 if (blob == NULL)
582 // Failed to parse back the blob, use it as a string.
583 tv.v_type = VAR_STRING;
584 else
585 {
586 vim_free(tv.vval.v_string);
587 tv.v_type = VAR_BLOB;
588 tv.vval.v_blob = blob;
589 }
590 }
591
592 // when in a function use global variables
593 save_funccal(&funccal_entry);
594 set_var(virp->vir_line + 1, &tv, FALSE);
595 restore_funccal();
596
597 if (tv.v_type == VAR_STRING)
598 vim_free(tv.vval.v_string);
599 else if (tv.v_type == VAR_DICT || tv.v_type == VAR_LIST ||
600 tv.v_type == VAR_BLOB)
601 clear_tv(&tv);
602 }
603 }
604 }
605
606 return viminfo_readline(virp);
607}
608
609/*
610 * Write global vars that start with a capital to the viminfo file
611 */
612 static void
613write_viminfo_varlist(FILE *fp)
614{
615 hashitem_T *hi;
616 dictitem_T *this_var;
617 int todo;
618 char *s = "";
619 char_u *p;
620 char_u *tofree;
621 char_u numbuf[NUMBUFLEN];
622
623 if (find_viminfo_parameter('!') == NULL)
624 return;
625
626 fputs(_("\n# global variables:\n"), fp);
627
628 todo = (int)globvarht.ht_used;
629 for (hi = globvarht.ht_array; todo > 0; ++hi)
630 {
631 if (!HASHITEM_EMPTY(hi))
632 {
633 --todo;
634 this_var = HI2DI(hi);
635 if (var_flavour(this_var->di_key) == VAR_FLAVOUR_VIMINFO)
636 {
637 switch (this_var->di_tv.v_type)
638 {
639 case VAR_STRING: s = "STR"; break;
640 case VAR_NUMBER: s = "NUM"; break;
641 case VAR_FLOAT: s = "FLO"; break;
642 case VAR_DICT: s = "DIC"; break;
643 case VAR_LIST: s = "LIS"; break;
644 case VAR_BLOB: s = "BLO"; break;
645 case VAR_SPECIAL: s = "XPL"; break;
646
647 case VAR_UNKNOWN:
648 case VAR_FUNC:
649 case VAR_PARTIAL:
650 case VAR_JOB:
651 case VAR_CHANNEL:
652 continue;
653 }
654 fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
655 if (this_var->di_tv.v_type == VAR_SPECIAL)
656 {
657 sprintf((char *)numbuf, "%ld",
658 (long)this_var->di_tv.vval.v_number);
659 p = numbuf;
660 tofree = NULL;
661 }
662 else
663 p = echo_string(&this_var->di_tv, &tofree, numbuf, 0);
664 if (p != NULL)
665 viminfo_writestring(fp, p);
666 vim_free(tofree);
667 }
668 }
669 }
670}
671#endif // FEAT_EVAL
672
673/*
674 * read_viminfo_up_to_marks() -- Only called from do_viminfo(). Reads in the
675 * first part of the viminfo file which contains everything but the marks that
676 * are local to a file. Returns TRUE when end-of-file is reached. -- webb
677 */
678 static int
679read_viminfo_up_to_marks(
680 vir_T *virp,
681 int forceit,
682 int writing)
683{
684 int eof;
685 buf_T *buf;
686 int got_encoding = FALSE;
687
688#ifdef FEAT_CMDHIST
689 prepare_viminfo_history(forceit ? 9999 : 0, writing);
690#endif
691
692 eof = viminfo_readline(virp);
693 while (!eof && virp->vir_line[0] != '>')
694 {
695 switch (virp->vir_line[0])
696 {
697 // Characters reserved for future expansion, ignored now
698 case '+': // "+40 /path/dir file", for running vim without args
699 case '^': // to be defined
700 case '<': // long line - ignored
701 // A comment or empty line.
702 case NUL:
703 case '\r':
704 case '\n':
705 case '#':
706 eof = viminfo_readline(virp);
707 break;
708 case '|':
709 eof = read_viminfo_barline(virp, got_encoding,
710 forceit, writing);
711 break;
712 case '*': // "*encoding=value"
713 got_encoding = TRUE;
714 eof = viminfo_encoding(virp);
715 break;
716 case '!': // global variable
717#ifdef FEAT_EVAL
718 eof = read_viminfo_varlist(virp, writing);
719#else
720 eof = viminfo_readline(virp);
721#endif
722 break;
723 case '%': // entry for buffer list
724 eof = read_viminfo_bufferlist(virp, writing);
725 break;
726 case '"':
727 // When registers are in bar lines skip the old style register
728 // lines.
729 if (virp->vir_version < VIMINFO_VERSION_WITH_REGISTERS)
730 eof = read_viminfo_register(virp, forceit);
731 else
732 do {
733 eof = viminfo_readline(virp);
734 } while (!eof && (virp->vir_line[0] == TAB
735 || virp->vir_line[0] == '<'));
736 break;
737 case '/': // Search string
738 case '&': // Substitute search string
739 case '~': // Last search string, followed by '/' or '&'
740 eof = read_viminfo_search_pattern(virp, forceit);
741 break;
742 case '$':
743 eof = read_viminfo_sub_string(virp, forceit);
744 break;
745 case ':':
746 case '?':
747 case '=':
748 case '@':
749#ifdef FEAT_CMDHIST
750 // When history is in bar lines skip the old style history
751 // lines.
752 if (virp->vir_version < VIMINFO_VERSION_WITH_HISTORY)
753 eof = read_viminfo_history(virp, writing);
754 else
755#endif
756 eof = viminfo_readline(virp);
757 break;
758 case '-':
759 case '\'':
760 // When file marks are in bar lines skip the old style lines.
761 if (virp->vir_version < VIMINFO_VERSION_WITH_MARKS)
762 eof = read_viminfo_filemark(virp, forceit);
763 else
764 eof = viminfo_readline(virp);
765 break;
766 default:
767 if (viminfo_error("E575: ", _("Illegal starting char"),
768 virp->vir_line))
769 eof = TRUE;
770 else
771 eof = viminfo_readline(virp);
772 break;
773 }
774 }
775
776#ifdef FEAT_CMDHIST
777 // Finish reading history items.
778 if (!writing)
779 finish_viminfo_history(virp);
780#endif
781
782 // Change file names to buffer numbers for fmarks.
783 FOR_ALL_BUFFERS(buf)
784 fmarks_check_names(buf);
785
786 return eof;
787}
788
789/*
790 * do_viminfo() -- Should only be called from read_viminfo() & write_viminfo().
791 */
792 static void
793do_viminfo(FILE *fp_in, FILE *fp_out, int flags)
794{
795 int eof = FALSE;
796 vir_T vir;
797 int merge = FALSE;
798 int do_copy_marks = FALSE;
799 garray_T buflist;
800
801 if ((vir.vir_line = alloc(LSIZE)) == NULL)
802 return;
803 vir.vir_fd = fp_in;
804 vir.vir_conv.vc_type = CONV_NONE;
805 ga_init2(&vir.vir_barlines, (int)sizeof(char_u *), 100);
806 vir.vir_version = -1;
807
808 if (fp_in != NULL)
809 {
810 if (flags & VIF_WANT_INFO)
811 {
812 if (fp_out != NULL)
813 {
814 // Registers and marks are read and kept separate from what
815 // this Vim is using. They are merged when writing.
816 prepare_viminfo_registers();
817 prepare_viminfo_marks();
818 }
819
820 eof = read_viminfo_up_to_marks(&vir,
821 flags & VIF_FORCEIT, fp_out != NULL);
822 merge = TRUE;
823 }
824 else if (flags != 0)
825 // Skip info, find start of marks
826 while (!(eof = viminfo_readline(&vir))
827 && vir.vir_line[0] != '>')
828 ;
829
830 do_copy_marks = (flags &
831 (VIF_WANT_MARKS | VIF_GET_OLDFILES | VIF_FORCEIT));
832 }
833
834 if (fp_out != NULL)
835 {
836 // Write the info:
837 fprintf(fp_out, _("# This viminfo file was generated by Vim %s.\n"),
838 VIM_VERSION_MEDIUM);
839 fputs(_("# You may edit it if you're careful!\n\n"), fp_out);
840 write_viminfo_version(fp_out);
841 fputs(_("# Value of 'encoding' when this file was written\n"), fp_out);
842 fprintf(fp_out, "*encoding=%s\n\n", p_enc);
843 write_viminfo_search_pattern(fp_out);
844 write_viminfo_sub_string(fp_out);
845#ifdef FEAT_CMDHIST
846 write_viminfo_history(fp_out, merge);
847#endif
848 write_viminfo_registers(fp_out);
849 finish_viminfo_registers();
850#ifdef FEAT_EVAL
851 write_viminfo_varlist(fp_out);
852#endif
853 write_viminfo_filemarks(fp_out);
854 finish_viminfo_marks();
855 write_viminfo_bufferlist(fp_out);
856 write_viminfo_barlines(&vir, fp_out);
857
858 if (do_copy_marks)
859 ga_init2(&buflist, sizeof(buf_T *), 50);
860 write_viminfo_marks(fp_out, do_copy_marks ? &buflist : NULL);
861 }
862
863 if (do_copy_marks)
864 {
865 copy_viminfo_marks(&vir, fp_out, &buflist, eof, flags);
866 if (fp_out != NULL)
867 ga_clear(&buflist);
868 }
869
870 vim_free(vir.vir_line);
871 if (vir.vir_conv.vc_type != CONV_NONE)
872 convert_setup(&vir.vir_conv, NULL, NULL);
873 ga_clear_strings(&vir.vir_barlines);
874}
875
876/*
877 * read_viminfo() -- Read the viminfo file. Registers etc. which are already
878 * set are not over-written unless "flags" includes VIF_FORCEIT. -- webb
879 */
880 int
881read_viminfo(
882 char_u *file, // file name or NULL to use default name
883 int flags) // VIF_WANT_INFO et al.
884{
885 FILE *fp;
886 char_u *fname;
887
888 if (no_viminfo())
889 return FAIL;
890
891 fname = viminfo_filename(file); // get file name in allocated buffer
892 if (fname == NULL)
893 return FAIL;
894 fp = mch_fopen((char *)fname, READBIN);
895
896 if (p_verbose > 0)
897 {
898 verbose_enter();
899 smsg(_("Reading viminfo file \"%s\"%s%s%s"),
900 fname,
901 (flags & VIF_WANT_INFO) ? _(" info") : "",
902 (flags & VIF_WANT_MARKS) ? _(" marks") : "",
903 (flags & VIF_GET_OLDFILES) ? _(" oldfiles") : "",
904 fp == NULL ? _(" FAILED") : "");
905 verbose_leave();
906 }
907
908 vim_free(fname);
909 if (fp == NULL)
910 return FAIL;
911
912 viminfo_errcnt = 0;
913 do_viminfo(fp, NULL, flags);
914
915 fclose(fp);
916 return OK;
917}
918
919/*
920 * Write the viminfo file. The old one is read in first so that effectively a
921 * merge of current info and old info is done. This allows multiple vims to
922 * run simultaneously, without losing any marks etc.
923 * If "forceit" is TRUE, then the old file is not read in, and only internal
924 * info is written to the file.
925 */
926 void
927write_viminfo(char_u *file, int forceit)
928{
929 char_u *fname;
930 FILE *fp_in = NULL; // input viminfo file, if any
931 FILE *fp_out = NULL; // output viminfo file
932 char_u *tempname = NULL; // name of temp viminfo file
933 stat_T st_new; // mch_stat() of potential new file
934#if defined(UNIX) || defined(VMS)
935 mode_t umask_save;
936#endif
937#ifdef UNIX
938 int shortname = FALSE; // use 8.3 file name
939 stat_T st_old; // mch_stat() of existing viminfo file
940#endif
941#ifdef MSWIN
942 int hidden = FALSE;
943#endif
944
945 if (no_viminfo())
946 return;
947
948 fname = viminfo_filename(file); // may set to default if NULL
949 if (fname == NULL)
950 return;
951
952 fp_in = mch_fopen((char *)fname, READBIN);
953 if (fp_in == NULL)
954 {
955 int fd;
956
957 // if it does exist, but we can't read it, don't try writing
958 if (mch_stat((char *)fname, &st_new) == 0)
959 goto end;
960
961 // Create the new .viminfo non-accessible for others, because it may
962 // contain text from non-accessible documents. It is up to the user to
963 // widen access (e.g. to a group). This may also fail if there is a
964 // race condition, then just give up.
965 fd = mch_open((char *)fname,
966 O_CREAT|O_EXTRA|O_EXCL|O_WRONLY|O_NOFOLLOW, 0600);
967 if (fd < 0)
968 goto end;
969 fp_out = fdopen(fd, WRITEBIN);
970 }
971 else
972 {
973 /*
974 * There is an existing viminfo file. Create a temporary file to
975 * write the new viminfo into, in the same directory as the
976 * existing viminfo file, which will be renamed once all writing is
977 * successful.
978 */
979#ifdef UNIX
980 /*
981 * For Unix we check the owner of the file. It's not very nice to
982 * overwrite a user's viminfo file after a "su root", with a
983 * viminfo file that the user can't read.
984 */
985 st_old.st_dev = (dev_t)0;
986 st_old.st_ino = 0;
987 st_old.st_mode = 0600;
988 if (mch_stat((char *)fname, &st_old) == 0
989 && getuid() != ROOT_UID
990 && !(st_old.st_uid == getuid()
991 ? (st_old.st_mode & 0200)
992 : (st_old.st_gid == getgid()
993 ? (st_old.st_mode & 0020)
994 : (st_old.st_mode & 0002))))
995 {
996 int tt = msg_didany;
997
998 // avoid a wait_return for this message, it's annoying
999 semsg(_("E137: Viminfo file is not writable: %s"), fname);
1000 msg_didany = tt;
1001 fclose(fp_in);
1002 goto end;
1003 }
1004#endif
1005#ifdef MSWIN
1006 // Get the file attributes of the existing viminfo file.
1007 hidden = mch_ishidden(fname);
1008#endif
1009
1010 /*
1011 * Make tempname, find one that does not exist yet.
1012 * Beware of a race condition: If someone logs out and all Vim
1013 * instances exit at the same time a temp file might be created between
1014 * stat() and open(). Use mch_open() with O_EXCL to avoid that.
1015 * May try twice: Once normal and once with shortname set, just in
1016 * case somebody puts his viminfo file in an 8.3 filesystem.
1017 */
1018 for (;;)
1019 {
1020 int next_char = 'z';
1021 char_u *wp;
1022
1023 tempname = buf_modname(
1024#ifdef UNIX
1025 shortname,
1026#else
1027 FALSE,
1028#endif
1029 fname,
1030#ifdef VMS
1031 (char_u *)"-tmp",
1032#else
1033 (char_u *)".tmp",
1034#endif
1035 FALSE);
1036 if (tempname == NULL) // out of memory
1037 break;
1038
1039 /*
1040 * Try a series of names. Change one character, just before
1041 * the extension. This should also work for an 8.3
1042 * file name, when after adding the extension it still is
1043 * the same file as the original.
1044 */
1045 wp = tempname + STRLEN(tempname) - 5;
1046 if (wp < gettail(tempname)) // empty file name?
1047 wp = gettail(tempname);
1048 for (;;)
1049 {
1050 /*
1051 * Check if tempfile already exists. Never overwrite an
1052 * existing file!
1053 */
1054 if (mch_stat((char *)tempname, &st_new) == 0)
1055 {
1056#ifdef UNIX
1057 /*
1058 * Check if tempfile is same as original file. May happen
1059 * when modname() gave the same file back. E.g. silly
1060 * link, or file name-length reached. Try again with
1061 * shortname set.
1062 */
1063 if (!shortname && st_new.st_dev == st_old.st_dev
1064 && st_new.st_ino == st_old.st_ino)
1065 {
1066 VIM_CLEAR(tempname);
1067 shortname = TRUE;
1068 break;
1069 }
1070#endif
1071 }
1072 else
1073 {
1074 // Try creating the file exclusively. This may fail if
1075 // another Vim tries to do it at the same time.
1076#ifdef VMS
1077 // fdopen() fails for some reason
1078 umask_save = umask(077);
1079 fp_out = mch_fopen((char *)tempname, WRITEBIN);
1080 (void)umask(umask_save);
1081#else
1082 int fd;
1083
1084 // Use mch_open() to be able to use O_NOFOLLOW and set file
1085 // protection:
1086 // Unix: same as original file, but strip s-bit. Reset
1087 // umask to avoid it getting in the way.
1088 // Others: r&w for user only.
1089# ifdef UNIX
1090 umask_save = umask(0);
1091 fd = mch_open((char *)tempname,
1092 O_CREAT|O_EXTRA|O_EXCL|O_WRONLY|O_NOFOLLOW,
1093 (int)((st_old.st_mode & 0777) | 0600));
1094 (void)umask(umask_save);
1095# else
1096 fd = mch_open((char *)tempname,
1097 O_CREAT|O_EXTRA|O_EXCL|O_WRONLY|O_NOFOLLOW, 0600);
1098# endif
1099 if (fd < 0)
1100 {
1101 fp_out = NULL;
1102# ifdef EEXIST
1103 // Avoid trying lots of names while the problem is lack
1104 // of permission, only retry if the file already
1105 // exists.
1106 if (errno != EEXIST)
1107 break;
1108# endif
1109 }
1110 else
1111 fp_out = fdopen(fd, WRITEBIN);
1112#endif // VMS
1113 if (fp_out != NULL)
1114 break;
1115 }
1116
1117 // Assume file exists, try again with another name.
1118 if (next_char == 'a' - 1)
1119 {
1120 // They all exist? Must be something wrong! Don't write
1121 // the viminfo file then.
1122 semsg(_("E929: Too many viminfo temp files, like %s!"),
1123 tempname);
1124 break;
1125 }
1126 *wp = next_char;
1127 --next_char;
1128 }
1129
1130 if (tempname != NULL)
1131 break;
1132 // continue if shortname was set
1133 }
1134
1135#if defined(UNIX) && defined(HAVE_FCHOWN)
1136 if (tempname != NULL && fp_out != NULL)
1137 {
1138 stat_T tmp_st;
1139
1140 /*
1141 * Make sure the original owner can read/write the tempfile and
1142 * otherwise preserve permissions, making sure the group matches.
1143 */
1144 if (mch_stat((char *)tempname, &tmp_st) >= 0)
1145 {
1146 if (st_old.st_uid != tmp_st.st_uid)
1147 // Changing the owner might fail, in which case the
1148 // file will now owned by the current user, oh well.
1149 vim_ignored = fchown(fileno(fp_out), st_old.st_uid, -1);
1150 if (st_old.st_gid != tmp_st.st_gid
1151 && fchown(fileno(fp_out), -1, st_old.st_gid) == -1)
1152 // can't set the group to what it should be, remove
1153 // group permissions
1154 (void)mch_setperm(tempname, 0600);
1155 }
1156 else
1157 // can't stat the file, set conservative permissions
1158 (void)mch_setperm(tempname, 0600);
1159 }
1160#endif
1161 }
1162
1163 /*
1164 * Check if the new viminfo file can be written to.
1165 */
1166 if (fp_out == NULL)
1167 {
1168 semsg(_("E138: Can't write viminfo file %s!"),
1169 (fp_in == NULL || tempname == NULL) ? fname : tempname);
1170 if (fp_in != NULL)
1171 fclose(fp_in);
1172 goto end;
1173 }
1174
1175 if (p_verbose > 0)
1176 {
1177 verbose_enter();
1178 smsg(_("Writing viminfo file \"%s\""), fname);
1179 verbose_leave();
1180 }
1181
1182 viminfo_errcnt = 0;
1183 do_viminfo(fp_in, fp_out, forceit ? 0 : (VIF_WANT_INFO | VIF_WANT_MARKS));
1184
1185 if (fclose(fp_out) == EOF)
1186 ++viminfo_errcnt;
1187
1188 if (fp_in != NULL)
1189 {
1190 fclose(fp_in);
1191
1192 // In case of an error keep the original viminfo file. Otherwise
1193 // rename the newly written file. Give an error if that fails.
1194 if (viminfo_errcnt == 0)
1195 {
1196 if (vim_rename(tempname, fname) == -1)
1197 {
1198 ++viminfo_errcnt;
1199 semsg(_("E886: Can't rename viminfo file to %s!"), fname);
1200 }
1201# ifdef MSWIN
1202 // If the viminfo file was hidden then also hide the new file.
1203 else if (hidden)
1204 mch_hide(fname);
1205# endif
1206 }
1207 if (viminfo_errcnt > 0)
1208 mch_remove(tempname);
1209 }
1210
1211end:
1212 vim_free(fname);
1213 vim_free(tempname);
1214}
1215
1216/*
1217 * Read a line from the viminfo file.
1218 * Returns TRUE for end-of-file;
1219 */
1220 int
1221viminfo_readline(vir_T *virp)
1222{
1223 return vim_fgets(virp->vir_line, LSIZE, virp->vir_fd);
1224}
1225
1226/*
1227 * Check string read from viminfo file.
1228 * Remove '\n' at the end of the line.
1229 * - replace CTRL-V CTRL-V with CTRL-V
1230 * - replace CTRL-V 'n' with '\n'
1231 *
1232 * Check for a long line as written by viminfo_writestring().
1233 *
1234 * Return the string in allocated memory (NULL when out of memory).
1235 */
1236 char_u *
1237viminfo_readstring(
1238 vir_T *virp,
1239 int off, // offset for virp->vir_line
1240 int convert UNUSED) // convert the string
1241{
1242 char_u *retval;
1243 char_u *s, *d;
1244 long len;
1245
1246 if (virp->vir_line[off] == Ctrl_V && vim_isdigit(virp->vir_line[off + 1]))
1247 {
1248 len = atol((char *)virp->vir_line + off + 1);
1249 retval = lalloc(len, TRUE);
1250 if (retval == NULL)
1251 {
1252 // Line too long? File messed up? Skip next line.
1253 (void)vim_fgets(virp->vir_line, 10, virp->vir_fd);
1254 return NULL;
1255 }
1256 (void)vim_fgets(retval, (int)len, virp->vir_fd);
1257 s = retval + 1; // Skip the leading '<'
1258 }
1259 else
1260 {
1261 retval = vim_strsave(virp->vir_line + off);
1262 if (retval == NULL)
1263 return NULL;
1264 s = retval;
1265 }
1266
1267 // Change CTRL-V CTRL-V to CTRL-V and CTRL-V n to \n in-place.
1268 d = retval;
1269 while (*s != NUL && *s != '\n')
1270 {
1271 if (s[0] == Ctrl_V && s[1] != NUL)
1272 {
1273 if (s[1] == 'n')
1274 *d++ = '\n';
1275 else
1276 *d++ = Ctrl_V;
1277 s += 2;
1278 }
1279 else
1280 *d++ = *s++;
1281 }
1282 *d = NUL;
1283
1284 if (convert && virp->vir_conv.vc_type != CONV_NONE && *retval != NUL)
1285 {
1286 d = string_convert(&virp->vir_conv, retval, NULL);
1287 if (d != NULL)
1288 {
1289 vim_free(retval);
1290 retval = d;
1291 }
1292 }
1293
1294 return retval;
1295}
1296
1297/*
1298 * write string to viminfo file
1299 * - replace CTRL-V with CTRL-V CTRL-V
1300 * - replace '\n' with CTRL-V 'n'
1301 * - add a '\n' at the end
1302 *
1303 * For a long line:
1304 * - write " CTRL-V <length> \n " in first line
1305 * - write " < <string> \n " in second line
1306 */
1307 void
1308viminfo_writestring(FILE *fd, char_u *p)
1309{
1310 int c;
1311 char_u *s;
1312 int len = 0;
1313
1314 for (s = p; *s != NUL; ++s)
1315 {
1316 if (*s == Ctrl_V || *s == '\n')
1317 ++len;
1318 ++len;
1319 }
1320
1321 // If the string will be too long, write its length and put it in the next
1322 // line. Take into account that some room is needed for what comes before
1323 // the string (e.g., variable name). Add something to the length for the
1324 // '<', NL and trailing NUL.
1325 if (len > LSIZE / 2)
1326 fprintf(fd, IF_EB("\026%d\n<", CTRL_V_STR "%d\n<"), len + 3);
1327
1328 while ((c = *p++) != NUL)
1329 {
1330 if (c == Ctrl_V || c == '\n')
1331 {
1332 putc(Ctrl_V, fd);
1333 if (c == '\n')
1334 c = 'n';
1335 }
1336 putc(c, fd);
1337 }
1338 putc('\n', fd);
1339}
1340
1341/*
1342 * Write a string in quotes that barline_parse() can read back.
1343 * Breaks the line in less than LSIZE pieces when needed.
1344 * Returns remaining characters in the line.
1345 */
1346 int
1347barline_writestring(FILE *fd, char_u *s, int remaining_start)
1348{
1349 char_u *p;
1350 int remaining = remaining_start;
1351 int len = 2;
1352
1353 // Count the number of characters produced, including quotes.
1354 for (p = s; *p != NUL; ++p)
1355 {
1356 if (*p == NL)
1357 len += 2;
1358 else if (*p == '"' || *p == '\\')
1359 len += 2;
1360 else
1361 ++len;
1362 }
1363 if (len > remaining - 2)
1364 {
1365 fprintf(fd, ">%d\n|<", len);
1366 remaining = LSIZE - 20;
1367 }
1368
1369 putc('"', fd);
1370 for (p = s; *p != NUL; ++p)
1371 {
1372 if (*p == NL)
1373 {
1374 putc('\\', fd);
1375 putc('n', fd);
1376 --remaining;
1377 }
1378 else if (*p == '"' || *p == '\\')
1379 {
1380 putc('\\', fd);
1381 putc(*p, fd);
1382 --remaining;
1383 }
1384 else
1385 putc(*p, fd);
1386 --remaining;
1387
1388 if (remaining < 3)
1389 {
1390 putc('\n', fd);
1391 putc('|', fd);
1392 putc('<', fd);
1393 // Leave enough space for another continuation.
1394 remaining = LSIZE - 20;
1395 }
1396 }
1397 putc('"', fd);
1398 return remaining - 2;
1399}
1400
1401/*
1402 * ":rviminfo" and ":wviminfo".
1403 */
1404 void
1405ex_viminfo(
1406 exarg_T *eap)
1407{
1408 char_u *save_viminfo;
1409
1410 save_viminfo = p_viminfo;
1411 if (*p_viminfo == NUL)
1412 p_viminfo = (char_u *)"'100";
1413 if (eap->cmdidx == CMD_rviminfo)
1414 {
1415 if (read_viminfo(eap->arg, VIF_WANT_INFO | VIF_WANT_MARKS
1416 | (eap->forceit ? VIF_FORCEIT : 0)) == FAIL)
1417 emsg(_("E195: Cannot open viminfo file for reading"));
1418 }
1419 else
1420 write_viminfo(eap->arg, eap->forceit);
1421 p_viminfo = save_viminfo;
1422}
1423
1424#endif // FEAT_VIMINFO