/**
* @file gzfile.c
*
*
* @brief zlib あるいは gzip を用いた圧縮ファイルの読み込み
*
* 圧縮ファイルの読み込みに対応したファイルのオープン・クローズ・
* 読み込み関数群です.
*
* コンパイル時に zlib 無い場合,gzip を用いて圧縮ファイルの展開を
* 行います.この場合,複数のファイルを同時に開くことは出来ませんので
* 注意してください.
*
*
*
* @brief Read Compressed files using gzip or zlib
*
* These are functions to enable open/close/reading of gzipped files.
*
* If zlib library and header are not found, the gzip executables will
* be used to uncompress the input file. In the latter case, opening
* multiple files with these functions is not allowed.
*
*
* @author Akinobu LEE
* @date Thu Feb 17 15:46:00 2005
*
* $Revision: 1.4 $
*
*/
/*
* Copyright (c) 1991-2012 Kawahara Lab., Kyoto University
* Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
* Copyright (c) 2005-2012 Julius project team, Nagoya Institute of Technology
* All rights reserved
*/
#include
#include
#ifdef HAVE_ZLIB
/* use built-in zlib functions */
/* current implementatin casts gzFile to FILE... */
#include
/**
* Open a file with zlib.
*
* @param filename [in] file name to open
*
* @return gzFile pointer if succeed, NULL on failure.
*/
FILE *
fopen_readfile(char *filename)
{
gzFile gp;
gp = gzopen(filename, "rb");
if (gp == NULL) {
jlog("Error: gzfile: unable to open %s\n", filename);
}
return(gp);
}
/**
* Close a file previously opened by fopen_readfile().
*
* @param fp [in] gzFile pointer
*
* @return 0 on success, -1 on error.
*/
int
fclose_readfile(FILE *fp)
{
if (gzclose((gzFile)fp) < 0) {
jlog("Error: gzfile: unable to close file\n");
return -1;
}
return 0;
}
/**
* Read data from input stream opened by fopen_readfile().
*
* @param ptr [out] data buffer
* @param size [in] size of unit in bytes
* @param n [in] number of unit to be read
* @param fp [in] gzFile pointer
*
* @return number of read units or EOF, -1 on error.
*/
size_t
myfread(void *ptr, size_t size, size_t n, FILE *fp)
{
int cnt;
cnt = gzread((gzFile)fp, (voidp)ptr, (unsigned)size * n);
if (cnt < 0) {
jlog("Error: gzfile: failed to read %d bytes\n", size * n);
return(-1);
}
return(cnt / size);
}
/**
* Read one character from input stream opened by fopen_readfile().
*
* @param fp [in] gzFile pointer
*
* @return the read character, or -1 on EOF or error.
*/
int
myfgetc(FILE *fp)
{
int ret;
ret = gzgetc((gzFile)fp);
return(ret);
}
/**
* Test if reached end of file, for files opened by fopen_readfile().
*
* @param fp [in] gzFile pointer.
*
* @return 1 if already on EOF, 0 if otherwise.
*/
int
myfeof(FILE *fp)
{
if (gzeof((gzFile)fp) == 0) {
return 0;
}
return 1;
}
/**
* Seek to the first of the file.
*
* @param fp [in] gzFile pointer.
*
* @return 0 on success, -1 on error.
*/
int
myfrewind(FILE *fp)
{
if (gzrewind((gzFile)fp) != 0) return -1;
return 0;
}
#else /* ~HAVE_ZLIB */
/* use external "gzip" via pipe */
/* can read only one file at a time */
static boolean isopen = FALSE; ///< TRUE if a file is now opened
static FILE *zcat_pipe = NULL; ///< File pointer of the gzip pipe
/**
* Guess if the file is compressed or not, only by its filename suffix.
*
* @param filename [in] file name
*
* @return TRUE if compressed file, FALSE if not.
*/
static boolean
is_zcatfile(char *filename)
{
int len;
len = strlen(filename);
if (strmatch(".Z", &filename[len - 2])) {
return TRUE;
} else if (strmatch(".z", &filename[len - 2]) || strmatch(".gz", &filename[len - 3])) {
return TRUE;
}
return FALSE;
}
/**
* Open the file using external gzip command. Only one file can open at a time.
*
* @param filename [in] filename to open
*
* @return the file pointer, or NULL if open failed.
*/
FILE *
fopen_readfile(char *filename)
{
FILE *fp;
char *cmd;
if (isopen) { /* already open */
jlog("Error: gzfile: previously opened file is not closed yet.\n");
return NULL;
}
if (is_zcatfile(filename)) { /* open compressed file */
cmd = (char *)mymalloc(strlen(ZCAT) + strlen(filename) + 2);
strcpy(cmd, ZCAT);
strcat(cmd," ");
strcat(cmd, filename);
zcat_pipe = popen(cmd, "r");
if (zcat_pipe == NULL) {
jlog("Error: gzfile: failed to exec \"%s\" for opening file \"%s\"\n", cmd, filename);
return NULL;
}
free(cmd);
fp = zcat_pipe;
} else { /* open normal file */
fp = fopen(filename, "rb");
if (fp == NULL) { /* error */
jlog("Error: gzfile: failed to open \"%s\"\n", filename);
return NULL;
}
zcat_pipe = NULL;
}
isopen = TRUE;
return (fp);
}
/**
* Close a file previously opened by fopen_readfile().
*
* @param fp [in] gzFile pointer
*
* @return 0 on success, -1 on error.
*/
int
fclose_readfile(FILE *fp)
{
if (!isopen) { /* not opened yet */
return -1;
}
if (zcat_pipe != NULL) { /* pipe opened fp */
if (fp != zcat_pipe) {
jlog("Error: gzfile: fp is not opened by fopen_readfile()\n");
return -1;
}
if (pclose(zcat_pipe) == -1) {
jlog("Error: gzfile: failed to close gzip pipe\n");
return -1;
}
zcat_pipe = NULL;
} else { /* normal opened fp */
if (fclose(fp) != 0) {
jlog("Error: gzfile: failed to close file\n");
return -1;
}
}
isopen = FALSE;
return 0;
}
/**
* Read data from input stream opened by fopen_readfile().
*
* @param ptr [out] data buffer
* @param size [in] size of unit in bytes
* @param n [in] number of unit to be read
* @param fp [in] gzFile pointer
*
* @return number of read units or EOF, -1 on error.
*/
size_t
myfread(void *ptr, size_t size, size_t n, FILE *fp)
{
size_t ret;
ret = fread(ptr, size, n, fp);
if (ret == 0) {
if (myfeof(fp) == 1) {
return 0;
} else {
return -1;
}
}
return(ret);
}
/**
* Read one character from input stream opened by fopen_readfile().
*
* @param fp [in] gzFile pointer
*
* @return the read character, or -1 on EOF or error.
*/
int
myfgetc(FILE *fp)
{
int ret;
ret = fgetc(fp);
if (ret == EOF) return -1;
return(ret);
}
/**
* Test if reached end of file, for files opened by fopen_readfile().
*
* @param fp [in] gzFile pointer.
*
* @return 1 if already on EOF, 0 if otherwise.
*/
int
myfeof(FILE *fp)
{
if (feof(fp) == 0) {
return 0;
}
return 1;
}
/**
* Seek to the first of the file.
*
* @param fp [in] File pointer.
*
* @return 0 on success, -1 on error.
*/
int
myfrewind(FILE *fp)
{
if (fseek(fp, 0L, SEEK_SET) != 0) return -1;
return 0;
}
#endif /* ~HAVE_ZLIB */
/**
* Open or create a file for writing (no compression supported),
*
* @param filename [in] filename
*
* @return the file pointer or NULL on failure.
*/
FILE *
fopen_writefile(char *filename)
{
FILE *fp;
fp = fopen(filename, "wb");
if (fp == NULL) { /* error */
jlog("Error: gzfile: failed to open \"%s\" for writing\n", filename);
}
return (fp);
}
/**
* Close file previously opened by open_writefile().
*
* @param fp [in] file pointer
*
* @return 0 on success, -1 on failure.
*/
int /* return value: 0=success, -1=failure */
fclose_writefile(FILE *fp)
{
if (fclose(fp) != 0) {
return -1;
}
return 0;
}
/**
* Write data.
*
* @param ptr [in] data buffer
* @param size [in] size of unit in bytes
* @param n [in] number of unit to write
* @param fp [in] file pointer
*
* @return the number of units successfully written, or 0 if EOF or failed.
*/
size_t
myfwrite(void *ptr, size_t size, size_t n, FILE *fp)
{
return(fwrite(ptr, size, n, fp));
}