30 zinfo(
bool writing_,
const char *filename_,
const char *pipe_cmd_)
45 if (strchr(mode,
'a')) {
46 error =
"Cannot append to file using ARB_zfopen";
49 if (strchr(mode,
't')) {
50 error =
"Cannot use textmode for ARB_zfopen";
53 if (strchr(mode,
'+')) {
54 error =
"Cannot open file in read and write mode with ARB_zfopen";
58 bool forOutput = strchr(mode,
'w');
63 error =
"Autodetecting compression mode only works for input files";
66 fp = fopen(name,
"rb");
70 const size_t MAGICSIZE = 5;
73 size_t bytes_read = fread(buffer, 1, MAGICSIZE, fp);
77 if (bytes_read>=2 && strncmp(buffer,
"\x1f\x8b", 2) == 0) cmode =
ZFILE_GZIP;
78 else if (bytes_read>=2 && strncmp(buffer,
"BZ", 2) == 0) cmode =
ZFILE_BZIP2;
79 else if (bytes_read>=5 && strncmp(buffer,
"\xfd" "7zXZ", 5) == 0) cmode =
ZFILE_XZ;
88 fp = fopen(name, mode);
91 zfile_info[fp] =
zinfo(forOutput, name,
"");
96 const char *compressor =
NULp;
97 const char *decompress_flag =
"-d";
112 case ZFILE_XZ: compressor =
"xz";
break;
118 #if defined(USE_BROKEN_COMPRESSION)
120 compressor =
"arb_weirdo";
126 char *pipeCmd = forOutput
137 char *b = strchr(impl_b_mode,
'b');
143 fp = popen(pipeCmd, impl_b_mode);
144 if (!fp) error =
GB_IO_error(
"writing to pipe", pipeCmd);
147 fp = popen(pipeCmd, impl_b_mode);
148 if (!fp) error =
GB_IO_error(
"reading from pipe", pipeCmd);
152 zfile_info[fp] =
zinfo(forOutput, name, pipeCmd);
169 arb_assert(zfile_info.find(fp) != zfile_info.end());
172 zfile_info.erase(fp);
184 int exited = WIFEXITED(res);
185 int status = WEXITSTATUS(res);
187 int signaled = WIFSIGNALED(res);
196 " failed with exitcode=%i (broken pipe? corrupted archive?)\n",
197 info.isOutputPipe() ?
"writing to" :
"reading from",
204 if (!error) error =
GB_IO_error(
"closing", info.get_filename());
206 error =
GBS_global_string(
"%s (res=%i, exited=%i, signaled=%i, status=%i)", error, res, exited, signaled, status);
219 static char *fileContent(FILE *in,
size_t& bytes_read) {
221 char *
buffer = ARB_alloc<char>(BUFFERSIZE+1);
222 bytes_read = fread(buffer, 1, BUFFERSIZE, in);
224 buffer[bytes_read] = 0;
228 #define TEST_EXPECT_ZFOPEN_FAILS(name,mode,cmode,errpart) do{ \
229 GB_ERROR error = NULp; \
230 FILE *fp = ARB_zfopen(name, mode, cmode, error, false); \
233 TEST_EXPECT_NULL(error); \
234 error = ARB_zfclose(fp); \
237 TEST_EXPECT_NULL(fp); \
239 TEST_REJECT_NULL(error); \
240 TEST_EXPECT_CONTAINS(error, errpart); \
243 void TEST_compressed_io() {
244 const char *inText =
"general/text.input";
245 const char *outFile =
"compressed.out";
248 TEST_EXPECT_ZFOPEN_FAILS(outFile,
"a",
ZFILE_UNCOMPRESSED,
"Cannot append to file using ARB_zfopen");
249 TEST_EXPECT_ZFOPEN_FAILS(outFile,
"r",
ZFILE_UNDEFINED,
"Invalid compression mode");
250 TEST_EXPECT_ZFOPEN_FAILS(outFile,
"w",
ZFILE_AUTODETECT,
"only works for input files");
251 TEST_EXPECT_ZFOPEN_FAILS(outFile,
"rt",
ZFILE_AUTODETECT,
"Cannot use textmode");
252 TEST_EXPECT_ZFOPEN_FAILS(outFile,
"r+",
ZFILE_AUTODETECT,
"Cannot open file in read and write mode");
254 #if defined(USE_BROKEN_COMPRESSION)
255 TEST_EXPECT_ZFOPEN_FAILS(outFile,
"r", ZFILE_BROKEN,
"broken pipe");
256 TEST_EXPECT_ZFOPEN_FAILS(outFile,
"w", ZFILE_BROKEN,
"broken pipe");
260 const size_t TEST_TEXT_SIZE = 428;
268 testText = fileContent(in, bytes_read);
274 int successful_compressions = 0;
282 bool compressed_save_failed =
false;
285 FILE *out =
ARB_zfopen(outFile,
"w", cmode, error,
false);
293 if (error && strstr(error,
"failed with exitcode=127") && cmode !=
ZFILE_UNCOMPRESSED) {
295 compressed_save_failed =
true;
302 if (!compressed_save_failed) {
303 for (
int detect = 0; detect<=1; ++detect) {
313 char *content = fileContent(in, bytes_read);
318 successful_compressions++;
#define implicated(hypothesis, conclusion)
bool isOutputPipe() const
void ARB_warn_about_unwanted_chars(const char *path, const char *path_description)
const char * ARB_getenv_ignore_empty(const char *envvar)
GB_ERROR GB_IO_error(const char *action, const char *filename)
char * ARB_strdup(const char *str)
const char * GBS_global_string(const char *templat,...)
int GB_unlink(const char *path)
FILE * ARB_zfopen(const char *name, const char *mode, FileCompressionMode cmode, GB_ERROR &error, bool hideStderr)
char buffer[MESSAGE_BUFFERSIZE]
char * ARB_executable(const char *exe_name, const char *path)
#define TEST_EXPECT(cond)
zinfo(bool writing_, const char *filename_, const char *pipe_cmd_)
#define TEST_REJECT(cond)
#define TEST_REJECT_NULL(n)
static void error(const char *msg)
bool GB_is_fifo(const char *path)
const char * get_filename() const
static map< FILE *, zinfo > zfile_info
static BasicStatus status
fputs(TRACE_PREFIX, stderr)
#define TEST_EXPECT_NULL(n)
GB_ERROR ARB_zfclose(FILE *fp)
#define TEST_EXPECT_NO_ERROR(call)
#define TEST_EXPECT_DIFFERENT(expr, want)
const char * get_pipecmd() const
static int info[maxsites+1]
#define TEST_EXPECT_EQUAL(expr, want)
char * GBS_global_string_copy(const char *templat,...)