tfc_io: xread and xwrite, which transparently handle EINTR case.
[tfcrypt.git] / tfcrypt.c
index c544cfd01ee256be65a17ae622f1aab07e4ffc3a..8608cf16011399202e66f08b8855211c6368a56e 100644 (file)
--- a/tfcrypt.c
+++ b/tfcrypt.c
@@ -177,6 +177,8 @@ int main(int argc, char **argv)
                                        error_action = TFC_ERRACT_CONT;
                                else if (!strcmp(optarg, "sync"))
                                        error_action = TFC_ERRACT_SYNC;
+                               else if (!strcmp(optarg, "lsync"))
+                                       error_action = TFC_ERRACT_LSYNC;
                                else xerror(NO, YES, YES, "invalid error action %s specified", optarg);
                                break;
                        case 'O':
@@ -480,7 +482,7 @@ int main(int argc, char **argv)
                if (!strcmp(saltf, "-")) saltfd = 0;
                else saltfd = open(saltf, O_RDONLY | O_LARGEFILE);
                if (saltfd == -1) xerror(NO, NO, YES, "%s", saltf);
-               lio = read(saltfd, tfc_salt, TFC_MAX_SALT - TF_FROM_BITS(TFC_KEY_BITS));
+               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;
                xclose(saltfd);
@@ -503,7 +505,8 @@ _nosalt:
                        pblk = tmpdata;
                        ldone = 0;
                        lrem = lblock = sizeof(tmpdata);
-_mkragain:             lio = read(mkfd, pblk, lrem);
+                       if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(mkfd);
+_mkragain:             lio = xread(mkfd, pblk, lrem);
                        if (lio == 0) do_stop = YES;
                        if (lio != NOSIZE) ldone += lio;
                        else {
@@ -512,10 +515,12 @@ _mkragain:                lio = read(mkfd, pblk, lrem);
                                switch (error_action) {
                                        case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", mackeyf); goto _mkragain; break;
                                        case TFC_ERRACT_SYNC:
+                                       case TFC_ERRACT_LSYNC:
                                                xerror(YES, NO, NO, "%s", mackeyf);
                                                lio = ldone = lrem = lblock;
                                                memset(tmpdata, 0, lio);
-                                               lseek(mkfd, lio, SEEK_CUR);
+                                               if (rdpos == NOFSIZE) lseek(mkfd, lio, SEEK_CUR);
+                                               else lseek(mkfd, rdpos + lio, SEEK_SET);
                                                break;
                                        default: xerror(NO, NO, NO, "%s", mackeyf); break;
                                }
@@ -588,7 +593,7 @@ _mkragain:          lio = read(mkfd, pblk, lrem);
                if (!strcmp(tweakf, "-")) twfd = 0;
                else twfd = open(tweakf, O_RDONLY | O_LARGEFILE);
                if (twfd == -1) xerror(NO, NO, YES, "%s", tweakf);
-               lio = ldone = read(twfd, key+TF_FROM_BITS(TF_MAX_BITS)+TF_SIZE_UNIT, 2*TF_SIZE_UNIT);
+               lio = ldone = xread(twfd, key+TF_FROM_BITS(TF_MAX_BITS)+TF_SIZE_UNIT, 2*TF_SIZE_UNIT);
                if (lio == NOSIZE) xerror(NO, NO, YES, "%s", tweakf);
                if (ldone < 2*TF_SIZE_UNIT)
                        xerror(NO, NO, YES, "%s: %zu bytes tweak required", tweakf, 2*TF_SIZE_UNIT);
@@ -637,7 +642,7 @@ _nokeyfd:
                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);
-               lio = read(ctrfd, ctr, ctrsz);
+               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);
                xclose(ctrfd);
@@ -646,7 +651,8 @@ _nokeyfd:
                pblk = ctr;
                ldone = 0;
                lrem = lblock = ctrsz;
