|
| 1 | +#include <stdint.h> |
| 2 | +#include <stdbool.h> |
1 | 3 | #include <stdio.h>
|
2 | 4 | #include <stdlib.h>
|
3 |
| -#include <string.h> |
4 | 5 | #include <unistd.h>
|
| 6 | +#include <err.h> |
5 | 7 | #include <fcntl.h>
|
6 | 8 | #include <sys/stat.h>
|
7 | 9 | #include <sys/mman.h>
|
8 |
| -#include <err.h> |
9 | 10 |
|
10 | 11 | extern char *__progname;
|
11 | 12 |
|
12 | 13 | void
|
13 | 14 | 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); |
19 | 19 | exit(1);
|
20 | 20 | }
|
21 | 21 |
|
@@ -44,121 +44,146 @@ int
|
44 | 44 | main(int argc, char *argv[]) {
|
45 | 45 | int vopt;
|
46 | 46 | vopt = 0;
|
| 47 | + bool fopt; |
| 48 | + fopt = false; |
| 49 | + bool sopt; |
| 50 | + sopt = false; |
| 51 | + uintptr_t soptarg; |
| 52 | + soptarg = 0; |
47 | 53 | 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 | + |
60 | 58 | char ch;
|
61 |
| - while ((ch = getopt(argc, argv, "hvctrw")) != -1) { |
| 59 | + while ((ch = getopt(argc, argv, "hvfs:c:r:i:o:")) != -1) { |
62 | 60 | switch (ch) {
|
63 | 61 | case 'v':
|
64 | 62 | vopt++;
|
65 | 63 | 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; |
66 | 75 | case 'c':
|
67 |
| - case 't': |
68 | 76 | case 'r':
|
69 |
| - case 'w': |
70 |
| - if (mopt != 0) |
| 77 | + case 'i': |
| 78 | + case 'o': |
| 79 | + if (mopt != '\0') |
71 | 80 | usage();
|
72 | 81 | mopt = ch;
|
| 82 | + moptarg = eatoi(optarg); |
73 | 83 | break;
|
74 | 84 | case 'h':
|
75 | 85 | default:
|
76 | 86 | usage();
|
77 | 87 | }
|
78 | 88 | }
|
79 | 89 |
|
80 |
| - if (mopt == 0) |
| 90 | + if (mopt == '\0') |
81 | 91 | usage();
|
82 |
| - |
83 |
| - argc -= optind; |
84 |
| - argv += optind; |
85 | 92 |
|
86 | 93 | switch (mopt) {
|
87 | 94 | case 'c':
|
88 |
| - case 't': |
89 |
| - if (argc != 2) |
| 95 | + if (sopt) |
90 | 96 | usage();
|
91 |
| - ifn = argv[0]; |
92 |
| - ms = eatoi(argv[1]); |
93 | 97 | break;
|
94 | 98 | case 'r':
|
95 |
| - case 'w': |
96 |
| - if (argc != 3) |
| 99 | + if (fopt || sopt) |
97 | 100 | 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; |
132 | 107 | }
|
133 | 108 |
|
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]; |
145 | 117 |
|
146 | 118 | switch (mopt) {
|
| 119 | + case 'c': |
147 | 120 | 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); |
152 | 144 | break;
|
153 | 145 | }
|
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); |
159 | 186 | break;
|
160 | 187 | }
|
161 | 188 | }
|
162 |
| - |
163 |
| - munmap(e, ms); |
164 | 189 | }
|
0 commit comments