[BACK]Return to fileio.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / vim

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: }