Skip to content

Commit 855886d

Browse files
committed
fwrite(): emit gzip header even if !col.names
Previously, fwrite() emitted a raw DEFLATE stream if col.names was FALSE (and thus headerLen was zero). Decompressing such files is possible, but not trivial.
1 parent 6a8634e commit 855886d

File tree

2 files changed

+26
-10
lines changed

2 files changed

+26
-10
lines changed

inst/tests/tests.Rraw

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10024,9 +10024,12 @@ if (!haszlib()) {
1002410024
fwrite(DT, file=f3<-tempfile(), compress="gzip") # compress to filename not ending .gz
1002510025
fwrite(DT, file=f4<-tempfile(), compress="gzip", compressLevel=1) # test compressLevel
1002610026
fwrite(DT, file=f5<-tempfile(), compress="gzip", compressLevel=9)
10027+
# col.names=FALSE must not disable gzip header, #6852
10028+
fwrite(DT, file=f6<-tempfile(), compress="gzip", col.names=FALSE)
1002710029
test(1658.441, file.info(f3)$size, file.info(f1)$size)
1002810030
test(1658.442, file.info(f4)$size >= file.info(f1)$size)
1002910031
test(1658.443, file.info(f1)$size >= file.info(f5)$size)
10032+
test(1658.444, fread(f6, col.names = c("a", "b")), DT)
1003010033
unlink(c(f1,f2,f3,f4,f5))
1003110034
}
1003210035
DT = data.table(a=1:3, b=list(1:4, c(3.14, 100e10), c("foo", "bar", "baz")))

src/fwrite.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -829,8 +829,27 @@ void fwriteMain(fwriteMainArgs args)
829829
zbuffSize / MEGA, nth, errno, strerror(errno));
830830
// # nocov end
831831
}
832-
}
832+
len = 0;
833+
crc = crc32(0L, Z_NULL, 0);
834+
835+
if (f != -1) {
836+
// write minimal gzip header, but not on the console
837+
static const char header[] = "\037\213\10\0\0\0\0\0\0\3";
838+
int ret0 = WRITE(f, header, (sizeof header) - 1);
839+
compress_len += (sizeof header) - 1;
833840

841+
if (ret0 == -1) {
842+
// # nocov start
843+
int errwrite = errno; // capture write errno now in case close fails with a different errno
844+
CLOSE(f);
845+
free(buffPool);
846+
free(zbuffPool);
847+
deflateEnd(&strm);
848+
STOP(_("Failed to write gzip header. Write returned %d"), ret0);
849+
// # nocov end
850+
}
851+
}
852+
}
834853
#endif
835854

836855
// write header
@@ -873,15 +892,10 @@ void fwriteMain(fwriteMainArgs args)
873892
*ch = '\0';
874893
DTPRINT("%s", buff); // # notranslate
875894
} else {
876-
int ret0=0, ret1=0, ret2=0;
895+
int ret1=0, ret2=0;
877896
#ifndef NOZLIB
878897
if (args.is_gzip) {
879898
char* zbuff = zbuffPool;
880-
// write minimal gzip header
881-
char* header = "\037\213\10\0\0\0\0\0\0\3";
882-
ret0 = WRITE(f, header, 10);
883-
compress_len += 10;
884-
crc = crc32(0L, Z_NULL, 0);
885899

886900
size_t zbuffUsed = zbuffSize;
887901
len = (size_t)(ch - buff);
@@ -898,16 +912,15 @@ void fwriteMain(fwriteMainArgs args)
898912
#ifndef NOZLIB
899913
}
900914
#endif
901-
if (ret0 == -1 || ret1 || ret2 == -1) {
915+
if (ret1 || ret2 == -1) {
902916
// # nocov start
903917
int errwrite = errno; // capture write errno now in case close fails with a different errno
904918
CLOSE(f);
905919
free(buffPool);
906920
#ifndef NOZLIB
907921
free(zbuffPool);
908922
#endif
909-
if (ret0 == -1) STOP(_("Failed to write gzip header. Write returned %d"), ret0);
910-
else if (ret1) STOP(_("Failed to compress gzip. compressbuff() returned %d"), ret1);
923+
if (ret1) STOP(_("Failed to compress gzip. compressbuff() returned %d"), ret1);
911924
else STOP(_("%s: '%s'"), strerror(errwrite), args.filename);
912925
// # nocov end
913926
}

0 commit comments

Comments
 (0)