Skip to content

Commit cae4aa6

Browse files
committed
Rewrite
1 parent 4a7eca6 commit cae4aa6

File tree

3 files changed

+155
-93
lines changed

3 files changed

+155
-93
lines changed

Makefile

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ BIN=img
33
PREFIX?=/usr/local
44
BINDIR=${PREFIX}/bin
55

6-
CFLAGS+=-g
6+
CFLAGS+=-g -O2 -std=c11 -D_POSIX_C_SOURCE=200112L -pedantic -Wall
77

88
.PHONY: build clean install uninstall
99

1010
build: ${BIN}
1111

1212
clean:
13-
-rm ${BIN}
13+
-rm -vf ${BIN}
1414

1515
install: ${BIN}
1616
@mkdir -p ${BINDIR}
1717
cp ${BIN} ${BINDIR}/${BIN}
1818

1919
uninstall:
20-
rm ${BINDIR}/${BIN}
20+
-rm -vf ${BINDIR}/${BIN}

README

+38-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,40 @@
1+
img
2+
13
A tool for working with Forth image files.
24

3-
ISC License :-) Enjoy!
5+
GETTING STARTED
6+
7+
Building and installing
8+
9+
$ make install
10+
...
11+
$
12+
13+
Examples
14+
15+
To create a 1M image file:
16+
17+
$ img -c 1M forth.img
18+
$
19+
20+
To resize an image file:
21+
22+
$ img -r 192B forth.img
23+
$
24+
25+
Process and input data into an image file:
26+
27+
When it appears with an input or output option the -s option operation specifies
28+
an absolute position within the image file.
29+
30+
$ ... | img -s 256B -i 256B forth.img
31+
$
32+
33+
Output and process data from an image file:
34+
35+
$ img -s 256B -o 128B forth.img | ...
36+
$
37+
38+
LICENSE
39+
40+
ISC-style license

img.c

+114-89
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1+
#include <stdint.h>
2+
#include <stdbool.h>
13
#include <stdio.h>
24
#include <stdlib.h>
3-
#include <string.h>
45
#include <unistd.h>
6+
#include <err.h>
57
#include <fcntl.h>
68
#include <sys/stat.h>
79
#include <sys/mman.h>
8-
#include <err.h>
910

1011
extern char *__progname;
1112

1213
void
1314
usage() {
14-
fprintf(stderr, "usage %s [-hv]\n", __progname);
15-
fprintf(stderr, " %s [-hv] -c file size\n", __progname);
16-
fprintf(stderr, " %s [-hv] -t file size\n", __progname);
17-
fprintf(stderr, " %s [-hv] -r file addr size > data\n", __progname);
18-
fprintf(stderr, " %s [-hv] -w file addr size < data\n", __progname);
15+
fprintf(stderr, "usage: %s [-hvf] -c size file\n", __progname);
16+
fprintf(stderr, " %s [-hv] -r size file\n", __progname);
17+
fprintf(stderr, " %s [-hv] [-s addr] -i size file < data\n", __progname);
18+
fprintf(stderr, " %s [-hv] [-s addr] -o size file > data\n", __progname);
1919
exit(1);
2020
}
2121

