diff --git a/R/fread.R b/R/fread.R index 265cd9901f..31168a3d53 100644 --- a/R/fread.R +++ b/R/fread.R @@ -70,9 +70,13 @@ yaml=FALSE, tmpdir=tempdir(), tz="UTC") } } if (!is.null(cmd)) { - (if (.Platform$OS.type == "unix") system else shell)(paste0('(', cmd, ') > ', tmpFile<-tempfile(tmpdir=tmpdir))) - file = tmpFile + tmpFile = tempfile(tmpdir=tmpdir) on.exit(unlink(tmpFile), add=TRUE) + status = (if (.Platform$OS.type == "unix") system else shell)(paste0('(', cmd, ') > ', tmpFile)) + if (status != 0) { + stopf("External command failed with exit code %d. This can happen when the disk is full in the temporary directory ('%s'). See ?fread for the tmpdir argument.", status, tmpdir) + } + file = tmpFile } if (!is.null(file)) { if (!is.character(file) || length(file)!=1L) @@ -116,9 +120,14 @@ yaml=FALSE, tmpdir=tempdir(), tz="UTC") if (!requireNamespace("R.utils", quietly = TRUE)) stopf("To read %s files directly, fread() requires 'R.utils' package which cannot be found. Please install 'R.utils' using 'install.packages('R.utils')'.", if (w<=2L || gzsig) "gz" else "bz2") # nocov FUN = if (w<=2L || gzsig) gzfile else bzfile - R.utils::decompressFile(file, decompFile<-tempfile(tmpdir=tmpdir), ext=NULL, FUN=FUN, remove=FALSE) # ext is not used by decompressFile when destname is supplied, but isn't optional - file = decompFile # don't use 'tmpFile' symbol again, as tmpFile might be the http://domain.org/file.csv.gz download + decompFile = tempfile(tmpdir=tmpdir) on.exit(unlink(decompFile), add=TRUE) + tryCatch({ + R.utils::decompressFile(file, decompFile, ext=NULL, FUN=FUN, remove=FALSE) # ext is not used by decompressFile when destname is supplied, but isn't optional + }, error = function(e) { + stopf("R.utils::decompressFile failed to decompress file '%s':\n %s\n. This can happen when the disk is full in the temporary directory ('%s'). See ?fread for the tmpdir argument.", file, conditionMessage(e), tmpdir) + }) + file = decompFile # don't use 'tmpFile' symbol again, as tmpFile might be the http://domain.org/file.csv.gz download } file = enc2native(file) # CfreadR cannot handle UTF-8 if that is not the native encoding, see #3078. diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index a0175738c5..7572d4962e 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -21192,3 +21192,16 @@ test(2319.1, !is.null(attr(dt_get, ".internal.selfref"))) dt_get0 = data.frame(a = 1:3, b = letters[1:3]) setDT(get0("dt_get0")) test(2319.2, !is.null(attr(dt_get0, ".internal.selfref"))) + +# Improved fread error handling for cmd exe and decompression #5415 +test(2320.1, fread(cmd="false"), error="External command failed with exit code", warning = if (.Platform$OS.type=="windows") "execution failed") + +if (test_R.utils) local({ + tmp <- tempfile(fileext=".gz") + file.create(tmp); on.exit(unlink(tmp)) + local({ + conn <- file(tmp, 'wb'); on.exit(close(conn)) + writeBin(as.raw(c(31L, 139L)), conn) # Gzip header magic numbers to trigger that read path + }) + test(2320.2, fread(tmp), error="R.utils::decompressFile failed to decompress", warning="invalid") +})