]> git.donarmstrong.com Git - samtools.git/commitdiff
* samtools-0.1.6-5 (r462)
authorHeng Li <lh3@live.co.uk>
Wed, 16 Sep 2009 08:51:07 +0000 (08:51 +0000)
committerHeng Li <lh3@live.co.uk>
Wed, 16 Sep 2009 08:51:07 +0000 (08:51 +0000)
 * Added knetfile support in razf and faidx (on behalf of Petr Danecek)

bamtk.c
faidx.c
knetfile.c
knetfile.h
razf.c
razf.h

diff --git a/bamtk.c b/bamtk.c
index 0b4aef4fdfcf58856962e7aaf4f2577f7d98d8a6..a383c45c1ea990cbb195f63e831e740011f7aa43 100644 (file)
--- a/bamtk.c
+++ b/bamtk.c
@@ -9,7 +9,7 @@
 #endif
 
 #ifndef PACKAGE_VERSION
-#define PACKAGE_VERSION "0.1.6-4 (r459)"
+#define PACKAGE_VERSION "0.1.6-5 (r462)"
 #endif
 
 int bam_taf2baf(int argc, char *argv[]);
diff --git a/faidx.c b/faidx.c
index 77adbde781d393ff09d264e05385b347aa22090c..811bdf8858ff9ef18479fb644981ad4780bf7a8d 100644 (file)
--- a/faidx.c
+++ b/faidx.c
@@ -28,6 +28,9 @@ extern int fseeko(FILE *stream, off_t offset, int whence);
 #define razf_seek(fp, offset, whence) fseeko(fp, offset, whence)
 #define razf_tell(fp) ftello(fp)
 #endif
+#ifdef _USE_KNETFILE
+#include "knetfile.h"
+#endif
 
 struct __faidx_t {
        RAZF *rz;
@@ -194,7 +197,7 @@ int fai_build(const char *fn)
        sprintf(str, "%s.fai", fn);
        rz = razf_open(fn, "r");
        if (rz == 0) {
-               fprintf(stderr, "[fai_build] fail to open the FASTA file.\n");
+               fprintf(stderr, "[fai_build] fail to open the FASTA file %s\n",str);
                free(str);
                return -1;
        }
@@ -202,7 +205,7 @@ int fai_build(const char *fn)
        razf_close(rz);
        fp = fopen(str, "wb");
        if (fp == 0) {
-               fprintf(stderr, "[fai_build] fail to write FASTA index.\n");
+               fprintf(stderr, "[fai_build] fail to write FASTA index %s\n",str);
                fai_destroy(fai); free(str);
                return -1;
        }
@@ -213,6 +216,47 @@ int fai_build(const char *fn)
        return 0;
 }
 
