Compare commits

...

3 Commits

2 changed files with 75 additions and 29 deletions

View File

@ -4,7 +4,7 @@
.\" This work is licensed under CC BY-SA 4.0. To see a copy of this license,
.\" visit <http://creativecommons.org/licenses/by-sa/4.0/>.
.\"
.TH DJ 1 2024-06-29 "Harakit X.X.X"
.TH DJ 1 2024-07-03 "Harakit X.X.X"
.SH NAME
dj \(en disk jockey
.\"
@ -34,10 +34,17 @@ respectively. This language is inherited from the
.BR dd (1p)
utility and used here to decrease ambiguity.
When seeking or skipping to a byte, writing or reading starts at the byte
immediately subsequent to the specified byte. Seeks and skips aren\(cqt counted
in the output statistics because they're guaranteed to succeed (or the utility
will exit unsuccessfully).
The offset used when skipping or seeking refers to how many bytes are skipped
or sought. Running
.BR dj (1)
with a skip offset of 1 skips one byte into the input and reads from the second
byte onwards. A programmer may think of a file as a zero-indexed array of
bytes; in this analogy, the offset given is the index of the byte at which to
start reading or writing.
Seeks and skips aren\(cqt counted in the output statistics because they're
guaranteed to succeed (or the utility will exit unsuccessfully, before it has
written any data).
.\"
.SH OPTIONS
@ -82,6 +89,54 @@ input file is \(lq-\(rq.
The standard output shall be used as an output if no inputs are specified or if
the output file is \(lq-\(rq.
.\"
.SH EXAMPLES
The following
.BR sh (1p)
line:
.RS
printf 'Hello, world!\(rsn' | dj -c 1 -b 7 -s 7 2>/dev/null
.RE
Produces the following output:
.RS
world!
.RE
The following
.BR sh (1p)
lines run sequentially:
.RS
tr '\(rs0' 0 </dev/zero | dj -c 1 -b 6 -o hello.txt
tr '\(rs0' H </dev/zero | dj -c 1 -b 1 -o hello.txt
tr '\(rs0' e </dev/zero | dj -c 1 -b 1 -o hello.txt -S 1
tr '\(rs0' l </dev/zero | dj -c 1 -b 2 -o hello.txt -S 2
tr '\(rs0' o </dev/zero | dj -c 1 -b 1 -o hello.txt -S 4
tr '\(rs0' '\(rsn' </dev/zero | dj -c 1 -b 1 -o hello.txt -S 5
dj -i hello.txt
.RE
Produce the following output:
.RS
Hello
.RE
It may be particularly illuminating to print the contents of the example
.B hello.txt
after each
.BR dj (1)
invocation.
.\"
.SH DIAGNOSTICS
On a partial or empty read, a diagnostic message is printed. Then, the program

View File

@ -35,15 +35,15 @@ char *program_name = "dj";
* writing ends of its jockeyed "pipe". User-configurable members are noted
* with their relevant options. */
struct Io{
int bs; /* buffer size (-bB) */
int bs; /* buffer size (-bB) */
size_t bufuse; /* buffer usage */
char *buf; /* buffer */
int bytes; /* bytes processed */
size_t bytes; /* bytes processed */
int fd; /* file descriptor */
int fl; /* file opening flags */
char *fn; /* file name (may be stdin_name or stdout_name) (-io) */
int prec; /* partial records processed */
int rec; /* records processed */
size_t prec; /* partial records processed */
size_t rec; /* records processed */
long seek; /* bytes to seek/skip (will be 0 after skippage) (-sS) */
};
@ -75,25 +75,6 @@ Io_bufrpad(struct Io *io, int padding){
return io;
}
/* Copies from the buffer in src as much as possible to the free space in the
* dest buffer, removing the copied units from src and permuting the remaining
* units in the src buffer to the start of the buffer, modifying both the src
* and dest bufuse and returning dest. */
static struct Io*
Io_bufxapp(struct Io *dest, struct Io *src){
int n;
assert(dest != NULL && src != NULL);
n = MIN(src->bufuse, dest->bs - dest->bufuse);
memcpy(dest->buf + dest->bufuse, src->buf, n);
dest->bufuse += n;
memmove(src->buf, src->buf + n, src->bs - n);
src->bufuse -= n;
return dest;
}
/* Copies from the buffer in src to the buffer in dest no more than n units,
* removing the copied units from src and permuting the remaining units in the
* src buffer to the start of the buffer, modifying both the src and dest
@ -216,6 +197,7 @@ int main(int argc, char *argv[]){
noerror = 0;
for(i = 0; i < 2; ++i){
io[i].bs = 1024 /* 1 KiB */; /* GNU dd(1) default; POSIX says 512B */
io[i].bufuse = 0;
io[i].bytes = 0;
io[i].fd = i == 0 ? STDIN_FILENO : STDOUT_FILENO;
io[i].fn = i == 0 ? stdin_name : stdout_name;
@ -338,7 +320,16 @@ int main(int argc, char *argv[]){
int t;
if(io[1].bs > io[0].bs){
Io_bufxapp(&io[1], &io[0]);
int n;
/* copy from ibuf as much as possible to the obuf */
memcpy(io[1].buf + io[1].bufuse, io[0].buf,
(n = MIN(io[0].bufuse, io[1].bs - io[1].bufuse)));
io[1].bufuse += n;
/* permute out the copied units */
memmove(io[0].buf, io[0].buf + n, io[0].bs - n);
io[0].bufuse -= n;
if(io[0].bs + io[1].bufuse <= io[1].bs && count != 1)
continue; /* we could write more */
}else