SIGTSTP: fix quiet mode.
[tfcrypt.git] / tfc_base64.c
1 /*
2  * tfcrypt -- high security Threefish encryption tool.
3  *
4  * tfcrypt is copyrighted:
5  * Copyright (C) 2012-2019 Andrey Rys. All rights reserved.
6  *
7  * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining
10  * a copy of this software and associated documentation files (the
11  * "Software"), to deal in the Software without restriction, including
12  * without limitation the rights to use, copy, modify, merge, publish,
13  * distribute, sublicense, and/or sell copies of the Software, and to
14  * permit persons to whom the Software is furnished to do so, subject to
15  * the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be
18  * included in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27  */
28
29 #include "tfcrypt.h"
30
31 enum { TFB64_STOP1 = 1, TFB64_STOPF };
32
33 void do_edbase64(char **fargv)
34 {
35         struct base64_decodestate dstate;
36         struct base64_encodestate estate;
37         size_t lread = 0;
38
39         sfd = 0; dfd = 1;
40
41         if (fargv[0]) {
42                 if (!strcmp(fargv[0], "-")) sfd = 0;
43                 else {
44                         sfd = open(fargv[0], O_RDONLY | O_LARGEFILE);
45                         if (do_preserve_time) if (fstat(sfd, &s_stat) == -1)
46                                 xerror(YES, NO, YES, "stat(%s)", fargv[0]);
47                 }
48                 if (sfd == -1) xerror(NO, NO, YES, "%s", fargv[0]);
49         }
50
51         if (fargv[0] && fargv[1]) {
52                 if (!strcmp(fargv[1], "-")) dfd = 1;
53                 else dfd = open(fargv[1], O_WRONLY | O_CREAT | O_LARGEFILE | write_flags, 0666);
54                 if (dfd == -1) xerror(NO, NO, YES, "%s", fargv[1]);
55         }
56
57         if (do_edcrypt == TFC_DO_ENCRYPT) {
58                 memset(&estate, 0, sizeof(struct base64_encodestate));
59                 base64_init_encodestate(&estate);
60         }
61         else if (do_edcrypt == TFC_DO_DECRYPT) {
62                 memset(&dstate, 0, sizeof(struct base64_decodestate));
63                 base64_init_decodestate(&dstate);
64         }
65
66         errno = 0;
67         do_stop = NO;
68         while (1) {
69                 if (do_stop) break;
70                 pblk = srcblk;
71                 lblock = lrem = do_edcrypt == TFC_DO_DECRYPT ? TFC_B64_DWIDTH : TFC_B64_EWIDTH;
72                 ldone = 0;
73                 if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd);
74 _again:         lio = xread(sfd, pblk, lrem);
75                 if (lio == 0) do_stop = TFB64_STOP1;
76                 if (lio != NOSIZE) ldone += lio;
77                 else {
78                         if (errno != EIO && catch_all_errors != YES)
79                                 xerror(NO, NO, NO, "%s", fargv[0]);
80                         switch (error_action) {
81                                 case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", fargv[0]); goto _again; break;
82                                 case TFC_ERRACT_SYNC:
83                                 case TFC_ERRACT_LSYNC:
84                                         xerror(YES, NO, NO, "%s", fargv[0]);
85                                         lio = ldone = lrem = lblock;
86                                         memset(srcblk, 0, lio);
87                                         if (rdpos == NOFSIZE) lseek(sfd, lio, SEEK_CUR);
88                                         else lseek(sfd, rdpos + lio, SEEK_SET);
89                                         break;
90                                 default: xerror(NO, NO, NO, "%s", fargv[0]); break;
91                         }
92                 }
93                 if (lio && lio < lrem) {
94                         pblk += lio;
95                         lrem -= lio;
96                         goto _again;
97                 }
98
99                 if (do_edcrypt == TFC_DO_ENCRYPT) {
100                         estate.count = 0;
101                         base64_encode_block((const char *)srcblk, ldone, (char *)dstblk, &estate);
102                         lread = ldone;
103                         ldone = estate.count;
104                 }
105                 else if (do_edcrypt == TFC_DO_DECRYPT) {
106                         dstate.count = 0;
107                         base64_decode_block((const char *)srcblk, ldone, (char *)dstblk, sizeof(dstblk), &dstate);
108                         ldone = dstate.count;
109                 }
110
111                 pblk = dstblk;
112                 if (ldone == 0) {
113                         do_stop = TFB64_STOPF;
114                         break;
115                 }
116                 lrem = ldone;
117                 ldone = 0;
118 _wagain:        lio = xwrite(dfd, pblk, lrem);
119                 if (lio != NOSIZE) ldone += lio;
120                 else xerror(NO, NO, NO, "%s", fargv[1]);
121                 if (do_edcrypt == TFC_DO_ENCRYPT) {
122                         size_t t;
123                         if (lread >= lblock || do_stop == TFB64_STOPF) {
124                                 t = xwrite(dfd, "\n", 1);
125                                 if (t != NOSIZE) lio += t;
126                                 else lio = NOSIZE;
127                         }
128                 }
129                 if (lio != NOSIZE) ldone += lio;
130                 else xerror(NO, NO, NO, "%s", fargv[1]);
131                 if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", fargv[1]);
132                 if (lio < lrem) {
133                         pblk += lio;
134                         lrem -= lio;
135                         goto _wagain;
136                 }
137         }
138
139         if (do_edcrypt == TFC_DO_ENCRYPT && do_stop == TFB64_STOP1) {
140                 size_t t = estate.count;
141                 pblk = dstblk + estate.count;
142                 base64_encode_blockend((char *)dstblk, &estate);
143                 lrem = estate.count - t;
144                 ldone = 0;
145                 do_stop = TFB64_STOPF;
146                 goto _wagain;
147         }
148
149         memset(&estate, 0, sizeof(struct base64_encodestate));
150         memset(&dstate, 0, sizeof(struct base64_decodestate));
151         if (do_preserve_time) fcopy_matime(dfd, &s_stat);
152         xexit(0);
153 }
154
155 static void base64_eprint(FILE *where, struct base64_encodestate *estate, const char *input, size_t inputl)
156 {
157         static char t[256];
158         ssize_t ix = inputl;
159
160         while (ix > 0) {
161                 memset(t, 0, sizeof(t));
162                 estate->count = 0;
163                 base64_encode_block(input, ix > 128 ? 128 : ix, t, estate);
164                 ix -= 128;
165                 if (ix < 128) base64_encode_blockend(t, estate);
166                 fprintf(where, "%s", t);
167                 fflush(where);
168         }
169
170         memset(t, 0, sizeof(t));
171 }
172
173 void tfc_printbase64(FILE *where, const void *p, size_t n, tfc_yesno nl)
174 {
175         struct base64_encodestate estate;
176         memset(&estate, 0, sizeof(struct base64_encodestate));
177         base64_eprint(where, &estate, (const char *)p, n);
178         if (nl) tfc_nfsay(where, "\n");
179 }