+#ifdef _USE_KNETFILE
+FILE *download_and_open(const char *fn)
+{
+    const int buf_size = 1 * 1024 * 1024;
+    uint8_t *buf;
+    FILE *fp;
+    knetFile *fp_remote;
+    const char *url = fn;
+    const char *p;
+    int l = strlen(fn);
+    for (p = fn + l - 1; p >= fn; --p)
+        if (*p == '/') break;
+    fn = p + 1;
+
+    // First try to open a local copy
+    fp = fopen(fn, "r");
+    if (fp)
+        return fp;
+
+    // If failed, download from remote and open
+    fp_remote = knet_open(url, "rb");
+    if (fp_remote == 0) {
+        fprintf(stderr, "[download_from_remote] fail to open remote file %s\n",url);
+        return NULL;
+    }
+    if ((fp = fopen(fn, "wb")) == 0) {
+        fprintf(stderr, "[download_from_remote] fail to create file in the working directory %s\n",fn);
+        knet_close(fp_remote);
+        return NULL;
+    }
+    buf = (uint8_t*)calloc(buf_size, 1);
+    while ((l = knet_read(fp_remote, buf, buf_size)) != 0)
+        fwrite(buf, 1, l, fp);
+    free(buf);
+    fclose(fp);
+    knet_close(fp_remote);
+
+    return fopen(fn, "r");
+}
+#endif
+
 faidx_t *fai_load(const char *fn)
 {
        char *str;
@@ -220,19 +264,35 @@ faidx_t *fai_load(const char *fn)
        faidx_t *fai;
        str = (char*)calloc(strlen(fn) + 5, 1);
        sprintf(str, "%s.fai", fn);
-       fp = fopen(str, "rb");
+
+#ifdef _USE_KNETFILE
+    if (strstr(fn, "ftp://") == fn || strstr(fn, "http://") == fn)
+    {
+        fp = download_and_open(str);
+        if ( !fp )
+        {
+            fprintf(stderr, "[fai_load] failed to open remote FASTA index %s\n", str);
+            free(str);
+            return 0;
+        }
+    }
+    else
+#endif
+        fp = fopen(str, "rb");
        if (fp == 0) {
                fprintf(stderr, "[fai_load] build FASTA index.\n");
                fai_build(fn);
-               fp = fopen(str, "r");
+               fp = fopen(str, "rb");
                if (fp == 0) {
                        fprintf(stderr, "[fai_load] fail to open FASTA index.\n");
                        free(str);
                        return 0;
                }
        }
+
        fai = fai_read(fp);
        fclose(fp);
+
        fai->rz = razf_open(fn, "rb");
        free(str);
        if (fai->rz == 0) {
@@ -287,7 +347,7 @@ char *fai_fetch(const faidx_t *fai, const char *str, int *len)
        l = 0;
        s = (char*)malloc(end - beg + 2);
        razf_seek(fai->rz, val.offset + beg / val.line_blen * val.line_len + beg % val.line_blen, SEEK_SET);
-       while (razf_read(fai->rz, &c, 1) == 1 && l < end - beg)
+       while (razf_read(fai->rz, &c, 1) == 1 && l < end - beg && !fai->rz->z_err)
                if (isgraph(c)) s[l++] = c;
        s[l] = '\0';
        *len = l;
index e110aa720f6577e7f8dee34fddc32cb6220d7154..ac51a6bf39b4e702bbe24cc4afdb118bf5524911 100644 (file)
@@ -262,7 +262,7 @@ int kftp_reconnect(knetFile *ftp)
        return kftp_connect(ftp);
 }
 
-// initialize ->type, ->host and ->retr
+// initialize ->type, ->host, ->retr and ->size
 knetFile *kftp_parse_url(const char *fn, const char *mode)
 {
        knetFile *fp;
@@ -283,19 +283,28 @@ knetFile *kftp_parse_url(const char *fn, const char *mode)
        strncpy(fp->host, fn + 6, l);
        fp->retr = calloc(strlen(p) + 8, 1);
        sprintf(fp->retr, "RETR %s\r\n", p);
-       fp->seek_offset = -1;
+    fp->size_cmd = calloc(strlen(p) + 8, 1);
+    sprintf(fp->size_cmd, "SIZE %s\r\n", p);
+       fp->seek_offset = 0;
        return fp;
 }
 // place ->fd at offset off
 int kftp_connect_file(knetFile *fp)
 {
        int ret;
+       long long file_size;
        if (fp->fd != -1) {
                netclose(fp->fd);
                if (fp->no_reconnect) kftp_get_response(fp);
        }
        kftp_pasv_prep(fp);
-       if (fp->offset) {
+    kftp_send_cmd(fp, fp->size_cmd, 1);
+    if ( sscanf(fp->response,"%*d %lld", &file_size) != 1 )
+    {
+        fprintf(stderr,"[kftp_connect_file] %s\n", fp->response);
+        return -1;
+    } else fp->file_size = file_size;
+       if (fp->offset>=0) {
                char tmp[32];
 #ifndef _WIN32
                sprintf(tmp, "REST %lld\r\n", (long long)fp->offset);
@@ -319,6 +328,7 @@ int kftp_connect_file(knetFile *fp)
        return 0;
 }
 
+
 /**************************
  * HTTP specific routines *
  **************************/
@@ -354,7 +364,7 @@ knetFile *khttp_parse_url(const char *fn, const char *mode)
        }
        fp->type = KNF_TYPE_HTTP;
        fp->ctrl_fd = fp->fd = -1;
-       fp->seek_offset = -1;
+       fp->seek_offset = 0;
        return fp;
 }
 
@@ -366,8 +376,7 @@ int khttp_connect_file(knetFile *fp)
        fp->fd = socket_connect(fp->host, fp->port);
        buf = calloc(0x10000, 1); // FIXME: I am lazy... But in principle, 64KB should be large enough.
        l += sprintf(buf + l, "GET %s HTTP/1.0\r\nHost: %s\r\n", fp->path, fp->http_host);
-       if (fp->offset)
-               l += sprintf(buf + l, "Range: bytes=%lld-\r\n", (long long)fp->offset);
+    l += sprintf(buf + l, "Range: bytes=%lld-\r\n", (long long)fp->offset);
        l += sprintf(buf + l, "\r\n");
        netwrite(fp->fd, buf, l);
        l = 0;
@@ -383,7 +392,7 @@ int khttp_connect_file(knetFile *fp)
                return -1;
        }
        ret = strtol(buf + 8, &p, 0); // HTTP return code
