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