@@ -44,121 +44,146 @@ int
4444
main(int argc, char *argv[]) {
4545
int vopt;
4646
vopt = 0;
47+
bool fopt;
48+
fopt = false;
49+
bool sopt;
50+
sopt = false;
51+
uintptr_t soptarg;
52+
soptarg = 0;
4753
char mopt;
48-
mopt = 0;
49-
int topt;
50-
topt = 0;
51-
char *ifn;
52-
ifn = NULL;
53-
size_t ms;
54-
ms = 0;
55-
intptr_t a;
56-
a = 0;
57-
size_t ds;
58-
ds = 0;
59-
54+
mopt = '\0';
55+
size_t moptarg;
56+
moptarg = 0;
57+
6058
char ch;
61-
while ((ch = getopt(argc, argv, "hvctrw")) != -1) {
59+
while ((ch = getopt(argc, argv, "hvfs:c:r:i:o:")) != -1) {
6260
switch (ch) {
6361
case 'v':
6462
vopt++;
6563
break;
64+
case 'f':
65+
if (fopt)
66+
usage();
67+
fopt = true;
68+
break;
69+
case 's':
70+
if (sopt)
71+
usage();
72+
sopt = true;
73+
soptarg = eatoi(optarg);
74+
break;
6675
case 'c':
67-
case 't':
6876
case 'r':
69-
case 'w':
70-
if (mopt != 0)
77+
case 'i':
78+
case 'o':
79+
if (mopt != '\0')
7180
usage();
7281
mopt = ch;
82+
moptarg = eatoi(optarg);
7383
break;
7484
case 'h':
7585
default:
7686
usage();
7787
}
7888
}
7989

80-
if (mopt == 0)
90+
if (mopt == '\0')
8191
usage();
82-
83-
argc -= optind;
84-
argv += optind;
8592

8693
switch (mopt) {
8794
case 'c':
88-
case 't':
89-
if (argc != 2)
95+
if (sopt)
9096
usage();
91-
ifn = argv[0];
92-
ms = eatoi(argv[1]);
9397
break;
9498
case 'r':
95-
case 'w':
96-
if (argc != 3)
99+
if (fopt || sopt)
97100
usage();
98-
ifn = argv[0];
99-
int rc;
100-
struct stat ifs;
101-
rc = stat(ifn, &ifs);
102-
if (rc == -1)
103-
err(2, "%s", ifn);
104-
ms = ifs.st_size;
105-
a = eatoi(argv[1]);
106-
ds = eatoi(argv[2]);
107-
}
108-
109-
int ifd;
110-
ifd = open(ifn, O_RDWR);
111-
if (ifd == -1) {
112-
if (mopt == 'c')
113-
ifd = open(ifn, O_RDWR|O_CREAT, 0600);
114-
if (ifd == -1)
115-
err(2, "%s", ifn);
116-
int rc;
117-
rc = ftruncate(ifd, ms);
118-
if (rc == -1)
119-
err(3, NULL);
120-
if (mopt == 'c')
121-
exit(0);
122-
} else {
123-
if (mopt == 'c')
124-
errx(2, "%s: File exists", ifn);
125-
if (mopt == 't') {
126-
int rc;
127-
rc = ftruncate(ifd, ms);
128-
if (rc == -1)
129-
err(3, NULL);
130-
exit(0);
131-
}
101+
break;
102+
case 'i':
103+
case 'o':
104+
if (fopt)
105+
usage();
106+
break;
132107
}
133108

134-
if (a + ds > ms)
135-
errx(4, "Address out of range");
136-
137-
if (ds == 0)
138-
exit(0);
139-
140-
char *e;
141-
e = mmap(NULL, ms, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
142-
if (e == MAP_FAILED)
143-
exit(2);
144-
close(ifd);
109+
argc -= optind;
110+
argv += optind;
111+
112+
if (argc != 1)
113+
usage();
114+
115+
char *ifn;
116+
ifn = argv[0];
145117

146118
switch (mopt) {
119+
case 'c':
147120
case 'r': {
148-
size_t n;
149-
n = fwrite(e + a, sizeof(char), ds, stdout);
150-
if (vopt >= 1)
151-
fprintf(stderr, "Read %zu bytes of %zu bytes\n", n, ds);
121+
int ifd;
122+
if (mopt == 'c') {
123+
if (access(ifn, F_OK) == 0) {
124+
if (!fopt)
125+
errx(2, "%s: File exists", ifn);
126+
int y;
127+
y = unlink(ifn);
128+
if (y != 0)
129+
err(2, "%s", ifn);
130+
}
131+
ifd = open(ifn, O_WRONLY|O_CREAT, 0600);
132+
} else {
133+
if (access(ifn, F_OK) != 0)
134+
errx(2, "%s: File not found", ifn);
135+
ifd = open(ifn, O_WRONLY);
136+
}
137+
if (ifd == -1)
138+
err(2, "%s", ifn);
139+
140+
int y;
141+
y = ftruncate(ifd, moptarg);
142+
if (y == -1)
143+
err(3, NULL);
152144
break;
153145
}
154-
case 'w': {
155-
size_t n;
156-
n = fread(e + a, sizeof(char), ds, stdin);
157-
if (vopt >= 1)
158-
fprintf(stderr, "Wrote %zu bytes of %zu bytes\n", n, ds);
146+
case 'i':
147+
case 'o': {
148+
struct stat ifs;
149+
int y;
150+
y = stat(ifn, &ifs);
151+
if (y == -1)
152+
err(2, "%s", ifn);
153+
size_t mc;
154+
mc = ifs.st_size;
155+
156+
int ifd;
157+
ifd = open(ifn, O_RDWR);
158+
if (ifd == -1)
159+
errx(2, "%s: File not found", ifn);
160+
char *m;
161+
m = mmap(NULL, mc, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
162+
if (m == MAP_FAILED)
163+
err(3, NULL);
164+
close(ifd);
165+
166+
uintptr_t a;
167+
a = soptarg;
168+
size_t dc;
169+
dc = moptarg;
170+
if (a > UINTPTR_MAX - dc || a + dc > mc)
171+
errx(4, "Address out of range");
172+
173+
if (mopt == 'i') {
174+
size_t n;
175+
n = fread(m + a, sizeof(char), dc, stdin);
176+
if (vopt >= 1)
177+
fprintf(stderr, "Wrote %zu bytes of %zu bytes\n", n, dc);
178+
} else {
179+
size_t n;
180+
n = fwrite(m + a, sizeof(char), dc, stdout);
181+
if (vopt >= 1)
182+
fprintf(stderr, "Read %zu bytes of %zu bytes\n", n, dc);
183+
}
184+
185+
munmap(m, mc);
159186
break;
160187
}
161188
}
162-
163-
munmap(e, ms);
164189
}

0 commit comments

Comments
 (0)