📄 bf_torek.c
字号:
** already been committed. If fp is not a buffered file, this is
** equivalent to fclose().
**
** Sets errno:
** any value of errno specified by fclose()
*/
int
bfclose(fp)
FILE *fp;
{
struct bf *bfp;
/* If called on a normal FILE *, call fclose() on it */
if (!bftest(fp))
return fclose(fp);
/* Cast cookie back to correct type */
bfp = (struct bf *)fp->_cookie;
/* Check reference count to see if we actually want to close */
if (bfp != NULL && --bfp->bf_refcount > 0)
return 0;
/*
** In this implementation, just call fclose--the _bfclose
** routine will be called by that
*/
return fclose(fp);
}
/*
** BFTEST -- test if a FILE * is a buffered file
**
** Parameters:
** fp -- FILE * to test
**
** Returns:
** TRUE if fp is a buffered file, FALSE otherwise.
**
** Side Effects:
** none.
**
** Sets errno:
** never.
*/
bool
bftest(fp)
FILE *fp;
{
/*
** Check to see if our special I/O routines are installed
** in this file structure
*/
return ((fp->_close == _bfclose) &&
(fp->_read == _bfread) &&
(fp->_seek == _bfseek) &&
(fp->_write == _bfwrite));
}
/*
** _BFCLOSE -- close a buffered file
**
** Parameters:
** cookie -- cookie of file to close
**
** Returns:
** 0 to indicate success
**
** Side Effects:
** deletes backing file, frees memory.
**
** Sets errno:
** never.
*/
int
_bfclose(cookie)
void *cookie;
{
struct bf *bfp;
/* Cast cookie back to correct type */
bfp = (struct bf *)cookie;
/* Need to clean up the file */
if (bfp->bf_ondisk && !bfp->bf_committed)
unlink(bfp->bf_filename);
/* Need to free the buffer */
if (bfp->bf_bufsize > 0)
free(bfp->bf_buf);
/* Finally, free the structure */
free(bfp);
return 0;
}
/*
** _BFREAD -- read a buffered file
**
** Parameters:
** cookie -- cookie of file to read
** buf -- buffer to fill
** nbytes -- how many bytes to read
**
** Returns:
** number of bytes read or -1 indicate failure
**
** Side Effects:
** none.
**
*/
int
_bfread(cookie, buf, nbytes)
void *cookie;
char *buf;
int nbytes;
{
struct bf *bfp;
int count = 0; /* Number of bytes put in buf so far */
int retval;
/* Cast cookie back to correct type */
bfp = (struct bf *)cookie;
if (bfp->bf_offset < bfp->bf_buffilled)
{
/* Need to grab some from buffer */
count = nbytes;
if ((bfp->bf_offset + count) > bfp->bf_buffilled)
count = bfp->bf_buffilled - bfp->bf_offset;
memcpy(buf, bfp->bf_buf + bfp->bf_offset, count);
}
if ((bfp->bf_offset + nbytes) > bfp->bf_buffilled)
{
/* Need to grab some from file */
if (!bfp->bf_ondisk)
{
/* Oops, the file doesn't exist. EOF. */
goto finished;
}
/* Catch a read() on an earlier failed write to disk */
if (bfp->bf_disk_fd < 0)
{
errno = EIO;
return -1;
}
if (lseek(bfp->bf_disk_fd,
bfp->bf_offset + count, SEEK_SET) < 0)
{
if ((errno == EINVAL) || (errno == ESPIPE))
{
/*
** stdio won't be expecting these
** errnos from read()! Change them
** into something it can understand.
*/
errno = EIO;
}
return -1;
}
while (count < nbytes)
{
retval = read(bfp->bf_disk_fd,
buf + count,
nbytes - count);
if (retval < 0)
{
/* errno is set implicitly by read() */
return -1;
}
else if (retval == 0)
goto finished;
else
count += retval;
}
}
finished:
bfp->bf_offset += count;
return count;
}
/*
** _BFSEEK -- seek to a position in a buffered file
**
** Parameters:
** cookie -- cookie of file to seek
** offset -- position to seek to
** whence -- how to seek
**
** Returns:
** new file offset or -1 indicate failure
**
** Side Effects:
** none.
**
*/
fpos_t
_bfseek(cookie, offset, whence)
void *cookie;
fpos_t offset;
int whence;
{
struct bf *bfp;
/* Cast cookie back to correct type */
bfp = (struct bf *)cookie;
switch (whence)
{
case SEEK_SET:
bfp->bf_offset = offset;
break;
case SEEK_CUR:
bfp->bf_offset += offset;
break;
case SEEK_END:
bfp->bf_offset = bfp->bf_size + offset;
break;
default:
errno = EINVAL;
return -1;
}
return bfp->bf_offset;
}
/*
** _BFWRITE -- write to a buffered file
**
** Parameters:
** cookie -- cookie of file to write
** buf -- data buffer
** nbytes -- how many bytes to write
**
** Returns:
** number of bytes written or -1 indicate failure
**
** Side Effects:
** may create backing file if over memory limit for file.
**
*/
int
_bfwrite(cookie, buf, nbytes)
void *cookie;
const char *buf;
int nbytes;
{
struct bf *bfp;
int count = 0; /* Number of bytes written so far */
int retval;
/* Cast cookie back to correct type */
bfp = (struct bf *)cookie;
/* If committed, go straight to disk */
if (bfp->bf_committed)
{
if (lseek(bfp->bf_disk_fd, bfp->bf_offset, SEEK_SET) < 0)
{
if ((errno == EINVAL) || (errno == ESPIPE))
{
/*
** stdio won't be expecting these
** errnos from write()! Change them
** into something it can understand.
*/
errno = EIO;
}
return -1;
}
count = write(bfp->bf_disk_fd, buf, nbytes);
if (count < 0)
{
/* errno is set implicitly by write() */
return -1;
}
goto finished;
}
if (bfp->bf_offset < bfp->bf_bufsize)
{
/* Need to put some in buffer */
count = nbytes;
if ((bfp->bf_offset + count) > bfp->bf_bufsize)
count = bfp->bf_bufsize - bfp->bf_offset;
memcpy(bfp->bf_buf + bfp->bf_offset, buf, count);
if ((bfp->bf_offset + count) > bfp->bf_buffilled)
bfp->bf_buffilled = bfp->bf_offset + count;
}
if ((bfp->bf_offset + nbytes) > bfp->bf_bufsize)
{
/* Need to put some in file */
if (!bfp->bf_ondisk)
{
/* Oops, the file doesn't exist. */
if (tTd(58, 8))
dprintf("_bfwrite(%s): to disk\n",
bfp->bf_filename);
retval = OPEN(bfp->bf_filename,
O_RDWR | O_CREAT | O_TRUNC,
bfp->bf_filemode, bfp->bf_flags);
/* Couldn't create file: failure */
if (retval < 0)
{
/*
** stdio may not be expecting these
** errnos from write()! Change to
** something which it can understand.
** Note that ENOSPC and EDQUOT are saved
** because they are actually valid for
** write().
*/
if (!((errno == ENOSPC) || (errno == EDQUOT)))
errno = EIO;
return -1;
}
bfp->bf_disk_fd = retval;
bfp->bf_ondisk = TRUE;
}
/* Catch a write() on an earlier failed write to disk */
if (bfp->bf_ondisk && bfp->bf_disk_fd < 0)
{
errno = EIO;
return -1;
}
if (lseek(bfp->bf_disk_fd,
bfp->bf_offset + count, SEEK_SET) < 0)
{
if ((errno == EINVAL) || (errno == ESPIPE))
{
/*
** stdio won't be expecting these
** errnos from write()! Change them into
** something which it can understand.
*/
errno = EIO;
}
return -1;
}
while (count < nbytes)
{
retval = write(bfp->bf_disk_fd, buf + count,
nbytes - count);
if (retval < 0)
{
/* errno is set implicitly by write() */
return -1;
}
else
count += retval;
}
}
finished:
bfp->bf_offset += count;
if (bfp->bf_offset > bfp->bf_size)
bfp->bf_size = bfp->bf_offset;
return count;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -