1// This is an open source non-commercial project. Dear PVS-Studio, please check
2// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
3
4// fileio.c: read from and write to a file
5
6#include <assert.h>
7#include <errno.h>
8#include <stdbool.h>
9#include <string.h>
10#include <inttypes.h>
11#include <fcntl.h>
12
13#include "nvim/vim.h"
14#include "nvim/api/private/handle.h"
15#include "nvim/ascii.h"
16#include "nvim/fileio.h"
17#include "nvim/buffer.h"
18#include "nvim/change.h"
19#include "nvim/charset.h"
20#include "nvim/cursor.h"
21#include "nvim/diff.h"
22#include "nvim/edit.h"
23#include "nvim/eval.h"
24#include "nvim/ex_cmds.h"
25#include "nvim/ex_docmd.h"
26#include "nvim/ex_eval.h"
27#include "nvim/fold.h"
28#include "nvim/func_attr.h"
29#include "nvim/getchar.h"
30#include "nvim/hashtab.h"
31#include "nvim/iconv.h"
32#include "nvim/mbyte.h"
33#include "nvim/memfile.h"
34#include "nvim/memline.h"
35#include "nvim/memory.h"
36#include "nvim/message.h"
37#include "nvim/misc1.h"
38#include "nvim/garray.h"
39#include "nvim/move.h"
40#include "nvim/normal.h"
41#include "nvim/option.h"
42#include "nvim/os_unix.h"
43#include "nvim/path.h"
44#include "nvim/quickfix.h"
45#include "nvim/regexp.h"
46#include "nvim/screen.h"
47#include "nvim/search.h"
48#include "nvim/sha256.h"
49#include "nvim/state.h"
50#include "nvim/strings.h"
51#include "nvim/ui.h"
52#include "nvim/ui_compositor.h"
53#include "nvim/types.h"
54#include "nvim/undo.h"
55#include "nvim/window.h"
56#include "nvim/shada.h"
57#include "nvim/os/os.h"
58#include "nvim/os/os_defs.h"
59#include "nvim/os/time.h"
60#include "nvim/os/input.h"
61
62#define BUFSIZE 8192 /* size of normal write buffer */
63#define SMBUFSIZE 256 /* size of emergency write buffer */
64
65//
66// The autocommands are stored in a list for each event.
67// Autocommands for the same pattern, that are consecutive, are joined
68// together, to avoid having to match the pattern too often.
69// The result is an array of Autopat lists, which point to AutoCmd lists:
70//
71// last_autopat[0] -----------------------------+
72// V
73// first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
74// Autopat.cmds Autopat.cmds
75// | |
76// V V
77// AutoCmd.next AutoCmd.next
78// | |
79// V V
80// AutoCmd.next NULL
81// |
82// V
83// NULL
84//
85// last_autopat[1] --------+
86// V
87// first_autopat[1] --> Autopat.next --> NULL
88// Autopat.cmds
89// |
90// V
91// AutoCmd.next
92// |
93// V
94// NULL
95// etc.
96//
97// The order of AutoCmds is important, this is the order in which they were
98// defined and will have to be executed.
99//
100typedef struct AutoCmd {
101 char_u *cmd; // Command to be executed (NULL when
102 // command has been removed)
103 bool once; // "One shot": removed after execution
104 char nested; // If autocommands nest here
105 char last; // last command in list
106 sctx_T script_ctx; // script context where defined
107 struct AutoCmd *next; // Next AutoCmd in list
108} AutoCmd;
109
110typedef struct AutoPat {
111 struct AutoPat *next; // next AutoPat in AutoPat list; MUST
112 // be the first entry
113 char_u *pat; // pattern as typed (NULL when pattern
114 // has been removed)
115 regprog_T *reg_prog; // compiled regprog for pattern
116 AutoCmd *cmds; // list of commands to do
117 int group; // group ID
118 int patlen; // strlen() of pat
119 int buflocal_nr; // !=0 for buffer-local AutoPat
120 char allow_dirs; // Pattern may match whole path
121 char last; // last pattern for apply_autocmds()
122} AutoPat;
123
124///
125/// Struct used to keep status while executing autocommands for an event.
126///
127typedef struct AutoPatCmd {
128 AutoPat *curpat; // next AutoPat to examine
129 AutoCmd *nextcmd; // next AutoCmd to execute
130 int group; // group being used
131 char_u *fname; // fname to match with
132 char_u *sfname; // sfname to match with
133 char_u *tail; // tail of fname
134 event_T event; // current event
135 int arg_bufnr; // initially equal to <abuf>, set to zero when
136 // buf is deleted
137 struct AutoPatCmd *next; // chain of active apc-s for auto-invalidation
138} AutoPatCmd;
139
140#define AUGROUP_DEFAULT -1 /* default autocmd group */
141#define AUGROUP_ERROR -2 /* erroneous autocmd group */
142#define AUGROUP_ALL -3 /* all autocmd groups */
143
144#define HAS_BW_FLAGS
145#define FIO_LATIN1 0x01 /* convert Latin1 */
146#define FIO_UTF8 0x02 /* convert UTF-8 */
147#define FIO_UCS2 0x04 /* convert UCS-2 */
148#define FIO_UCS4 0x08 /* convert UCS-4 */
149#define FIO_UTF16 0x10 /* convert UTF-16 */
150#define FIO_ENDIAN_L 0x80 /* little endian */
151#define FIO_NOCONVERT 0x2000 /* skip encoding conversion */
152#define FIO_UCSBOM 0x4000 /* check for BOM at start of file */
153#define FIO_ALL -1 /* allow all formats */
154
155/* When converting, a read() or write() may leave some bytes to be converted
156 * for the next call. The value is guessed... */
157#define CONV_RESTLEN 30
158
159/* We have to guess how much a sequence of bytes may expand when converting
160 * with iconv() to be able to allocate a buffer. */
161#define ICONV_MULT 8
162
163/*
164 * Structure to pass arguments from buf_write() to buf_write_bytes().
165 */
166struct bw_info {
167 int bw_fd; // file descriptor
168 char_u *bw_buf; // buffer with data to be written
169 int bw_len; // length of data
170#ifdef HAS_BW_FLAGS
171 int bw_flags; // FIO_ flags
172#endif
173 char_u bw_rest[CONV_RESTLEN]; // not converted bytes
174 int bw_restlen; // nr of bytes in bw_rest[]
175 int bw_first; // first write call
176 char_u *bw_conv_buf; // buffer for writing converted chars
177 int bw_conv_buflen; // size of bw_conv_buf
178 int bw_conv_error; // set for conversion error
179 linenr_T bw_conv_error_lnum; // first line with error or zero
180 linenr_T bw_start_lnum; // line number at start of buffer
181# ifdef HAVE_ICONV
182 iconv_t bw_iconv_fd; // descriptor for iconv() or -1
183# endif
184};
185
186#ifdef INCLUDE_GENERATED_DECLARATIONS
187# include "fileio.c.generated.h"
188#endif
189
190static char *e_auchangedbuf = N_(
191 "E812: Autocommands changed buffer or buffer name");
192
193// Set by the apply_autocmds_group function if the given event is equal to
194// EVENT_FILETYPE. Used by the readfile function in order to determine if
195// EVENT_BUFREADPOST triggered the EVENT_FILETYPE.
196//
197// Relying on this value requires one to reset it prior calling
198// apply_autocmds_group.
199static bool au_did_filetype INIT(= false);
200
201void filemess(buf_T *buf, char_u *name, char_u *s, int attr)
202{
203 int msg_scroll_save;
204
205 if (msg_silent != 0) {
206 return;
207 }
208 add_quoted_fname((char *)IObuff, IOSIZE - 80, buf, (const char *)name);
209 xstrlcat((char *)IObuff, (const char *)s, IOSIZE);
210 // For the first message may have to start a new line.
211 // For further ones overwrite the previous one, reset msg_scroll before
212 // calling filemess().
213 msg_scroll_save = msg_scroll;
214 if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0)
215 msg_scroll = FALSE;
216 if (!msg_scroll) /* wait a bit when overwriting an error msg */
217 check_for_delay(FALSE);
218 msg_start();
219 msg_scroll = msg_scroll_save;
220 msg_scrolled_ign = TRUE;
221 /* may truncate the message to avoid a hit-return prompt */
222 msg_outtrans_attr(msg_may_trunc(FALSE, IObuff), attr);
223 msg_clr_eos();
224 ui_flush();
225 msg_scrolled_ign = FALSE;
226}
227
228static AutoPat *last_autopat[NUM_EVENTS] = {
229 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
230 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
231 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
232 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
233 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
234 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
235};
236
237/*
238 * Read lines from file "fname" into the buffer after line "from".
239 *
240 * 1. We allocate blocks with try_malloc, as big as possible.
241 * 2. Each block is filled with characters from the file with a single read().
242 * 3. The lines are inserted in the buffer with ml_append().
243 *
244 * (caller must check that fname != NULL, unless READ_STDIN is used)
245 *
246 * "lines_to_skip" is the number of lines that must be skipped
247 * "lines_to_read" is the number of lines that are appended
248 * When not recovering lines_to_skip is 0 and lines_to_read MAXLNUM.
249 *
250 * flags:
251 * READ_NEW starting to edit a new buffer
252 * READ_FILTER reading filter output
253 * READ_STDIN read from stdin instead of a file
254 * READ_BUFFER read from curbuf instead of a file (converting after reading
255 * stdin)
256 * READ_DUMMY read into a dummy buffer (to check if file contents changed)
257 * READ_KEEP_UNDO don't clear undo info or read it from a file
258 * READ_FIFO read from fifo/socket instead of a file
259 *
260 * return FAIL for failure, NOTDONE for directory (failure), or OK
261 */
262int
263readfile(
264 char_u *fname,
265 char_u *sfname,
266 linenr_T from,
267 linenr_T lines_to_skip,
268 linenr_T lines_to_read,
269 exarg_T *eap, // can be NULL!
270 int flags
271)
272{
273 int fd = 0;
274 int newfile = (flags & READ_NEW);
275 int check_readonly;
276 int filtering = (flags & READ_FILTER);
277 int read_stdin = (flags & READ_STDIN);
278 int read_buffer = (flags & READ_BUFFER);
279 int read_fifo = (flags & READ_FIFO);
280 int set_options = newfile || read_buffer
281 || (eap != NULL && eap->read_edit);
282 linenr_T read_buf_lnum = 1; /* next line to read from curbuf */
283 colnr_T read_buf_col = 0; /* next char to read from this line */
284 char_u c;
285 linenr_T lnum = from;
286 char_u *ptr = NULL; /* pointer into read buffer */
287 char_u *buffer = NULL; /* read buffer */
288 char_u *new_buffer = NULL; /* init to shut up gcc */
289 char_u *line_start = NULL; /* init to shut up gcc */
290 int wasempty; /* buffer was empty before reading */
291 colnr_T len;
292 long size = 0;
293 uint8_t *p = NULL;
294 off_T filesize = 0;
295 int skip_read = false;
296 context_sha256_T sha_ctx;
297 int read_undo_file = false;
298 linenr_T linecnt;
299 int error = FALSE; /* errors encountered */
300 int ff_error = EOL_UNKNOWN; /* file format with errors */
301 long linerest = 0; /* remaining chars in line */
302 int perm = 0;
303#ifdef UNIX
304 int swap_mode = -1; /* protection bits for swap file */
305#endif
306 int fileformat = 0; // end-of-line format
307 bool keep_fileformat = false;
308 FileInfo file_info;
309 int file_readonly;
310 linenr_T skip_count = 0;
311 linenr_T read_count = 0;
312 int msg_save = msg_scroll;
313 linenr_T read_no_eol_lnum = 0; // non-zero lnum when last line of
314 // last read was missing the eol
315 bool file_rewind = false;
316 int can_retry;
317 linenr_T conv_error = 0; // line nr with conversion error
318 linenr_T illegal_byte = 0; // line nr with illegal byte
319 bool keep_dest_enc = false; // don't retry when char doesn't fit
320 // in destination encoding
321 int bad_char_behavior = BAD_REPLACE;
322 /* BAD_KEEP, BAD_DROP or character to
323 * replace with */
324 char_u *tmpname = NULL; /* name of 'charconvert' output file */
325 int fio_flags = 0;
326 char_u *fenc; // fileencoding to use
327 bool fenc_alloced; // fenc_next is in allocated memory
328 char_u *fenc_next = NULL; // next item in 'fencs' or NULL
329 bool advance_fenc = false;
330 long real_size = 0;
331# ifdef HAVE_ICONV
332 iconv_t iconv_fd = (iconv_t)-1; // descriptor for iconv() or -1
333 int did_iconv = false; // TRUE when iconv() failed and trying
334 // 'charconvert' next
335# endif
336 int converted = FALSE; /* TRUE if conversion done */
337 int notconverted = FALSE; /* TRUE if conversion wanted but it
338 wasn't possible */
339 char_u conv_rest[CONV_RESTLEN];
340 int conv_restlen = 0; /* nr of bytes in conv_rest[] */
341 buf_T *old_curbuf;
342 char_u *old_b_ffname;
343 char_u *old_b_fname;
344 int using_b_ffname;
345 int using_b_fname;
346
347 au_did_filetype = false; // reset before triggering any autocommands
348
349 curbuf->b_no_eol_lnum = 0; /* in case it was set by the previous read */
350
351 /*
352 * If there is no file name yet, use the one for the read file.
353 * BF_NOTEDITED is set to reflect this.
354 * Don't do this for a read from a filter.
355 * Only do this when 'cpoptions' contains the 'f' flag.
356 */
357 if (curbuf->b_ffname == NULL
358 && !filtering
359 && fname != NULL
360 && vim_strchr(p_cpo, CPO_FNAMER) != NULL
361 && !(flags & READ_DUMMY)) {
362 if (set_rw_fname(fname, sfname) == FAIL)
363 return FAIL;
364 }
365
366 /* Remember the initial values of curbuf, curbuf->b_ffname and
367 * curbuf->b_fname to detect whether they are altered as a result of
368 * executing nasty autocommands. Also check if "fname" and "sfname"
369 * point to one of these values. */
370 old_curbuf = curbuf;
371 old_b_ffname = curbuf->b_ffname;
372 old_b_fname = curbuf->b_fname;
373 using_b_ffname = (fname == curbuf->b_ffname)
374 || (sfname == curbuf->b_ffname);
375 using_b_fname = (fname == curbuf->b_fname) || (sfname == curbuf->b_fname);
376
377 /* After reading a file the cursor line changes but we don't want to
378 * display the line. */
379 ex_no_reprint = TRUE;
380
381 /* don't display the file info for another buffer now */
382 need_fileinfo = FALSE;
383
384 // For Unix: Use the short file name whenever possible.
385 // Avoids problems with networks and when directory names are changed.
386 // Don't do this for Windows, a "cd" in a sub-shell may have moved us to
387 // another directory, which we don't detect.
388 if (sfname == NULL) {
389 sfname = fname;
390 }
391#if defined(UNIX)
392 fname = sfname;
393#endif
394
395 /*
396 * The BufReadCmd and FileReadCmd events intercept the reading process by
397 * executing the associated commands instead.
398 */
399 if (!filtering && !read_stdin && !read_buffer) {
400 pos_T pos;
401
402 pos = curbuf->b_op_start;
403
404 /* Set '[ mark to the line above where the lines go (line 1 if zero). */
405 curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
406 curbuf->b_op_start.col = 0;
407
408 if (newfile) {
409 if (apply_autocmds_exarg(EVENT_BUFREADCMD, NULL, sfname,
410 FALSE, curbuf, eap))
411 return aborting() ? FAIL : OK;
412 } else if (apply_autocmds_exarg(EVENT_FILEREADCMD, sfname, sfname,
413 FALSE, NULL, eap))
414 return aborting() ? FAIL : OK;
415
416 curbuf->b_op_start = pos;
417 }
418
419 if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0)
420 msg_scroll = FALSE; /* overwrite previous file message */
421 else
422 msg_scroll = TRUE; /* don't overwrite previous file message */
423
424 /*
425 * If the name is too long we might crash further on, quit here.
426 */
427 if (fname != NULL && *fname != NUL) {
428 if (STRLEN(fname) >= MAXPATHL) {
429 filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0);
430 msg_end();
431 msg_scroll = msg_save;
432 return FAIL;
433 }
434 }
435
436 if (!read_buffer && !read_stdin && !read_fifo) {
437 perm = os_getperm((const char *)fname);
438#ifdef UNIX
439 // On Unix it is possible to read a directory, so we have to
440 // check for it before os_open().
441 if (perm >= 0 && !S_ISREG(perm) // not a regular file ...
442# ifdef S_ISFIFO
443 && !S_ISFIFO(perm) // ... or fifo
444# endif
445# ifdef S_ISSOCK
446 && !S_ISSOCK(perm) // ... or socket
447# endif
448# ifdef OPEN_CHR_FILES
449 && !(S_ISCHR(perm) && is_dev_fd_file(fname))
450 // ... or a character special file named /dev/fd/<n>
451# endif
452 ) {
453 if (S_ISDIR(perm)) {
454 filemess(curbuf, fname, (char_u *)_("is a directory"), 0);
455 } else {
456 filemess(curbuf, fname, (char_u *)_("is not a file"), 0);
457 }
458 msg_end();
459 msg_scroll = msg_save;
460 return S_ISDIR(perm) ? NOTDONE : FAIL;
461 }
462#endif
463 }
464
465 /* Set default or forced 'fileformat' and 'binary'. */
466 set_file_options(set_options, eap);
467
468 /*
469 * When opening a new file we take the readonly flag from the file.
470 * Default is r/w, can be set to r/o below.
471 * Don't reset it when in readonly mode
472 * Only set/reset b_p_ro when BF_CHECK_RO is set.
473 */
474 check_readonly = (newfile && (curbuf->b_flags & BF_CHECK_RO));
475 if (check_readonly && !readonlymode)
476 curbuf->b_p_ro = FALSE;
477
478 if (newfile && !read_stdin && !read_buffer && !read_fifo) {
479 // Remember time of file.
480 if (os_fileinfo((char *)fname, &file_info)) {
481 buf_store_file_info(curbuf, &file_info);
482 curbuf->b_mtime_read = curbuf->b_mtime;
483#ifdef UNIX
484 /*
485 * Use the protection bits of the original file for the swap file.
486 * This makes it possible for others to read the name of the
487 * edited file from the swapfile, but only if they can read the
488 * edited file.
489 * Remove the "write" and "execute" bits for group and others
490 * (they must not write the swapfile).
491 * Add the "read" and "write" bits for the user, otherwise we may
492 * not be able to write to the file ourselves.
493 * Setting the bits is done below, after creating the swap file.
494 */
495 swap_mode = (file_info.stat.st_mode & 0644) | 0600;
496#endif
497 } else {
498 curbuf->b_mtime = 0;
499 curbuf->b_mtime_read = 0;
500 curbuf->b_orig_size = 0;
501 curbuf->b_orig_mode = 0;
502 }
503
504 /* Reset the "new file" flag. It will be set again below when the
505 * file doesn't exist. */
506 curbuf->b_flags &= ~(BF_NEW | BF_NEW_W);
507 }
508
509 // Check readonly.
510 file_readonly = false;
511 if (!read_buffer && !read_stdin) {
512 if (!newfile || readonlymode || !(perm & 0222)
513 || !os_file_is_writable((char *)fname)) {
514 file_readonly = true;
515 }
516 fd = os_open((char *)fname, O_RDONLY, 0);
517 }
518
519 if (fd < 0) { // cannot open at all
520 msg_scroll = msg_save;
521#ifndef UNIX
522 // On non-unix systems we can't open a directory, check here.
523 if (os_isdir(fname)) {
524 filemess(curbuf, sfname, (char_u *)_("is a directory"), 0);
525 curbuf->b_p_ro = true; // must use "w!" now
526 } else {
527#endif
528 if (!newfile) {
529 return FAIL;
530 }
531 if (perm == UV_ENOENT) { // check if the file exists
532 // Set the 'new-file' flag, so that when the file has
533 // been created by someone else, a ":w" will complain.
534 curbuf->b_flags |= BF_NEW;
535
536 /* Create a swap file now, so that other Vims are warned
537 * that we are editing this file. Don't do this for a
538 * "nofile" or "nowrite" buffer type. */
539 if (!bt_dontwrite(curbuf)) {
540 check_need_swap(newfile);
541 /* SwapExists autocommand may mess things up */
542 if (curbuf != old_curbuf
543 || (using_b_ffname
544 && (old_b_ffname != curbuf->b_ffname))
545 || (using_b_fname
546 && (old_b_fname != curbuf->b_fname))) {
547 EMSG(_(e_auchangedbuf));
548 return FAIL;
549 }
550 }
551 if (dir_of_file_exists(fname))
552 filemess(curbuf, sfname, (char_u *)_("[New File]"), 0);
553 else
554 filemess(curbuf, sfname,
555 (char_u *)_("[New DIRECTORY]"), 0);
556 /* Even though this is a new file, it might have been
557 * edited before and deleted. Get the old marks. */
558 check_marks_read();
559 /* Set forced 'fileencoding'. */
560 if (eap != NULL)
561 set_forced_fenc(eap);
562 apply_autocmds_exarg(EVENT_BUFNEWFILE, sfname, sfname,
563 FALSE, curbuf, eap);
564 /* remember the current fileformat */
565 save_file_ff(curbuf);
566
567 if (aborting()) /* autocmds may abort script processing */
568 return FAIL;
569 return OK; /* a new file is not an error */
570 } else {
571 filemess(curbuf, sfname, (char_u *)(
572 (fd == UV_EFBIG) ? _("[File too big]") :
573# if defined(UNIX) && defined(EOVERFLOW)
574 // libuv only returns -errno in Unix and in Windows open() does not
575 // set EOVERFLOW
576 (fd == -EOVERFLOW) ? _("[File too big]") :
577# endif
578 _("[Permission Denied]")), 0);
579 curbuf->b_p_ro = TRUE; /* must use "w!" now */
580 }
581
582 return FAIL;
583 }
584#ifndef UNIX
585 }
586#endif
587
588 /*
589 * Only set the 'ro' flag for readonly files the first time they are
590 * loaded. Help files always get readonly mode
591 */
592 if ((check_readonly && file_readonly) || curbuf->b_help)
593 curbuf->b_p_ro = TRUE;
594
595 if (set_options) {
596 /* Don't change 'eol' if reading from buffer as it will already be
597 * correctly set when reading stdin. */
598 if (!read_buffer) {
599 curbuf->b_p_eol = TRUE;
600 curbuf->b_start_eol = TRUE;
601 }
602 curbuf->b_p_bomb = FALSE;
603 curbuf->b_start_bomb = FALSE;
604 }
605
606 /* Create a swap file now, so that other Vims are warned that we are
607 * editing this file.
608 * Don't do this for a "nofile" or "nowrite" buffer type. */
609 if (!bt_dontwrite(curbuf)) {
610 check_need_swap(newfile);
611 if (!read_stdin
612 && (curbuf != old_curbuf
613 || (using_b_ffname && (old_b_ffname != curbuf->b_ffname))
614 || (using_b_fname && (old_b_fname != curbuf->b_fname)))) {
615 EMSG(_(e_auchangedbuf));
616 if (!read_buffer) {
617 close(fd);
618 }
619 return FAIL;
620 }
621#ifdef UNIX
622 // Set swap file protection bits after creating it.
623 if (swap_mode > 0 && curbuf->b_ml.ml_mfp != NULL
624 && curbuf->b_ml.ml_mfp->mf_fname != NULL) {
625 const char *swap_fname = (const char *)curbuf->b_ml.ml_mfp->mf_fname;
626
627 // If the group-read bit is set but not the world-read bit, then
628 // the group must be equal to the group of the original file. If
629 // we can't make that happen then reset the group-read bit. This
630 // avoids making the swap file readable to more users when the
631 // primary group of the user is too permissive.
632 if ((swap_mode & 044) == 040) {
633 FileInfo swap_info;
634
635 if (os_fileinfo(swap_fname, &swap_info)
636 && file_info.stat.st_gid != swap_info.stat.st_gid
637 && os_fchown(curbuf->b_ml.ml_mfp->mf_fd, -1, file_info.stat.st_gid)
638 == -1) {
639 swap_mode &= 0600;
640 }
641 }
642
643 (void)os_setperm(swap_fname, swap_mode);
644 }
645#endif
646 }
647
648 // If "Quit" selected at ATTENTION dialog, don't load the file.
649 if (swap_exists_action == SEA_QUIT) {
650 if (!read_buffer && !read_stdin)
651 close(fd);
652 return FAIL;
653 }
654
655 ++no_wait_return; /* don't wait for return yet */
656
657 /*
658 * Set '[ mark to the line above where the lines go (line 1 if zero).
659 */
660 curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
661 curbuf->b_op_start.col = 0;
662
663 int try_mac = (vim_strchr(p_ffs, 'm') != NULL);
664 int try_dos = (vim_strchr(p_ffs, 'd') != NULL);
665 int try_unix = (vim_strchr(p_ffs, 'x') != NULL);
666
667 if (!read_buffer) {
668 int m = msg_scroll;
669 int n = msg_scrolled;
670
671 // The file must be closed again, the autocommands may want to change
672 // the file before reading it.
673 if (!read_stdin) {
674 close(fd); // ignore errors
675 }
676
677 // The output from the autocommands should not overwrite anything and
678 // should not be overwritten: Set msg_scroll, restore its value if no
679 // output was done.
680 msg_scroll = true;
681 if (filtering) {
682 apply_autocmds_exarg(EVENT_FILTERREADPRE, NULL, sfname,
683 false, curbuf, eap);
684 } else if (read_stdin) {
685 apply_autocmds_exarg(EVENT_STDINREADPRE, NULL, sfname,
686 false, curbuf, eap);
687 } else if (newfile) {
688 apply_autocmds_exarg(EVENT_BUFREADPRE, NULL, sfname,
689 false, curbuf, eap);
690 } else {
691 apply_autocmds_exarg(EVENT_FILEREADPRE, sfname, sfname,
692 false, NULL, eap);
693 }
694
695 // autocommands may have changed it
696 try_mac = (vim_strchr(p_ffs, 'm') != NULL);
697 try_dos = (vim_strchr(p_ffs, 'd') != NULL);
698 try_unix = (vim_strchr(p_ffs, 'x') != NULL);
699
700 if (msg_scrolled == n) {
701 msg_scroll = m;
702 }
703
704 if (aborting()) { /* autocmds may abort script processing */
705 --no_wait_return;
706 msg_scroll = msg_save;
707 curbuf->b_p_ro = TRUE; /* must use "w!" now */
708 return FAIL;
709 }
710 /*
711 * Don't allow the autocommands to change the current buffer.
712 * Try to re-open the file.
713 *
714 * Don't allow the autocommands to change the buffer name either
715 * (cd for example) if it invalidates fname or sfname.
716 */
717 if (!read_stdin && (curbuf != old_curbuf
718 || (using_b_ffname && (old_b_ffname != curbuf->b_ffname))
719 || (using_b_fname && (old_b_fname != curbuf->b_fname))
720 || (fd = os_open((char *)fname, O_RDONLY, 0)) < 0)) {
721 --no_wait_return;
722 msg_scroll = msg_save;
723 if (fd < 0)
724 EMSG(_("E200: *ReadPre autocommands made the file unreadable"));
725 else
726 EMSG(_("E201: *ReadPre autocommands must not change current buffer"));
727 curbuf->b_p_ro = TRUE; /* must use "w!" now */
728 return FAIL;
729 }
730 }
731
732 /* Autocommands may add lines to the file, need to check if it is empty */
733 wasempty = (curbuf->b_ml.ml_flags & ML_EMPTY);
734
735 if (!recoverymode && !filtering && !(flags & READ_DUMMY)) {
736 if (!read_stdin && !read_buffer) {
737 filemess(curbuf, sfname, (char_u *)"", 0);
738 }
739 }
740
741 msg_scroll = FALSE; /* overwrite the file message */
742
743 /*
744 * Set linecnt now, before the "retry" caused by a wrong guess for
745 * fileformat, and after the autocommands, which may change them.
746 */
747 linecnt = curbuf->b_ml.ml_line_count;
748
749 /* "++bad=" argument. */
750 if (eap != NULL && eap->bad_char != 0) {
751 bad_char_behavior = eap->bad_char;
752 if (set_options)
753 curbuf->b_bad_char = eap->bad_char;
754 } else
755 curbuf->b_bad_char = 0;
756
757 /*
758 * Decide which 'encoding' to use or use first.
759 */
760 if (eap != NULL && eap->force_enc != 0) {
761 fenc = enc_canonize(eap->cmd + eap->force_enc);
762 fenc_alloced = true;
763 keep_dest_enc = true;
764 } else if (curbuf->b_p_bin) {
765 fenc = (char_u *)""; // binary: don't convert
766 fenc_alloced = false;
767 } else if (curbuf->b_help) {
768 // Help files are either utf-8 or latin1. Try utf-8 first, if this
769 // fails it must be latin1.
770 // It is needed when the first line contains non-ASCII characters.
771 // That is only in *.??x files.
772 fenc_next = (char_u *)"latin1";
773 fenc = (char_u *)"utf-8";
774
775 fenc_alloced = false;
776 } else if (*p_fencs == NUL) {
777 fenc = curbuf->b_p_fenc; // use format from buffer
778 fenc_alloced = false;
779 } else {
780 fenc_next = p_fencs; // try items in 'fileencodings'
781 fenc = next_fenc(&fenc_next, &fenc_alloced);
782 }
783
784 /*
785 * Jump back here to retry reading the file in different ways.
786 * Reasons to retry:
787 * - encoding conversion failed: try another one from "fenc_next"
788 * - BOM detected and fenc was set, need to setup conversion
789 * - "fileformat" check failed: try another
790 *
791 * Variables set for special retry actions:
792 * "file_rewind" Rewind the file to start reading it again.
793 * "advance_fenc" Advance "fenc" using "fenc_next".
794 * "skip_read" Re-use already read bytes (BOM detected).
795 * "did_iconv" iconv() conversion failed, try 'charconvert'.
796 * "keep_fileformat" Don't reset "fileformat".
797 *
798 * Other status indicators:
799 * "tmpname" When != NULL did conversion with 'charconvert'.
800 * Output file has to be deleted afterwards.
801 * "iconv_fd" When != -1 did conversion with iconv().
802 */
803retry:
804
805 if (file_rewind) {
806 if (read_buffer) {
807 read_buf_lnum = 1;
808 read_buf_col = 0;
809 } else if (read_stdin || vim_lseek(fd, (off_T)0L, SEEK_SET) != 0) {
810 // Can't rewind the file, give up.
811 error = true;
812 goto failed;
813 }
814 // Delete the previously read lines.
815 while (lnum > from) {
816 ml_delete(lnum--, false);
817 }
818 file_rewind = false;
819 if (set_options) {
820 curbuf->b_p_bomb = FALSE;
821 curbuf->b_start_bomb = FALSE;
822 }
823 conv_error = 0;
824 }
825
826 /*
827 * When retrying with another "fenc" and the first time "fileformat"
828 * will be reset.
829 */
830 if (keep_fileformat) {
831 keep_fileformat = false;
832 } else {
833 if (eap != NULL && eap->force_ff != 0) {
834 fileformat = get_fileformat_force(curbuf, eap);
835 try_unix = try_dos = try_mac = FALSE;
836 } else if (curbuf->b_p_bin)
837 fileformat = EOL_UNIX; /* binary: use Unix format */
838 else if (*p_ffs == NUL)
839 fileformat = get_fileformat(curbuf); /* use format from buffer */
840 else
841 fileformat = EOL_UNKNOWN; /* detect from file */
842 }
843
844# ifdef HAVE_ICONV
845 if (iconv_fd != (iconv_t)-1) {
846 /* aborted conversion with iconv(), close the descriptor */
847 iconv_close(iconv_fd);
848 iconv_fd = (iconv_t)-1;
849 }
850# endif
851
852 if (advance_fenc) {
853 /*
854 * Try the next entry in 'fileencodings'.
855 */
856 advance_fenc = false;
857
858 if (eap != NULL && eap->force_enc != 0) {
859 /* Conversion given with "++cc=" wasn't possible, read
860 * without conversion. */
861 notconverted = TRUE;
862 conv_error = 0;
863 if (fenc_alloced)
864 xfree(fenc);
865 fenc = (char_u *)"";
866 fenc_alloced = false;
867 } else {
868 if (fenc_alloced)
869 xfree(fenc);
870 if (fenc_next != NULL) {
871 fenc = next_fenc(&fenc_next, &fenc_alloced);
872 } else {
873 fenc = (char_u *)"";
874 fenc_alloced = false;
875 }
876 }
877 if (tmpname != NULL) {
878 os_remove((char *)tmpname); // delete converted file
879 XFREE_CLEAR(tmpname);
880 }
881 }
882
883 /*
884 * Conversion may be required when the encoding of the file is different
885 * from 'encoding' or 'encoding' is UTF-16, UCS-2 or UCS-4.
886 */
887 fio_flags = 0;
888 converted = need_conversion(fenc);
889 if (converted) {
890
891 /* "ucs-bom" means we need to check the first bytes of the file
892 * for a BOM. */
893 if (STRCMP(fenc, ENC_UCSBOM) == 0)
894 fio_flags = FIO_UCSBOM;
895
896 /*
897 * Check if UCS-2/4 or Latin1 to UTF-8 conversion needs to be
898 * done. This is handled below after read(). Prepare the
899 * fio_flags to avoid having to parse the string each time.
900 * Also check for Unicode to Latin1 conversion, because iconv()
901 * appears not to handle this correctly. This works just like
902 * conversion to UTF-8 except how the resulting character is put in
903 * the buffer.
904 */
905 else if (enc_utf8 || STRCMP(p_enc, "latin1") == 0)
906 fio_flags = get_fio_flags(fenc);
907
908
909
910# ifdef HAVE_ICONV
911 // Try using iconv() if we can't convert internally.
912 if (fio_flags == 0
913 && !did_iconv
914 ) {
915 iconv_fd = (iconv_t)my_iconv_open(
916 enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc);
917 }
918# endif
919
920 /*
921 * Use the 'charconvert' expression when conversion is required
922 * and we can't do it internally or with iconv().
923 */
924 if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL
925 && !read_fifo
926# ifdef HAVE_ICONV
927 && iconv_fd == (iconv_t)-1
928# endif
929 ) {
930# ifdef HAVE_ICONV
931 did_iconv = false;
932# endif
933 /* Skip conversion when it's already done (retry for wrong
934 * "fileformat"). */
935 if (tmpname == NULL) {
936 tmpname = readfile_charconvert(fname, fenc, &fd);
937 if (tmpname == NULL) {
938 // Conversion failed. Try another one.
939 advance_fenc = true;
940 if (fd < 0) {
941 /* Re-opening the original file failed! */
942 EMSG(_("E202: Conversion made file unreadable!"));
943 error = TRUE;
944 goto failed;
945 }
946 goto retry;
947 }
948 }
949 } else {
950 if (fio_flags == 0
951# ifdef HAVE_ICONV
952 && iconv_fd == (iconv_t)-1
953# endif
954 ) {
955 /* Conversion wanted but we can't.
956 * Try the next conversion in 'fileencodings' */
957 advance_fenc = true;
958 goto retry;
959 }
960 }
961 }
962
963 /* Set "can_retry" when it's possible to rewind the file and try with
964 * another "fenc" value. It's FALSE when no other "fenc" to try, reading
965 * stdin or fixed at a specific encoding. */
966 can_retry = (*fenc != NUL && !read_stdin && !keep_dest_enc && !read_fifo);
967
968 if (!skip_read) {
969 linerest = 0;
970 filesize = 0;
971 skip_count = lines_to_skip;
972 read_count = lines_to_read;
973 conv_restlen = 0;
974 read_undo_file = (newfile && (flags & READ_KEEP_UNDO) == 0
975 && curbuf->b_ffname != NULL
976 && curbuf->b_p_udf
977 && !filtering
978 && !read_fifo
979 && !read_stdin
980 && !read_buffer);
981 if (read_undo_file)
982 sha256_start(&sha_ctx);
983 }
984
985 while (!error && !got_int) {
986 /*
987 * We allocate as much space for the file as we can get, plus
988 * space for the old line plus room for one terminating NUL.
989 * The amount is limited by the fact that read() only can read
990 * up to max_unsigned characters (and other things).
991 */
992 {
993 if (!skip_read) {
994 size = 0x10000L; /* use buffer >= 64K */
995
996 for (; size >= 10; size /= 2) {
997 new_buffer = verbose_try_malloc((size_t)size + (size_t)linerest + 1);
998 if (new_buffer) {
999 break;
1000 }
1001 }
1002 if (new_buffer == NULL) {
1003 error = TRUE;
1004 break;
1005 }
1006 if (linerest) /* copy characters from the previous buffer */
1007 memmove(new_buffer, ptr - linerest, (size_t)linerest);
1008 xfree(buffer);
1009 buffer = new_buffer;
1010 ptr = buffer + linerest;
1011 line_start = buffer;
1012
1013 /* May need room to translate into.
1014 * For iconv() we don't really know the required space, use a
1015 * factor ICONV_MULT.
1016 * latin1 to utf-8: 1 byte becomes up to 2 bytes
1017 * utf-16 to utf-8: 2 bytes become up to 3 bytes, 4 bytes
1018 * become up to 4 bytes, size must be multiple of 2
1019 * ucs-2 to utf-8: 2 bytes become up to 3 bytes, size must be
1020 * multiple of 2
1021 * ucs-4 to utf-8: 4 bytes become up to 6 bytes, size must be
1022 * multiple of 4 */
1023 real_size = (int)size;
1024# ifdef HAVE_ICONV
1025 if (iconv_fd != (iconv_t)-1) {
1026 size = size / ICONV_MULT;
1027 } else {
1028# endif
1029 if (fio_flags & FIO_LATIN1) {
1030 size = size / 2;
1031 } else if (fio_flags & (FIO_UCS2 | FIO_UTF16)) {
1032 size = (size * 2 / 3) & ~1;
1033 } else if (fio_flags & FIO_UCS4) {
1034 size = (size * 2 / 3) & ~3;
1035 } else if (fio_flags == FIO_UCSBOM) {
1036 size = size / ICONV_MULT; // worst case
1037 }
1038# ifdef HAVE_ICONV
1039 }
1040# endif
1041 if (conv_restlen > 0) {
1042 // Insert unconverted bytes from previous line.
1043 memmove(ptr, conv_rest, conv_restlen); // -V614
1044 ptr += conv_restlen;
1045 size -= conv_restlen;
1046 }
1047
1048 if (read_buffer) {
1049 /*
1050 * Read bytes from curbuf. Used for converting text read
1051 * from stdin.
1052 */
1053 if (read_buf_lnum > from)
1054 size = 0;
1055 else {
1056 int n, ni;
1057 long tlen;
1058
1059 tlen = 0;
1060 for (;; ) {
1061 p = ml_get(read_buf_lnum) + read_buf_col;
1062 n = (int)STRLEN(p);
1063 if ((int)tlen + n + 1 > size) {
1064 /* Filled up to "size", append partial line.
1065 * Change NL to NUL to reverse the effect done
1066 * below. */
1067 n = (int)(size - tlen);
1068 for (ni = 0; ni < n; ++ni) {
1069 if (p[ni] == NL)
1070 ptr[tlen++] = NUL;
1071 else
1072 ptr[tlen++] = p[ni];
1073 }
1074 read_buf_col += n;
1075 break;
1076 } else {
1077 /* Append whole line and new-line. Change NL
1078 * to NUL to reverse the effect done below. */
1079 for (ni = 0; ni < n; ++ni) {
1080 if (p[ni] == NL)
1081 ptr[tlen++] = NUL;
1082 else
1083 ptr[tlen++] = p[ni];
1084 }
1085 ptr[tlen++] = NL;
1086 read_buf_col = 0;
1087 if (++read_buf_lnum > from) {
1088 /* When the last line didn't have an
1089 * end-of-line don't add it now either. */
1090 if (!curbuf->b_p_eol)
1091 --tlen;
1092 size = tlen;
1093 break;
1094 }
1095 }
1096 }
1097 }
1098 } else {
1099 /*
1100 * Read bytes from the file.
1101 */
1102 size = read_eintr(fd, ptr, size);
1103 }
1104
1105 if (size <= 0) {
1106 if (size < 0) /* read error */
1107 error = TRUE;
1108 else if (conv_restlen > 0) {
1109 /*
1110 * Reached end-of-file but some trailing bytes could
1111 * not be converted. Truncated file?
1112 */
1113
1114 /* When we did a conversion report an error. */
1115 if (fio_flags != 0
1116# ifdef HAVE_ICONV
1117 || iconv_fd != (iconv_t)-1
1118# endif
1119 ) {
1120 if (can_retry)
1121 goto rewind_retry;
1122 if (conv_error == 0)
1123 conv_error = curbuf->b_ml.ml_line_count
1124 - linecnt + 1;
1125 }
1126 /* Remember the first linenr with an illegal byte */
1127 else if (illegal_byte == 0)
1128 illegal_byte = curbuf->b_ml.ml_line_count
1129 - linecnt + 1;
1130 if (bad_char_behavior == BAD_DROP) {
1131 *(ptr - conv_restlen) = NUL;
1132 conv_restlen = 0;
1133 } else {
1134 /* Replace the trailing bytes with the replacement
1135 * character if we were converting; if we weren't,
1136 * leave the UTF8 checking code to do it, as it
1137 * works slightly differently. */
1138 if (bad_char_behavior != BAD_KEEP && (fio_flags != 0
1139# ifdef HAVE_ICONV
1140 || iconv_fd != (iconv_t)-1
1141# endif
1142 )) {
1143 while (conv_restlen > 0) {
1144 *(--ptr) = bad_char_behavior;
1145 --conv_restlen;
1146 }
1147 }
1148 fio_flags = 0; // don't convert this
1149# ifdef HAVE_ICONV
1150 if (iconv_fd != (iconv_t)-1) {
1151 iconv_close(iconv_fd);
1152 iconv_fd = (iconv_t)-1;
1153 }
1154# endif
1155 }
1156 }
1157 }
1158 }
1159
1160 skip_read = FALSE;
1161
1162 /*
1163 * At start of file: Check for BOM.
1164 * Also check for a BOM for other Unicode encodings, but not after
1165 * converting with 'charconvert' or when a BOM has already been
1166 * found.
1167 */
1168 if ((filesize == 0)
1169 && (fio_flags == FIO_UCSBOM
1170 || (!curbuf->b_p_bomb
1171 && tmpname == NULL
1172 && (*fenc == 'u' || (*fenc == NUL && enc_utf8))))) {
1173 char_u *ccname;
1174 int blen;
1175
1176 /* no BOM detection in a short file or in binary mode */
1177 if (size < 2 || curbuf->b_p_bin)
1178 ccname = NULL;
1179 else
1180 ccname = check_for_bom(ptr, size, &blen,
1181 fio_flags == FIO_UCSBOM ? FIO_ALL : get_fio_flags(fenc));
1182 if (ccname != NULL) {
1183 /* Remove BOM from the text */
1184 filesize += blen;
1185 size -= blen;
1186 memmove(ptr, ptr + blen, (size_t)size);
1187 if (set_options) {
1188 curbuf->b_p_bomb = TRUE;
1189 curbuf->b_start_bomb = TRUE;
1190 }
1191 }
1192
1193 if (fio_flags == FIO_UCSBOM) {
1194 if (ccname == NULL) {
1195 // No BOM detected: retry with next encoding.
1196 advance_fenc = true;
1197 } else {
1198 /* BOM detected: set "fenc" and jump back */
1199 if (fenc_alloced)
1200 xfree(fenc);
1201 fenc = ccname;
1202 fenc_alloced = false;
1203 }
1204 /* retry reading without getting new bytes or rewinding */
1205 skip_read = TRUE;
1206 goto retry;
1207 }
1208 }
1209
1210 /* Include not converted bytes. */
1211 ptr -= conv_restlen;
1212 size += conv_restlen;
1213 conv_restlen = 0;
1214 /*
1215 * Break here for a read error or end-of-file.
1216 */
1217 if (size <= 0)
1218 break;
1219
1220# ifdef HAVE_ICONV
1221 if (iconv_fd != (iconv_t)-1) {
1222 /*
1223 * Attempt conversion of the read bytes to 'encoding' using
1224 * iconv().
1225 */
1226 const char *fromp;
1227 char *top;
1228 size_t from_size;
1229 size_t to_size;
1230
1231 fromp = (char *)ptr;
1232 from_size = size;
1233 ptr += size;
1234 top = (char *)ptr;
1235 to_size = real_size - size;
1236
1237 /*
1238 * If there is conversion error or not enough room try using
1239 * another conversion. Except for when there is no
1240 * alternative (help files).
1241 */
1242 while ((iconv(iconv_fd, (void *)&fromp, &from_size,
1243 &top, &to_size)
1244 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
1245 || from_size > CONV_RESTLEN) {
1246 if (can_retry)
1247 goto rewind_retry;
1248 if (conv_error == 0)
1249 conv_error = readfile_linenr(linecnt,
1250 ptr, (char_u *)top);
1251
1252 /* Deal with a bad byte and continue with the next. */
1253 ++fromp;
1254 --from_size;
1255 if (bad_char_behavior == BAD_KEEP) {
1256 *top++ = *(fromp - 1);
1257 --to_size;
1258 } else if (bad_char_behavior != BAD_DROP) {
1259 *top++ = bad_char_behavior;
1260 --to_size;
1261 }
1262 }
1263
1264 if (from_size > 0) {
1265 /* Some remaining characters, keep them for the next
1266 * round. */
1267 memmove(conv_rest, (char_u *)fromp, from_size);
1268 conv_restlen = (int)from_size;
1269 }
1270
1271 /* move the linerest to before the converted characters */
1272 line_start = ptr - linerest;
1273 memmove(line_start, buffer, (size_t)linerest);
1274 size = (long)((char_u *)top - ptr);
1275 }
1276# endif
1277
1278 if (fio_flags != 0) {
1279 unsigned int u8c;
1280 char_u *dest;
1281 char_u *tail = NULL;
1282
1283 /*
1284 * "enc_utf8" set: Convert Unicode or Latin1 to UTF-8.
1285 * "enc_utf8" not set: Convert Unicode to Latin1.
1286 * Go from end to start through the buffer, because the number
1287 * of bytes may increase.
1288 * "dest" points to after where the UTF-8 bytes go, "p" points
1289 * to after the next character to convert.
1290 */
1291 dest = ptr + real_size;
1292 if (fio_flags == FIO_LATIN1 || fio_flags == FIO_UTF8) {
1293 p = ptr + size;
1294 if (fio_flags == FIO_UTF8) {
1295 /* Check for a trailing incomplete UTF-8 sequence */
1296 tail = ptr + size - 1;
1297 while (tail > ptr && (*tail & 0xc0) == 0x80)
1298 --tail;
1299 if (tail + utf_byte2len(*tail) <= ptr + size)
1300 tail = NULL;
1301 else
1302 p = tail;
1303 }
1304 } else if (fio_flags & (FIO_UCS2 | FIO_UTF16)) {
1305 /* Check for a trailing byte */
1306 p = ptr + (size & ~1);
1307 if (size & 1)
1308 tail = p;
1309 if ((fio_flags & FIO_UTF16) && p > ptr) {
1310 /* Check for a trailing leading word */
1311 if (fio_flags & FIO_ENDIAN_L) {
1312 u8c = (*--p << 8);
1313 u8c += *--p;
1314 } else {
1315 u8c = *--p;
1316 u8c += (*--p << 8);
1317 }
1318 if (u8c >= 0xd800 && u8c <= 0xdbff)
1319 tail = p;
1320 else
1321 p += 2;
1322 }
1323 } else { /* FIO_UCS4 */
1324 /* Check for trailing 1, 2 or 3 bytes */
1325 p = ptr + (size & ~3);
1326 if (size & 3)
1327 tail = p;
1328 }
1329
1330 /* If there is a trailing incomplete sequence move it to
1331 * conv_rest[]. */
1332 if (tail != NULL) {
1333 conv_restlen = (int)((ptr + size) - tail);
1334 memmove(conv_rest, tail, conv_restlen);
1335 size -= conv_restlen;
1336 }
1337
1338
1339 while (p > ptr) {
1340 if (fio_flags & FIO_LATIN1)
1341 u8c = *--p;
1342 else if (fio_flags & (FIO_UCS2 | FIO_UTF16)) {
1343 if (fio_flags & FIO_ENDIAN_L) {
1344 u8c = (*--p << 8);
1345 u8c += *--p;
1346 } else {
1347 u8c = *--p;
1348 u8c += (*--p << 8);
1349 }
1350 if ((fio_flags & FIO_UTF16)
1351 && u8c >= 0xdc00 && u8c <= 0xdfff) {
1352 int u16c;
1353
1354 if (p == ptr) {
1355 /* Missing leading word. */
1356 if (can_retry)
1357 goto rewind_retry;
1358 if (conv_error == 0)
1359 conv_error = readfile_linenr(linecnt,
1360 ptr, p);
1361 if (bad_char_behavior == BAD_DROP)
1362 continue;
1363 if (bad_char_behavior != BAD_KEEP)
1364 u8c = bad_char_behavior;
1365 }
1366
1367 /* found second word of double-word, get the first
1368 * word and compute the resulting character */
1369 if (fio_flags & FIO_ENDIAN_L) {
1370 u16c = (*--p << 8);
1371 u16c += *--p;
1372 } else {
1373 u16c = *--p;
1374 u16c += (*--p << 8);
1375 }
1376 u8c = 0x10000 + ((u16c & 0x3ff) << 10)
1377 + (u8c & 0x3ff);
1378
1379 /* Check if the word is indeed a leading word. */
1380 if (u16c < 0xd800 || u16c > 0xdbff) {
1381 if (can_retry)
1382 goto rewind_retry;
1383 if (conv_error == 0)
1384 conv_error = readfile_linenr(linecnt,
1385 ptr, p);
1386 if (bad_char_behavior == BAD_DROP)
1387 continue;
1388 if (bad_char_behavior != BAD_KEEP)
1389 u8c = bad_char_behavior;
1390 }
1391 }
1392 } else if (fio_flags & FIO_UCS4) {
1393 if (fio_flags & FIO_ENDIAN_L) {
1394 u8c = (unsigned)(*--p) << 24;
1395 u8c += (unsigned)(*--p) << 16;
1396 u8c += (unsigned)(*--p) << 8;
1397 u8c += *--p;
1398 } else { /* big endian */
1399 u8c = *--p;
1400 u8c += (unsigned)(*--p) << 8;
1401 u8c += (unsigned)(*--p) << 16;
1402 u8c += (unsigned)(*--p) << 24;
1403 }
1404 } else { /* UTF-8 */
1405 if (*--p < 0x80)
1406 u8c = *p;
1407 else {
1408 len = utf_head_off(ptr, p);
1409 p -= len;
1410 u8c = utf_ptr2char(p);
1411 if (len == 0) {
1412 /* Not a valid UTF-8 character, retry with
1413 * another fenc when possible, otherwise just
1414 * report the error. */
1415 if (can_retry)
1416 goto rewind_retry;
1417 if (conv_error == 0)
1418 conv_error = readfile_linenr(linecnt,
1419 ptr, p);
1420 if (bad_char_behavior == BAD_DROP)
1421 continue;
1422 if (bad_char_behavior != BAD_KEEP)
1423 u8c = bad_char_behavior;
1424 }
1425 }
1426 }
1427 assert(u8c <= INT_MAX);
1428 // produce UTF-8
1429 dest -= utf_char2len((int)u8c);
1430 (void)utf_char2bytes((int)u8c, dest);
1431 }
1432
1433 // move the linerest to before the converted characters
1434 line_start = dest - linerest;
1435 memmove(line_start, buffer, (size_t)linerest);
1436 size = (long)((ptr + real_size) - dest);
1437 ptr = dest;
1438 } else if (enc_utf8 && !curbuf->b_p_bin) {
1439 int incomplete_tail = FALSE;
1440
1441 // Reading UTF-8: Check if the bytes are valid UTF-8.
1442 for (p = ptr;; p++) {
1443 int todo = (int)((ptr + size) - p);
1444 int l;
1445
1446 if (todo <= 0) {
1447 break;
1448 }
1449 if (*p >= 0x80) {
1450 // A length of 1 means it's an illegal byte. Accept
1451 // an incomplete character at the end though, the next
1452 // read() will get the next bytes, we'll check it
1453 // then.
1454 l = utf_ptr2len_len(p, todo);
1455 if (l > todo && !incomplete_tail) {
1456 /* Avoid retrying with a different encoding when
1457 * a truncated file is more likely, or attempting
1458 * to read the rest of an incomplete sequence when
1459 * we have already done so. */
1460 if (p > ptr || filesize > 0)
1461 incomplete_tail = TRUE;
1462 /* Incomplete byte sequence, move it to conv_rest[]
1463 * and try to read the rest of it, unless we've
1464 * already done so. */
1465 if (p > ptr) {
1466 conv_restlen = todo;
1467 memmove(conv_rest, p, conv_restlen);
1468 size -= conv_restlen;
1469 break;
1470 }
1471 }
1472 if (l == 1 || l > todo) {
1473 /* Illegal byte. If we can try another encoding
1474 * do that, unless at EOF where a truncated
1475 * file is more likely than a conversion error. */
1476 if (can_retry && !incomplete_tail)
1477 break;
1478# ifdef HAVE_ICONV
1479 // When we did a conversion report an error.
1480 if (iconv_fd != (iconv_t)-1 && conv_error == 0) {
1481 conv_error = readfile_linenr(linecnt, ptr, p);
1482 }
1483# endif
1484 /* Remember the first linenr with an illegal byte */
1485 if (conv_error == 0 && illegal_byte == 0)
1486 illegal_byte = readfile_linenr(linecnt, ptr, p);
1487
1488 /* Drop, keep or replace the bad byte. */
1489 if (bad_char_behavior == BAD_DROP) {
1490 memmove(p, p + 1, todo - 1);
1491 --p;
1492 --size;
1493 } else if (bad_char_behavior != BAD_KEEP)
1494 *p = bad_char_behavior;
1495 } else
1496 p += l - 1;
1497 }
1498 }
1499 if (p < ptr + size && !incomplete_tail) {
1500 /* Detected a UTF-8 error. */
1501rewind_retry:
1502 // Retry reading with another conversion.
1503# ifdef HAVE_ICONV
1504 if (*p_ccv != NUL && iconv_fd != (iconv_t)-1) {
1505 // iconv() failed, try 'charconvert'
1506 did_iconv = true;
1507 } else {
1508# endif
1509 // use next item from 'fileencodings'
1510 advance_fenc = true;
1511# ifdef HAVE_ICONV
1512 }
1513# endif
1514 file_rewind = true;
1515 goto retry;
1516 }
1517 }
1518
1519 /* count the number of characters (after conversion!) */
1520 filesize += size;
1521
1522 /*
1523 * when reading the first part of a file: guess EOL type
1524 */
1525 if (fileformat == EOL_UNKNOWN) {
1526 /* First try finding a NL, for Dos and Unix */
1527 if (try_dos || try_unix) {
1528 // Reset the carriage return counter.
1529 if (try_mac) {
1530 try_mac = 1;
1531 }
1532
1533 for (p = ptr; p < ptr + size; ++p) {
1534 if (*p == NL) {
1535 if (!try_unix
1536 || (try_dos && p > ptr && p[-1] == CAR))
1537 fileformat = EOL_DOS;
1538 else
1539 fileformat = EOL_UNIX;
1540 break;
1541 } else if (*p == CAR && try_mac) {
1542 try_mac++;
1543 }
1544 }
1545
1546 /* Don't give in to EOL_UNIX if EOL_MAC is more likely */
1547 if (fileformat == EOL_UNIX && try_mac) {
1548 /* Need to reset the counters when retrying fenc. */
1549 try_mac = 1;
1550 try_unix = 1;
1551 for (; p >= ptr && *p != CAR; p--)
1552 ;
1553 if (p >= ptr) {
1554 for (p = ptr; p < ptr + size; ++p) {
1555 if (*p == NL)
1556 try_unix++;
1557 else if (*p == CAR)
1558 try_mac++;
1559 }
1560 if (try_mac > try_unix)
1561 fileformat = EOL_MAC;
1562 }
1563 } else if (fileformat == EOL_UNKNOWN && try_mac == 1) {
1564 // Looking for CR but found no end-of-line markers at all:
1565 // use the default format.
1566 fileformat = default_fileformat();
1567 }
1568 }
1569
1570 /* No NL found: may use Mac format */
1571 if (fileformat == EOL_UNKNOWN && try_mac)
1572 fileformat = EOL_MAC;
1573
1574 /* Still nothing found? Use first format in 'ffs' */
1575 if (fileformat == EOL_UNKNOWN)
1576 fileformat = default_fileformat();
1577
1578 // May set 'p_ff' if editing a new file.
1579 if (set_options) {
1580 set_fileformat(fileformat, OPT_LOCAL);
1581 }
1582 }
1583 }
1584
1585 /*
1586 * This loop is executed once for every character read.
1587 * Keep it fast!
1588 */
1589 if (fileformat == EOL_MAC) {
1590 --ptr;
1591 while (++ptr, --size >= 0) {
1592 /* catch most common case first */
1593 if ((c = *ptr) != NUL && c != CAR && c != NL)
1594 continue;
1595 if (c == NUL)
1596 *ptr = NL; /* NULs are replaced by newlines! */
1597 else if (c == NL)
1598 *ptr = CAR; /* NLs are replaced by CRs! */
1599 else {
1600 if (skip_count == 0) {
1601 *ptr = NUL; /* end of line */
1602 len = (colnr_T) (ptr - line_start + 1);
1603 if (ml_append(lnum, line_start, len, newfile) == FAIL) {
1604 error = TRUE;
1605 break;
1606 }
1607 if (read_undo_file)
1608 sha256_update(&sha_ctx, line_start, len);
1609 ++lnum;
1610 if (--read_count == 0) {
1611 error = TRUE; /* break loop */
1612 line_start = ptr; /* nothing left to write */
1613 break;
1614 }
1615 } else
1616 --skip_count;
1617 line_start = ptr + 1;
1618 }
1619 }
1620 } else {
1621 --ptr;
1622 while (++ptr, --size >= 0) {
1623 if ((c = *ptr) != NUL && c != NL) /* catch most common case */
1624 continue;
1625 if (c == NUL)
1626 *ptr = NL; /* NULs are replaced by newlines! */
1627 else {
1628 if (skip_count == 0) {
1629 *ptr = NUL; /* end of line */
1630 len = (colnr_T)(ptr - line_start + 1);
1631 if (fileformat == EOL_DOS) {
1632 if (ptr > line_start && ptr[-1] == CAR) {
1633 // remove CR before NL
1634 ptr[-1] = NUL;
1635 len--;
1636 } else if (ff_error != EOL_DOS) {
1637 // Reading in Dos format, but no CR-LF found!
1638 // When 'fileformats' includes "unix", delete all
1639 // the lines read so far and start all over again.
1640 // Otherwise give an error message later.
1641 if (try_unix
1642 && !read_stdin
1643 && (read_buffer
1644 || vim_lseek(fd, (off_T)0L, SEEK_SET) == 0)) {
1645 fileformat = EOL_UNIX;
1646 if (set_options)
1647 set_fileformat(EOL_UNIX, OPT_LOCAL);
1648 file_rewind = true;
1649 keep_fileformat = true;
1650 goto retry;
1651 }
1652 ff_error = EOL_DOS;
1653 }
1654 }
1655 if (ml_append(lnum, line_start, len, newfile) == FAIL) {
1656 error = TRUE;
1657 break;
1658 }
1659 if (read_undo_file)
1660 sha256_update(&sha_ctx, line_start, len);
1661 ++lnum;
1662 if (--read_count == 0) {
1663 error = TRUE; /* break loop */
1664 line_start = ptr; /* nothing left to write */
1665 break;
1666 }
1667 } else
1668 --skip_count;
1669 line_start = ptr + 1;
1670 }
1671 }
1672 }
1673 linerest = (long)(ptr - line_start);
1674 os_breakcheck();
1675 }
1676
1677failed:
1678 /* not an error, max. number of lines reached */
1679 if (error && read_count == 0)
1680 error = FALSE;
1681
1682 /*
1683 * If we get EOF in the middle of a line, note the fact and
1684 * complete the line ourselves.
1685 * In Dos format ignore a trailing CTRL-Z, unless 'binary' set.
1686 */
1687 if (!error
1688 && !got_int
1689 && linerest != 0
1690 && !(!curbuf->b_p_bin
1691 && fileformat == EOL_DOS
1692 && *line_start == Ctrl_Z
1693 && ptr == line_start + 1)) {
1694 /* remember for when writing */
1695 if (set_options)
1696 curbuf->b_p_eol = FALSE;
1697 *ptr = NUL;
1698 len = (colnr_T)(ptr - line_start + 1);
1699 if (ml_append(lnum, line_start, len, newfile) == FAIL)
1700 error = TRUE;
1701 else {
1702 if (read_undo_file)
1703 sha256_update(&sha_ctx, line_start, len);
1704 read_no_eol_lnum = ++lnum;
1705 }
1706 }
1707
1708 if (set_options) {
1709 // Remember the current file format.
1710 save_file_ff(curbuf);
1711 // If editing a new file: set 'fenc' for the current buffer.
1712 // Also for ":read ++edit file".
1713 set_string_option_direct((char_u *)"fenc", -1, fenc,
1714 OPT_FREE | OPT_LOCAL, 0);
1715 }
1716 if (fenc_alloced)
1717 xfree(fenc);
1718# ifdef HAVE_ICONV
1719 if (iconv_fd != (iconv_t)-1) {
1720 iconv_close(iconv_fd);
1721# ifndef __clang_analyzer__
1722 iconv_fd = (iconv_t)-1;
1723# endif
1724 }
1725# endif
1726
1727 if (!read_buffer && !read_stdin) {
1728 close(fd); // errors are ignored
1729 } else {
1730 (void)os_set_cloexec(fd);
1731 }
1732 xfree(buffer);
1733
1734 if (read_stdin) {
1735 close(0);
1736#ifndef WIN32
1737 // On Unix, use stderr for stdin, makes shell commands work.
1738 vim_ignored = dup(2);
1739#else
1740 // On Windows, use the console input handle for stdin.
1741 HANDLE conin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
1742 FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES)NULL,
1743 OPEN_EXISTING, 0, (HANDLE)NULL);
1744 vim_ignored = _open_osfhandle(conin, _O_RDONLY);
1745#endif
1746 }
1747
1748 if (tmpname != NULL) {
1749 os_remove((char *)tmpname); // delete converted file
1750 xfree(tmpname);
1751 }
1752 --no_wait_return; /* may wait for return now */
1753
1754 /*
1755 * In recovery mode everything but autocommands is skipped.
1756 */
1757 if (!recoverymode) {
1758 /* need to delete the last line, which comes from the empty buffer */
1759 if (newfile && wasempty && !(curbuf->b_ml.ml_flags & ML_EMPTY)) {
1760 ml_delete(curbuf->b_ml.ml_line_count, false);
1761 linecnt--;
1762 }
1763 curbuf->deleted_bytes = 0;
1764 curbuf->deleted_codepoints = 0;
1765 curbuf->deleted_codeunits = 0;
1766 linecnt = curbuf->b_ml.ml_line_count - linecnt;
1767 if (filesize == 0)
1768 linecnt = 0;
1769 if (newfile || read_buffer) {
1770 redraw_curbuf_later(NOT_VALID);
1771 /* After reading the text into the buffer the diff info needs to
1772 * be updated. */
1773 diff_invalidate(curbuf);
1774 /* All folds in the window are invalid now. Mark them for update
1775 * before triggering autocommands. */
1776 foldUpdateAll(curwin);
1777 } else if (linecnt) /* appended at least one line */
1778 appended_lines_mark(from, linecnt);
1779
1780 /*
1781 * If we were reading from the same terminal as where messages go,
1782 * the screen will have been messed up.
1783 * Switch on raw mode now and clear the screen.
1784 */
1785 if (read_stdin) {
1786 screenclear();
1787 }
1788
1789 if (got_int) {
1790 if (!(flags & READ_DUMMY)) {
1791 filemess(curbuf, sfname, (char_u *)_(e_interr), 0);
1792 if (newfile)
1793 curbuf->b_p_ro = TRUE; /* must use "w!" now */
1794 }
1795 msg_scroll = msg_save;
1796 check_marks_read();
1797 return OK; /* an interrupt isn't really an error */
1798 }
1799
1800 if (!filtering && !(flags & READ_DUMMY)) {
1801 add_quoted_fname((char *)IObuff, IOSIZE, curbuf, (const char *)sfname);
1802 c = false;
1803
1804#ifdef UNIX
1805# ifdef S_ISFIFO
1806 if (S_ISFIFO(perm)) { /* fifo or socket */
1807 STRCAT(IObuff, _("[fifo/socket]"));
1808 c = TRUE;
1809 }
1810# else
1811# ifdef S_IFIFO
1812 if ((perm & S_IFMT) == S_IFIFO) { /* fifo */
1813 STRCAT(IObuff, _("[fifo]"));
1814 c = TRUE;
1815 }
1816# endif
1817# ifdef S_IFSOCK
1818 if ((perm & S_IFMT) == S_IFSOCK) { /* or socket */
1819 STRCAT(IObuff, _("[socket]"));
1820 c = TRUE;
1821 }
1822# endif
1823# endif
1824# ifdef OPEN_CHR_FILES
1825 if (S_ISCHR(perm)) { /* or character special */
1826 STRCAT(IObuff, _("[character special]"));
1827 c = TRUE;
1828 }
1829# endif
1830#endif
1831 if (curbuf->b_p_ro) {
1832 STRCAT(IObuff, shortmess(SHM_RO) ? _("[RO]") : _("[readonly]"));
1833 c = TRUE;
1834 }
1835 if (read_no_eol_lnum) {
1836 msg_add_eol();
1837 c = TRUE;
1838 }
1839 if (ff_error == EOL_DOS) {
1840 STRCAT(IObuff, _("[CR missing]"));
1841 c = TRUE;
1842 }
1843 if (notconverted) {
1844 STRCAT(IObuff, _("[NOT converted]"));
1845 c = TRUE;
1846 } else if (converted) {
1847 STRCAT(IObuff, _("[converted]"));
1848 c = TRUE;
1849 }
1850 if (conv_error != 0) {
1851 sprintf((char *)IObuff + STRLEN(IObuff),
1852 _("[CONVERSION ERROR in line %" PRId64 "]"), (int64_t)conv_error);
1853 c = TRUE;
1854 } else if (illegal_byte > 0) {
1855 sprintf((char *)IObuff + STRLEN(IObuff),
1856 _("[ILLEGAL BYTE in line %" PRId64 "]"), (int64_t)illegal_byte);
1857 c = TRUE;
1858 } else if (error) {
1859 STRCAT(IObuff, _("[READ ERRORS]"));
1860 c = TRUE;
1861 }
1862 if (msg_add_fileformat(fileformat))
1863 c = TRUE;
1864
1865 msg_add_lines(c, (long)linecnt, filesize);
1866
1867 XFREE_CLEAR(keep_msg);
1868 p = NULL;
1869 msg_scrolled_ign = TRUE;
1870
1871 if (!read_stdin && !read_buffer) {
1872 p = msg_trunc_attr(IObuff, FALSE, 0);
1873 }
1874
1875 if (read_stdin || read_buffer || restart_edit != 0
1876 || (msg_scrolled != 0 && !need_wait_return)) {
1877 // Need to repeat the message after redrawing when:
1878 // - When reading from stdin (the screen will be cleared next).
1879 // - When restart_edit is set (otherwise there will be a delay before
1880 // redrawing).
1881 // - When the screen was scrolled but there is no wait-return prompt.
1882 set_keep_msg(p, 0);
1883 }
1884 msg_scrolled_ign = FALSE;
1885 }
1886
1887 /* with errors writing the file requires ":w!" */
1888 if (newfile && (error
1889 || conv_error != 0
1890 || (illegal_byte > 0 && bad_char_behavior != BAD_KEEP)
1891 ))
1892 curbuf->b_p_ro = TRUE;
1893
1894 u_clearline(); /* cannot use "U" command after adding lines */
1895
1896 /*
1897 * In Ex mode: cursor at last new line.
1898 * Otherwise: cursor at first new line.
1899 */
1900 if (exmode_active)
1901 curwin->w_cursor.lnum = from + linecnt;
1902 else
1903 curwin->w_cursor.lnum = from + 1;
1904 check_cursor_lnum();
1905 beginline(BL_WHITE | BL_FIX); /* on first non-blank */
1906
1907 /*
1908 * Set '[ and '] marks to the newly read lines.
1909 */
1910 curbuf->b_op_start.lnum = from + 1;
1911 curbuf->b_op_start.col = 0;
1912 curbuf->b_op_end.lnum = from + linecnt;
1913 curbuf->b_op_end.col = 0;
1914
1915 }
1916 msg_scroll = msg_save;
1917
1918 /*
1919 * Get the marks before executing autocommands, so they can be used there.
1920 */
1921 check_marks_read();
1922
1923 /*
1924 * We remember if the last line of the read didn't have
1925 * an eol even when 'binary' is off, to support turning 'fixeol' off,
1926 * or writing the read again with 'binary' on. The latter is required
1927 * for ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work.
1928 */
1929 curbuf->b_no_eol_lnum = read_no_eol_lnum;
1930
1931 /* When reloading a buffer put the cursor at the first line that is
1932 * different. */
1933 if (flags & READ_KEEP_UNDO)
1934 u_find_first_changed();
1935
1936 /*
1937 * When opening a new file locate undo info and read it.
1938 */
1939 if (read_undo_file) {
1940 char_u hash[UNDO_HASH_SIZE];
1941
1942 sha256_finish(&sha_ctx, hash);
1943 u_read_undo(NULL, hash, fname);
1944 }
1945
1946 if (!read_stdin && !read_fifo && (!read_buffer || sfname != NULL)) {
1947 int m = msg_scroll;
1948 int n = msg_scrolled;
1949
1950 /* Save the fileformat now, otherwise the buffer will be considered
1951 * modified if the format/encoding was automatically detected. */
1952 if (set_options)
1953 save_file_ff(curbuf);
1954
1955 /*
1956 * The output from the autocommands should not overwrite anything and
1957 * should not be overwritten: Set msg_scroll, restore its value if no
1958 * output was done.
1959 */
1960 msg_scroll = true;
1961 if (filtering) {
1962 apply_autocmds_exarg(EVENT_FILTERREADPOST, NULL, sfname,
1963 false, curbuf, eap);
1964 } else if (newfile || (read_buffer && sfname != NULL)) {
1965 apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname,
1966 false, curbuf, eap);
1967 if (!au_did_filetype && *curbuf->b_p_ft != NUL) {
1968 // EVENT_FILETYPE was not triggered but the buffer already has a
1969 // filetype. Trigger EVENT_FILETYPE using the existing filetype.
1970 apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname,
1971 true, curbuf);
1972 }
1973 } else {
1974 apply_autocmds_exarg(EVENT_FILEREADPOST, sfname, sfname,
1975 false, NULL, eap);
1976 }
1977 if (msg_scrolled == n) {
1978 msg_scroll = m;
1979 }
1980 if (aborting()) { // autocmds may abort script processing
1981 return FAIL;
1982 }
1983 }
1984
1985 if (recoverymode && error)
1986 return FAIL;
1987 return OK;
1988}
1989
1990#ifdef OPEN_CHR_FILES
1991/// Returns true if the file name argument is of the form "/dev/fd/\d\+",
1992/// which is the name of files used for process substitution output by
1993/// some shells on some operating systems, e.g., bash on SunOS.
1994/// Do not accept "/dev/fd/[012]", opening these may hang Vim.
1995///
1996/// @param fname file name to check
1997bool is_dev_fd_file(char_u *fname)
1998 FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
1999{
2000 return STRNCMP(fname, "/dev/fd/", 8) == 0
2001 && ascii_isdigit(fname[8])
2002 && *skipdigits(fname + 9) == NUL
2003 && (fname[9] != NUL
2004 || (fname[8] != '0' && fname[8] != '1' && fname[8] != '2'));
2005}
2006#endif
2007
2008
2009/*
2010 * From the current line count and characters read after that, estimate the
2011 * line number where we are now.
2012 * Used for error messages that include a line number.
2013 */
2014static linenr_T
2015readfile_linenr(
2016 linenr_T linecnt, // line count before reading more bytes
2017 char_u *p, // start of more bytes read
2018 char_u *endp // end of more bytes read
2019)
2020{
2021 char_u *s;
2022 linenr_T lnum;
2023
2024 lnum = curbuf->b_ml.ml_line_count - linecnt + 1;
2025 for (s = p; s < endp; ++s)
2026 if (*s == '\n')
2027 ++lnum;
2028 return lnum;
2029}
2030
2031/*
2032 * Fill "*eap" to force the 'fileencoding', 'fileformat' and 'binary to be
2033 * equal to the buffer "buf". Used for calling readfile().
2034 */
2035void prep_exarg(exarg_T *eap, buf_T *buf)
2036{
2037 eap->cmd = xmalloc(STRLEN(buf->b_p_ff) + STRLEN(buf->b_p_fenc) + 15);
2038
2039 sprintf((char *)eap->cmd, "e ++ff=%s ++enc=%s", buf->b_p_ff, buf->b_p_fenc);
2040 eap->force_enc = 14 + (int)STRLEN(buf->b_p_ff);
2041 eap->bad_char = buf->b_bad_char;
2042 eap->force_ff = 7;
2043
2044 eap->force_bin = buf->b_p_bin ? FORCE_BIN : FORCE_NOBIN;
2045 eap->read_edit = FALSE;
2046 eap->forceit = FALSE;
2047}
2048
2049/*
2050 * Set default or forced 'fileformat' and 'binary'.
2051 */
2052void set_file_options(int set_options, exarg_T *eap)
2053{
2054 /* set default 'fileformat' */
2055 if (set_options) {
2056 if (eap != NULL && eap->force_ff != 0)
2057 set_fileformat(get_fileformat_force(curbuf, eap), OPT_LOCAL);
2058 else if (*p_ffs != NUL)
2059 set_fileformat(default_fileformat(), OPT_LOCAL);
2060 }
2061
2062 /* set or reset 'binary' */
2063 if (eap != NULL && eap->force_bin != 0) {
2064 int oldval = curbuf->b_p_bin;
2065
2066 curbuf->b_p_bin = (eap->force_bin == FORCE_BIN);
2067 set_options_bin(oldval, curbuf->b_p_bin, OPT_LOCAL);
2068 }
2069}
2070
2071/*
2072 * Set forced 'fileencoding'.
2073 */
2074void set_forced_fenc(exarg_T *eap)
2075{
2076 if (eap->force_enc != 0) {
2077 char_u *fenc = enc_canonize(eap->cmd + eap->force_enc);
2078 set_string_option_direct((char_u *)"fenc", -1, fenc, OPT_FREE|OPT_LOCAL, 0);
2079 xfree(fenc);
2080 }
2081}
2082
2083// Find next fileencoding to use from 'fileencodings'.
2084// "pp" points to fenc_next. It's advanced to the next item.
2085// When there are no more items, an empty string is returned and *pp is set to
2086// NULL.
2087// When *pp is not set to NULL, the result is in allocated memory and "alloced"
2088// is set to true.
2089static char_u *next_fenc(char_u **pp, bool *alloced)
2090 FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
2091{
2092 char_u *p;
2093 char_u *r;
2094
2095 *alloced = false;
2096 if (**pp == NUL) {
2097 *pp = NULL;
2098 return (char_u *)"";
2099 }
2100 p = vim_strchr(*pp, ',');
2101 if (p == NULL) {
2102 r = enc_canonize(*pp);
2103 *pp += STRLEN(*pp);
2104 } else {
2105 r = vim_strnsave(*pp, (int)(p - *pp));
2106 *pp = p + 1;
2107 p = enc_canonize(r);
2108 xfree(r);
2109 r = p;
2110 }
2111 *alloced = true;
2112 return r;
2113}
2114
2115/*
2116 * Convert a file with the 'charconvert' expression.
2117 * This closes the file which is to be read, converts it and opens the
2118 * resulting file for reading.
2119 * Returns name of the resulting converted file (the caller should delete it
2120 * after reading it).
2121 * Returns NULL if the conversion failed ("*fdp" is not set) .
2122 */
2123static char_u *
2124readfile_charconvert (
2125 char_u *fname, /* name of input file */
2126 char_u *fenc, /* converted from */
2127 int *fdp /* in/out: file descriptor of file */
2128)
2129{
2130 char_u *tmpname;
2131 char_u *errmsg = NULL;
2132
2133 tmpname = vim_tempname();
2134 if (tmpname == NULL)
2135 errmsg = (char_u *)_("Can't find temp file for conversion");
2136 else {
2137 close(*fdp); /* close the input file, ignore errors */
2138 *fdp = -1;
2139 if (eval_charconvert((char *) fenc, enc_utf8 ? "utf-8" : (char *) p_enc,
2140 (char *) fname, (char *) tmpname) == FAIL) {
2141 errmsg = (char_u *)_("Conversion with 'charconvert' failed");
2142 }
2143 if (errmsg == NULL && (*fdp = os_open((char *)tmpname, O_RDONLY, 0)) < 0) {
2144 errmsg = (char_u *)_("can't read output of 'charconvert'");
2145 }
2146 }
2147
2148 if (errmsg != NULL) {
2149 /* Don't use emsg(), it breaks mappings, the retry with
2150 * another type of conversion might still work. */
2151 MSG(errmsg);
2152 if (tmpname != NULL) {
2153 os_remove((char *)tmpname); // delete converted file
2154 XFREE_CLEAR(tmpname);
2155 }
2156 }
2157
2158 /* If the input file is closed, open it (caller should check for error). */
2159 if (*fdp < 0) {
2160 *fdp = os_open((char *)fname, O_RDONLY, 0);
2161 }
2162
2163 return tmpname;
2164}
2165
2166
2167/*
2168 * Read marks for the current buffer from the ShaDa file, when we support
2169 * buffer marks and the buffer has a name.
2170 */
2171static void check_marks_read(void)
2172{
2173 if (!curbuf->b_marks_read && get_shada_parameter('\'') > 0
2174 && curbuf->b_ffname != NULL) {
2175 shada_read_marks();
2176 }
2177
2178 /* Always set b_marks_read; needed when 'shada' is changed to include
2179 * the ' parameter after opening a buffer. */
2180 curbuf->b_marks_read = true;
2181}
2182
2183/*
2184 * buf_write() - write to file "fname" lines "start" through "end"
2185 *
2186 * We do our own buffering here because fwrite() is so slow.
2187 *
2188 * If "forceit" is true, we don't care for errors when attempting backups.
2189 * In case of an error everything possible is done to restore the original
2190 * file. But when "forceit" is TRUE, we risk losing it.
2191 *
2192 * When "reset_changed" is TRUE and "append" == FALSE and "start" == 1 and
2193 * "end" == curbuf->b_ml.ml_line_count, reset curbuf->b_changed.
2194 *
2195 * This function must NOT use NameBuff (because it's called by autowrite()).
2196 *
2197 * return FAIL for failure, OK otherwise
2198 */
2199int
2200buf_write(
2201 buf_T *buf,
2202 char_u *fname,
2203 char_u *sfname,
2204 linenr_T start,
2205 linenr_T end,
2206 exarg_T *eap, /* for forced 'ff' and 'fenc', can be
2207 NULL! */
2208 int append, /* append to the file */
2209 int forceit,
2210 int reset_changed,
2211 int filtering
2212)
2213{
2214 int fd;
2215 char_u *backup = NULL;
2216 int backup_copy = FALSE; /* copy the original file? */
2217 int dobackup;
2218 char_u *ffname;
2219 char_u *wfname = NULL; /* name of file to write to */
2220 char_u *s;
2221 char_u *ptr;
2222 char_u c;
2223 int len;
2224 linenr_T lnum;
2225 long nchars;
2226#define SET_ERRMSG_NUM(num, msg) \
2227 errnum = num, errmsg = msg, errmsgarg = 0
2228#define SET_ERRMSG_ARG(msg, error) \
2229 errnum = NULL, errmsg = msg, errmsgarg = error
2230#define SET_ERRMSG(msg) \
2231 errnum = NULL, errmsg = msg, errmsgarg = 0
2232 const char *errnum = NULL;
2233 char *errmsg = NULL;
2234 int errmsgarg = 0;
2235 bool errmsg_allocated = false;
2236 char_u *buffer;
2237 char_u smallbuf[SMBUFSIZE];
2238 char_u *backup_ext;
2239 int bufsize;
2240 long perm; // file permissions
2241 int retval = OK;
2242 int newfile = false; // TRUE if file doesn't exist yet
2243 int msg_save = msg_scroll;
2244 int overwriting; // TRUE if writing over original
2245 int no_eol = false; // no end-of-line written
2246 int device = false; // writing to a device
2247 int prev_got_int = got_int;
2248 int checking_conversion;
2249 bool file_readonly = false; // overwritten file is read-only
2250 static char *err_readonly =
2251 "is read-only (cannot override: \"W\" in 'cpoptions')";
2252#if defined(UNIX)
2253 int made_writable = FALSE; /* 'w' bit has been set */
2254#endif
2255 /* writing everything */
2256 int whole = (start == 1 && end == buf->b_ml.ml_line_count);
2257 linenr_T old_line_count = buf->b_ml.ml_line_count;
2258 int fileformat;
2259 int write_bin;
2260 struct bw_info write_info; /* info for buf_write_bytes() */
2261 int converted = FALSE;
2262 int notconverted = FALSE;
2263 char_u *fenc; /* effective 'fileencoding' */
2264 char_u *fenc_tofree = NULL; /* allocated "fenc" */
2265#ifdef HAS_BW_FLAGS
2266 int wb_flags = 0;
2267#endif
2268#ifdef HAVE_ACL
2269 vim_acl_T acl = NULL; /* ACL copied from original file to
2270 backup or new file */
2271#endif
2272 int write_undo_file = FALSE;
2273 context_sha256_T sha_ctx;
2274 unsigned int bkc = get_bkc_value(buf);
2275
2276 if (fname == NULL || *fname == NUL) /* safety check */
2277 return FAIL;
2278 if (buf->b_ml.ml_mfp == NULL) {
2279 /* This can happen during startup when there is a stray "w" in the
2280 * vimrc file. */
2281 EMSG(_(e_emptybuf));
2282 return FAIL;
2283 }
2284
2285 /*
2286 * Disallow writing from .exrc and .vimrc in current directory for
2287 * security reasons.
2288 */
2289 if (check_secure())
2290 return FAIL;
2291
2292 /* Avoid a crash for a long name. */
2293 if (STRLEN(fname) >= MAXPATHL) {
2294 EMSG(_(e_longname));
2295 return FAIL;
2296 }
2297
2298 /* must init bw_conv_buf and bw_iconv_fd before jumping to "fail" */
2299 write_info.bw_conv_buf = NULL;
2300 write_info.bw_conv_error = FALSE;
2301 write_info.bw_conv_error_lnum = 0;
2302 write_info.bw_restlen = 0;
2303# ifdef HAVE_ICONV
2304 write_info.bw_iconv_fd = (iconv_t)-1;
2305# endif
2306
2307 /* After writing a file changedtick changes but we don't want to display
2308 * the line. */
2309 ex_no_reprint = TRUE;
2310
2311 /*
2312 * If there is no file name yet, use the one for the written file.
2313 * BF_NOTEDITED is set to reflect this (in case the write fails).
2314 * Don't do this when the write is for a filter command.
2315 * Don't do this when appending.
2316 * Only do this when 'cpoptions' contains the 'F' flag.
2317 */
2318 if (buf->b_ffname == NULL
2319 && reset_changed
2320 && whole
2321 && buf == curbuf
2322 && !bt_nofile(buf)
2323 && !filtering
2324 && (!append || vim_strchr(p_cpo, CPO_FNAMEAPP) != NULL)
2325 && vim_strchr(p_cpo, CPO_FNAMEW) != NULL) {
2326 if (set_rw_fname(fname, sfname) == FAIL)
2327 return FAIL;
2328 buf = curbuf; /* just in case autocmds made "buf" invalid */
2329 }
2330
2331 if (sfname == NULL)
2332 sfname = fname;
2333
2334 // For Unix: Use the short file name whenever possible.
2335 // Avoids problems with networks and when directory names are changed.
2336 // Don't do this for Windows, a "cd" in a sub-shell may have moved us to
2337 // another directory, which we don't detect.
2338 ffname = fname; // remember full fname
2339#ifdef UNIX
2340 fname = sfname;
2341#endif
2342
2343 if (buf->b_ffname != NULL && fnamecmp(ffname, buf->b_ffname) == 0)
2344 overwriting = TRUE;
2345 else
2346 overwriting = FALSE;
2347
2348 ++no_wait_return; /* don't wait for return yet */
2349
2350 /*
2351 * Set '[ and '] marks to the lines to be written.
2352 */
2353 buf->b_op_start.lnum = start;
2354 buf->b_op_start.col = 0;
2355 buf->b_op_end.lnum = end;
2356 buf->b_op_end.col = 0;
2357
2358 {
2359 aco_save_T aco;
2360 int buf_ffname = FALSE;
2361 int buf_sfname = FALSE;
2362 int buf_fname_f = FALSE;
2363 int buf_fname_s = FALSE;
2364 int did_cmd = FALSE;
2365 int nofile_err = FALSE;
2366 int empty_memline = (buf->b_ml.ml_mfp == NULL);
2367 bufref_T bufref;
2368
2369 /*
2370 * Apply PRE autocommands.
2371 * Set curbuf to the buffer to be written.
2372 * Careful: The autocommands may call buf_write() recursively!
2373 */
2374 if (ffname == buf->b_ffname)
2375 buf_ffname = TRUE;
2376 if (sfname == buf->b_sfname)
2377 buf_sfname = TRUE;
2378 if (fname == buf->b_ffname)
2379 buf_fname_f = TRUE;
2380 if (fname == buf->b_sfname)
2381 buf_fname_s = TRUE;
2382
2383 // Set curwin/curbuf to buf and save a few things.
2384 aucmd_prepbuf(&aco, buf);
2385 set_bufref(&bufref, buf);
2386
2387 if (append) {
2388 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEAPPENDCMD,
2389 sfname, sfname, FALSE, curbuf, eap))) {
2390 if (overwriting && bt_nofile(curbuf))
2391 nofile_err = TRUE;
2392 else
2393 apply_autocmds_exarg(EVENT_FILEAPPENDPRE,
2394 sfname, sfname, FALSE, curbuf, eap);
2395 }
2396 } else if (filtering) {
2397 apply_autocmds_exarg(EVENT_FILTERWRITEPRE,
2398 NULL, sfname, FALSE, curbuf, eap);
2399 } else if (reset_changed && whole) {
2400 int was_changed = curbufIsChanged();
2401
2402 did_cmd = apply_autocmds_exarg(EVENT_BUFWRITECMD,
2403 sfname, sfname, FALSE, curbuf, eap);
2404 if (did_cmd) {
2405 if (was_changed && !curbufIsChanged()) {
2406 /* Written everything correctly and BufWriteCmd has reset
2407 * 'modified': Correct the undo information so that an
2408 * undo now sets 'modified'. */
2409 u_unchanged(curbuf);
2410 u_update_save_nr(curbuf);
2411 }
2412 } else {
2413 if (overwriting && bt_nofile(curbuf))
2414 nofile_err = TRUE;
2415 else
2416 apply_autocmds_exarg(EVENT_BUFWRITEPRE,
2417 sfname, sfname, FALSE, curbuf, eap);
2418 }
2419 } else {
2420 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEWRITECMD,
2421 sfname, sfname, FALSE, curbuf, eap))) {
2422 if (overwriting && bt_nofile(curbuf))
2423 nofile_err = TRUE;
2424 else
2425 apply_autocmds_exarg(EVENT_FILEWRITEPRE,
2426 sfname, sfname, FALSE, curbuf, eap);
2427 }
2428 }
2429
2430 /* restore curwin/curbuf and a few other things */
2431 aucmd_restbuf(&aco);
2432
2433 // In three situations we return here and don't write the file:
2434 // 1. the autocommands deleted or unloaded the buffer.
2435 // 2. The autocommands abort script processing.
2436 // 3. If one of the "Cmd" autocommands was executed.
2437 if (!bufref_valid(&bufref)) {
2438 buf = NULL;
2439 }
2440 if (buf == NULL || (buf->b_ml.ml_mfp == NULL && !empty_memline)
2441 || did_cmd || nofile_err
2442 || aborting()
2443 ) {
2444 --no_wait_return;
2445 msg_scroll = msg_save;
2446 if (nofile_err)
2447 EMSG(_("E676: No matching autocommands for acwrite buffer"));
2448
2449 if (nofile_err
2450 || aborting()
2451 )
2452 /* An aborting error, interrupt or exception in the
2453 * autocommands. */
2454 return FAIL;
2455 if (did_cmd) {
2456 if (buf == NULL)
2457 /* The buffer was deleted. We assume it was written
2458 * (can't retry anyway). */
2459 return OK;
2460 if (overwriting) {
2461 /* Assume the buffer was written, update the timestamp. */
2462 ml_timestamp(buf);
2463 if (append)
2464 buf->b_flags &= ~BF_NEW;
2465 else
2466 buf->b_flags &= ~BF_WRITE_MASK;
2467 }
2468 if (reset_changed && buf->b_changed && !append
2469 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL))
2470 /* Buffer still changed, the autocommands didn't work
2471 * properly. */
2472 return FAIL;
2473 return OK;
2474 }
2475 if (!aborting())
2476 EMSG(_("E203: Autocommands deleted or unloaded buffer to be written"));
2477 return FAIL;
2478 }
2479
2480 /*
2481 * The autocommands may have changed the number of lines in the file.
2482 * When writing the whole file, adjust the end.
2483 * When writing part of the file, assume that the autocommands only
2484 * changed the number of lines that are to be written (tricky!).
2485 */
2486 if (buf->b_ml.ml_line_count != old_line_count) {
2487 if (whole) /* write all */
2488 end = buf->b_ml.ml_line_count;
2489 else if (buf->b_ml.ml_line_count > old_line_count) /* more lines */
2490 end += buf->b_ml.ml_line_count - old_line_count;
2491 else { /* less lines */
2492 end -= old_line_count - buf->b_ml.ml_line_count;
2493 if (end < start) {
2494 --no_wait_return;
2495 msg_scroll = msg_save;
2496 EMSG(_("E204: Autocommand changed number of lines in unexpected way"));
2497 return FAIL;
2498 }
2499 }
2500 }
2501
2502 /*
2503 * The autocommands may have changed the name of the buffer, which may
2504 * be kept in fname, ffname and sfname.
2505 */
2506 if (buf_ffname)
2507 ffname = buf->b_ffname;
2508 if (buf_sfname)
2509 sfname = buf->b_sfname;
2510 if (buf_fname_f)
2511 fname = buf->b_ffname;
2512 if (buf_fname_s)
2513 fname = buf->b_sfname;
2514 }
2515
2516
2517 if (shortmess(SHM_OVER) && !exiting)
2518 msg_scroll = FALSE; /* overwrite previous file message */
2519 else
2520 msg_scroll = TRUE; /* don't overwrite previous file message */
2521 if (!filtering)
2522 filemess(buf,
2523#ifndef UNIX
2524 sfname,
2525#else
2526 fname,
2527#endif
2528 (char_u *)"", 0); /* show that we are busy */
2529 msg_scroll = FALSE; /* always overwrite the file message now */
2530
2531 buffer = verbose_try_malloc(BUFSIZE);
2532 // can't allocate big buffer, use small one (to be able to write when out of
2533 // memory)
2534 if (buffer == NULL) {
2535 buffer = smallbuf;
2536 bufsize = SMBUFSIZE;
2537 } else
2538 bufsize = BUFSIZE;
2539
2540 /*
2541 * Get information about original file (if there is one).
2542 */
2543 FileInfo file_info_old;
2544#if defined(UNIX)
2545 perm = -1;
2546 if (!os_fileinfo((char *)fname, &file_info_old)) {
2547 newfile = TRUE;
2548 } else {
2549 perm = file_info_old.stat.st_mode;
2550 if (!S_ISREG(file_info_old.stat.st_mode)) { /* not a file */
2551 if (S_ISDIR(file_info_old.stat.st_mode)) {
2552 SET_ERRMSG_NUM("E502", _("is a directory"));
2553 goto fail;
2554 }
2555 if (os_nodetype((char *)fname) != NODE_WRITABLE) {
2556 SET_ERRMSG_NUM("E503", _("is not a file or writable device"));
2557 goto fail;
2558 }
2559 /* It's a device of some kind (or a fifo) which we can write to
2560 * but for which we can't make a backup. */
2561 device = TRUE;
2562 newfile = TRUE;
2563 perm = -1;
2564 }
2565 }
2566#else // win32
2567 // Check for a writable device name.
2568 c = fname == NULL ? NODE_OTHER : os_nodetype((char *)fname);
2569 if (c == NODE_OTHER) {
2570 SET_ERRMSG_NUM("E503", _("is not a file or writable device"));
2571 goto fail;
2572 }
2573 if (c == NODE_WRITABLE) {
2574 device = TRUE;
2575 newfile = TRUE;
2576 perm = -1;
2577 } else {
2578 perm = os_getperm((const char *)fname);
2579 if (perm < 0) {
2580 newfile = true;
2581 } else if (os_isdir(fname)) {
2582 SET_ERRMSG_NUM("E502", _("is a directory"));
2583 goto fail;
2584 }
2585 if (overwriting) {
2586 os_fileinfo((char *)fname, &file_info_old);
2587 }
2588 }
2589#endif // !UNIX
2590
2591 if (!device && !newfile) {
2592 /*
2593 * Check if the file is really writable (when renaming the file to
2594 * make a backup we won't discover it later).
2595 */
2596 file_readonly = !os_file_is_writable((char *)fname);
2597
2598 if (!forceit && file_readonly) {
2599 if (vim_strchr(p_cpo, CPO_FWRITE) != NULL) {
2600 SET_ERRMSG_NUM("E504", _(err_readonly));
2601 } else {
2602 SET_ERRMSG_NUM("E505", _("is read-only (add ! to override)"));
2603 }
2604 goto fail;
2605 }
2606
2607 /*
2608 * Check if the timestamp hasn't changed since reading the file.
2609 */
2610 if (overwriting) {
2611 retval = check_mtime(buf, &file_info_old);
2612 if (retval == FAIL)
2613 goto fail;
2614 }
2615 }
2616
2617#ifdef HAVE_ACL
2618 /*
2619 * For systems that support ACL: get the ACL from the original file.
2620 */
2621 if (!newfile)
2622 acl = mch_get_acl(fname);
2623#endif
2624
2625 /*
2626 * If 'backupskip' is not empty, don't make a backup for some files.
2627 */
2628 dobackup = (p_wb || p_bk || *p_pm != NUL);
2629 if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, sfname, ffname))
2630 dobackup = FALSE;
2631
2632 /*
2633 * Save the value of got_int and reset it. We don't want a previous
2634 * interruption cancel writing, only hitting CTRL-C while writing should
2635 * abort it.
2636 */
2637 prev_got_int = got_int;
2638 got_int = FALSE;
2639
2640 /* Mark the buffer as 'being saved' to prevent changed buffer warnings */
2641 buf->b_saving = true;
2642
2643 /*
2644 * If we are not appending or filtering, the file exists, and the
2645 * 'writebackup', 'backup' or 'patchmode' option is set, need a backup.
2646 * When 'patchmode' is set also make a backup when appending.
2647 *
2648 * Do not make any backup, if 'writebackup' and 'backup' are both switched
2649 * off. This helps when editing large files on almost-full disks.
2650 */
2651 if (!(append && *p_pm == NUL) && !filtering && perm >= 0 && dobackup) {
2652 FileInfo file_info;
2653
2654 if ((bkc & BKC_YES) || append) { /* "yes" */
2655 backup_copy = TRUE;
2656 } else if ((bkc & BKC_AUTO)) { /* "auto" */
2657 int i;
2658
2659 /*
2660 * Don't rename the file when:
2661 * - it's a hard link
2662 * - it's a symbolic link
2663 * - we don't have write permission in the directory
2664 */
2665 if (os_fileinfo_hardlinks(&file_info_old) > 1
2666 || !os_fileinfo_link((char *)fname, &file_info)
2667 || !os_fileinfo_id_equal(&file_info, &file_info_old)) {
2668 backup_copy = TRUE;
2669 } else {
2670 /*
2671 * Check if we can create a file and set the owner/group to
2672 * the ones from the original file.
2673 * First find a file name that doesn't exist yet (use some
2674 * arbitrary numbers).
2675 */
2676 STRCPY(IObuff, fname);
2677 for (i = 4913;; i += 123) {
2678 sprintf((char *)path_tail(IObuff), "%d", i);
2679 if (!os_fileinfo_link((char *)IObuff, &file_info)) {
2680 break;
2681 }
2682 }
2683 fd = os_open((char *)IObuff,
2684 O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm);
2685 if (fd < 0) /* can't write in directory */
2686 backup_copy = TRUE;
2687 else {
2688# ifdef UNIX
2689 os_fchown(fd, file_info_old.stat.st_uid, file_info_old.stat.st_gid);
2690 if (!os_fileinfo((char *)IObuff, &file_info)
2691 || file_info.stat.st_uid != file_info_old.stat.st_uid
2692 || file_info.stat.st_gid != file_info_old.stat.st_gid
2693 || (long)file_info.stat.st_mode != perm) {
2694 backup_copy = TRUE;
2695 }
2696# endif
2697 /* Close the file before removing it, on MS-Windows we
2698 * can't delete an open file. */
2699 close(fd);
2700 os_remove((char *)IObuff);
2701 }
2702 }
2703 }
2704
2705 /*
2706 * Break symlinks and/or hardlinks if we've been asked to.
2707 */
2708 if ((bkc & BKC_BREAKSYMLINK) || (bkc & BKC_BREAKHARDLINK)) {
2709# ifdef UNIX
2710 bool file_info_link_ok = os_fileinfo_link((char *)fname, &file_info);
2711
2712 /* Symlinks. */
2713 if ((bkc & BKC_BREAKSYMLINK)
2714 && file_info_link_ok
2715 && !os_fileinfo_id_equal(&file_info, &file_info_old)) {
2716 backup_copy = FALSE;
2717 }
2718
2719 /* Hardlinks. */
2720 if ((bkc & BKC_BREAKHARDLINK)
2721 && os_fileinfo_hardlinks(&file_info_old) > 1
2722 && (!file_info_link_ok
2723 || os_fileinfo_id_equal(&file_info, &file_info_old))) {
2724 backup_copy = FALSE;
2725 }
2726# endif
2727 }
2728
2729 /* make sure we have a valid backup extension to use */
2730 if (*p_bex == NUL)
2731 backup_ext = (char_u *)".bak";
2732 else
2733 backup_ext = p_bex;
2734
2735 if (backup_copy) {
2736 char_u *wp;
2737 int some_error = false;
2738 char_u *dirp;
2739 char_u *rootname;
2740
2741 /*
2742 * Try to make the backup in each directory in the 'bdir' option.
2743 *
2744 * Unix semantics has it, that we may have a writable file,
2745 * that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
2746 * - the directory is not writable,
2747 * - the file may be a symbolic link,
2748 * - the file may belong to another user/group, etc.
2749 *
2750 * For these reasons, the existing writable file must be truncated
2751 * and reused. Creation of a backup COPY will be attempted.
2752 */
2753 dirp = p_bdir;
2754 while (*dirp) {
2755 /*
2756 * Isolate one directory name, using an entry in 'bdir'.
2757 */
2758 (void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
2759 rootname = get_file_in_dir(fname, IObuff);
2760 if (rootname == NULL) {
2761 some_error = TRUE; /* out of memory */
2762 goto nobackup;
2763 }
2764
2765 FileInfo file_info_new;
2766 {
2767 /*
2768 * Make backup file name.
2769 */
2770 backup = (char_u *)modname((char *)rootname, (char *)backup_ext, FALSE);
2771 if (backup == NULL) {
2772 xfree(rootname);
2773 some_error = TRUE; /* out of memory */
2774 goto nobackup;
2775 }
2776
2777 /*
2778 * Check if backup file already exists.
2779 */
2780 if (os_fileinfo((char *)backup, &file_info_new)) {
2781 if (os_fileinfo_id_equal(&file_info_new, &file_info_old)) {
2782 //
2783 // Backup file is same as original file.
2784 // May happen when modname() gave the same file back (e.g. silly
2785 // link). If we don't check here, we either ruin the file when
2786 // copying or erase it after writing.
2787 //
2788 XFREE_CLEAR(backup); // no backup file to delete
2789 } else if (!p_bk) {
2790 // We are not going to keep the backup file, so don't
2791 // delete an existing one, and try to use another name instead.
2792 // Change one character, just before the extension.
2793 //
2794 wp = backup + STRLEN(backup) - 1 - STRLEN(backup_ext);
2795 if (wp < backup) { // empty file name ???
2796 wp = backup;
2797 }
2798 *wp = 'z';
2799 while (*wp > 'a'
2800 && os_fileinfo((char *)backup, &file_info_new)) {
2801 --*wp;
2802 }
2803 // They all exist??? Must be something wrong.
2804 if (*wp == 'a') {
2805 XFREE_CLEAR(backup);
2806 }
2807 }
2808 }
2809 }
2810 xfree(rootname);
2811
2812 /*
2813 * Try to create the backup file
2814 */
2815 if (backup != NULL) {
2816 /* remove old backup, if present */
2817 os_remove((char *)backup);
2818
2819 // set file protection same as original file, but
2820 // strip s-bit.
2821 (void)os_setperm((const char *)backup, perm & 0777);
2822
2823#ifdef UNIX
2824 //
2825 // Try to set the group of the backup same as the original file. If
2826 // this fails, set the protection bits for the group same as the
2827 // protection bits for others.
2828 //
2829 if (file_info_new.stat.st_gid != file_info_old.stat.st_gid
2830 && os_chown((char *)backup, -1, file_info_old.stat.st_gid) != 0) {
2831 os_setperm((const char *)backup,
2832 (perm & 0707) | ((perm & 07) << 3));
2833 }
2834#endif
2835
2836 // copy the file
2837 if (os_copy((char *)fname, (char *)backup, UV_FS_COPYFILE_FICLONE)
2838 != 0) {
2839 SET_ERRMSG(_("E506: Can't write to backup file "
2840 "(add ! to override)"));
2841 }
2842
2843#ifdef UNIX
2844 os_file_settime((char *)backup,
2845 file_info_old.stat.st_atim.tv_sec,
2846 file_info_old.stat.st_mtim.tv_sec);
2847#endif
2848#ifdef HAVE_ACL
2849 mch_set_acl(backup, acl);
2850#endif
2851 break;
2852 }
2853 }
2854
2855nobackup:
2856 if (backup == NULL && errmsg == NULL) {
2857 SET_ERRMSG(_(
2858 "E509: Cannot create backup file (add ! to override)"));
2859 }
2860 // Ignore errors when forceit is TRUE.
2861 if ((some_error || errmsg != NULL) && !forceit) {
2862 retval = FAIL;
2863 goto fail;
2864 }
2865 SET_ERRMSG(NULL);
2866 } else {
2867 char_u *dirp;
2868 char_u *p;
2869 char_u *rootname;
2870
2871 /*
2872 * Make a backup by renaming the original file.
2873 */
2874 /*
2875 * If 'cpoptions' includes the "W" flag, we don't want to
2876 * overwrite a read-only file. But rename may be possible
2877 * anyway, thus we need an extra check here.
2878 */
2879 if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL) {
2880 SET_ERRMSG_NUM("E504", _(err_readonly));
2881 goto fail;
2882 }
2883
2884 /*
2885 *
2886 * Form the backup file name - change path/fo.o.h to
2887 * path/fo.o.h.bak Try all directories in 'backupdir', first one
2888 * that works is used.
2889 */
2890 dirp = p_bdir;
2891 while (*dirp) {
2892 /*
2893 * Isolate one directory name and make the backup file name.
2894 */
2895 (void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
2896 rootname = get_file_in_dir(fname, IObuff);
2897 if (rootname == NULL)
2898 backup = NULL;
2899 else {
2900 backup = (char_u *)modname((char *)rootname, (char *)backup_ext, FALSE);
2901 xfree(rootname);
2902 }
2903
2904 if (backup != NULL) {
2905 /*
2906 * If we are not going to keep the backup file, don't
2907 * delete an existing one, try to use another name.
2908 * Change one character, just before the extension.
2909 */
2910 if (!p_bk && os_path_exists(backup)) {
2911 p = backup + STRLEN(backup) - 1 - STRLEN(backup_ext);
2912 if (p < backup) /* empty file name ??? */
2913 p = backup;
2914 *p = 'z';
2915 while (*p > 'a' && os_path_exists(backup)) {
2916 (*p)--;
2917 }
2918 // They all exist??? Must be something wrong!
2919 if (*p == 'a') {
2920 XFREE_CLEAR(backup);
2921 }
2922 }
2923 }
2924 if (backup != NULL) {
2925 // Delete any existing backup and move the current version
2926 // to the backup. For safety, we don't remove the backup
2927 // until the write has finished successfully. And if the
2928 // 'backup' option is set, leave it around.
2929
2930 // If the renaming of the original file to the backup file
2931 // works, quit here.
2932 ///
2933 if (vim_rename(fname, backup) == 0) {
2934 break;
2935 }
2936
2937 XFREE_CLEAR(backup); // don't do the rename below
2938 }
2939 }
2940 if (backup == NULL && !forceit) {
2941 SET_ERRMSG(_("E510: Can't make backup file (add ! to override)"));
2942 goto fail;
2943 }
2944 }
2945 }
2946
2947#if defined(UNIX)
2948 // When using ":w!" and the file was read-only: make it writable
2949 if (forceit && perm >= 0 && !(perm & 0200)
2950 && file_info_old.stat.st_uid == getuid()
2951 && vim_strchr(p_cpo, CPO_FWRITE) == NULL) {
2952 perm |= 0200;
2953 (void)os_setperm((const char *)fname, perm);
2954 made_writable = true;
2955 }
2956#endif
2957
2958 // When using ":w!" and writing to the current file, 'readonly' makes no
2959 // sense, reset it, unless 'Z' appears in 'cpoptions'.
2960 if (forceit && overwriting && vim_strchr(p_cpo, CPO_KEEPRO) == NULL) {
2961 buf->b_p_ro = false;
2962 need_maketitle = true; // set window title later
2963 status_redraw_all(); // redraw status lines later
2964 }
2965
2966 if (end > buf->b_ml.ml_line_count)
2967 end = buf->b_ml.ml_line_count;
2968 if (buf->b_ml.ml_flags & ML_EMPTY)
2969 start = end + 1;
2970
2971 // If the original file is being overwritten, there is a small chance that
2972 // we crash in the middle of writing. Therefore the file is preserved now.
2973 // This makes all block numbers positive so that recovery does not need
2974 // the original file.
2975 // Don't do this if there is a backup file and we are exiting.
2976 if (reset_changed && !newfile && overwriting
2977 && !(exiting && backup != NULL)) {
2978 ml_preserve(buf, false, !!p_fs);
2979 if (got_int) {
2980 SET_ERRMSG(_(e_interr));
2981 goto restore_backup;
2982 }
2983 }
2984
2985
2986 // Default: write the file directly. May write to a temp file for
2987 // multi-byte conversion.
2988 wfname = fname;
2989
2990 // Check for forced 'fileencoding' from "++opt=val" argument.
2991 if (eap != NULL && eap->force_enc != 0) {
2992 fenc = eap->cmd + eap->force_enc;
2993 fenc = enc_canonize(fenc);
2994 fenc_tofree = fenc;
2995 } else {
2996 fenc = buf->b_p_fenc;
2997 }
2998
2999 // Check if the file needs to be converted.
3000 converted = need_conversion(fenc);
3001
3002 // Check if UTF-8 to UCS-2/4 or Latin1 conversion needs to be done. Or
3003 // Latin1 to Unicode conversion. This is handled in buf_write_bytes().
3004 // Prepare the flags for it and allocate bw_conv_buf when needed.
3005 if (converted && (enc_utf8 || STRCMP(p_enc, "latin1") == 0)) {
3006 wb_flags = get_fio_flags(fenc);
3007 if (wb_flags & (FIO_UCS2 | FIO_UCS4 | FIO_UTF16 | FIO_UTF8)) {
3008 // Need to allocate a buffer to translate into.
3009 if (wb_flags & (FIO_UCS2 | FIO_UTF16 | FIO_UTF8)) {
3010 write_info.bw_conv_buflen = bufsize * 2;
3011 } else { // FIO_UCS4
3012 write_info.bw_conv_buflen = bufsize * 4;
3013 }
3014 write_info.bw_conv_buf = verbose_try_malloc(write_info.bw_conv_buflen);
3015 if (!write_info.bw_conv_buf) {
3016 end = 0;
3017 }
3018 }
3019 }
3020
3021
3022
3023 if (converted && wb_flags == 0) {
3024# ifdef HAVE_ICONV
3025 // Use iconv() conversion when conversion is needed and it's not done
3026 // internally.
3027 write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc,
3028 enc_utf8 ? (char_u *)"utf-8" : p_enc);
3029 if (write_info.bw_iconv_fd != (iconv_t)-1) {
3030 /* We're going to use iconv(), allocate a buffer to convert in. */
3031 write_info.bw_conv_buflen = bufsize * ICONV_MULT;
3032 write_info.bw_conv_buf = verbose_try_malloc(write_info.bw_conv_buflen);
3033 if (!write_info.bw_conv_buf) {
3034 end = 0;
3035 }
3036 write_info.bw_first = TRUE;
3037 } else
3038# endif
3039
3040 /*
3041 * When the file needs to be converted with 'charconvert' after
3042 * writing, write to a temp file instead and let the conversion
3043 * overwrite the original file.
3044 */
3045 if (*p_ccv != NUL) {
3046 wfname = vim_tempname();
3047 if (wfname == NULL) { // Can't write without a tempfile!
3048 SET_ERRMSG(_("E214: Can't find temp file for writing"));
3049 goto restore_backup;
3050 }
3051 }
3052 }
3053 if (converted && wb_flags == 0
3054# ifdef HAVE_ICONV
3055 && write_info.bw_iconv_fd == (iconv_t)-1
3056# endif
3057 && wfname == fname
3058 ) {
3059 if (!forceit) {
3060 SET_ERRMSG(_(
3061 "E213: Cannot convert (add ! to write without conversion)"));
3062 goto restore_backup;
3063 }
3064 notconverted = TRUE;
3065 }
3066
3067 // If conversion is taking place, we may first pretend to write and check
3068 // for conversion errors. Then loop again to write for real.
3069 // When not doing conversion this writes for real right away.
3070 for (checking_conversion = true; ; checking_conversion = false) {
3071 // There is no need to check conversion when:
3072 // - there is no conversion
3073 // - we make a backup file, that can be restored in case of conversion
3074 // failure.
3075 if (!converted || dobackup) {
3076 checking_conversion = false;
3077 }
3078
3079 if (checking_conversion) {
3080 // Make sure we don't write anything.
3081 fd = -1;
3082 write_info.bw_fd = fd;
3083 } else {
3084 // Open the file "wfname" for writing.
3085 // We may try to open the file twice: If we can't write to the file
3086 // and forceit is TRUE we delete the existing file and try to
3087 // create a new one. If this still fails we may have lost the
3088 // original file! (this may happen when the user reached his
3089 // quotum for number of files).
3090 // Appending will fail if the file does not exist and forceit is
3091 // FALSE.
3092 while ((fd = os_open((char *)wfname,
3093 O_WRONLY |
3094 (append ?
3095 (forceit ? (O_APPEND | O_CREAT) : O_APPEND)
3096 : (O_CREAT | O_TRUNC))
3097 , perm < 0 ? 0666 : (perm & 0777))) < 0) {
3098 // A forced write will try to create a new file if the old one
3099 // is still readonly. This may also happen when the directory
3100 // is read-only. In that case the mch_remove() will fail.
3101 if (errmsg == NULL) {
3102#ifdef UNIX
3103 FileInfo file_info;
3104
3105 // Don't delete the file when it's a hard or symbolic link.
3106 if ((!newfile && os_fileinfo_hardlinks(&file_info_old) > 1)
3107 || (os_fileinfo_link((char *)fname, &file_info)
3108 && !os_fileinfo_id_equal(&file_info, &file_info_old))) {
3109 SET_ERRMSG(_("E166: Can't open linked file for writing"));
3110 } else {
3111#endif
3112 SET_ERRMSG_ARG(_("E212: Can't open file for writing: %s"), fd);
3113 if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL
3114 && perm >= 0) {
3115#ifdef UNIX
3116 // we write to the file, thus it should be marked
3117 // writable after all
3118 if (!(perm & 0200)) {
3119 made_writable = true;
3120 }
3121 perm |= 0200;
3122 if (file_info_old.stat.st_uid != getuid()
3123 || file_info_old.stat.st_gid != getgid()) {
3124 perm &= 0777;
3125 }
3126#endif
3127 if (!append) { // don't remove when appending
3128 os_remove((char *)wfname);
3129 }
3130 continue;
3131 }
3132#ifdef UNIX
3133 }
3134#endif
3135 }
3136
3137restore_backup:
3138 {
3139 // If we failed to open the file, we don't need a backup. Throw it
3140 // away. If we moved or removed the original file try to put the
3141 // backup in its place.
3142 if (backup != NULL && wfname == fname) {
3143 if (backup_copy) {
3144 // There is a small chance that we removed the original,
3145 // try to move the copy in its place.
3146 // This may not work if the vim_rename() fails.
3147 // In that case we leave the copy around.
3148 // If file does not exist, put the copy in its place
3149 if (!os_path_exists(fname)) {
3150 vim_rename(backup, fname);
3151 }
3152 // if original file does exist throw away the copy
3153 if (os_path_exists(fname)) {
3154 os_remove((char *)backup);
3155 }
3156 } else {
3157 // try to put the original file back
3158 vim_rename(backup, fname);
3159 }
3160 }
3161
3162 // if original file no longer exists give an extra warning
3163 if (!newfile && !os_path_exists(fname)) {
3164 end = 0;
3165 }
3166 }
3167
3168 if (wfname != fname) {
3169 xfree(wfname);
3170 }
3171 goto fail;
3172 }
3173 write_info.bw_fd = fd;
3174 }
3175 SET_ERRMSG(NULL);
3176
3177 write_info.bw_buf = buffer;
3178 nchars = 0;
3179
3180 // use "++bin", "++nobin" or 'binary'
3181 if (eap != NULL && eap->force_bin != 0) {
3182 write_bin = (eap->force_bin == FORCE_BIN);
3183 } else {
3184 write_bin = buf->b_p_bin;
3185 }
3186
3187 // Skip the BOM when appending and the file already existed, the BOM
3188 // only makes sense at the start of the file.
3189 if (buf->b_p_bomb && !write_bin && (!append || perm < 0)) {
3190 write_info.bw_len = make_bom(buffer, fenc);
3191 if (write_info.bw_len > 0) {
3192 // don't convert
3193 write_info.bw_flags = FIO_NOCONVERT | wb_flags;
3194 if (buf_write_bytes(&write_info) == FAIL) {
3195 end = 0;
3196 } else {
3197 nchars += write_info.bw_len;
3198 }
3199 }
3200 }
3201 write_info.bw_start_lnum = start;
3202
3203 write_undo_file = (buf->b_p_udf && overwriting && !append
3204 && !filtering && reset_changed && !checking_conversion);
3205 if (write_undo_file) {
3206 // Prepare for computing the hash value of the text.
3207 sha256_start(&sha_ctx);
3208 }
3209
3210 write_info.bw_len = bufsize;
3211#ifdef HAS_BW_FLAGS
3212 write_info.bw_flags = wb_flags;
3213#endif
3214 fileformat = get_fileformat_force(buf, eap);
3215 s = buffer;
3216 len = 0;
3217 for (lnum = start; lnum <= end; lnum++) {
3218 // The next while loop is done once for each character written.
3219 // Keep it fast!
3220 ptr = ml_get_buf(buf, lnum, false) - 1;
3221 if (write_undo_file) {
3222 sha256_update(&sha_ctx, ptr + 1, (uint32_t)(STRLEN(ptr + 1) + 1));
3223 }
3224 while ((c = *++ptr) != NUL) {
3225 if (c == NL) {
3226 *s = NUL; // replace newlines with NULs
3227 } else if (c == CAR && fileformat == EOL_MAC) {
3228 *s = NL; // Mac: replace CRs with NLs
3229 } else {
3230 *s = c;
3231 }
3232 s++;
3233 if (++len != bufsize) {
3234 continue;
3235 }
3236 if (buf_write_bytes(&write_info) == FAIL) {
3237 end = 0; // write error: break loop
3238 break;
3239 }
3240 nchars += bufsize;
3241 s = buffer;
3242 len = 0;
3243 write_info.bw_start_lnum = lnum;
3244 }
3245 // write failed or last line has no EOL: stop here
3246 if (end == 0
3247 || (lnum == end
3248 && (write_bin || !buf->b_p_fixeol)
3249 && (lnum == buf->b_no_eol_lnum
3250 || (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol)))) {
3251 lnum++; // written the line, count it
3252 no_eol = true;
3253 break;
3254 }
3255 if (fileformat == EOL_UNIX) {
3256 *s++ = NL;
3257 } else {
3258 *s++ = CAR; // EOL_MAC or EOL_DOS: write CR
3259 if (fileformat == EOL_DOS) { // write CR-NL
3260 if (++len == bufsize) {
3261 if (buf_write_bytes(&write_info) == FAIL) {
3262 end = 0; // write error: break loop
3263 break;
3264 }
3265 nchars += bufsize;
3266 s = buffer;
3267 len = 0;
3268 }
3269 *s++ = NL;
3270 }
3271 }
3272 if (++len == bufsize) {
3273 if (buf_write_bytes(&write_info) == FAIL) {
3274 end = 0; // Write error: break loop.
3275 break;
3276 }
3277 nchars += bufsize;
3278 s = buffer;
3279 len = 0;
3280
3281 os_breakcheck();
3282 if (got_int) {
3283 end = 0; // Interrupted, break loop.
3284 break;
3285 }
3286 }
3287 }
3288 if (len > 0 && end > 0) {
3289 write_info.bw_len = len;
3290 if (buf_write_bytes(&write_info) == FAIL) {
3291 end = 0; // write error
3292 }
3293 nchars += len;
3294 }
3295
3296 // Stop when writing done or an error was encountered.
3297 if (!checking_conversion || end == 0) {
3298 break;
3299 }
3300
3301 // If no error happened until now, writing should be ok, so loop to
3302 // really write the buffer.
3303 }
3304
3305 // If we started writing, finish writing. Also when an error was
3306 // encountered.
3307 if (!checking_conversion) {
3308 // On many journalling file systems there is a bug that causes both the
3309 // original and the backup file to be lost when halting the system right
3310 // after writing the file. That's because only the meta-data is
3311 // journalled. Syncing the file slows down the system, but assures it has
3312 // been written to disk and we don't lose it.
3313 // For a device do try the fsync() but don't complain if it does not work
3314 // (could be a pipe).
3315 // If the 'fsync' option is FALSE, don't fsync(). Useful for laptops.
3316 int error;
3317 if (p_fs && (error = os_fsync(fd)) != 0 && !device
3318 // fsync not supported on this storage.
3319 && error != UV_ENOTSUP) {
3320 SET_ERRMSG_ARG(e_fsync, error);
3321 end = 0;
3322 }
3323
3324#ifdef UNIX
3325 // When creating a new file, set its owner/group to that of the original
3326 // file. Get the new device and inode number.
3327 if (backup != NULL && !backup_copy) {
3328 // don't change the owner when it's already OK, some systems remove
3329 // permission or ACL stuff
3330 FileInfo file_info;
3331 if (!os_fileinfo((char *)wfname, &file_info)
3332 || file_info.stat.st_uid != file_info_old.stat.st_uid
3333 || file_info.stat.st_gid != file_info_old.stat.st_gid) {
3334 os_fchown(fd, file_info_old.stat.st_uid, file_info_old.stat.st_gid);
3335 if (perm >= 0) { // Set permission again, may have changed.
3336 (void)os_setperm((const char *)wfname, perm);
3337 }
3338 }
3339 buf_set_file_id(buf);
3340 } else if (!buf->file_id_valid) {
3341 // Set the file_id when creating a new file.
3342 buf_set_file_id(buf);
3343 }
3344#endif
3345
3346 if ((error = os_close(fd)) != 0) {
3347 SET_ERRMSG_ARG(_("E512: Close failed: %s"), error);
3348 end = 0;
3349 }
3350
3351#ifdef UNIX
3352 if (made_writable) {
3353 perm &= ~0200; // reset 'w' bit for security reasons
3354 }
3355#endif
3356 if (perm >= 0) { // Set perm. of new file same as old file.
3357 (void)os_setperm((const char *)wfname, perm);
3358 }
3359#ifdef HAVE_ACL
3360 // Probably need to set the ACL before changing the user (can't set the
3361 // ACL on a file the user doesn't own).
3362 if (!backup_copy) {
3363 mch_set_acl(wfname, acl);
3364 }
3365#endif
3366
3367 if (wfname != fname) {
3368 // The file was written to a temp file, now it needs to be converted
3369 // with 'charconvert' to (overwrite) the output file.
3370 if (end != 0) {
3371 if (eval_charconvert(enc_utf8 ? "utf-8" : (char *)p_enc, (char *)fenc,
3372 (char *)wfname, (char *)fname) == FAIL) {
3373 write_info.bw_conv_error = true;
3374 end = 0;
3375 }
3376 }
3377 os_remove((char *)wfname);
3378 xfree(wfname);
3379 }
3380 }
3381
3382 if (end == 0) {
3383 // Error encountered.
3384 if (errmsg == NULL) {
3385 if (write_info.bw_conv_error) {
3386 if (write_info.bw_conv_error_lnum == 0) {
3387 SET_ERRMSG(_(
3388 "E513: write error, conversion failed "
3389 "(make 'fenc' empty to override)"));
3390 } else {
3391 errmsg_allocated = true;
3392 SET_ERRMSG(xmalloc(300));
3393 vim_snprintf(
3394 errmsg, 300,
3395 _("E513: write error, conversion failed in line %" PRIdLINENR
3396 " (make 'fenc' empty to override)"),
3397 write_info.bw_conv_error_lnum);
3398 }
3399 } else if (got_int) {
3400 SET_ERRMSG(_(e_interr));
3401 } else {
3402 SET_ERRMSG(_("E514: write error (file system full?)"));
3403 }
3404 }
3405
3406 // If we have a backup file, try to put it in place of the new file,
3407 // because the new file is probably corrupt. This avoids losing the
3408 // original file when trying to make a backup when writing the file a
3409 // second time.
3410 // When "backup_copy" is set we need to copy the backup over the new
3411 // file. Otherwise rename the backup file.
3412 // If this is OK, don't give the extra warning message.
3413 if (backup != NULL) {
3414 if (backup_copy) {
3415 // This may take a while, if we were interrupted let the user
3416 // know we got the message.
3417 if (got_int) {
3418 MSG(_(e_interr));
3419 ui_flush();
3420 }
3421
3422 // copy the file.
3423 if (os_copy((char *)backup, (char *)fname, UV_FS_COPYFILE_FICLONE)
3424 == 0) {
3425 end = 1; // success
3426 }
3427 } else {
3428 if (vim_rename(backup, fname) == 0) {
3429 end = 1;
3430 }
3431 }
3432 }
3433 goto fail;
3434 }
3435
3436 lnum -= start; /* compute number of written lines */
3437 --no_wait_return; /* may wait for return now */
3438
3439#if !defined(UNIX)
3440 fname = sfname; /* use shortname now, for the messages */
3441#endif
3442 if (!filtering) {
3443 add_quoted_fname((char *)IObuff, IOSIZE, buf, (const char *)fname);
3444 c = false;
3445 if (write_info.bw_conv_error) {
3446 STRCAT(IObuff, _(" CONVERSION ERROR"));
3447 c = TRUE;
3448 if (write_info.bw_conv_error_lnum != 0)
3449 vim_snprintf_add((char *)IObuff, IOSIZE, _(" in line %" PRId64 ";"),
3450 (int64_t)write_info.bw_conv_error_lnum);
3451 } else if (notconverted) {
3452 STRCAT(IObuff, _("[NOT converted]"));
3453 c = TRUE;
3454 } else if (converted) {
3455 STRCAT(IObuff, _("[converted]"));
3456 c = TRUE;
3457 }
3458 if (device) {
3459 STRCAT(IObuff, _("[Device]"));
3460 c = TRUE;
3461 } else if (newfile) {
3462 STRCAT(IObuff, shortmess(SHM_NEW) ? _("[New]") : _("[New File]"));
3463 c = TRUE;
3464 }
3465 if (no_eol) {
3466 msg_add_eol();
3467 c = TRUE;
3468 }
3469 /* may add [unix/dos/mac] */
3470 if (msg_add_fileformat(fileformat))
3471 c = TRUE;
3472 msg_add_lines(c, (long)lnum, nchars); /* add line/char count */
3473 if (!shortmess(SHM_WRITE)) {
3474 if (append)
3475 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended"));
3476 else
3477 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [w]") : _(" written"));
3478 }
3479
3480 set_keep_msg(msg_trunc_attr(IObuff, FALSE, 0), 0);
3481 }
3482
3483 /* When written everything correctly: reset 'modified'. Unless not
3484 * writing to the original file and '+' is not in 'cpoptions'. */
3485 if (reset_changed && whole && !append
3486 && !write_info.bw_conv_error
3487 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL)) {
3488 unchanged(buf, true, false);
3489 const varnumber_T changedtick = buf_get_changedtick(buf);
3490 if (buf->b_last_changedtick + 1 == changedtick) {
3491 // b:changedtick may be incremented in unchanged() but that
3492 // should not trigger a TextChanged event.
3493 buf->b_last_changedtick = changedtick;
3494 }
3495 u_unchanged(buf);
3496 u_update_save_nr(buf);
3497 }
3498
3499 /*
3500 * If written to the current file, update the timestamp of the swap file
3501 * and reset the BF_WRITE_MASK flags. Also sets buf->b_mtime.
3502 */
3503 if (overwriting) {
3504 ml_timestamp(buf);
3505 if (append)
3506 buf->b_flags &= ~BF_NEW;
3507 else
3508 buf->b_flags &= ~BF_WRITE_MASK;
3509 }
3510
3511 /*
3512 * If we kept a backup until now, and we are in patch mode, then we make
3513 * the backup file our 'original' file.
3514 */
3515 if (*p_pm && dobackup) {
3516 char *org = modname((char *)fname, (char *)p_pm, FALSE);
3517
3518 if (backup != NULL) {
3519 /*
3520 * If the original file does not exist yet
3521 * the current backup file becomes the original file
3522 */
3523 if (org == NULL) {
3524 EMSG(_("E205: Patchmode: can't save original file"));
3525 } else if (!os_path_exists((char_u *)org)) {
3526 vim_rename(backup, (char_u *)org);
3527 XFREE_CLEAR(backup); // don't delete the file
3528#ifdef UNIX
3529 os_file_settime(org,
3530 file_info_old.stat.st_atim.tv_sec,
3531 file_info_old.stat.st_mtim.tv_sec);
3532#endif
3533 }
3534 }
3535 /*
3536 * If there is no backup file, remember that a (new) file was
3537 * created.
3538 */
3539 else {
3540 int empty_fd;
3541
3542 if (org == NULL
3543 || (empty_fd = os_open(org,
3544 O_CREAT | O_EXCL | O_NOFOLLOW,
3545 perm < 0 ? 0666 : (perm & 0777))) < 0)
3546 EMSG(_("E206: patchmode: can't touch empty original file"));
3547 else
3548 close(empty_fd);
3549 }
3550 if (org != NULL) {
3551 os_setperm(org, os_getperm((const char *)fname) & 0777);
3552 xfree(org);
3553 }
3554 }
3555
3556 /*
3557 * Remove the backup unless 'backup' option is set
3558 */
3559 if (!p_bk && backup != NULL
3560 && !write_info.bw_conv_error
3561 && os_remove((char *)backup) != 0) {
3562 EMSG(_("E207: Can't delete backup file"));
3563 }
3564
3565 goto nofail;
3566
3567 /*
3568 * Finish up. We get here either after failure or success.
3569 */
3570fail:
3571 --no_wait_return; /* may wait for return now */
3572nofail:
3573
3574 /* Done saving, we accept changed buffer warnings again */
3575 buf->b_saving = false;
3576
3577 xfree(backup);
3578 if (buffer != smallbuf)
3579 xfree(buffer);
3580 xfree(fenc_tofree);
3581 xfree(write_info.bw_conv_buf);
3582# ifdef HAVE_ICONV
3583 if (write_info.bw_iconv_fd != (iconv_t)-1) {
3584 iconv_close(write_info.bw_iconv_fd);
3585 write_info.bw_iconv_fd = (iconv_t)-1;
3586 }
3587# endif
3588#ifdef HAVE_ACL
3589 mch_free_acl(acl);
3590#endif
3591
3592 if (errmsg != NULL) {
3593 // - 100 to save some space for further error message
3594#ifndef UNIX
3595 add_quoted_fname((char *)IObuff, IOSIZE - 100, buf, (const char *)sfname);
3596#else
3597 add_quoted_fname((char *)IObuff, IOSIZE - 100, buf, (const char *)fname);
3598#endif
3599 if (errnum != NULL) {
3600 if (errmsgarg != 0) {
3601 emsgf("%s: %s%s: %s", errnum, IObuff, errmsg, os_strerror(errmsgarg));
3602 } else {
3603 emsgf("%s: %s%s", errnum, IObuff, errmsg);
3604 }
3605 } else if (errmsgarg != 0) {
3606 emsgf(errmsg, os_strerror(errmsgarg));
3607 } else {
3608 EMSG(errmsg);
3609 }
3610 if (errmsg_allocated) {
3611 xfree(errmsg);
3612 }
3613
3614 retval = FAIL;
3615 if (end == 0) {
3616 const int attr = HL_ATTR(HLF_E); // Set highlight for error messages.
3617 MSG_PUTS_ATTR(_("\nWARNING: Original file may be lost or damaged\n"),
3618 attr | MSG_HIST);
3619 MSG_PUTS_ATTR(_(
3620 "don't quit the editor until the file is successfully written!"),
3621 attr | MSG_HIST);
3622
3623 /* Update the timestamp to avoid an "overwrite changed file"
3624 * prompt when writing again. */
3625 if (os_fileinfo((char *)fname, &file_info_old)) {
3626 buf_store_file_info(buf, &file_info_old);
3627 buf->b_mtime_read = buf->b_mtime;
3628 }
3629 }
3630 }
3631 msg_scroll = msg_save;
3632
3633 /*
3634 * When writing the whole file and 'undofile' is set, also write the undo
3635 * file.
3636 */
3637 if (retval == OK && write_undo_file) {
3638 char_u hash[UNDO_HASH_SIZE];
3639
3640 sha256_finish(&sha_ctx, hash);
3641 u_write_undo(NULL, FALSE, buf, hash);
3642 }
3643
3644 if (!should_abort(retval)) {
3645 aco_save_T aco;
3646
3647 curbuf->b_no_eol_lnum = 0; /* in case it was set by the previous read */
3648
3649 /*
3650 * Apply POST autocommands.
3651 * Careful: The autocommands may call buf_write() recursively!
3652 */
3653 aucmd_prepbuf(&aco, buf);
3654
3655 if (append)
3656 apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname,
3657 FALSE, curbuf, eap);
3658 else if (filtering)
3659 apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname,
3660 FALSE, curbuf, eap);
3661 else if (reset_changed && whole)
3662 apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname,
3663 FALSE, curbuf, eap);
3664 else
3665 apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname,
3666 FALSE, curbuf, eap);
3667
3668 /* restore curwin/curbuf and a few other things */
3669 aucmd_restbuf(&aco);
3670
3671 if (aborting()) /* autocmds may abort script processing */
3672 retval = FALSE;
3673 }
3674
3675 got_int |= prev_got_int;
3676
3677 return retval;
3678#undef SET_ERRMSG
3679#undef SET_ERRMSG_ARG
3680#undef SET_ERRMSG_NUM
3681}
3682
3683/*
3684 * Set the name of the current buffer. Use when the buffer doesn't have a
3685 * name and a ":r" or ":w" command with a file name is used.
3686 */
3687static int set_rw_fname(char_u *fname, char_u *sfname)
3688{
3689 buf_T *buf = curbuf;
3690
3691 /* It's like the unnamed buffer is deleted.... */
3692 if (curbuf->b_p_bl)
3693 apply_autocmds(EVENT_BUFDELETE, NULL, NULL, FALSE, curbuf);
3694 apply_autocmds(EVENT_BUFWIPEOUT, NULL, NULL, FALSE, curbuf);
3695 if (aborting()) /* autocmds may abort script processing */
3696 return FAIL;
3697 if (curbuf != buf) {
3698 /* We are in another buffer now, don't do the renaming. */
3699 EMSG(_(e_auchangedbuf));
3700 return FAIL;
3701 }
3702
3703 if (setfname(curbuf, fname, sfname, FALSE) == OK)
3704 curbuf->b_flags |= BF_NOTEDITED;
3705
3706 /* ....and a new named one is created */
3707 apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, curbuf);
3708 if (curbuf->b_p_bl)
3709 apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, curbuf);
3710 if (aborting()) /* autocmds may abort script processing */
3711 return FAIL;
3712
3713 /* Do filetype detection now if 'filetype' is empty. */
3714 if (*curbuf->b_p_ft == NUL) {
3715 if (au_has_group((char_u *)"filetypedetect")) {
3716 (void)do_doautocmd((char_u *)"filetypedetect BufRead", false, NULL);
3717 }
3718 do_modelines(0);
3719 }
3720
3721 return OK;
3722}
3723
3724/// Put file name into the specified buffer with quotes
3725///
3726/// Replaces home directory at the start with `~`.
3727///
3728/// @param[out] ret_buf Buffer to save results to.
3729/// @param[in] buf_len ret_buf length.
3730/// @param[in] buf buf_T file name is coming from.
3731/// @param[in] fname File name to write.
3732static void add_quoted_fname(char *const ret_buf, const size_t buf_len,
3733 const buf_T *const buf, const char *fname)
3734 FUNC_ATTR_NONNULL_ARG(1)
3735{
3736 if (fname == NULL) {
3737 fname = "-stdin-";
3738 }
3739 ret_buf[0] = '"';
3740 home_replace(buf, (const char_u *)fname, (char_u *)ret_buf + 1,
3741 (int)buf_len - 4, true);
3742 xstrlcat(ret_buf, "\" ", buf_len);
3743}
3744
3745/// Append message for text mode to IObuff.
3746///
3747/// @param eol_type line ending type
3748///
3749/// @return true if something was appended.
3750static bool msg_add_fileformat(int eol_type)
3751{
3752#ifndef USE_CRNL
3753 if (eol_type == EOL_DOS) {
3754 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[dos]") : _("[dos format]"));
3755 return true;
3756 }
3757#endif
3758 if (eol_type == EOL_MAC) {
3759 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[mac]") : _("[mac format]"));
3760 return true;
3761 }
3762#ifdef USE_CRNL
3763 if (eol_type == EOL_UNIX) {
3764 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[unix]") : _("[unix format]"));
3765 return true;
3766 }
3767#endif
3768 return false;
3769}
3770
3771/*
3772 * Append line and character count to IObuff.
3773 */
3774void msg_add_lines(int insert_space, long lnum, off_T nchars)
3775{
3776 char_u *p;
3777
3778 p = IObuff + STRLEN(IObuff);
3779
3780 if (insert_space)
3781 *p++ = ' ';
3782 if (shortmess(SHM_LINES)) {
3783 sprintf((char *)p, "%" PRId64 "L, %" PRId64 "C",
3784 (int64_t)lnum, (int64_t)nchars);
3785 }
3786 else {
3787 if (lnum == 1)
3788 STRCPY(p, _("1 line, "));
3789 else
3790 sprintf((char *)p, _("%" PRId64 " lines, "), (int64_t)lnum);
3791 p += STRLEN(p);
3792 if (nchars == 1)
3793 STRCPY(p, _("1 character"));
3794 else {
3795 sprintf((char *)p, _("%" PRId64 " characters"), (int64_t)nchars);
3796 }
3797 }
3798}
3799
3800/*
3801 * Append message for missing line separator to IObuff.
3802 */
3803static void msg_add_eol(void)
3804{
3805 STRCAT(IObuff,
3806 shortmess(SHM_LAST) ? _("[noeol]") : _("[Incomplete last line]"));
3807}
3808
3809/*
3810 * Check modification time of file, before writing to it.
3811 * The size isn't checked, because using a tool like "gzip" takes care of
3812 * using the same timestamp but can't set the size.
3813 */
3814static int check_mtime(buf_T *buf, FileInfo *file_info)
3815{
3816 if (buf->b_mtime_read != 0
3817 && time_differs(file_info->stat.st_mtim.tv_sec,
3818 buf->b_mtime_read)) {
3819 msg_scroll = true; // Don't overwrite messages here.
3820 msg_silent = 0; // Must give this prompt.
3821 // Don't use emsg() here, don't want to flush the buffers.
3822 msg_attr(_("WARNING: The file has been changed since reading it!!!"),
3823 HL_ATTR(HLF_E));
3824 if (ask_yesno(_("Do you really want to write to it"), true) == 'n') {
3825 return FAIL;
3826 }
3827 msg_scroll = false; // Always overwrite the file message now.
3828 }
3829 return OK;
3830}
3831
3832/// Return true if the times differ
3833///
3834/// @param t1 first time
3835/// @param t2 second time
3836static bool time_differs(long t1, long t2) FUNC_ATTR_CONST
3837{
3838#if defined(__linux__) || defined(MSWIN)
3839 /* On a FAT filesystem, esp. under Linux, there are only 5 bits to store
3840 * the seconds. Since the roundoff is done when flushing the inode, the
3841 * time may change unexpectedly by one second!!! */
3842 return t1 - t2 > 1 || t2 - t1 > 1;
3843#else
3844 return t1 != t2;
3845#endif
3846}
3847
3848/*
3849 * Call write() to write a number of bytes to the file.
3850 * Handles 'encoding' conversion.
3851 *
3852 * Return FAIL for failure, OK otherwise.
3853 */
3854static int buf_write_bytes(struct bw_info *ip)
3855{
3856 int wlen;
3857 char_u *buf = ip->bw_buf; /* data to write */
3858 int len = ip->bw_len; /* length of data */
3859#ifdef HAS_BW_FLAGS
3860 int flags = ip->bw_flags; /* extra flags */
3861#endif
3862
3863 /*
3864 * Skip conversion when writing the BOM.
3865 */
3866 if (!(flags & FIO_NOCONVERT)) {
3867 char_u *p;
3868 unsigned c;
3869 int n;
3870
3871 if (flags & FIO_UTF8) {
3872 /*
3873 * Convert latin1 in the buffer to UTF-8 in the file.
3874 */
3875 p = ip->bw_conv_buf; /* translate to buffer */
3876 for (wlen = 0; wlen < len; ++wlen)
3877 p += utf_char2bytes(buf[wlen], p);
3878 buf = ip->bw_conv_buf;
3879 len = (int)(p - ip->bw_conv_buf);
3880 } else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1)) {
3881 /*
3882 * Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or
3883 * Latin1 chars in the file.
3884 */
3885 if (flags & FIO_LATIN1)
3886 p = buf; /* translate in-place (can only get shorter) */
3887 else
3888 p = ip->bw_conv_buf; /* translate to buffer */
3889 for (wlen = 0; wlen < len; wlen += n) {
3890 if (wlen == 0 && ip->bw_restlen != 0) {
3891 int l;
3892
3893 /* Use remainder of previous call. Append the start of
3894 * buf[] to get a full sequence. Might still be too
3895 * short! */
3896 l = CONV_RESTLEN - ip->bw_restlen;
3897 if (l > len)
3898 l = len;
3899 memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l);
3900 n = utf_ptr2len_len(ip->bw_rest, ip->bw_restlen + l);
3901 if (n > ip->bw_restlen + len) {
3902 /* We have an incomplete byte sequence at the end to
3903 * be written. We can't convert it without the
3904 * remaining bytes. Keep them for the next call. */
3905 if (ip->bw_restlen + len > CONV_RESTLEN)
3906 return FAIL;
3907 ip->bw_restlen += len;
3908 break;
3909 }
3910 if (n > 1)
3911 c = utf_ptr2char(ip->bw_rest);
3912 else
3913 c = ip->bw_rest[0];
3914 if (n >= ip->bw_restlen) {
3915 n -= ip->bw_restlen;
3916 ip->bw_restlen = 0;
3917 } else {
3918 ip->bw_restlen -= n;
3919 memmove(ip->bw_rest, ip->bw_rest + n,
3920 (size_t)ip->bw_restlen);
3921 n = 0;
3922 }
3923 } else {
3924 n = utf_ptr2len_len(buf + wlen, len - wlen);
3925 if (n > len - wlen) {
3926 /* We have an incomplete byte sequence at the end to
3927 * be written. We can't convert it without the
3928 * remaining bytes. Keep them for the next call. */
3929 if (len - wlen > CONV_RESTLEN)
3930 return FAIL;
3931 ip->bw_restlen = len - wlen;
3932 memmove(ip->bw_rest, buf + wlen,
3933 (size_t)ip->bw_restlen);
3934 break;
3935 }
3936 if (n > 1)
3937 c = utf_ptr2char(buf + wlen);
3938 else
3939 c = buf[wlen];
3940 }
3941
3942 if (ucs2bytes(c, &p, flags) && !ip->bw_conv_error) {
3943 ip->bw_conv_error = TRUE;
3944 ip->bw_conv_error_lnum = ip->bw_start_lnum;
3945 }
3946 if (c == NL)
3947 ++ip->bw_start_lnum;
3948 }
3949 if (flags & FIO_LATIN1)
3950 len = (int)(p - buf);
3951 else {
3952 buf = ip->bw_conv_buf;
3953 len = (int)(p - ip->bw_conv_buf);
3954 }
3955 }
3956
3957# ifdef HAVE_ICONV
3958 if (ip->bw_iconv_fd != (iconv_t)-1) {
3959 const char *from;
3960 size_t fromlen;
3961 char *to;
3962 size_t tolen;
3963
3964 /* Convert with iconv(). */
3965 if (ip->bw_restlen > 0) {
3966 char *fp;
3967
3968 /* Need to concatenate the remainder of the previous call and
3969 * the bytes of the current call. Use the end of the
3970 * conversion buffer for this. */
3971 fromlen = len + ip->bw_restlen;
3972 fp = (char *)ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
3973 memmove(fp, ip->bw_rest, (size_t)ip->bw_restlen);
3974 memmove(fp + ip->bw_restlen, buf, (size_t)len);
3975 from = fp;
3976 tolen = ip->bw_conv_buflen - fromlen;
3977 } else {
3978 from = (const char *)buf;
3979 fromlen = len;
3980 tolen = ip->bw_conv_buflen;
3981 }
3982 to = (char *)ip->bw_conv_buf;
3983
3984 if (ip->bw_first) {
3985 size_t save_len = tolen;
3986
3987 /* output the initial shift state sequence */
3988 (void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen);
3989
3990 /* There is a bug in iconv() on Linux (which appears to be
3991 * wide-spread) which sets "to" to NULL and messes up "tolen".
3992 */
3993 if (to == NULL) {
3994 to = (char *)ip->bw_conv_buf;
3995 tolen = save_len;
3996 }
3997 ip->bw_first = FALSE;
3998 }
3999
4000 /*
4001 * If iconv() has an error or there is not enough room, fail.
4002 */
4003 if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen)
4004 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
4005 || fromlen > CONV_RESTLEN) {
4006 ip->bw_conv_error = TRUE;
4007 return FAIL;
4008 }
4009
4010 /* copy remainder to ip->bw_rest[] to be used for the next call. */
4011 if (fromlen > 0)
4012 memmove(ip->bw_rest, (void *)from, fromlen);
4013 ip->bw_restlen = (int)fromlen;
4014
4015 buf = ip->bw_conv_buf;
4016 len = (int)((char_u *)to - ip->bw_conv_buf);
4017 }
4018# endif
4019 }
4020
4021 if (ip->bw_fd < 0) {
4022 // Only checking conversion, which is OK if we get here.
4023 return OK;
4024 }
4025 wlen = write_eintr(ip->bw_fd, buf, len);
4026 return (wlen < len) ? FAIL : OK;
4027}
4028
4029/// Convert a Unicode character to bytes.
4030///
4031/// @param c character to convert
4032/// @param[in,out] pp pointer to store the result at
4033/// @param flags FIO_ flags that specify which encoding to use
4034///
4035/// @return true for an error, false when it's OK.
4036static bool ucs2bytes(unsigned c, char_u **pp, int flags) FUNC_ATTR_NONNULL_ALL
4037{
4038 char_u *p = *pp;
4039 bool error = false;
4040 int cc;
4041
4042
4043 if (flags & FIO_UCS4) {
4044 if (flags & FIO_ENDIAN_L) {
4045 *p++ = c;
4046 *p++ = (c >> 8);
4047 *p++ = (c >> 16);
4048 *p++ = (c >> 24);
4049 } else {
4050 *p++ = (c >> 24);
4051 *p++ = (c >> 16);
4052 *p++ = (c >> 8);
4053 *p++ = c;
4054 }
4055 } else if (flags & (FIO_UCS2 | FIO_UTF16)) {
4056 if (c >= 0x10000) {
4057 if (flags & FIO_UTF16) {
4058 /* Make two words, ten bits of the character in each. First
4059 * word is 0xd800 - 0xdbff, second one 0xdc00 - 0xdfff */
4060 c -= 0x10000;
4061 if (c >= 0x100000) {
4062 error = true;
4063 }
4064 cc = ((c >> 10) & 0x3ff) + 0xd800;
4065 if (flags & FIO_ENDIAN_L) {
4066 *p++ = cc;
4067 *p++ = ((unsigned)cc >> 8);
4068 } else {
4069 *p++ = ((unsigned)cc >> 8);
4070 *p++ = cc;
4071 }
4072 c = (c & 0x3ff) + 0xdc00;
4073 } else {
4074 error = true;
4075 }
4076 }
4077 if (flags & FIO_ENDIAN_L) {
4078 *p++ = c;
4079 *p++ = (c >> 8);
4080 } else {
4081 *p++ = (c >> 8);
4082 *p++ = c;
4083 }
4084 } else { /* Latin1 */
4085 if (c >= 0x100) {
4086 error = true;
4087 *p++ = 0xBF;
4088 } else
4089 *p++ = c;
4090 }
4091
4092 *pp = p;
4093 return error;
4094}
4095
4096/// Return true if file encoding "fenc" requires conversion from or to
4097/// 'encoding'.
4098///
4099/// @param fenc file encoding to check
4100///
4101/// @return true if conversion is required
4102static bool need_conversion(const char_u *fenc)
4103 FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
4104{
4105 int same_encoding;
4106 int enc_flags;
4107 int fenc_flags;
4108
4109 if (*fenc == NUL || STRCMP(p_enc, fenc) == 0) {
4110 same_encoding = TRUE;
4111 fenc_flags = 0;
4112 } else {
4113 /* Ignore difference between "ansi" and "latin1", "ucs-4" and
4114 * "ucs-4be", etc. */
4115 enc_flags = get_fio_flags(p_enc);
4116 fenc_flags = get_fio_flags(fenc);
4117 same_encoding = (enc_flags != 0 && fenc_flags == enc_flags);
4118 }
4119 if (same_encoding) {
4120 // Specified file encoding matches UTF-8.
4121 return false;
4122 }
4123
4124 /* Encodings differ. However, conversion is not needed when 'enc' is any
4125 * Unicode encoding and the file is UTF-8. */
4126 return !(enc_utf8 && fenc_flags == FIO_UTF8);
4127}
4128
4129/// Return the FIO_ flags needed for the internal conversion if 'name' was
4130/// unicode or latin1, otherwise 0. If "name" is an empty string,
4131/// use 'encoding'.
4132///
4133/// @param name string to check for encoding
4134static int get_fio_flags(const char_u *name)
4135{
4136 int prop;
4137
4138 if (*name == NUL) {
4139 name = p_enc;
4140 }
4141 prop = enc_canon_props(name);
4142 if (prop & ENC_UNICODE) {
4143 if (prop & ENC_2BYTE) {
4144 if (prop & ENC_ENDIAN_L)
4145 return FIO_UCS2 | FIO_ENDIAN_L;
4146 return FIO_UCS2;
4147 }
4148 if (prop & ENC_4BYTE) {
4149 if (prop & ENC_ENDIAN_L)
4150 return FIO_UCS4 | FIO_ENDIAN_L;
4151 return FIO_UCS4;
4152 }
4153 if (prop & ENC_2WORD) {
4154 if (prop & ENC_ENDIAN_L)
4155 return FIO_UTF16 | FIO_ENDIAN_L;
4156 return FIO_UTF16;
4157 }
4158 return FIO_UTF8;
4159 }
4160 if (prop & ENC_LATIN1)
4161 return FIO_LATIN1;
4162 /* must be ENC_DBCS, requires iconv() */
4163 return 0;
4164}
4165
4166
4167
4168/*
4169 * Check for a Unicode BOM (Byte Order Mark) at the start of p[size].
4170 * "size" must be at least 2.
4171 * Return the name of the encoding and set "*lenp" to the length.
4172 * Returns NULL when no BOM found.
4173 */
4174static char_u *check_for_bom(char_u *p, long size, int *lenp, int flags)
4175{
4176 char *name = NULL;
4177 int len = 2;
4178
4179 if (p[0] == 0xef && p[1] == 0xbb && size >= 3 && p[2] == 0xbf
4180 && (flags == FIO_ALL || flags == FIO_UTF8 || flags == 0)) {
4181 name = "utf-8"; /* EF BB BF */
4182 len = 3;
4183 } else if (p[0] == 0xff && p[1] == 0xfe) {
4184 if (size >= 4 && p[2] == 0 && p[3] == 0
4185 && (flags == FIO_ALL || flags == (FIO_UCS4 | FIO_ENDIAN_L))) {
4186 name = "ucs-4le"; /* FF FE 00 00 */
4187 len = 4;
4188 } else if (flags == (FIO_UCS2 | FIO_ENDIAN_L))
4189 name = "ucs-2le"; /* FF FE */
4190 else if (flags == FIO_ALL || flags == (FIO_UTF16 | FIO_ENDIAN_L))
4191 /* utf-16le is preferred, it also works for ucs-2le text */
4192 name = "utf-16le"; /* FF FE */
4193 } else if (p[0] == 0xfe && p[1] == 0xff
4194 && (flags == FIO_ALL || flags == FIO_UCS2 || flags ==
4195 FIO_UTF16)) {
4196 /* Default to utf-16, it works also for ucs-2 text. */
4197 if (flags == FIO_UCS2)
4198 name = "ucs-2"; /* FE FF */
4199 else
4200 name = "utf-16"; /* FE FF */
4201 } else if (size >= 4 && p[0] == 0 && p[1] == 0 && p[2] == 0xfe
4202 && p[3] == 0xff && (flags == FIO_ALL || flags == FIO_UCS4)) {
4203 name = "ucs-4"; /* 00 00 FE FF */
4204 len = 4;
4205 }
4206
4207 *lenp = len;
4208 return (char_u *)name;
4209}
4210
4211/*
4212 * Generate a BOM in "buf[4]" for encoding "name".
4213 * Return the length of the BOM (zero when no BOM).
4214 */
4215static int make_bom(char_u *buf, char_u *name)
4216{
4217 int flags;
4218 char_u *p;
4219
4220 flags = get_fio_flags(name);
4221
4222 /* Can't put a BOM in a non-Unicode file. */
4223 if (flags == FIO_LATIN1 || flags == 0)
4224 return 0;
4225
4226 if (flags == FIO_UTF8) { /* UTF-8 */
4227 buf[0] = 0xef;
4228 buf[1] = 0xbb;
4229 buf[2] = 0xbf;
4230 return 3;
4231 }
4232 p = buf;
4233 (void)ucs2bytes(0xfeff, &p, flags);
4234 return (int)(p - buf);
4235}
4236
4237/// Shorten filename of a buffer.
4238/// When "force" is TRUE: Use full path from now on for files currently being
4239/// edited, both for file name and swap file name. Try to shorten the file
4240/// names a bit, if safe to do so.
4241/// When "force" is FALSE: Only try to shorten absolute file names.
4242/// For buffers that have buftype "nofile" or "scratch": never change the file
4243/// name.
4244void shorten_buf_fname(buf_T *buf, char_u *dirname, int force)
4245{
4246 char_u *p;
4247
4248 if (buf->b_fname != NULL
4249 && !bt_nofile(buf)
4250 && !path_with_url((char *)buf->b_fname)
4251 && (force
4252 || buf->b_sfname == NULL
4253 || path_is_absolute(buf->b_sfname))) {
4254 XFREE_CLEAR(buf->b_sfname);
4255 p = path_shorten_fname(buf->b_ffname, dirname);
4256 if (p != NULL) {
4257 buf->b_sfname = vim_strsave(p);
4258 buf->b_fname = buf->b_sfname;
4259 }
4260 if (p == NULL) {
4261 buf->b_fname = buf->b_ffname;
4262 }
4263 }
4264}
4265
4266/// Shorten filenames for all buffers.
4267void shorten_fnames(int force)
4268{
4269 char_u dirname[MAXPATHL];
4270
4271 os_dirname(dirname, MAXPATHL);
4272 FOR_ALL_BUFFERS(buf) {
4273 shorten_buf_fname(buf, dirname, force);
4274
4275 // Always make the swap file name a full path, a "nofile" buffer may
4276 // also have a swap file.
4277 mf_fullname(buf->b_ml.ml_mfp);
4278 }
4279 status_redraw_all();
4280 redraw_tabline = TRUE;
4281}
4282
4283/// Get new filename ended by given extension.
4284///
4285/// @param fname The original filename.
4286/// If NULL, use current directory name and ext to
4287/// compute new filename.
4288/// @param ext The extension to add to the filename.
4289/// 4 chars max if prefixed with a dot, 3 otherwise.
4290/// @param prepend_dot If true, prefix ext with a dot.
4291/// Does nothing if ext already starts with a dot, or
4292/// if fname is NULL.
4293///
4294/// @return [allocated] - A new filename, made up from:
4295/// * fname + ext, if fname not NULL.
4296/// * current dir + ext, if fname is NULL.
4297/// Result is guaranteed to:
4298/// * be ended by <ext>.
4299/// * have a basename with at most BASENAMELEN chars:
4300/// original basename is truncated if necessary.
4301/// * be different than original: basename chars are
4302/// replaced by "_" if necessary. If that can't be done
4303/// because truncated value of original filename was
4304/// made of all underscores, replace first "_" by "v".
4305/// - NULL, if fname is NULL and there was a problem trying
4306/// to get current directory.
4307char *modname(const char *fname, const char *ext, bool prepend_dot)
4308 FUNC_ATTR_NONNULL_ARG(2)
4309{
4310 char *retval;
4311 size_t fnamelen;
4312 size_t extlen = strlen(ext);
4313
4314 // If there is no file name we must get the name of the current directory
4315 // (we need the full path in case :cd is used).
4316 if (fname == NULL || *fname == NUL) {
4317 retval = xmalloc(MAXPATHL + extlen + 3); // +3 for PATHSEP, "_" (Win), NUL
4318 if (os_dirname((char_u *)retval, MAXPATHL) == FAIL
4319 || (fnamelen = strlen(retval)) == 0) {
4320 xfree(retval);
4321 return NULL;
4322 }
4323 add_pathsep(retval);
4324 fnamelen = strlen(retval);
4325 prepend_dot = FALSE; // nothing to prepend a dot to
4326 } else {
4327 fnamelen = strlen(fname);
4328 retval = xmalloc(fnamelen + extlen + 3);
4329 strcpy(retval, fname);
4330 }
4331
4332 // Search backwards until we hit a '/', '\' or ':'.
4333 // Then truncate what is after the '/', '\' or ':' to BASENAMELEN characters.
4334 char *ptr = NULL;
4335 for (ptr = retval + fnamelen; ptr > retval; MB_PTR_BACK(retval, ptr)) {
4336 if (vim_ispathsep(*ptr)) {
4337 ptr++;
4338 break;
4339 }
4340 }
4341
4342 // the file name has at most BASENAMELEN characters.
4343 if (strlen(ptr) > BASENAMELEN) {
4344 ptr[BASENAMELEN] = '\0';
4345 }
4346
4347 char *s;
4348 s = ptr + strlen(ptr);
4349
4350 // Append the extension.
4351 // ext can start with '.' and cannot exceed 3 more characters.
4352 strcpy(s, ext);
4353
4354 char *e;
4355 // Prepend the dot if needed.
4356 if (prepend_dot && *(e = (char *)path_tail((char_u *)retval)) != '.') {
4357 STRMOVE(e + 1, e);
4358 *e = '.';
4359 }
4360
4361 // Check that, after appending the extension, the file name is really
4362 // different.
4363 if (fname != NULL && strcmp(fname, retval) == 0) {
4364 // we search for a character that can be replaced by '_'
4365 while (--s >= ptr) {
4366 if (*s != '_') {
4367 *s = '_';
4368 break;
4369 }
4370 }
4371 if (s < ptr) { // fname was "________.<ext>", how tricky!
4372 *ptr = 'v';
4373 }
4374 }
4375 return retval;
4376}
4377
4378/// Like fgets(), but if the file line is too long, it is truncated and the
4379/// rest of the line is thrown away.
4380///
4381/// @param[out] buf buffer to fill
4382/// @param size size of the buffer
4383/// @param fp file to read from
4384///
4385/// @return true for EOF or error
4386bool vim_fgets(char_u *buf, int size, FILE *fp) FUNC_ATTR_NONNULL_ALL
4387{
4388 char *retval;
4389
4390 assert(size > 0);
4391 buf[size - 2] = NUL;
4392
4393 do {
4394 errno = 0;
4395 retval = fgets((char *)buf, size, fp);
4396 } while (retval == NULL && errno == EINTR && ferror(fp));
4397
4398 if (buf[size - 2] != NUL && buf[size - 2] != '\n') {
4399 char tbuf[200];
4400
4401 buf[size - 1] = NUL; // Truncate the line.
4402
4403 // Now throw away the rest of the line:
4404 do {
4405 tbuf[sizeof(tbuf) - 2] = NUL;
4406 errno = 0;
4407 retval = fgets((char *)tbuf, sizeof(tbuf), fp);
4408 if (retval == NULL && (feof(fp) || errno != EINTR)) {
4409 break;
4410 }
4411 } while (tbuf[sizeof(tbuf) - 2] != NUL && tbuf[sizeof(tbuf) - 2] != '\n');
4412 }
4413 return retval == NULL;
4414}
4415
4416/// Read 2 bytes from "fd" and turn them into an int, MSB first.
4417/// Returns -1 when encountering EOF.
4418int get2c(FILE *fd)
4419{
4420 const int n = getc(fd);
4421 if (n == EOF) {
4422 return -1;
4423 }
4424 const int c = getc(fd);
4425 if (c == EOF) {
4426 return -1;
4427 }
4428 return (n << 8) + c;
4429}
4430
4431/// Read 3 bytes from "fd" and turn them into an int, MSB first.
4432/// Returns -1 when encountering EOF.
4433int get3c(FILE *fd)
4434{
4435 int n = getc(fd);
4436 if (n == EOF) {
4437 return -1;
4438 }
4439 int c = getc(fd);
4440 if (c == EOF) {
4441 return -1;
4442 }
4443 n = (n << 8) + c;
4444 c = getc(fd);
4445 if (c == EOF) {
4446 return -1;
4447 }
4448 return (n << 8) + c;
4449}
4450
4451/// Read 4 bytes from "fd" and turn them into an int, MSB first.
4452/// Returns -1 when encountering EOF.
4453int get4c(FILE *fd)
4454{
4455 // Use unsigned rather than int otherwise result is undefined
4456 // when left-shift sets the MSB.
4457 unsigned n;
4458
4459 int c = getc(fd);
4460 if (c == EOF) {
4461 return -1;
4462 }
4463 n = (unsigned)c;
4464 c = getc(fd);
4465 if (c == EOF) {
4466 return -1;
4467 }
4468 n = (n << 8) + (unsigned)c;
4469 c = getc(fd);
4470 if (c == EOF) {
4471 return -1;
4472 }
4473 n = (n << 8) + (unsigned)c;
4474 c = getc(fd);
4475 if (c == EOF) {
4476 return -1;
4477 }
4478 n = (n << 8) + (unsigned)c;
4479 return (int)n;
4480}
4481
4482/// Read 8 bytes from `fd` and turn them into a time_t, MSB first.
4483/// Returns -1 when encountering EOF.
4484time_t get8ctime(FILE *fd)
4485{
4486 time_t n = 0;
4487
4488 for (int i = 0; i < 8; i++) {
4489 const int c = getc(fd);
4490 if (c == EOF) {
4491 return -1;
4492 }
4493 n = (n << 8) + c;
4494 }
4495 return n;
4496}
4497
4498/// Reads a string of length "cnt" from "fd" into allocated memory.
4499/// @return pointer to the string or NULL when unable to read that many bytes.
4500char *read_string(FILE *fd, size_t cnt)
4501{
4502 char *str = xmallocz(cnt);
4503 for (size_t i = 0; i < cnt; i++) {
4504 int c = getc(fd);
4505 if (c == EOF) {
4506 xfree(str);
4507 return NULL;
4508 }
4509 str[i] = (char)c;
4510 }
4511 return str;
4512}
4513
4514/// Writes a number to file "fd", most significant bit first, in "len" bytes.
4515/// @returns false in case of an error.
4516bool put_bytes(FILE *fd, uintmax_t number, size_t len)
4517{
4518 assert(len > 0);
4519 for (size_t i = len - 1; i < len; i--) {
4520 if (putc((int)(number >> (i * 8)), fd) == EOF) {
4521 return false;
4522 }
4523 }
4524 return true;
4525}
4526
4527/// Writes time_t to file "fd" in 8 bytes.
4528/// @returns FAIL when the write failed.
4529int put_time(FILE *fd, time_t time_)
4530{
4531 uint8_t buf[8];
4532 time_to_bytes(time_, buf);
4533 return fwrite(buf, sizeof(uint8_t), ARRAY_SIZE(buf), fd) == 1 ? OK : FAIL;
4534}
4535
4536/// os_rename() only works if both files are on the same file system, this
4537/// function will (attempts to?) copy the file across if rename fails -- webb
4538///
4539/// @return -1 for failure, 0 for success
4540int vim_rename(const char_u *from, const char_u *to)
4541 FUNC_ATTR_NONNULL_ALL
4542{
4543 int fd_in;
4544 int fd_out;
4545 int n;
4546 char *errmsg = NULL;
4547 char *buffer;
4548 long perm;
4549#ifdef HAVE_ACL
4550 vim_acl_T acl; /* ACL from original file */
4551#endif
4552 bool use_tmp_file = false;
4553
4554 /*
4555 * When the names are identical, there is nothing to do. When they refer
4556 * to the same file (ignoring case and slash/backslash differences) but
4557 * the file name differs we need to go through a temp file.
4558 */
4559 if (fnamecmp(from, to) == 0) {
4560 if (p_fic && (STRCMP(path_tail((char_u *)from), path_tail((char_u *)to))
4561 != 0)) {
4562 use_tmp_file = true;
4563 } else {
4564 return 0;
4565 }
4566 }
4567
4568 // Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
4569 FileInfo from_info;
4570 if (!os_fileinfo((char *)from, &from_info)) {
4571 return -1;
4572 }
4573
4574 // It's possible for the source and destination to be the same file.
4575 // This happens when "from" and "to" differ in case and are on a FAT32
4576 // filesystem. In that case go through a temp file name.
4577 FileInfo to_info;
4578 if (os_fileinfo((char *)to, &to_info)
4579 && os_fileinfo_id_equal(&from_info, &to_info)) {
4580 use_tmp_file = true;
4581 }
4582
4583 if (use_tmp_file) {
4584 char_u tempname[MAXPATHL + 1];
4585
4586 /*
4587 * Find a name that doesn't exist and is in the same directory.
4588 * Rename "from" to "tempname" and then rename "tempname" to "to".
4589 */
4590 if (STRLEN(from) >= MAXPATHL - 5)
4591 return -1;
4592 STRCPY(tempname, from);
4593 for (n = 123; n < 99999; n++) {
4594 char * tail = (char *)path_tail(tempname);
4595 snprintf(tail, (MAXPATHL + 1) - (tail - (char *)tempname - 1), "%d", n);
4596
4597 if (!os_path_exists(tempname)) {
4598 if (os_rename(from, tempname) == OK) {
4599 if (os_rename(tempname, to) == OK)
4600 return 0;
4601 /* Strange, the second step failed. Try moving the
4602 * file back and return failure. */
4603 os_rename(tempname, from);
4604 return -1;
4605 }
4606 /* If it fails for one temp name it will most likely fail
4607 * for any temp name, give up. */
4608 return -1;
4609 }
4610 }
4611 return -1;
4612 }
4613
4614 /*
4615 * Delete the "to" file, this is required on some systems to make the
4616 * os_rename() work, on other systems it makes sure that we don't have
4617 * two files when the os_rename() fails.
4618 */
4619
4620 os_remove((char *)to);
4621
4622 /*
4623 * First try a normal rename, return if it works.
4624 */
4625 if (os_rename(from, to) == OK)
4626 return 0;
4627
4628 /*
4629 * Rename() failed, try copying the file.
4630 */
4631 perm = os_getperm((const char *)from);
4632#ifdef HAVE_ACL
4633 // For systems that support ACL: get the ACL from the original file.
4634 acl = mch_get_acl(from);
4635#endif
4636 fd_in = os_open((char *)from, O_RDONLY, 0);
4637 if (fd_in < 0) {
4638#ifdef HAVE_ACL
4639 mch_free_acl(acl);
4640#endif
4641 return -1;
4642 }
4643
4644 /* Create the new file with same permissions as the original. */
4645 fd_out = os_open((char *)to,
4646 O_CREAT|O_EXCL|O_WRONLY|O_NOFOLLOW, (int)perm);
4647 if (fd_out < 0) {
4648 close(fd_in);
4649#ifdef HAVE_ACL
4650 mch_free_acl(acl);
4651#endif
4652 return -1;
4653 }
4654
4655 // Avoid xmalloc() here as vim_rename() is called by buf_write() when nvim
4656 // is `preserve_exit()`ing.
4657 buffer = try_malloc(BUFSIZE);
4658 if (buffer == NULL) {
4659 close(fd_out);
4660 close(fd_in);
4661#ifdef HAVE_ACL
4662 mch_free_acl(acl);
4663#endif
4664 return -1;
4665 }
4666
4667 while ((n = read_eintr(fd_in, buffer, BUFSIZE)) > 0)
4668 if (write_eintr(fd_out, buffer, n) != n) {
4669 errmsg = _("E208: Error writing to \"%s\"");
4670 break;
4671 }
4672
4673 xfree(buffer);
4674 close(fd_in);
4675 if (close(fd_out) < 0)
4676 errmsg = _("E209: Error closing \"%s\"");
4677 if (n < 0) {
4678 errmsg = _("E210: Error reading \"%s\"");
4679 to = from;
4680 }
4681#ifndef UNIX // For Unix os_open() already set the permission.
4682 os_setperm((const char *)to, perm);
4683#endif
4684#ifdef HAVE_ACL
4685 mch_set_acl(to, acl);
4686 mch_free_acl(acl);
4687#endif
4688 if (errmsg != NULL) {
4689 EMSG2(errmsg, to);
4690 return -1;
4691 }
4692 os_remove((char *)from);
4693 return 0;
4694}
4695
4696static int already_warned = FALSE;
4697
4698// Check if any not hidden buffer has been changed.
4699// Postpone the check if there are characters in the stuff buffer, a global
4700// command is being executed, a mapping is being executed or an autocommand is
4701// busy.
4702// Returns TRUE if some message was written (screen should be redrawn and
4703// cursor positioned).
4704int
4705check_timestamps(
4706 int focus // called for GUI focus event
4707)
4708{
4709 int didit = 0;
4710 int n;
4711
4712 /* Don't check timestamps while system() or another low-level function may
4713 * cause us to lose and gain focus. */
4714 if (no_check_timestamps > 0)
4715 return FALSE;
4716
4717 /* Avoid doing a check twice. The OK/Reload dialog can cause a focus
4718 * event and we would keep on checking if the file is steadily growing.
4719 * Do check again after typing something. */
4720 if (focus && did_check_timestamps) {
4721 need_check_timestamps = TRUE;
4722 return FALSE;
4723 }
4724
4725 if (!stuff_empty() || global_busy || !typebuf_typed()
4726 || autocmd_busy || curbuf_lock > 0 || allbuf_lock > 0
4727 ) {
4728 need_check_timestamps = true; // check later
4729 } else {
4730 no_wait_return++;
4731 did_check_timestamps = true;
4732 already_warned = false;
4733 FOR_ALL_BUFFERS(buf) {
4734 // Only check buffers in a window.
4735 if (buf->b_nwindows > 0) {
4736 bufref_T bufref;
4737 set_bufref(&bufref, buf);
4738 n = buf_check_timestamp(buf, focus);
4739 if (didit < n) {
4740 didit = n;
4741 }
4742 if (n > 0 && !bufref_valid(&bufref)) {
4743 // Autocommands have removed the buffer, start at the first one again.
4744 buf = firstbuf;
4745 continue;
4746 }
4747 }
4748 }
4749 --no_wait_return;
4750 need_check_timestamps = FALSE;
4751 if (need_wait_return && didit == 2) {
4752 // make sure msg isn't overwritten
4753 msg_puts("\n");
4754 ui_flush();
4755 }
4756 }
4757 return didit;
4758}
4759
4760/*
4761 * Move all the lines from buffer "frombuf" to buffer "tobuf".
4762 * Return OK or FAIL. When FAIL "tobuf" is incomplete and/or "frombuf" is not
4763 * empty.
4764 */
4765static int move_lines(buf_T *frombuf, buf_T *tobuf)
4766{
4767 buf_T *tbuf = curbuf;
4768 int retval = OK;
4769 linenr_T lnum;
4770 char_u *p;
4771
4772 /* Copy the lines in "frombuf" to "tobuf". */
4773 curbuf = tobuf;
4774 for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; lnum++) {
4775 p = vim_strsave(ml_get_buf(frombuf, lnum, false));
4776 if (ml_append(lnum - 1, p, 0, false) == FAIL) {
4777 xfree(p);
4778 retval = FAIL;
4779 break;
4780 }
4781 xfree(p);
4782 }
4783
4784 /* Delete all the lines in "frombuf". */
4785 if (retval != FAIL) {
4786 curbuf = frombuf;
4787 for (lnum = curbuf->b_ml.ml_line_count; lnum > 0; lnum--) {
4788 if (ml_delete(lnum, false) == FAIL) {
4789 // Oops! We could try putting back the saved lines, but that
4790 // might fail again...
4791 retval = FAIL;
4792 break;
4793 }
4794 }
4795 }
4796
4797 curbuf = tbuf;
4798 return retval;
4799}
4800
4801/*
4802 * Check if buffer "buf" has been changed.
4803 * Also check if the file for a new buffer unexpectedly appeared.
4804 * return 1 if a changed buffer was found.
4805 * return 2 if a message has been displayed.
4806 * return 0 otherwise.
4807 */
4808int
4809buf_check_timestamp(
4810 buf_T *buf,
4811 int focus /* called for GUI focus event */
4812)
4813 FUNC_ATTR_NONNULL_ALL
4814{
4815 int retval = 0;
4816 char_u *path;
4817 char *mesg = NULL;
4818 char *mesg2 = "";
4819 bool helpmesg = false;
4820 bool reload = false;
4821 bool can_reload = false;
4822 uint64_t orig_size = buf->b_orig_size;
4823 int orig_mode = buf->b_orig_mode;
4824 static bool busy = false;
4825 char_u *s;
4826 char *reason;
4827
4828 bufref_T bufref;
4829 set_bufref(&bufref, buf);
4830
4831 // If its a terminal, there is no file name, the buffer is not loaded,
4832 // 'buftype' is set, we are in the middle of a save or being called
4833 // recursively: ignore this buffer.
4834 if (buf->terminal
4835 || buf->b_ffname == NULL
4836 || buf->b_ml.ml_mfp == NULL
4837 || *buf->b_p_bt != NUL
4838 || buf->b_saving
4839 || busy
4840 )
4841 return 0;
4842
4843 FileInfo file_info;
4844 bool file_info_ok;
4845 if (!(buf->b_flags & BF_NOTEDITED)
4846 && buf->b_mtime != 0
4847 && (!(file_info_ok = os_fileinfo((char *)buf->b_ffname, &file_info))
4848 || time_differs(file_info.stat.st_mtim.tv_sec, buf->b_mtime)
4849 || (int)file_info.stat.st_mode != buf->b_orig_mode)) {
4850 const long prev_b_mtime = buf->b_mtime;
4851
4852 retval = 1;
4853
4854 // set b_mtime to stop further warnings (e.g., when executing
4855 // FileChangedShell autocmd)
4856 if (!file_info_ok) {
4857 // Check the file again later to see if it re-appears.
4858 buf->b_mtime = -1;
4859 buf->b_orig_size = 0;
4860 buf->b_orig_mode = 0;
4861 } else {
4862 buf_store_file_info(buf, &file_info);
4863 }
4864
4865 /* Don't do anything for a directory. Might contain the file
4866 * explorer. */
4867 if (os_isdir(buf->b_fname)) {
4868 } else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar)
4869 && !bufIsChanged(buf) && file_info_ok) {
4870 // If 'autoread' is set, the buffer has no changes and the file still
4871 // exists, reload the buffer. Use the buffer-local option value if it
4872 // was set, the global option value otherwise.
4873 reload = true;
4874 } else {
4875 if (!file_info_ok) {
4876 reason = "deleted";
4877 } else if (bufIsChanged(buf)) {
4878 reason = "conflict";
4879 } else if (orig_size != buf->b_orig_size || buf_contents_changed(buf)) {
4880 reason = "changed";
4881 } else if (orig_mode != buf->b_orig_mode) {
4882 reason = "mode";
4883 } else {
4884 reason = "time";
4885 }
4886
4887 // Only give the warning if there are no FileChangedShell
4888 // autocommands.
4889 // Avoid being called recursively by setting "busy".
4890 busy = true;
4891 set_vim_var_string(VV_FCS_REASON, reason, -1);
4892 set_vim_var_string(VV_FCS_CHOICE, "", -1);
4893 allbuf_lock++;
4894 bool n = apply_autocmds(EVENT_FILECHANGEDSHELL,
4895 buf->b_fname, buf->b_fname, false, buf);
4896 allbuf_lock--;
4897 busy = false;
4898 if (n) {
4899 if (!bufref_valid(&bufref)) {
4900 EMSG(_("E246: FileChangedShell autocommand deleted buffer"));
4901 }
4902 s = get_vim_var_str(VV_FCS_CHOICE);
4903 if (STRCMP(s, "reload") == 0 && *reason != 'd') {
4904 reload = true;
4905 } else if (STRCMP(s, "ask") == 0) {
4906 n = false;
4907 } else {
4908 return 2;
4909 }
4910 }
4911 if (!n) {
4912 if (*reason == 'd') {
4913 // Only give the message once.
4914 if (prev_b_mtime != -1) {
4915 mesg = _("E211: File \"%s\" no longer available");
4916 }
4917 } else {
4918 helpmesg = true;
4919 can_reload = true;
4920
4921 // Check if the file contents really changed to avoid
4922 // giving a warning when only the timestamp was set (e.g.,
4923 // checked out of CVS). Always warn when the buffer was
4924 // changed.
4925 if (reason[2] == 'n') {
4926 mesg = _(
4927 "W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as well");
4928 mesg2 = _("See \":help W12\" for more info.");
4929 } else if (reason[1] == 'h') {
4930 mesg = _(
4931 "W11: Warning: File \"%s\" has changed since editing started");
4932 mesg2 = _("See \":help W11\" for more info.");
4933 } else if (*reason == 'm') {
4934 mesg = _(
4935 "W16: Warning: Mode of file \"%s\" has changed since editing started");
4936 mesg2 = _("See \":help W16\" for more info.");
4937 } else
4938 /* Only timestamp changed, store it to avoid a warning
4939 * in check_mtime() later. */
4940 buf->b_mtime_read = buf->b_mtime;
4941 }
4942 }
4943 }
4944
4945 } else if ((buf->b_flags & BF_NEW) && !(buf->b_flags & BF_NEW_W)
4946 && os_path_exists(buf->b_ffname)) {
4947 retval = 1;
4948 mesg = _("W13: Warning: File \"%s\" has been created after editing started");
4949 buf->b_flags |= BF_NEW_W;
4950 can_reload = true;
4951 }
4952
4953 if (mesg != NULL) {
4954 path = home_replace_save(buf, buf->b_fname);
4955 if (!helpmesg) {
4956 mesg2 = "";
4957 }
4958 const size_t tbuf_len = STRLEN(path) + STRLEN(mesg) + STRLEN(mesg2) + 2;
4959 char *const tbuf = xmalloc(tbuf_len);
4960 snprintf(tbuf, tbuf_len, mesg, path);
4961 // Set warningmsg here, before the unimportant and output-specific
4962 // mesg2 has been appended.
4963 set_vim_var_string(VV_WARNINGMSG, tbuf, -1);
4964 if (can_reload) {
4965 if (*mesg2 != NUL) {
4966 xstrlcat(tbuf, "\n", tbuf_len - 1);
4967 xstrlcat(tbuf, mesg2, tbuf_len - 1);
4968 }
4969 if (do_dialog(VIM_WARNING, (char_u *) _("Warning"), (char_u *) tbuf,
4970 (char_u *) _("&OK\n&Load File"), 1, NULL, true) == 2) {
4971 reload = true;
4972 }
4973 } else if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned) {
4974 if (*mesg2 != NUL) {
4975 xstrlcat(tbuf, "; ", tbuf_len - 1);
4976 xstrlcat(tbuf, mesg2, tbuf_len - 1);
4977 }
4978 EMSG(tbuf);
4979 retval = 2;
4980 } else {
4981 if (!autocmd_busy) {
4982 msg_start();
4983 msg_puts_attr(tbuf, HL_ATTR(HLF_E) + MSG_HIST);
4984 if (*mesg2 != NUL) {
4985 msg_puts_attr(mesg2, HL_ATTR(HLF_W) + MSG_HIST);
4986 }
4987 msg_clr_eos();
4988 (void)msg_end();
4989 if (emsg_silent == 0) {
4990 ui_flush();
4991 /* give the user some time to think about it */
4992 os_delay(1000L, true);
4993
4994 /* don't redraw and erase the message */
4995 redraw_cmdline = FALSE;
4996 }
4997 }
4998 already_warned = TRUE;
4999 }
5000
5001 xfree(path);
5002 xfree(tbuf);
5003 }
5004
5005 if (reload) {
5006 /* Reload the buffer. */
5007 buf_reload(buf, orig_mode);
5008 if (buf->b_p_udf && buf->b_ffname != NULL) {
5009 char_u hash[UNDO_HASH_SIZE];
5010 buf_T *save_curbuf = curbuf;
5011
5012 /* Any existing undo file is unusable, write it now. */
5013 curbuf = buf;
5014 u_compute_hash(hash);
5015 u_write_undo(NULL, FALSE, buf, hash);
5016 curbuf = save_curbuf;
5017 }
5018 }
5019
5020 // Trigger FileChangedShell when the file was changed in any way.
5021 if (bufref_valid(&bufref) && retval != 0) {
5022 (void)apply_autocmds(EVENT_FILECHANGEDSHELLPOST, buf->b_fname, buf->b_fname,
5023 false, buf);
5024 }
5025 return retval;
5026}
5027
5028/*
5029 * Reload a buffer that is already loaded.
5030 * Used when the file was changed outside of Vim.
5031 * "orig_mode" is buf->b_orig_mode before the need for reloading was detected.
5032 * buf->b_orig_mode may have been reset already.
5033 */
5034void buf_reload(buf_T *buf, int orig_mode)
5035{
5036 exarg_T ea;
5037 pos_T old_cursor;
5038 linenr_T old_topline;
5039 int old_ro = buf->b_p_ro;
5040 buf_T *savebuf;
5041 bufref_T bufref;
5042 int saved = OK;
5043 aco_save_T aco;
5044 int flags = READ_NEW;
5045
5046 /* set curwin/curbuf for "buf" and save some things */
5047 aucmd_prepbuf(&aco, buf);
5048
5049 // We only want to read the text from the file, not reset the syntax
5050 // highlighting, clear marks, diff status, etc. Force the fileformat and
5051 // encoding to be the same.
5052
5053 prep_exarg(&ea, buf);
5054 old_cursor = curwin->w_cursor;
5055 old_topline = curwin->w_topline;
5056
5057 if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur) {
5058 /* Save all the text, so that the reload can be undone.
5059 * Sync first so that this is a separate undo-able action. */
5060 u_sync(FALSE);
5061 saved = u_savecommon(0, curbuf->b_ml.ml_line_count + 1, 0, TRUE);
5062 flags |= READ_KEEP_UNDO;
5063 }
5064
5065 // To behave like when a new file is edited (matters for
5066 // BufReadPost autocommands) we first need to delete the current
5067 // buffer contents. But if reading the file fails we should keep
5068 // the old contents. Can't use memory only, the file might be
5069 // too big. Use a hidden buffer to move the buffer contents to.
5070 if (BUFEMPTY() || saved == FAIL) {
5071 savebuf = NULL;
5072 } else {
5073 // Allocate a buffer without putting it in the buffer list.
5074 savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
5075 set_bufref(&bufref, savebuf);
5076 if (savebuf != NULL && buf == curbuf) {
5077 /* Open the memline. */
5078 curbuf = savebuf;
5079 curwin->w_buffer = savebuf;
5080 saved = ml_open(curbuf);
5081 curbuf = buf;
5082 curwin->w_buffer = buf;
5083 }
5084 if (savebuf == NULL || saved == FAIL || buf != curbuf
5085 || move_lines(buf, savebuf) == FAIL) {
5086 EMSG2(_("E462: Could not prepare for reloading \"%s\""),
5087 buf->b_fname);
5088 saved = FAIL;
5089 }
5090 }
5091
5092 if (saved == OK) {
5093 curbuf->b_flags |= BF_CHECK_RO; // check for RO again
5094 keep_filetype = true; // don't detect 'filetype'
5095 if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0, (linenr_T)0,
5096 (linenr_T)MAXLNUM, &ea, flags) != OK) {
5097 if (!aborting()) {
5098 EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname);
5099 }
5100 if (savebuf != NULL && bufref_valid(&bufref) && buf == curbuf) {
5101 // Put the text back from the save buffer. First
5102 // delete any lines that readfile() added.
5103 while (!BUFEMPTY()) {
5104 if (ml_delete(buf->b_ml.ml_line_count, false) == FAIL) {
5105 break;
5106 }
5107 }
5108 (void)move_lines(savebuf, buf);
5109 }
5110 } else if (buf == curbuf) { // "buf" still valid.
5111 // Mark the buffer as unmodified and free undo info.
5112 unchanged(buf, true, true);
5113 if ((flags & READ_KEEP_UNDO) == 0) {
5114 u_blockfree(buf);
5115 u_clearall(buf);
5116 } else {
5117 // Mark all undo states as changed.
5118 u_unchanged(curbuf);
5119 }
5120 }
5121 }
5122 xfree(ea.cmd);
5123
5124 if (savebuf != NULL && bufref_valid(&bufref)) {
5125 wipe_buffer(savebuf, false);
5126 }
5127
5128 /* Invalidate diff info if necessary. */
5129 diff_invalidate(curbuf);
5130
5131 /* Restore the topline and cursor position and check it (lines may
5132 * have been removed). */
5133 if (old_topline > curbuf->b_ml.ml_line_count)
5134 curwin->w_topline = curbuf->b_ml.ml_line_count;
5135 else
5136 curwin->w_topline = old_topline;
5137 curwin->w_cursor = old_cursor;
5138 check_cursor();
5139 update_topline();
5140 keep_filetype = FALSE;
5141
5142 /* Update folds unless they are defined manually. */
5143 FOR_ALL_TAB_WINDOWS(tp, wp) {
5144 if (wp->w_buffer == curwin->w_buffer
5145 && !foldmethodIsManual(wp)) {
5146 foldUpdateAll(wp);
5147 }
5148 }
5149
5150 /* If the mode didn't change and 'readonly' was set, keep the old
5151 * value; the user probably used the ":view" command. But don't
5152 * reset it, might have had a read error. */
5153 if (orig_mode == curbuf->b_orig_mode)
5154 curbuf->b_p_ro |= old_ro;
5155
5156 /* Modelines must override settings done by autocommands. */
5157 do_modelines(0);
5158
5159 /* restore curwin/curbuf and a few other things */
5160 aucmd_restbuf(&aco);
5161 /* Careful: autocommands may have made "buf" invalid! */
5162}
5163
5164void buf_store_file_info(buf_T *buf, FileInfo *file_info)
5165 FUNC_ATTR_NONNULL_ALL
5166{
5167 buf->b_mtime = file_info->stat.st_mtim.tv_sec;
5168 buf->b_orig_size = os_fileinfo_size(file_info);
5169 buf->b_orig_mode = (int)file_info->stat.st_mode;
5170}
5171
5172/*
5173 * Adjust the line with missing eol, used for the next write.
5174 * Used for do_filter(), when the input lines for the filter are deleted.
5175 */
5176void write_lnum_adjust(linenr_T offset)
5177{
5178 if (curbuf->b_no_eol_lnum != 0) /* only if there is a missing eol */
5179 curbuf->b_no_eol_lnum += offset;
5180}
5181
5182#if defined(BACKSLASH_IN_FILENAME)
5183/// Convert all backslashes in fname to forward slashes in-place,
5184/// unless when it looks like a URL.
5185void forward_slash(char_u *fname)
5186{
5187 char_u *p;
5188
5189 if (path_with_url((const char *)fname)) {
5190 return;
5191 }
5192 for (p = fname; *p != NUL; p++) {
5193 // The Big5 encoding can have '\' in the trail byte.
5194 if (*p == '\\') {
5195 *p = '/';
5196 }
5197 }
5198}
5199#endif
5200
5201/// Name of Vim's own temp dir. Ends in a slash.
5202static char_u *vim_tempdir = NULL;
5203
5204/// Create a directory for private use by this instance of Neovim.
5205/// This is done once, and the same directory is used for all temp files.
5206/// This method avoids security problems because of symlink attacks et al.
5207/// It's also a bit faster, because we only need to check for an existing
5208/// file when creating the directory and not for each temp file.
5209static void vim_maketempdir(void)
5210{
5211 static const char *temp_dirs[] = TEMP_DIR_NAMES;
5212 // Try the entries in `TEMP_DIR_NAMES` to create the temp directory.
5213 char_u template[TEMP_FILE_PATH_MAXLEN];
5214 char_u path[TEMP_FILE_PATH_MAXLEN];
5215
5216 // Make sure the umask doesn't remove the executable bit.
5217 // "repl" has been reported to use "0177".
5218 mode_t umask_save = umask(0077);
5219 for (size_t i = 0; i < ARRAY_SIZE(temp_dirs); i++) {
5220 // Expand environment variables, leave room for "/nvimXXXXXX/999999999"
5221 expand_env((char_u *)temp_dirs[i], template, TEMP_FILE_PATH_MAXLEN - 22);
5222 if (!os_isdir(template)) { // directory doesn't exist
5223 continue;
5224 }
5225
5226 add_pathsep((char *)template);
5227 // Concatenate with temporary directory name pattern
5228 STRCAT(template, "nvimXXXXXX");
5229
5230 if (os_mkdtemp((const char *)template, (char *)path) != 0) {
5231 continue;
5232 }
5233
5234 if (vim_settempdir((char *)path)) {
5235 // Successfully created and set temporary directory so stop trying.
5236 break;
5237 } else {
5238 // Couldn't set `vim_tempdir` to `path` so remove created directory.
5239 os_rmdir((char *)path);
5240 }
5241 }
5242 (void)umask(umask_save);
5243}
5244
5245/// Delete "name" and everything in it, recursively.
5246/// @param name The path which should be deleted.
5247/// @return 0 for success, -1 if some file was not deleted.
5248int delete_recursive(const char *name)
5249{
5250 int result = 0;
5251
5252 if (os_isrealdir(name)) {
5253 snprintf((char *)NameBuff, MAXPATHL, "%s/*", name); // NOLINT
5254
5255 char_u **files;
5256 int file_count;
5257 char_u *exp = vim_strsave(NameBuff);
5258 if (gen_expand_wildcards(1, &exp, &file_count, &files,
5259 EW_DIR | EW_FILE | EW_SILENT | EW_ALLLINKS
5260 | EW_DODOT | EW_EMPTYOK) == OK) {
5261 for (int i = 0; i < file_count; i++) {
5262 if (delete_recursive((const char *)files[i]) != 0) {
5263 result = -1;
5264 }
5265 }
5266 FreeWild(file_count, files);
5267 } else {
5268 result = -1;
5269 }
5270
5271 xfree(exp);
5272 os_rmdir(name);
5273 } else {
5274 result = os_remove(name) == 0 ? 0 : -1;
5275 }
5276
5277 return result;
5278}
5279
5280/// Delete the temp directory and all files it contains.
5281void vim_deltempdir(void)
5282{
5283 if (vim_tempdir != NULL) {
5284 // remove the trailing path separator
5285 path_tail(vim_tempdir)[-1] = NUL;
5286 delete_recursive((const char *)vim_tempdir);
5287 XFREE_CLEAR(vim_tempdir);
5288 }
5289}
5290
5291/// Get the name of temp directory. This directory would be created on the first
5292/// call to this function.
5293char_u *vim_gettempdir(void)
5294{
5295 if (vim_tempdir == NULL) {
5296 vim_maketempdir();
5297 }
5298
5299 return vim_tempdir;
5300}
5301
5302/// Set Neovim own temporary directory name to `tempdir`. This directory should
5303/// be already created. Expand this name to a full path and put it in
5304/// `vim_tempdir`. This avoids that using `:cd` would confuse us.
5305///
5306/// @param tempdir must be no longer than MAXPATHL.
5307///
5308/// @return false if we run out of memory.
5309static bool vim_settempdir(char *tempdir)
5310{
5311 char *buf = verbose_try_malloc(MAXPATHL + 2);
5312 if (!buf) {
5313 return false;
5314 }
5315 vim_FullName(tempdir, buf, MAXPATHL, false);
5316 add_pathsep(buf);
5317 vim_tempdir = (char_u *)xstrdup(buf);
5318 xfree(buf);
5319 return true;
5320}
5321
5322/// Return a unique name that can be used for a temp file.
5323///
5324/// @note The temp file is NOT created.
5325///
5326/// @return pointer to the temp file name or NULL if Neovim can't create
5327/// temporary directory for its own temporary files.
5328char_u *vim_tempname(void)
5329{
5330 // Temp filename counter.
5331 static uint32_t temp_count;
5332
5333 char_u *tempdir = vim_gettempdir();
5334 if (!tempdir) {
5335 return NULL;
5336 }
5337
5338 // There is no need to check if the file exists, because we own the directory
5339 // and nobody else creates a file in it.
5340 char_u template[TEMP_FILE_PATH_MAXLEN];
5341 snprintf((char *)template, TEMP_FILE_PATH_MAXLEN,
5342 "%s%" PRIu32, tempdir, temp_count++);
5343 return vim_strsave(template);
5344}
5345
5346
5347/*
5348 * Code for automatic commands.
5349 */
5350#ifdef INCLUDE_GENERATED_DECLARATIONS
5351# include "auevents_name_map.generated.h"
5352#endif
5353
5354static AutoPatCmd *active_apc_list = NULL; /* stack of active autocommands */
5355
5356/// List of autocmd group names
5357static garray_T augroups = { 0, 0, sizeof(char_u *), 10, NULL };
5358#define AUGROUP_NAME(i) (((char **)augroups.ga_data)[i])
5359
5360/*
5361 * The ID of the current group. Group 0 is the default one.
5362 */
5363static int current_augroup = AUGROUP_DEFAULT;
5364
5365static int au_need_clean = FALSE; /* need to delete marked patterns */
5366
5367
5368
5369static event_T last_event;
5370static int last_group;
5371static int autocmd_blocked = 0; /* block all autocmds */
5372
5373// use get_deleted_augroup() to get this
5374static const char *deleted_augroup = NULL;
5375
5376static inline const char *get_deleted_augroup(void)
5377 FUNC_ATTR_ALWAYS_INLINE
5378{
5379 if (deleted_augroup == NULL) {
5380 deleted_augroup = _("--Deleted--");
5381 }
5382 return deleted_augroup;
5383}
5384
5385/*
5386 * Show the autocommands for one AutoPat.
5387 */
5388static void show_autocmd(AutoPat *ap, event_T event)
5389{
5390 AutoCmd *ac;
5391
5392 /* Check for "got_int" (here and at various places below), which is set
5393 * when "q" has been hit for the "--more--" prompt */
5394 if (got_int)
5395 return;
5396 if (ap->pat == NULL) /* pattern has been removed */
5397 return;
5398
5399 msg_putchar('\n');
5400 if (got_int)
5401 return;
5402 if (event != last_event || ap->group != last_group) {
5403 if (ap->group != AUGROUP_DEFAULT) {
5404 if (AUGROUP_NAME(ap->group) == NULL) {
5405 msg_puts_attr(get_deleted_augroup(), HL_ATTR(HLF_E));
5406 } else {
5407 msg_puts_attr(AUGROUP_NAME(ap->group), HL_ATTR(HLF_T));
5408 }
5409 msg_puts(" ");
5410 }
5411 msg_puts_attr(event_nr2name(event), HL_ATTR(HLF_T));
5412 last_event = event;
5413 last_group = ap->group;
5414 msg_putchar('\n');
5415 if (got_int)
5416 return;
5417 }
5418 msg_col = 4;
5419 msg_outtrans(ap->pat);
5420
5421 for (ac = ap->cmds; ac != NULL; ac = ac->next) {
5422 if (ac->cmd == NULL) { /* skip removed commands */
5423 continue;
5424 }
5425 if (msg_col >= 14) {
5426 msg_putchar('\n');
5427 }
5428 msg_col = 14;
5429 if (got_int) {
5430 return;
5431 }
5432 msg_outtrans(ac->cmd);
5433 if (p_verbose > 0) {
5434 last_set_msg(ac->script_ctx);
5435 }
5436 if (got_int) {
5437 return;
5438 }
5439 if (ac->next != NULL) {
5440 msg_putchar('\n');
5441 if (got_int) {
5442 return;
5443 }
5444 }
5445 }
5446}
5447
5448// Mark an autocommand handler for deletion.
5449static void au_remove_pat(AutoPat *ap)
5450{
5451 XFREE_CLEAR(ap->pat);
5452 ap->buflocal_nr = -1;
5453 au_need_clean = true;
5454}
5455
5456// Mark all commands for a pattern for deletion.
5457static void au_remove_cmds(AutoPat *ap)
5458{
5459 for (AutoCmd *ac = ap->cmds; ac != NULL; ac = ac->next) {
5460 XFREE_CLEAR(ac->cmd);
5461 }
5462 au_need_clean = true;
5463}
5464
5465// Delete one command from an autocmd pattern.
5466static void au_del_cmd(AutoCmd *ac)
5467{
5468 XFREE_CLEAR(ac->cmd);
5469 au_need_clean = true;
5470}
5471
5472/// Cleanup autocommands and patterns that have been deleted.
5473/// This is only done when not executing autocommands.
5474static void au_cleanup(void)
5475{
5476 AutoPat *ap, **prev_ap;
5477 AutoCmd *ac, **prev_ac;
5478 event_T event;
5479
5480 if (autocmd_busy || !au_need_clean) {
5481 return;
5482 }
5483
5484 // Loop over all events.
5485 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
5486 event = (event_T)((int)event + 1)) {
5487 // Loop over all autocommand patterns.
5488 prev_ap = &(first_autopat[(int)event]);
5489 for (ap = *prev_ap; ap != NULL; ap = *prev_ap) {
5490 // Loop over all commands for this pattern.
5491 prev_ac = &(ap->cmds);
5492 bool has_cmd = false;
5493
5494 for (ac = *prev_ac; ac != NULL; ac = *prev_ac) {
5495 // Remove the command if the pattern is to be deleted or when
5496 // the command has been marked for deletion.
5497 if (ap->pat == NULL || ac->cmd == NULL) {
5498 *prev_ac = ac->next;
5499 xfree(ac->cmd);
5500 xfree(ac);
5501 } else {
5502 has_cmd = true;
5503 prev_ac = &(ac->next);
5504 }
5505 }
5506
5507 if (ap->pat != NULL && !has_cmd) {
5508 // Pattern was not marked for deletion, but all of its commands were.
5509 // So mark the pattern for deletion.
5510 au_remove_pat(ap);
5511 }
5512
5513 // Remove the pattern if it has been marked for deletion.
5514 if (ap->pat == NULL) {
5515 if (ap->next == NULL) {
5516 if (prev_ap == &(first_autopat[(int)event])) {
5517 last_autopat[(int)event] = NULL;
5518 } else {
5519 // this depends on the "next" field being the first in
5520 // the struct
5521 last_autopat[(int)event] = (AutoPat *)prev_ap;
5522 }
5523 }
5524 *prev_ap = ap->next;
5525 vim_regfree(ap->reg_prog);
5526 xfree(ap);
5527 } else {
5528 prev_ap = &(ap->next);
5529 }
5530 }
5531 }
5532
5533 au_need_clean = false;
5534}
5535
5536/*
5537 * Called when buffer is freed, to remove/invalidate related buffer-local
5538 * autocmds.
5539 */
5540void aubuflocal_remove(buf_T *buf)
5541{
5542 AutoPat *ap;
5543 event_T event;
5544 AutoPatCmd *apc;
5545
5546 /* invalidate currently executing autocommands */
5547 for (apc = active_apc_list; apc; apc = apc->next)
5548 if (buf->b_fnum == apc->arg_bufnr)
5549 apc->arg_bufnr = 0;
5550
5551 /* invalidate buflocals looping through events */
5552 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
5553 event = (event_T)((int)event + 1))
5554 /* loop over all autocommand patterns */
5555 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
5556 if (ap->buflocal_nr == buf->b_fnum) {
5557 au_remove_pat(ap);
5558 if (p_verbose >= 6) {
5559 verbose_enter();
5560 smsg(_("auto-removing autocommand: %s <buffer=%d>"),
5561 event_nr2name(event), buf->b_fnum);
5562 verbose_leave();
5563 }
5564 }
5565 au_cleanup();
5566}
5567
5568// Add an autocmd group name.
5569// Return its ID. Returns AUGROUP_ERROR (< 0) for error.
5570static int au_new_group(char_u *name)
5571{
5572 int i = au_find_group(name);
5573 if (i == AUGROUP_ERROR) { // the group doesn't exist yet, add it.
5574 // First try using a free entry.
5575 for (i = 0; i < augroups.ga_len; i++) {
5576 if (AUGROUP_NAME(i) == NULL) {
5577 break;
5578 }
5579 }
5580 if (i == augroups.ga_len) {
5581 ga_grow(&augroups, 1);
5582 }
5583
5584 AUGROUP_NAME(i) = xstrdup((char *)name);
5585 if (i == augroups.ga_len) {
5586 augroups.ga_len++;
5587 }
5588 }
5589
5590 return i;
5591}
5592
5593static void au_del_group(char_u *name)
5594{
5595 int i = au_find_group(name);
5596 if (i == AUGROUP_ERROR) { // the group doesn't exist
5597 EMSG2(_("E367: No such group: \"%s\""), name);
5598 } else if (i == current_augroup) {
5599 EMSG(_("E936: Cannot delete the current group"));
5600 } else {
5601 event_T event;
5602 AutoPat *ap;
5603 int in_use = false;
5604
5605 for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
5606 event = (event_T)((int)event + 1)) {
5607 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next) {
5608 if (ap->group == i && ap->pat != NULL) {
5609 give_warning((char_u *)
5610 _("W19: Deleting augroup that is still in use"), true);
5611 in_use = true;
5612 event = NUM_EVENTS;
5613 break;
5614 }
5615 }
5616 }
5617 xfree(AUGROUP_NAME(i));
5618 if (in_use) {
5619 AUGROUP_NAME(i) = (char *)get_deleted_augroup();
5620 } else {
5621 AUGROUP_NAME(i) = NULL;
5622 }
5623 }
5624}
5625
5626/// Find the ID of an autocmd group name.
5627///
5628/// @param name augroup name
5629///
5630/// @return the ID or AUGROUP_ERROR (< 0) for error.
5631static int au_find_group(const char_u *name)
5632 FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
5633{
5634 for (int i = 0; i < augroups.ga_len; i++) {
5635 if (AUGROUP_NAME(i) != NULL && AUGROUP_NAME(i) != get_deleted_augroup()
5636 && STRCMP(AUGROUP_NAME(i), name) == 0) {
5637 return i;
5638 }
5639 }
5640 return AUGROUP_ERROR;
5641}
5642
5643/// Return true if augroup "name" exists.
5644///
5645/// @param name augroup name
5646bool au_has_group(const char_u *name)
5647 FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
5648{
5649 return au_find_group(name) != AUGROUP_ERROR;
5650}
5651
5652/// ":augroup {name}".
5653void do_augroup(char_u *arg, int del_group)
5654{
5655 if (del_group) {
5656 if (*arg == NUL) {
5657 EMSG(_(e_argreq));
5658 } else {
5659 au_del_group(arg);
5660 }
5661 } else if (STRICMP(arg, "end") == 0) { // ":aug end": back to group 0
5662 current_augroup = AUGROUP_DEFAULT;
5663 } else if (*arg) { // ":aug xxx": switch to group xxx
5664 int i = au_new_group(arg);
5665 if (i != AUGROUP_ERROR)
5666 current_augroup = i;
5667 } else { // ":aug": list the group names
5668 msg_start();
5669 for (int i = 0; i < augroups.ga_len; ++i) {
5670 if (AUGROUP_NAME(i) != NULL) {
5671 msg_puts(AUGROUP_NAME(i));
5672 msg_puts(" ");
5673 }
5674 }
5675 msg_clr_eos();
5676 msg_end();
5677 }
5678}
5679
5680#if defined(EXITFREE)
5681void free_all_autocmds(void)
5682{
5683 for (current_augroup = -1; current_augroup < augroups.ga_len;
5684 current_augroup++) {
5685 do_autocmd((char_u *)"", true);
5686 }
5687
5688 for (int i = 0; i < augroups.ga_len; i++) {
5689 char *const s = ((char **)(augroups.ga_data))[i];
5690 if ((const char *)s != get_deleted_augroup()) {
5691 xfree(s);
5692 }
5693 }
5694 ga_clear(&augroups);
5695}
5696#endif
5697
5698/*
5699 * Return the event number for event name "start".
5700 * Return NUM_EVENTS if the event name was not found.
5701 * Return a pointer to the next event name in "end".
5702 */
5703static event_T event_name2nr(const char_u *start, char_u **end)
5704{
5705 const char_u *p;
5706 int i;
5707 int len;
5708
5709 // the event name ends with end of line, '|', a blank or a comma
5710 for (p = start; *p && !ascii_iswhite(*p) && *p != ',' && *p != '|'; p++) {
5711 }
5712 for (i = 0; event_names[i].name != NULL; i++) {
5713 len = (int)event_names[i].len;
5714 if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0) {
5715 break;
5716 }
5717 }
5718 if (*p == ',') {
5719 p++;
5720 }
5721 *end = (char_u *)p;
5722 if (event_names[i].name == NULL) {
5723 return NUM_EVENTS;
5724 }
5725 return event_names[i].event;
5726}
5727
5728/// Return the name for event
5729///
5730/// @param[in] event Event to return name for.
5731///
5732/// @return Event name, static string. Returns "Unknown" for unknown events.
5733static const char *event_nr2name(event_T event)
5734 FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_CONST
5735{
5736 int i;
5737
5738 for (i = 0; event_names[i].name != NULL; i++) {
5739 if (event_names[i].event == event) {
5740 return event_names[i].name;
5741 }
5742 }
5743 return "Unknown";
5744}
5745
5746/*
5747 * Scan over the events. "*" stands for all events.
5748 */
5749static char_u *
5750find_end_event (
5751 char_u *arg,
5752 int have_group /* TRUE when group name was found */
5753)
5754{
5755 char_u *pat;
5756 char_u *p;
5757
5758 if (*arg == '*') {
5759 if (arg[1] && !ascii_iswhite(arg[1])) {
5760 EMSG2(_("E215: Illegal character after *: %s"), arg);
5761 return NULL;
5762 }
5763 pat = arg + 1;
5764 } else {
5765 for (pat = arg; *pat && *pat != '|' && !ascii_iswhite(*pat); pat = p) {
5766 if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS) {
5767 if (have_group)
5768 EMSG2(_("E216: No such event: %s"), pat);
5769 else
5770 EMSG2(_("E216: No such group or event: %s"), pat);
5771 return NULL;
5772 }
5773 }
5774 }
5775 return pat;
5776}
5777
5778/// Return true if "event" is included in 'eventignore'.
5779///
5780/// @param event event to check
5781static bool event_ignored(event_T event)
5782 FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
5783{
5784 char_u *p = p_ei;
5785
5786 while (*p != NUL) {
5787 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ',')) {
5788 return true;
5789 }
5790 if (event_name2nr(p, &p) == event) {
5791 return true;
5792 }
5793 }
5794
5795 return false;
5796}
5797
5798/*
5799 * Return OK when the contents of p_ei is valid, FAIL otherwise.
5800 */
5801int check_ei(void)
5802{
5803 char_u *p = p_ei;
5804
5805 while (*p) {
5806 if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ',')) {
5807 p += 3;
5808 if (*p == ',')
5809 ++p;
5810 } else if (event_name2nr(p, &p) == NUM_EVENTS)
5811 return FAIL;
5812 }
5813
5814 return OK;
5815}
5816
5817/*
5818 * Add "what" to 'eventignore' to skip loading syntax highlighting for every
5819 * buffer loaded into the window. "what" must start with a comma.
5820 * Returns the old value of 'eventignore' in allocated memory.
5821 */
5822char_u *au_event_disable(char *what)
5823{
5824 char_u *new_ei;
5825 char_u *save_ei;
5826
5827 save_ei = vim_strsave(p_ei);
5828 new_ei = vim_strnsave(p_ei, (int)(STRLEN(p_ei) + STRLEN(what)));
5829 if (*what == ',' && *p_ei == NUL)
5830 STRCPY(new_ei, what + 1);
5831 else
5832 STRCAT(new_ei, what);
5833 set_string_option_direct((char_u *)"ei", -1, new_ei, OPT_FREE, SID_NONE);
5834 xfree(new_ei);
5835
5836 return save_ei;
5837}
5838
5839void au_event_restore(char_u *old_ei)
5840{
5841 if (old_ei != NULL) {
5842 set_string_option_direct((char_u *)"ei", -1, old_ei,
5843 OPT_FREE, SID_NONE);
5844 xfree(old_ei);
5845 }
5846}
5847
5848// Implements :autocmd.
5849// Defines an autocmd (does not execute; cf. apply_autocmds_group).
5850//
5851// Can be used in the following ways:
5852//
5853// :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
5854// will be automatically executed for <event>
5855// when editing a file matching <pat>, in
5856// the current group.
5857// :autocmd <event> <pat> Show the autocommands associated with
5858// <event> and <pat>.
5859// :autocmd <event> Show the autocommands associated with
5860// <event>.
5861// :autocmd Show all autocommands.
5862// :autocmd! <event> <pat> <cmd> Remove all autocommands associated with
5863// <event> and <pat>, and add the command
5864// <cmd>, for the current group.
5865// :autocmd! <event> <pat> Remove all autocommands associated with
5866// <event> and <pat> for the current group.
5867// :autocmd! <event> Remove all autocommands associated with
5868// <event> for the current group.
5869// :autocmd! Remove ALL autocommands for the current
5870// group.
5871//
5872// Multiple events and patterns may be given separated by commas. Here are
5873// some examples:
5874// :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
5875// :autocmd bufleave * set tw=79 nosmartindent ic infercase
5876//
5877// :autocmd * *.c show all autocommands for *.c files.
5878//
5879// Mostly a {group} argument can optionally appear before <event>.
5880void do_autocmd(char_u *arg_in, int forceit)
5881{
5882 char_u *arg = arg_in;
5883 char_u *pat;
5884 char_u *envpat = NULL;
5885 char_u *cmd;
5886 int need_free = false;
5887 int nested = false;
5888 bool once = false;
5889 int group;
5890
5891 if (*arg == '|') {
5892 arg = (char_u *)"";
5893 group = AUGROUP_ALL; // no argument, use all groups
5894 } else {
5895 // Check for a legal group name. If not, use AUGROUP_ALL.
5896 group = au_get_grouparg(&arg);
5897 }
5898
5899 /*
5900 * Scan over the events.
5901 * If we find an illegal name, return here, don't do anything.
5902 */
5903 pat = find_end_event(arg, group != AUGROUP_ALL);
5904 if (pat == NULL)
5905 return;
5906
5907 pat = skipwhite(pat);
5908 if (*pat == '|') {
5909 pat = (char_u *)"";
5910 cmd = (char_u *)"";
5911 } else {
5912 // Scan over the pattern. Put a NUL at the end.
5913 cmd = pat;
5914 while (*cmd && (!ascii_iswhite(*cmd) || cmd[-1] == '\\')) {
5915 cmd++;
5916 }
5917 if (*cmd) {
5918 *cmd++ = NUL;
5919 }
5920
5921 // Expand environment variables in the pattern. Set 'shellslash', we want
5922 // forward slashes here.
5923 if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL) {
5924#ifdef BACKSLASH_IN_FILENAME
5925 int p_ssl_save = p_ssl;
5926
5927 p_ssl = true;
5928#endif
5929 envpat = expand_env_save(pat);
5930#ifdef BACKSLASH_IN_FILENAME
5931 p_ssl = p_ssl_save;
5932#endif
5933 if (envpat != NULL) {
5934 pat = envpat;
5935 }
5936 }
5937
5938 cmd = skipwhite(cmd);
5939 for (size_t i = 0; i < 2; i++) {
5940 if (*cmd != NUL) {
5941 // Check for "++once" flag.
5942 if (STRNCMP(cmd, "++once", 6) == 0 && ascii_iswhite(cmd[6])) {
5943 if (once) {
5944 EMSG2(_(e_duparg2), "++once");
5945 }
5946 once = true;
5947 cmd = skipwhite(cmd + 6);
5948 }
5949
5950 // Check for "++nested" flag.
5951 if ((STRNCMP(cmd, "++nested", 8) == 0 && ascii_iswhite(cmd[8]))) {
5952 if (nested) {
5953 EMSG2(_(e_duparg2), "++nested");
5954 }
5955 nested = true;
5956 cmd = skipwhite(cmd + 8);
5957 }
5958
5959 // Check for the old (deprecated) "nested" flag.
5960 if (STRNCMP(cmd, "nested", 6) == 0 && ascii_iswhite(cmd[6])) {
5961 if (nested) {
5962 EMSG2(_(e_duparg2), "nested");
5963 }
5964 nested = true;
5965 cmd = skipwhite(cmd + 6);
5966 }
5967 }
5968 }
5969
5970 // Find the start of the commands.
5971 // Expand <sfile> in it.
5972 if (*cmd != NUL) {
5973 cmd = expand_sfile(cmd);
5974 if (cmd == NULL) { // some error
5975 return;
5976 }
5977 need_free = true;
5978 }
5979 }
5980
5981 /*
5982 * Print header when showing autocommands.
5983 */
5984 if (!forceit && *cmd == NUL) {
5985 // Highlight title
5986 MSG_PUTS_TITLE(_("\n--- Autocommands ---"));
5987 }
5988
5989 /*
5990 * Loop over the events.
5991 */
5992 last_event = (event_T)-1; // for listing the event name
5993 last_group = AUGROUP_ERROR; // for listing the group name
5994 if (*arg == '*' || *arg == NUL || *arg == '|') {
5995 for (event_T event = (event_T)0; (int)event < (int)NUM_EVENTS;
5996 event = (event_T)((int)event + 1)) {
5997 if (do_autocmd_event(event, pat, once, nested, cmd, forceit, group)
5998 == FAIL) {
5999 break;
6000 }
6001 }
6002 } else {
6003 while (*arg && *arg != '|' && !ascii_iswhite(*arg)) {
6004 event_T event = event_name2nr(arg, &arg);
6005 assert(event < NUM_EVENTS);
6006 if (do_autocmd_event(event, pat, once, nested, cmd, forceit, group)
6007 == FAIL) {
6008 break;
6009 }
6010 }
6011 }
6012
6013 if (need_free)
6014 xfree(cmd);
6015 xfree(envpat);
6016}
6017
6018/*
6019 * Find the group ID in a ":autocmd" or ":doautocmd" argument.
6020 * The "argp" argument is advanced to the following argument.
6021 *
6022 * Returns the group ID or AUGROUP_ALL.
6023 */
6024static int au_get_grouparg(char_u **argp)
6025{
6026 char_u *group_name;
6027 char_u *p;
6028 char_u *arg = *argp;
6029 int group = AUGROUP_ALL;
6030
6031 for (p = arg; *p && !ascii_iswhite(*p) && *p != '|'; p++) {
6032 }
6033 if (p > arg) {
6034 group_name = vim_strnsave(arg, (int)(p - arg));
6035 group = au_find_group(group_name);
6036 if (group == AUGROUP_ERROR)
6037 group = AUGROUP_ALL; /* no match, use all groups */
6038 else
6039 *argp = skipwhite(p); /* match, skip over group name */
6040 xfree(group_name);
6041 }
6042 return group;
6043}
6044
6045// do_autocmd() for one event.
6046// Defines an autocmd (does not execute; cf. apply_autocmds_group).
6047//
6048// If *pat == NUL: do for all patterns.
6049// If *cmd == NUL: show entries.
6050// If forceit == TRUE: delete entries.
6051// If group is not AUGROUP_ALL: only use this group.
6052static int do_autocmd_event(event_T event, char_u *pat, bool once, int nested,
6053 char_u *cmd, int forceit, int group)
6054{
6055 AutoPat *ap;
6056 AutoPat **prev_ap;
6057 AutoCmd *ac;
6058 AutoCmd **prev_ac;
6059 int brace_level;
6060 char_u *endpat;
6061 int findgroup;
6062 int allgroups;
6063 int patlen;
6064 int is_buflocal;
6065 int buflocal_nr;
6066 char_u buflocal_pat[25]; /* for "<buffer=X>" */
6067
6068 if (group == AUGROUP_ALL)
6069 findgroup = current_augroup;
6070 else
6071 findgroup = group;
6072 allgroups = (group == AUGROUP_ALL && !forceit && *cmd == NUL);
6073
6074 /*
6075 * Show or delete all patterns for an event.
6076 */
6077 if (*pat == NUL) {
6078 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next) {
6079 if (forceit) { /* delete the AutoPat, if it's in the current group */
6080 if (ap->group == findgroup)
6081 au_remove_pat(ap);
6082 } else if (group == AUGROUP_ALL || ap->group == group)
6083 show_autocmd(ap, event);
6084 }
6085 }
6086
6087 /*
6088 * Loop through all the specified patterns.
6089 */
6090 for (; *pat; pat = (*endpat == ',' ? endpat + 1 : endpat)) {
6091 /*
6092 * Find end of the pattern.
6093 * Watch out for a comma in braces, like "*.\{obj,o\}".
6094 */
6095 endpat = pat;
6096 // ignore single comma
6097 if (*endpat == ',') {
6098 continue;
6099 }
6100 brace_level = 0;
6101 for (; *endpat && (*endpat != ',' || brace_level || endpat[-1] == '\\');
6102 ++endpat) {
6103 if (*endpat == '{')
6104 brace_level++;
6105 else if (*endpat == '}')
6106 brace_level--;
6107 }
6108 patlen = (int)(endpat - pat);
6109
6110 /*
6111 * detect special <buflocal[=X]> buffer-local patterns
6112 */
6113 is_buflocal = FALSE;
6114 buflocal_nr = 0;
6115
6116 if (patlen >= 8 && STRNCMP(pat, "<buffer", 7) == 0
6117 && pat[patlen - 1] == '>') {
6118 /* "<buffer...>": Error will be printed only for addition.
6119 * printing and removing will proceed silently. */
6120 is_buflocal = TRUE;
6121 if (patlen == 8)
6122 /* "<buffer>" */
6123 buflocal_nr = curbuf->b_fnum;
6124 else if (patlen > 9 && pat[7] == '=') {
6125 if (patlen == 13 && STRNICMP(pat, "<buffer=abuf>", 13) == 0)
6126 /* "<buffer=abuf>" */
6127 buflocal_nr = autocmd_bufnr;
6128 else if (skipdigits(pat + 8) == pat + patlen - 1)
6129 /* "<buffer=123>" */
6130 buflocal_nr = atoi((char *)pat + 8);
6131 }
6132 }
6133
6134 if (is_buflocal) {
6135 /* normalize pat into standard "<buffer>#N" form */
6136 sprintf((char *)buflocal_pat, "<buffer=%d>", buflocal_nr);
6137 pat = buflocal_pat; /* can modify pat and patlen */
6138 patlen = (int)STRLEN(buflocal_pat); /* but not endpat */
6139 }
6140
6141 // Find AutoPat entries with this pattern. When adding a command it
6142 // always goes at or after the last one, so start at the end.
6143 if (!forceit && *cmd != NUL && last_autopat[(int)event] != NULL) {
6144 prev_ap = &last_autopat[(int)event];
6145 } else {
6146 prev_ap = &first_autopat[(int)event];
6147 }
6148 while ((ap = *prev_ap) != NULL) {
6149 if (ap->pat != NULL) {
6150 /* Accept a pattern when:
6151 * - a group was specified and it's that group, or a group was
6152 * not specified and it's the current group, or a group was
6153 * not specified and we are listing
6154 * - the length of the pattern matches
6155 * - the pattern matches.
6156 * For <buffer[=X]>, this condition works because we normalize
6157 * all buffer-local patterns.
6158 */
6159 if ((allgroups || ap->group == findgroup)
6160 && ap->patlen == patlen
6161 && STRNCMP(pat, ap->pat, patlen) == 0) {
6162 /*
6163 * Remove existing autocommands.
6164 * If adding any new autocmd's for this AutoPat, don't
6165 * delete the pattern from the autopat list, append to
6166 * this list.
6167 */
6168 if (forceit) {
6169 if (*cmd != NUL && ap->next == NULL) {
6170 au_remove_cmds(ap);
6171 break;
6172 }
6173 au_remove_pat(ap);
6174 }
6175 /*
6176 * Show autocmd's for this autopat, or buflocals <buffer=X>
6177 */
6178 else if (*cmd == NUL)
6179 show_autocmd(ap, event);
6180
6181 /*
6182 * Add autocmd to this autopat, if it's the last one.
6183 */
6184 else if (ap->next == NULL)
6185 break;
6186 }
6187 }
6188 prev_ap = &ap->next;
6189 }
6190
6191 /*
6192 * Add a new command.
6193 */
6194 if (*cmd != NUL) {
6195 /*
6196 * If the pattern we want to add a command to does appear at the
6197 * end of the list (or not is not in the list at all), add the
6198 * pattern at the end of the list.
6199 */
6200 if (ap == NULL) {
6201 /* refuse to add buffer-local ap if buffer number is invalid */
6202 if (is_buflocal && (buflocal_nr == 0
6203 || buflist_findnr(buflocal_nr) == NULL)) {
6204 emsgf(_("E680: <buffer=%d>: invalid buffer number "),
6205 buflocal_nr);
6206 return FAIL;
6207 }
6208
6209 ap = xmalloc(sizeof(AutoPat));
6210 ap->pat = vim_strnsave(pat, patlen);
6211 ap->patlen = patlen;
6212
6213 if (is_buflocal) {
6214 ap->buflocal_nr = buflocal_nr;
6215 ap->reg_prog = NULL;
6216 } else {
6217 char_u *reg_pat;
6218
6219 ap->buflocal_nr = 0;
6220 reg_pat = file_pat_to_reg_pat(pat, endpat,
6221 &ap->allow_dirs, TRUE);
6222 if (reg_pat != NULL)
6223 ap->reg_prog = vim_regcomp(reg_pat, RE_MAGIC);
6224 xfree(reg_pat);
6225 if (reg_pat == NULL || ap->reg_prog == NULL) {
6226 xfree(ap->pat);
6227 xfree(ap);
6228 return FAIL;
6229 }
6230 }
6231 ap->cmds = NULL;
6232 *prev_ap = ap;
6233 last_autopat[(int)event] = ap;
6234 ap->next = NULL;
6235 if (group == AUGROUP_ALL)
6236 ap->group = current_augroup;
6237 else
6238 ap->group = group;
6239 }
6240
6241 /*
6242 * Add the autocmd at the end of the AutoCmd list.
6243 */
6244 prev_ac = &(ap->cmds);
6245 while ((ac = *prev_ac) != NULL)
6246 prev_ac = &ac->next;
6247 ac = xmalloc(sizeof(AutoCmd));
6248 ac->cmd = vim_strsave(cmd);
6249 ac->script_ctx = current_sctx;
6250 ac->script_ctx.sc_lnum += sourcing_lnum;
6251 ac->next = NULL;
6252 *prev_ac = ac;
6253 ac->once = once;
6254 ac->nested = nested;
6255 }
6256 }
6257
6258 au_cleanup(); /* may really delete removed patterns/commands now */
6259 return OK;
6260}
6261
6262// Implementation of ":doautocmd [group] event [fname]".
6263// Return OK for success, FAIL for failure;
6264int
6265do_doautocmd(
6266 char_u *arg,
6267 int do_msg, // give message for no matching autocmds?
6268 bool *did_something
6269)
6270{
6271 char_u *fname;
6272 int nothing_done = TRUE;
6273 int group;
6274
6275 if (did_something != NULL) {
6276 *did_something = false;
6277 }
6278
6279 /*
6280 * Check for a legal group name. If not, use AUGROUP_ALL.
6281 */
6282 group = au_get_grouparg(&arg);
6283
6284 if (*arg == '*') {
6285 EMSG(_("E217: Can't execute autocommands for ALL events"));
6286 return FAIL;
6287 }
6288
6289 /*
6290 * Scan over the events.
6291 * If we find an illegal name, return here, don't do anything.
6292 */
6293 fname = find_end_event(arg, group != AUGROUP_ALL);
6294 if (fname == NULL)
6295 return FAIL;
6296
6297 fname = skipwhite(fname);
6298
6299 // Loop over the events.
6300 while (*arg && !ends_excmd(*arg) && !ascii_iswhite(*arg)) {
6301 if (apply_autocmds_group(event_name2nr(arg, &arg), fname, NULL, true,
6302 group, curbuf, NULL)) {
6303 nothing_done = false;
6304 }
6305 }
6306
6307 if (nothing_done && do_msg) {
6308 MSG(_("No matching autocommands"));
6309 }
6310 if (did_something != NULL) {
6311 *did_something = !nothing_done;
6312 }
6313
6314 return aborting() ? FAIL : OK;
6315}
6316
6317/*
6318 * ":doautoall": execute autocommands for each loaded buffer.
6319 */
6320void ex_doautoall(exarg_T *eap)
6321{
6322 int retval;
6323 aco_save_T aco;
6324 char_u *arg = eap->arg;
6325 int call_do_modelines = check_nomodeline(&arg);
6326 bufref_T bufref;
6327
6328 /*
6329 * This is a bit tricky: For some commands curwin->w_buffer needs to be
6330 * equal to curbuf, but for some buffers there may not be a window.
6331 * So we change the buffer for the current window for a moment. This
6332 * gives problems when the autocommands make changes to the list of
6333 * buffers or windows...
6334 */
6335 FOR_ALL_BUFFERS(buf) {
6336 if (buf->b_ml.ml_mfp == NULL) {
6337 continue;
6338 }
6339 // Find a window for this buffer and save some values.
6340 aucmd_prepbuf(&aco, buf);
6341 set_bufref(&bufref, buf);
6342
6343 bool did_aucmd;
6344 // execute the autocommands for this buffer
6345 retval = do_doautocmd(arg, false, &did_aucmd);
6346
6347 if (call_do_modelines && did_aucmd) {
6348 // Execute the modeline settings, but don't set window-local
6349 // options if we are using the current window for another
6350 // buffer.
6351 do_modelines(curwin == aucmd_win ? OPT_NOWIN : 0);
6352 }
6353
6354 /* restore the current window */
6355 aucmd_restbuf(&aco);
6356
6357 // Stop if there is some error or buffer was deleted.
6358 if (retval == FAIL || !bufref_valid(&bufref)) {
6359 break;
6360 }
6361 }
6362
6363 check_cursor(); /* just in case lines got deleted */
6364}
6365
6366/// Check *argp for <nomodeline>. When it is present return false, otherwise
6367/// return true and advance *argp to after it. Thus do_modelines() should be
6368/// called when true is returned.
6369///
6370/// @param[in,out] argp argument string
6371bool check_nomodeline(char_u **argp)
6372 FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
6373{
6374 if (STRNCMP(*argp, "<nomodeline>", 12) == 0) {
6375 *argp = skipwhite(*argp + 12);
6376 return false;
6377 }
6378 return true;
6379}
6380
6381/// Prepare for executing autocommands for (hidden) buffer `buf`.
6382/// If the current buffer is not in any visible window, put it in a temporary
6383/// floating window `aucmd_win`.
6384/// Set `curbuf` and `curwin` to match `buf`.
6385///
6386/// @param aco structure to save values in
6387/// @param buf new curbuf
6388void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
6389{
6390 win_T *win;
6391 bool need_append = true; // Append `aucmd_win` to the window list.
6392
6393 /* Find a window that is for the new buffer */
6394 if (buf == curbuf) { /* be quick when buf is curbuf */
6395 win = curwin;
6396 } else {
6397 win = NULL;
6398 FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
6399 if (wp->w_buffer == buf) {
6400 win = wp;
6401 break;
6402 }
6403 }
6404 }
6405
6406 // Allocate the `aucmd_win` dummy floating window.
6407 if (win == NULL && aucmd_win == NULL) {
6408 win_alloc_aucmd_win();
6409 need_append = false;
6410 }
6411 if (win == NULL && aucmd_win_used)
6412 /* Strange recursive autocommand, fall back to using the current
6413 * window. Expect a few side effects... */
6414 win = curwin;
6415
6416 aco->save_curwin = curwin;
6417 aco->save_prevwin = prevwin;
6418 aco->save_curbuf = curbuf;
6419 if (win != NULL) {
6420 /* There is a window for "buf" in the current tab page, make it the
6421 * curwin. This is preferred, it has the least side effects (esp. if
6422 * "buf" is curbuf). */
6423 aco->use_aucmd_win = FALSE;
6424 curwin = win;
6425 } else {
6426 /* There is no window for "buf", use "aucmd_win". To minimize the side
6427 * effects, insert it in the current tab page.
6428 * Anything related to a window (e.g., setting folds) may have
6429 * unexpected results. */
6430 aco->use_aucmd_win = TRUE;
6431 aucmd_win_used = TRUE;
6432 aucmd_win->w_buffer = buf;
6433 aucmd_win->w_s = &buf->b_s;
6434 ++buf->b_nwindows;
6435 win_init_empty(aucmd_win); /* set cursor and topline to safe values */
6436
6437 /* Make sure w_localdir and globaldir are NULL to avoid a chdir() in
6438 * win_enter_ext(). */
6439 XFREE_CLEAR(aucmd_win->w_localdir);
6440 aco->globaldir = globaldir;
6441 globaldir = NULL;
6442
6443 block_autocmds(); // We don't want BufEnter/WinEnter autocommands.
6444 if (need_append) {
6445 win_append(lastwin, aucmd_win);
6446 handle_register_window(aucmd_win);
6447 win_config_float(aucmd_win, aucmd_win->w_float_config);
6448 }
6449 // Prevent chdir() call in win_enter_ext(), through do_autochdir()
6450 int save_acd = p_acd;
6451 p_acd = false;
6452 win_enter(aucmd_win, false);
6453 p_acd = save_acd;
6454 unblock_autocmds();
6455 curwin = aucmd_win;
6456 }
6457 curbuf = buf;
6458 aco->new_curwin = curwin;
6459 set_bufref(&aco->new_curbuf, curbuf);
6460}
6461
6462/// Cleanup after executing autocommands for a (hidden) buffer.
6463/// Restore the window as it was (if possible).
6464///
6465/// @param aco structure holding saved values
6466void aucmd_restbuf(aco_save_T *aco)
6467{
6468 if (aco->use_aucmd_win) {
6469 curbuf->b_nwindows--;
6470 // Find "aucmd_win", it can't be closed, but it may be in another tab page.
6471 // Do not trigger autocommands here.
6472 block_autocmds();
6473 if (curwin != aucmd_win) {
6474 FOR_ALL_TAB_WINDOWS(tp, wp) {
6475 if (wp == aucmd_win) {
6476 if (tp != curtab) {
6477 goto_tabpage_tp(tp, true, true);
6478 }
6479 win_goto(aucmd_win);
6480 goto win_found;
6481 }
6482 }
6483 }
6484win_found:
6485
6486 win_remove(curwin, NULL);
6487 handle_unregister_window(curwin);
6488 if (curwin->w_grid.chars != NULL) {
6489 ui_comp_remove_grid(&curwin->w_grid);
6490 ui_call_win_hide(curwin->w_grid.handle);
6491 grid_free(&curwin->w_grid);
6492 }
6493
6494 aucmd_win_used = false;
6495 last_status(false); // may need to remove last status line
6496
6497 if (!valid_tabpage_win(curtab)) {
6498 // no valid window in current tabpage
6499 close_tabpage(curtab);
6500 }
6501
6502 unblock_autocmds();
6503
6504 if (win_valid(aco->save_curwin)) {
6505 curwin = aco->save_curwin;
6506 } else {
6507 // Hmm, original window disappeared. Just use the first one.
6508 curwin = firstwin;
6509 }
6510 prevwin = win_valid(aco->save_prevwin) ? aco->save_prevwin
6511 : firstwin; // window disappeared?
6512 vars_clear(&aucmd_win->w_vars->dv_hashtab); // free all w: variables
6513 hash_init(&aucmd_win->w_vars->dv_hashtab); // re-use the hashtab
6514 curbuf = curwin->w_buffer;
6515
6516 xfree(globaldir);
6517 globaldir = aco->globaldir;
6518
6519 // the buffer contents may have changed
6520 check_cursor();
6521 if (curwin->w_topline > curbuf->b_ml.ml_line_count) {
6522 curwin->w_topline = curbuf->b_ml.ml_line_count;
6523 curwin->w_topfill = 0;
6524 }
6525 } else {
6526 // restore curwin
6527 if (win_valid(aco->save_curwin)) {
6528 // Restore the buffer which was previously edited by curwin, if it was
6529 // changed, we are still the same window and the buffer is valid.
6530 if (curwin == aco->new_curwin
6531 && curbuf != aco->new_curbuf.br_buf
6532 && bufref_valid(&aco->new_curbuf)
6533 && aco->new_curbuf.br_buf->b_ml.ml_mfp != NULL) {
6534 if (curwin->w_s == &curbuf->b_s) {
6535 curwin->w_s = &aco->new_curbuf.br_buf->b_s;
6536 }
6537 curbuf->b_nwindows--;
6538 curbuf = aco->new_curbuf.br_buf;
6539 curwin->w_buffer = curbuf;
6540 curbuf->b_nwindows++;
6541 }
6542
6543 curwin = aco->save_curwin;
6544 prevwin = win_valid(aco->save_prevwin) ? aco->save_prevwin
6545 : firstwin; // window disappeared?
6546 curbuf = curwin->w_buffer;
6547 // In case the autocommand moves the cursor to a position that does not
6548 // exist in curbuf
6549 check_cursor();
6550 }
6551 }
6552}
6553
6554static int autocmd_nested = FALSE;
6555
6556/// Execute autocommands for "event" and file name "fname".
6557///
6558/// @param event event that occured
6559/// @param fname filename, NULL or empty means use actual file name
6560/// @param fname_io filename to use for <afile> on cmdline
6561/// @param force When true, ignore autocmd_busy
6562/// @param buf Buffer for <abuf>
6563///
6564/// @return true if some commands were executed.
6565bool apply_autocmds(event_T event, char_u *fname, char_u *fname_io, bool force,
6566 buf_T *buf)
6567{
6568 return apply_autocmds_group(event, fname, fname_io, force,
6569 AUGROUP_ALL, buf, NULL);
6570}
6571
6572/// Like apply_autocmds(), but with extra "eap" argument. This takes care of
6573/// setting v:filearg.
6574///
6575/// @param event event that occured
6576/// @param fname NULL or empty means use actual file name
6577/// @param fname_io fname to use for <afile> on cmdline
6578/// @param force When true, ignore autocmd_busy
6579/// @param buf Buffer for <abuf>
6580/// @param exarg Ex command arguments
6581///
6582/// @return true if some commands were executed.
6583static bool apply_autocmds_exarg(event_T event, char_u *fname, char_u *fname_io,
6584 bool force, buf_T *buf, exarg_T *eap)
6585{
6586 return apply_autocmds_group(event, fname, fname_io, force,
6587 AUGROUP_ALL, buf, eap);
6588}
6589
6590/// Like apply_autocmds(), but handles the caller's retval. If the script
6591/// processing is being aborted or if retval is FAIL when inside a try
6592/// conditional, no autocommands are executed. If otherwise the autocommands
6593/// cause the script to be aborted, retval is set to FAIL.
6594///
6595/// @param event event that occured
6596/// @param fname NULL or empty means use actual file name
6597/// @param fname_io fname to use for <afile> on cmdline
6598/// @param force When true, ignore autocmd_busy
6599/// @param buf Buffer for <abuf>
6600/// @param[in,out] retval caller's retval
6601///
6602/// @return true if some autocommands were executed
6603bool apply_autocmds_retval(event_T event, char_u *fname, char_u *fname_io,
6604 bool force, buf_T *buf, int *retval)
6605{
6606 if (should_abort(*retval)) {
6607 return false;
6608 }
6609
6610 bool did_cmd = apply_autocmds_group(event, fname, fname_io, force,
6611 AUGROUP_ALL, buf, NULL);
6612 if (did_cmd && aborting()) {
6613 *retval = FAIL;
6614 }
6615 return did_cmd;
6616}
6617
6618/// Return true when there is a CursorHold/CursorHoldI autocommand defined for
6619/// the current mode.
6620bool has_cursorhold(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
6621{
6622 return first_autopat[(int)(get_real_state() == NORMAL_BUSY
6623 ? EVENT_CURSORHOLD : EVENT_CURSORHOLDI)] != NULL;
6624}
6625
6626/// Return true if the CursorHold/CursorHoldI event can be triggered.
6627bool trigger_cursorhold(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
6628{
6629 int state;
6630
6631 if (!did_cursorhold
6632 && has_cursorhold()
6633 && reg_recording == 0
6634 && typebuf.tb_len == 0
6635 && !ins_compl_active()
6636 ) {
6637 state = get_real_state();
6638 if (state == NORMAL_BUSY || (state & INSERT) != 0) {
6639 return true;
6640 }
6641 }
6642 return false;
6643}
6644
6645/// Return true if "event" autocommand is defined.
6646///
6647/// @param event the autocommand to check
6648bool has_event(event_T event) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
6649{
6650 return first_autopat[event] != NULL;
6651}
6652
6653/// Execute autocommands for "event" and file name "fname".
6654///
6655/// @param event event that occured
6656/// @param fname filename, NULL or empty means use actual file name
6657/// @param fname_io filename to use for <afile> on cmdline,
6658/// NULL means use `fname`.
6659/// @param force When true, ignore autocmd_busy
6660/// @param group autocmd group ID or AUGROUP_ALL
6661/// @param buf Buffer for <abuf>
6662/// @param eap Ex command arguments
6663///
6664/// @return true if some commands were executed.
6665static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io,
6666 bool force, int group, buf_T *buf,
6667 exarg_T *eap)
6668{
6669 char_u *sfname = NULL; /* short file name */
6670 char_u *tail;
6671 bool save_changed;
6672 buf_T *old_curbuf;
6673 bool retval = false;
6674 char_u *save_sourcing_name;
6675 linenr_T save_sourcing_lnum;
6676 char_u *save_autocmd_fname;
6677 int save_autocmd_bufnr;
6678 char_u *save_autocmd_match;
6679 int save_autocmd_busy;
6680 int save_autocmd_nested;
6681 static int nesting = 0;
6682 AutoPatCmd patcmd;
6683 AutoPat *ap;
6684 void *save_funccalp;
6685 char_u *save_cmdarg;
6686 long save_cmdbang;
6687 static int filechangeshell_busy = FALSE;
6688 proftime_T wait_time;
6689 bool did_save_redobuff = false;
6690 save_redo_T save_redo;
6691 const bool save_KeyTyped = KeyTyped;
6692
6693 // Quickly return if there are no autocommands for this event or
6694 // autocommands are blocked.
6695 if (event == NUM_EVENTS || first_autopat[(int)event] == NULL
6696 || autocmd_blocked > 0) {
6697 goto BYPASS_AU;
6698 }
6699
6700 /*
6701 * When autocommands are busy, new autocommands are only executed when
6702 * explicitly enabled with the "nested" flag.
6703 */
6704 if (autocmd_busy && !(force || autocmd_nested))
6705 goto BYPASS_AU;
6706
6707 /*
6708 * Quickly return when immediately aborting on error, or when an interrupt
6709 * occurred or an exception was thrown but not caught.
6710 */
6711 if (aborting())
6712 goto BYPASS_AU;
6713
6714 /*
6715 * FileChangedShell never nests, because it can create an endless loop.
6716 */
6717 if (filechangeshell_busy && (event == EVENT_FILECHANGEDSHELL
6718 || event == EVENT_FILECHANGEDSHELLPOST))
6719 goto BYPASS_AU;
6720
6721 /*
6722 * Ignore events in 'eventignore'.
6723 */
6724 if (event_ignored(event))
6725 goto BYPASS_AU;
6726
6727 /*
6728 * Allow nesting of autocommands, but restrict the depth, because it's
6729 * possible to create an endless loop.
6730 */
6731 if (nesting == 10) {
6732 EMSG(_("E218: autocommand nesting too deep"));
6733 goto BYPASS_AU;
6734 }
6735
6736 /*
6737 * Check if these autocommands are disabled. Used when doing ":all" or
6738 * ":ball".
6739 */
6740 if ( (autocmd_no_enter
6741 && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
6742 || (autocmd_no_leave
6743 && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
6744 goto BYPASS_AU;
6745
6746 /*
6747 * Save the autocmd_* variables and info about the current buffer.
6748 */
6749 save_autocmd_fname = autocmd_fname;
6750 save_autocmd_bufnr = autocmd_bufnr;
6751 save_autocmd_match = autocmd_match;
6752 save_autocmd_busy = autocmd_busy;
6753 save_autocmd_nested = autocmd_nested;
6754 save_changed = curbuf->b_changed;
6755 old_curbuf = curbuf;
6756
6757 /*
6758 * Set the file name to be used for <afile>.
6759 * Make a copy to avoid that changing a buffer name or directory makes it
6760 * invalid.
6761 */
6762 if (fname_io == NULL) {
6763 if (event == EVENT_COLORSCHEME
6764 || event == EVENT_COLORSCHEMEPRE
6765 || event == EVENT_OPTIONSET) {
6766 autocmd_fname = NULL;
6767 } else if (fname != NULL && !ends_excmd(*fname)) {
6768 autocmd_fname = fname;
6769 } else if (buf != NULL) {
6770 autocmd_fname = buf->b_ffname;
6771 } else {
6772 autocmd_fname = NULL;
6773 }
6774 } else {
6775 autocmd_fname = fname_io;
6776 }
6777 if (autocmd_fname != NULL) {
6778 // Allocate MAXPATHL for when eval_vars() resolves the fullpath.
6779 autocmd_fname = vim_strnsave(autocmd_fname, MAXPATHL);
6780 }
6781
6782 /*
6783 * Set the buffer number to be used for <abuf>.
6784 */
6785 if (buf == NULL)
6786 autocmd_bufnr = 0;
6787 else
6788 autocmd_bufnr = buf->b_fnum;
6789
6790 /*
6791 * When the file name is NULL or empty, use the file name of buffer "buf".
6792 * Always use the full path of the file name to match with, in case
6793 * "allow_dirs" is set.
6794 */
6795 if (fname == NULL || *fname == NUL) {
6796 if (buf == NULL)
6797 fname = NULL;
6798 else {
6799 if (event == EVENT_SYNTAX)
6800 fname = buf->b_p_syn;
6801 else if (event == EVENT_FILETYPE)
6802 fname = buf->b_p_ft;
6803 else {
6804 if (buf->b_sfname != NULL)
6805 sfname = vim_strsave(buf->b_sfname);
6806 fname = buf->b_ffname;
6807 }
6808 }
6809 if (fname == NULL)
6810 fname = (char_u *)"";
6811 fname = vim_strsave(fname); /* make a copy, so we can change it */
6812 } else {
6813 sfname = vim_strsave(fname);
6814 // Don't try expanding the following events.
6815 if (event == EVENT_CMDLINECHANGED
6816 || event == EVENT_CMDLINEENTER
6817 || event == EVENT_CMDLINELEAVE
6818 || event == EVENT_CMDWINENTER
6819 || event == EVENT_CMDWINLEAVE
6820 || event == EVENT_CMDUNDEFINED
6821 || event == EVENT_COLORSCHEME
6822 || event == EVENT_COLORSCHEMEPRE
6823 || event == EVENT_DIRCHANGED
6824 || event == EVENT_FILETYPE
6825 || event == EVENT_FUNCUNDEFINED
6826 || event == EVENT_OPTIONSET
6827 || event == EVENT_QUICKFIXCMDPOST
6828 || event == EVENT_QUICKFIXCMDPRE
6829 || event == EVENT_REMOTEREPLY
6830 || event == EVENT_SPELLFILEMISSING
6831 || event == EVENT_SYNTAX
6832 || event == EVENT_SIGNAL
6833 || event == EVENT_TABCLOSED) {
6834 fname = vim_strsave(fname);
6835 } else {
6836 fname = (char_u *)FullName_save((char *)fname, false);
6837 }
6838 }
6839 if (fname == NULL) { /* out of memory */
6840 xfree(sfname);
6841 retval = false;
6842 goto BYPASS_AU;
6843 }
6844
6845#ifdef BACKSLASH_IN_FILENAME
6846 // Replace all backslashes with forward slashes. This makes the
6847 // autocommand patterns portable between Unix and Windows.
6848 if (sfname != NULL) {
6849 forward_slash(sfname);
6850 }
6851 forward_slash(fname);
6852#endif
6853
6854
6855 /*
6856 * Set the name to be used for <amatch>.
6857 */
6858 autocmd_match = fname;
6859
6860
6861 // Don't redraw while doing autocommands.
6862 RedrawingDisabled++;
6863 save_sourcing_name = sourcing_name;
6864 sourcing_name = NULL; /* don't free this one */
6865 save_sourcing_lnum = sourcing_lnum;
6866 sourcing_lnum = 0; /* no line number here */
6867
6868 const sctx_T save_current_sctx = current_sctx;
6869
6870 if (do_profiling == PROF_YES)
6871 prof_child_enter(&wait_time); /* doesn't count for the caller itself */
6872
6873 /* Don't use local function variables, if called from a function */
6874 save_funccalp = save_funccal();
6875
6876 /*
6877 * When starting to execute autocommands, save the search patterns.
6878 */
6879 if (!autocmd_busy) {
6880 save_search_patterns();
6881 if (!ins_compl_active()) {
6882 saveRedobuff(&save_redo);
6883 did_save_redobuff = true;
6884 }
6885 did_filetype = keep_filetype;
6886 }
6887
6888 /*
6889 * Note that we are applying autocmds. Some commands need to know.
6890 */
6891 autocmd_busy = TRUE;
6892 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
6893 ++nesting; /* see matching decrement below */
6894
6895 /* Remember that FileType was triggered. Used for did_filetype(). */
6896 if (event == EVENT_FILETYPE)
6897 did_filetype = TRUE;
6898
6899 tail = path_tail(fname);
6900
6901 /* Find first autocommand that matches */
6902 patcmd.curpat = first_autopat[(int)event];
6903 patcmd.nextcmd = NULL;
6904 patcmd.group = group;
6905 patcmd.fname = fname;
6906 patcmd.sfname = sfname;
6907 patcmd.tail = tail;
6908 patcmd.event = event;
6909 patcmd.arg_bufnr = autocmd_bufnr;
6910 patcmd.next = NULL;
6911 auto_next_pat(&patcmd, false);
6912
6913 /* found one, start executing the autocommands */
6914 if (patcmd.curpat != NULL) {
6915 /* add to active_apc_list */
6916 patcmd.next = active_apc_list;
6917 active_apc_list = &patcmd;
6918
6919 // set v:cmdarg (only when there is a matching pattern)
6920 save_cmdbang = (long)get_vim_var_nr(VV_CMDBANG);
6921 if (eap != NULL) {
6922 save_cmdarg = set_cmdarg(eap, NULL);
6923 set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
6924 } else {
6925 save_cmdarg = NULL; // avoid gcc warning
6926 }
6927 retval = true;
6928 // mark the last pattern, to avoid an endless loop when more patterns
6929 // are added when executing autocommands
6930 for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next) {
6931 ap->last = false;
6932 }
6933 ap->last = true;
6934 check_lnums(true); // make sure cursor and topline are valid
6935
6936 // Execute the autocmd. The `getnextac` callback handles iteration.
6937 do_cmdline(NULL, getnextac, (void *)&patcmd,
6938 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
6939
6940 reset_lnums(); // restore cursor and topline, unless they were changed
6941
6942 if (eap != NULL) {
6943 (void)set_cmdarg(NULL, save_cmdarg);
6944 set_vim_var_nr(VV_CMDBANG, save_cmdbang);
6945 }
6946 /* delete from active_apc_list */
6947 if (active_apc_list == &patcmd) /* just in case */
6948 active_apc_list = patcmd.next;
6949 }
6950
6951 --RedrawingDisabled;
6952 autocmd_busy = save_autocmd_busy;
6953 filechangeshell_busy = FALSE;
6954 autocmd_nested = save_autocmd_nested;
6955 xfree(sourcing_name);
6956 sourcing_name = save_sourcing_name;
6957 sourcing_lnum = save_sourcing_lnum;
6958 xfree(autocmd_fname);
6959 autocmd_fname = save_autocmd_fname;
6960 autocmd_bufnr = save_autocmd_bufnr;
6961 autocmd_match = save_autocmd_match;
6962 current_sctx = save_current_sctx;
6963 restore_funccal(save_funccalp);
6964 if (do_profiling == PROF_YES)
6965 prof_child_exit(&wait_time);
6966 KeyTyped = save_KeyTyped;
6967 xfree(fname);
6968 xfree(sfname);
6969 --nesting; /* see matching increment above */
6970
6971 // When stopping to execute autocommands, restore the search patterns and
6972 // the redo buffer. Free any buffers in the au_pending_free_buf list and
6973 // free any windows in the au_pending_free_win list.
6974 if (!autocmd_busy) {
6975 restore_search_patterns();
6976 if (did_save_redobuff) {
6977 restoreRedobuff(&save_redo);
6978 }
6979 did_filetype = FALSE;
6980 while (au_pending_free_buf != NULL) {
6981 buf_T *b = au_pending_free_buf->b_next;
6982 xfree(au_pending_free_buf);
6983 au_pending_free_buf = b;
6984 }
6985 while (au_pending_free_win != NULL) {
6986 win_T *w = au_pending_free_win->w_next;
6987 xfree(au_pending_free_win);
6988 au_pending_free_win = w;
6989 }
6990 }
6991
6992 /*
6993 * Some events don't set or reset the Changed flag.
6994 * Check if still in the same buffer!
6995 */
6996 if (curbuf == old_curbuf
6997 && (event == EVENT_BUFREADPOST
6998 || event == EVENT_BUFWRITEPOST
6999 || event == EVENT_FILEAPPENDPOST
7000 || event == EVENT_VIMLEAVE
7001 || event == EVENT_VIMLEAVEPRE)) {
7002 if (curbuf->b_changed != save_changed)
7003 need_maketitle = TRUE;
7004 curbuf->b_changed = save_changed;
7005 }
7006
7007 au_cleanup(); /* may really delete removed patterns/commands now */
7008
7009BYPASS_AU:
7010 /* When wiping out a buffer make sure all its buffer-local autocommands
7011 * are deleted. */
7012 if (event == EVENT_BUFWIPEOUT && buf != NULL)
7013 aubuflocal_remove(buf);
7014
7015 if (retval == OK && event == EVENT_FILETYPE) {
7016 au_did_filetype = true;
7017 }
7018
7019 return retval;
7020}
7021
7022static char_u *old_termresponse = NULL;
7023
7024/*
7025 * Block triggering autocommands until unblock_autocmd() is called.
7026 * Can be used recursively, so long as it's symmetric.
7027 */
7028void block_autocmds(void)
7029{
7030 /* Remember the value of v:termresponse. */
7031 if (autocmd_blocked == 0)
7032 old_termresponse = get_vim_var_str(VV_TERMRESPONSE);
7033 ++autocmd_blocked;
7034}
7035
7036void unblock_autocmds(void)
7037{
7038 --autocmd_blocked;
7039
7040 /* When v:termresponse was set while autocommands were blocked, trigger
7041 * the autocommands now. Esp. useful when executing a shell command
7042 * during startup (nvim -d). */
7043 if (autocmd_blocked == 0
7044 && get_vim_var_str(VV_TERMRESPONSE) != old_termresponse)
7045 apply_autocmds(EVENT_TERMRESPONSE, NULL, NULL, FALSE, curbuf);
7046}
7047
7048// Find next autocommand pattern that matches.
7049static void
7050auto_next_pat(
7051 AutoPatCmd *apc,
7052 int stop_at_last /* stop when 'last' flag is set */
7053)
7054{
7055 AutoPat *ap;
7056 AutoCmd *cp;
7057 char *s;
7058
7059 XFREE_CLEAR(sourcing_name);
7060
7061 for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next) {
7062 apc->curpat = NULL;
7063
7064 /* Only use a pattern when it has not been removed, has commands and
7065 * the group matches. For buffer-local autocommands only check the
7066 * buffer number. */
7067 if (ap->pat != NULL && ap->cmds != NULL
7068 && (apc->group == AUGROUP_ALL || apc->group == ap->group)) {
7069 /* execution-condition */
7070 if (ap->buflocal_nr == 0
7071 ? match_file_pat(NULL, &ap->reg_prog, apc->fname, apc->sfname,
7072 apc->tail, ap->allow_dirs)
7073 : ap->buflocal_nr == apc->arg_bufnr) {
7074 const char *const name = event_nr2name(apc->event);
7075 s = _("%s Autocommands for \"%s\"");
7076 const size_t sourcing_name_len = (STRLEN(s) + strlen(name) + ap->patlen
7077 + 1);
7078 sourcing_name = xmalloc(sourcing_name_len);
7079 snprintf((char *)sourcing_name, sourcing_name_len, s, name,
7080 (char *)ap->pat);
7081 if (p_verbose >= 8) {
7082 verbose_enter();
7083 smsg(_("Executing %s"), sourcing_name);
7084 verbose_leave();
7085 }
7086
7087 apc->curpat = ap;
7088 apc->nextcmd = ap->cmds;
7089 /* mark last command */
7090 for (cp = ap->cmds; cp->next != NULL; cp = cp->next)
7091 cp->last = FALSE;
7092 cp->last = TRUE;
7093 }
7094 line_breakcheck();
7095 if (apc->curpat != NULL) /* found a match */
7096 break;
7097 }
7098 if (stop_at_last && ap->last)
7099 break;
7100 }
7101}
7102
7103/*
7104 * Get next autocommand command.
7105 * Called by do_cmdline() to get the next line for ":if".
7106 * Returns allocated string, or NULL for end of autocommands.
7107 */
7108char_u *getnextac(int c, void *cookie, int indent)
7109{
7110 AutoPatCmd *acp = (AutoPatCmd *)cookie;
7111 char_u *retval;
7112 AutoCmd *ac;
7113
7114 /* Can be called again after returning the last line. */
7115 if (acp->curpat == NULL)
7116 return NULL;
7117
7118 /* repeat until we find an autocommand to execute */
7119 for (;; ) {
7120 /* skip removed commands */
7121 while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL)
7122 if (acp->nextcmd->last)
7123 acp->nextcmd = NULL;
7124 else
7125 acp->nextcmd = acp->nextcmd->next;
7126
7127 if (acp->nextcmd != NULL)
7128 break;
7129
7130 /* at end of commands, find next pattern that matches */
7131 if (acp->curpat->last)
7132 acp->curpat = NULL;
7133 else
7134 acp->curpat = acp->curpat->next;
7135 if (acp->curpat != NULL)
7136 auto_next_pat(acp, TRUE);
7137 if (acp->curpat == NULL)
7138 return NULL;
7139 }
7140
7141 ac = acp->nextcmd;
7142
7143 if (p_verbose >= 9) {
7144 verbose_enter_scroll();
7145 smsg(_("autocommand %s"), ac->cmd);
7146 msg_puts("\n"); // don't overwrite this either
7147 verbose_leave_scroll();
7148 }
7149 retval = vim_strsave(ac->cmd);
7150 // Remove one-shot ("once") autocmd in anticipation of its execution.
7151 if (ac->once) {
7152 au_del_cmd(ac);
7153 }
7154 autocmd_nested = ac->nested;
7155 current_sctx = ac->script_ctx;
7156 if (ac->last) {
7157 acp->nextcmd = NULL;
7158 } else {
7159 acp->nextcmd = ac->next;
7160 }
7161
7162 return retval;
7163}
7164
7165/// Return true if there is a matching autocommand for "fname".
7166/// To account for buffer-local autocommands, function needs to know
7167/// in which buffer the file will be opened.
7168///
7169/// @param event event that occured.
7170/// @param sfname filename the event occured in.
7171/// @param buf buffer the file is open in
7172bool has_autocmd(event_T event, char_u *sfname, buf_T *buf)
7173 FUNC_ATTR_WARN_UNUSED_RESULT
7174{
7175 AutoPat *ap;
7176 char_u *fname;
7177 char_u *tail = path_tail(sfname);
7178 bool retval = false;
7179
7180 fname = (char_u *)FullName_save((char *)sfname, false);
7181 if (fname == NULL) {
7182 return false;
7183 }
7184
7185#ifdef BACKSLASH_IN_FILENAME
7186 // Replace all backslashes with forward slashes. This makes the
7187 // autocommand patterns portable between Unix and Windows.
7188 sfname = vim_strsave(sfname);
7189 forward_slash(sfname);
7190 forward_slash(fname);
7191#endif
7192
7193 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next) {
7194 if (ap->pat != NULL && ap->cmds != NULL
7195 && (ap->buflocal_nr == 0
7196 ? match_file_pat(NULL, &ap->reg_prog, fname, sfname, tail,
7197 ap->allow_dirs)
7198 : buf != NULL && ap->buflocal_nr == buf->b_fnum)) {
7199 retval = true;
7200 break;
7201 }
7202 }
7203
7204 xfree(fname);
7205#ifdef BACKSLASH_IN_FILENAME
7206 xfree(sfname);
7207#endif
7208
7209 return retval;
7210}
7211
7212/*
7213 * Function given to ExpandGeneric() to obtain the list of autocommand group
7214 * names.
7215 */
7216char_u *get_augroup_name(expand_T *xp, int idx)
7217{
7218 if (idx == augroups.ga_len) { // add "END" add the end
7219 return (char_u *)"END";
7220 }
7221 if (idx >= augroups.ga_len) { // end of list
7222 return NULL;
7223 }
7224 if (AUGROUP_NAME(idx) == NULL || AUGROUP_NAME(idx) == get_deleted_augroup()) {
7225 // skip deleted entries
7226 return (char_u *)"";
7227 }
7228 return (char_u *)AUGROUP_NAME(idx);
7229}
7230
7231static int include_groups = FALSE;
7232
7233char_u *
7234set_context_in_autocmd (
7235 expand_T *xp,
7236 char_u *arg,
7237 int doautocmd /* TRUE for :doauto*, FALSE for :autocmd */
7238)
7239{
7240 char_u *p;
7241 int group;
7242
7243 /* check for a group name, skip it if present */
7244 include_groups = FALSE;
7245 p = arg;
7246 group = au_get_grouparg(&arg);
7247
7248 /* If there only is a group name that's what we expand. */
7249 if (*arg == NUL && group != AUGROUP_ALL && !ascii_iswhite(arg[-1])) {
7250 arg = p;
7251 group = AUGROUP_ALL;
7252 }
7253
7254 /* skip over event name */
7255 for (p = arg; *p != NUL && !ascii_iswhite(*p); ++p)
7256 if (*p == ',')
7257 arg = p + 1;
7258 if (*p == NUL) {
7259 if (group == AUGROUP_ALL)
7260 include_groups = TRUE;
7261 xp->xp_context = EXPAND_EVENTS; /* expand event name */
7262 xp->xp_pattern = arg;
7263 return NULL;
7264 }
7265
7266 /* skip over pattern */
7267 arg = skipwhite(p);
7268 while (*arg && (!ascii_iswhite(*arg) || arg[-1] == '\\'))
7269 arg++;
7270 if (*arg)
7271 return arg; /* expand (next) command */
7272
7273 if (doautocmd)
7274 xp->xp_context = EXPAND_FILES; /* expand file names */
7275 else
7276 xp->xp_context = EXPAND_NOTHING; /* pattern is not expanded */
7277 return NULL;
7278}
7279
7280/*
7281 * Function given to ExpandGeneric() to obtain the list of event names.
7282 */
7283char_u *get_event_name(expand_T *xp, int idx)
7284{
7285 if (idx < augroups.ga_len) { // First list group names, if wanted
7286 if (!include_groups || AUGROUP_NAME(idx) == NULL
7287 || AUGROUP_NAME(idx) == get_deleted_augroup()) {
7288 return (char_u *)""; // skip deleted entries
7289 }
7290 return (char_u *)AUGROUP_NAME(idx);
7291 }
7292 return (char_u *)event_names[idx - augroups.ga_len].name;
7293}
7294
7295
7296/// Check whether given autocommand is supported
7297///
7298/// @param[in] event Event to check.
7299///
7300/// @return True if it is, false otherwise.
7301bool autocmd_supported(const char *const event)
7302 FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
7303{
7304 char_u *p;
7305 return event_name2nr((const char_u *)event, &p) != NUM_EVENTS;
7306}
7307
7308/// Return true if an autocommand is defined for a group, event and
7309/// pattern: The group can be omitted to accept any group.
7310/// `event` and `pattern` can be omitted to accept any event and pattern.
7311/// Buffer-local patterns <buffer> or <buffer=N> are accepted.
7312/// Used for:
7313/// exists("#Group") or
7314/// exists("#Group#Event") or
7315/// exists("#Group#Event#pat") or
7316/// exists("#Event") or
7317/// exists("#Event#pat")
7318///
7319/// @param arg autocommand string
7320bool au_exists(const char *const arg) FUNC_ATTR_WARN_UNUSED_RESULT
7321{
7322 event_T event;
7323 AutoPat *ap;
7324 buf_T *buflocal_buf = NULL;
7325 int group;
7326 bool retval = false;
7327
7328 // Make a copy so that we can change the '#' chars to a NUL.
7329 char *const arg_save = xstrdup(arg);
7330 char *p = strchr(arg_save, '#');
7331 if (p != NULL) {
7332 *p++ = NUL;
7333 }
7334
7335 // First, look for an autocmd group name.
7336 group = au_find_group((char_u *)arg_save);
7337 char *event_name;
7338 if (group == AUGROUP_ERROR) {
7339 /* Didn't match a group name, assume the first argument is an event. */
7340 group = AUGROUP_ALL;
7341 event_name = arg_save;
7342 } else {
7343 if (p == NULL) {
7344 // "Group": group name is present and it's recognized
7345 retval = true;
7346 goto theend;
7347 }
7348
7349 // Must be "Group#Event" or "Group#Event#pat".
7350 event_name = p;
7351 p = strchr(event_name, '#');
7352 if (p != NULL) {
7353 *p++ = NUL; // "Group#Event#pat"
7354 }
7355 }
7356
7357 char *pattern = p; // "pattern" is NULL when there is no pattern.
7358
7359 // Find the index (enum) for the event name.
7360 event = event_name2nr((char_u *)event_name, (char_u **)&p);
7361
7362 /* return FALSE if the event name is not recognized */
7363 if (event == NUM_EVENTS)
7364 goto theend;
7365
7366 /* Find the first autocommand for this event.
7367 * If there isn't any, return FALSE;
7368 * If there is one and no pattern given, return TRUE; */
7369 ap = first_autopat[(int)event];
7370 if (ap == NULL)
7371 goto theend;
7372
7373 /* if pattern is "<buffer>", special handling is needed which uses curbuf */
7374 /* for pattern "<buffer=N>, fnamecmp() will work fine */
7375 if (pattern != NULL && STRICMP(pattern, "<buffer>") == 0)
7376 buflocal_buf = curbuf;
7377
7378 /* Check if there is an autocommand with the given pattern. */
7379 for (; ap != NULL; ap = ap->next)
7380 /* only use a pattern when it has not been removed and has commands. */
7381 /* For buffer-local autocommands, fnamecmp() works fine. */
7382 if (ap->pat != NULL && ap->cmds != NULL
7383 && (group == AUGROUP_ALL || ap->group == group)
7384 && (pattern == NULL
7385 || (buflocal_buf == NULL
7386 ? fnamecmp(ap->pat, (char_u *)pattern) == 0
7387 : ap->buflocal_nr == buflocal_buf->b_fnum))) {
7388 retval = true;
7389 break;
7390 }
7391
7392theend:
7393 xfree(arg_save);
7394 return retval;
7395}
7396
7397/// Tries matching a filename with a "pattern" ("prog" is NULL), or use the
7398/// precompiled regprog "prog" ("pattern" is NULL). That avoids calling
7399/// vim_regcomp() often.
7400///
7401/// Used for autocommands and 'wildignore'.
7402///
7403/// @param pattern pattern to match with
7404/// @param prog pre-compiled regprog or NULL
7405/// @param fname full path of the file name
7406/// @param sfname short file name or NULL
7407/// @param tail tail of the path
7408/// @param allow_dirs Allow matching with dir
7409///
7410/// @return true if there is a match, false otherwise
7411static bool match_file_pat(char_u *pattern, regprog_T **prog, char_u *fname,
7412 char_u *sfname, char_u *tail, int allow_dirs)
7413{
7414 regmatch_T regmatch;
7415 bool result = false;
7416
7417 regmatch.rm_ic = p_fic; /* ignore case if 'fileignorecase' is set */
7418 {
7419 if (prog != NULL)
7420 regmatch.regprog = *prog;
7421 else
7422 regmatch.regprog = vim_regcomp(pattern, RE_MAGIC);
7423 }
7424
7425 /*
7426 * Try for a match with the pattern with:
7427 * 1. the full file name, when the pattern has a '/'.
7428 * 2. the short file name, when the pattern has a '/'.
7429 * 3. the tail of the file name, when the pattern has no '/'.
7430 */
7431 if (regmatch.regprog != NULL
7432 && ((allow_dirs
7433 && (vim_regexec(&regmatch, fname, (colnr_T)0)
7434 || (sfname != NULL
7435 && vim_regexec(&regmatch, sfname, (colnr_T)0))))
7436 || (!allow_dirs && vim_regexec(&regmatch, tail, (colnr_T)0)))) {
7437 result = true;
7438 }
7439
7440 if (prog != NULL) {
7441 *prog = regmatch.regprog;
7442 } else {
7443 vim_regfree(regmatch.regprog);
7444 }
7445 return result;
7446}
7447
7448/// Check if a file matches with a pattern in "list".
7449/// "list" is a comma-separated list of patterns, like 'wildignore'.
7450/// "sfname" is the short file name or NULL, "ffname" the long file name.
7451///
7452/// @param list list of patterns to match
7453/// @param sfname short file name
7454/// @param ffname full file name
7455///
7456/// @return true if there was a match
7457bool match_file_list(char_u *list, char_u *sfname, char_u *ffname)
7458 FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1, 3)
7459{
7460 char_u buf[100];
7461 char_u *tail;
7462 char_u *regpat;
7463 char allow_dirs;
7464 bool match;
7465 char_u *p;
7466
7467 tail = path_tail(sfname);
7468
7469 // try all patterns in 'wildignore'
7470 p = list;
7471 while (*p) {
7472 copy_option_part(&p, buf, ARRAY_SIZE(buf), ",");
7473 regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, false);
7474 if (regpat == NULL) {
7475 break;
7476 }
7477 match = match_file_pat(regpat, NULL, ffname, sfname, tail, (int)allow_dirs);
7478 xfree(regpat);
7479 if (match) {
7480 return true;
7481 }
7482 }
7483 return false;
7484}
7485
7486/// Convert the given pattern "pat" which has shell style wildcards in it, into
7487/// a regular expression, and return the result in allocated memory. If there
7488/// is a directory path separator to be matched, then TRUE is put in
7489/// allow_dirs, otherwise FALSE is put there -- webb.
7490/// Handle backslashes before special characters, like "\*" and "\ ".
7491///
7492/// Returns NULL on failure.
7493char_u * file_pat_to_reg_pat(
7494 const char_u *pat,
7495 const char_u *pat_end, // first char after pattern or NULL
7496 char *allow_dirs, // Result passed back out in here
7497 int no_bslash // Don't use a backward slash as pathsep
7498)
7499 FUNC_ATTR_NONNULL_ARG(1)
7500{
7501 const char_u *endp;
7502 char_u *reg_pat;
7503 const char_u *p;
7504 int nested = 0;
7505 int add_dollar = TRUE;
7506
7507 if (allow_dirs != NULL)
7508 *allow_dirs = FALSE;
7509 if (pat_end == NULL)
7510 pat_end = pat + STRLEN(pat);
7511
7512 if (pat_end == pat) {
7513 return (char_u *)xstrdup("^$");
7514 }
7515
7516 size_t size = 2; // '^' at start, '$' at end.
7517
7518 for (p = pat; p < pat_end; p++) {
7519 switch (*p) {
7520 case '*':
7521 case '.':
7522 case ',':
7523 case '{':
7524 case '}':
7525 case '~':
7526 size += 2; /* extra backslash */
7527 break;
7528#ifdef BACKSLASH_IN_FILENAME
7529 case '\\':
7530 case '/':
7531 size += 4; /* could become "[\/]" */
7532 break;
7533#endif
7534 default:
7535 size++;
7536 break;
7537 }
7538 }
7539 reg_pat = xmalloc(size + 1);
7540
7541 size_t i = 0;
7542
7543 if (pat[0] == '*')
7544 while (pat[0] == '*' && pat < pat_end - 1)
7545 pat++;
7546 else
7547 reg_pat[i++] = '^';
7548 endp = pat_end - 1;
7549 if (endp >= pat && *endp == '*') {
7550 while (endp - pat > 0 && *endp == '*') {
7551 endp--;
7552 }
7553 add_dollar = false;
7554 }
7555 for (p = pat; *p && nested >= 0 && p <= endp; p++) {
7556 switch (*p) {
7557 case '*':
7558 reg_pat[i++] = '.';
7559 reg_pat[i++] = '*';
7560 while (p[1] == '*') /* "**" matches like "*" */
7561 ++p;
7562 break;
7563 case '.':
7564 case '~':
7565 reg_pat[i++] = '\\';
7566 reg_pat[i++] = *p;
7567 break;
7568 case '?':
7569 reg_pat[i++] = '.';
7570 break;
7571 case '\\':
7572 if (p[1] == NUL)
7573 break;
7574#ifdef BACKSLASH_IN_FILENAME
7575 if (!no_bslash) {
7576 /* translate:
7577 * "\x" to "\\x" e.g., "dir\file"
7578 * "\*" to "\\.*" e.g., "dir\*.c"
7579 * "\?" to "\\." e.g., "dir\??.c"
7580 * "\+" to "\+" e.g., "fileX\+.c"
7581 */
7582 if ((vim_isfilec(p[1]) || p[1] == '*' || p[1] == '?')
7583 && p[1] != '+') {
7584 reg_pat[i++] = '[';
7585 reg_pat[i++] = '\\';
7586 reg_pat[i++] = '/';
7587 reg_pat[i++] = ']';
7588 if (allow_dirs != NULL)
7589 *allow_dirs = TRUE;
7590 break;
7591 }
7592 }
7593#endif
7594 /* Undo escaping from ExpandEscape():
7595 * foo\?bar -> foo?bar
7596 * foo\%bar -> foo%bar
7597 * foo\,bar -> foo,bar
7598 * foo\ bar -> foo bar
7599 * Don't unescape \, * and others that are also special in a
7600 * regexp.
7601 * An escaped { must be unescaped since we use magic not
7602 * verymagic. Use "\\\{n,m\}"" to get "\{n,m}".
7603 */
7604 if (*++p == '?'
7605#ifdef BACKSLASH_IN_FILENAME
7606 && no_bslash
7607#endif
7608 ) {
7609 reg_pat[i++] = '?';
7610 } else if (*p == ',' || *p == '%' || *p == '#'
7611 || ascii_isspace(*p) || *p == '{' || *p == '}') {
7612 reg_pat[i++] = *p;
7613 } else if (*p == '\\' && p[1] == '\\' && p[2] == '{') {
7614 reg_pat[i++] = '\\';
7615 reg_pat[i++] = '{';
7616 p += 2;
7617 } else {
7618 if (allow_dirs != NULL && vim_ispathsep(*p)
7619#ifdef BACKSLASH_IN_FILENAME
7620 && (!no_bslash || *p != '\\')
7621#endif
7622 )
7623 *allow_dirs = TRUE;
7624 reg_pat[i++] = '\\';
7625 reg_pat[i++] = *p;
7626 }
7627 break;
7628#ifdef BACKSLASH_IN_FILENAME
7629 case '/':
7630 reg_pat[i++] = '[';
7631 reg_pat[i++] = '\\';
7632 reg_pat[i++] = '/';
7633 reg_pat[i++] = ']';
7634 if (allow_dirs != NULL)
7635 *allow_dirs = TRUE;
7636 break;
7637#endif
7638 case '{':
7639 reg_pat[i++] = '\\';
7640 reg_pat[i++] = '(';
7641 nested++;
7642 break;
7643 case '}':
7644 reg_pat[i++] = '\\';
7645 reg_pat[i++] = ')';
7646 --nested;
7647 break;
7648 case ',':
7649 if (nested) {
7650 reg_pat[i++] = '\\';
7651 reg_pat[i++] = '|';
7652 } else
7653 reg_pat[i++] = ',';
7654 break;
7655 default:
7656 if (allow_dirs != NULL && vim_ispathsep(*p)) {
7657 *allow_dirs = true;
7658 }
7659 reg_pat[i++] = *p;
7660 break;
7661 }
7662 }
7663 if (add_dollar)
7664 reg_pat[i++] = '$';
7665 reg_pat[i] = NUL;
7666 if (nested != 0) {
7667 if (nested < 0) {
7668 EMSG(_("E219: Missing {."));
7669 } else {
7670 EMSG(_("E220: Missing }."));
7671 }
7672 XFREE_CLEAR(reg_pat);
7673 }
7674 return reg_pat;
7675}
7676
7677#if defined(EINTR)
7678/*
7679 * Version of read() that retries when interrupted by EINTR (possibly
7680 * by a SIGWINCH).
7681 */
7682long read_eintr(int fd, void *buf, size_t bufsize)
7683{
7684 long ret;
7685
7686 for (;; ) {
7687 ret = read(fd, buf, bufsize);
7688 if (ret >= 0 || errno != EINTR)
7689 break;
7690 }
7691 return ret;
7692}
7693
7694/*
7695 * Version of write() that retries when interrupted by EINTR (possibly
7696 * by a SIGWINCH).
7697 */
7698long write_eintr(int fd, void *buf, size_t bufsize)
7699{
7700 long ret = 0;
7701 long wlen;
7702
7703 /* Repeat the write() so long it didn't fail, other than being interrupted
7704 * by a signal. */
7705 while (ret < (long)bufsize) {
7706 wlen = write(fd, (char *)buf + ret, bufsize - ret);
7707 if (wlen < 0) {
7708 if (errno != EINTR)
7709 break;
7710 } else
7711 ret += wlen;
7712 }
7713 return ret;
7714}
7715#endif
7716