dj(1): Refactor out Io_fdseek entirely

This commit is contained in:
dtb 2024-07-03 16:07:02 -06:00
parent 66ca4b9a12
commit 944feef434
Signed by: trinity
GPG Key ID: 34C0543BBB6AF81B

View File

@ -129,52 +129,6 @@ Io_fdopen(struct Io *io, char *fn){
return fd; return fd;
} }
/* Seeks io->seek bytes through *io's file descriptor, subtracting the number
* of sought bytes from io->seek. This procedure leaves garbage in io->buf.
* Read/written bytes here aren't counted in the statistics because successful
* seeking is guaranteed. */
static void
Io_fdseek(struct Io *io){
assert(io != NULL);
assert(io->fd != STDIN_FILENO || io->fl == read_flags);
assert(io->fd != STDOUT_FILENO || io->fl == write_flags);
if(io->seek == 0
|| (!fdisstd(io->fd) && lseek(io->fd, io->seek, SEEK_SET) != -1)){
io->seek = 0;
return;
}
if(io->fl == write_flags)
memset(io->buf, '\0', io->bs);
if(io->fl == write_flags){
memset(io->buf, '\0', io->bs);
/* We're going to cheat and use bufuse as the retval for write(2),
* which is fine because it'll be zeroed as this function returns
* anyway. */
do{
if((io->bufuse = write(io->fd, io->buf, MIN(io->bs, io->seek)))
== 0)
/* second chance */
io->bufuse = write(io->fd, io->buf, MIN(io->bs, io->seek));
}while((io->seek -= io->bufuse) > 0 && io->bufuse != 0);
}else if(io->fl == read_flags){
do{
if((io->bufuse = read(io->fd, io->buf, MIN(io->bs, io->seek)))
== 0)
/* second chance */
io->bufuse = read(io->fd, io->buf, MIN(io->bs, io->seek));
}while((io->seek -= io->bufuse) > 0 && io->bufuse != 0);
}else
assert(0); /* UNREACHABLE */
io->bufuse = 0;
return;
}
/* Reads io->bs bytes from *io's file descriptor into io->buf, storing the /* Reads io->bs bytes from *io's file descriptor into io->buf, storing the
* number of read bytes in io->bufuse and updating io->bytes. If io->bufuse is * number of read bytes in io->bufuse and updating io->bytes. If io->bufuse is
* 0, errno will probably be set. Returns io. */ * 0, errno will probably be set. Returns io. */
@ -307,24 +261,61 @@ int main(int argc, char *argv[]){
} }
} }
assert(io->fd != STDIN_FILENO || io->fl == read_flags);
assert(io->fd != STDOUT_FILENO || io->fl == write_flags);
if(argc > optind){ if(argc > optind){
return usage(program_name); return usage(program_name);
} }
for(i = 0; i < 2; ++i){ for(i = 0; i < 2; ++i){
/* buffer allocation */
if((io[i].buf = malloc(io[i].bs * (sizeof *(io[i].buf)))) == NULL){ if((io[i].buf = malloc(io[i].bs * (sizeof *(io[i].buf)))) == NULL){
fprintf(stderr, "%s: Failed to allocate %d bytes\n", fprintf(stderr, "%s: Failed to allocate %d bytes\n",
program_name, io[i].bs); program_name, io[i].bs);
return EX_OSERR; return EX_OSERR;
}else if(io[i].seek > 0){
Io_fdseek(&io[i]);
if(io[i].seek > 0){
return oserr(io[i].fn);
}
} }
/* easy seeking */
if(!fdisstd(io[i].fd) && lseek(io[i].fd, io[i].seek, SEEK_SET) != -1)
io[i].seek = 0;
} }
/* hard skipping */
if(io[0].seek > 0){
do{
if((io[0].bufuse = read(
io[0].fd, io[0].buf, MIN(io[0].bs, io[0].seek)))
== 0)
/* second chance */
io->bufuse = read(
io[0].fd, io[0].buf, MIN(io[0].bs, io[0].seek));
}while((io[0].seek -= io[0].bufuse) > 0 && io[0].bufuse != 0);
io[0].bufuse = 0;
}
/* hard seeking */
if(io[1].seek > 0){
memset(io[1].buf, '\0', io[1].bs);
/* We're going to cheat and use bufuse as the retval for write(2),
* which is fine because it'll be zeroed as this function returns
* anyway. */
do{
if((io[1].bufuse = write(
io[1].fd, io[1].buf, MIN(io[1].bs, io[1].seek)))
== 0)
/* second chance */
io[1].bufuse = write(
io[1].fd, io[1].buf, MIN(io[1].bs, io[1].seek));
}while((io[1].seek -= io[1].bufuse) > 0 && io[1].bufuse != 0);
io[1].bufuse = 0;
}
/* Sought bytes aren't counted in the statistics because successful seeking
* is guaranteed here. */
for(i = 0; i < 2; ++i)
if(io[i].seek > 0)
return oserr(io[i].fn);
do{ /* read */ do{ /* read */
Io_read(&io[0]); Io_read(&io[0]);
if(!noerror && io[0].bufuse == 0) if(!noerror && io[0].bufuse == 0)