[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.3

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