Mercurial > vim
comparison src/bufwrite.c @ 18199:e2be5a6485f5 v8.1.2094
patch 8.1.2094: the fileio.c file is too big
Commit: https://github.com/vim/vim/commit/473952e85286eb9c6098801f1819981ba61ad153
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Sep 28 16:30:04 2019 +0200
patch 8.1.2094: the fileio.c file is too big
Problem: The fileio.c file is too big.
Solution: Move buf_write() to bufwrite.c. (Yegappan Lakshmanan,
closes #4990)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 28 Sep 2019 16:45:04 +0200 |
parents | |
children | 788d76db02ac |
comparison
equal
deleted
inserted
replaced
18198:3ebea66ebaff | 18199:e2be5a6485f5 |
---|---|
1 /* vi:set ts=8 sts=4 sw=4 noet: | |
2 * | |
3 * VIM - Vi IMproved by Bram Moolenaar | |
4 * | |
5 * Do ":help uganda" in Vim to read copying and usage conditions. | |
6 * Do ":help credits" in Vim to see a list of people who contributed. | |
7 * See README.txt for an overview of the Vim source code. | |
8 */ | |
9 | |
10 /* | |
11 * bufwrite.c: functions for writing a buffer | |
12 */ | |
13 | |
14 #include "vim.h" | |
15 | |
16 #if defined(HAVE_UTIME) && defined(HAVE_UTIME_H) | |
17 # include <utime.h> // for struct utimbuf | |
18 #endif | |
19 | |
20 #define SMALLBUFSIZE 256 // size of emergency write buffer | |
21 | |
22 /* | |
23 * Structure to pass arguments from buf_write() to buf_write_bytes(). | |
24 */ | |
25 struct bw_info | |
26 { | |
27 int bw_fd; // file descriptor | |
28 char_u *bw_buf; // buffer with data to be written | |
29 int bw_len; // length of data | |
30 int bw_flags; // FIO_ flags | |
31 #ifdef FEAT_CRYPT | |
32 buf_T *bw_buffer; // buffer being written | |
33 #endif | |
34 char_u bw_rest[CONV_RESTLEN]; // not converted bytes | |
35 int bw_restlen; // nr of bytes in bw_rest[] | |
36 int bw_first; // first write call | |
37 char_u *bw_conv_buf; // buffer for writing converted chars | |
38 size_t bw_conv_buflen; // size of bw_conv_buf | |
39 int bw_conv_error; // set for conversion error | |
40 linenr_T bw_conv_error_lnum; // first line with error or zero | |
41 linenr_T bw_start_lnum; // line number at start of buffer | |
42 #ifdef USE_ICONV | |
43 iconv_t bw_iconv_fd; // descriptor for iconv() or -1 | |
44 #endif | |
45 }; | |
46 | |
47 /* | |
48 * Convert a Unicode character to bytes. | |
49 * Return TRUE for an error, FALSE when it's OK. | |
50 */ | |
51 static int | |
52 ucs2bytes( | |
53 unsigned c, // in: character | |
54 char_u **pp, // in/out: pointer to result | |
55 int flags) // FIO_ flags | |
56 { | |
57 char_u *p = *pp; | |
58 int error = FALSE; | |
59 int cc; | |
60 | |
61 | |
62 if (flags & FIO_UCS4) | |
63 { | |
64 if (flags & FIO_ENDIAN_L) | |
65 { | |
66 *p++ = c; | |
67 *p++ = (c >> 8); | |
68 *p++ = (c >> 16); | |
69 *p++ = (c >> 24); | |
70 } | |
71 else | |
72 { | |
73 *p++ = (c >> 24); | |
74 *p++ = (c >> 16); | |
75 *p++ = (c >> 8); | |
76 *p++ = c; | |
77 } | |
78 } | |
79 else if (flags & (FIO_UCS2 | FIO_UTF16)) | |
80 { | |
81 if (c >= 0x10000) | |
82 { | |
83 if (flags & FIO_UTF16) | |
84 { | |
85 // Make two words, ten bits of the character in each. First | |
86 // word is 0xd800 - 0xdbff, second one 0xdc00 - 0xdfff | |
87 c -= 0x10000; | |
88 if (c >= 0x100000) | |
89 error = TRUE; | |
90 cc = ((c >> 10) & 0x3ff) + 0xd800; | |
91 if (flags & FIO_ENDIAN_L) | |
92 { | |
93 *p++ = cc; | |
94 *p++ = ((unsigned)cc >> 8); | |
95 } | |
96 else | |
97 { | |
98 *p++ = ((unsigned)cc >> 8); | |
99 *p++ = cc; | |
100 } | |
101 c = (c & 0x3ff) + 0xdc00; | |
102 } | |
103 else | |
104 error = TRUE; | |
105 } | |
106 if (flags & FIO_ENDIAN_L) | |
107 { | |
108 *p++ = c; | |
109 *p++ = (c >> 8); | |
110 } | |
111 else | |
112 { | |
113 *p++ = (c >> 8); | |
114 *p++ = c; | |
115 } | |
116 } | |
117 else // Latin1 | |
118 { | |
119 if (c >= 0x100) | |
120 { | |
121 error = TRUE; | |
122 *p++ = 0xBF; | |
123 } | |
124 else | |
125 *p++ = c; | |
126 } | |
127 | |
128 *pp = p; | |
129 return error; | |
130 } | |
131 | |
132 /* | |
133 * Call write() to write a number of bytes to the file. | |
134 * Handles encryption and 'encoding' conversion. | |
135 * | |
136 * Return FAIL for failure, OK otherwise. | |
137 */ | |
138 static int | |
139 buf_write_bytes(struct bw_info *ip) | |
140 { | |
141 int wlen; | |
142 char_u *buf = ip->bw_buf; // data to write | |
143 int len = ip->bw_len; // length of data | |
144 int flags = ip->bw_flags; // extra flags | |
145 | |
146 // Skip conversion when writing the crypt magic number or the BOM. | |
147 if (!(flags & FIO_NOCONVERT)) | |
148 { | |
149 char_u *p; | |
150 unsigned c; | |
151 int n; | |
152 | |
153 if (flags & FIO_UTF8) | |
154 { | |
155 // Convert latin1 in the buffer to UTF-8 in the file. | |
156 p = ip->bw_conv_buf; // translate to buffer | |
157 for (wlen = 0; wlen < len; ++wlen) | |
158 p += utf_char2bytes(buf[wlen], p); | |
159 buf = ip->bw_conv_buf; | |
160 len = (int)(p - ip->bw_conv_buf); | |
161 } | |
162 else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1)) | |
163 { | |
164 // Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or | |
165 // Latin1 chars in the file. | |
166 if (flags & FIO_LATIN1) | |
167 p = buf; // translate in-place (can only get shorter) | |
168 else | |
169 p = ip->bw_conv_buf; // translate to buffer | |
170 for (wlen = 0; wlen < len; wlen += n) | |
171 { | |
172 if (wlen == 0 && ip->bw_restlen != 0) | |
173 { | |
174 int l; | |
175 | |
176 // Use remainder of previous call. Append the start of | |
177 // buf[] to get a full sequence. Might still be too | |
178 // short! | |
179 l = CONV_RESTLEN - ip->bw_restlen; | |
180 if (l > len) | |
181 l = len; | |
182 mch_memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l); | |
183 n = utf_ptr2len_len(ip->bw_rest, ip->bw_restlen + l); | |
184 if (n > ip->bw_restlen + len) | |
185 { | |
186 // We have an incomplete byte sequence at the end to | |
187 // be written. We can't convert it without the | |
188 // remaining bytes. Keep them for the next call. | |
189 if (ip->bw_restlen + len > CONV_RESTLEN) | |
190 return FAIL; | |
191 ip->bw_restlen += len; | |
192 break; | |
193 } | |
194 if (n > 1) | |
195 c = utf_ptr2char(ip->bw_rest); | |
196 else | |
197 c = ip->bw_rest[0]; | |
198 if (n >= ip->bw_restlen) | |
199 { | |
200 n -= ip->bw_restlen; | |
201 ip->bw_restlen = 0; | |
202 } | |
203 else | |
204 { | |
205 ip->bw_restlen -= n; | |
206 mch_memmove(ip->bw_rest, ip->bw_rest + n, | |
207 (size_t)ip->bw_restlen); | |
208 n = 0; | |
209 } | |
210 } | |
211 else | |
212 { | |
213 n = utf_ptr2len_len(buf + wlen, len - wlen); | |
214 if (n > len - wlen) | |
215 { | |
216 // We have an incomplete byte sequence at the end to | |
217 // be written. We can't convert it without the | |
218 // remaining bytes. Keep them for the next call. | |
219 if (len - wlen > CONV_RESTLEN) | |
220 return FAIL; | |
221 ip->bw_restlen = len - wlen; | |
222 mch_memmove(ip->bw_rest, buf + wlen, | |
223 (size_t)ip->bw_restlen); | |
224 break; | |
225 } | |
226 if (n > 1) | |
227 c = utf_ptr2char(buf + wlen); | |
228 else | |
229 c = buf[wlen]; | |
230 } | |
231 | |
232 if (ucs2bytes(c, &p, flags) && !ip->bw_conv_error) | |
233 { | |
234 ip->bw_conv_error = TRUE; | |
235 ip->bw_conv_error_lnum = ip->bw_start_lnum; | |
236 } | |
237 if (c == NL) | |
238 ++ip->bw_start_lnum; | |
239 } | |
240 if (flags & FIO_LATIN1) | |
241 len = (int)(p - buf); | |
242 else | |
243 { | |
244 buf = ip->bw_conv_buf; | |
245 len = (int)(p - ip->bw_conv_buf); | |
246 } | |
247 } | |
248 | |
249 #ifdef MSWIN | |
250 else if (flags & FIO_CODEPAGE) | |
251 { | |
252 // Convert UTF-8 or codepage to UCS-2 and then to MS-Windows | |
253 // codepage. | |
254 char_u *from; | |
255 size_t fromlen; | |
256 char_u *to; | |
257 int u8c; | |
258 BOOL bad = FALSE; | |
259 int needed; | |
260 | |
261 if (ip->bw_restlen > 0) | |
262 { | |
263 // Need to concatenate the remainder of the previous call and | |
264 // the bytes of the current call. Use the end of the | |
265 // conversion buffer for this. | |
266 fromlen = len + ip->bw_restlen; | |
267 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen; | |
268 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen); | |
269 mch_memmove(from + ip->bw_restlen, buf, (size_t)len); | |
270 } | |
271 else | |
272 { | |
273 from = buf; | |
274 fromlen = len; | |
275 } | |
276 | |
277 to = ip->bw_conv_buf; | |
278 if (enc_utf8) | |
279 { | |
280 // Convert from UTF-8 to UCS-2, to the start of the buffer. | |
281 // The buffer has been allocated to be big enough. | |
282 while (fromlen > 0) | |
283 { | |
284 n = (int)utf_ptr2len_len(from, (int)fromlen); | |
285 if (n > (int)fromlen) // incomplete byte sequence | |
286 break; | |
287 u8c = utf_ptr2char(from); | |
288 *to++ = (u8c & 0xff); | |
289 *to++ = (u8c >> 8); | |
290 fromlen -= n; | |
291 from += n; | |
292 } | |
293 | |
294 // Copy remainder to ip->bw_rest[] to be used for the next | |
295 // call. | |
296 if (fromlen > CONV_RESTLEN) | |
297 { | |
298 // weird overlong sequence | |
299 ip->bw_conv_error = TRUE; | |
300 return FAIL; | |
301 } | |
302 mch_memmove(ip->bw_rest, from, fromlen); | |
303 ip->bw_restlen = (int)fromlen; | |
304 } | |
305 else | |
306 { | |
307 // Convert from enc_codepage to UCS-2, to the start of the | |
308 // buffer. The buffer has been allocated to be big enough. | |
309 ip->bw_restlen = 0; | |
310 needed = MultiByteToWideChar(enc_codepage, | |
311 MB_ERR_INVALID_CHARS, (LPCSTR)from, (int)fromlen, | |
312 NULL, 0); | |
313 if (needed == 0) | |
314 { | |
315 // When conversion fails there may be a trailing byte. | |
316 needed = MultiByteToWideChar(enc_codepage, | |
317 MB_ERR_INVALID_CHARS, (LPCSTR)from, (int)fromlen - 1, | |
318 NULL, 0); | |
319 if (needed == 0) | |
320 { | |
321 // Conversion doesn't work. | |
322 ip->bw_conv_error = TRUE; | |
323 return FAIL; | |
324 } | |
325 // Save the trailing byte for the next call. | |
326 ip->bw_rest[0] = from[fromlen - 1]; | |
327 ip->bw_restlen = 1; | |
328 } | |
329 needed = MultiByteToWideChar(enc_codepage, MB_ERR_INVALID_CHARS, | |
330 (LPCSTR)from, (int)(fromlen - ip->bw_restlen), | |
331 (LPWSTR)to, needed); | |
332 if (needed == 0) | |
333 { | |
334 // Safety check: Conversion doesn't work. | |
335 ip->bw_conv_error = TRUE; | |
336 return FAIL; | |
337 } | |
338 to += needed * 2; | |
339 } | |
340 | |
341 fromlen = to - ip->bw_conv_buf; | |
342 buf = to; | |
343 # ifdef CP_UTF8 // VC 4.1 doesn't define CP_UTF8 | |
344 if (FIO_GET_CP(flags) == CP_UTF8) | |
345 { | |
346 // Convert from UCS-2 to UTF-8, using the remainder of the | |
347 // conversion buffer. Fails when out of space. | |
348 for (from = ip->bw_conv_buf; fromlen > 1; fromlen -= 2) | |
349 { | |
350 u8c = *from++; | |
351 u8c += (*from++ << 8); | |
352 to += utf_char2bytes(u8c, to); | |
353 if (to + 6 >= ip->bw_conv_buf + ip->bw_conv_buflen) | |
354 { | |
355 ip->bw_conv_error = TRUE; | |
356 return FAIL; | |
357 } | |
358 } | |
359 len = (int)(to - buf); | |
360 } | |
361 else | |
362 # endif | |
363 { | |
364 // Convert from UCS-2 to the codepage, using the remainder of | |
365 // the conversion buffer. If the conversion uses the default | |
366 // character "0", the data doesn't fit in this encoding, so | |
367 // fail. | |
368 len = WideCharToMultiByte(FIO_GET_CP(flags), 0, | |
369 (LPCWSTR)ip->bw_conv_buf, (int)fromlen / sizeof(WCHAR), | |
370 (LPSTR)to, (int)(ip->bw_conv_buflen - fromlen), 0, | |
371 &bad); | |
372 if (bad) | |
373 { | |
374 ip->bw_conv_error = TRUE; | |
375 return FAIL; | |
376 } | |
377 } | |
378 } | |
379 #endif | |
380 | |
381 #ifdef MACOS_CONVERT | |
382 else if (flags & FIO_MACROMAN) | |
383 { | |
384 // Convert UTF-8 or latin1 to Apple MacRoman. | |
385 char_u *from; | |
386 size_t fromlen; | |
387 | |
388 if (ip->bw_restlen > 0) | |
389 { | |
390 // Need to concatenate the remainder of the previous call and | |
391 // the bytes of the current call. Use the end of the | |
392 // conversion buffer for this. | |
393 fromlen = len + ip->bw_restlen; | |
394 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen; | |
395 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen); | |
396 mch_memmove(from + ip->bw_restlen, buf, (size_t)len); | |
397 } | |
398 else | |
399 { | |
400 from = buf; | |
401 fromlen = len; | |
402 } | |
403 | |
404 if (enc2macroman(from, fromlen, | |
405 ip->bw_conv_buf, &len, ip->bw_conv_buflen, | |
406 ip->bw_rest, &ip->bw_restlen) == FAIL) | |
407 { | |
408 ip->bw_conv_error = TRUE; | |
409 return FAIL; | |
410 } | |
411 buf = ip->bw_conv_buf; | |
412 } | |
413 #endif | |
414 | |
415 #ifdef USE_ICONV | |
416 if (ip->bw_iconv_fd != (iconv_t)-1) | |
417 { | |
418 const char *from; | |
419 size_t fromlen; | |
420 char *to; | |
421 size_t tolen; | |
422 | |
423 // Convert with iconv(). | |
424 if (ip->bw_restlen > 0) | |
425 { | |
426 char *fp; | |
427 | |
428 // Need to concatenate the remainder of the previous call and | |
429 // the bytes of the current call. Use the end of the | |
430 // conversion buffer for this. | |
431 fromlen = len + ip->bw_restlen; | |
432 fp = (char *)ip->bw_conv_buf + ip->bw_conv_buflen - fromlen; | |
433 mch_memmove(fp, ip->bw_rest, (size_t)ip->bw_restlen); | |
434 mch_memmove(fp + ip->bw_restlen, buf, (size_t)len); | |
435 from = fp; | |
436 tolen = ip->bw_conv_buflen - fromlen; | |
437 } | |
438 else | |
439 { | |
440 from = (const char *)buf; | |
441 fromlen = len; | |
442 tolen = ip->bw_conv_buflen; | |
443 } | |
444 to = (char *)ip->bw_conv_buf; | |
445 | |
446 if (ip->bw_first) | |
447 { | |
448 size_t save_len = tolen; | |
449 | |
450 // output the initial shift state sequence | |
451 (void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen); | |
452 | |
453 // There is a bug in iconv() on Linux (which appears to be | |
454 // wide-spread) which sets "to" to NULL and messes up "tolen". | |
455 if (to == NULL) | |
456 { | |
457 to = (char *)ip->bw_conv_buf; | |
458 tolen = save_len; | |
459 } | |
460 ip->bw_first = FALSE; | |
461 } | |
462 | |
463 // If iconv() has an error or there is not enough room, fail. | |
464 if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen) | |
465 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL) | |
466 || fromlen > CONV_RESTLEN) | |
467 { | |
468 ip->bw_conv_error = TRUE; | |
469 return FAIL; | |
470 } | |
471 | |
472 // copy remainder to ip->bw_rest[] to be used for the next call. | |
473 if (fromlen > 0) | |
474 mch_memmove(ip->bw_rest, (void *)from, fromlen); | |
475 ip->bw_restlen = (int)fromlen; | |
476 | |
477 buf = ip->bw_conv_buf; | |
478 len = (int)((char_u *)to - ip->bw_conv_buf); | |
479 } | |
480 #endif | |
481 } | |
482 | |
483 if (ip->bw_fd < 0) | |
484 // Only checking conversion, which is OK if we get here. | |
485 return OK; | |
486 | |
487 #ifdef FEAT_CRYPT | |
488 if (flags & FIO_ENCRYPTED) | |
489 { | |
490 // Encrypt the data. Do it in-place if possible, otherwise use an | |
491 // allocated buffer. | |
492 # ifdef CRYPT_NOT_INPLACE | |
493 if (crypt_works_inplace(ip->bw_buffer->b_cryptstate)) | |
494 { | |
495 # endif | |
496 crypt_encode_inplace(ip->bw_buffer->b_cryptstate, buf, len); | |
497 # ifdef CRYPT_NOT_INPLACE | |
498 } | |
499 else | |
500 { | |
501 char_u *outbuf; | |
502 | |
503 len = crypt_encode_alloc(curbuf->b_cryptstate, buf, len, &outbuf); | |
504 if (len == 0) | |
505 return OK; // Crypt layer is buffering, will flush later. | |
506 wlen = write_eintr(ip->bw_fd, outbuf, len); | |
507 vim_free(outbuf); | |
508 return (wlen < len) ? FAIL : OK; | |
509 } | |
510 # endif | |
511 } | |
512 #endif | |
513 | |
514 wlen = write_eintr(ip->bw_fd, buf, len); | |
515 return (wlen < len) ? FAIL : OK; | |
516 } | |
517 | |
518 /* | |
519 * Check modification time of file, before writing to it. | |
520 * The size isn't checked, because using a tool like "gzip" takes care of | |
521 * using the same timestamp but can't set the size. | |
522 */ | |
523 static int | |
524 check_mtime(buf_T *buf, stat_T *st) | |
525 { | |
526 if (buf->b_mtime_read != 0 | |
527 && time_differs((long)st->st_mtime, buf->b_mtime_read)) | |
528 { | |
529 msg_scroll = TRUE; // don't overwrite messages here | |
530 msg_silent = 0; // must give this prompt | |
531 // don't use emsg() here, don't want to flush the buffers | |
532 msg_attr(_("WARNING: The file has been changed since reading it!!!"), | |
533 HL_ATTR(HLF_E)); | |
534 if (ask_yesno((char_u *)_("Do you really want to write to it"), | |
535 TRUE) == 'n') | |
536 return FAIL; | |
537 msg_scroll = FALSE; // always overwrite the file message now | |
538 } | |
539 return OK; | |
540 } | |
541 | |
542 /* | |
543 * Generate a BOM in "buf[4]" for encoding "name". | |
544 * Return the length of the BOM (zero when no BOM). | |
545 */ | |
546 static int | |
547 make_bom(char_u *buf, char_u *name) | |
548 { | |
549 int flags; | |
550 char_u *p; | |
551 | |
552 flags = get_fio_flags(name); | |
553 | |
554 // Can't put a BOM in a non-Unicode file. | |
555 if (flags == FIO_LATIN1 || flags == 0) | |
556 return 0; | |
557 | |
558 if (flags == FIO_UTF8) // UTF-8 | |
559 { | |
560 buf[0] = 0xef; | |
561 buf[1] = 0xbb; | |
562 buf[2] = 0xbf; | |
563 return 3; | |
564 } | |
565 p = buf; | |
566 (void)ucs2bytes(0xfeff, &p, flags); | |
567 return (int)(p - buf); | |
568 } | |
569 | |
570 #ifdef UNIX | |
571 static void | |
572 set_file_time( | |
573 char_u *fname, | |
574 time_t atime, // access time | |
575 time_t mtime) // modification time | |
576 { | |
577 # if defined(HAVE_UTIME) && defined(HAVE_UTIME_H) | |
578 struct utimbuf buf; | |
579 | |
580 buf.actime = atime; | |
581 buf.modtime = mtime; | |
582 (void)utime((char *)fname, &buf); | |
583 # else | |
584 # if defined(HAVE_UTIMES) | |
585 struct timeval tvp[2]; | |
586 | |
587 tvp[0].tv_sec = atime; | |
588 tvp[0].tv_usec = 0; | |
589 tvp[1].tv_sec = mtime; | |
590 tvp[1].tv_usec = 0; | |
591 # ifdef NeXT | |
592 (void)utimes((char *)fname, tvp); | |
593 # else | |
594 (void)utimes((char *)fname, (const struct timeval *)&tvp); | |
595 # endif | |
596 # endif | |
597 # endif | |
598 } | |
599 #endif // UNIX | |
600 | |
601 /* | |
602 * buf_write() - write to file "fname" lines "start" through "end" | |
603 * | |
604 * We do our own buffering here because fwrite() is so slow. | |
605 * | |
606 * If "forceit" is true, we don't care for errors when attempting backups. | |
607 * In case of an error everything possible is done to restore the original | |
608 * file. But when "forceit" is TRUE, we risk losing it. | |
609 * | |
610 * When "reset_changed" is TRUE and "append" == FALSE and "start" == 1 and | |
611 * "end" == curbuf->b_ml.ml_line_count, reset curbuf->b_changed. | |
612 * | |
613 * This function must NOT use NameBuff (because it's called by autowrite()). | |
614 * | |
615 * return FAIL for failure, OK otherwise | |
616 */ | |
617 int | |
618 buf_write( | |
619 buf_T *buf, | |
620 char_u *fname, | |
621 char_u *sfname, | |
622 linenr_T start, | |
623 linenr_T end, | |
624 exarg_T *eap, // for forced 'ff' and 'fenc', can be | |
625 // NULL! | |
626 int append, // append to the file | |
627 int forceit, | |
628 int reset_changed, | |
629 int filtering) | |
630 { | |
631 int fd; | |
632 char_u *backup = NULL; | |
633 int backup_copy = FALSE; // copy the original file? | |
634 int dobackup; | |
635 char_u *ffname; | |
636 char_u *wfname = NULL; // name of file to write to | |
637 char_u *s; | |
638 char_u *ptr; | |
639 char_u c; | |
640 int len; | |
641 linenr_T lnum; | |
642 long nchars; | |
643 char_u *errmsg = NULL; | |
644 int errmsg_allocated = FALSE; | |
645 char_u *errnum = NULL; | |
646 char_u *buffer; | |
647 char_u smallbuf[SMALLBUFSIZE]; | |
648 char_u *backup_ext; | |
649 int bufsize; | |
650 long perm; // file permissions | |
651 int retval = OK; | |
652 int newfile = FALSE; // TRUE if file doesn't exist yet | |
653 int msg_save = msg_scroll; | |
654 int overwriting; // TRUE if writing over original | |
655 int no_eol = FALSE; // no end-of-line written | |
656 int device = FALSE; // writing to a device | |
657 stat_T st_old; | |
658 int prev_got_int = got_int; | |
659 int checking_conversion; | |
660 int file_readonly = FALSE; // overwritten file is read-only | |
661 static char *err_readonly = "is read-only (cannot override: \"W\" in 'cpoptions')"; | |
662 #if defined(UNIX) // XXX fix me sometime? | |
663 int made_writable = FALSE; // 'w' bit has been set | |
664 #endif | |
665 // writing everything | |
666 int whole = (start == 1 && end == buf->b_ml.ml_line_count); | |
667 linenr_T old_line_count = buf->b_ml.ml_line_count; | |
668 int attr; | |
669 int fileformat; | |
670 int write_bin; | |
671 struct bw_info write_info; // info for buf_write_bytes() | |
672 int converted = FALSE; | |
673 int notconverted = FALSE; | |
674 char_u *fenc; // effective 'fileencoding' | |
675 char_u *fenc_tofree = NULL; // allocated "fenc" | |
676 int wb_flags = 0; | |
677 #ifdef HAVE_ACL | |
678 vim_acl_T acl = NULL; // ACL copied from original file to | |
679 // backup or new file | |
680 #endif | |
681 #ifdef FEAT_PERSISTENT_UNDO | |
682 int write_undo_file = FALSE; | |
683 context_sha256_T sha_ctx; | |
684 #endif | |
685 unsigned int bkc = get_bkc_value(buf); | |
686 | |
687 if (fname == NULL || *fname == NUL) // safety check | |
688 return FAIL; | |
689 if (buf->b_ml.ml_mfp == NULL) | |
690 { | |
691 // This can happen during startup when there is a stray "w" in the | |
692 // vimrc file. | |
693 emsg(_(e_emptybuf)); | |
694 return FAIL; | |
695 } | |
696 | |
697 // Disallow writing from .exrc and .vimrc in current directory for | |
698 // security reasons. | |
699 if (check_secure()) | |
700 return FAIL; | |
701 | |
702 // Avoid a crash for a long name. | |
703 if (STRLEN(fname) >= MAXPATHL) | |
704 { | |
705 emsg(_(e_longname)); | |
706 return FAIL; | |
707 } | |
708 | |
709 // must init bw_conv_buf and bw_iconv_fd before jumping to "fail" | |
710 write_info.bw_conv_buf = NULL; | |
711 write_info.bw_conv_error = FALSE; | |
712 write_info.bw_conv_error_lnum = 0; | |
713 write_info.bw_restlen = 0; | |
714 #ifdef USE_ICONV | |
715 write_info.bw_iconv_fd = (iconv_t)-1; | |
716 #endif | |
717 #ifdef FEAT_CRYPT | |
718 write_info.bw_buffer = buf; | |
719 #endif | |
720 | |
721 // After writing a file changedtick changes but we don't want to display | |
722 // the line. | |
723 ex_no_reprint = TRUE; | |
724 | |
725 // If there is no file name yet, use the one for the written file. | |
726 // BF_NOTEDITED is set to reflect this (in case the write fails). | |
727 // Don't do this when the write is for a filter command. | |
728 // Don't do this when appending. | |
729 // Only do this when 'cpoptions' contains the 'F' flag. | |
730 if (buf->b_ffname == NULL | |
731 && reset_changed | |
732 && whole | |
733 && buf == curbuf | |
734 #ifdef FEAT_QUICKFIX | |
735 && !bt_nofilename(buf) | |
736 #endif | |
737 && !filtering | |
738 && (!append || vim_strchr(p_cpo, CPO_FNAMEAPP) != NULL) | |
739 && vim_strchr(p_cpo, CPO_FNAMEW) != NULL) | |
740 { | |
741 if (set_rw_fname(fname, sfname) == FAIL) | |
742 return FAIL; | |
743 buf = curbuf; // just in case autocmds made "buf" invalid | |
744 } | |
745 | |
746 if (sfname == NULL) | |
747 sfname = fname; | |
748 // For Unix: Use the short file name whenever possible. | |
749 // Avoids problems with networks and when directory names are changed. | |
750 // Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to | |
751 // another directory, which we don't detect | |
752 ffname = fname; // remember full fname | |
753 #ifdef UNIX | |
754 fname = sfname; | |
755 #endif | |
756 | |
757 if (buf->b_ffname != NULL && fnamecmp(ffname, buf->b_ffname) == 0) | |
758 overwriting = TRUE; | |
759 else | |
760 overwriting = FALSE; | |
761 | |
762 if (exiting) | |
763 settmode(TMODE_COOK); // when exiting allow typeahead now | |
764 | |
765 ++no_wait_return; // don't wait for return yet | |
766 | |
767 // Set '[ and '] marks to the lines to be written. | |
768 buf->b_op_start.lnum = start; | |
769 buf->b_op_start.col = 0; | |
770 buf->b_op_end.lnum = end; | |
771 buf->b_op_end.col = 0; | |
772 | |
773 { | |
774 aco_save_T aco; | |
775 int buf_ffname = FALSE; | |
776 int buf_sfname = FALSE; | |
777 int buf_fname_f = FALSE; | |
778 int buf_fname_s = FALSE; | |
779 int did_cmd = FALSE; | |
780 int nofile_err = FALSE; | |
781 int empty_memline = (buf->b_ml.ml_mfp == NULL); | |
782 bufref_T bufref; | |
783 | |
784 // Apply PRE autocommands. | |
785 // Set curbuf to the buffer to be written. | |
786 // Careful: The autocommands may call buf_write() recursively! | |
787 if (ffname == buf->b_ffname) | |
788 buf_ffname = TRUE; | |
789 if (sfname == buf->b_sfname) | |
790 buf_sfname = TRUE; | |
791 if (fname == buf->b_ffname) | |
792 buf_fname_f = TRUE; | |
793 if (fname == buf->b_sfname) | |
794 buf_fname_s = TRUE; | |
795 | |
796 // set curwin/curbuf to buf and save a few things | |
797 aucmd_prepbuf(&aco, buf); | |
798 set_bufref(&bufref, buf); | |
799 | |
800 if (append) | |
801 { | |
802 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEAPPENDCMD, | |
803 sfname, sfname, FALSE, curbuf, eap))) | |
804 { | |
805 #ifdef FEAT_QUICKFIX | |
806 if (overwriting && bt_nofilename(curbuf)) | |
807 nofile_err = TRUE; | |
808 else | |
809 #endif | |
810 apply_autocmds_exarg(EVENT_FILEAPPENDPRE, | |
811 sfname, sfname, FALSE, curbuf, eap); | |
812 } | |
813 } | |
814 else if (filtering) | |
815 { | |
816 apply_autocmds_exarg(EVENT_FILTERWRITEPRE, | |
817 NULL, sfname, FALSE, curbuf, eap); | |
818 } | |
819 else if (reset_changed && whole) | |
820 { | |
821 int was_changed = curbufIsChanged(); | |
822 | |
823 did_cmd = apply_autocmds_exarg(EVENT_BUFWRITECMD, | |
824 sfname, sfname, FALSE, curbuf, eap); | |
825 if (did_cmd) | |
826 { | |
827 if (was_changed && !curbufIsChanged()) | |
828 { | |
829 // Written everything correctly and BufWriteCmd has reset | |
830 // 'modified': Correct the undo information so that an | |
831 // undo now sets 'modified'. | |
832 u_unchanged(curbuf); | |
833 u_update_save_nr(curbuf); | |
834 } | |
835 } | |
836 else | |
837 { | |
838 #ifdef FEAT_QUICKFIX | |
839 if (overwriting && bt_nofilename(curbuf)) | |
840 nofile_err = TRUE; | |
841 else | |
842 #endif | |
843 apply_autocmds_exarg(EVENT_BUFWRITEPRE, | |
844 sfname, sfname, FALSE, curbuf, eap); | |
845 } | |
846 } | |
847 else | |
848 { | |
849 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEWRITECMD, | |
850 sfname, sfname, FALSE, curbuf, eap))) | |
851 { | |
852 #ifdef FEAT_QUICKFIX | |
853 if (overwriting && bt_nofilename(curbuf)) | |
854 nofile_err = TRUE; | |
855 else | |
856 #endif | |
857 apply_autocmds_exarg(EVENT_FILEWRITEPRE, | |
858 sfname, sfname, FALSE, curbuf, eap); | |
859 } | |
860 } | |
861 | |
862 // restore curwin/curbuf and a few other things | |
863 aucmd_restbuf(&aco); | |
864 | |
865 // In three situations we return here and don't write the file: | |
866 // 1. the autocommands deleted or unloaded the buffer. | |
867 // 2. The autocommands abort script processing. | |
868 // 3. If one of the "Cmd" autocommands was executed. | |
869 if (!bufref_valid(&bufref)) | |
870 buf = NULL; | |
871 if (buf == NULL || (buf->b_ml.ml_mfp == NULL && !empty_memline) | |
872 || did_cmd || nofile_err | |
873 #ifdef FEAT_EVAL | |
874 || aborting() | |
875 #endif | |
876 ) | |
877 { | |
878 --no_wait_return; | |
879 msg_scroll = msg_save; | |
880 if (nofile_err) | |
881 emsg(_("E676: No matching autocommands for acwrite buffer")); | |
882 | |
883 if (nofile_err | |
884 #ifdef FEAT_EVAL | |
885 || aborting() | |
886 #endif | |
887 ) | |
888 // An aborting error, interrupt or exception in the | |
889 // autocommands. | |
890 return FAIL; | |
891 if (did_cmd) | |
892 { | |
893 if (buf == NULL) | |
894 // The buffer was deleted. We assume it was written | |
895 // (can't retry anyway). | |
896 return OK; | |
897 if (overwriting) | |
898 { | |
899 // Assume the buffer was written, update the timestamp. | |
900 ml_timestamp(buf); | |
901 if (append) | |
902 buf->b_flags &= ~BF_NEW; | |
903 else | |
904 buf->b_flags &= ~BF_WRITE_MASK; | |
905 } | |
906 if (reset_changed && buf->b_changed && !append | |
907 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL)) | |
908 // Buffer still changed, the autocommands didn't work | |
909 // properly. | |
910 return FAIL; | |
911 return OK; | |
912 } | |
913 #ifdef FEAT_EVAL | |
914 if (!aborting()) | |
915 #endif | |
916 emsg(_("E203: Autocommands deleted or unloaded buffer to be written")); | |
917 return FAIL; | |
918 } | |
919 | |
920 // The autocommands may have changed the number of lines in the file. | |
921 // When writing the whole file, adjust the end. | |
922 // When writing part of the file, assume that the autocommands only | |
923 // changed the number of lines that are to be written (tricky!). | |
924 if (buf->b_ml.ml_line_count != old_line_count) | |
925 { | |
926 if (whole) // write all | |
927 end = buf->b_ml.ml_line_count; | |
928 else if (buf->b_ml.ml_line_count > old_line_count) // more lines | |
929 end += buf->b_ml.ml_line_count - old_line_count; | |
930 else // less lines | |
931 { | |
932 end -= old_line_count - buf->b_ml.ml_line_count; | |
933 if (end < start) | |
934 { | |
935 --no_wait_return; | |
936 msg_scroll = msg_save; | |
937 emsg(_("E204: Autocommand changed number of lines in unexpected way")); | |
938 return FAIL; | |
939 } | |
940 } | |
941 } | |
942 | |
943 // The autocommands may have changed the name of the buffer, which may | |
944 // be kept in fname, ffname and sfname. | |
945 if (buf_ffname) | |
946 ffname = buf->b_ffname; | |
947 if (buf_sfname) | |
948 sfname = buf->b_sfname; | |
949 if (buf_fname_f) | |
950 fname = buf->b_ffname; | |
951 if (buf_fname_s) | |
952 fname = buf->b_sfname; | |
953 } | |
954 | |
955 #ifdef FEAT_NETBEANS_INTG | |
956 if (netbeans_active() && isNetbeansBuffer(buf)) | |
957 { | |
958 if (whole) | |
959 { | |
960 // b_changed can be 0 after an undo, but we still need to write | |
961 // the buffer to NetBeans. | |
962 if (buf->b_changed || isNetbeansModified(buf)) | |
963 { | |
964 --no_wait_return; // may wait for return now | |
965 msg_scroll = msg_save; | |
966 netbeans_save_buffer(buf); // no error checking... | |
967 return retval; | |
968 } | |
969 else | |
970 { | |
971 errnum = (char_u *)"E656: "; | |
972 errmsg = (char_u *)_("NetBeans disallows writes of unmodified buffers"); | |
973 buffer = NULL; | |
974 goto fail; | |
975 } | |
976 } | |
977 else | |
978 { | |
979 errnum = (char_u *)"E657: "; | |
980 errmsg = (char_u *)_("Partial writes disallowed for NetBeans buffers"); | |
981 buffer = NULL; | |
982 goto fail; | |
983 } | |
984 } | |
985 #endif | |
986 | |
987 if (shortmess(SHM_OVER) && !exiting) | |
988 msg_scroll = FALSE; // overwrite previous file message | |
989 else | |
990 msg_scroll = TRUE; // don't overwrite previous file message | |
991 if (!filtering) | |
992 filemess(buf, | |
993 #ifndef UNIX | |
994 sfname, | |
995 #else | |
996 fname, | |
997 #endif | |
998 (char_u *)"", 0); // show that we are busy | |
999 msg_scroll = FALSE; // always overwrite the file message now | |
1000 | |
1001 buffer = alloc(WRITEBUFSIZE); | |
1002 if (buffer == NULL) // can't allocate big buffer, use small | |
1003 // one (to be able to write when out of | |
1004 // memory) | |
1005 { | |
1006 buffer = smallbuf; | |
1007 bufsize = SMALLBUFSIZE; | |
1008 } | |
1009 else | |
1010 bufsize = WRITEBUFSIZE; | |
1011 | |
1012 // Get information about original file (if there is one). | |
1013 #if defined(UNIX) | |
1014 st_old.st_dev = 0; | |
1015 st_old.st_ino = 0; | |
1016 perm = -1; | |
1017 if (mch_stat((char *)fname, &st_old) < 0) | |
1018 newfile = TRUE; | |
1019 else | |
1020 { | |
1021 perm = st_old.st_mode; | |
1022 if (!S_ISREG(st_old.st_mode)) // not a file | |
1023 { | |
1024 if (S_ISDIR(st_old.st_mode)) | |
1025 { | |
1026 errnum = (char_u *)"E502: "; | |
1027 errmsg = (char_u *)_("is a directory"); | |
1028 goto fail; | |
1029 } | |
1030 if (mch_nodetype(fname) != NODE_WRITABLE) | |
1031 { | |
1032 errnum = (char_u *)"E503: "; | |
1033 errmsg = (char_u *)_("is not a file or writable device"); | |
1034 goto fail; | |
1035 } | |
1036 // It's a device of some kind (or a fifo) which we can write to | |
1037 // but for which we can't make a backup. | |
1038 device = TRUE; | |
1039 newfile = TRUE; | |
1040 perm = -1; | |
1041 } | |
1042 } | |
1043 #else // !UNIX | |
1044 // Check for a writable device name. | |
1045 c = mch_nodetype(fname); | |
1046 if (c == NODE_OTHER) | |
1047 { | |
1048 errnum = (char_u *)"E503: "; | |
1049 errmsg = (char_u *)_("is not a file or writable device"); | |
1050 goto fail; | |
1051 } | |
1052 if (c == NODE_WRITABLE) | |
1053 { | |
1054 # if defined(MSWIN) | |
1055 // MS-Windows allows opening a device, but we will probably get stuck | |
1056 // trying to write to it. | |
1057 if (!p_odev) | |
1058 { | |
1059 errnum = (char_u *)"E796: "; | |
1060 errmsg = (char_u *)_("writing to device disabled with 'opendevice' option"); | |
1061 goto fail; | |
1062 } | |
1063 # endif | |
1064 device = TRUE; | |
1065 newfile = TRUE; | |
1066 perm = -1; | |
1067 } | |
1068 else | |
1069 { | |
1070 perm = mch_getperm(fname); | |
1071 if (perm < 0) | |
1072 newfile = TRUE; | |
1073 else if (mch_isdir(fname)) | |
1074 { | |
1075 errnum = (char_u *)"E502: "; | |
1076 errmsg = (char_u *)_("is a directory"); | |
1077 goto fail; | |
1078 } | |
1079 if (overwriting) | |
1080 (void)mch_stat((char *)fname, &st_old); | |
1081 } | |
1082 #endif // !UNIX | |
1083 | |
1084 if (!device && !newfile) | |
1085 { | |
1086 // Check if the file is really writable (when renaming the file to | |
1087 // make a backup we won't discover it later). | |
1088 file_readonly = check_file_readonly(fname, (int)perm); | |
1089 | |
1090 if (!forceit && file_readonly) | |
1091 { | |
1092 if (vim_strchr(p_cpo, CPO_FWRITE) != NULL) | |
1093 { | |
1094 errnum = (char_u *)"E504: "; | |
1095 errmsg = (char_u *)_(err_readonly); | |
1096 } | |
1097 else | |
1098 { | |
1099 errnum = (char_u *)"E505: "; | |
1100 errmsg = (char_u *)_("is read-only (add ! to override)"); | |
1101 } | |
1102 goto fail; | |
1103 } | |
1104 | |
1105 // Check if the timestamp hasn't changed since reading the file. | |
1106 if (overwriting) | |
1107 { | |
1108 retval = check_mtime(buf, &st_old); | |
1109 if (retval == FAIL) | |
1110 goto fail; | |
1111 } | |
1112 } | |
1113 | |
1114 #ifdef HAVE_ACL | |
1115 // For systems that support ACL: get the ACL from the original file. | |
1116 if (!newfile) | |
1117 acl = mch_get_acl(fname); | |
1118 #endif | |
1119 | |
1120 // If 'backupskip' is not empty, don't make a backup for some files. | |
1121 dobackup = (p_wb || p_bk || *p_pm != NUL); | |
1122 #ifdef FEAT_WILDIGN | |
1123 if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, sfname, ffname)) | |
1124 dobackup = FALSE; | |
1125 #endif | |
1126 | |
1127 // Save the value of got_int and reset it. We don't want a previous | |
1128 // interruption cancel writing, only hitting CTRL-C while writing should | |
1129 // abort it. | |
1130 prev_got_int = got_int; | |
1131 got_int = FALSE; | |
1132 | |
1133 // Mark the buffer as 'being saved' to prevent changed buffer warnings | |
1134 buf->b_saving = TRUE; | |
1135 | |
1136 // If we are not appending or filtering, the file exists, and the | |
1137 // 'writebackup', 'backup' or 'patchmode' option is set, need a backup. | |
1138 // When 'patchmode' is set also make a backup when appending. | |
1139 // | |
1140 // Do not make any backup, if 'writebackup' and 'backup' are both switched | |
1141 // off. This helps when editing large files on almost-full disks. | |
1142 if (!(append && *p_pm == NUL) && !filtering && perm >= 0 && dobackup) | |
1143 { | |
1144 #if defined(UNIX) || defined(MSWIN) | |
1145 stat_T st; | |
1146 #endif | |
1147 | |
1148 if ((bkc & BKC_YES) || append) // "yes" | |
1149 backup_copy = TRUE; | |
1150 #if defined(UNIX) || defined(MSWIN) | |
1151 else if ((bkc & BKC_AUTO)) // "auto" | |
1152 { | |
1153 int i; | |
1154 | |
1155 # ifdef UNIX | |
1156 // Don't rename the file when: | |
1157 // - it's a hard link | |
1158 // - it's a symbolic link | |
1159 // - we don't have write permission in the directory | |
1160 // - we can't set the owner/group of the new file | |
1161 if (st_old.st_nlink > 1 | |
1162 || mch_lstat((char *)fname, &st) < 0 | |
1163 || st.st_dev != st_old.st_dev | |
1164 || st.st_ino != st_old.st_ino | |
1165 # ifndef HAVE_FCHOWN | |
1166 || st.st_uid != st_old.st_uid | |
1167 || st.st_gid != st_old.st_gid | |
1168 # endif | |
1169 ) | |
1170 backup_copy = TRUE; | |
1171 else | |
1172 # else | |
1173 # ifdef MSWIN | |
1174 // On NTFS file systems hard links are possible. | |
1175 if (mch_is_linked(fname)) | |
1176 backup_copy = TRUE; | |
1177 else | |
1178 # endif | |
1179 # endif | |
1180 { | |
1181 // Check if we can create a file and set the owner/group to | |
1182 // the ones from the original file. | |
1183 // First find a file name that doesn't exist yet (use some | |
1184 // arbitrary numbers). | |
1185 STRCPY(IObuff, fname); | |
1186 for (i = 4913; ; i += 123) | |
1187 { | |
1188 sprintf((char *)gettail(IObuff), "%d", i); | |
1189 if (mch_lstat((char *)IObuff, &st) < 0) | |
1190 break; | |
1191 } | |
1192 fd = mch_open((char *)IObuff, | |
1193 O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm); | |
1194 if (fd < 0) // can't write in directory | |
1195 backup_copy = TRUE; | |
1196 else | |
1197 { | |
1198 # ifdef UNIX | |
1199 # ifdef HAVE_FCHOWN | |
1200 vim_ignored = fchown(fd, st_old.st_uid, st_old.st_gid); | |
1201 # endif | |
1202 if (mch_stat((char *)IObuff, &st) < 0 | |
1203 || st.st_uid != st_old.st_uid | |
1204 || st.st_gid != st_old.st_gid | |
1205 || (long)st.st_mode != perm) | |
1206 backup_copy = TRUE; | |
1207 # endif | |
1208 // Close the file before removing it, on MS-Windows we | |
1209 // can't delete an open file. | |
1210 close(fd); | |
1211 mch_remove(IObuff); | |
1212 # ifdef MSWIN | |
1213 // MS-Windows may trigger a virus scanner to open the | |
1214 // file, we can't delete it then. Keep trying for half a | |
1215 // second. | |
1216 { | |
1217 int try; | |
1218 | |
1219 for (try = 0; try < 10; ++try) | |
1220 { | |
1221 if (mch_lstat((char *)IObuff, &st) < 0) | |
1222 break; | |
1223 ui_delay(50L, TRUE); // wait 50 msec | |
1224 mch_remove(IObuff); | |
1225 } | |
1226 } | |
1227 # endif | |
1228 } | |
1229 } | |
1230 } | |
1231 | |
1232 // Break symlinks and/or hardlinks if we've been asked to. | |
1233 if ((bkc & BKC_BREAKSYMLINK) || (bkc & BKC_BREAKHARDLINK)) | |
1234 { | |
1235 # ifdef UNIX | |
1236 int lstat_res; | |
1237 | |
1238 lstat_res = mch_lstat((char *)fname, &st); | |
1239 | |
1240 // Symlinks. | |
1241 if ((bkc & BKC_BREAKSYMLINK) | |
1242 && lstat_res == 0 | |
1243 && st.st_ino != st_old.st_ino) | |
1244 backup_copy = FALSE; | |
1245 | |
1246 // Hardlinks. | |
1247 if ((bkc & BKC_BREAKHARDLINK) | |
1248 && st_old.st_nlink > 1 | |
1249 && (lstat_res != 0 || st.st_ino == st_old.st_ino)) | |
1250 backup_copy = FALSE; | |
1251 # else | |
1252 # if defined(MSWIN) | |
1253 // Symlinks. | |
1254 if ((bkc & BKC_BREAKSYMLINK) && mch_is_symbolic_link(fname)) | |
1255 backup_copy = FALSE; | |
1256 | |
1257 // Hardlinks. | |
1258 if ((bkc & BKC_BREAKHARDLINK) && mch_is_hard_link(fname)) | |
1259 backup_copy = FALSE; | |
1260 # endif | |
1261 # endif | |
1262 } | |
1263 | |
1264 #endif | |
1265 | |
1266 // make sure we have a valid backup extension to use | |
1267 if (*p_bex == NUL) | |
1268 backup_ext = (char_u *)".bak"; | |
1269 else | |
1270 backup_ext = p_bex; | |
1271 | |
1272 if (backup_copy | |
1273 && (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) >= 0) | |
1274 { | |
1275 int bfd; | |
1276 char_u *copybuf, *wp; | |
1277 int some_error = FALSE; | |
1278 stat_T st_new; | |
1279 char_u *dirp; | |
1280 char_u *rootname; | |
1281 #if defined(UNIX) || defined(MSWIN) | |
1282 char_u *p; | |
1283 #endif | |
1284 #if defined(UNIX) | |
1285 int did_set_shortname; | |
1286 mode_t umask_save; | |
1287 #endif | |
1288 | |
1289 copybuf = alloc(WRITEBUFSIZE + 1); | |
1290 if (copybuf == NULL) | |
1291 { | |
1292 some_error = TRUE; // out of memory | |
1293 goto nobackup; | |
1294 } | |
1295 | |
1296 // Try to make the backup in each directory in the 'bdir' option. | |
1297 // | |
1298 // Unix semantics has it, that we may have a writable file, | |
1299 // that cannot be recreated with a simple open(..., O_CREAT, ) e.g: | |
1300 // - the directory is not writable, | |
1301 // - the file may be a symbolic link, | |
1302 // - the file may belong to another user/group, etc. | |
1303 // | |
1304 // For these reasons, the existing writable file must be truncated | |
1305 // and reused. Creation of a backup COPY will be attempted. | |
1306 dirp = p_bdir; | |
1307 while (*dirp) | |
1308 { | |
1309 #ifdef UNIX | |
1310 st_new.st_ino = 0; | |
1311 st_new.st_dev = 0; | |
1312 st_new.st_gid = 0; | |
1313 #endif | |
1314 | |
1315 // Isolate one directory name, using an entry in 'bdir'. | |
1316 (void)copy_option_part(&dirp, copybuf, WRITEBUFSIZE, ","); | |
1317 | |
1318 #if defined(UNIX) || defined(MSWIN) | |
1319 p = copybuf + STRLEN(copybuf); | |
1320 if (after_pathsep(copybuf, p) && p[-1] == p[-2]) | |
1321 // Ends with '//', use full path | |
1322 if ((p = make_percent_swname(copybuf, fname)) != NULL) | |
1323 { | |
1324 backup = modname(p, backup_ext, FALSE); | |
1325 vim_free(p); | |
1326 } | |
1327 #endif | |
1328 rootname = get_file_in_dir(fname, copybuf); | |
1329 if (rootname == NULL) | |
1330 { | |
1331 some_error = TRUE; // out of memory | |
1332 goto nobackup; | |
1333 } | |
1334 | |
1335 #if defined(UNIX) | |
1336 did_set_shortname = FALSE; | |
1337 #endif | |
1338 | |
1339 // May try twice if 'shortname' not set. | |
1340 for (;;) | |
1341 { | |
1342 // Make the backup file name. | |
1343 if (backup == NULL) | |
1344 backup = buf_modname((buf->b_p_sn || buf->b_shortname), | |
1345 rootname, backup_ext, FALSE); | |
1346 if (backup == NULL) | |
1347 { | |
1348 vim_free(rootname); | |
1349 some_error = TRUE; // out of memory | |
1350 goto nobackup; | |
1351 } | |
1352 | |
1353 // Check if backup file already exists. | |
1354 if (mch_stat((char *)backup, &st_new) >= 0) | |
1355 { | |
1356 #ifdef UNIX | |
1357 // Check if backup file is same as original file. | |
1358 // May happen when modname() gave the same file back. | |
1359 // E.g. silly link, or file name-length reached. | |
1360 // If we don't check here, we either ruin the file | |
1361 // when copying or erase it after writing. jw. | |
1362 if (st_new.st_dev == st_old.st_dev | |
1363 && st_new.st_ino == st_old.st_ino) | |
1364 { | |
1365 VIM_CLEAR(backup); // no backup file to delete | |
1366 // may try again with 'shortname' set | |
1367 if (!(buf->b_shortname || buf->b_p_sn)) | |
1368 { | |
1369 buf->b_shortname = TRUE; | |
1370 did_set_shortname = TRUE; | |
1371 continue; | |
1372 } | |
1373 // setting shortname didn't help | |
1374 if (did_set_shortname) | |
1375 buf->b_shortname = FALSE; | |
1376 break; | |
1377 } | |
1378 #endif | |
1379 | |
1380 // If we are not going to keep the backup file, don't | |
1381 // delete an existing one, try to use another name. | |
1382 // Change one character, just before the extension. | |
1383 if (!p_bk) | |
1384 { | |
1385 wp = backup + STRLEN(backup) - 1 | |
1386 - STRLEN(backup_ext); | |
1387 if (wp < backup) // empty file name ??? | |
1388 wp = backup; | |
1389 *wp = 'z'; | |
1390 while (*wp > 'a' | |
1391 && mch_stat((char *)backup, &st_new) >= 0) | |
1392 --*wp; | |
1393 // They all exist??? Must be something wrong. | |
1394 if (*wp == 'a') | |
1395 VIM_CLEAR(backup); | |
1396 } | |
1397 } | |
1398 break; | |
1399 } | |
1400 vim_free(rootname); | |
1401 | |
1402 // Try to create the backup file | |
1403 if (backup != NULL) | |
1404 { | |
1405 // remove old backup, if present | |
1406 mch_remove(backup); | |
1407 // Open with O_EXCL to avoid the file being created while | |
1408 // we were sleeping (symlink hacker attack?). Reset umask | |
1409 // if possible to avoid mch_setperm() below. | |
1410 #ifdef UNIX | |
1411 umask_save = umask(0); | |
1412 #endif | |
1413 bfd = mch_open((char *)backup, | |
1414 O_WRONLY|O_CREAT|O_EXTRA|O_EXCL|O_NOFOLLOW, | |
1415 perm & 0777); | |
1416 #ifdef UNIX | |
1417 (void)umask(umask_save); | |
1418 #endif | |
1419 if (bfd < 0) | |
1420 VIM_CLEAR(backup); | |
1421 else | |
1422 { | |
1423 // Set file protection same as original file, but | |
1424 // strip s-bit. Only needed if umask() wasn't used | |
1425 // above. | |
1426 #ifndef UNIX | |
1427 (void)mch_setperm(backup, perm & 0777); | |
1428 #else | |
1429 // Try to set the group of the backup same as the | |
1430 // original file. If this fails, set the protection | |
1431 // bits for the group same as the protection bits for | |
1432 // others. | |
1433 if (st_new.st_gid != st_old.st_gid | |
1434 # ifdef HAVE_FCHOWN // sequent-ptx lacks fchown() | |
1435 && fchown(bfd, (uid_t)-1, st_old.st_gid) != 0 | |
1436 # endif | |
1437 ) | |
1438 mch_setperm(backup, | |
1439 (perm & 0707) | ((perm & 07) << 3)); | |
1440 # if defined(HAVE_SELINUX) || defined(HAVE_SMACK) | |
1441 mch_copy_sec(fname, backup); | |
1442 # endif | |
1443 #endif | |
1444 | |
1445 // copy the file. | |
1446 write_info.bw_fd = bfd; | |
1447 write_info.bw_buf = copybuf; | |
1448 write_info.bw_flags = FIO_NOCONVERT; | |
1449 while ((write_info.bw_len = read_eintr(fd, copybuf, | |
1450 WRITEBUFSIZE)) > 0) | |
1451 { | |
1452 if (buf_write_bytes(&write_info) == FAIL) | |
1453 { | |
1454 errmsg = (char_u *)_("E506: Can't write to backup file (add ! to override)"); | |
1455 break; | |
1456 } | |
1457 ui_breakcheck(); | |
1458 if (got_int) | |
1459 { | |
1460 errmsg = (char_u *)_(e_interr); | |
1461 break; | |
1462 } | |
1463 } | |
1464 | |
1465 if (close(bfd) < 0 && errmsg == NULL) | |
1466 errmsg = (char_u *)_("E507: Close error for backup file (add ! to override)"); | |
1467 if (write_info.bw_len < 0) | |
1468 errmsg = (char_u *)_("E508: Can't read file for backup (add ! to override)"); | |
1469 #ifdef UNIX | |
1470 set_file_time(backup, st_old.st_atime, st_old.st_mtime); | |
1471 #endif | |
1472 #ifdef HAVE_ACL | |
1473 mch_set_acl(backup, acl); | |
1474 #endif | |
1475 #if defined(HAVE_SELINUX) || defined(HAVE_SMACK) | |
1476 mch_copy_sec(fname, backup); | |
1477 #endif | |
1478 break; | |
1479 } | |
1480 } | |
1481 } | |
1482 nobackup: | |
1483 close(fd); // ignore errors for closing read file | |
1484 vim_free(copybuf); | |
1485 | |
1486 if (backup == NULL && errmsg == NULL) | |
1487 errmsg = (char_u *)_("E509: Cannot create backup file (add ! to override)"); | |
1488 // ignore errors when forceit is TRUE | |
1489 if ((some_error || errmsg != NULL) && !forceit) | |
1490 { | |
1491 retval = FAIL; | |
1492 goto fail; | |
1493 } | |
1494 errmsg = NULL; | |
1495 } | |
1496 else | |
1497 { | |
1498 char_u *dirp; | |
1499 char_u *p; | |
1500 char_u *rootname; | |
1501 | |
1502 // Make a backup by renaming the original file. | |
1503 | |
1504 // If 'cpoptions' includes the "W" flag, we don't want to | |
1505 // overwrite a read-only file. But rename may be possible | |
1506 // anyway, thus we need an extra check here. | |
1507 if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL) | |
1508 { | |
1509 errnum = (char_u *)"E504: "; | |
1510 errmsg = (char_u *)_(err_readonly); | |
1511 goto fail; | |
1512 } | |
1513 | |
1514 // Form the backup file name - change path/fo.o.h to | |
1515 // path/fo.o.h.bak Try all directories in 'backupdir', first one | |
1516 // that works is used. | |
1517 dirp = p_bdir; | |
1518 while (*dirp) | |
1519 { | |
1520 // Isolate one directory name and make the backup file name. | |
1521 (void)copy_option_part(&dirp, IObuff, IOSIZE, ","); | |
1522 | |
1523 #if defined(UNIX) || defined(MSWIN) | |
1524 p = IObuff + STRLEN(IObuff); | |
1525 if (after_pathsep(IObuff, p) && p[-1] == p[-2]) | |
1526 // path ends with '//', use full path | |
1527 if ((p = make_percent_swname(IObuff, fname)) != NULL) | |
1528 { | |
1529 backup = modname(p, backup_ext, FALSE); | |
1530 vim_free(p); | |
1531 } | |
1532 #endif | |
1533 if (backup == NULL) | |
1534 { | |
1535 rootname = get_file_in_dir(fname, IObuff); | |
1536 if (rootname == NULL) | |
1537 backup = NULL; | |
1538 else | |
1539 { | |
1540 backup = buf_modname( | |
1541 (buf->b_p_sn || buf->b_shortname), | |
1542 rootname, backup_ext, FALSE); | |
1543 vim_free(rootname); | |
1544 } | |
1545 } | |
1546 | |
1547 if (backup != NULL) | |
1548 { | |
1549 // If we are not going to keep the backup file, don't | |
1550 // delete an existing one, try to use another name. | |
1551 // Change one character, just before the extension. | |
1552 if (!p_bk && mch_getperm(backup) >= 0) | |
1553 { | |
1554 p = backup + STRLEN(backup) - 1 - STRLEN(backup_ext); | |
1555 if (p < backup) // empty file name ??? | |
1556 p = backup; | |
1557 *p = 'z'; | |
1558 while (*p > 'a' && mch_getperm(backup) >= 0) | |
1559 --*p; | |
1560 // They all exist??? Must be something wrong! | |
1561 if (*p == 'a') | |
1562 VIM_CLEAR(backup); | |
1563 } | |
1564 } | |
1565 if (backup != NULL) | |
1566 { | |
1567 // Delete any existing backup and move the current version | |
1568 // to the backup. For safety, we don't remove the backup | |
1569 // until the write has finished successfully. And if the | |
1570 // 'backup' option is set, leave it around. | |
1571 | |
1572 // If the renaming of the original file to the backup file | |
1573 // works, quit here. | |
1574 if (vim_rename(fname, backup) == 0) | |
1575 break; | |
1576 | |
1577 VIM_CLEAR(backup); // don't do the rename below | |
1578 } | |
1579 } | |
1580 if (backup == NULL && !forceit) | |
1581 { | |
1582 errmsg = (char_u *)_("E510: Can't make backup file (add ! to override)"); | |
1583 goto fail; | |
1584 } | |
1585 } | |
1586 } | |
1587 | |
1588 #if defined(UNIX) | |
1589 // When using ":w!" and the file was read-only: make it writable | |
1590 if (forceit && perm >= 0 && !(perm & 0200) && st_old.st_uid == getuid() | |
1591 && vim_strchr(p_cpo, CPO_FWRITE) == NULL) | |
1592 { | |
1593 perm |= 0200; | |
1594 (void)mch_setperm(fname, perm); | |
1595 made_writable = TRUE; | |
1596 } | |
1597 #endif | |
1598 | |
1599 // When using ":w!" and writing to the current file, 'readonly' makes no | |
1600 // sense, reset it, unless 'Z' appears in 'cpoptions'. | |
1601 if (forceit && overwriting && vim_strchr(p_cpo, CPO_KEEPRO) == NULL) | |
1602 { | |
1603 buf->b_p_ro = FALSE; | |
1604 #ifdef FEAT_TITLE | |
1605 need_maketitle = TRUE; // set window title later | |
1606 #endif | |
1607 status_redraw_all(); // redraw status lines later | |
1608 } | |
1609 | |
1610 if (end > buf->b_ml.ml_line_count) | |
1611 end = buf->b_ml.ml_line_count; | |
1612 if (buf->b_ml.ml_flags & ML_EMPTY) | |
1613 start = end + 1; | |
1614 | |
1615 // If the original file is being overwritten, there is a small chance that | |
1616 // we crash in the middle of writing. Therefore the file is preserved now. | |
1617 // This makes all block numbers positive so that recovery does not need | |
1618 // the original file. | |
1619 // Don't do this if there is a backup file and we are exiting. | |
1620 if (reset_changed && !newfile && overwriting | |
1621 && !(exiting && backup != NULL)) | |
1622 { | |
1623 ml_preserve(buf, FALSE); | |
1624 if (got_int) | |
1625 { | |
1626 errmsg = (char_u *)_(e_interr); | |
1627 goto restore_backup; | |
1628 } | |
1629 } | |
1630 | |
1631 #ifdef VMS | |
1632 vms_remove_version(fname); // remove version | |
1633 #endif | |
1634 // Default: write the file directly. May write to a temp file for | |
1635 // multi-byte conversion. | |
1636 wfname = fname; | |
1637 | |
1638 // Check for forced 'fileencoding' from "++opt=val" argument. | |
1639 if (eap != NULL && eap->force_enc != 0) | |
1640 { | |
1641 fenc = eap->cmd + eap->force_enc; | |
1642 fenc = enc_canonize(fenc); | |
1643 fenc_tofree = fenc; | |
1644 } | |
1645 else | |
1646 fenc = buf->b_p_fenc; | |
1647 | |
1648 // Check if the file needs to be converted. | |
1649 converted = need_conversion(fenc); | |
1650 | |
1651 // Check if UTF-8 to UCS-2/4 or Latin1 conversion needs to be done. Or | |
1652 // Latin1 to Unicode conversion. This is handled in buf_write_bytes(). | |
1653 // Prepare the flags for it and allocate bw_conv_buf when needed. | |
1654 if (converted && (enc_utf8 || STRCMP(p_enc, "latin1") == 0)) | |
1655 { | |
1656 wb_flags = get_fio_flags(fenc); | |
1657 if (wb_flags & (FIO_UCS2 | FIO_UCS4 | FIO_UTF16 | FIO_UTF8)) | |
1658 { | |
1659 // Need to allocate a buffer to translate into. | |
1660 if (wb_flags & (FIO_UCS2 | FIO_UTF16 | FIO_UTF8)) | |
1661 write_info.bw_conv_buflen = bufsize * 2; | |
1662 else // FIO_UCS4 | |
1663 write_info.bw_conv_buflen = bufsize * 4; | |
1664 write_info.bw_conv_buf = alloc(write_info.bw_conv_buflen); | |
1665 if (write_info.bw_conv_buf == NULL) | |
1666 end = 0; | |
1667 } | |
1668 } | |
1669 | |
1670 #ifdef MSWIN | |
1671 if (converted && wb_flags == 0 && (wb_flags = get_win_fio_flags(fenc)) != 0) | |
1672 { | |
1673 // Convert UTF-8 -> UCS-2 and UCS-2 -> DBCS. Worst-case * 4: | |
1674 write_info.bw_conv_buflen = bufsize * 4; | |
1675 write_info.bw_conv_buf = alloc(write_info.bw_conv_buflen); | |
1676 if (write_info.bw_conv_buf == NULL) | |
1677 end = 0; | |
1678 } | |
1679 #endif | |
1680 | |
1681 #ifdef MACOS_CONVERT | |
1682 if (converted && wb_flags == 0 && (wb_flags = get_mac_fio_flags(fenc)) != 0) | |
1683 { | |
1684 write_info.bw_conv_buflen = bufsize * 3; | |
1685 write_info.bw_conv_buf = alloc(write_info.bw_conv_buflen); | |
1686 if (write_info.bw_conv_buf == NULL) | |
1687 end = 0; | |
1688 } | |
1689 #endif | |
1690 | |
1691 #if defined(FEAT_EVAL) || defined(USE_ICONV) | |
1692 if (converted && wb_flags == 0) | |
1693 { | |
1694 # ifdef USE_ICONV | |
1695 // Use iconv() conversion when conversion is needed and it's not done | |
1696 // internally. | |
1697 write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc, | |
1698 enc_utf8 ? (char_u *)"utf-8" : p_enc); | |
1699 if (write_info.bw_iconv_fd != (iconv_t)-1) | |
1700 { | |
1701 // We're going to use iconv(), allocate a buffer to convert in. | |
1702 write_info.bw_conv_buflen = bufsize * ICONV_MULT; | |
1703 write_info.bw_conv_buf = alloc(write_info.bw_conv_buflen); | |
1704 if (write_info.bw_conv_buf == NULL) | |
1705 end = 0; | |
1706 write_info.bw_first = TRUE; | |
1707 } | |
1708 # ifdef FEAT_EVAL | |
1709 else | |
1710 # endif | |
1711 # endif | |
1712 | |
1713 # ifdef FEAT_EVAL | |
1714 // When the file needs to be converted with 'charconvert' after | |
1715 // writing, write to a temp file instead and let the conversion | |
1716 // overwrite the original file. | |
1717 if (*p_ccv != NUL) | |
1718 { | |
1719 wfname = vim_tempname('w', FALSE); | |
1720 if (wfname == NULL) // Can't write without a tempfile! | |
1721 { | |
1722 errmsg = (char_u *)_("E214: Can't find temp file for writing"); | |
1723 goto restore_backup; | |
1724 } | |
1725 } | |
1726 # endif | |
1727 } | |
1728 #endif | |
1729 if (converted && wb_flags == 0 | |
1730 #ifdef USE_ICONV | |
1731 && write_info.bw_iconv_fd == (iconv_t)-1 | |
1732 # endif | |
1733 # ifdef FEAT_EVAL | |
1734 && wfname == fname | |
1735 # endif | |
1736 ) | |
1737 { | |
1738 if (!forceit) | |
1739 { | |
1740 errmsg = (char_u *)_("E213: Cannot convert (add ! to write without conversion)"); | |
1741 goto restore_backup; | |
1742 } | |
1743 notconverted = TRUE; | |
1744 } | |
1745 | |
1746 // If conversion is taking place, we may first pretend to write and check | |
1747 // for conversion errors. Then loop again to write for real. | |
1748 // When not doing conversion this writes for real right away. | |
1749 for (checking_conversion = TRUE; ; checking_conversion = FALSE) | |
1750 { | |
1751 // There is no need to check conversion when: | |
1752 // - there is no conversion | |
1753 // - we make a backup file, that can be restored in case of conversion | |
1754 // failure. | |
1755 if (!converted || dobackup) | |
1756 checking_conversion = FALSE; | |
1757 | |
1758 if (checking_conversion) | |
1759 { | |
1760 // Make sure we don't write anything. | |
1761 fd = -1; | |
1762 write_info.bw_fd = fd; | |
1763 } | |
1764 else | |
1765 { | |
1766 #ifdef HAVE_FTRUNCATE | |
1767 # define TRUNC_ON_OPEN 0 | |
1768 #else | |
1769 # define TRUNC_ON_OPEN O_TRUNC | |
1770 #endif | |
1771 // Open the file "wfname" for writing. | |
1772 // We may try to open the file twice: If we can't write to the file | |
1773 // and forceit is TRUE we delete the existing file and try to | |
1774 // create a new one. If this still fails we may have lost the | |
1775 // original file! (this may happen when the user reached his | |
1776 // quotum for number of files). | |
1777 // Appending will fail if the file does not exist and forceit is | |
1778 // FALSE. | |
1779 while ((fd = mch_open((char *)wfname, O_WRONLY | O_EXTRA | (append | |
1780 ? (forceit ? (O_APPEND | O_CREAT) : O_APPEND) | |
1781 : (O_CREAT | TRUNC_ON_OPEN)) | |
1782 , perm < 0 ? 0666 : (perm & 0777))) < 0) | |
1783 { | |
1784 // A forced write will try to create a new file if the old one | |
1785 // is still readonly. This may also happen when the directory | |
1786 // is read-only. In that case the mch_remove() will fail. | |
1787 if (errmsg == NULL) | |
1788 { | |
1789 #ifdef UNIX | |
1790 stat_T st; | |
1791 | |
1792 // Don't delete the file when it's a hard or symbolic link. | |
1793 if ((!newfile && st_old.st_nlink > 1) | |
1794 || (mch_lstat((char *)fname, &st) == 0 | |
1795 && (st.st_dev != st_old.st_dev | |
1796 || st.st_ino != st_old.st_ino))) | |
1797 errmsg = (char_u *)_("E166: Can't open linked file for writing"); | |
1798 else | |
1799 #endif | |
1800 { | |
1801 errmsg = (char_u *)_("E212: Can't open file for writing"); | |
1802 if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL | |
1803 && perm >= 0) | |
1804 { | |
1805 #ifdef UNIX | |
1806 // we write to the file, thus it should be marked | |
1807 // writable after all | |
1808 if (!(perm & 0200)) | |
1809 made_writable = TRUE; | |
1810 perm |= 0200; | |
1811 if (st_old.st_uid != getuid() | |
1812 || st_old.st_gid != getgid()) | |
1813 perm &= 0777; | |
1814 #endif | |
1815 if (!append) // don't remove when appending | |
1816 mch_remove(wfname); | |
1817 continue; | |
1818 } | |
1819 } | |
1820 } | |
1821 | |
1822 restore_backup: | |
1823 { | |
1824 stat_T st; | |
1825 | |
1826 // If we failed to open the file, we don't need a backup. | |
1827 // Throw it away. If we moved or removed the original file | |
1828 // try to put the backup in its place. | |
1829 if (backup != NULL && wfname == fname) | |
1830 { | |
1831 if (backup_copy) | |
1832 { | |
1833 // There is a small chance that we removed the | |
1834 // original, try to move the copy in its place. | |
1835 // This may not work if the vim_rename() fails. | |
1836 // In that case we leave the copy around. | |
1837 | |
1838 // If file does not exist, put the copy in its | |
1839 // place | |
1840 if (mch_stat((char *)fname, &st) < 0) | |
1841 vim_rename(backup, fname); | |
1842 // if original file does exist throw away the copy | |
1843 if (mch_stat((char *)fname, &st) >= 0) | |
1844 mch_remove(backup); | |
1845 } | |
1846 else | |
1847 { | |
1848 // try to put the original file back | |
1849 vim_rename(backup, fname); | |
1850 } | |
1851 } | |
1852 | |
1853 // if original file no longer exists give an extra warning | |
1854 if (!newfile && mch_stat((char *)fname, &st) < 0) | |
1855 end = 0; | |
1856 } | |
1857 | |
1858 if (wfname != fname) | |
1859 vim_free(wfname); | |
1860 goto fail; | |
1861 } | |
1862 write_info.bw_fd = fd; | |
1863 | |
1864 #if defined(UNIX) | |
1865 { | |
1866 stat_T st; | |
1867 | |
1868 // Double check we are writing the intended file before making | |
1869 // any changes. | |
1870 if (overwriting | |
1871 && (!dobackup || backup_copy) | |
1872 && fname == wfname | |
1873 && perm >= 0 | |
1874 && mch_fstat(fd, &st) == 0 | |
1875 && st.st_ino != st_old.st_ino) | |
1876 { | |
1877 close(fd); | |
1878 errmsg = (char_u *)_("E949: File changed while writing"); | |
1879 goto fail; | |
1880 } | |
1881 } | |
1882 #endif | |
1883 #ifdef HAVE_FTRUNCATE | |
1884 if (!append) | |
1885 vim_ignored = ftruncate(fd, (off_t)0); | |
1886 #endif | |
1887 | |
1888 #if defined(MSWIN) | |
1889 if (backup != NULL && overwriting && !append) | |
1890 { | |
1891 if (backup_copy) | |
1892 (void)mch_copy_file_attribute(wfname, backup); | |
1893 else | |
1894 (void)mch_copy_file_attribute(backup, wfname); | |
1895 } | |
1896 | |
1897 if (!overwriting && !append) | |
1898 { | |
1899 if (buf->b_ffname != NULL) | |
1900 (void)mch_copy_file_attribute(buf->b_ffname, wfname); | |
1901 // Should copy resource fork | |
1902 } | |
1903 #endif | |
1904 | |
1905 #ifdef FEAT_CRYPT | |
1906 if (*buf->b_p_key != NUL && !filtering) | |
1907 { | |
1908 char_u *header; | |
1909 int header_len; | |
1910 | |
1911 buf->b_cryptstate = crypt_create_for_writing( | |
1912 crypt_get_method_nr(buf), | |
1913 buf->b_p_key, &header, &header_len); | |
1914 if (buf->b_cryptstate == NULL || header == NULL) | |
1915 end = 0; | |
1916 else | |
1917 { | |
1918 // Write magic number, so that Vim knows how this file is | |
1919 // encrypted when reading it back. | |
1920 write_info.bw_buf = header; | |
1921 write_info.bw_len = header_len; | |
1922 write_info.bw_flags = FIO_NOCONVERT; | |
1923 if (buf_write_bytes(&write_info) == FAIL) | |
1924 end = 0; | |
1925 wb_flags |= FIO_ENCRYPTED; | |
1926 vim_free(header); | |
1927 } | |
1928 } | |
1929 #endif | |
1930 } | |
1931 errmsg = NULL; | |
1932 | |
1933 write_info.bw_buf = buffer; | |
1934 nchars = 0; | |
1935 | |
1936 // use "++bin", "++nobin" or 'binary' | |
1937 if (eap != NULL && eap->force_bin != 0) | |
1938 write_bin = (eap->force_bin == FORCE_BIN); | |
1939 else | |
1940 write_bin = buf->b_p_bin; | |
1941 | |
1942 // The BOM is written just after the encryption magic number. | |
1943 // Skip it when appending and the file already existed, the BOM only | |
1944 // makes sense at the start of the file. | |
1945 if (buf->b_p_bomb && !write_bin && (!append || perm < 0)) | |
1946 { | |
1947 write_info.bw_len = make_bom(buffer, fenc); | |
1948 if (write_info.bw_len > 0) | |
1949 { | |
1950 // don't convert, do encryption | |
1951 write_info.bw_flags = FIO_NOCONVERT | wb_flags; | |
1952 if (buf_write_bytes(&write_info) == FAIL) | |
1953 end = 0; | |
1954 else | |
1955 nchars += write_info.bw_len; | |
1956 } | |
1957 } | |
1958 write_info.bw_start_lnum = start; | |
1959 | |
1960 #ifdef FEAT_PERSISTENT_UNDO | |
1961 write_undo_file = (buf->b_p_udf | |
1962 && overwriting | |
1963 && !append | |
1964 && !filtering | |
1965 && reset_changed | |
1966 && !checking_conversion); | |
1967 if (write_undo_file) | |
1968 // Prepare for computing the hash value of the text. | |
1969 sha256_start(&sha_ctx); | |
1970 #endif | |
1971 | |
1972 write_info.bw_len = bufsize; | |
1973 write_info.bw_flags = wb_flags; | |
1974 fileformat = get_fileformat_force(buf, eap); | |
1975 s = buffer; | |
1976 len = 0; | |
1977 for (lnum = start; lnum <= end; ++lnum) | |
1978 { | |
1979 // The next while loop is done once for each character written. | |
1980 // Keep it fast! | |
1981 ptr = ml_get_buf(buf, lnum, FALSE) - 1; | |
1982 #ifdef FEAT_PERSISTENT_UNDO | |
1983 if (write_undo_file) | |
1984 sha256_update(&sha_ctx, ptr + 1, | |
1985 (UINT32_T)(STRLEN(ptr + 1) + 1)); | |
1986 #endif | |
1987 while ((c = *++ptr) != NUL) | |
1988 { | |
1989 if (c == NL) | |
1990 *s = NUL; // replace newlines with NULs | |
1991 else if (c == CAR && fileformat == EOL_MAC) | |
1992 *s = NL; // Mac: replace CRs with NLs | |
1993 else | |
1994 *s = c; | |
1995 ++s; | |
1996 if (++len != bufsize) | |
1997 continue; | |
1998 if (buf_write_bytes(&write_info) == FAIL) | |
1999 { | |
2000 end = 0; // write error: break loop | |
2001 break; | |
2002 } | |
2003 nchars += bufsize; | |
2004 s = buffer; | |
2005 len = 0; | |
2006 write_info.bw_start_lnum = lnum; | |
2007 } | |
2008 // write failed or last line has no EOL: stop here | |
2009 if (end == 0 | |
2010 || (lnum == end | |
2011 && (write_bin || !buf->b_p_fixeol) | |
2012 && (lnum == buf->b_no_eol_lnum | |
2013 || (lnum == buf->b_ml.ml_line_count | |
2014 && !buf->b_p_eol)))) | |
2015 { | |
2016 ++lnum; // written the line, count it | |
2017 no_eol = TRUE; | |
2018 break; | |
2019 } | |
2020 if (fileformat == EOL_UNIX) | |
2021 *s++ = NL; | |
2022 else | |
2023 { | |
2024 *s++ = CAR; // EOL_MAC or EOL_DOS: write CR | |
2025 if (fileformat == EOL_DOS) // write CR-NL | |
2026 { | |
2027 if (++len == bufsize) | |
2028 { | |
2029 if (buf_write_bytes(&write_info) == FAIL) | |
2030 { | |
2031 end = 0; // write error: break loop | |
2032 break; | |
2033 } | |
2034 nchars += bufsize; | |
2035 s = buffer; | |
2036 len = 0; | |
2037 } | |
2038 *s++ = NL; | |
2039 } | |
2040 } | |
2041 if (++len == bufsize && end) | |
2042 { | |
2043 if (buf_write_bytes(&write_info) == FAIL) | |
2044 { | |
2045 end = 0; // write error: break loop | |
2046 break; | |
2047 } | |
2048 nchars += bufsize; | |
2049 s = buffer; | |
2050 len = 0; | |
2051 | |
2052 ui_breakcheck(); | |
2053 if (got_int) | |
2054 { | |
2055 end = 0; // Interrupted, break loop | |
2056 break; | |
2057 } | |
2058 } | |
2059 #ifdef VMS | |
2060 // On VMS there is a problem: newlines get added when writing | |
2061 // blocks at a time. Fix it by writing a line at a time. | |
2062 // This is much slower! | |
2063 // Explanation: VAX/DECC RTL insists that records in some RMS | |
2064 // structures end with a newline (carriage return) character, and | |
2065 // if they don't it adds one. | |
2066 // With other RMS structures it works perfect without this fix. | |
2067 if (buf->b_fab_rfm == FAB$C_VFC | |
2068 || ((buf->b_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0)) | |
2069 { | |
2070 int b2write; | |
2071 | |
2072 buf->b_fab_mrs = (buf->b_fab_mrs == 0 | |
2073 ? MIN(4096, bufsize) | |
2074 : MIN(buf->b_fab_mrs, bufsize)); | |
2075 | |
2076 b2write = len; | |
2077 while (b2write > 0) | |
2078 { | |
2079 write_info.bw_len = MIN(b2write, buf->b_fab_mrs); | |
2080 if (buf_write_bytes(&write_info) == FAIL) | |
2081 { | |
2082 end = 0; | |
2083 break; | |
2084 } | |
2085 b2write -= MIN(b2write, buf->b_fab_mrs); | |
2086 } | |
2087 write_info.bw_len = bufsize; | |
2088 nchars += len; | |
2089 s = buffer; | |
2090 len = 0; | |
2091 } | |
2092 #endif | |
2093 } | |
2094 if (len > 0 && end > 0) | |
2095 { | |
2096 write_info.bw_len = len; | |
2097 if (buf_write_bytes(&write_info) == FAIL) | |
2098 end = 0; // write error | |
2099 nchars += len; | |
2100 } | |
2101 | |
2102 // Stop when writing done or an error was encountered. | |
2103 if (!checking_conversion || end == 0) | |
2104 break; | |
2105 | |
2106 // If no error happened until now, writing should be ok, so loop to | |
2107 // really write the buffer. | |
2108 } | |
2109 | |
2110 // If we started writing, finish writing. Also when an error was | |
2111 // encountered. | |
2112 if (!checking_conversion) | |
2113 { | |
2114 #if defined(UNIX) && defined(HAVE_FSYNC) | |
2115 // On many journalling file systems there is a bug that causes both the | |
2116 // original and the backup file to be lost when halting the system | |
2117 // right after writing the file. That's because only the meta-data is | |
2118 // journalled. Syncing the file slows down the system, but assures it | |
2119 // has been written to disk and we don't lose it. | |
2120 // For a device do try the fsync() but don't complain if it does not | |
2121 // work (could be a pipe). | |
2122 // If the 'fsync' option is FALSE, don't fsync(). Useful for laptops. | |
2123 if (p_fs && vim_fsync(fd) != 0 && !device) | |
2124 { | |
2125 errmsg = (char_u *)_(e_fsync); | |
2126 end = 0; | |
2127 } | |
2128 #endif | |
2129 | |
2130 #if defined(HAVE_SELINUX) || defined(HAVE_SMACK) | |
2131 // Probably need to set the security context. | |
2132 if (!backup_copy) | |
2133 mch_copy_sec(backup, wfname); | |
2134 #endif | |
2135 | |
2136 #ifdef UNIX | |
2137 // When creating a new file, set its owner/group to that of the | |
2138 // original file. Get the new device and inode number. | |
2139 if (backup != NULL && !backup_copy) | |
2140 { | |
2141 # ifdef HAVE_FCHOWN | |
2142 stat_T st; | |
2143 | |
2144 // Don't change the owner when it's already OK, some systems remove | |
2145 // permission or ACL stuff. | |
2146 if (mch_stat((char *)wfname, &st) < 0 | |
2147 || st.st_uid != st_old.st_uid | |
2148 || st.st_gid != st_old.st_gid) | |
2149 { | |
2150 // changing owner might not be possible | |
2151 vim_ignored = fchown(fd, st_old.st_uid, -1); | |
2152 // if changing group fails clear the group permissions | |
2153 if (fchown(fd, -1, st_old.st_gid) == -1 && perm > 0) | |
2154 perm &= ~070; | |
2155 } | |
2156 # endif | |
2157 buf_setino(buf); | |
2158 } | |
2159 else if (!buf->b_dev_valid) | |
2160 // Set the inode when creating a new file. | |
2161 buf_setino(buf); | |
2162 #endif | |
2163 | |
2164 #ifdef UNIX | |
2165 if (made_writable) | |
2166 perm &= ~0200; // reset 'w' bit for security reasons | |
2167 #endif | |
2168 #ifdef HAVE_FCHMOD | |
2169 // set permission of new file same as old file | |
2170 if (perm >= 0) | |
2171 (void)mch_fsetperm(fd, perm); | |
2172 #endif | |
2173 if (close(fd) != 0) | |
2174 { | |
2175 errmsg = (char_u *)_("E512: Close failed"); | |
2176 end = 0; | |
2177 } | |
2178 | |
2179 #ifndef HAVE_FCHMOD | |
2180 // set permission of new file same as old file | |
2181 if (perm >= 0) | |
2182 (void)mch_setperm(wfname, perm); | |
2183 #endif | |
2184 #ifdef HAVE_ACL | |
2185 // Probably need to set the ACL before changing the user (can't set the | |
2186 // ACL on a file the user doesn't own). | |
2187 // On Solaris, with ZFS and the aclmode property set to "discard" (the | |
2188 // default), chmod() discards all part of a file's ACL that don't | |
2189 // represent the mode of the file. It's non-trivial for us to discover | |
2190 // whether we're in that situation, so we simply always re-set the ACL. | |
2191 # ifndef HAVE_SOLARIS_ZFS_ACL | |
2192 if (!backup_copy) | |
2193 # endif | |
2194 mch_set_acl(wfname, acl); | |
2195 #endif | |
2196 #ifdef FEAT_CRYPT | |
2197 if (buf->b_cryptstate != NULL) | |
2198 { | |
2199 crypt_free_state(buf->b_cryptstate); | |
2200 buf->b_cryptstate = NULL; | |
2201 } | |
2202 #endif | |
2203 | |
2204 #if defined(FEAT_EVAL) | |
2205 if (wfname != fname) | |
2206 { | |
2207 // The file was written to a temp file, now it needs to be | |
2208 // converted with 'charconvert' to (overwrite) the output file. | |
2209 if (end != 0) | |
2210 { | |
2211 if (eval_charconvert(enc_utf8 ? (char_u *)"utf-8" : p_enc, | |
2212 fenc, wfname, fname) == FAIL) | |
2213 { | |
2214 write_info.bw_conv_error = TRUE; | |
2215 end = 0; | |
2216 } | |
2217 } | |
2218 mch_remove(wfname); | |
2219 vim_free(wfname); | |
2220 } | |
2221 #endif | |
2222 } | |
2223 | |
2224 if (end == 0) | |
2225 { | |
2226 // Error encountered. | |
2227 if (errmsg == NULL) | |
2228 { | |
2229 if (write_info.bw_conv_error) | |
2230 { | |
2231 if (write_info.bw_conv_error_lnum == 0) | |
2232 errmsg = (char_u *)_("E513: write error, conversion failed (make 'fenc' empty to override)"); | |
2233 else | |
2234 { | |
2235 errmsg_allocated = TRUE; | |
2236 errmsg = alloc(300); | |
2237 vim_snprintf((char *)errmsg, 300, _("E513: write error, conversion failed in line %ld (make 'fenc' empty to override)"), | |
2238 (long)write_info.bw_conv_error_lnum); | |
2239 } | |
2240 } | |
2241 else if (got_int) | |
2242 errmsg = (char_u *)_(e_interr); | |
2243 else | |
2244 errmsg = (char_u *)_("E514: write error (file system full?)"); | |
2245 } | |
2246 | |
2247 // If we have a backup file, try to put it in place of the new file, | |
2248 // because the new file is probably corrupt. This avoids losing the | |
2249 // original file when trying to make a backup when writing the file a | |
2250 // second time. | |
2251 // When "backup_copy" is set we need to copy the backup over the new | |
2252 // file. Otherwise rename the backup file. | |
2253 // If this is OK, don't give the extra warning message. | |
2254 if (backup != NULL) | |
2255 { | |
2256 if (backup_copy) | |
2257 { | |
2258 // This may take a while, if we were interrupted let the user | |
2259 // know we got the message. | |
2260 if (got_int) | |
2261 { | |
2262 msg(_(e_interr)); | |
2263 out_flush(); | |
2264 } | |
2265 if ((fd = mch_open((char *)backup, O_RDONLY | O_EXTRA, 0)) >= 0) | |
2266 { | |
2267 if ((write_info.bw_fd = mch_open((char *)fname, | |
2268 O_WRONLY | O_CREAT | O_TRUNC | O_EXTRA, | |
2269 perm & 0777)) >= 0) | |
2270 { | |
2271 // copy the file. | |
2272 write_info.bw_buf = smallbuf; | |
2273 write_info.bw_flags = FIO_NOCONVERT; | |
2274 while ((write_info.bw_len = read_eintr(fd, smallbuf, | |
2275 SMALLBUFSIZE)) > 0) | |
2276 if (buf_write_bytes(&write_info) == FAIL) | |
2277 break; | |
2278 | |
2279 if (close(write_info.bw_fd) >= 0 | |
2280 && write_info.bw_len == 0) | |
2281 end = 1; // success | |
2282 } | |
2283 close(fd); // ignore errors for closing read file | |
2284 } | |
2285 } | |
2286 else | |
2287 { | |
2288 if (vim_rename(backup, fname) == 0) | |
2289 end = 1; | |
2290 } | |
2291 } | |
2292 goto fail; | |
2293 } | |
2294 | |
2295 lnum -= start; // compute number of written lines | |
2296 --no_wait_return; // may wait for return now | |
2297 | |
2298 #if !(defined(UNIX) || defined(VMS)) | |
2299 fname = sfname; // use shortname now, for the messages | |
2300 #endif | |
2301 if (!filtering) | |
2302 { | |
2303 msg_add_fname(buf, fname); // put fname in IObuff with quotes | |
2304 c = FALSE; | |
2305 if (write_info.bw_conv_error) | |
2306 { | |
2307 STRCAT(IObuff, _(" CONVERSION ERROR")); | |
2308 c = TRUE; | |
2309 if (write_info.bw_conv_error_lnum != 0) | |
2310 vim_snprintf_add((char *)IObuff, IOSIZE, _(" in line %ld;"), | |
2311 (long)write_info.bw_conv_error_lnum); | |
2312 } | |
2313 else if (notconverted) | |
2314 { | |
2315 STRCAT(IObuff, _("[NOT converted]")); | |
2316 c = TRUE; | |
2317 } | |
2318 else if (converted) | |
2319 { | |
2320 STRCAT(IObuff, _("[converted]")); | |
2321 c = TRUE; | |
2322 } | |
2323 if (device) | |
2324 { | |
2325 STRCAT(IObuff, _("[Device]")); | |
2326 c = TRUE; | |
2327 } | |
2328 else if (newfile) | |
2329 { | |
2330 STRCAT(IObuff, shortmess(SHM_NEW) ? _("[New]") : _("[New File]")); | |
2331 c = TRUE; | |
2332 } | |
2333 if (no_eol) | |
2334 { | |
2335 msg_add_eol(); | |
2336 c = TRUE; | |
2337 } | |
2338 // may add [unix/dos/mac] | |
2339 if (msg_add_fileformat(fileformat)) | |
2340 c = TRUE; | |
2341 #ifdef FEAT_CRYPT | |
2342 if (wb_flags & FIO_ENCRYPTED) | |
2343 { | |
2344 crypt_append_msg(buf); | |
2345 c = TRUE; | |
2346 } | |
2347 #endif | |
2348 msg_add_lines(c, (long)lnum, nchars); // add line/char count | |
2349 if (!shortmess(SHM_WRITE)) | |
2350 { | |
2351 if (append) | |
2352 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended")); | |
2353 else | |
2354 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [w]") : _(" written")); | |
2355 } | |
2356 | |
2357 set_keep_msg((char_u *)msg_trunc_attr((char *)IObuff, FALSE, 0), 0); | |
2358 } | |
2359 | |
2360 // When written everything correctly: reset 'modified'. Unless not | |
2361 // writing to the original file and '+' is not in 'cpoptions'. | |
2362 if (reset_changed && whole && !append | |
2363 && !write_info.bw_conv_error | |
2364 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL)) | |
2365 { | |
2366 unchanged(buf, TRUE, FALSE); | |
2367 // b:changedtick is may be incremented in unchanged() but that | |
2368 // should not trigger a TextChanged event. | |
2369 if (buf->b_last_changedtick + 1 == CHANGEDTICK(buf)) | |
2370 buf->b_last_changedtick = CHANGEDTICK(buf); | |
2371 u_unchanged(buf); | |
2372 u_update_save_nr(buf); | |
2373 } | |
2374 | |
2375 // If written to the current file, update the timestamp of the swap file | |
2376 // and reset the BF_WRITE_MASK flags. Also sets buf->b_mtime. | |
2377 if (overwriting) | |
2378 { | |
2379 ml_timestamp(buf); | |
2380 if (append) | |
2381 buf->b_flags &= ~BF_NEW; | |
2382 else | |
2383 buf->b_flags &= ~BF_WRITE_MASK; | |
2384 } | |
2385 | |
2386 // If we kept a backup until now, and we are in patch mode, then we make | |
2387 // the backup file our 'original' file. | |
2388 if (*p_pm && dobackup) | |
2389 { | |
2390 char *org = (char *)buf_modname((buf->b_p_sn || buf->b_shortname), | |
2391 fname, p_pm, FALSE); | |
2392 | |
2393 if (backup != NULL) | |
2394 { | |
2395 stat_T st; | |
2396 | |
2397 // If the original file does not exist yet | |
2398 // the current backup file becomes the original file | |
2399 if (org == NULL) | |
2400 emsg(_("E205: Patchmode: can't save original file")); | |
2401 else if (mch_stat(org, &st) < 0) | |
2402 { | |
2403 vim_rename(backup, (char_u *)org); | |
2404 VIM_CLEAR(backup); // don't delete the file | |
2405 #ifdef UNIX | |
2406 set_file_time((char_u *)org, st_old.st_atime, st_old.st_mtime); | |
2407 #endif | |
2408 } | |
2409 } | |
2410 // If there is no backup file, remember that a (new) file was | |
2411 // created. | |
2412 else | |
2413 { | |
2414 int empty_fd; | |
2415 | |
2416 if (org == NULL | |
2417 || (empty_fd = mch_open(org, | |
2418 O_CREAT | O_EXTRA | O_EXCL | O_NOFOLLOW, | |
2419 perm < 0 ? 0666 : (perm & 0777))) < 0) | |
2420 emsg(_("E206: patchmode: can't touch empty original file")); | |
2421 else | |
2422 close(empty_fd); | |
2423 } | |
2424 if (org != NULL) | |
2425 { | |
2426 mch_setperm((char_u *)org, mch_getperm(fname) & 0777); | |
2427 vim_free(org); | |
2428 } | |
2429 } | |
2430 | |
2431 // Remove the backup unless 'backup' option is set or there was a | |
2432 // conversion error. | |
2433 if (!p_bk && backup != NULL && !write_info.bw_conv_error | |
2434 && mch_remove(backup) != 0) | |
2435 emsg(_("E207: Can't delete backup file")); | |
2436 | |
2437 goto nofail; | |
2438 | |
2439 // Finish up. We get here either after failure or success. | |
2440 fail: | |
2441 --no_wait_return; // may wait for return now | |
2442 nofail: | |
2443 | |
2444 // Done saving, we accept changed buffer warnings again | |
2445 buf->b_saving = FALSE; | |
2446 | |
2447 vim_free(backup); | |
2448 if (buffer != smallbuf) | |
2449 vim_free(buffer); | |
2450 vim_free(fenc_tofree); | |
2451 vim_free(write_info.bw_conv_buf); | |
2452 #ifdef USE_ICONV | |
2453 if (write_info.bw_iconv_fd != (iconv_t)-1) | |
2454 { | |
2455 iconv_close(write_info.bw_iconv_fd); | |
2456 write_info.bw_iconv_fd = (iconv_t)-1; | |
2457 } | |
2458 #endif | |
2459 #ifdef HAVE_ACL | |
2460 mch_free_acl(acl); | |
2461 #endif | |
2462 | |
2463 if (errmsg != NULL) | |
2464 { | |
2465 int numlen = errnum != NULL ? (int)STRLEN(errnum) : 0; | |
2466 | |
2467 attr = HL_ATTR(HLF_E); // set highlight for error messages | |
2468 msg_add_fname(buf, | |
2469 #ifndef UNIX | |
2470 sfname | |
2471 #else | |
2472 fname | |
2473 #endif | |
2474 ); // put file name in IObuff with quotes | |
2475 if (STRLEN(IObuff) + STRLEN(errmsg) + numlen >= IOSIZE) | |
2476 IObuff[IOSIZE - STRLEN(errmsg) - numlen - 1] = NUL; | |
2477 // If the error message has the form "is ...", put the error number in | |
2478 // front of the file name. | |
2479 if (errnum != NULL) | |
2480 { | |
2481 STRMOVE(IObuff + numlen, IObuff); | |
2482 mch_memmove(IObuff, errnum, (size_t)numlen); | |
2483 } | |
2484 STRCAT(IObuff, errmsg); | |
2485 emsg((char *)IObuff); | |
2486 if (errmsg_allocated) | |
2487 vim_free(errmsg); | |
2488 | |
2489 retval = FAIL; | |
2490 if (end == 0) | |
2491 { | |
2492 msg_puts_attr(_("\nWARNING: Original file may be lost or damaged\n"), | |
2493 attr | MSG_HIST); | |
2494 msg_puts_attr(_("don't quit the editor until the file is successfully written!"), | |
2495 attr | MSG_HIST); | |
2496 | |
2497 // Update the timestamp to avoid an "overwrite changed file" | |
2498 // prompt when writing again. | |
2499 if (mch_stat((char *)fname, &st_old) >= 0) | |
2500 { | |
2501 buf_store_time(buf, &st_old, fname); | |
2502 buf->b_mtime_read = buf->b_mtime; | |
2503 } | |
2504 } | |
2505 } | |
2506 msg_scroll = msg_save; | |
2507 | |
2508 #ifdef FEAT_PERSISTENT_UNDO | |
2509 // When writing the whole file and 'undofile' is set, also write the undo | |
2510 // file. | |
2511 if (retval == OK && write_undo_file) | |
2512 { | |
2513 char_u hash[UNDO_HASH_SIZE]; | |
2514 | |
2515 sha256_finish(&sha_ctx, hash); | |
2516 u_write_undo(NULL, FALSE, buf, hash); | |
2517 } | |
2518 #endif | |
2519 | |
2520 #ifdef FEAT_EVAL | |
2521 if (!should_abort(retval)) | |
2522 #else | |
2523 if (!got_int) | |
2524 #endif | |
2525 { | |
2526 aco_save_T aco; | |
2527 | |
2528 curbuf->b_no_eol_lnum = 0; // in case it was set by the previous read | |
2529 | |
2530 // Apply POST autocommands. | |
2531 // Careful: The autocommands may call buf_write() recursively! | |
2532 aucmd_prepbuf(&aco, buf); | |
2533 | |
2534 if (append) | |
2535 apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname, | |
2536 FALSE, curbuf, eap); | |
2537 else if (filtering) | |
2538 apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname, | |
2539 FALSE, curbuf, eap); | |
2540 else if (reset_changed && whole) | |
2541 apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname, | |
2542 FALSE, curbuf, eap); | |
2543 else | |
2544 apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname, | |
2545 FALSE, curbuf, eap); | |
2546 | |
2547 // restore curwin/curbuf and a few other things | |
2548 aucmd_restbuf(&aco); | |
2549 | |
2550 #ifdef FEAT_EVAL | |
2551 if (aborting()) // autocmds may abort script processing | |
2552 retval = FALSE; | |
2553 #endif | |
2554 } | |
2555 | |
2556 got_int |= prev_got_int; | |
2557 | |
2558 return retval; | |
2559 } |