X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=knetfile.c;h=9029ee4c6f93fecd353866ad6a3cbc6cb723c0e5;hb=e7c6e7a7c181d8ee9d1a206d264a24b54b4911f4;hp=d30fcbbb0617f0e86d255ed2261f1891c8426b0f;hpb=cd86e7be490dcde2d2166caaf3b61de38417ba18;p=samtools.git diff --git a/knetfile.c b/knetfile.c index d30fcbb..9029ee4 100644 --- a/knetfile.c +++ b/knetfile.c @@ -15,14 +15,15 @@ static int kftp_get_response(knetFile *ftp) int n = 0; char *p; while (read(ftp->ctrl_fd, &c, 1)) { // FIXME: this is *VERY BAD* for unbuffered I/O -// fputc(c, stderr); + //fputc(c, stderr); if (n >= ftp->max_response) { ftp->max_response = ftp->max_response? ftp->max_response<<1 : 256; ftp->response = realloc(ftp->response, ftp->max_response); } ftp->response[n++] = c; if (c == '\n') { - if (n >= 4 && isdigit(ftp->response[0]) && isdigit(ftp->response[1]) && isdigit(ftp->response[2]) && ftp->response[3] != '-') break; + if (n >= 4 && isdigit(ftp->response[0]) && isdigit(ftp->response[1]) && isdigit(ftp->response[2]) + && ftp->response[3] != '-') break; n = 0; continue; } @@ -58,7 +59,7 @@ static int kftp_pasv_connect(knetFile *ftp) struct addrinfo hints, *res; struct linger lng = { 0, 0 }; - int on; + int on = 1; char host[80], port[10]; if (ftp->pasv_port == 0) { @@ -83,7 +84,7 @@ int kftp_connect(knetFile *ftp) { #define __err_connect(func) do { perror(func); return -1; } while (0) - int on; + int on = 1; { // open socket struct addrinfo hints, *res; memset(&hints, 0, sizeof(struct addrinfo)); @@ -106,16 +107,16 @@ int kftp_connect(knetFile *ftp) int kftp_reconnect(knetFile *ftp) { - if (ftp->ctrl_fd) { + if (ftp->ctrl_fd >= 0) { close(ftp->ctrl_fd); - ftp->ctrl_fd = 0; + ftp->ctrl_fd = -1; } close(ftp->fd); return kftp_connect(ftp); } // initialize ->type, ->host and ->retr -knetFile *kftp_prep(const char *fn, const char *mode) +knetFile *kftp_parse_url(const char *fn, const char *mode) { knetFile *fp; char *p; @@ -126,30 +127,39 @@ knetFile *kftp_prep(const char *fn, const char *mode) l = p - fn - 6; fp = calloc(1, sizeof(knetFile)); fp->type = KNF_TYPE_FTP; + fp->fd = -1; fp->host = calloc(l + 1, 1); if (strchr(mode, 'c')) fp->no_reconnect = 1; strncpy(fp->host, fn + 6, l); - fp->retr = calloc(strlen(p) + 7, 1); + fp->retr = calloc(strlen(p) + 8, 1); sprintf(fp->retr, "RETR %s\r\n", p); + fp->seek_offset = -1; return fp; } // place ->fd at offset off -int kftp_connect_file(knetFile *fp, off_t off) +int kftp_connect_file(knetFile *fp) { - if (fp->fd) { + int ret; + if (fp->fd >= 0) { close(fp->fd); if (fp->no_reconnect) kftp_get_response(fp); } kftp_pasv_prep(fp); - if (off) { + if (fp->offset) { char tmp[32]; - sprintf(tmp, "REST %lld\r\n", (long long)off); + sprintf(tmp, "REST %lld\r\n", (long long)fp->offset); kftp_send_cmd(fp, tmp, 1); } kftp_send_cmd(fp, fp->retr, 0); kftp_pasv_connect(fp); - kftp_get_response(fp); - fp->offset = off; + ret = kftp_get_response(fp); + if (ret != 150) { + fprintf(stderr, "[kftp_connect_file] %s\n", fp->response); + close(fp->fd); + fp->fd = -1; + return -1; + } + fp->is_ready = 1; return 0; } @@ -161,13 +171,17 @@ knetFile *knet_open(const char *fn, const char *mode) return 0; } if (strstr(fn, "ftp://") == fn) { - fp = kftp_prep(fn, mode); + fp = kftp_parse_url(fn, mode); if (fp == 0) return 0; if (kftp_connect(fp) == -1) { knet_close(fp); return 0; } - kftp_connect_file(fp, 0); + kftp_connect_file(fp); + if (fp->fd < 0) { + knet_close(fp); + return 0; + } } else { int fd = open(fn, O_RDONLY); if (fd == -1) { @@ -181,36 +195,65 @@ knetFile *knet_open(const char *fn, const char *mode) return fp; } +knetFile *knet_dopen(int fd, const char *mode) +{ + knetFile *fp = (knetFile*)calloc(1, sizeof(knetFile)); + fp->type = KNF_TYPE_LOCAL; + fp->fd = fd; + return fp; +} + off_t knet_read(knetFile *fp, void *buf, off_t len) { - off_t l = read(fp->fd, buf, len); - fp->offset += l; + off_t l = 0; + if (fp->fd < 0) return 0; + if (fp->type == KNF_TYPE_LOCAL) { + l = read(fp->fd, buf, len); + fp->offset += l; + } else { + off_t rest = len, curr; + if (fp->is_ready == 0) { + if (!fp->no_reconnect) kftp_reconnect(fp); + kftp_connect_file(fp); + fp->is_ready = 1; + } + while (rest) { + curr = read(fp->fd, buf + l, rest); + if (curr == 0) break; // FIXME: end of file or bad network? I do not know... + l += curr; rest -= curr; + } + fp->offset += l; + } return l; } -off_t knet_seek(knetFile *fp, off_t off, int whence) +int knet_seek(knetFile *fp, off_t off, int whence) { if (fp->type == KNF_TYPE_LOCAL) { - fp->offset = lseek(fp->fd, off, whence); - return fp->offset; + if (lseek(fp->fd, off, whence) == -1) { + perror("lseek"); + return -1; + } + fp->offset = off; + return 0; } if (fp->type == KNF_TYPE_FTP) { - if (whence != SEEK_SET) { + 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. Offset is unchanged.\n"); return -1; } - if (!fp->no_reconnect) kftp_reconnect(fp); - kftp_connect_file(fp, off); - return fp->offset; + fp->offset = off; + fp->is_ready = 0; + return 0; } - return 0; + return -1; } int knet_close(knetFile *fp) { if (fp == 0) return 0; - if (fp->ctrl_fd > 0) close(fp->ctrl_fd); - if (fp->fd > 0) close(fp->fd); + if (fp->ctrl_fd >= 0) close(fp->ctrl_fd); + if (fp->fd >= 0) close(fp->fd); free(fp->response); free(fp->retr); free(fp->host); free(fp); return 0; @@ -222,8 +265,8 @@ int main(void) char buf[256]; knetFile *fp; // fp = knet_open("ftp://ftp.ncbi.nih.gov/1000genomes/ftp/data/NA12878/alignment/NA12878.chrom6.SLX.SRP000032.2009_06.bam", "r"); knet_seek(fp, 2500000000ll, SEEK_SET); -// fp = knet_open("ftp://ftp.sanger.ac.uk/pub4/treefam/tmp/index.shtml", "r"); knet_seek(fp, 2000, SEEK_SET); - fp = knet_open("knetfile.c", "r"); knet_seek(fp, 2000, SEEK_SET); + fp = knet_open("ftp://ftp.sanger.ac.uk/pub4/treefam/tmp/index.shtml", "r"); knet_seek(fp, 2000, SEEK_SET); +// fp = knet_open("knetfile.c", "r"); knet_seek(fp, 2000, SEEK_SET); knet_read(fp, buf, 255); buf[255] = 0; printf("%s\n", buf);