Add -E lsync to turn on older version.
tfc_fdsize: properly return NOFSIZE on errors.
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;
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;
}
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.");
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;
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;
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;
}
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;
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':
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;
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;
}
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 {
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;
}
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 {
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;
}
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;
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;
}
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 {
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;
}
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;
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);
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 };