Example #1
0
/*
 * Sync the memory file *mfp to disk.
 * Flags:
 *  MFS_ALL	If not given, blocks with negative numbers are not synced,
 *		even when they are dirty!
 *  MFS_STOP	Stop syncing when a character becomes available, but sync at
 *		least one block.
 *  MFS_FLUSH	Make sure buffers are flushed to disk, so they will survive a
 *		system crash.
 *  MFS_ZERO	Only write block 0.
 *
 * Return FAIL for failure, OK otherwise
 */
    int
mf_sync(memfile_T *mfp, int flags)
{
    int		status;
    bhdr_T	*hp;
#if defined(SYNC_DUP_CLOSE)
    int		fd;
#endif
    int		got_int_save = got_int;

    if (mfp->mf_fd < 0)	    /* there is no file, nothing to do */
    {
	mfp->mf_dirty = FALSE;
	return FAIL;
    }

    /* Only a CTRL-C while writing will break us here, not one typed
     * previously. */
    got_int = FALSE;

    /*
     * sync from last to first (may reduce the probability of an inconsistent
     * file) If a write fails, it is very likely caused by a full filesystem.
     * Then we only try to write blocks within the existing file. If that also
     * fails then we give up.
     */
    status = OK;
    for (hp = mfp->mf_used_last; hp != NULL; hp = hp->bh_prev)
	if (((flags & MFS_ALL) || hp->bh_bnum >= 0)
		&& (hp->bh_flags & BH_DIRTY)
		&& (status == OK || (hp->bh_bnum >= 0
		    && hp->bh_bnum < mfp->mf_infile_count)))
	{
	    if ((flags & MFS_ZERO) && hp->bh_bnum != 0)
		continue;
	    if (mf_write(mfp, hp) == FAIL)
	    {
		if (status == FAIL)	/* double error: quit syncing */
		    break;
		status = FAIL;
	    }
	    if (flags & MFS_STOP)
	    {
		/* Stop when char available now. */
		if (ui_char_avail())
		    break;
	    }
	    else
		ui_breakcheck();
	    if (got_int)
		break;
	}

    /*
     * If the whole list is flushed, the memfile is not dirty anymore.
     * In case of an error this flag is also set, to avoid trying all the time.
     */
    if (hp == NULL || status == FAIL)
	mfp->mf_dirty = FALSE;

    if ((flags & MFS_FLUSH) && *p_sws != NUL)
    {
#if defined(UNIX)
# ifdef HAVE_FSYNC
	/*
	 * most Unixes have the very useful fsync() function, just what we need.
	 * However, with OS/2 and EMX it is also available, but there are
	 * reports of bad problems with it (a bug in HPFS.IFS).
	 * So we disable use of it here in case someone tries to be smart
	 * and changes os_os2_cfg.h... (even though there is no __EMX__ test
	 * in the #if, as __EMX__ does not have sync(); we hope for a timely
	 * sync from the system itself).
	 */
#  if defined(__EMX__)
   error "Don't use fsync with EMX! Read emxdoc.doc or emxfix01.doc for info."
#  endif
	if (STRCMP(p_sws, "fsync") == 0)
	{
	    if (fsync(mfp->mf_fd))
		status = FAIL;
	}
	else
# endif
	    /* OpenNT is strictly POSIX (Benzinger) */
	    /* Tandem/Himalaya NSK-OSS doesn't have sync() */
	    /* No sync() on Stratus VOS */
# if defined(__OPENNT) || defined(__TANDEM) || defined(__VOS__)
	    fflush(NULL);
# else
	    sync();
# endif
#endif
#ifdef VMS
	if (STRCMP(p_sws, "fsync") == 0)
	{
	    if (fsync(mfp->mf_fd))
		status = FAIL;
	}
#endif
#ifdef SYNC_DUP_CLOSE
	/*
	 * Win32 is a bit more work: Duplicate the file handle and close it.
	 * This should flush the file to disk.
	 */
	if ((fd = dup(mfp->mf_fd)) >= 0)
	    close(fd);
#endif
#ifdef AMIGA
# if defined(__AROS__) || defined(__amigaos4__)
	if (fsync(mfp->mf_fd) != 0)
	    status = FAIL;
# else
	/*
	 * Flush() only exists for AmigaDos 2.0.
	 * For 1.3 it should be done with close() + open(), but then the risk
	 * is that the open() may fail and lose the file....
	 */
#  ifdef FEAT_ARP
	if (dos2)
#  endif
#  ifdef SASC
	{
	    struct UFB *fp = chkufb(mfp->mf_fd);

	    if (fp != NULL)
		Flush(fp->ufbfh);
	}
#  else
#   if defined(_DCC) || defined(__GNUC__) || defined(__MORPHOS__)
	{
#    if defined(__GNUC__) && !defined(__MORPHOS__) && defined(__libnix__)
	    /* Have function (in libnix at least),
	     * but ain't got no prototype anywhere. */
	    extern unsigned long fdtofh(int filedescriptor);
#    endif
#    if !defined(__libnix__)
	    fflush(NULL);
#    else
	    BPTR fh = (BPTR)fdtofh(mfp->mf_fd);

	    if (fh != 0)
		Flush(fh);
#    endif
	}
#   else /* assume Manx */
	    Flush(_devtab[mfp->mf_fd].fd);
#   endif
#  endif
# endif
#endif /* AMIGA */
    }
Example #2
0
/*
 * rpipe() - gets a `cmd' to run and a `file descriptor' to use as its stdin.
 */
int
rpipe(UBYTE * cmd, int fd)
{
    BPTR         fdFH = 0,	/* FileHandle of passed file descriptor */
                 outPH = 0,	/* Pipe (File) Handle for child to write to. */
                 inPH = 0,	/* Pipe (File) Handle for child to read from. */
                 lock = 0;
    int          fdr = 0;
    char         pname[32], *pc;
    extern char  o_shell[];

    if (isOldDOS())
	return -1;

    /*-
     * Sorry, I'm playing with an AZTEC internal here:
     * _devtab[fd].fd is Aztec's FileHandle for the file descriptor `fd'.
     * 
     * HINT: For your compiler, look in your compiler's fcntl.h.
     */

    switch (fd)
    {
    case 0:
	inPH = Open((UBYTE *) "*", MODE_READWRITE);
	break;
    default:

#ifdef	AZTEC_C
	fdFH = _devtab[fd].fd;		/* Grab FileHandle from fd */
#elif	_DCC
	fdFH = fdtofh(fd);		/* DCC does it right! */
#else
	return -1;			/* Sorry, can't help you. */
#endif

	/*
	 * Get a FileHandle to use for the child's stdin.
	 * The only reason we Dup is because we'll run the child ASynch,
	 * and it will close its Input and Output on exit.
	 */
	lock = DupLockFromFH(fdFH);
	if (!lock)
	    return -1;
	inPH = OpenFromLock(lock);
    }

    if (!inPH)
    {
	if (lock)
	    UnLock(lock);
	return -1;
    }

    /*
     * Get a pipe to use for the child's stdout, which we will read from.
     */
    strcpy(pname, "PIPE:ElvisXXX.XXX");
    pc = mktemp(pname);			/* Get a unique PIPE: */
    if (!*pc)
    {
    	Close(inPH);
	return -1;			/* Failure. */
    }

    /*
     * Get a FileHandle to use for the child's stdout.
     */
    if ((BPTR) 0 == (outPH = Open((UBYTE *) pc, MODE_NEWFILE)))
    {
	Close(inPH);
	return -1;			/* Failure. */
    }

    /* Get a file descriptor to return to the calling function */
    if ((fdr = open(pc, O_RDONLY)) < 0)
    {
	Close(inPH);
	Close(outPH);
	return -1;			/* Failure. */
    }

    /* exec the cmd */
    systags[0].ti_Data = inPH;		/* Input FileHandle for child */
    systags[1].ti_Data = outPH;		/* Output FileHandle for child */
    systags[2].ti_Data = (long) o_shell;/* which shell to use */

    if (System((UBYTE *) cmd, systags))
    {
	close(fdr);
	return -1;			/* Failure. */
    }

    return fdr;				/* Success! */
}