From 2da8baf01e863c80eccdeb5f428f16e1cf3a0473 Mon Sep 17 00:00:00 2001 From: Andrey Rys Date: Fri, 25 Jan 2019 15:45:51 +0700 Subject: [PATCH] -E sync: reform logic. Prequery file position, jump over error hole. Add -E lsync to turn on older version. tfc_fdsize: properly return NOFSIZE on errors. --- VERSION | 2 +- tfc_base64.c | 5 ++++- tfc_error.c | 8 ++++++-- tfc_misc.c | 13 +++++++++++-- tfc_skein.c | 5 ++++- tfc_vars.c | 1 + tfcrypt.c | 27 ++++++++++++++++++++++----- tfcrypt.h | 4 +++- 8 files changed, 52 insertions(+), 13 deletions(-) diff --git a/VERSION b/VERSION index 00750ed..b8626c4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3 +4 diff --git a/tfc_base64.c b/tfc_base64.c index b92ac96..2498004 100644 --- a/tfc_base64.c +++ b/tfc_base64.c @@ -68,6 +68,7 @@ void do_edbase64(char **fargv) pblk = srcblk; lblock = lrem = do_edcrypt == TFC_DO_DECRYPT ? TFC_B64_DWIDTH : TFC_B64_EWIDTH; ldone = 0; + if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd); _again: lio = read(sfd, pblk, lrem); if (lio == 0) do_stop = YES; if (lio != NOSIZE) ldone += lio; @@ -77,10 +78,12 @@ _again: lio = read(sfd, pblk, lrem); switch (error_action) { case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", fargv[0]); goto _again; break; case TFC_ERRACT_SYNC: + case TFC_ERRACT_LSYNC: xerror(YES, NO, NO, "%s", fargv[0]); 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", fargv[0]); break; } diff --git a/tfc_error.c b/tfc_error.c index 048c0bb..e331315 100644 --- a/tfc_error.c +++ b/tfc_error.c @@ -212,9 +212,13 @@ void usage(void) tfc_say(" cont: print error if not quiet, then continue,"); tfc_say(" no action to pad missing data is attempted."); tfc_say(" may be dangerous when working with block devices."); - tfc_say(" sync: print error if not quiet, then continue."); + tfc_say(" sync: print error if not quiet, then continue,"); tfc_say(" pad missing data block with zeroes."); - tfc_say(" note that sync works only with read errors!"); + tfc_say(" lsync: same as sync, but does not use SEEK_SET logic,"); + tfc_say(" lsync uses only relative seek operations, and does not prequery"); + tfc_say(" the current file position for exact offsets, which maybe unsafe."); + tfc_say(" For this reason, it is HIGHLY recommended to use sync instead!"); + tfc_say(" Note that both sync and lsync work only with read errors!"); tfc_say(" default error action is exit with printing status if not quiet."); tfc_say(" -E xall: turn on error actions above for all errors, not just EIO errors."); tfc_say(" This must be a separate option given before usual -E how option."); diff --git a/tfc_misc.c b/tfc_misc.c index d1bb783..e6af46a 100644 --- a/tfc_misc.c +++ b/tfc_misc.c @@ -100,14 +100,23 @@ tfc_fsize tfc_fdsize(int fd) cur = lseek(fd, 0L, SEEK_CUR); l = lseek(fd, 0L, SEEK_SET); - if (l == -1) return -1; + if (l == -1) return NOFSIZE; l = lseek(fd, 0L, SEEK_END); - if (l == -1) return -1; + if (l == -1) return NOFSIZE; lseek(fd, cur, SEEK_SET); return (tfc_fsize)l; } +tfc_fsize tfc_fdgetpos(int fd) +{ + off_t t; + + t = lseek(fd, 0L, SEEK_CUR); + if (t == -1) return NOFSIZE; + return (tfc_fsize)t; +} + tfc_fsize tfc_fnamesize(char *fname, tfc_yesno noexit) { int fnmfd; diff --git a/tfc_skein.c b/tfc_skein.c index 369fc23..6c595e1 100644 --- a/tfc_skein.c +++ b/tfc_skein.c @@ -77,6 +77,7 @@ tfc_yesno skeinfd(void *hash, size_t bits, const void *key, int fd, tfc_fsize re pblk = skblk; lblock = lrem = blk_len_adj(readto, total, TFC_BLKSIZE); ldone = 0; + if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(fd); _again: lio = read(fd, pblk, lrem); if (lio == 0) stop = YES; if (lio != NOSIZE) ldone += lio; @@ -85,11 +86,13 @@ _again: lio = read(fd, pblk, lrem); switch (error_action) { case TFC_ERRACT_CONT: xerror(YES, NO, NO, "skeinfd: %d", fd); goto _again; break; case TFC_ERRACT_SYNC: + case TFC_ERRACT_LSYNC: xerror(YES, NO, NO, "skeinfd: %d", fd); lio = lrem = ldone = lblock; total += lio; memset(skblk, 0, lio); - lseek(fd, lio, SEEK_CUR); + if (rdpos == NOFSIZE) lseek(fd, lio, SEEK_CUR); + else lseek(fd, rdpos + lio, SEEK_SET); break; default: goto _fail; break; } diff --git a/tfc_vars.c b/tfc_vars.c index 4986334..5f75952 100644 --- a/tfc_vars.c +++ b/tfc_vars.c @@ -45,6 +45,7 @@ tfc_fsize iseek_blocks, iseek, oseek, maxlen = NOFSIZE; tfc_fsize total_processed_src, total_processed_dst; tfc_fsize delta_processed; tfc_fsize genrandom_nr_bytes, genzero_nr_bytes; +tfc_fsize rdpos = NOFSIZE; int sfd, kfd = -1, dfd = 1; struct stat s_stat; size_t blksize = TFC_BLKSIZE, xtsblocks = TFC_XTSBLOCKS; diff --git a/tfcrypt.c b/tfcrypt.c index c544cfd..07939a7 100644 --- 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': @@ -503,6 +505,7 @@ _nosalt: pblk = tmpdata; ldone = 0; lrem = lblock = sizeof(tmpdata); + if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(mkfd); _mkragain: lio = read(mkfd, pblk, lrem); if (lio == 0) do_stop = YES; if (lio != NOSIZE) ldone += lio; @@ -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; } @@ -646,6 +651,7 @@ _nokeyfd: pblk = ctr; ldone = 0; lrem = lblock = ctrsz; + if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd); _ctrragain: lio = read(sfd, pblk, lrem); if (lio != NOSIZE) ldone += lio; else { @@ -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,6 +696,7 @@ _ctrskip1: pblk = key; _xts2key: ldone = 0; lrem = lblock = TF_FROM_BITS(TFC_KEY_BITS); + if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(kfd); _keyragain: lio = read(kfd, pblk, lrem); if (lio != NOSIZE) ldone += lio; else { @@ -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; } @@ -969,6 +980,7 @@ _ctrwagain: lio = write(dfd, pblk, lrem); pblk = srcblk; ldone = 0; lrem = lblock = blk_len_adj(maxlen, total_processed_src, blksize); + if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd); _ragain: lio = read(sfd, pblk, lrem); if (lio == 0) do_stop = TFC_STOP_BEGAN; if (lio != NOSIZE) ldone += lio; @@ -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; } @@ -1056,6 +1070,7 @@ _nowrite: total_processed_dst += ldone; pblk = macvrfy; ldone = 0; lrem = lblock = TF_FROM_BITS(macbits); + if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd); _macragain: lio = read(sfd, pblk, lrem); if (lio != NOSIZE) ldone += lio; else { @@ -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; } diff --git a/tfcrypt.h b/tfcrypt.h index fcc75ee..6efb5e3 100644 --- a/tfcrypt.h +++ b/tfcrypt.h @@ -132,6 +132,7 @@ extern tfc_fsize iseek_blocks, iseek, oseek, maxlen; extern tfc_fsize total_processed_src, total_processed_dst; extern tfc_fsize delta_processed; extern tfc_fsize genrandom_nr_bytes, genzero_nr_bytes; +extern tfc_fsize rdpos; extern int sfd, kfd, dfd; extern struct stat s_stat; extern size_t blksize, xtsblocks; @@ -174,6 +175,7 @@ void xclose(int fd); const char *tfc_modename(int mode); void tfc_getcurtime(tfc_useconds *tx); tfc_fsize tfc_fdsize(int fd); +tfc_fsize tfc_fdgetpos(int fd); tfc_fsize tfc_fnamesize(char *fname, tfc_yesno noexit); tfc_fsize tfc_modifysize(tfc_fsize szmodify, const char *szspec); void fcopy_matime(int fd, const struct stat *st); @@ -198,7 +200,7 @@ void do_benchmark(tfc_useconds useconds, double dseconds); enum { NO, YES }; -enum { TFC_ERRACT_EXIT, TFC_ERRACT_CONT, TFC_ERRACT_SYNC }; +enum { TFC_ERRACT_EXIT, TFC_ERRACT_CONT, TFC_ERRACT_SYNC, TFC_ERRACT_LSYNC }; enum { TFC_STOP_BEGAN = 1, TFC_STOP_FULL }; enum { TFC_DO_PLAIN, TFC_DO_ENCRYPT, TFC_DO_DECRYPT }; enum { TFC_MAC_DROP = -1, TFC_MAC_SIGN = 1, TFC_MAC_VRFY, TFC_MAC_JUST_VRFY }; -- 2.31.1