1/* vi:set ts=8 sts=4 sw=4:
2 *
3 * VIM - Vi IMproved	by Bram Moolenaar
4 *
5 * Do ":help uganda"  in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * memfile.c: Contains the functions for handling blocks of memory which can
12 * be stored in a file. This is the implementation of a sort of virtual memory.
13 *
14 * A memfile consists of a sequence of blocks. The blocks numbered from 0
15 * upwards have been assigned a place in the actual file. The block number
16 * is equal to the page number in the file. The
17 * blocks with negative numbers are currently in memory only. They can be
18 * assigned a place in the file when too much memory is being used. At that
19 * moment they get a new, positive, number. A list is used for translation of
20 * negative to positive numbers.
21 *
22 * The size of a block is a multiple of a page size, normally the page size of
23 * the device the file is on. Most blocks are 1 page long. A Block of multiple
24 * pages is used for a line that does not fit in a single page.
25 *
26 * Each block can be in memory and/or in a file. The block stays in memory
27 * as long as it is locked. If it is no longer locked it can be swapped out to
28 * the file. It is only written to the file if it has been changed.
29 *
30 * Under normal operation the file is created when opening the memory file and
31 * deleted when closing the memory file. Only with recovery an existing memory
32 * file is opened.
33 */
34
35#if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64)
36# include "vimio.h"	/* for lseek(), must be before vim.h */
37#endif
38
39#include "vim.h"
40
41/*
42 * Some systems have the page size in statfs.f_bsize, some in stat.st_blksize
43 */
44#ifdef HAVE_ST_BLKSIZE
45# define STATFS stat
46# define F_BSIZE st_blksize
47# define fstatfs(fd, buf, len, nul) mch_fstat((fd), (buf))
48#else
49# ifdef HAVE_SYS_STATFS_H
50#  include <sys/statfs.h>
51#  define STATFS statfs
52#  define F_BSIZE f_bsize
53#  ifdef __MINT__		/* do we still need this? */
54#   define fstatfs(fd, buf, len, nul) mch_fstat((fd), (buf))
55#  endif
56# endif
57#endif
58
59/*
60 * for Amiga Dos 2.0x we use Flush
61 */
62#ifdef AMIGA
63# ifdef FEAT_ARP
64extern int dos2;			/* this is in os_amiga.c */
65# endif
66# ifdef SASC
67#  include <proto/dos.h>
68#  include <ios1.h>			/* for chkufb() */
69# endif
70#endif
71
72#define MEMFILE_PAGE_SIZE 4096		/* default page size */
73
74static long_u	total_mem_used = 0;	/* total memory used for memfiles */
75
76static void mf_ins_hash __ARGS((memfile_T *, bhdr_T *));
77static void mf_rem_hash __ARGS((memfile_T *, bhdr_T *));
78static bhdr_T *mf_find_hash __ARGS((memfile_T *, blocknr_T));
79static void mf_ins_used __ARGS((memfile_T *, bhdr_T *));
80static void mf_rem_used __ARGS((memfile_T *, bhdr_T *));
81static bhdr_T *mf_release __ARGS((memfile_T *, int));
82static bhdr_T *mf_alloc_bhdr __ARGS((memfile_T *, int));
83static void mf_free_bhdr __ARGS((bhdr_T *));
84static void mf_ins_free __ARGS((memfile_T *, bhdr_T *));
85static bhdr_T *mf_rem_free __ARGS((memfile_T *));
86static int  mf_read __ARGS((memfile_T *, bhdr_T *));
87static int  mf_write __ARGS((memfile_T *, bhdr_T *));
88static int  mf_write_block __ARGS((memfile_T *mfp, bhdr_T *hp, off_t offset, unsigned size));
89static int  mf_trans_add __ARGS((memfile_T *, bhdr_T *));
90static void mf_do_open __ARGS((memfile_T *, char_u *, int));
91
92/*
93 * The functions for using a memfile:
94 *
95 * mf_open()	    open a new or existing memfile
96 * mf_open_file()   open a swap file for an existing memfile
97 * mf_close()	    close (and delete) a memfile
98 * mf_new()	    create a new block in a memfile and lock it
99 * mf_get()	    get an existing block and lock it
100 * mf_put()	    unlock a block, may be marked for writing
101 * mf_free()	    remove a block
102 * mf_sync()	    sync changed parts of memfile to disk
103 * mf_release_all() release as much memory as possible
104 * mf_trans_del()   may translate negative to positive block number
105 * mf_fullname()    make file name full path (use before first :cd)
106 */
107
108/*
109 * Open an existing or new memory block file.
110 *
111 *  fname:	name of file to use (NULL means no file at all)
112 *		Note: fname must have been allocated, it is not copied!
113 *			If opening the file fails, fname is freed.
114 *  flags:	flags for open() call
115 *
116 *  If fname != NULL and file cannot be opened, fail.
117 *
118 * return value: identifier for this memory block file.
119 */
120    memfile_T *
121mf_open(fname, flags)
122    char_u	*fname;
123    int		flags;
124{
125    memfile_T		*mfp;
126    int			i;
127    off_t		size;
128#if defined(STATFS) && defined(UNIX) && !defined(__QNX__)
129# define USE_FSTATFS
130    struct STATFS	stf;
131#endif
132
133    if ((mfp = (memfile_T *)alloc((unsigned)sizeof(memfile_T))) == NULL)
134	return NULL;
135
136    if (fname == NULL)	    /* no file for this memfile, use memory only */
137    {
138	mfp->mf_fname = NULL;
139	mfp->mf_ffname = NULL;
140	mfp->mf_fd = -1;
141    }
142    else
143    {
144	mf_do_open(mfp, fname, flags);	/* try to open the file */
145
146	/* if the file cannot be opened, return here */
147	if (mfp->mf_fd < 0)
148	{
149	    vim_free(mfp);
150	    return NULL;
151	}
152    }
153
154    mfp->mf_free_first = NULL;		/* free list is empty */
155    mfp->mf_used_first = NULL;		/* used list is empty */
156    mfp->mf_used_last = NULL;
157    mfp->mf_dirty = FALSE;
158    mfp->mf_used_count = 0;
159    for (i = 0; i < MEMHASHSIZE; ++i)
160    {
161	mfp->mf_hash[i] = NULL;		/* hash lists are empty */
162	mfp->mf_trans[i] = NULL;	/* trans lists are empty */
163    }
164    mfp->mf_page_size = MEMFILE_PAGE_SIZE;
165#ifdef FEAT_CRYPT
166    mfp->mf_old_key = NULL;
167#endif
168
169#ifdef USE_FSTATFS
170    /*
171     * Try to set the page size equal to the block size of the device.
172     * Speeds up I/O a lot.
173     * When recovering, the actual block size will be retrieved from block 0
174     * in ml_recover().  The size used here may be wrong, therefore
175     * mf_blocknr_max must be rounded up.
176     */
177    if (mfp->mf_fd >= 0
178	    && fstatfs(mfp->mf_fd, &stf, sizeof(struct statfs), 0) == 0
179	    && stf.F_BSIZE >= MIN_SWAP_PAGE_SIZE
180	    && stf.F_BSIZE <= MAX_SWAP_PAGE_SIZE)
181	mfp->mf_page_size = stf.F_BSIZE;
182#endif
183
184    if (mfp->mf_fd < 0 || (flags & (O_TRUNC|O_EXCL))
185		      || (size = lseek(mfp->mf_fd, (off_t)0L, SEEK_END)) <= 0)
186	mfp->mf_blocknr_max = 0;	/* no file or empty file */
187    else
188	mfp->mf_blocknr_max = (blocknr_T)((size + mfp->mf_page_size - 1)
189							 / mfp->mf_page_size);
190    mfp->mf_blocknr_min = -1;
191    mfp->mf_neg_count = 0;
192    mfp->mf_infile_count = mfp->mf_blocknr_max;
193
194    /*
195     * Compute maximum number of pages ('maxmem' is in Kbyte):
196     *	'mammem' * 1Kbyte / page-size-in-bytes.
197     * Avoid overflow by first reducing page size as much as possible.
198     */
199    {
200	int	    shift = 10;
201	unsigned    page_size = mfp->mf_page_size;
202
203	while (shift > 0 && (page_size & 1) == 0)
204	{
205	    page_size = page_size >> 1;
206	    --shift;
207	}
208	mfp->mf_used_count_max = (p_mm << shift) / page_size;
209	if (mfp->mf_used_count_max < 10)
210	    mfp->mf_used_count_max = 10;
211    }
212
213    return mfp;
214}
215
216/*
217 * Open a file for an existing memfile.  Used when updatecount set from 0 to
218 * some value.
219 * If the file already exists, this fails.
220 * "fname" is the name of file to use (NULL means no file at all)
221 * Note: "fname" must have been allocated, it is not copied!  If opening the
222 * file fails, "fname" is freed.
223 *
224 * return value: FAIL if file could not be opened, OK otherwise
225 */
226    int
227mf_open_file(mfp, fname)
228    memfile_T	*mfp;
229    char_u	*fname;
230{
231    mf_do_open(mfp, fname, O_RDWR|O_CREAT|O_EXCL); /* try to open the file */
232
233    if (mfp->mf_fd < 0)
234	return FAIL;
235
236    mfp->mf_dirty = TRUE;
237    return OK;
238}
239
240/*
241 * Close a memory file and delete the associated file if 'del_file' is TRUE.
242 */
243    void
244mf_close(mfp, del_file)
245    memfile_T	*mfp;
246    int		del_file;
247{
248    bhdr_T	*hp, *nextp;
249    NR_TRANS	*tp, *tpnext;
250    int		i;
251
252    if (mfp == NULL)		    /* safety check */
253	return;
254    if (mfp->mf_fd >= 0)
255    {
256	if (close(mfp->mf_fd) < 0)
257	    EMSG(_(e_swapclose));
258    }
259    if (del_file && mfp->mf_fname != NULL)
260	mch_remove(mfp->mf_fname);
261					    /* free entries in used list */
262    for (hp = mfp->mf_used_first; hp != NULL; hp = nextp)
263    {
264	total_mem_used -= hp->bh_page_count * mfp->mf_page_size;
265	nextp = hp->bh_next;
266	mf_free_bhdr(hp);
267    }
268    while (mfp->mf_free_first != NULL)	    /* free entries in free list */
269	vim_free(mf_rem_free(mfp));
270    for (i = 0; i < MEMHASHSIZE; ++i)	    /* free entries in trans lists */
271	for (tp = mfp->mf_trans[i]; tp != NULL; tp = tpnext)
272	{
273	    tpnext = tp->nt_next;
274	    vim_free(tp);
275	}
276    vim_free(mfp->mf_fname);
277    vim_free(mfp->mf_ffname);
278    vim_free(mfp);
279}
280
281/*
282 * Close the swap file for a memfile.  Used when 'swapfile' is reset.
283 */
284    void
285mf_close_file(buf, getlines)
286    buf_T	*buf;
287    int		getlines;	/* get all lines into memory? */
288{
289    memfile_T	*mfp;
290    linenr_T	lnum;
291
292    mfp = buf->b_ml.ml_mfp;
293    if (mfp == NULL || mfp->mf_fd < 0)		/* nothing to close */
294	return;
295
296    if (getlines)
297    {
298	/* get all blocks in memory by accessing all lines (clumsy!) */
299	mf_dont_release = TRUE;
300	for (lnum = 1; lnum <= buf->b_ml.ml_line_count; ++lnum)
301	    (void)ml_get_buf(buf, lnum, FALSE);
302	mf_dont_release = FALSE;
303	/* TODO: should check if all blocks are really in core */
304    }
305
306    if (close(mfp->mf_fd) < 0)			/* close the file */
307	EMSG(_(e_swapclose));
308    mfp->mf_fd = -1;
309
310    if (mfp->mf_fname != NULL)
311    {
312	mch_remove(mfp->mf_fname);		/* delete the swap file */
313	vim_free(mfp->mf_fname);
314	vim_free(mfp->mf_ffname);
315	mfp->mf_fname = NULL;
316	mfp->mf_ffname = NULL;
317    }
318}
319
320/*
321 * Set new size for a memfile.  Used when block 0 of a swapfile has been read
322 * and the size it indicates differs from what was guessed.
323 */
324    void
325mf_new_page_size(mfp, new_size)
326    memfile_T	*mfp;
327    unsigned	new_size;
328{
329    /* Correct the memory used for block 0 to the new size, because it will be
330     * freed with that size later on. */
331    total_mem_used += new_size - mfp->mf_page_size;
332    mfp->mf_page_size = new_size;
333}
334
335/*
336 * get a new block
337 *
338 *   negative: TRUE if negative block number desired (data block)
339 */
340    bhdr_T *
341mf_new(mfp, negative, page_count)
342    memfile_T	*mfp;
343    int		negative;
344    int		page_count;
345{
346    bhdr_T	*hp;	/* new bhdr_T */
347    bhdr_T	*freep;	/* first block in free list */
348    char_u	*p;
349
350    /*
351     * If we reached the maximum size for the used memory blocks, release one
352     * If a bhdr_T is returned, use it and adjust the page_count if necessary.
353     */
354    hp = mf_release(mfp, page_count);
355
356/*
357 * Decide on the number to use:
358 * If there is a free block, use its number.
359 * Otherwise use mf_block_min for a negative number, mf_block_max for
360 * a positive number.
361 */
362    freep = mfp->mf_free_first;
363    if (!negative && freep != NULL && freep->bh_page_count >= page_count)
364    {
365	/*
366	 * If the block in the free list has more pages, take only the number
367	 * of pages needed and allocate a new bhdr_T with data
368	 *
369	 * If the number of pages matches and mf_release() did not return a
370	 * bhdr_T, use the bhdr_T from the free list and allocate the data
371	 *
372	 * If the number of pages matches and mf_release() returned a bhdr_T,
373	 * just use the number and free the bhdr_T from the free list
374	 */
375	if (freep->bh_page_count > page_count)
376	{
377	    if (hp == NULL && (hp = mf_alloc_bhdr(mfp, page_count)) == NULL)
378		return NULL;
379	    hp->bh_bnum = freep->bh_bnum;
380	    freep->bh_bnum += page_count;
381	    freep->bh_page_count -= page_count;
382	}
383	else if (hp == NULL)	    /* need to allocate memory for this block */
384	{
385	    if ((p = (char_u *)alloc(mfp->mf_page_size * page_count)) == NULL)
386		return NULL;
387	    hp = mf_rem_free(mfp);
388	    hp->bh_data = p;
389	}
390	else		    /* use the number, remove entry from free list */
391	{
392	    freep = mf_rem_free(mfp);
393	    hp->bh_bnum = freep->bh_bnum;
394	    vim_free(freep);
395	}
396    }
397    else	/* get a new number */
398    {
399	if (hp == NULL && (hp = mf_alloc_bhdr(mfp, page_count)) == NULL)
400	    return NULL;
401	if (negative)
402	{
403	    hp->bh_bnum = mfp->mf_blocknr_min--;
404	    mfp->mf_neg_count++;
405	}
406	else
407	{
408	    hp->bh_bnum = mfp->mf_blocknr_max;
409	    mfp->mf_blocknr_max += page_count;
410	}
411    }
412    hp->bh_flags = BH_LOCKED | BH_DIRTY;	/* new block is always dirty */
413    mfp->mf_dirty = TRUE;
414    hp->bh_page_count = page_count;
415    mf_ins_used(mfp, hp);
416    mf_ins_hash(mfp, hp);
417
418    /*
419     * Init the data to all zero, to avoid reading uninitialized data.
420     * This also avoids that the passwd file ends up in the swap file!
421     */
422    (void)vim_memset((char *)(hp->bh_data), 0,
423				      (size_t)mfp->mf_page_size * page_count);
424
425    return hp;
426}
427
428/*
429 * Get existing block "nr" with "page_count" pages.
430 *
431 * Note: The caller should first check a negative nr with mf_trans_del()
432 */
433    bhdr_T *
434mf_get(mfp, nr, page_count)
435    memfile_T	*mfp;
436    blocknr_T	nr;
437    int		page_count;
438{
439    bhdr_T    *hp;
440						/* doesn't exist */
441    if (nr >= mfp->mf_blocknr_max || nr <= mfp->mf_blocknr_min)
442	return NULL;
443
444    /*
445     * see if it is in the cache
446     */
447    hp = mf_find_hash(mfp, nr);
448    if (hp == NULL)	/* not in the hash list */
449    {
450	if (nr < 0 || nr >= mfp->mf_infile_count)   /* can't be in the file */
451	    return NULL;
452
453	/* could check here if the block is in the free list */
454
455	/*
456	 * Check if we need to flush an existing block.
457	 * If so, use that block.
458	 * If not, allocate a new block.
459	 */
460	hp = mf_release(mfp, page_count);
461	if (hp == NULL && (hp = mf_alloc_bhdr(mfp, page_count)) == NULL)
462	    return NULL;
463
464	hp->bh_bnum = nr;
465	hp->bh_flags = 0;
466	hp->bh_page_count = page_count;
467	if (mf_read(mfp, hp) == FAIL)	    /* cannot read the block! */
468	{
469	    mf_free_bhdr(hp);
470	    return NULL;
471	}
472    }
473    else
474    {
475	mf_rem_used(mfp, hp);	/* remove from list, insert in front below */
476	mf_rem_hash(mfp, hp);
477    }
478
479    hp->bh_flags |= BH_LOCKED;
480    mf_ins_used(mfp, hp);	/* put in front of used list */
481    mf_ins_hash(mfp, hp);	/* put in front of hash list */
482
483    return hp;
484}
485
486/*
487 * release the block *hp
488 *
489 *   dirty: Block must be written to file later
490 *   infile: Block should be in file (needed for recovery)
491 *
492 *  no return value, function cannot fail
493 */
494    void
495mf_put(mfp, hp, dirty, infile)
496    memfile_T	*mfp;
497    bhdr_T	*hp;
498    int		dirty;
499    int		infile;
500{
501    int		flags;
502
503    flags = hp->bh_flags;
504
505    if ((flags & BH_LOCKED) == 0)
506	EMSG(_("E293: block was not locked"));
507    flags &= ~BH_LOCKED;
508    if (dirty)
509    {
510	flags |= BH_DIRTY;
511	mfp->mf_dirty = TRUE;
512    }
513    hp->bh_flags = flags;
514    if (infile)
515	mf_trans_add(mfp, hp);	    /* may translate negative in positive nr */
516}
517
518/*
519 * block *hp is no longer in used, may put it in the free list of memfile *mfp
520 */
521    void
522mf_free(mfp, hp)
523    memfile_T	*mfp;
524    bhdr_T	*hp;
525{
526    vim_free(hp->bh_data);	/* free the memory */
527    mf_rem_hash(mfp, hp);	/* get *hp out of the hash list */
528    mf_rem_used(mfp, hp);	/* get *hp out of the used list */
529    if (hp->bh_bnum < 0)
530    {
531	vim_free(hp);		/* don't want negative numbers in free list */
532	mfp->mf_neg_count--;
533    }
534    else
535	mf_ins_free(mfp, hp);	/* put *hp in the free list */
536}
537
538#if defined(__MORPHOS__) && defined(__libnix__)
539/* function is missing in MorphOS libnix version */
540extern unsigned long *__stdfiledes;
541
542    static unsigned long
543fdtofh(int filedescriptor)
544{
545    return __stdfiledes[filedescriptor];
546}
547#endif
548
549/*
550 * Sync the memory file *mfp to disk.
551 * Flags:
552 *  MFS_ALL	If not given, blocks with negative numbers are not synced,
553 *		even when they are dirty!
554 *  MFS_STOP	Stop syncing when a character becomes available, but sync at
555 *		least one block.
556 *  MFS_FLUSH	Make sure buffers are flushed to disk, so they will survive a
557 *		system crash.
558 *  MFS_ZERO	Only write block 0.
559 *
560 * Return FAIL for failure, OK otherwise
561 */
562    int
563mf_sync(mfp, flags)
564    memfile_T	*mfp;
565    int		flags;
566{
567    int		status;
568    bhdr_T	*hp;
569#if defined(SYNC_DUP_CLOSE) && !defined(MSDOS)
570    int		fd;
571#endif
572    int		got_int_save = got_int;
573
574    if (mfp->mf_fd < 0)	    /* there is no file, nothing to do */
575    {
576	mfp->mf_dirty = FALSE;
577	return FAIL;
578    }
579
580    /* Only a CTRL-C while writing will break us here, not one typed
581     * previously. */
582    got_int = FALSE;
583
584    /*
585     * sync from last to first (may reduce the probability of an inconsistent
586     * file) If a write fails, it is very likely caused by a full filesystem.
587     * Then we only try to write blocks within the existing file. If that also
588     * fails then we give up.
589     */
590    status = OK;
591    for (hp = mfp->mf_used_last; hp != NULL; hp = hp->bh_prev)
592	if (((flags & MFS_ALL) || hp->bh_bnum >= 0)
593		&& (hp->bh_flags & BH_DIRTY)
594		&& (status == OK || (hp->bh_bnum >= 0
595		    && hp->bh_bnum < mfp->mf_infile_count)))
596	{
597	    if ((flags & MFS_ZERO) && hp->bh_bnum != 0)
598		continue;
599	    if (mf_write(mfp, hp) == FAIL)
600	    {
601		if (status == FAIL)	/* double error: quit syncing */
602		    break;
603		status = FAIL;
604	    }
605	    if (flags & MFS_STOP)
606	    {
607		/* Stop when char available now. */
608		if (ui_char_avail())
609		    break;
610	    }
611	    else
612		ui_breakcheck();
613	    if (got_int)
614		break;
615	}
616
617    /*
618     * If the whole list is flushed, the memfile is not dirty anymore.
619     * In case of an error this flag is also set, to avoid trying all the time.
620     */
621    if (hp == NULL || status == FAIL)
622	mfp->mf_dirty = FALSE;
623
624    if ((flags & MFS_FLUSH) && *p_sws != NUL)
625    {
626#if defined(UNIX)
627# ifdef HAVE_FSYNC
628	/*
629	 * most Unixes have the very useful fsync() function, just what we need.
630	 * However, with OS/2 and EMX it is also available, but there are
631	 * reports of bad problems with it (a bug in HPFS.IFS).
632	 * So we disable use of it here in case someone tries to be smart
633	 * and changes os_os2_cfg.h... (even though there is no __EMX__ test
634	 * in the #if, as __EMX__ does not have sync(); we hope for a timely
635	 * sync from the system itself).
636	 */
637#  if defined(__EMX__)
638   error "Dont use fsync with EMX! Read emxdoc.doc or emxfix01.doc for info."
639#  endif
640	if (STRCMP(p_sws, "fsync") == 0)
641	{
642	    if (fsync(mfp->mf_fd))
643		status = FAIL;
644	}
645	else
646# endif
647	    /* OpenNT is strictly POSIX (Benzinger) */
648	    /* Tandem/Himalaya NSK-OSS doesn't have sync() */
649# if defined(__OPENNT) || defined(__TANDEM)
650	    fflush(NULL);
651# else
652	    sync();
653# endif
654#endif
655#ifdef VMS
656	if (STRCMP(p_sws, "fsync") == 0)
657	{
658	    if (fsync(mfp->mf_fd))
659		status = FAIL;
660	}
661#endif
662#ifdef MSDOS
663	if (_dos_commit(mfp->mf_fd))
664	    status = FAIL;
665#else
666# ifdef SYNC_DUP_CLOSE
667	/*
668	 * Win32 is a bit more work: Duplicate the file handle and close it.
669	 * This should flush the file to disk.
670	 */
671	if ((fd = dup(mfp->mf_fd)) >= 0)
672	    close(fd);
673# endif
674#endif
675#ifdef AMIGA
676# if defined(__AROS__) || defined(__amigaos4__)
677	if (fsync(mfp->mf_fd) != 0)
678	    status = FAIL;
679# else
680	/*
681	 * Flush() only exists for AmigaDos 2.0.
682	 * For 1.3 it should be done with close() + open(), but then the risk
683	 * is that the open() may fail and lose the file....
684	 */
685#  ifdef FEAT_ARP
686	if (dos2)
687#  endif
688#  ifdef SASC
689	{
690	    struct UFB *fp = chkufb(mfp->mf_fd);
691
692	    if (fp != NULL)
693		Flush(fp->ufbfh);
694	}
695#  else
696#   if defined(_DCC) || defined(__GNUC__) || defined(__MORPHOS__)
697	{
698#    if defined(__GNUC__) && !defined(__MORPHOS__) && defined(__libnix__)
699	    /* Have function (in libnix at least),
700	     * but ain't got no prototype anywhere. */
701	    extern unsigned long fdtofh(int filedescriptor);
702#    endif
703#    if !defined(__libnix__)
704	    fflush(NULL);
705#    else
706	    BPTR fh = (BPTR)fdtofh(mfp->mf_fd);
707
708	    if (fh != 0)
709		Flush(fh);
710#    endif
711	}
712#   else /* assume Manx */
713	    Flush(_devtab[mfp->mf_fd].fd);
714#   endif
715#  endif
716# endif
717#endif /* AMIGA */
718    }
719
720    got_int |= got_int_save;
721
722    return status;
723}
724
725/*
726 * For all blocks in memory file *mfp that have a positive block number set
727 * the dirty flag.  These are blocks that need to be written to a newly
728 * created swapfile.
729 */
730    void
731mf_set_dirty(mfp)
732    memfile_T	*mfp;
733{
734    bhdr_T	*hp;
735
736    for (hp = mfp->mf_used_last; hp != NULL; hp = hp->bh_prev)
737	if (hp->bh_bnum > 0)
738	    hp->bh_flags |= BH_DIRTY;
739    mfp->mf_dirty = TRUE;
740}
741
742/*
743 * insert block *hp in front of hashlist of memfile *mfp
744 */
745    static void
746mf_ins_hash(mfp, hp)
747    memfile_T	*mfp;
748    bhdr_T	*hp;
749{
750    bhdr_T	*hhp;
751    int		hash;
752
753    hash = MEMHASH(hp->bh_bnum);
754    hhp = mfp->mf_hash[hash];
755    hp->bh_hash_next = hhp;
756    hp->bh_hash_prev = NULL;
757    if (hhp != NULL)
758	hhp->bh_hash_prev = hp;
759    mfp->mf_hash[hash] = hp;
760}
761
762/*
763 * remove block *hp from hashlist of memfile list *mfp
764 */
765    static void
766mf_rem_hash(mfp, hp)
767    memfile_T	*mfp;
768    bhdr_T	*hp;
769{
770    if (hp->bh_hash_prev == NULL)
771	mfp->mf_hash[MEMHASH(hp->bh_bnum)] = hp->bh_hash_next;
772    else
773	hp->bh_hash_prev->bh_hash_next = hp->bh_hash_next;
774
775    if (hp->bh_hash_next)
776	hp->bh_hash_next->bh_hash_prev = hp->bh_hash_prev;
777}
778
779/*
780 * look in hash lists of memfile *mfp for block header with number 'nr'
781 */
782    static bhdr_T *
783mf_find_hash(mfp, nr)
784    memfile_T	*mfp;
785    blocknr_T	nr;
786{
787    bhdr_T	*hp;
788
789    for (hp = mfp->mf_hash[MEMHASH(nr)]; hp != NULL; hp = hp->bh_hash_next)
790	if (hp->bh_bnum == nr)
791	    break;
792    return hp;
793}
794
795/*
796 * insert block *hp in front of used list of memfile *mfp
797 */
798    static void
799mf_ins_used(mfp, hp)
800    memfile_T	*mfp;
801    bhdr_T	*hp;
802{
803    hp->bh_next = mfp->mf_used_first;
804    mfp->mf_used_first = hp;
805    hp->bh_prev = NULL;
806    if (hp->bh_next == NULL)	    /* list was empty, adjust last pointer */
807	mfp->mf_used_last = hp;
808    else
809	hp->bh_next->bh_prev = hp;
810    mfp->mf_used_count += hp->bh_page_count;
811    total_mem_used += hp->bh_page_count * mfp->mf_page_size;
812}
813
814/*
815 * remove block *hp from used list of memfile *mfp
816 */
817    static void
818mf_rem_used(mfp, hp)
819    memfile_T	*mfp;
820    bhdr_T	*hp;
821{
822    if (hp->bh_next == NULL)	    /* last block in used list */
823	mfp->mf_used_last = hp->bh_prev;
824    else
825	hp->bh_next->bh_prev = hp->bh_prev;
826    if (hp->bh_prev == NULL)	    /* first block in used list */
827	mfp->mf_used_first = hp->bh_next;
828    else
829	hp->bh_prev->bh_next = hp->bh_next;
830    mfp->mf_used_count -= hp->bh_page_count;
831    total_mem_used -= hp->bh_page_count * mfp->mf_page_size;
832}
833
834/*
835 * Release the least recently used block from the used list if the number
836 * of used memory blocks gets to big.
837 *
838 * Return the block header to the caller, including the memory block, so
839 * it can be re-used. Make sure the page_count is right.
840 */
841    static bhdr_T *
842mf_release(mfp, page_count)
843    memfile_T	*mfp;
844    int		page_count;
845{
846    bhdr_T	*hp;
847    int		need_release;
848    buf_T	*buf;
849
850    /* don't release while in mf_close_file() */
851    if (mf_dont_release)
852	return NULL;
853
854    /*
855     * Need to release a block if the number of blocks for this memfile is
856     * higher than the maximum or total memory used is over 'maxmemtot'
857     */
858    need_release = ((mfp->mf_used_count >= mfp->mf_used_count_max)
859				  || (total_mem_used >> 10) >= (long_u)p_mmt);
860
861    /*
862     * Try to create a swap file if the amount of memory used is getting too
863     * high.
864     */
865    if (mfp->mf_fd < 0 && need_release && p_uc)
866    {
867	/* find for which buffer this memfile is */
868	for (buf = firstbuf; buf != NULL; buf = buf->b_next)
869	    if (buf->b_ml.ml_mfp == mfp)
870		break;
871	if (buf != NULL && buf->b_may_swap)
872	    ml_open_file(buf);
873    }
874
875    /*
876     * don't release a block if
877     *	there is no file for this memfile
878     * or
879     *	the number of blocks for this memfile is lower than the maximum
880     *	  and
881     *	total memory used is not up to 'maxmemtot'
882     */
883    if (mfp->mf_fd < 0 || !need_release)
884	return NULL;
885
886    for (hp = mfp->mf_used_last; hp != NULL; hp = hp->bh_prev)
887	if (!(hp->bh_flags & BH_LOCKED))
888	    break;
889    if (hp == NULL)	/* not a single one that can be released */
890	return NULL;
891
892    /*
893     * If the block is dirty, write it.
894     * If the write fails we don't free it.
895     */
896    if ((hp->bh_flags & BH_DIRTY) && mf_write(mfp, hp) == FAIL)
897	return NULL;
898
899    mf_rem_used(mfp, hp);
900    mf_rem_hash(mfp, hp);
901
902    /*
903     * If a bhdr_T is returned, make sure that the page_count of bh_data is
904     * right
905     */
906    if (hp->bh_page_count != page_count)
907    {
908	vim_free(hp->bh_data);
909	if ((hp->bh_data = alloc(mfp->mf_page_size * page_count)) == NULL)
910	{
911	    vim_free(hp);
912	    return NULL;
913	}
914	hp->bh_page_count = page_count;
915    }
916    return hp;
917}
918
919/*
920 * release as many blocks as possible
921 * Used in case of out of memory
922 *
923 * return TRUE if any memory was released
924 */
925    int
926mf_release_all()
927{
928    buf_T	*buf;
929    memfile_T	*mfp;
930    bhdr_T	*hp;
931    int		retval = FALSE;
932
933    for (buf = firstbuf; buf != NULL; buf = buf->b_next)
934    {
935	mfp = buf->b_ml.ml_mfp;
936	if (mfp != NULL)
937	{
938	    /* If no swap file yet, may open one */
939	    if (mfp->mf_fd < 0 && buf->b_may_swap)
940		ml_open_file(buf);
941
942	    /* only if there is a swapfile */
943	    if (mfp->mf_fd >= 0)
944	    {
945		for (hp = mfp->mf_used_last; hp != NULL; )
946		{
947		    if (!(hp->bh_flags & BH_LOCKED)
948			    && (!(hp->bh_flags & BH_DIRTY)
949				|| mf_write(mfp, hp) != FAIL))
950		    {
951			mf_rem_used(mfp, hp);
952			mf_rem_hash(mfp, hp);
953			mf_free_bhdr(hp);
954			hp = mfp->mf_used_last;	/* re-start, list was changed */
955			retval = TRUE;
956		    }
957		    else
958			hp = hp->bh_prev;
959		}
960	    }
961	}
962    }
963    return retval;
964}
965
966/*
967 * Allocate a block header and a block of memory for it
968 */
969    static bhdr_T *
970mf_alloc_bhdr(mfp, page_count)
971    memfile_T	*mfp;
972    int		page_count;
973{
974    bhdr_T	*hp;
975
976    if ((hp = (bhdr_T *)alloc((unsigned)sizeof(bhdr_T))) != NULL)
977    {
978	if ((hp->bh_data = (char_u *)alloc(mfp->mf_page_size * page_count))
979								      == NULL)
980	{
981	    vim_free(hp);	    /* not enough memory */
982	    return NULL;
983	}
984	hp->bh_page_count = page_count;
985    }
986    return hp;
987}
988
989/*
990 * Free a block header and the block of memory for it
991 */
992    static void
993mf_free_bhdr(hp)
994    bhdr_T	*hp;
995{
996    vim_free(hp->bh_data);
997    vim_free(hp);
998}
999
1000/*
1001 * insert entry *hp in the free list
1002 */
1003    static void
1004mf_ins_free(mfp, hp)
1005    memfile_T	*mfp;
1006    bhdr_T	*hp;
1007{
1008    hp->bh_next = mfp->mf_free_first;
1009    mfp->mf_free_first = hp;
1010}
1011
1012/*
1013 * remove the first entry from the free list and return a pointer to it
1014 * Note: caller must check that mfp->mf_free_first is not NULL!
1015 */
1016    static bhdr_T *
1017mf_rem_free(mfp)
1018    memfile_T	*mfp;
1019{
1020    bhdr_T	*hp;
1021
1022    hp = mfp->mf_free_first;
1023    mfp->mf_free_first = hp->bh_next;
1024    return hp;
1025}
1026
1027/*
1028 * read a block from disk
1029 *
1030 * Return FAIL for failure, OK otherwise
1031 */
1032    static int
1033mf_read(mfp, hp)
1034    memfile_T	*mfp;
1035    bhdr_T	*hp;
1036{
1037    off_t	offset;
1038    unsigned	page_size;
1039    unsigned	size;
1040
1041    if (mfp->mf_fd < 0)	    /* there is no file, can't read */
1042	return FAIL;
1043
1044    page_size = mfp->mf_page_size;
1045    offset = (off_t)page_size * hp->bh_bnum;
1046    size = page_size * hp->bh_page_count;
1047    if (lseek(mfp->mf_fd, offset, SEEK_SET) != offset)
1048    {
1049	PERROR(_("E294: Seek error in swap file read"));
1050	return FAIL;
1051    }
1052    if ((unsigned)vim_read(mfp->mf_fd, hp->bh_data, size) != size)
1053    {
1054	PERROR(_("E295: Read error in swap file"));
1055	return FAIL;
1056    }
1057
1058#ifdef FEAT_CRYPT
1059    /* Decrypt if 'key' is set and this is a data block. */
1060    if (*mfp->mf_buffer->b_p_key != NUL)
1061	ml_decrypt_data(mfp, hp->bh_data, offset, size);
1062#endif
1063
1064    return OK;
1065}
1066
1067/*
1068 * write a block to disk
1069 *
1070 * Return FAIL for failure, OK otherwise
1071 */
1072    static int
1073mf_write(mfp, hp)
1074    memfile_T	*mfp;
1075    bhdr_T	*hp;
1076{
1077    off_t	offset;	    /* offset in the file */
1078    blocknr_T	nr;	    /* block nr which is being written */
1079    bhdr_T	*hp2;
1080    unsigned	page_size;  /* number of bytes in a page */
1081    unsigned	page_count; /* number of pages written */
1082    unsigned	size;	    /* number of bytes written */
1083
1084    if (mfp->mf_fd < 0)	    /* there is no file, can't write */
1085	return FAIL;
1086
1087    if (hp->bh_bnum < 0)	/* must assign file block number */
1088	if (mf_trans_add(mfp, hp) == FAIL)
1089	    return FAIL;
1090
1091    page_size = mfp->mf_page_size;
1092
1093    /*
1094     * We don't want gaps in the file. Write the blocks in front of *hp
1095     * to extend the file.
1096     * If block 'mf_infile_count' is not in the hash list, it has been
1097     * freed. Fill the space in the file with data from the current block.
1098     */
1099    for (;;)
1100    {
1101	nr = hp->bh_bnum;
1102	if (nr > mfp->mf_infile_count)		/* beyond end of file */
1103	{
1104	    nr = mfp->mf_infile_count;
1105	    hp2 = mf_find_hash(mfp, nr);	/* NULL catched below */
1106	}
1107	else
1108	    hp2 = hp;
1109
1110	offset = (off_t)page_size * nr;
1111	if (lseek(mfp->mf_fd, offset, SEEK_SET) != offset)
1112	{
1113	    PERROR(_("E296: Seek error in swap file write"));
1114	    return FAIL;
1115	}
1116	if (hp2 == NULL)	    /* freed block, fill with dummy data */
1117	    page_count = 1;
1118	else
1119	    page_count = hp2->bh_page_count;
1120	size = page_size * page_count;
1121	if (mf_write_block(mfp, hp2 == NULL ? hp : hp2, offset, size) == FAIL)
1122	{
1123	    /*
1124	     * Avoid repeating the error message, this mostly happens when the
1125	     * disk is full. We give the message again only after a successful
1126	     * write or when hitting a key. We keep on trying, in case some
1127	     * space becomes available.
1128	     */
1129	    if (!did_swapwrite_msg)
1130		EMSG(_("E297: Write error in swap file"));
1131	    did_swapwrite_msg = TRUE;
1132	    return FAIL;
1133	}
1134	did_swapwrite_msg = FALSE;
1135	if (hp2 != NULL)		    /* written a non-dummy block */
1136	    hp2->bh_flags &= ~BH_DIRTY;
1137					    /* appended to the file */
1138	if (nr + (blocknr_T)page_count > mfp->mf_infile_count)
1139	    mfp->mf_infile_count = nr + page_count;
1140	if (nr == hp->bh_bnum)		    /* written the desired block */
1141	    break;
1142    }
1143    return OK;
1144}
1145
1146/*
1147 * Write block "hp" with data size "size" to file "mfp->mf_fd".
1148 * Takes care of encryption.
1149 * Return FAIL or OK.
1150 */
1151    static int
1152mf_write_block(mfp, hp, offset, size)
1153    memfile_T	*mfp;
1154    bhdr_T	*hp;
1155    off_t	offset UNUSED;
1156    unsigned	size;
1157{
1158    char_u	*data = hp->bh_data;
1159    int		result = OK;
1160
1161#ifdef FEAT_CRYPT
1162    /* Encrypt if 'key' is set and this is a data block. */
1163    if (*mfp->mf_buffer->b_p_key != NUL)
1164    {
1165	data = ml_encrypt_data(mfp, data, offset, size);
1166	if (data == NULL)
1167	    return FAIL;
1168    }
1169#endif
1170
1171    if ((unsigned)vim_write(mfp->mf_fd, data, size) != size)
1172	result = FAIL;
1173
1174#ifdef FEAT_CRYPT
1175    if (data != hp->bh_data)
1176	vim_free(data);
1177#endif
1178
1179    return result;
1180}
1181
1182/*
1183 * Make block number for *hp positive and add it to the translation list
1184 *
1185 * Return FAIL for failure, OK otherwise
1186 */
1187    static int
1188mf_trans_add(mfp, hp)
1189    memfile_T	*mfp;
1190    bhdr_T	*hp;
1191{
1192    bhdr_T	*freep;
1193    blocknr_T	new_bnum;
1194    int		hash;
1195    NR_TRANS	*np;
1196    int		page_count;
1197
1198    if (hp->bh_bnum >= 0)		    /* it's already positive */
1199	return OK;
1200
1201    if ((np = (NR_TRANS *)alloc((unsigned)sizeof(NR_TRANS))) == NULL)
1202	return FAIL;
1203
1204/*
1205 * Get a new number for the block.
1206 * If the first item in the free list has sufficient pages, use its number
1207 * Otherwise use mf_blocknr_max.
1208 */
1209    freep = mfp->mf_free_first;
1210    page_count = hp->bh_page_count;
1211    if (freep != NULL && freep->bh_page_count >= page_count)
1212    {
1213	new_bnum = freep->bh_bnum;
1214	/*
1215	 * If the page count of the free block was larger, recude it.
1216	 * If the page count matches, remove the block from the free list
1217	 */
1218	if (freep->bh_page_count > page_count)
1219	{
1220	    freep->bh_bnum += page_count;
1221	    freep->bh_page_count -= page_count;
1222	}
1223	else
1224	{
1225	    freep = mf_rem_free(mfp);
1226	    vim_free(freep);
1227	}
1228    }
1229    else
1230    {
1231	new_bnum = mfp->mf_blocknr_max;
1232	mfp->mf_blocknr_max += page_count;
1233    }
1234
1235    np->nt_old_bnum = hp->bh_bnum;	    /* adjust number */
1236    np->nt_new_bnum = new_bnum;
1237
1238    mf_rem_hash(mfp, hp);		    /* remove from old hash list */
1239    hp->bh_bnum = new_bnum;
1240    mf_ins_hash(mfp, hp);		    /* insert in new hash list */
1241
1242    hash = MEMHASH(np->nt_old_bnum);	    /* insert in trans list */
1243    np->nt_next = mfp->mf_trans[hash];
1244    mfp->mf_trans[hash] = np;
1245    if (np->nt_next != NULL)
1246	np->nt_next->nt_prev = np;
1247    np->nt_prev = NULL;
1248
1249    return OK;
1250}
1251
1252/*
1253 * Lookup a translation from the trans lists and delete the entry
1254 *
1255 * Return the positive new number when found, the old number when not found
1256 */
1257    blocknr_T
1258mf_trans_del(mfp, old_nr)
1259    memfile_T	*mfp;
1260    blocknr_T	old_nr;
1261{
1262    int		hash;
1263    NR_TRANS	*np;
1264    blocknr_T	new_bnum;
1265
1266    hash = MEMHASH(old_nr);
1267    for (np = mfp->mf_trans[hash]; np != NULL; np = np->nt_next)
1268	if (np->nt_old_bnum == old_nr)
1269	    break;
1270    if (np == NULL)		/* not found */
1271	return old_nr;
1272
1273    mfp->mf_neg_count--;
1274    new_bnum = np->nt_new_bnum;
1275    if (np->nt_prev != NULL)		/* remove entry from the trans list */
1276	np->nt_prev->nt_next = np->nt_next;
1277    else
1278	mfp->mf_trans[hash] = np->nt_next;
1279    if (np->nt_next != NULL)
1280	np->nt_next->nt_prev = np->nt_prev;
1281    vim_free(np);
1282
1283    return new_bnum;
1284}
1285
1286/*
1287 * Set mfp->mf_ffname according to mfp->mf_fname and some other things.
1288 * Only called when creating or renaming the swapfile.	Either way it's a new
1289 * name so we must work out the full path name.
1290 */
1291    void
1292mf_set_ffname(mfp)
1293    memfile_T	*mfp;
1294{
1295    mfp->mf_ffname = FullName_save(mfp->mf_fname, FALSE);
1296}
1297
1298/*
1299 * Make the name of the file used for the memfile a full path.
1300 * Used before doing a :cd
1301 */
1302    void
1303mf_fullname(mfp)
1304    memfile_T	*mfp;
1305{
1306    if (mfp != NULL && mfp->mf_fname != NULL && mfp->mf_ffname != NULL)
1307    {
1308	vim_free(mfp->mf_fname);
1309	mfp->mf_fname = mfp->mf_ffname;
1310	mfp->mf_ffname = NULL;
1311    }
1312}
1313
1314/*
1315 * return TRUE if there are any translations pending for 'mfp'
1316 */
1317    int
1318mf_need_trans(mfp)
1319    memfile_T	*mfp;
1320{
1321    return (mfp->mf_fname != NULL && mfp->mf_neg_count > 0);
1322}
1323
1324/*
1325 * Open a swap file for a memfile.
1326 * The "fname" must be in allocated memory, and is consumed (also when an
1327 * error occurs).
1328 */
1329    static void
1330mf_do_open(mfp, fname, flags)
1331    memfile_T	*mfp;
1332    char_u	*fname;
1333    int		flags;		/* flags for open() */
1334{
1335#ifdef HAVE_LSTAT
1336    struct stat sb;
1337#endif
1338
1339    mfp->mf_fname = fname;
1340
1341    /*
1342     * Get the full path name before the open, because this is
1343     * not possible after the open on the Amiga.
1344     * fname cannot be NameBuff, because it must have been allocated.
1345     */
1346    mf_set_ffname(mfp);
1347#if defined(MSDOS) || defined(MSWIN) || defined(RISCOS)
1348    /*
1349     * A ":!cd e:xxx" may change the directory without us knowning, use the
1350     * full pathname always.  Careful: This frees fname!
1351     */
1352    mf_fullname(mfp);
1353#endif
1354
1355#ifdef HAVE_LSTAT
1356    /*
1357     * Extra security check: When creating a swap file it really shouldn't
1358     * exist yet.  If there is a symbolic link, this is most likely an attack.
1359     */
1360    if ((flags & O_CREAT) && mch_lstat((char *)mfp->mf_fname, &sb) >= 0)
1361    {
1362	mfp->mf_fd = -1;
1363	EMSG(_("E300: Swap file already exists (symlink attack?)"));
1364    }
1365    else
1366#endif
1367    {
1368	/*
1369	 * try to open the file
1370	 */
1371	flags |= O_EXTRA | O_NOFOLLOW;
1372#ifdef WIN32
1373	/* Prevent handle inheritance that cause problems with Cscope
1374	 * (swap file may not be deleted if cscope connection was open after
1375	 * the file) */
1376	flags |= O_NOINHERIT;
1377#endif
1378	mfp->mf_fd = mch_open_rw((char *)mfp->mf_fname, flags);
1379    }
1380
1381    /*
1382     * If the file cannot be opened, use memory only
1383     */
1384    if (mfp->mf_fd < 0)
1385    {
1386	vim_free(mfp->mf_fname);
1387	vim_free(mfp->mf_ffname);
1388	mfp->mf_fname = NULL;
1389	mfp->mf_ffname = NULL;
1390    }
1391    else
1392    {
1393#ifdef HAVE_FD_CLOEXEC
1394	int fdflags = fcntl(mfp->mf_fd, F_GETFD);
1395	if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0)
1396	    fcntl(mfp->mf_fd, F_SETFD, fdflags | FD_CLOEXEC);
1397#endif
1398#ifdef HAVE_SELINUX
1399	mch_copy_sec(fname, mfp->mf_fname);
1400#endif
1401	mch_hide(mfp->mf_fname);    /* try setting the 'hidden' flag */
1402    }
1403}
1404