51 broke -E logic completely, rewise it
[tfcrypt.git] / tfc_random.c
index 4b82aee99de018504f09a0686dd43afb1a24ab7e..321f97a6d1c3016e20e5e75048ad62bfa5db9929 100644 (file)
@@ -2,7 +2,7 @@
  * tfcrypt -- high security Threefish encryption tool.
  *
  * tfcrypt is copyrighted:
- * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
+ * Copyright (C) 2012-2019 Andrey Rys. All rights reserved.
  *
  * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
  *
 
 #include "tfcrypt.h"
 
+static void print_crypt_status_genrnd(int signal)
+{
+       print_crypt_status(signal);
+}
+
+static void exit_sigterm_genrnd(int signal)
+{
+       exit_sigterm(signal);
+}
+
 static void get_urandom(const char *src, void *buf, size_t size)
 {
        tfc_byte *ubuf = buf;
@@ -44,7 +54,7 @@ static void get_urandom(const char *src, void *buf, size_t size)
        if (fd == -1) fd = open("/dev/random", O_RDONLY);
        if (fd == -1) xerror(NO, YES, YES, "random source is required (tried %s)", src);
 
-_again:        rd = read(fd, ubuf, sz);
+_again:        rd = xread(fd, ubuf, sz);
        if (rd < sz && rd != NOSIZE) {
                ubuf += rd;
                sz -= rd;
@@ -83,30 +93,34 @@ void tfc_getrandom(void *buf, size_t sz)
 
 void gen_write_bytes(const char *foutname, tfc_fsize offset, tfc_fsize nrbytes)
 {
+       static tfc_fsize wrpos = NOFSIZE;
        int fd, x;
-       size_t lblock;
+       size_t lblock, lio, lrem;
+       tfc_byte *pblk;
 
        for (x = 1; x < NSIG; x++) signal(x, SIG_IGN);
        memset(&sigact, 0, sizeof(sigact));
        sigact.sa_flags = SA_RESTART;
        sigact.sa_handler = print_crypt_status;
        sigaction(SIGUSR1, &sigact, NULL);
-       sigaction(SIGTSTP, &sigact, NULL);
        sigaction(SIGALRM, &sigact, NULL);
-       if (status_timer) setup_next_alarm(status_timer);
+       if (status_timer) setup_next_alarm(status_timer > 1000000 ? 1000000 : status_timer);
        sigact.sa_handler = change_status_width;
        sigaction(SIGQUIT, &sigact, NULL);
        sigact.sa_handler = change_status_timer;
        sigaction(SIGUSR2, &sigact, NULL);
        if (quiet == NO) {
-               sigact.sa_handler = print_crypt_status;
+               sigact.sa_handler = print_crypt_status_genrnd;
                sigaction(SIGINT, &sigact, NULL);
                sigaction(SIGTERM, &sigact, NULL);
+               sigaction(SIGTSTP, &sigact, NULL);
        }
        else {
-               sigact.sa_handler = exit_sigterm;
+               sigact.sa_handler = exit_sigterm_genrnd;
                sigaction(SIGINT, &sigact, NULL);
                sigaction(SIGTERM, &sigact, NULL);
+               sigact.sa_handler = handle_sigtstp;
+               sigaction(SIGTSTP, &sigact, NULL);
        }
        memset(&sigact, 0, sizeof(struct sigaction));
 
@@ -123,30 +137,49 @@ void gen_write_bytes(const char *foutname, tfc_fsize offset, tfc_fsize nrbytes)
                fd = 1;
                foutname = TFC_STDOUT_NAME;
        }
-       else fd = open(foutname, O_WRONLY | O_CREAT | O_LARGEFILE | write_flags, 0666);
-       if (fd == -1) xerror(NO, NO, YES, "%s", foutname);
+       else fd = xopen(foutname, O_WRONLY | O_CREAT | O_LARGEFILE | write_flags);
 
        if (offset) {
                if (lseek(fd, offset, SEEK_SET) == -1)
-                       xerror(YES, NO, NO, "%s: seek failed", foutname);
+                       xerror(ignore_seek_errors, NO, NO, "%s: seek failed", foutname);
        }
 
-       if (ctr_mode == TFC_MODE_PLAIN) memset(srcblk, 0, sizeof(srcblk));
+       if (do_edcrypt == TFC_DO_PLAIN) memset(srcblk, 0, sizeof(srcblk));
 
        if (verbose) tfc_nfsay(stderr, "%s: writing %lld bytes to %s ... ",
-               progname, nrbytes, foutname);
+               tfc_format_pid(progname), nrbytes, foutname);
 
        errno = 0;
        do_stop = NO;
        while (1) {
                if (do_stop) break;
-               lblock = blk_len_adj(nrbytes, total_processed_src, sizeof(srcblk));
-
-               if (ctr_mode != TFC_MODE_PLAIN) tfc_getrandom(srcblk, lblock);
-
-               if (write(fd, srcblk, lblock) == -1)
-                       xerror(NO, NO, YES, "%s", foutname);
+               pblk = srcblk;
+               lblock = lrem = blk_len_adj(nrbytes, total_processed_src, blksize);
+
+               if (do_edcrypt != TFC_DO_PLAIN) tfc_getrandom(srcblk, lblock);
+
+               if (error_action == TFC_ERRACT_SYNC) wrpos = tfc_fdgetpos(fd);
+_wagain:       lio = xwrite(fd, pblk, lrem);
+               if (lio == NOSIZE) {
+                       if (errno != EIO && catch_all_errors != YES)
+                               xerror(NO, NO, YES, "%s", foutname);
+                       switch (error_action) {
+                               case TFC_ERRACT_CONT: xerror(YES, NO, YES, "%s", foutname); goto _wagain; break;
+                               case TFC_ERRACT_SYNC:
+                               case TFC_ERRACT_LSYNC:
+                                       xerror(YES, NO, YES, "%s", foutname);
+                                       if (wrpos == NOFSIZE) lseek(fd, lblock, SEEK_CUR);
+                                       else lseek(fd, wrpos + lblock, SEEK_SET);
+                                       break;
+                               default: xerror(NO, NO, YES, "%s", foutname); break;
+                       }
+               }
                if (do_fsync && fsync(fd) == -1) xerror(NO, NO, YES, "%s", foutname);
+               if (lio < lrem) {
+                       pblk += lio;
+                       lrem -= lio;
+                       goto _wagain;
+               }
 
                total_processed_src += lblock;
                delta_processed += lblock;
@@ -155,7 +188,10 @@ void gen_write_bytes(const char *foutname, tfc_fsize offset, tfc_fsize nrbytes)
        }
 
        if (verbose) tfc_esay("done!");
-       if (verbose || status_timer) print_crypt_status(0);
+       if (verbose || status_timer) {
+               print_crypt_status(TFC_SIGSTAT);
+               tfc_esay("\n");
+       }
 
        xclose(fd);
        xexit(0);