bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
0
|
// base64.c, version 1.0.1 |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
1
|
// OMKOV coreutils base64 |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
2
|
// Copyright (C) 2021, Jakob Wakeling |
e2140ec |
Jamozed |
2022-03-06 15:27:45 |
3
|
// MIT Licence |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
4
|
|
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
5
|
/* |
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
6
|
TODO Improve or replace fgetb64. |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
7
|
*/ |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
8
|
|
b181413 |
Jamozed |
2022-02-05 22:32:00 |
9
|
#include "util/base64.h" |
b181413 |
Jamozed |
2022-02-05 22:32:00 |
10
|
#include "util/error.h" |
b181413 |
Jamozed |
2022-02-05 22:32:00 |
11
|
#include "util/optget.h" |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
12
|
|
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
13
|
#include <ctype.h> |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
14
|
#include <stdbool.h> |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
15
|
#include <stdint.h> |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
16
|
#include <stdio.h> |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
17
|
|
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
18
|
#define VERSION "1.0.1" |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
19
|
|
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
20
|
static struct lop lops[] = { |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
21
|
{ "help", ARG_NUL, 256 }, |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
22
|
{ "version", ARG_NUL, 257 }, |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
23
|
{ NULL, 0, 0 } |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
24
|
}; |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
25
|
|
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
26
|
static bool dflag; |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
27
|
|
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
28
|
static inline int base64(const char *file); |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
29
|
static void encodeBase64(FILE *fi); |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
30
|
static void decodeBase64(FILE *fi); |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
31
|
|
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
32
|
static void wwrite(const uint8_t *p, size_t l, size_t c, size_t *cl, FILE *fi); |
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
33
|
static inline size_t fgetb64(uint8_t *buf, size_t len, FILE *fi); |
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
34
|
|
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
35
|
static void hlp(void); |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
36
|
static void ver(void); |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
37
|
|
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
38
|
int main(int ac, char *av[]) { A0 = av[0]; |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
39
|
struct opt opt = OPTGET_INIT; opt.str = "d"; opt.lops = lops; |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
40
|
for (int o; (o = optget(&opt, av, 1)) != -1;) switch (o) { |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
41
|
case 'd': { dflag = true; break; } |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
42
|
case 256: { hlp(); return 0; } |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
43
|
case 257: { ver(); return 0; } |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
44
|
default: { return 1; } |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
45
|
} |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
46
|
|
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
47
|
if (opt.ind == ac) { base64(NULL); } |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
48
|
else if (opt.ind != ac - 1) { error(1, "extra operand"); } |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
49
|
else if (base64(av[opt.ind])) { error(1, "%s: %s", av[opt.ind], serr()); } |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
50
|
|
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
51
|
return 0; |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
52
|
} |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
53
|
|
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
54
|
/* |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
55
|
Base64 encode or decode a file. |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
56
|
If the file path given is null, then use stdin. |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
57
|
*/ |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
58
|
static inline int base64(const char *file) { |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
59
|
FILE *fi; |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
60
|
|
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
61
|
if (file == NULL) { fi = stdin; } |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
62
|
else if (!(fi = fopen(file, "r"))) { return 1; } |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
63
|
|
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
64
|
if (dflag) { decodeBase64(fi); } else { encodeBase64(fi); } |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
65
|
|
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
66
|
if (fi != stdin) { fclose(fi); } return 0; |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
67
|
} |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
68
|
|
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
69
|
/* Encode base64 using fixed size buffers */ |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
70
|
static void encodeBase64(FILE *fi) { |
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
71
|
uint8_t ibuf[BUFSIZ * 12]; uint8_t obuf[BUFSIZ * 16]; size_t cl = 0; |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
72
|
|
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
73
|
for (register size_t c; (c = fread(ibuf, 1, sizeof (ibuf), fi));) { |
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
74
|
c = b64encode(obuf, ibuf, c); wwrite(obuf, c, 76, &cl, stdout); |
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
75
|
} fputc('\n', stdout); return; |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
76
|
} |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
77
|
|
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
78
|
/* Decode base64 using fixed size buffers */ |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
79
|
static void decodeBase64(FILE *fi) { |
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
80
|
uint8_t ibuf[BUFSIZ * 16]; uint8_t obuf[BUFSIZ * 12]; |
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
81
|
|
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
82
|
for (register size_t c; (c = fgetb64(ibuf, sizeof (ibuf), fi));) { |
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
83
|
c = b64decode(obuf, ibuf, c); fwrite(obuf, 1, c, stdout); |
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
84
|
} return; |
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
85
|
} |
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
86
|
|
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
87
|
/* Write string with wrapping */ |
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
88
|
static void wwrite(const uint8_t *p, size_t l, size_t c, size_t *cl, FILE *fi) { |
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
89
|
for (size_t w = 0; w < l;) { |
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
90
|
size_t cr = c - *cl < l - w ? c - *cl : l - w; |
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
91
|
|
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
92
|
if (!cr) { fputc('\n', fi); *cl = 0; } |
bb4ca85 |
Jamozed |
2021-02-22 16:00:20 |
93
|
else { fwrite(p + w, 1, cr, fi); w += cr; *cl += cr; } |
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
94
|
} |
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
95
|
} |
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
96
|
|
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
97
|
/* Read valid Base64 characters from a file */ |
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
98
|
static inline size_t fgetb64(uint8_t *buf, size_t len, FILE *fi) { |
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
99
|
size_t i = 0; for (int c; (c = fgetc(fi)) != EOF;) { |
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
100
|
if (isalnum(c) || c == '+' || c == '/') { buf[i++] = c; } |
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
101
|
if (i == len) { break; } |
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
102
|
} return i; |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
103
|
} |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
104
|
|
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
105
|
/* Print help information */ |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
106
|
static void hlp(void) { |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
107
|
puts("base64 - base64 encode or decode data\n"); |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
108
|
puts("usage: base64 [-d] [file]\n"); |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
109
|
puts("options:"); |
7ce4bd4 |
Jamozed |
2021-02-06 00:53:24 |
110
|
puts(" -d Decode data"); |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
111
|
puts(" --help Display help information"); |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
112
|
puts(" --version Display version information"); |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
113
|
} |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
114
|
|
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
115
|
/* Print version information */ |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
116
|
static void ver(void) { |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
117
|
puts("OMKOV coreutils base64, version " VERSION); |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
118
|
puts("Copyright (C) 2021, Jakob Wakeling"); |
e2140ec |
Jamozed |
2022-03-06 15:27:45 |
119
|
puts("MIT Licence (https://opensource.org/licenses/MIT)"); |
195ab4c |
Jamozed |
2021-01-11 15:26:50 |
120
|
} |
|
|
|
121
|
|