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); }
/* * _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); }