Annotation of src/usr.bin/vim/fileio.c, Revision 1.1.1.1
1.1 downsj 1: /* $OpenBSD$ */
2: /* vi:set ts=4 sw=4:
3: *
4: * VIM - Vi IMproved by Bram Moolenaar
5: *
6: * Do ":help uganda" in Vim to read copying and usage conditions.
7: * Do ":help credits" in Vim to see a list of people who contributed.
8: */
9:
10: /*
11: * fileio.c: read from and write to a file
12: */
13:
14: #if defined MSDOS || defined WIN32
15: # include <io.h> /* for lseek(), must be before vim.h */
16: #endif
17:
18: #include "vim.h"
19: #include "globals.h"
20: #include "proto.h"
21: #include "option.h"
22: #ifdef HAVE_FCNTL_H
23: # include <fcntl.h>
24: #endif
25:
26: #ifdef LATTICE
27: # include <proto/dos.h> /* for Lock() and UnLock() */
28: #endif
29:
30: #define BUFSIZE 8192 /* size of normal write buffer */
31: #define SBUFSIZE 256 /* size of emergency write buffer */
32:
33: #ifdef VIMINFO
34: static void check_marks_read __ARGS((void));
35: #endif
36: static void msg_add_fname __ARGS((BUF *, char_u *));
37: static int msg_add_textmode __ARGS((int));
38: static void msg_add_lines __ARGS((int, long, long));
39: static int write_buf __ARGS((int, char_u *, int));
40:
41: static linenr_t write_no_eol_lnum = 0; /* non-zero lnum when last line of
42: next binary write should not have
43: an eol */
44:
45: void
46: filemess(buf, name, s)
47: BUF *buf;
48: char_u *name;
49: char_u *s;
50: {
51: msg_add_fname(buf, name); /* put file name in IObuff with quotes */
52: STRCAT(IObuff, s);
53: /*
54: * For the first message may have to start a new line.
55: * For further ones overwrite the previous one, reset msg_scroll before
56: * calling filemess().
57: */
58: msg_start();
59: msg_outtrans(IObuff);
60: stop_highlight();
61: msg_clr_eos();
62: flushbuf();
63: }
64:
65: /*
66: * Read lines from file 'fname' into the buffer after line 'from'.
67: *
68: * 1. We allocate blocks with lalloc, as big as possible.
69: * 2. Each block is filled with characters from the file with a single read().
70: * 3. The lines are inserted in the buffer with ml_append().
71: *
72: * (caller must check that fname != NULL)
73: *
74: * lines_to_skip is the number of lines that must be skipped
75: * lines_to_read is the number of lines that are appended
76: * When not recovering lines_to_skip is 0 and lines_to_read MAXLNUM.
77: *
78: * return FAIL for failure, OK otherwise
79: */
80: int
81: readfile(fname, sfname, from, newfile, lines_to_skip, lines_to_read, filtering)
82: char_u *fname;
83: char_u *sfname;
84: linenr_t from;
85: int newfile;
86: linenr_t lines_to_skip;
87: linenr_t lines_to_read;
88: int filtering;
89: {
90: int fd;
91: register char_u c;
92: register linenr_t lnum = from;
93: register char_u *ptr = NULL; /* pointer into read buffer */
94: register char_u *buffer = NULL; /* read buffer */
95: char_u *new_buffer = NULL; /* init to shut up gcc */
96: char_u *line_start = NULL; /* init to shut up gcc */
97: colnr_t len;
98: register long size;
99: register char_u *p;
100: long filesize = 0;
101: int split = 0; /* number of split lines */
102: #define UNKNOWN 0x0fffffff /* file size is unknown */
103: linenr_t linecnt = curbuf->b_ml.ml_line_count;
104: int error = FALSE; /* errors encountered */
105: int tx_error = FALSE; /* textmode, but no CR */
106: long linerest = 0; /* remaining characters in line */
107: int firstpart = TRUE; /* reading first part */
108: #ifdef UNIX
109: int perm;
110: #endif
111: int textmode; /* accept CR-LF linebreak */
112: struct stat st;
113: int file_readonly;
114: linenr_t skip_count = lines_to_skip;
115: linenr_t read_count = lines_to_read;
116: int msg_save = msg_scroll;
117: linenr_t read_no_eol_lnum = 0; /* non-zero lnum when last
118: line of last read was
119: missing the eol */
120:
121:
122: /*
123: * If there is no file name yet, use the one for the read file.
124: * b_notedited is set to reflect this.
125: * Don't do this for a read from a filter.
126: * Only do this when 'cpoptions' contains the 'f' flag.
127: */
128: if (curbuf->b_filename == NULL && !filtering &&
129: vim_strchr(p_cpo, CPO_FNAMER) != NULL)
130: {
131: if (setfname(fname, sfname, FALSE) == OK)
132: curbuf->b_notedited = TRUE;
133: }
134:
135: if (shortmess(SHM_OVER) || curbuf->b_help)
136: msg_scroll = FALSE; /* overwrite previous file message */
137: else
138: msg_scroll = TRUE; /* don't overwrite previous file message */
139: if (sfname == NULL)
140: sfname = fname;
141: /*
142: * For Unix: Use the short filename whenever possible.
143: * Avoids problems with networks and when directory names are changed.
144: * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
145: * another directory, which we don't detect.
146: */
147: #if defined(UNIX) || defined(__EMX__)
148: if (!did_cd)
149: fname = sfname;
150: #endif
151:
152: #ifdef UNIX
153: /*
154: * On Unix it is possible to read a directory, so we have to
155: * check for it before the open().
156: */
157: perm = getperm(fname);
158: # ifdef _POSIX_SOURCE
159: if (perm >= 0 && !S_ISREG(perm) /* not a regular file ... */
160: # ifdef S_ISFIFO
161: && !S_ISFIFO(perm) /* ... or fifo or socket */
162: # endif
163: )
164: # else
165: if (perm >= 0 && (perm & S_IFMT) != S_IFREG /* not a regular file ... */
166: # ifdef S_IFIFO
167: && (perm & S_IFMT) != S_IFIFO /* ... or fifo ... */
168: # endif
169: # ifdef S_IFSOCK
170: && (perm & S_IFMT) != S_IFSOCK /* ... or socket */
171: # endif
172: )
173: # endif
174: {
175: # ifdef _POSIX_SOURCE
176: if (S_ISDIR(perm))
177: # else
178: if ((perm & S_IFMT) == S_IFDIR)
179: # endif
180: filemess(curbuf, fname, (char_u *)"is a directory");
181: else
182: filemess(curbuf, fname, (char_u *)"is not a file");
183: msg_scroll = msg_save;
184: return FAIL;
185: }
186: #endif
187:
188: /*
189: * When opening a new file we take the readonly flag from the file.
190: * Default is r/w, can be set to r/o below.
191: * Don't reset it when in readonly mode
192: */
193: if (newfile && !readonlymode) /* default: set file not readonly */
194: curbuf->b_p_ro = FALSE;
195:
196: if (newfile)
197: {
198: if (stat((char *)fname, &st) >= 0) /* remember time of file */
199: {
200: curbuf->b_mtime = st.st_mtime;
201: curbuf->b_mtime_read = st.st_mtime;
202: #ifdef UNIX
203: /*
204: * Set the protection bits of the swap file equal to the original
205: * file. This makes it possible for others to read the name of the
206: * original file from the swapfile.
207: */
208: if (curbuf->b_ml.ml_mfp->mf_fname != NULL)
209: (void)setperm(curbuf->b_ml.ml_mfp->mf_fname,
210: (st.st_mode & 0777) | 0600);
211: #endif
212: }
213: else
214: {
215: curbuf->b_mtime = 0;
216: curbuf->b_mtime_read = 0;
217: }
218: }
219:
220: /*
221: * for UNIX: check readonly with perm and access()
222: * for MSDOS and Amiga: check readonly by trying to open the file for writing
223: */
224: file_readonly = FALSE;
225: #if defined(UNIX) || defined(DJGPP) || defined(__EMX__)
226: if (
227: # ifdef UNIX
228: !(perm & 0222) ||
229: # endif
230: access((char *)fname, W_OK))
231: file_readonly = TRUE;
232: fd = open((char *)fname, O_RDONLY | O_EXTRA);
233: #else
234: if (!newfile || readonlymode || (fd =
235: open((char *)fname, O_RDWR | O_EXTRA)) < 0)
236: {
237: file_readonly = TRUE;
238: fd = open((char *)fname, O_RDONLY | O_EXTRA); /* try to open ro */
239: }
240: #endif
241:
242: if (fd < 0) /* cannot open at all */
243: {
244: #ifndef UNIX
245: int isdir_f;
246: #endif
247: msg_scroll = msg_save;
248: #ifndef UNIX
249: /*
250: * On MSDOS and Amiga we can't open a directory, check here.
251: */
252: isdir_f = (mch_isdir(fname));
253: /* replace with short name now, for the messages */
254: if (!did_cd)
255: fname = sfname;
256: if (isdir_f)
257: filemess(curbuf, fname, (char_u *)"is a directory");
258: else
259: #endif
260: if (newfile)
261: {
262: #ifdef UNIX
263: if (perm < 0)
264: #endif
265: {
266: filemess(curbuf, fname, (char_u *)"[New File]");
267: #ifdef AUTOCMD
268: apply_autocmds(EVENT_BUFNEWFILE, fname, fname);
269: #endif
270: return OK; /* a new file is not an error */
271: }
272: #ifdef UNIX
273: else
274: filemess(curbuf, fname, (char_u *)"[Permission Denied]");
275: #endif
276: }
277:
278: return FAIL;
279: }
280:
281: /*
282: * Only set the 'ro' flag for readonly files the first time they are
283: * loaded.
284: * Help files always get readonly mode
285: */
286: if ((newfile && file_readonly) || curbuf->b_help)
287: curbuf->b_p_ro = TRUE;
288:
289: if (newfile)
290: curbuf->b_p_eol = TRUE;
291:
292: #ifndef UNIX
293: /* replace with short name now, for the messages */
294: if (!did_cd)
295: fname = sfname;
296: #endif
297: ++no_wait_return; /* don't wait for return yet */
298:
299: /*
300: * Set '[ mark to the line above where the lines go (line 1 if zero).
301: */
302: curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
303: curbuf->b_op_start.col = 0;
304:
305: #ifdef AUTOCMD
306: {
307: int m = msg_scroll;
308: int n = msg_scrolled;
309:
310: /*
311: * The output from the autocommands should not overwrite anything and
312: * should not be overwritten: Set msg_scroll, restore its value if no
313: * output was done.
314: */
315: msg_scroll = TRUE;
316: if (filtering)
317: apply_autocmds(EVENT_FILTERREADPRE, NULL, fname);
318: else if (newfile)
319: apply_autocmds(EVENT_BUFREADPRE, NULL, fname);
320: else
321: apply_autocmds(EVENT_FILEREADPRE, fname, fname);
322: if (msg_scrolled == n)
323: msg_scroll = m;
324: }
325: #endif
326:
327: if (!recoverymode && !filtering)
328: filemess(curbuf, fname, (char_u *)""); /* show that we are busy */
329:
330: msg_scroll = FALSE; /* overwrite the file message */
331:
332: /*
333: * Set textmode now, before the "retry" caused by 'textauto' and after the
334: * autocommands, that may reset it.
335: */
336: textmode = curbuf->b_p_tx;
337:
338: retry:
339: while (!error && !got_int)
340: {
341: /*
342: * We allocate as much space for the file as we can get, plus
343: * space for the old line plus room for one terminating NUL.
344: * The amount is limited by the fact that read() only can read
345: * upto max_unsigned characters (and other things).
346: */
347: #if SIZEOF_INT <= 2
348: if (linerest >= 0x7ff0)
349: {
350: ++split;
351: *ptr = NL; /* split line by inserting a NL */
352: size = 1;
353: }
354: else
355: #endif
356: {
357: #if SIZEOF_INT > 2
358: size = 0x10000L; /* use buffer >= 64K */
359: #else
360: size = 0x7ff0L - linerest; /* limit buffer to 32K */
361: #endif
362:
363: for ( ; size >= 10; size >>= 1)
364: {
365: if ((new_buffer = lalloc((long_u)(size + linerest + 1), FALSE)) != NULL)
366: break;
367: }
368: if (new_buffer == NULL)
369: {
370: do_outofmem_msg();
371: error = TRUE;
372: break;
373: }
374: if (linerest) /* copy characters from the previous buffer */
375: vim_memmove(new_buffer, ptr - linerest, (size_t)linerest);
376: vim_free(buffer);
377: buffer = new_buffer;
378: ptr = buffer + linerest;
379: line_start = buffer;
380:
381: if ((size = read(fd, (char *)ptr, (size_t)size)) <= 0)
382: {
383: if (size < 0) /* read error */
384: error = TRUE;
385: break;
386: }
387: filesize += size; /* count the number of characters */
388:
389: /*
390: * when reading the first part of a file: guess EOL type
391: */
392: if (firstpart && p_ta)
393: {
394: for (p = ptr; p < ptr + size; ++p)
395: if (*p == NL)
396: {
397: if (p > ptr && p[-1] == CR) /* found CR-NL */
398: textmode = TRUE;
399: else /* found a single NL */
400: textmode = FALSE;
401: /* if editing a new file: may set p_tx */
402: if (newfile)
403: curbuf->b_p_tx = textmode;
404: break;
405: }
406: }
407: }
408:
409: firstpart = FALSE;
410:
411: /*
412: * This loop is executed once for every character read.
413: * Keep it fast!
414: */
415: --ptr;
416: while (++ptr, --size >= 0)
417: {
418: if ((c = *ptr) != NUL && c != NL) /* catch most common case */
419: continue;
420: if (c == NUL)
421: *ptr = NL; /* NULs are replaced by newlines! */
422: else
423: {
424: if (skip_count == 0)
425: {
426: *ptr = NUL; /* end of line */
427: len = ptr - line_start + 1;
428: if (textmode)
429: {
430: if (ptr[-1] == CR) /* remove CR */
431: {
432: ptr[-1] = NUL;
433: --len;
434: }
435: /*
436: * Reading in textmode, but no CR-LF found!
437: * When 'textauto' set, delete all the lines read so
438: * far and start all over again.
439: * Otherwise give an error message later.
440: */
441: else if (!tx_error)
442: {
443: if (p_ta && lseek(fd, 0L, SEEK_SET) == 0)
444: {
445: while (lnum > from)
446: ml_delete(lnum--, FALSE);
447: textmode = FALSE;
448: if (newfile)
449: curbuf->b_p_tx = FALSE;
450: linerest = 0;
451: filesize = 0;
452: skip_count = lines_to_skip;
453: read_count = lines_to_read;
454: goto retry;
455: }
456: else
457: tx_error = TRUE;
458: }
459: }
460: if (ml_append(lnum, line_start, len, newfile) == FAIL)
461: {
462: error = TRUE;
463: break;
464: }
465: ++lnum;
466: if (--read_count == 0)
467: {
468: error = TRUE; /* break loop */
469: line_start = ptr; /* nothing left to write */
470: break;
471: }
472: }
473: else
474: --skip_count;
475: line_start = ptr + 1;
476: }
477: }
478: linerest = ptr - line_start;
479: mch_breakcheck();
480: }
481:
482: /* not an error, max. number of lines reached */
483: if (error && read_count == 0)
484: error = FALSE;
485:
486: /*
487: * If we get EOF in the middle of a line, note the fact and
488: * complete the line ourselves.
489: * In textmode ignore a trailing CTRL-Z, unless 'binary' set.
490: */
491: if (!error && !got_int && linerest != 0 &&
492: !(!curbuf->b_p_bin && textmode &&
493: *line_start == Ctrl('Z') && ptr == line_start + 1))
494: {
495: if (newfile) /* remember for when writing */
496: curbuf->b_p_eol = FALSE;
497: *ptr = NUL;
498: if (ml_append(lnum, line_start,
499: (colnr_t)(ptr - line_start + 1), newfile) == FAIL)
500: error = TRUE;
501: else
502: read_no_eol_lnum = ++lnum;
503: }
504: if (lnum != from && !newfile) /* added at least one line */
505: CHANGED;
506:
507: close(fd); /* errors are ignored */
508: vim_free(buffer);
509:
510: --no_wait_return; /* may wait for return now */
511:
512: /* in recovery mode everything but autocommands are skipped */
513: if (!recoverymode)
514: {
515:
516: /* need to delete the last line, which comes from the empty buffer */
517: if (newfile && !(curbuf->b_ml.ml_flags & ML_EMPTY))
518: {
519: ml_delete(curbuf->b_ml.ml_line_count, FALSE);
520: --linecnt;
521: }
522: linecnt = curbuf->b_ml.ml_line_count - linecnt;
523: if (filesize == 0)
524: linecnt = 0;
525: if (!newfile)
526: mark_adjust(from + 1, MAXLNUM, (long)linecnt, 0L);
527:
528: if (got_int)
529: {
530: filemess(curbuf, fname, e_interr);
531: msg_scroll = msg_save;
532: #ifdef VIMINFO
533: check_marks_read();
534: #endif /* VIMINFO */
535: return OK; /* an interrupt isn't really an error */
536: }
537:
538: if (!filtering)
539: {
540: msg_add_fname(curbuf, fname); /* fname in IObuff with quotes */
541: c = FALSE;
542:
543: #ifdef UNIX
544: # ifdef S_ISFIFO
545: if (S_ISFIFO(perm)) /* fifo or socket */
546: {
547: STRCAT(IObuff, "[fifo/socket]");
548: c = TRUE;
549: }
550: # else
551: # ifdef S_IFIFO
552: if ((perm & S_IFMT) == S_IFIFO) /* fifo */
553: {
554: STRCAT(IObuff, "[fifo]");
555: c = TRUE;
556: }
557: # endif
558: # ifdef S_IFSOCK
559: if ((perm & S_IFMT) == S_IFSOCK) /* or socket */
560: {
561: STRCAT(IObuff, "[socket]");
562: c = TRUE;
563: }
564: # endif
565: # endif
566: #endif
567: if (curbuf->b_p_ro)
568: {
569: STRCAT(IObuff, shortmess(SHM_RO) ? "[RO]" : "[readonly]");
570: c = TRUE;
571: }
572: if (read_no_eol_lnum)
573: {
574: STRCAT(IObuff, shortmess(SHM_LAST) ? "[noeol]" :
575: "[Incomplete last line]");
576: c = TRUE;
577: }
578: if (tx_error)
579: {
580: STRCAT(IObuff, "[CR missing]");
581: c = TRUE;
582: }
583: if (split)
584: {
585: STRCAT(IObuff, "[long lines split]");
586: c = TRUE;
587: }
588: if (error)
589: {
590: STRCAT(IObuff, "[READ ERRORS]");
591: c = TRUE;
592: }
593: if (msg_add_textmode(textmode))
594: c = TRUE;
595: msg_add_lines(c, (long)linecnt, filesize);
596: msg_trunc(IObuff);
597: }
598:
599: if (error && newfile) /* with errors we should not write the file */
600: curbuf->b_p_ro = TRUE;
601:
602: u_clearline(); /* cannot use "U" command after adding lines */
603:
604: if (from < curbuf->b_ml.ml_line_count)
605: {
606: curwin->w_cursor.lnum = from + 1; /* cursor at first new line */
607: beginline(TRUE); /* on first non-blank */
608: }
609:
610: /*
611: * Set '[ and '] marks to the newly read lines.
612: */
613: curbuf->b_op_start.lnum = from + 1;
614: curbuf->b_op_start.col = 0;
615: curbuf->b_op_end.lnum = from + linecnt;
616: curbuf->b_op_end.col = 0;
617: }
618: msg_scroll = msg_save;
619:
620: #ifdef AUTOCMD
621: {
622: int m = msg_scroll;
623: int n = msg_scrolled;
624:
625: /*
626: * Trick: We remember if the last line of the read didn't have
627: * an eol for when writing it again. This is required for
628: * ":autocmd FileReadPost *.gz set bin|%!gunzip" to work.
629: */
630: write_no_eol_lnum = read_no_eol_lnum;
631:
632: /*
633: * The output from the autocommands should not overwrite anything and
634: * should not be overwritten: Set msg_scroll, restore its value if no
635: * output was done.
636: */
637: msg_scroll = TRUE;
638: if (filtering)
639: apply_autocmds(EVENT_FILTERREADPOST, NULL, fname);
640: else if (newfile)
641: apply_autocmds(EVENT_BUFREADPOST, NULL, fname);
642: else
643: apply_autocmds(EVENT_FILEREADPOST, fname, fname);
644: if (msg_scrolled == n)
645: msg_scroll = m;
646:
647: write_no_eol_lnum = 0;
648: }
649: #endif
650:
651: #ifdef VIMINFO
652: check_marks_read();
653: #endif /* VIMINFO */
654:
655: if (recoverymode && error)
656: return FAIL;
657: return OK;
658: }
659:
660: #ifdef VIMINFO
661: static void
662: check_marks_read()
663: {
664: if (!curbuf->b_marks_read && get_viminfo_parameter('\'') > 0)
665: {
666: read_viminfo(NULL, FALSE, TRUE, FALSE);
667: curbuf->b_marks_read = TRUE;
668: }
669: }
670: #endif /* VIMINFO */
671:
672: /*
673: * writeit - write to file 'fname' lines 'start' through 'end'
674: *
675: * We do our own buffering here because fwrite() is so slow.
676: *
677: * If forceit is true, we don't care for errors when attempting backups (jw).
678: * In case of an error everything possible is done to restore the original file.
679: * But when forceit is TRUE, we risk loosing it.
680: * When reset_changed is TRUE and start == 1 and end ==
681: * curbuf->b_ml.ml_line_count, reset curbuf->b_changed.
682: *
683: * This function must NOT use NameBuff (because it's called by autowrite()).
684: *
685: * return FAIL for failure, OK otherwise
686: */
687: int
688: buf_write(buf, fname, sfname, start, end, append, forceit,
689: reset_changed, filtering)
690: BUF *buf;
691: char_u *fname;
692: char_u *sfname;
693: linenr_t start, end;
694: int append;
695: int forceit;
696: int reset_changed;
697: int filtering;
698: {
699: int fd;
700: char_u *backup = NULL;
701: char_u *ffname;
702: #ifdef AUTOCMD
703: BUF *save_buf;
704: #endif
705: register char_u *s;
706: register char_u *ptr;
707: register char_u c;
708: register int len;
709: register linenr_t lnum;
710: long nchars;
711: char_u *errmsg = NULL;
712: char_u *buffer;
713: char_u smallbuf[SBUFSIZE];
714: char_u *backup_ext;
715: int bufsize;
716: long perm = -1; /* file permissions */
717: int retval = OK;
718: int newfile = FALSE; /* TRUE if file doesn't exist yet */
719: int msg_save = msg_scroll;
720: int overwriting; /* TRUE if writing over original */
721: #if defined(UNIX) || defined(__EMX__XX) /*XXX fix me sometime? */
722: struct stat st_old;
723: int made_writable = FALSE; /* 'w' bit has been set */
724: #endif
725: #ifdef AMIGA
726: BPTR flock;
727: #endif
728: /* writing everything */
729: int whole = (start == 1 && end == buf->b_ml.ml_line_count);
730: #ifdef AUTOCMD
731: linenr_t old_line_count = buf->b_ml.ml_line_count;
732: #endif
733:
734: if (fname == NULL || *fname == NUL) /* safety check */
735: return FAIL;
736:
737: /*
738: * If there is no file name yet, use the one for the written file.
739: * b_notedited is set to reflect this (in case the write fails).
740: * Don't do this when the write is for a filter command.
741: * Only do this when 'cpoptions' contains the 'f' flag.
742: */
743: if (reset_changed && whole && buf == curbuf &&
744: curbuf->b_filename == NULL && !filtering &&
745: vim_strchr(p_cpo, CPO_FNAMEW) != NULL)
746: {
747: if (setfname(fname, sfname, FALSE) == OK)
748: curbuf->b_notedited = TRUE;
749: }
750:
751: if (sfname == NULL)
752: sfname = fname;
753: /*
754: * For Unix: Use the short filename whenever possible.
755: * Avoids problems with networks and when directory names are changed.
756: * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
757: * another directory, which we don't detect
758: */
759: ffname = fname; /* remember full fname */
760: #ifdef UNIX
761: if (!did_cd)
762: fname = sfname;
763: #endif
764:
765: /* make sure we have a valid backup extension to use */
766: if (*p_bex == NUL)
767: backup_ext = (char_u *)".bak";
768: else
769: backup_ext = p_bex;
770:
771: if (buf->b_filename != NULL && fnamecmp(ffname, buf->b_filename) == 0)
772: overwriting = TRUE;
773: else
774: overwriting = FALSE;
775:
776: /*
777: * Disallow writing from .exrc and .vimrc in current directory for
778: * security reasons.
779: */
780: if (secure)
781: {
782: secure = 2;
783: emsg(e_curdir);
784: return FAIL;
785: }
786:
787: if (exiting)
788: settmode(0); /* when exiting allow typahead now */
789:
790: ++no_wait_return; /* don't wait for return yet */
791:
792: /*
793: * Set '[ and '] marks to the lines to be written.
794: */
795: buf->b_op_start.lnum = start;
796: buf->b_op_start.col = 0;
797: buf->b_op_end.lnum = end;
798: buf->b_op_end.col = 0;
799:
800: #ifdef AUTOCMD
801: /*
802: * Apply PRE aucocommands.
803: * Careful: The autocommands may call buf_write() recursively!
804: */
805: save_buf = curbuf;
806: curbuf = buf;
807: curwin->w_buffer = buf;
808: if (append)
809: apply_autocmds(EVENT_FILEAPPENDPRE, fname, fname);
810: else if (filtering)
811: apply_autocmds(EVENT_FILTERWRITEPRE, NULL, fname);
812: else if (reset_changed && whole)
813: apply_autocmds(EVENT_BUFWRITEPRE, fname, fname);
814: else
815: apply_autocmds(EVENT_FILEWRITEPRE, fname, fname);
816: curbuf = save_buf;
817: curwin->w_buffer = save_buf;
818:
819: /*
820: * The autocommands may have changed the number of lines in the file.
821: * When writing the whole file, adjust the end.
822: * When writing part of the file, assume that the autocommands only
823: * changed the number of lines that are to be written (tricky!).
824: */
825: if (buf->b_ml.ml_line_count != old_line_count)
826: {
827: if (whole) /* writing all */
828: end = buf->b_ml.ml_line_count;
829: else if (buf->b_ml.ml_line_count > old_line_count) /* more lines */
830: end += buf->b_ml.ml_line_count - old_line_count;
831: else /* less lines */
832: {
833: end -= old_line_count - buf->b_ml.ml_line_count;
834: if (end < start)
835: {
836: --no_wait_return;
837: EMSG("Autocommand changed number of lines in unexpected way");
838: return FAIL;
839: }
840: }
841: }
842: #endif
843:
844: if (shortmess(SHM_OVER))
845: msg_scroll = FALSE; /* overwrite previous file message */
846: else
847: msg_scroll = TRUE; /* don't overwrite previous file message */
848: if (!filtering)
849: filemess(buf,
850: #ifndef UNIX
851: did_cd ? fname : sfname,
852: #else
853: fname,
854: #endif
855: (char_u *)""); /* show that we are busy */
856: msg_scroll = FALSE; /* always overwrite the file message now */
857:
858: buffer = alloc(BUFSIZE);
859: if (buffer == NULL) /* can't allocate big buffer, use small
860: * one (to be able to write when out of
861: * memory) */
862: {
863: buffer = smallbuf;
864: bufsize = SBUFSIZE;
865: }
866: else
867: bufsize = BUFSIZE;
868:
869: #if defined(UNIX) && !defined(ARCHIE)
870: /* get information about original file (if there is one) */
871: st_old.st_dev = st_old.st_ino = 0;
872: if (stat((char *)fname, &st_old))
873: newfile = TRUE;
874: else
875: {
876: #ifdef _POSIX_SOURCE
877: if (!S_ISREG(st_old.st_mode)) /* not a file */
878: #else
879: if ((st_old.st_mode & S_IFMT) != S_IFREG) /* not a file */
880: #endif
881: {
882: #ifdef _POSIX_SOURCE
883: if (S_ISDIR(st_old.st_mode))
884: #else
885: if ((st_old.st_mode & S_IFMT) == S_IFDIR)
886: #endif
887: errmsg = (char_u *)"is a directory";
888: else
889: errmsg = (char_u *)"is not a file";
890: goto fail;
891: }
892: if (buf->b_mtime_read != 0 &&
893: buf->b_mtime_read != st_old.st_mtime && overwriting)
894: {
895: msg_scroll = TRUE; /* don't overwrite messages here */
896: (void)set_highlight('e'); /* set highlight for error messages */
897: msg_highlight = TRUE;
898: /* don't use emsg() here, don't want to flush the buffers */
899: MSG("WARNING: The file has been changed since reading it!!!");
900: if (ask_yesno((char_u *)"Do you really want to write to it",
901: TRUE) == 'n')
902: {
903: retval = FAIL;
904: goto fail;
905: }
906: msg_scroll = FALSE; /* always overwrite the file message now */
907: }
908: perm = st_old.st_mode;
909: }
910: /*
911: * If we are not appending, the file exists, and the 'writebackup', 'backup'
912: * or 'patchmode' option is set, try to make a backup copy of the file.
913: */
914: if (!append && perm >= 0 && (p_wb || p_bk || *p_pm != NUL) &&
915: (fd = open((char *)fname, O_RDONLY | O_EXTRA)) >= 0)
916: {
917: int bfd, buflen;
918: char_u copybuf[BUFSIZE + 1], *wp;
919: int some_error = FALSE;
920: struct stat st_new;
921: char_u *dirp;
922: #ifndef SHORT_FNAME
923: int did_set_shortname;
924: #endif
925:
926: /*
927: * Try to make the backup in each directory in the 'bdir' option.
928: *
929: * Unix semantics has it, that we may have a writable file,
930: * that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
931: * - the directory is not writable,
932: * - the file may be a symbolic link,
933: * - the file may belong to another user/group, etc.
934: *
935: * For these reasons, the existing writable file must be truncated
936: * and reused. Creation of a backup COPY will be attempted.
937: */
938: dirp = p_bdir;
939: while (*dirp)
940: {
941: st_new.st_dev = st_new.st_ino = 0;
942: st_new.st_gid = 0;
943:
944: /*
945: * Isolate one directory name.
946: */
947: len = copy_option_part(&dirp, copybuf, BUFSIZE, ",");
948:
949: if (*copybuf == '.') /* use same dir as file */
950: STRCPY(copybuf, fname);
951: else /* use dir from 'bdir' option */
952: {
953: if (!ispathsep(copybuf[len - 1]))
954: copybuf[len++] = PATHSEP;
955: STRCPY(copybuf + len, gettail(fname));
956: }
957:
958: #ifndef SHORT_FNAME
959: did_set_shortname = FALSE;
960: #endif
961:
962: /*
963: * May try twice if 'shortname' not set.
964: */
965: for (;;)
966: {
967: /*
968: * Make backup file name.
969: */
970: backup = buf_modname(buf, copybuf, backup_ext);
971: if (backup == NULL)
972: {
973: some_error = TRUE; /* out of memory */
974: goto nobackup;
975: }
976:
977: /*
978: * Check if backup file already exists.
979: */
980: if (!stat((char *)backup, &st_new))
981: {
982: /*
983: * Check if backup file is same as original file.
984: * May happen when modname gave the same file back.
985: * E.g. silly link, or filename-length reached.
986: * If we don't check here, we either ruin the file when
987: * copying or erase it after writing. jw.
988: */
989: if (st_new.st_dev == st_old.st_dev &&
990: st_new.st_ino == st_old.st_ino)
991: {
992: vim_free(backup);
993: backup = NULL; /* there is no backup file to delete */
994: #ifndef SHORT_FNAME
995: /*
996: * may try again with 'shortname' set
997: */
998: if (!(buf->b_shortname || buf->b_p_sn))
999: {
1000: buf->b_shortname = TRUE;
1001: did_set_shortname = TRUE;
1002: continue;
1003: }
1004: /* setting shortname didn't help */
1005: if (did_set_shortname)
1006: buf->b_shortname = FALSE;
1007: #endif
1008: break;
1009: }
1010:
1011: /*
1012: * If we are not going to keep the backup file, don't
1013: * delete an existing one, try to use another name.
1014: * Change one character, just before the extension.
1015: */
1016: if (!p_bk)
1017: {
1018: wp = backup + STRLEN(backup) - 1 - STRLEN(backup_ext);
1019: if (wp < backup) /* empty file name ??? */
1020: wp = backup;
1021: *wp = 'z';
1022: while (*wp > 'a' && !stat((char *)backup, &st_new))
1023: --*wp;
1024: /* They all exist??? Must be something wrong. */
1025: if (*wp == 'a')
1026: {
1027: vim_free(backup);
1028: backup = NULL;
1029: }
1030: }
1031: }
1032: break;
1033: }
1034:
1035: /*
1036: * Try to create the backup file
1037: */
1038: if (backup != NULL)
1039: {
1040: /* remove old backup, if present */
1041: vim_remove(backup);
1042: bfd = open((char *)backup, O_WRONLY | O_CREAT | O_EXTRA, 0666);
1043: if (bfd < 0)
1044: {
1045: vim_free(backup);
1046: backup = NULL;
1047: }
1048: else
1049: {
1050: /* set file protection same as original file, but strip
1051: * s-bit */
1052: (void)setperm(backup, perm & 0777);
1053:
1054: /*
1055: * Try to set the group of the backup same as the original
1056: * file. If this fails, set the protection bits for the
1057: * group same as the protection bits for others.
1058: */
1059: if (st_new.st_gid != st_old.st_gid &&
1060: #ifdef HAVE_FCHOWN /* sequent-ptx lacks fchown() */
1061: fchown(bfd, -1, st_old.st_gid) != 0)
1062: #else
1063: chown(backup, -1, st_old.st_gid) != 0)
1064: #endif
1065: setperm(backup, (perm & 0707) | ((perm & 07) << 3));
1066:
1067: /* copy the file. */
1068: while ((buflen = read(fd, (char *)copybuf, BUFSIZE)) > 0)
1069: {
1070: if (write_buf(bfd, copybuf, buflen) == FAIL)
1071: {
1072: errmsg = (char_u *)"Can't write to backup file (use ! to override)";
1073: break;
1074: }
1075: }
1076: if (close(bfd) < 0 && errmsg == NULL)
1077: errmsg = (char_u *)"Close error for backup file (use ! to override)";
1078: if (buflen < 0)
1079: errmsg = (char_u *)"Can't read file for backup (use ! to override)";
1080: break;
1081: }
1082: }
1083: }
1084: nobackup:
1085: close(fd); /* ignore errors for closing read file */
1086:
1087: if (backup == NULL && errmsg == NULL)
1088: errmsg = (char_u *)"Cannot create backup file (use ! to override)";
1089: /* ignore errors when forceit is TRUE */
1090: if ((some_error || errmsg) && !forceit)
1091: {
1092: retval = FAIL;
1093: goto fail;
1094: }
1095: errmsg = NULL;
1096: }
1097: /* When using ":w!" and the file was read-only: make it writable */
1098: if (forceit && (st_old.st_uid == getuid()) && perm >= 0 && !(perm & 0200))
1099: {
1100: perm |= 0200;
1101: (void)setperm(fname, perm);
1102: made_writable = TRUE;
1103: }
1104:
1105: #else /* end of UNIX, start of the rest */
1106:
1107: /*
1108: * If we are not appending, the file exists, and the 'writebackup' or
1109: * 'backup' option is set, make a backup.
1110: * Do not make any backup, if "writebackup" and "backup" are
1111: * both switched off. This helps when editing large files on
1112: * almost-full disks. (jw)
1113: */
1114: perm = getperm(fname);
1115: if (perm < 0)
1116: newfile = TRUE;
1117: else if (mch_isdir(fname))
1118: {
1119: errmsg = (char_u *)"is a directory";
1120: goto fail;
1121: }
1122: if (!append && perm >= 0 && (p_wb || p_bk || *p_pm != NUL))
1123: {
1124: char_u *dirp;
1125: char_u *p;
1126:
1127: /*
1128: * Form the backup file name - change path/fo.o.h to path/fo.o.h.bak
1129: * Try all directories in 'backupdir', first one that works is used.
1130: */
1131: dirp = p_bdir;
1132: while (*dirp)
1133: {
1134: /*
1135: * Isolate one directory name.
1136: */
1137: len = copy_option_part(&dirp, IObuff, IOSIZE, ",");
1138:
1139: #ifdef VMS
1140: if (!memcmp(IObuff, "sys$disk:", 9))
1141: #else
1142: if (*IObuff == '.') /* use same dir as file */
1143: #endif
1144: backup = buf_modname(buf, fname, backup_ext);
1145: else /* use dir from 'bdir' option */
1146: {
1147: if (!ispathsep(IObuff[len - 1]))
1148: IObuff[len++] = PATHSEP;
1149: STRCPY(IObuff + len, gettail(fname));
1150: backup = buf_modname(buf, IObuff, backup_ext);
1151: }
1152: if (backup != NULL)
1153: {
1154: /*
1155: * If we are not going to keep the backup file, don't
1156: * delete an existing one, try to use another name.
1157: * Change one character, just before the extension.
1158: */
1159: if (!p_bk && getperm(backup) >= 0)
1160: {
1161: p = backup + STRLEN(backup) - 1 - STRLEN(backup_ext);
1162: if (p < backup) /* empty file name ??? */
1163: p = backup;
1164: *p = 'z';
1165: while (*p > 'a' && getperm(backup) >= 0)
1166: --*p;
1167: /* They all exist??? Must be something wrong! */
1168: if (*p == 'a')
1169: {
1170: vim_free(backup);
1171: backup = NULL;
1172: }
1173: }
1174: }
1175: if (backup != NULL)
1176: {
1177:
1178: /*
1179: * Delete any existing backup and move the current version to
1180: * the backup. For safety, we don't remove the backup until
1181: * the write has finished successfully. And if the 'backup'
1182: * option is set, leave it around.
1183: */
1184: #ifdef AMIGA
1185: /*
1186: * With MSDOS-compatible filesystems (crossdos, messydos) it is
1187: * possible that the name of the backup file is the same as the
1188: * original file. To avoid the chance of accidently deleting the
1189: * original file (horror!) we lock it during the remove.
1190: * This should not happen with ":w", because startscript()
1191: * should detect this problem and set buf->b_shortname,
1192: * causing modname to return a correct ".bak" filename. This
1193: * problem does exist with ":w filename", but then the
1194: * original file will be somewhere else so the backup isn't
1195: * really important. If autoscripting is off the rename may
1196: * fail.
1197: */
1198: flock = Lock((UBYTE *)fname, (long)ACCESS_READ);
1199: #endif
1200: vim_remove(backup);
1201: #ifdef AMIGA
1202: if (flock)
1203: UnLock(flock);
1204: #endif
1205: /*
1206: * If the renaming of the original file to the backup file
1207: * works, quit here.
1208: */
1209: if (vim_rename(fname, backup) == 0)
1210: break;
1211:
1212: vim_free(backup); /* don't do the rename below */
1213: backup = NULL;
1214: }
1215: }
1216: if (backup == NULL && !forceit)
1217: {
1218: errmsg = (char_u *)"Can't make backup file (use ! to override)";
1219: goto fail;
1220: }
1221: }
1222: #endif /* UNIX */
1223:
1224: /* When using ":w!" and writing to the current file, readonly makes no
1225: * sense, reset it */
1226: if (forceit && overwriting)
1227: buf->b_p_ro = FALSE;
1228:
1229: /*
1230: * If the original file is being overwritten, there is a small chance that
1231: * we crash in the middle of writing. Therefore the file is preserved now.
1232: * This makes all block numbers positive so that recovery does not need
1233: * the original file.
1234: * Don't do this if there is a backup file and we are exiting.
1235: */
1236: if (reset_changed && !newfile && !otherfile(ffname) &&
1237: !(exiting && backup != NULL))
1238: ml_preserve(buf, FALSE);
1239:
1240: /*
1241: * We may try to open the file twice: If we can't write to the
1242: * file and forceit is TRUE we delete the existing file and try to create
1243: * a new one. If this still fails we may have lost the original file!
1244: * (this may happen when the user reached his quotum for number of files).
1245: * Appending will fail if the file does not exist and forceit is FALSE.
1246: */
1247: while ((fd = open((char *)fname, O_WRONLY | O_EXTRA | (append ?
1248: (forceit ? (O_APPEND | O_CREAT) : O_APPEND) :
1249: (O_CREAT | O_TRUNC)), 0666)) < 0)
1250: {
1251: /*
1252: * A forced write will try to create a new file if the old one is
1253: * still readonly. This may also happen when the directory is
1254: * read-only. In that case the vim_remove() will fail.
1255: */
1256: if (!errmsg)
1257: {
1258: errmsg = (char_u *)"Can't open file for writing";
1259: if (forceit)
1260: {
1261: #ifdef UNIX
1262: /* we write to the file, thus it should be marked
1263: writable after all */
1264: perm |= 0200;
1265: made_writable = TRUE;
1266: if (st_old.st_uid != getuid() || st_old.st_gid != getgid())
1267: perm &= 0777;
1268: #endif /* UNIX */
1269: if (!append) /* don't remove when appending */
1270: vim_remove(fname);
1271: continue;
1272: }
1273: }
1274: /*
1275: * If we failed to open the file, we don't need a backup. Throw it away.
1276: * If we moved or removed the original file try to put the backup in its place.
1277: */
1278: if (backup != NULL)
1279: {
1280: #ifdef UNIX
1281: struct stat st;
1282:
1283: /*
1284: * There is a small chance that we removed the original, try
1285: * to move the copy in its place.
1286: * This may not work if the vim_rename() fails.
1287: * In that case we leave the copy around.
1288: */
1289: /* file does not exist */
1290: if (stat((char *)fname, &st) < 0)
1291: /* put the copy in its place */
1292: vim_rename(backup, fname);
1293: /* original file does exist */
1294: if (stat((char *)fname, &st) >= 0)
1295: vim_remove(backup); /* throw away the copy */
1296: #else
1297: /* try to put the original file back */
1298: vim_rename(backup, fname);
1299: #endif
1300: }
1301: goto fail;
1302: }
1303: errmsg = NULL;
1304:
1305: if (end > buf->b_ml.ml_line_count)
1306: end = buf->b_ml.ml_line_count;
1307: len = 0;
1308: s = buffer;
1309: nchars = 0;
1310: if (buf->b_ml.ml_flags & ML_EMPTY)
1311: start = end + 1;
1312: for (lnum = start; lnum <= end; ++lnum)
1313: {
1314: /*
1315: * The next while loop is done once for each character written.
1316: * Keep it fast!
1317: */
1318: ptr = ml_get_buf(buf, lnum, FALSE) - 1;
1319: while ((c = *++ptr) != NUL)
1320: {
1321: if (c == NL)
1322: *s = NUL; /* replace newlines with NULs */
1323: else
1324: *s = c;
1325: ++s;
1326: if (++len != bufsize)
1327: continue;
1328: if (write_buf(fd, buffer, bufsize) == FAIL)
1329: {
1330: end = 0; /* write error: break loop */
1331: break;
1332: }
1333: nchars += bufsize;
1334: s = buffer;
1335: len = 0;
1336: }
1337: /* write failed or last line has no EOL: stop here */
1338: if (end == 0 || (lnum == end && buf->b_p_bin &&
1339: (lnum == write_no_eol_lnum ||
1340: (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol))))
1341: break;
1342: if (buf->b_p_tx) /* write CR-NL */
1343: {
1344: *s = CR;
1345: ++s;
1346: if (++len == bufsize)
1347: {
1348: if (write_buf(fd, buffer, bufsize) == FAIL)
1349: {
1350: end = 0; /* write error: break loop */
1351: break;
1352: }
1353: nchars += bufsize;
1354: s = buffer;
1355: len = 0;
1356: }
1357: }
1358: *s = NL;
1359: ++s;
1360: if (++len == bufsize && end)
1361: {
1362: if (write_buf(fd, buffer, bufsize) == FAIL)
1363: {
1364: end = 0; /* write error: break loop */
1365: break;
1366: }
1367: nchars += bufsize;
1368: s = buffer;
1369: len = 0;
1370: }
1371: }
1372: if (len && end)
1373: {
1374: if (write_buf(fd, buffer, len) == FAIL)
1375: end = 0; /* write error */
1376: nchars += len;
1377: }
1378:
1379: if (close(fd) != 0)
1380: {
1381: errmsg = (char_u *)"Close failed";
1382: goto fail;
1383: }
1384: #ifdef UNIX
1385: if (made_writable)
1386: perm &= ~0200; /* reset 'w' bit for security reasons */
1387: #endif
1388: if (perm >= 0)
1389: (void)setperm(fname, perm); /* set permissions of new file same as old file */
1390:
1391: if (end == 0)
1392: {
1393: errmsg = (char_u *)"write error (file system full?)";
1394: /*
1395: * If we have a backup file, try to put it in place of the new file,
1396: * because it is probably corrupt. This avoids loosing the original
1397: * file when trying to make a backup when writing the file a second
1398: * time.
1399: * For unix this means copying the backup over the new file.
1400: * For others this means renaming the backup file.
1401: * If this is OK, don't give the extra warning message.
1402: */
1403: if (backup != NULL)
1404: {
1405: #ifdef UNIX
1406: char_u copybuf[BUFSIZE + 1];
1407: int bfd, buflen;
1408:
1409: if ((bfd = open((char *)backup, O_RDONLY | O_EXTRA)) >= 0)
1410: {
1411: if ((fd = open((char *)fname,
1412: O_WRONLY | O_CREAT | O_TRUNC | O_EXTRA, 0666)) >= 0)
1413: {
1414: /* copy the file. */
1415: while ((buflen = read(bfd, (char *)copybuf, BUFSIZE)) > 0)
1416: if (write_buf(fd, copybuf, buflen) == FAIL)
1417: break;
1418: if (close(fd) >= 0 && buflen == 0) /* success */
1419: end = 1;
1420: }
1421: close(bfd); /* ignore errors for closing read file */
1422: }
1423: #else
1424: if (vim_rename(backup, fname) == 0)
1425: end = 1;
1426: #endif
1427: }
1428: goto fail;
1429: }
1430:
1431: lnum -= start; /* compute number of written lines */
1432: --no_wait_return; /* may wait for return now */
1433:
1434: #ifndef UNIX
1435: /* use shortname now, for the messages */
1436: if (!did_cd)
1437: fname = sfname;
1438: #endif
1439: if (!filtering)
1440: {
1441: msg_add_fname(buf, fname); /* put fname in IObuff with quotes */
1442: c = FALSE;
1443: if (newfile)
1444: {
1445: STRCAT(IObuff, shortmess(SHM_NEW) ? "[New]" : "[New File]");
1446: c = TRUE;
1447: }
1448: if (msg_add_textmode(buf->b_p_tx)) /* may add [textmode] */
1449: c = TRUE;
1450: msg_add_lines(c, (long)lnum, nchars); /* add line/char count */
1451: if (!shortmess(SHM_WRITE))
1452: STRCAT(IObuff, shortmess(SHM_WRI) ? " [w]" : " written");
1453:
1454: msg_trunc(IObuff);
1455: }
1456:
1457: if (reset_changed && whole) /* when written everything */
1458: {
1459: UNCHANGED(buf);
1460: u_unchanged(buf);
1461: }
1462:
1463: /*
1464: * If written to the current file, update the timestamp of the swap file
1465: * and reset the 'notedited' flag. Also sets buf->b_mtime.
1466: */
1467: if (!exiting && overwriting)
1468: {
1469: ml_timestamp(buf);
1470: buf->b_notedited = FALSE;
1471: }
1472:
1473: /*
1474: * If we kept a backup until now, and we are in patch mode, then we make
1475: * the backup file our 'original' file.
1476: */
1477: if (*p_pm)
1478: {
1479: char *org = (char *)buf_modname(buf, fname, p_pm);
1480:
1481: if (backup != NULL)
1482: {
1483: struct stat st;
1484:
1485: /*
1486: * If the original file does not exist yet
1487: * the current backup file becomes the original file
1488: */
1489: if (org == NULL)
1490: EMSG("patchmode: can't save original file");
1491: else if (stat(org, &st) < 0)
1492: {
1493: vim_rename(backup, (char_u *)org);
1494: vim_free(backup); /* don't delete the file */
1495: backup = NULL;
1496: }
1497: }
1498: /*
1499: * If there is no backup file, remember that a (new) file was
1500: * created.
1501: */
1502: else
1503: {
1504: int empty_fd;
1505:
1506: if (org == NULL || (empty_fd =
1507: open(org, O_CREAT | O_EXTRA, 0666)) < 0)
1508: EMSG("patchmode: can't touch empty original file");
1509: else
1510: close(empty_fd);
1511: }
1512: if (org != NULL)
1513: {
1514: setperm((char_u *)org, getperm(fname) & 0777);
1515: vim_free(org);
1516: }
1517: }
1518:
1519: /*
1520: * Remove the backup unless 'backup' option is set
1521: */
1522: if (!p_bk && backup != NULL && vim_remove(backup) != 0)
1523: EMSG("Can't delete backup file");
1524:
1525: goto nofail;
1526:
1527: fail:
1528: --no_wait_return; /* may wait for return now */
1529: nofail:
1530:
1531: vim_free(backup);
1532: if (buffer != smallbuf)
1533: vim_free(buffer);
1534:
1535: if (errmsg != NULL)
1536: {
1537: /* can't use emsg() here, do something alike */
1538: if (p_eb)
1539: beep_flush(); /* also includes flush_buffers() */
1540: else
1541: flush_buffers(FALSE); /* flush internal buffers */
1542: (void)set_highlight('e'); /* set highlight mode for error messages */
1543: start_highlight();
1544: filemess(buf,
1545: #ifndef UNIX
1546: did_cd ? fname : sfname,
1547: #else
1548: fname,
1549: #endif
1550: errmsg);
1551: retval = FAIL;
1552: if (end == 0)
1553: {
1554: MSG_OUTSTR("\nWARNING: Original file may be lost or damaged\n");
1555: MSG_OUTSTR("don't quit the editor until the file is sucessfully written!");
1556: }
1557: }
1558: msg_scroll = msg_save;
1559:
1560: #ifdef AUTOCMD
1561: /*
1562: * Apply POST aucocommands.
1563: * Careful: The autocommands may call buf_write() recursively!
1564: */
1565: save_buf = curbuf;
1566: curbuf = buf;
1567: curwin->w_buffer = buf;
1568: if (append)
1569: apply_autocmds(EVENT_FILEAPPENDPOST, fname, fname);
1570: else if (filtering)
1571: apply_autocmds(EVENT_FILTERWRITEPOST, NULL, fname);
1572: else if (reset_changed && whole)
1573: apply_autocmds(EVENT_BUFWRITEPOST, fname, fname);
1574: else
1575: apply_autocmds(EVENT_FILEWRITEPOST, fname, fname);
1576: curbuf = save_buf;
1577: curwin->w_buffer = save_buf;
1578: #endif
1579:
1580: return retval;
1581: }
1582:
1583: /*
1584: * Put file name into IObuff with quotes.
1585: */
1586: static void
1587: msg_add_fname(buf, fname)
1588: BUF *buf;
1589: char_u *fname;
1590: {
1591: /* careful: home_replace calls vim_getenv(), which also uses IObuff! */
1592: home_replace(buf, fname, IObuff + 1, IOSIZE - 1);
1593: IObuff[0] = '"';
1594: STRCAT(IObuff, "\" ");
1595: }
1596:
1597: /*
1598: * Append message for text mode to IObuff.
1599: * Return TRUE if something appended.
1600: */
1601: static int
1602: msg_add_textmode(textmode)
1603: int textmode;
1604: {
1605: #ifdef USE_CRNL
1606: if (!textmode)
1607: {
1608: STRCAT(IObuff, shortmess(SHM_TEXT) ? "[notx]" : "[notextmode]");
1609: return TRUE;
1610: }
1611: #else
1612: if (textmode)
1613: {
1614: STRCAT(IObuff, shortmess(SHM_TEXT) ? "[tx]" : "[textmode]");
1615: return TRUE;
1616: }
1617: #endif
1618: return FALSE;
1619: }
1620:
1621: /*
1622: * Append line and character count to IObuff.
1623: */
1624: static void
1625: msg_add_lines(insert_space, lnum, nchars)
1626: int insert_space;
1627: long lnum;
1628: long nchars;
1629: {
1630: char_u *p;
1631:
1632: p = IObuff + STRLEN(IObuff);
1633:
1634: if (insert_space)
1635: *p++ = ' ';
1636: if (shortmess(SHM_LINES))
1637: sprintf((char *)p, "%ldL, %ldC", lnum, nchars);
1638: else
1639: sprintf((char *)p, "%ld line%s, %ld character%s",
1640: lnum, plural(lnum),
1641: nchars, plural(nchars));
1642: }
1643:
1644: /*
1645: * write_buf: call write() to write a buffer
1646: *
1647: * return FAIL for failure, OK otherwise
1648: */
1649: static int
1650: write_buf(fd, buf, len)
1651: int fd;
1652: char_u *buf;
1653: int len;
1654: {
1655: int wlen;
1656:
1657: while (len)
1658: {
1659: wlen = write(fd, (char *)buf, (size_t)len);
1660: if (wlen <= 0) /* error! */
1661: return FAIL;
1662: len -= wlen;
1663: buf += wlen;
1664: }
1665: return OK;
1666: }
1667:
1668: /*
1669: * add extention to filename - change path/fo.o.h to path/fo.o.h.ext or
1670: * fo_o_h.ext for MSDOS or when shortname option set.
1671: *
1672: * Assumed that fname is a valid name found in the filesystem we assure that
1673: * the return value is a different name and ends in 'ext'.
1674: * "ext" MUST be at most 4 characters long if it starts with a dot, 3
1675: * characters otherwise.
1676: * Space for the returned name is allocated, must be freed later.
1677: */
1678:
1679: char_u *
1680: modname(fname, ext)
1681: char_u *fname, *ext;
1682: {
1683: return buf_modname(curbuf, fname, ext);
1684: }
1685:
1686: char_u *
1687: buf_modname(buf, fname, ext)
1688: BUF *buf;
1689: char_u *fname, *ext;
1690: {
1691: char_u *retval;
1692: register char_u *s;
1693: register char_u *e;
1694: register char_u *ptr;
1695: register int fnamelen, extlen;
1696:
1697: extlen = STRLEN(ext);
1698:
1699: /*
1700: * if there is no filename we must get the name of the current directory
1701: * (we need the full path in case :cd is used)
1702: */
1703: if (fname == NULL || *fname == NUL)
1704: {
1705: retval = alloc((unsigned)(MAXPATHL + extlen + 3));
1706: if (retval == NULL)
1707: return NULL;
1708: if (mch_dirname(retval, MAXPATHL) == FAIL ||
1709: (fnamelen = STRLEN(retval)) == 0)
1710: {
1711: vim_free(retval);
1712: return NULL;
1713: }
1714: if (!ispathsep(retval[fnamelen - 1]))
1715: {
1716: retval[fnamelen++] = PATHSEP;
1717: retval[fnamelen] = NUL;
1718: }
1719: }
1720: else
1721: {
1722: fnamelen = STRLEN(fname);
1723: retval = alloc((unsigned)(fnamelen + extlen + 2));
1724: if (retval == NULL)
1725: return NULL;
1726: STRCPY(retval, fname);
1727: }
1728:
1729: /*
1730: * search backwards until we hit a '/', '\' or ':' replacing all '.'
1731: * by '_' for MSDOS or when shortname option set and ext starts with a dot.
1732: * Then truncate what is after the '/', '\' or ':' to 8 characters for
1733: * MSDOS and 26 characters for AMIGA, a lot more for UNIX.
1734: */
1735: for (ptr = retval + fnamelen; ptr >= retval; ptr--)
1736: {
1737: if (*ext == '.'
1738: #ifdef USE_LONG_FNAME
1739: && (!USE_LONG_FNAME || buf->b_p_sn || buf->b_shortname)
1740: #else
1741: # ifndef SHORT_FNAME
1742: && (buf->b_p_sn || buf->b_shortname)
1743: # endif
1744: #endif
1745: )
1746: if (*ptr == '.') /* replace '.' by '_' */
1747: *ptr = '_';
1748: if (ispathsep(*ptr))
1749: break;
1750: }
1751: ptr++;
1752:
1753: /* the filename has at most BASENAMELEN characters. */
1754: #ifndef SHORT_FNAME
1755: if (STRLEN(ptr) > (unsigned)BASENAMELEN)
1756: ptr[BASENAMELEN] = '\0';
1757: #endif
1758:
1759: s = ptr + STRLEN(ptr);
1760:
1761: /*
1762: * For 8.3 filenames we may have to reduce the length.
1763: */
1764: #ifdef USE_LONG_FNAME
1765: if (!USE_LONG_FNAME || buf->b_p_sn || buf->b_shortname)
1766: #else
1767: # ifndef SHORT_FNAME
1768: if (buf->b_p_sn || buf->b_shortname)
1769: # endif
1770: #endif
1771: {
1772: /*
1773: * If there is no file name, and the extension starts with '.', put a
1774: * '_' before the dot, because just ".ext" is invalid.
1775: */
1776: if (fname == NULL || *fname == NUL)
1777: {
1778: if (*ext == '.')
1779: *s++ = '_';
1780: }
1781: /*
1782: * If the extension starts with '.', truncate the base name at 8
1783: * characters
1784: */
1785: else if (*ext == '.')
1786: {
1787: if (s - ptr > (size_t)8)
1788: {
1789: s = ptr + 8;
1790: *s = '\0';
1791: }
1792: }
1793: /*
1794: * If the extension doesn't start with '.', and the file name
1795: * doesn't have an extension yet, append a '.'
1796: */
1797: else if ((e = vim_strchr(ptr, '.')) == NULL)
1798: *s++ = '.';
1799: /*
1800: * If If the extension doesn't start with '.', and there already is an
1801: * extension, it may need to be tructated
1802: */
1803: else if ((int)STRLEN(e) + extlen > 4)
1804: s = e + 4 - extlen;
1805: }
1806: #ifdef OS2
1807: /*
1808: * If there is no file name, and the extension starts with '.', put a
1809: * '_' before the dot, because just ".ext" may be invalid if it's on a
1810: * FAT partition, and on HPFS it doesn't matter.
1811: */
1812: else if ((fname == NULL || *fname == NUL) && *ext == '.')
1813: *s++ = '_';
1814: #endif
1815:
1816: /*
1817: * Append the extention.
1818: * ext can start with '.' and cannot exceed 3 more characters.
1819: */
1820: STRCPY(s, ext);
1821:
1822: /*
1823: * Check that, after appending the extension, the file name is really
1824: * different.
1825: */
1826: if (fname != NULL && STRCMP(fname, retval) == 0)
1827: {
1828: /* we search for a character that can be replaced by '_' */
1829: while (--s >= ptr)
1830: {
1831: if (*s != '_')
1832: {
1833: *s = '_';
1834: break;
1835: }
1836: }
1837: if (s < ptr) /* fname was "________.<ext>" how tricky! */
1838: *ptr = 'v';
1839: }
1840: return retval;
1841: }
1842:
1843: /* vim_fgets();
1844: *
1845: * Like fgets(), but if the file line is too long, it is truncated and the
1846: * rest of the line is thrown away. Returns TRUE for end-of-file.
1847: * Note: do not pass IObuff as the buffer since this is used to read and
1848: * discard the extra part of any long lines.
1849: */
1850: int
1851: vim_fgets(buf, size, fp)
1852: char_u *buf;
1853: int size;
1854: FILE *fp;
1855: {
1856: char *eof;
1857:
1858: buf[size - 2] = NUL;
1859: eof = fgets((char *)buf, size, fp);
1860: if (buf[size - 2] != NUL && buf[size - 2] != '\n')
1861: {
1862: buf[size - 1] = NUL; /* Truncate the line */
1863:
1864: /* Now throw away the rest of the line: */
1865: do
1866: {
1867: IObuff[IOSIZE - 2] = NUL;
1868: fgets((char *)IObuff, IOSIZE, fp);
1869: } while (IObuff[IOSIZE - 2] != NUL && IObuff[IOSIZE - 2] != '\n');
1870: }
1871: return (eof == NULL);
1872: }
1873:
1874: /*
1875: * rename() only works if both files are on the same file system, this
1876: * function will (attempts to?) copy the file across if rename fails -- webb
1877: * Return -1 for failure, 0 for success.
1878: */
1879: int
1880: vim_rename(from, to)
1881: char_u *from;
1882: char_u *to;
1883: {
1884: int fd_in;
1885: int fd_out;
1886: int n;
1887: char *errmsg = NULL;
1888:
1889: /*
1890: * First delete the "to" file, this is required on some systems to make
1891: * the rename() work, on other systems it makes sure that we don't have
1892: * two files when the rename() fails.
1893: */
1894: vim_remove(to);
1895:
1896: /*
1897: * First try a normal rename, return if it works.
1898: */
1899: if (rename((char *)from, (char *)to) == 0)
1900: return 0;
1901:
1902: /*
1903: * Rename() failed, try copying the file.
1904: */
1905: fd_in = open((char *)from, O_RDONLY | O_EXTRA);
1906: if (fd_in == -1)
1907: return -1;
1908: fd_out = open((char *)to, O_CREAT | O_TRUNC | O_WRONLY | O_EXTRA, 0666);
1909: if (fd_out == -1)
1910: {
1911: close(fd_in);
1912: return -1;
1913: }
1914: while ((n = read(fd_in, (char *)IObuff, (size_t)IOSIZE)) > 0)
1915: if (write(fd_out, (char *)IObuff, (size_t)n) != n)
1916: {
1917: errmsg = "writing to";
1918: break;
1919: }
1920: close(fd_in);
1921: if (close(fd_out) < 0)
1922: errmsg = "closing";
1923: if (n < 0)
1924: {
1925: errmsg = "reading";
1926: to = from;
1927: }
1928: if (errmsg != NULL)
1929: {
1930: sprintf((char *)IObuff, "Error %s '%s'", errmsg, to);
1931: emsg(IObuff);
1932: return -1;
1933: }
1934: vim_remove(from);
1935: return 0;
1936: }
1937:
1938: /*
1939: * Check if any not hidden buffer has been changed.
1940: * Postpone the check if there are characters in the stuff buffer, a global
1941: * command is being executed, a mapping is being executed or an autocommand is
1942: * busy.
1943: */
1944: void
1945: check_timestamps()
1946: {
1947: BUF *buf;
1948:
1949: if (!stuff_empty() || global_busy || !typebuf_typed()
1950: #ifdef AUTOCMD
1951: || autocmd_busy
1952: #endif
1953: )
1954: need_check_timestamps = TRUE; /* check later */
1955: else
1956: {
1957: ++no_wait_return;
1958: for (buf = firstbuf; buf != NULL; buf = buf->b_next)
1959: buf_check_timestamp(buf);
1960: --no_wait_return;
1961: need_check_timestamps = FALSE;
1962: }
1963: }
1964:
1965: /*
1966: * Check if buffer "buf" has been changed.
1967: */
1968: void
1969: buf_check_timestamp(buf)
1970: BUF *buf;
1971: {
1972: struct stat st;
1973: char_u *path;
1974:
1975: if ( buf->b_filename != NULL &&
1976: buf->b_ml.ml_mfp != NULL &&
1977: !buf->b_notedited &&
1978: buf->b_mtime != 0 &&
1979: stat((char *)buf->b_filename, &st) >= 0 &&
1980: buf->b_mtime != st.st_mtime)
1981: {
1982: path = home_replace_save(buf, buf->b_xfilename);
1983: if (path != NULL)
1984: {
1985: EMSG2("Warning: File \"%s\" has changed since editing started",
1986: path);
1987: buf->b_mtime = st.st_mtime;
1988: vim_free(path);
1989: }
1990: }
1991: }