-_ctrragain:    lio = read(sfd, pblk, lrem);
+               if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd);
+_ctrragain:    lio = xread(sfd, pblk, lrem);
                if (lio != NOSIZE) ldone += lio;
                else {
                        if (errno != EIO && catch_all_errors != YES)
@@ -654,10 +660,12 @@ _ctrragain:       lio = read(sfd, pblk, lrem);
                        switch (error_action) {
                                case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", srcfname); goto _ctrragain; break;
                                case TFC_ERRACT_SYNC:
+                               case TFC_ERRACT_LSYNC:
                                        xerror(YES, NO, NO, "%s", srcfname);
                                        lio = ldone = lrem = lblock;
                                        memset(ctr, 0, lio);
-                                       lseek(sfd, lio, SEEK_CUR);
+                                       if (rdpos == NOFSIZE) lseek(sfd, lio, SEEK_CUR);
+                                       else lseek(sfd, rdpos + lio, SEEK_SET);
                                        break;
                                default: xerror(NO, NO, NO, "%s", srcfname); break;
                        }
@@ -688,7 +696,8 @@ _ctrskip1:
                pblk = key;
 _xts2key:      ldone = 0;
                lrem = lblock = TF_FROM_BITS(TFC_KEY_BITS);
-_keyragain:    lio = read(kfd, pblk, lrem);
+               if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(kfd);
+_keyragain:    lio = xread(kfd, pblk, lrem);
                if (lio != NOSIZE) ldone += lio;
                else {
                        if (errno != EIO && catch_all_errors != YES)
@@ -696,10 +705,12 @@ _keyragain:       lio = read(kfd, pblk, lrem);
                        switch (error_action) {
                                case TFC_ERRACT_CONT: xerror(YES, NO, NO, "reading key"); goto _keyragain; break;
                                case TFC_ERRACT_SYNC:
+                               case TFC_ERRACT_LSYNC:
                                        xerror(YES, NO, NO, "reading key");
                                        lio = ldone = lrem = lblock;
                                        memset(key, 0, lio);
-                                       lseek(kfd, lio, SEEK_CUR);
+                                       if (rdpos == NOFSIZE) lseek(kfd, lio, SEEK_CUR);
+                                       else lseek(kfd, rdpos + lio, SEEK_SET);
                                        break;
                                default: xerror(NO, NO, NO, "reading key"); break;
                        }
@@ -829,7 +840,7 @@ _pwdagain:  memset(&getps, 0, sizeof(struct getpasswd_state));
                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);
-_xts2genkey:   if (write(krfd, pblk, TF_FROM_BITS(TFC_KEY_BITS)) == -1) xerror(NO, NO, YES, "%s", genkeyf);
+_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) {
                        tfc_esay("%s: password hashing done", progname);
@@ -885,7 +896,7 @@ _xts2genkey:        if (write(krfd, pblk, TF_FROM_BITS(TFC_KEY_BITS)) == -1) xerror(NO,
                case TFC_CTR_SHOW:
                        switch (do_outfmt) {
                                case TFC_OUTFMT_B64: tfc_printbase64(stderr, ctr, ctrsz, YES); break;
-                               case TFC_OUTFMT_RAW: write(2, ctr, ctrsz); break;
+                               case TFC_OUTFMT_RAW: xwrite(2, ctr, ctrsz); break;
                                case TFC_OUTFMT_HEX: mehexdump(ctr, ctrsz, ctrsz, YES); break;
                        }
                        break;
@@ -949,7 +960,7 @@ _plain:
                pblk = ctr;
                lio = lrem = ctrsz;
                ldone = 0;
-_ctrwagain:    lio = write(dfd, pblk, lrem);
+_ctrwagain:    lio = xwrite(dfd, pblk, lrem);
                if (lio != NOSIZE) ldone += lio;
                else xerror(NO, NO, NO, "%s", dstfname);
                if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", dstfname);
@@ -969,7 +980,8 @@ _ctrwagain: lio = write(dfd, pblk, lrem);
                pblk = srcblk;
                ldone = 0;
                lrem = lblock = blk_len_adj(maxlen, total_processed_src, blksize);
-_ragain:       lio = read(sfd, pblk, lrem);
+               if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd);
+_ragain:       lio = xread(sfd, pblk, lrem);
                if (lio == 0) do_stop = TFC_STOP_BEGAN;
                if (lio != NOSIZE) ldone += lio;
                else {
@@ -978,10 +990,12 @@ _ragain:  lio = read(sfd, pblk, lrem);
                        switch (error_action) {
                                case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", srcfname); goto _ragain; break;
                                case TFC_ERRACT_SYNC:
+                               case TFC_ERRACT_LSYNC:
                                        xerror(YES, NO, NO, "%s", srcfname);
                                        lio = ldone = lrem = lblock;
                                        memset(srcblk, 0, lio);
-                                       lseek(sfd, lio, SEEK_CUR);
+                                       if (rdpos == NOFSIZE) lseek(sfd, lio, SEEK_CUR);
+                                       else lseek(sfd, rdpos + lio, SEEK_SET);
                                        break;
                                default: xerror(NO, NO, NO, "%s", srcfname); break;
                        }
@@ -1033,7 +1047,7 @@ _ragain:  lio = read(sfd, pblk, lrem);
                pblk = dstblk;
                lrem = ldone;
                ldone = 0;
-_wagain:       lio = write(dfd, pblk, lrem);
+_wagain:       lio = xwrite(dfd, pblk, lrem);
                if (lio != NOSIZE) ldone += lio;
                else xerror(NO, NO, NO, "%s", dstfname);
                if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", dstfname);
@@ -1056,7 +1070,8 @@ _nowrite: total_processed_dst += ldone;
                        pblk = macvrfy;
                        ldone = 0;
                        lrem = lblock = TF_FROM_BITS(macbits);
-_macragain:            lio = read(sfd, pblk, lrem);
+                       if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd);
+_macragain:            lio = xread(sfd, pblk, lrem);
                        if (lio != NOSIZE) ldone += lio;
                        else {
                                if (errno != EIO && catch_all_errors != YES)
@@ -1064,10 +1079,12 @@ _macragain:             lio = read(sfd, pblk, lrem);
                                switch (error_action) {
                                        case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", srcfname); goto _macragain; break;
                                        case TFC_ERRACT_SYNC:
+                                       case TFC_ERRACT_LSYNC:
                                                xerror(YES, NO, NO, "%s", srcfname);
                                                lio = ldone = lrem = lblock;
                                                memset(macvrfy, 0, lio);
-                                               lseek(sfd, lio, SEEK_CUR);
+                                               if (rdpos == NOFSIZE) lseek(sfd, lio, SEEK_CUR);
+                                               else lseek(sfd, rdpos + lio, SEEK_SET);
                                                break;
                                        default: xerror(NO, NO, NO, "%s", srcfname); break;
                                }
@@ -1085,7 +1102,7 @@ _macragain:               lio = read(sfd, pblk, lrem);
                        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);
-                       lio = ldone = read(mfd, tmpdata, sizeof(tmpdata));
+                       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)) {
                                memmove(tmpdata, tmpdata+TFC_ASCII_TFC_MAC_FOURCC_LEN,
@@ -1150,7 +1167,7 @@ _shortmac:        memset(macvrfy, 0, sizeof(macvrfy));
                        pblk = tmpdata;
                        lio = lrem = TF_FROM_BITS(macbits);
                        ldone = 0;
-_macwagain:            lio = write(dfd, pblk, lrem);
+_macwagain:            lio = xwrite(dfd, pblk, lrem);
                        if (lio != NOSIZE) ldone += lio;
                        else xerror(NO, NO, NO, "%s", dstfname);
                        if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", dstfname);
@@ -1178,9 +1195,9 @@ _macwagain:               lio = write(dfd, pblk, lrem);
                                        tmpdata[lrem] = '\n';
                                        lrem++;
                                }
-                               lio = write(mfd, tmpdata, lrem);
+                               lio = xwrite(mfd, tmpdata, lrem);
                        }
-                       else lio = write(mfd, tmpdata, TF_FROM_BITS(macbits));
+                       else lio = xwrite(mfd, tmpdata, TF_FROM_BITS(macbits));
                        if (lio == NOSIZE) xerror(NO, NO, YES, "%s", do_mac_file);
                        if (do_fsync && fsync(mfd) == -1) xerror(NO, NO, YES, "%s", do_mac_file);
                        xclose(mfd);