-       if (ret == 200 && fp->offset) { // 200 (complete result); then skip beginning of the file
+       if (ret == 200 && fp->offset>0) { // 200 (complete result); then skip beginning of the file
                off_t rest = fp->offset;
                while (rest) {
                        off_t l = rest < 0x10000? rest : 0x10000;
@@ -482,7 +491,7 @@ off_t knet_read(knetFile *fp, void *buf, off_t len)
        return l;
 }
 
-int knet_seek(knetFile *fp, off_t off, int whence)
+off_t knet_seek(knetFile *fp, off_t off, int whence)
 {
        if (whence == SEEK_SET && off == fp->offset) return 0;
        if (fp->type == KNF_TYPE_LOCAL) {
@@ -494,15 +503,31 @@ int knet_seek(knetFile *fp, off_t off, int whence)
                        return -1;
                }
                fp->offset = offset;
-               return 0;
-       } else if (fp->type == KNF_TYPE_FTP || fp->type == KNF_TYPE_HTTP) {
-               if (whence != SEEK_SET) { // FIXME: we can surely allow SEEK_CUR and SEEK_END in future
-                       fprintf(stderr, "[knet_seek] only SEEK_SET is supported for FTP/HTTP. Offset is unchanged.\n");
+               return fp->offset;
+       }
+    else if (fp->type == KNF_TYPE_FTP) 
+    {
+        if (whence==SEEK_CUR)
+            fp->offset += off;
+        else if (whence==SEEK_SET)
+            fp->offset = off;
+        else if ( whence==SEEK_END)
+            fp->offset = fp->file_size+off;
+               fp->is_ready = 0;
+               return fp->offset;
+       } 
+    else if (fp->type == KNF_TYPE_HTTP) 
+    {
+               if (whence == SEEK_END) { // FIXME: we can surely allow SEEK_CUR and SEEK_END in future
+                       fprintf(stderr, "[knet_seek] SEEK_END is supported for HTTP. Offset is unchanged.\n");
                        return -1;
                }
-               fp->offset = off;
+        if (whence==SEEK_CUR)
+            fp->offset += off;
+        else if (whence==SEEK_SET)
+            fp->offset = off;
                fp->is_ready = 0;
-               return 0;
+               return fp->offset;
        }
        return -1;
 }
index 9021b937ac211c1459ef1afec3c20b49ce6007a1..f5fa0fcfd6fdb9a25e02ee777d68c8a2301d23b0 100644 (file)
@@ -28,8 +28,9 @@ typedef struct knetFile_s {
 
        // the following are for FTP only
        int ctrl_fd, pasv_ip[4], pasv_port, max_response, no_reconnect, is_ready;
-       char *response, *retr;
+       char *response, *retr, *size_cmd;
        int64_t seek_offset; // for lazy seek
+    int64_t file_size;
 
        // the following are for HTTP only
        char *path, *http_host;
@@ -64,7 +65,7 @@ extern "C" {
          This routine only sets ->offset and ->is_ready=0. It does not
          communicate with the FTP server.
         */
-       int knet_seek(knetFile *fp, off_t off, int whence);
+       off_t knet_seek(knetFile *fp, off_t off, int whence);
        int knet_close(knetFile *fp);
 
 #ifdef __cplusplus
diff --git a/razf.c b/razf.c
index ea4e37d5717a102b77801e254e4828ac8f3c8f14..ce8edb886797033a434423d68046fea9928ae481 100644 (file)
--- a/razf.c
+++ b/razf.c
@@ -38,6 +38,7 @@
 #include <unistd.h>
 #include "razf.h"
 
+
 #if ZLIB_VERNUM < 0x1221
 struct _gz_header_s {
     int     text;
@@ -107,20 +108,36 @@ static void save_zindex(RAZF *rz, int fd){
 }
 #endif
 
+#ifdef _USE_KNETFILE
+static void load_zindex(RAZF *rz, knetFile *fp){
+#else
 static void load_zindex(RAZF *rz, int fd){
+#endif
        int32_t i, v32;
        int is_be;
        if(!rz->load_index) return;
        if(rz->index == NULL) rz->index = malloc(sizeof(ZBlockIndex));
        is_be = is_big_endian();
+#ifdef _USE_KNETFILE
+       knet_read(fp, &rz->index->size, sizeof(int));
+#else
        read(fd, &rz->index->size, sizeof(int));
+#endif
        if(!is_be) rz->index->size = byte_swap_4((uint32_t)rz->index->size);
        rz->index->cap = rz->index->size;
        v32 = rz->index->size / RZ_BIN_SIZE + 1;
        rz->index->bin_offsets  = malloc(sizeof(int64_t) * v32);
+#ifdef _USE_KNETFILE
+       knet_read(fp, rz->index->bin_offsets, sizeof(int64_t) * v32);
+#else
        read(fd, rz->index->bin_offsets, sizeof(int64_t) * v32);
+#endif
        rz->index->cell_offsets = malloc(sizeof(int) * rz->index->size);
+#ifdef _USE_KNETFILE
+       knet_read(fp, rz->index->cell_offsets, sizeof(int) * rz->index->size);
+#else
        read(fd, rz->index->cell_offsets, sizeof(int) * rz->index->size);
+#endif
        if(!is_be){
                for(i=0;i<v32;i++) rz->index->bin_offsets[i] = byte_swap_8((uint64_t)rz->index->bin_offsets[i]);
                for(i=0;i<rz->index->size;i++) rz->index->cell_offsets[i] = byte_swap_4((uint32_t)rz->index->cell_offsets[i]);
@@ -141,7 +158,11 @@ static RAZF* razf_open_w(int fd){
 #endif
        rz = calloc(1, sizeof(RAZF));
        rz->mode = 'w';
+#ifdef _USE_KNETFILE
+    rz->x.fpw = fd;
+#else
        rz->filedes = fd;
+#endif
        rz->stream = calloc(sizeof(z_stream), 1);
        rz->inbuf  = malloc(RZ_BUFFER_SIZE);
        rz->outbuf = malloc(RZ_BUFFER_SIZE);
@@ -176,7 +197,11 @@ static void _razf_write(RAZF* rz, const void *data, int size){
                deflate(rz->stream, Z_NO_FLUSH);
                rz->out += tout - rz->stream->avail_out;
                if(rz->stream->avail_out) break;
+#ifdef _USE_KNETFILE
+               write(rz->x.fpw, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);
+#else
                write(rz->filedes, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);
+#endif
                rz->stream->avail_out = RZ_BUFFER_SIZE;
                rz->stream->next_out  = rz->outbuf;
                if(rz->stream->avail_in == 0) break;
@@ -192,7 +217,11 @@ static void razf_flush(RAZF *rz){
                rz->buf_off = rz->buf_len = 0;
        }
        if(rz->stream->avail_out){
+#ifdef _USE_KNETFILE    
+               write(rz->x.fpw, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);
+#else        
                write(rz->filedes, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);
+#endif
                rz->stream->avail_out = RZ_BUFFER_SIZE;
                rz->stream->next_out  = rz->outbuf;
        }
@@ -201,7 +230,11 @@ static void razf_flush(RAZF *rz){
                deflate(rz->stream, Z_FULL_FLUSH);
                rz->out += tout - rz->stream->avail_out;
                if(rz->stream->avail_out == 0){
+#ifdef _USE_KNETFILE    
+                       write(rz->x.fpw, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);
+#else            
                        write(rz->filedes, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);
+#endif
                        rz->stream->avail_out = RZ_BUFFER_SIZE;
                        rz->stream->next_out  = rz->outbuf;
                } else break;
@@ -221,7 +254,11 @@ static void razf_end_flush(RAZF *rz){
                deflate(rz->stream, Z_FINISH);
                rz->out += tout - rz->stream->avail_out;
                if(rz->stream->avail_out < RZ_BUFFER_SIZE){
+#ifdef _USE_KNETFILE        
+                       write(rz->x.fpw, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);
+#else            
                        write(rz->filedes, rz->outbuf, RZ_BUFFER_SIZE - rz->stream->avail_out);
+#endif
                        rz->stream->avail_out = RZ_BUFFER_SIZE;
                        rz->stream->next_out  = rz->outbuf;
                } else break;
@@ -308,23 +345,35 @@ static int _read_gz_header(unsigned char *data, int size, int *extra_off, int *e
        return n;
 }
 
+#ifdef _USE_KNETFILE
+static RAZF* razf_open_r(knetFile *fp, int _load_index){
+#else
 static RAZF* razf_open_r(int fd, int _load_index){
+#endif
        RAZF *rz;
        int ext_off, ext_len;
        int n, is_be, ret;
        int64_t end;
        unsigned char c[] = "RAZF";
+       rz = calloc(1, sizeof(RAZF));
+       rz->mode = 'r';
+#ifdef _USE_KNETFILE
+    rz->x.fpr = fp;
+#else
 #ifdef _WIN32
        setmode(fd, O_BINARY);
 #endif
-       rz = calloc(1, sizeof(RAZF));
-       rz->mode = 'r';
        rz->filedes = fd;
+#endif
        rz->stream = calloc(sizeof(z_stream), 1);
        rz->inbuf  = malloc(RZ_BUFFER_SIZE);
        rz->outbuf = malloc(RZ_BUFFER_SIZE);
        rz->end = rz->src_end = 0x7FFFFFFFFFFFFFFFLL;
+#ifdef _USE_KNETFILE
+    n = knet_read(rz->x.fpr, rz->inbuf, RZ_BUFFER_SIZE);
+#else
        n = read(rz->filedes, rz->inbuf, RZ_BUFFER_SIZE);
+#endif
        ret = _read_gz_header(rz->inbuf, n, &ext_off, &ext_len);
        if(ret == 0){
                PLAIN_FILE:
@@ -355,7 +404,11 @@ static RAZF* razf_open_r(int fd, int _load_index){
        }
        rz->load_index = _load_index;
        rz->file_type = FILE_TYPE_RZ;
+#ifdef _USE_KNETFILE
+       if(knet_seek(fp, -16, SEEK_END) == -1){
+#else
        if(lseek(fd, -16, SEEK_END) == -1){
+#endif
                UNSEEKABLE:
                rz->seekable = 0;
                rz->index = NULL;
@@ -363,10 +416,19 @@ static RAZF* razf_open_r(int fd, int _load_index){
        } else {
                is_be = is_big_endian();
                rz->seekable = 1;
+#ifdef _USE_KNETFILE
+        knet_read(fp, &end, sizeof(int64_t));
+#else
                read(fd, &end, sizeof(int64_t));
+#endif        
                if(!is_be) rz->src_end = (int64_t)byte_swap_8((uint64_t)end);
                else rz->src_end = end;
+
+#ifdef _USE_KNETFILE
+               knet_read(fp, &end, sizeof(int64_t));
+#else
                read(fd, &end, sizeof(int64_t));
+#endif        
                if(!is_be) rz->end = (int64_t)byte_swap_8((uint64_t)end);
                else rz->end = end;
                if(n > rz->end){
@@ -374,19 +436,46 @@ static RAZF* razf_open_r(int fd, int _load_index){
                        n = rz->end;
                }
                if(rz->end > rz->src_end){
+#ifdef _USE_KNETFILE
+            knet_seek(fp, rz->in, SEEK_SET);
+#else
                        lseek(fd, rz->in, SEEK_SET);
+#endif
                        goto UNSEEKABLE;
                }
+#ifdef _USE_KNETFILE
+               if(knet_seek(fp, rz->end, SEEK_SET) != rz->end){
+                       knet_seek(fp, rz->in, SEEK_SET);
+#else
                if(lseek(fd, rz->end, SEEK_SET) != rz->end){
                        lseek(fd, rz->in, SEEK_SET);
+#endif
                        goto UNSEEKABLE;
                }
+#ifdef _USE_KNETFILE
+               load_zindex(rz, fp);
+               knet_seek(fp, n, SEEK_SET);
+#else
                load_zindex(rz, fd);
                lseek(fd, n, SEEK_SET);
+#endif
        }
        return rz;
 }
 
+#ifdef _USE_KNETFILE
+RAZF* razf_dopen(int fd, const char *mode){
+    if (strstr(mode, "r")) fprintf(stderr,"[razf_dopen] implement me\n");
+    else if(strstr(mode, "w")) return razf_open_w(fd);
+       return NULL;
+}
+
+RAZF* razf_dopen2(int fd, const char *mode)
+{
+    fprintf(stderr,"[razf_dopen2] implement me\n");
+    return NULL;
+}
+#else
 RAZF* razf_dopen(int fd, const char *mode){
        if(strstr(mode, "r")) return razf_open_r(fd, 1);
        else if(strstr(mode, "w")) return razf_open_w(fd);
@@ -399,15 +488,24 @@ RAZF* razf_dopen2(int fd, const char *mode)
        else if(strstr(mode, "w")) return razf_open_w(fd);
        else return NULL;
 }
+#endif
 
 static inline RAZF* _razf_open(const char *filename, const char *mode, int _load_index){
        int fd;
        RAZF *rz;
        if(strstr(mode, "r")){
+#ifdef _USE_KNETFILE
+        knetFile *fd = knet_open(filename, "r");
+        if (fd == 0) {
+            fprintf(stderr, "[_razf_open] fail to open remote file %s\n", filename);
+            return NULL;
+        }
+#else
 #ifdef _WIN32
                fd = open(filename, O_RDONLY | O_BINARY);
 #else
                fd = open(filename, O_RDONLY);
+#endif
 #endif
                if(fd < 0) return NULL;
                rz = razf_open_r(fd, _load_index);
@@ -437,9 +535,15 @@ int razf_get_data_size(RAZF *rz, int64_t *u_size, int64_t *c_size){
        switch(rz->file_type){
                case FILE_TYPE_PLAIN:
                        if(rz->end == 0x7fffffffffffffffLL){
+#ifdef _USE_KNETFILE
+                               if((n = knet_seek(rz->x.fpr, 0, SEEK_CUR)) == -1) return 0;
+                               rz->end = knet_seek(rz->x.fpr, 0, SEEK_END);
+                               knet_seek(rz->x.fpr, n, SEEK_SET);
+#else
                                if((n = lseek(rz->filedes, 0, SEEK_CUR)) == -1) return 0;
                                rz->end = lseek(rz->filedes, 0, SEEK_END);
                                lseek(rz->filedes, n, SEEK_SET);
+#endif                
                        }
                        *u_size = *c_size = rz->end;
                        return 1;
@@ -459,7 +563,11 @@ static int _razf_read(RAZF* rz, void *data, int size){
        int ret, tin;
        if(rz->z_eof || rz->z_err) return 0;
        if (rz->file_type == FILE_TYPE_PLAIN) {
+#ifdef _USE_KNETFILE
+               ret = knet_read(rz->x.fpr, data, size);
+#else
                ret = read(rz->filedes, data, size);
+#endif        
                if (ret == 0) rz->z_eof = 1;
                return ret;
        }
@@ -469,9 +577,17 @@ static int _razf_read(RAZF* rz, void *data, int size){
                if(rz->stream->avail_in == 0){
                        if(rz->in >= rz->end){ rz->z_eof = 1; break; }
                        if(rz->end - rz->in < RZ_BUFFER_SIZE){
+#ifdef _USE_KNETFILE
+                               rz->stream->avail_in = knet_read(rz->x.fpr, rz->inbuf, rz->end -rz->in);
+#else
                                rz->stream->avail_in = read(rz->filedes, rz->inbuf, rz->end -rz->in);
+#endif        
                        } else {
+#ifdef _USE_KNETFILE
+                               rz->stream->avail_in = knet_read(rz->x.fpr, rz->inbuf, RZ_BUFFER_SIZE);
+#else
                                rz->stream->avail_in = read(rz->filedes, rz->inbuf, RZ_BUFFER_SIZE);
+#endif        
                        }
                        if(rz->stream->avail_in == 0){
                                rz->z_eof = 1;
@@ -483,7 +599,7 @@ static int _razf_read(RAZF* rz, void *data, int size){
                ret = inflate(rz->stream, Z_BLOCK);
                rz->in += tin - rz->stream->avail_in;
                if(ret == Z_NEED_DICT || ret == Z_MEM_ERROR || ret == Z_DATA_ERROR){
-                       fprintf(stderr, "[_razf_read] inflate error: %d (at %s:%d)\n", ret, __FILE__, __LINE__);
+                       fprintf(stderr, "[_razf_read] inflate error: %d %s (at %s:%d)\n", ret, rz->stream->msg ? rz->stream->msg : "", __FILE__, __LINE__);
                        rz->z_err = 1;
                        break;
                }
@@ -568,14 +684,18 @@ int razf_skip(RAZF* rz, int size){
                }
                if(rz->buf_flush) continue;
                rz->buf_len = _razf_read(rz, rz->outbuf, RZ_BUFFER_SIZE);
-               if(rz->z_eof) break;
+               if(rz->z_eof || rz->z_err) break;
        }
        rz->out += ori_size - size;
        return ori_size - size;
 }
 
 static void _razf_reset_read(RAZF *rz, int64_t in, int64_t out){
+#ifdef _USE_KNETFILE
+       knet_seek(rz->x.fpr, in, SEEK_SET);
+#else
        lseek(rz->filedes, in, SEEK_SET);
+#endif
        rz->in  = in;
        rz->out = out;
        rz->block_pos = in;
@@ -594,7 +714,11 @@ int64_t razf_jump(RAZF *rz, int64_t block_start, int block_offset){
        if(rz->file_type == FILE_TYPE_PLAIN){
                rz->buf_off = rz->buf_len = 0;
                pos = block_start + block_offset;
+#ifdef _USE_KNETFILE
+               pos = knet_seek(rz->x.fpr, pos, SEEK_SET);
+#else
                pos = lseek(rz->filedes, pos, SEEK_SET);
+#endif
                rz->out = rz->in = pos;
                return pos;
        }
@@ -616,7 +740,11 @@ int64_t razf_seek(RAZF* rz, int64_t pos, int where){
        if (where == SEEK_CUR) pos += rz->out;
        else if (where == SEEK_END) pos += rz->src_end;
        if(rz->file_type == FILE_TYPE_PLAIN){
+#ifdef _USE_KNETFILE
+               seek_pos = knet_seek(rz->x.fpr, pos, SEEK_SET);
+#else
                seek_pos = lseek(rz->filedes, pos, SEEK_SET);
+#endif
                rz->buf_off = rz->buf_len = 0;
                rz->out = rz->in = seek_pos;
                return seek_pos;
@@ -665,6 +793,18 @@ void razf_close(RAZF *rz){
 #ifndef _RZ_READONLY
                razf_end_flush(rz);
                deflateEnd(rz->stream);
+#ifdef _USE_KNETFILE
+               save_zindex(rz, rz->x.fpw);
+               if(is_big_endian()){
+                       write(rz->x.fpw, &rz->in, sizeof(int64_t));
+                       write(rz->x.fpw, &rz->out, sizeof(int64_t));
+               } else {
+                       uint64_t v64 = byte_swap_8((uint64_t)rz->in);
+                       write(rz->x.fpw, &v64, sizeof(int64_t));
+                       v64 = byte_swap_8((uint64_t)rz->out);
+                       write(rz->x.fpw, &v64, sizeof(int64_t));
+               }
+#else
                save_zindex(rz, rz->filedes);
                if(is_big_endian()){
                        write(rz->filedes, &rz->in, sizeof(int64_t));
@@ -675,6 +815,7 @@ void razf_close(RAZF *rz){
                        v64 = byte_swap_8((uint64_t)rz->out);
                        write(rz->filedes, &v64, sizeof(int64_t));
                }
+#endif
 #endif
        } else if(rz->mode == 'r'){
                if(rz->stream) inflateEnd(rz->stream);
@@ -693,7 +834,14 @@ void razf_close(RAZF *rz){
                free(rz->index);
        }
        free(rz->stream);
+#ifdef _USE_KNETFILE
+    if (rz->mode == 'r')
+        knet_close(rz->x.fpr);
+    if (rz->mode == 'w')
+        close(rz->x.fpw);
+#else
        close(rz->filedes);
+#endif
        free(rz);
 }
 
diff --git a/razf.h b/razf.h
index f7e5097687359d02cf5019a642435a25ba781811..60a0c96457304ec5a728a5dcddb61e1f649e5637 100644 (file)
--- a/razf.h
+++ b/razf.h
 #include <stdio.h>
 #include "zlib.h"
 
+#ifdef _USE_KNETFILE
+#include "knetfile.h"
+#endif
+
 #if ZLIB_VERNUM < 0x1221
 #define _RZ_READONLY
 struct _gz_header_s;
@@ -76,7 +80,14 @@ typedef struct RandomAccessZFile  {
        char mode; /* 'w' : write mode; 'r' : read mode */
        int file_type;
        /* plain file or rz file, razf_read support plain file as input too, in this case, razf_read work as buffered fread */
+#ifdef _USE_KNETFILE
+    union {
+        knetFile *fpr;
+        int fpw;
+    } x;
+#else
        int filedes; /* the file descriptor */
+#endif
        z_stream *stream;
        ZBlockIndex *index;
        int64_t in, out, end, src_end;