-O ro: readonly files, never write anything (except to standard streams)
[tfcrypt.git] / tfcrypt.c
index dd137ae6ba4d9ac26d05fd5596bee5c4e9d22d6e..e6d422dbe25277dbf231633021e4f318fac14ee4 100644 (file)
--- a/tfcrypt.c
+++ b/tfcrypt.c
 #include "tfcrypt.h"
 
 static tfc_byte svctr[TF_BLOCK_SIZE];
+static tfc_fsize rwd, do_read_loops, loopcnt;
 
 static void open_log(const char *logfile)
 {
        int fd;
+       tfc_yesno ro;
 
        if (!strcmp(logfile, "-")) return;
 
-       fd = open(logfile, O_WRONLY | O_CREAT | O_LARGEFILE | O_TRUNC, 0666);
-       if (fd == -1) xerror(NO, NO, YES, "%s", logfile);
+       ro = read_only;
+       read_only = NO;
+       fd = xopen(logfile, O_WRONLY | O_CREAT | O_LARGEFILE | O_TRUNC);
+       read_only = ro;
        xclose(2);
        if (dup2(fd, 2) == -1) xexit(2);
        xclose(fd);
@@ -129,7 +133,6 @@ int main(int argc, char **argv)
        double td;
        char *s, *d, *t, *stoi;
        size_t x, n;
-       tfc_fsize rwd;
 
        progpid = getpid();
        progname = basename(argv[0]);
@@ -311,10 +314,16 @@ _baddfname:
                                                write_flags |= O_SYNC;
                                        else if (!strcmp(s, "trunc"))
                                                write_flags |= O_TRUNC;
+                                       else if (!strcmp(s, "append"))
+                                               write_flags |= O_APPEND;
                                        else if (!strcmp(s, "fsync"))
                                                do_fsync = YES;
                                        else if (!strcmp(s, "pad"))
                                                do_pad = YES;
+                                       else if (!strcmp(s, "ro"))
+                                               read_only = YES;
+                                       else if (!strcmp(s, "rw"))
+                                               read_only = NO;
                                        else if (!strcmp(s, "xtime"))
                                                do_preserve_time = YES;
                                        else if (!strcmp(s, "gibsize"))
@@ -339,6 +348,10 @@ _baddfname:
                                                show_when_done = YES;
                                        else if (!strcmp(s, "pid"))
                                                show_pid = YES;
+                                       else if (!strncmp(s, "readloops", 9) && *(s+9) == '=') {
+                                               do_read_loops = tfc_humanfsize(s+10, &stoi);
+                                               if (!str_empty(stoi)) do_read_loops = NOSIZE;
+                                       }
                                        else if (!strncmp(s, "logfile", 7) && *(s+7) == '=')
                                                open_log(s+8);
                                        else if (!strncmp(s, "iobs", 4) && *(s+4) == '=') {
@@ -576,6 +589,7 @@ _baddfname:
                                break;
                        case 'q':
                                quiet = YES;
+                               xexit_no_nl = YES;
                                verbose = NO;
                                do_full_hexdump = NO;
                                status_timer = 0;
@@ -643,8 +657,7 @@ _baddfname:
                if (!strcasecmp(saltf, "disable")) goto _nosalt;
 
                if (!strcmp(saltf, "-")) saltfd = 0;
-               else saltfd = open(saltf, O_RDONLY | O_LARGEFILE);
-               if (saltfd == -1) xerror(NO, NO, YES, "%s", saltf);
+               else saltfd = xopen(saltf, O_RDONLY | O_LARGEFILE);
                lio = xread(saltfd, tfc_salt, TFC_MAX_SALT - TF_FROM_BITS(TFC_KEY_BITS));
                if (lio == NOSIZE) xerror(NO, NO, YES, "%s", saltf);
                tfc_saltsz = lio;
@@ -657,8 +670,7 @@ _nosalt:
                tfc_yesno do_stop;
 
                if (!strcmp(mackeyf, "-")) mkfd = 0;
-               else mkfd = open(mackeyf, O_RDONLY | O_LARGEFILE);
-               if (mkfd == -1) xerror(NO, NO, YES, "%s", mackeyf);
+               else mkfd = xopen(mackeyf, O_RDONLY | O_LARGEFILE);
 
                skein_init(&sk, TFC_KEY_BITS);
 
@@ -733,8 +745,7 @@ _mkragain:          lio = xread(mkfd, pblk, lrem);
        if (argv[idx]) {
                if (password || rawkey > TFC_RAWKEY_KEYFILE) goto _nokeyfd;
                if (!strcmp(argv[idx], "-")) kfd = 0;
-               else kfd = open(argv[idx], O_RDONLY | O_LARGEFILE);
-               if (kfd == -1) xerror(NO, NO, YES, "%s", argv[idx]);
+               else kfd = xopen(argv[idx], O_RDONLY | O_LARGEFILE);
 
                lio = strnlen(argv[idx], PATH_MAX);
                memset(argv[idx], '*', lio);
@@ -762,19 +773,12 @@ _nokeyfd:
        if (argv[idx]) {
                if (!strcmp(argv[idx], "-") && kfd) sfd = 0;
                else {
-                       sfd = open(argv[idx], O_RDONLY | O_LARGEFILE);
+                       sfd = xopen(argv[idx], O_RDONLY | O_LARGEFILE);
                        if (do_preserve_time) if (fstat(sfd, &s_stat) == -1)
                                xerror(YES, NO, YES, "stat(%s)", argv[idx]);
                }
-               if (sfd == -1) xerror(NO, NO, YES, "%s", argv[idx]);
-
-               if (do_edcrypt == TFC_DO_DECRYPT && do_mac != NO && maxlen != NOFSIZE) {
-                       if (verbose) tfc_esay("%s: disabling signature verification on "
-                               "requested partial decryption.", tfc_format_pid(progname));
-                       do_mac = NO;
-               }
 
-               if ((do_mac >= TFC_MAC_VRFY || do_mac == TFC_MAC_DROP) && !do_mac_file) {
+               if ((do_mac >= TFC_MAC_VRFY || do_mac <= TFC_MAC_DROP) && !do_mac_file) {
                        maxlen = tfc_fdsize(sfd);
                        if (maxlen == NOFSIZE)
                                xerror(NO, YES, YES,
@@ -797,8 +801,7 @@ _nokeyfd:
                int ctrfd;
 
                if (!strcmp(counter_file, "-")) ctrfd = 0;
-               else ctrfd = open(counter_file, O_RDONLY | O_LARGEFILE);
-               if (ctrfd == -1) xerror(NO, NO, YES, "%s", counter_file);
+               else ctrfd = xopen(counter_file, O_RDONLY | O_LARGEFILE);
                lio = xread(ctrfd, ctr, ctrsz);
                if (lio == NOSIZE) xerror(NO, NO, YES, "%s", counter_file);
                if (lio < ctrsz) xerror(NO, YES, YES, "counter file is too small (%zu)!", lio);
@@ -998,8 +1001,7 @@ _pwdagain: memset(&getps, 0, sizeof(struct getpasswd_state));
 
                pblk = key;
                if (!strcmp(genkeyf, "-")) krfd = 1;
-               else krfd = open(genkeyf, O_WRONLY | O_CREAT | O_LARGEFILE | write_flags, 0666);
-               if (krfd == -1) xerror(NO, NO, YES, "%s", genkeyf);
+               else krfd = xopen(genkeyf, O_WRONLY | O_CREAT | O_LARGEFILE | write_flags);
 _xts2genkey:   if (xwrite(krfd, pblk, TF_FROM_BITS(TFC_KEY_BITS)) == NOSIZE) xerror(NO, NO, YES, "%s", genkeyf);
                if (do_fsync && fsync(krfd) == -1) xerror(NO, NO, YES, "%s", genkeyf);
                if (verbose && xtskeyset == NO) {
@@ -1021,12 +1023,6 @@ _xts2genkey:     if (xwrite(krfd, pblk, TF_FROM_BITS(TFC_KEY_BITS)) == NOSIZE) xerro
                xexit(0);
        }
 
-       if (iseek_blocks && (do_edcrypt == TFC_DO_DECRYPT && do_mac != NO)) {
-               if (verbose) tfc_esay("%s: disabling signature verification on "
-                       "requested partial decryption.", tfc_format_pid(progname));
-               do_mac = NO;
-       }
-
        if (do_mac != NO) {
                if (mackey_opt == TFC_MACKEY_RAWKEY) skein(mackey, TF_MAX_BITS, key, key, TF_FROM_BITS(TFC_KEY_BITS));
                if (ctr_mode < TFC_MODE_OCB) {
@@ -1076,11 +1072,8 @@ _ctrskip2:
 _plain:
        if (argv[idx]) {
                if (!strcmp(argv[idx], "-")) dfd = 1;
-               else dfd = open(argv[idx], O_RDWR | O_LARGEFILE | write_flags, 0666);
-               if (dfd == -1) {
-                       dfd = open(argv[idx], O_WRONLY | O_CREAT | O_LARGEFILE | write_flags, 0666);
-                       if (dfd == -1) xerror(NO, NO, YES, "%s", argv[idx]);
-               }
+               else dfd = xxopen(YES, argv[idx], O_RDWR | O_LARGEFILE | write_flags);
+               if (dfd == -1) dfd = xopen(argv[idx], O_WRONLY | O_CREAT | O_LARGEFILE | write_flags);
                dstfname = argv[idx];
                idx++;
        }
@@ -1132,6 +1125,7 @@ _ctrwagain:       lio = xwrite(dfd, pblk, lrem);
                        lrem -= lio;
                        goto _ctrwagain;
                }
+               total_written_dst += ldone;
                total_processed_dst += ldone;
                delta_processed += ldone;
        }
@@ -1156,6 +1150,7 @@ _decrypt_again_vrfy2:
        }
 
 _nodecrypt_again_vrfy2:
+       loopcnt = 1;
        errno = 0;
        do_stop = NO;
        while (1) {
@@ -1165,7 +1160,15 @@ _nodecrypt_again_vrfy2:
                lrem = lblock = blk_len_adj(maxlen, total_processed_src, blksize);
                if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd);
 _ragain:       lio = xread(sfd, pblk, lrem);
-               if (lio == 0) do_stop = YES;
+               if (lio == 0) {
+                       if ((do_read_loops != 0 && sfd != 0) && (loopcnt < do_read_loops)) {
+                               lseek(sfd, 0L, SEEK_SET);
+                               loopcnt++;
+                               goto _ragain;
+                       }
+
+                       do_stop = YES;
+               }
                if (lio != NOSIZE) ldone += lio;
                else {
                        if (errno != EIO && catch_all_errors != YES)
@@ -1249,6 +1252,8 @@ _nowrite: total_processed_dst += ldone;
                }
        }
 
+       if (verbose && status_timer && do_statline_dynamic == YES && statline_was_shown == YES) tfc_esay("\n");
+
        errno = 0;
        if (do_mac >= TFC_MAC_VRFY) {
                if (!do_mac_file) {
@@ -1285,8 +1290,7 @@ _macragain:               lio = xread(sfd, pblk, lrem);
                        int mfd;
 
                        if (!strcmp(do_mac_file, "-")) mfd = 0;
-                       else mfd = open(do_mac_file, O_RDONLY | O_LARGEFILE);
-                       if (mfd == -1) xerror(YES, NO, NO, "%s", do_mac_file);
+                       else mfd = xopen(do_mac_file, O_RDONLY | O_LARGEFILE);
                        lio = ldone = xread(mfd, tmpdata, sizeof(tmpdata));
                        if (lio == NOSIZE) xerror(NO, NO, YES, "%s", do_mac_file);
                        if (!memcmp(tmpdata, TFC_ASCII_TFC_MAC_FOURCC, TFC_ASCII_TFC_MAC_FOURCC_LEN)) {
@@ -1326,7 +1330,8 @@ _macragain:               lio = xread(sfd, pblk, lrem);
                        }
                        if (do_mac == TFC_MAC_JUST_VRFY2) {
                                if (verbose) tfc_esay("%s: -u: MAC signature is valid, proceeding with decrypting it again", tfc_format_pid(progname));
-                               do_mac = TFC_MAC_DROP;
+                               maxlen = total_processed_src - SKEIN_DIGEST_SIZE;
+                               do_mac = TFC_MAC_DROP2;
                                goto _decrypt_again_vrfy2;
                        }
                }
@@ -1343,7 +1348,6 @@ _shortmac:        memset(macvrfy, 0, sizeof(macvrfy));
                memset(macresult, 0, sizeof(macresult));
                memset(tmpdata, 0, sizeof(tmpdata));
        }
-
        else if (do_mac == TFC_MAC_SIGN) {
                if (ctr_mode < TFC_MODE_OCB) skein_final(macresult, &sk);
                else skein(macresult, macbits, mackey, macresult, TF_FROM_BITS(macbits));
@@ -1369,6 +1373,7 @@ _macwagain:               lio = xwrite(dfd, pblk, lrem);
                                lrem -= lio;
                                goto _macwagain;
                        }
+                       total_written_dst += ldone;
                        total_processed_dst += ldone;
                        delta_processed += ldone;
                }
@@ -1376,8 +1381,7 @@ _macwagain:               lio = xwrite(dfd, pblk, lrem);
                        int mfd;
 
                        if (!strcmp(do_mac_file, "-")) mfd = 1;
-                       else mfd = open(do_mac_file, O_WRONLY | O_CREAT | O_LARGEFILE | write_flags, 0666);
-                       if (mfd == -1) xerror(YES, NO, NO, "%s", do_mac_file);
+                       else mfd = xopen(do_mac_file, O_WRONLY | O_CREAT | O_LARGEFILE | write_flags);
                        if (do_outfmt == TFC_OUTFMT_B64) {
                                memcpy(macvrfy, tmpdata, TF_FROM_BITS(macbits));
                                memset(tmpdata, 0, TFC_TMPSIZE);
@@ -1400,6 +1404,7 @@ _macwagain:               lio = xwrite(dfd, pblk, lrem);
                memset(macresult, 0, sizeof(macresult));
                memset(tmpdata, 0, sizeof(tmpdata));
        }
+       else if (do_mac == TFC_MAC_DROP2) total_processed_src += SKEIN_DIGEST_SIZE;
 
        if (verbose || status_timer || (do_stop == YES && quiet == NO)) print_crypt_status(0);