Esempio n. 1
0
int
_unit_bksp(unit *cup)
{
	int		errn;
	unsigned char	tbuf[TBUFSZB], *tp;
	struct ffsw	fst;
	int first_read;

        if (cup->useq == 0)	/* If direct access file */
                return(FEBKSPIV);	/* BACKSPACE invalid on dir. acc.*/

/*
 *      Wait for completion of a preceding asynchronous BUFFER IN/OUT.
 */

	WAITIO(cup, return(cup->uffsw.sw_error));

	if (cup->uwrt) {
		if (cup->utrunc) {
			/*
			 * Truncate file after last sequential write before
			 * this BACKSPACE.
			 */
			errn	= _unit_trunc(cup);
			if (errn != 0)
				return(errn);
		}
		cup->uwrt	= 0;
	}

/*
 *	According to the file structure make the appropriate request to
 *      backspace one logical record. 
 */
	switch( cup->ufs ) {

	case  FS_FDC:
		if ((cup->uend != LOGICAL_ENDFILE) || (cup->uspcproc==1)) {

			errn	= XRCALL(cup->ufp.fdc, backrtn) cup->ufp.fdc,
				&fst);

			if (errn < 0)
				return(fst.sw_error);
		}
		break;
 

	case  FS_TEXT:
	case  STD:
		/*
		 * Can't backspace pipes. sockets, ttys.  
		 */
		if (!cup->useek)
			return(FENOBKPI);	/* can't backspace pipe */
 
		if (!cup->ufmt)		/* if not formatted */
			return(FENOBKSP); /* can't backspace unblocked files */

		if (cup->uend) goto ok;

		first_read = 1;

		for ( ; ; ) {
			ssize_t i;
			size_t	ret;
			_ftelltype x, y;

			y	= LIBFTELL(cup->ufp.std);	
#ifdef KEY /* Bug 1678 */
			if (((_ftelltype) -1) == y) {
			  return FEINTUNK;
			}
#endif /* KEY Bug 1678 */
			x	= y;

			if (x < TBUFSZB)
				x	= 0;
			else
				x -= TBUFSZB;

#ifdef KEY /* Bug 1678 */
			if (LIBFSEEK(cup->ufp.std, x, 0)) {
			  return FEINTUNK;
			}
#else /* KEY Bug 1678 */
			(void) LIBFSEEK(cup->ufp.std, x, 0);
#endif /* KEY Bug 1678 */

			/*
			 * starting at the current character position
			 * minus 2 chars, search backwards for a newline 
			 * character.
			 */

        		ret	= fread(tbuf, 1,(size_t)(y - x), cup->ufp.std);

			if (ret < (y-x) && ferror(cup->ufp.std))
				return(FEBSPNRD);

			/* only the first time fread, we need to skip the
                         * first 2 chars
                         */
                        if (first_read) i = ret - 2;
                        else i = ret;
                        first_read = 0;

			tp	= tbuf;

        		for ( ; i >= 0; i--) {
  				if ( *(tp+i) != '\n') continue;
#ifdef KEY /* Bug 1678 */
				if (LIBFSEEK(cup->ufp.std, (_ftelltype)i+1-ret,
				  1)) {
				  return FEINTUNK;
				}
#else /* KEY Bug 1678 */
				(void) LIBFSEEK(cup->ufp.std, (_ftelltype)i+1-ret, 1);
#endif /* KEY Bug 1678 */
				goto ok;
			}

			if (x == 0) {
#ifdef KEY /* Bug 1678 */
				if (LIBFSEEK(cup->ufp.std, FTELLZERO, 0)) {
				  return FEINTUNK;
				}
#else /* KEY Bug 1678 */
				(void) LIBFSEEK(cup->ufp.std, FTELLZERO, 0);
#endif /* KEY Bug 1678 */
				goto ok;
        		} 
			else
				if (ret <= 0)	/* Should never occur */
					return(FEINTUNK);

#ifdef KEY /* Bug 1678 */
			if (LIBFSEEK(cup->ufp.std, x, 0)) {
			  return FEINTUNK;
			}
#else /* KEY Bug 1678 */
			(void) LIBFSEEK(cup->ufp.std, x, 0);
#endif /* KEY Bug 1678 */
		}
 
	case FS_BIN:
		return(FENOBKSP);


        case FS_AUX:
                errn	= FEMIXAUX;        /* BACKSPACE not allowed on a WAIO,
                                         * MSIO, DRIO, or AQIO file. */
                break;
	default:
		return(FEINTFST);
	}
Esempio n. 2
0
/*
 *	_unit_trunc()
 *
 *		Truncate a file at its current position. 
 *
 *	Return value
 *
 *		0 for OK
 *		error code if an error is encountered
 */
int
_unit_trunc(unit *cup) 
{
	_ftelltype flength;
	FILE	*iop;
 	
	if (cup->useq == 0)	/* If direct access file */ 
		return(0);	/* Don't truncate direct access files */

	switch(cup->ufs) {

	case FS_TEXT:
	case STD:

/*
 *		Truncate the file with trunc(2) if the file is a a regular 
 *		file.  The trunc(2) system call is not allowed on terminal 
 *		files, FIFO piped files, "/dev/null", or sockets.
 */
		if (cup->useek) {
			iop = cup->ufp.std;

			/*
			 * If stream is in O_APPEND mode (as when 'a.out>>ofil')
			 * we call fseek to current position.  Turns out that on
			 * SysV systems, ftell does not flush the buffer.  Thus
			 * the file offset does not get bumped to EOF as the
			 * result of the flush.
			 */
			if (LIBFSEEK(iop, 0, SEEK_CUR) != 0)
				return(errno);

			flength = LIBFTELL(iop);	/* get current position */

			/* position fd to the location of the truncation */
			if (LIBFSEEK(iop, flength, SEEK_SET) != 0)
				return(errno);
#ifdef	_UNICOS
			if (trunc(fileno(iop)) == -1L) 
#else
			if (LIBFTRUNC(fileno(iop), flength) == -1) 
#endif
				return(errno);
#ifdef KEY /* Bug 5386 */
			/* Until Fedora Core 3, this code never encountered
			 * a Unix system that required an "fflush" here. But
			 * without it, the FC3 stdio code doesn't notice that
			 * we've bypassed stdio and truncated the file, and
			 * to be honest, it seems like blind dumb luck that
			 * other systems haven't encountered a problem here.
			 */
			fflush(iop);
#endif /* KEY Bug 5386 */
		}
		break;

	case FS_FDC:
		if (XRCALL(cup->ufp.fdc, weodrtn)cup->ufp.fdc,
			&cup->uffsw) < 0)
			return(cup->uffsw.sw_error);
		break;

	default:
		return(FEINTFST);
	}

	return(0);
}