From a3f923573bbf99961c922107172c7fc97dd2ae9d Mon Sep 17 00:00:00 2001 From: Heng Li Date: Sat, 1 Aug 2009 21:41:19 +0000 Subject: [PATCH] * samtools-0.1.5-21 (r428) * knetfile.c is now compatible with mingw-winsock --- Makefile.mingw | 7 +-- bamtk.c | 10 +++-- knetfile.c | 114 ++++++++++++++++++++++++++++++++++++++----------- knetfile.h | 16 +++++++ 4 files changed, 116 insertions(+), 31 deletions(-) diff --git a/Makefile.mingw b/Makefile.mingw index 601bfb5..fd00358 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -1,9 +1,10 @@ CC= gcc.exe AR= ar.exe CFLAGS= -g -Wall -O2 -DFLAGS= -D_FILE_OFFSET_BITS=64 -D_CURSES_LIB=0 #-D_USE_KNETFILE +DFLAGS= -D_FILE_OFFSET_BITS=64 -D_CURSES_LIB=0 -D_USE_KNETFILE LOBJS= bgzf.o kstring.o bam_aux.o bam.o bam_import.o sam.o bam_index.o \ - bam_pileup.o bam_lpileup.o bam_md.o glf.o razf.o faidx.o bam_sort.o + bam_pileup.o bam_lpileup.o bam_md.o glf.o razf.o faidx.o bam_sort.o \ + knetfile.o AOBJS= bam_tview.o bam_maqcns.o bam_plcmd.o sam_view.o \ bam_rmdup.o bam_rmdupse.o bam_mate.o bam_stat.o bam_color.o \ bamtk.o @@ -25,7 +26,7 @@ libbam.a:$(LOBJS) $(AR) -cru $@ $(LOBJS) samtools:lib $(AOBJS) - $(CC) $(CFLAGS) -o $@ $(AOBJS) $(LIBPATH) -lm -L. -lbam -Lwin32 -lz + $(CC) $(CFLAGS) -o $@ $(AOBJS) $(LIBPATH) -lm -L. -lbam -Lwin32 -lz -lws2_32 razip:razip.o razf.o $(CC) $(CFLAGS) -o $@ razf.o razip.o -lz diff --git a/bamtk.c b/bamtk.c index 25ebff4..fb65838 100644 --- a/bamtk.c +++ b/bamtk.c @@ -1,14 +1,15 @@ #include #include #include +#include #include "bam.h" -#if defined(_WIN32) || defined(_MSC_VER) -#include +#ifdef _USE_KNETFILE +#include "knetfile.h" #endif #ifndef PACKAGE_VERSION -#define PACKAGE_VERSION "0.1.5-20 (r427)" +#define PACKAGE_VERSION "0.1.5-21 (r428)" #endif int bam_taf2baf(int argc, char *argv[]); @@ -99,6 +100,9 @@ int main(int argc, char *argv[]) #ifdef _WIN32 setmode(fileno(stdout), O_BINARY); setmode(fileno(stdin), O_BINARY); +#ifdef _USE_KNETFILE + knet_win32_init(); +#endif #endif if (argc < 2) return usage(); if (strcmp(argv[1], "view") == 0) return main_samview(argc-1, argv+1); diff --git a/knetfile.c b/knetfile.c index 358ee64..3ed3b2c 100644 --- a/knetfile.c +++ b/knetfile.c @@ -1,13 +1,19 @@ #include #include -#include #include #include #include #include #include + +#ifdef _WIN32 +#include +#else +#include #include #include +#endif + #include "knetfile.h" static int socket_wait(int fd, int is_read) @@ -25,6 +31,7 @@ static int socket_wait(int fd, int is_read) return ret; } +#ifndef _WIN32 static int socket_connect(const char *host, const char *port) { #define __err_connect(func) do { perror(func); freeaddrinfo(res); return -1; } while (0) @@ -43,13 +50,53 @@ static int socket_connect(const char *host, const char *port) freeaddrinfo(res); return fd; } +#else +int knet_win32_init() +{ + WSADATA wsaData; + return WSAStartup(MAKEWORD(2, 2), &wsaData); +} +void knet_win32_destroy() +{ + WSACleanup(); +} +static SOCKET socket_connect(const char *host, const char *port) +{ +#define __err_connect(func) do { perror(func); return -1; } while (0) -static off_t my_read(int fd, void *buf, off_t len) + int on = 1; + SOCKET fd; + struct linger lng = { 0, 0 }; + struct sockaddr_in server; + struct hostent *hp = 0; + // open socket + if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) __err_connect("socket"); + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)) == -1) __err_connect("setsockopt"); + if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&lng, sizeof(lng)) == -1) __err_connect("setsockopt"); + // get host info + if (isalpha(host[0])) hp = gethostbyname(host); + else { + struct in_addr addr; + addr.s_addr = inet_addr(host); + hp = gethostbyaddr((char*)&addr, 4, AF_INET); + } + if (hp == 0) __err_connect("gethost"); + // connect + server.sin_addr.s_addr = *((unsigned long*)hp->h_addr); + server.sin_family= AF_INET; + server.sin_port = htons(atoi(port)); + if (connect(fd, (struct sockaddr*)&server, sizeof(server)) != 0) __err_connect("connect"); + // freehostent(hp); // strangely in MSDN, hp is NOT freed (memory leak?!) + return fd; +} +#endif + +static off_t my_netread(int fd, void *buf, off_t len) { off_t rest = len, curr, l = 0; while (rest) { if (socket_wait(fd, 1) <= 0) break; // socket is not ready for reading - curr = read(fd, buf + l, rest); + curr = netread(fd, buf + l, rest); if (curr == 0) break; l += curr; rest -= curr; } @@ -66,7 +113,7 @@ static int kftp_get_response(knetFile *ftp) int n = 0; char *p; if (socket_wait(ftp->ctrl_fd, 1) <= 0) return 0; - while (read(ftp->ctrl_fd, &c, 1)) { // FIXME: this is *VERY BAD* for unbuffered I/O + while (netread(ftp->ctrl_fd, &c, 1)) { // FIXME: this is *VERY BAD* for unbuffered I/O //fputc(c, stderr); if (n >= ftp->max_response) { ftp->max_response = ftp->max_response? ftp->max_response<<1 : 256; @@ -88,7 +135,7 @@ static int kftp_get_response(knetFile *ftp) static int kftp_send_cmd(knetFile *ftp, const char *cmd, int is_get) { if (socket_wait(ftp->ctrl_fd, 0) <= 0) return -1; // socket is not ready for writing - write(ftp->ctrl_fd, cmd, strlen(cmd)); + netwrite(ftp->ctrl_fd, cmd, strlen(cmd)); return is_get? kftp_get_response(ftp) : 0; } @@ -134,11 +181,11 @@ int kftp_connect(knetFile *ftp) int kftp_reconnect(knetFile *ftp) { - if (ftp->ctrl_fd >= 0) { - close(ftp->ctrl_fd); + if (ftp->ctrl_fd != -1) { + netclose(ftp->ctrl_fd); ftp->ctrl_fd = -1; } - close(ftp->fd); + netclose(ftp->fd); return kftp_connect(ftp); } @@ -155,7 +202,7 @@ knetFile *kftp_parse_url(const char *fn, const char *mode) fp = calloc(1, sizeof(knetFile)); fp->type = KNF_TYPE_FTP; fp->fd = -1; - fp->port = strdup("ftp"); + fp->port = strdup("21"); fp->host = calloc(l + 1, 1); if (strchr(mode, 'c')) fp->no_reconnect = 1; strncpy(fp->host, fn + 6, l); @@ -168,8 +215,8 @@ knetFile *kftp_parse_url(const char *fn, const char *mode) int kftp_connect_file(knetFile *fp) { int ret; - if (fp->fd >= 0) { - close(fp->fd); + if (fp->fd != -1) { + netclose(fp->fd); if (fp->no_reconnect) kftp_get_response(fp); } kftp_pasv_prep(fp); @@ -183,7 +230,7 @@ int kftp_connect_file(knetFile *fp) ret = kftp_get_response(fp); if (ret != 150) { fprintf(stderr, "[kftp_connect_file] %s\n", fp->response); - close(fp->fd); + netclose(fp->fd); fp->fd = -1; return -1; } @@ -215,13 +262,13 @@ knetFile *khttp_parse_url(const char *fn, const char *mode) // set ->host, ->port and ->path if (proxy == 0) { fp->host = strdup(fp->http_host); // when there is no proxy, server name is identical to http_host name. - fp->port = strdup(*q? q : "http"); + fp->port = strdup(*q? q : "80"); fp->path = strdup(*p? p : "/"); } else { fp->host = (strstr(proxy, "http://") == proxy)? strdup(proxy + 7) : strdup(proxy); for (q = fp->host; *q && *q != ':'; ++q); if (*q == ':') *q++ = 0; - fp->port = strdup(*q? q : "http"); + fp->port = strdup(*q? q : "80"); fp->path = strdup(fn); } fp->type = KNF_TYPE_HTTP; @@ -234,23 +281,23 @@ int khttp_connect_file(knetFile *fp) { int ret, l = 0; char *buf, *p; - if (fp->fd >= 0) close(fp->fd); + if (fp->fd != -1) netclose(fp->fd); 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, "\r\n"); - write(fp->fd, buf, l); + netwrite(fp->fd, buf, l); l = 0; - while (read(fp->fd, buf + l, 1)) { // read HTTP header; FIXME: bad efficiency + while (netread(fp->fd, buf + l, 1)) { // read HTTP header; FIXME: bad efficiency if (buf[l] == '\n' && l >= 3) if (strncmp(buf + l - 3, "\r\n\r\n", 4) == 0) break; ++l; } buf[l] = 0; if (l < 14) { // prematured header - close(fp->fd); + netclose(fp->fd); fp->fd = -1; return -1; } @@ -259,12 +306,12 @@ int khttp_connect_file(knetFile *fp) off_t rest = fp->offset; while (rest) { off_t l = rest < 0x10000? rest : 0x10000; - rest -= my_read(fp->fd, buf, l); + rest -= my_netread(fp->fd, buf, l); } } else if (ret != 206 && ret != 200) { free(buf); fprintf(stderr, "[khttp_connect_file] fail to open file (HTTP code: %d).\n", ret); - close(fp->fd); + netclose(fp->fd); fp->fd = -1; return -1; } @@ -297,7 +344,11 @@ knetFile *knet_open(const char *fn, const char *mode) if (fp == 0) return 0; khttp_connect_file(fp); } else { // local file +#ifdef _WIN32 + int fd = open(fn, O_RDONLY | O_BINARY); +#else int fd = open(fn, O_RDONLY); +#endif if (fd == -1) { perror("open"); return 0; @@ -307,7 +358,7 @@ knetFile *knet_open(const char *fn, const char *mode) fp->fd = fd; fp->ctrl_fd = -1; } - if (fp && fp->fd < 0) { + if (fp && fp->fd == -1) { knet_close(fp); return 0; } @@ -325,7 +376,7 @@ knetFile *knet_dopen(int fd, const char *mode) off_t knet_read(knetFile *fp, void *buf, off_t len) { off_t l = 0; - if (fp->fd < 0) return 0; + if (fp->fd == -1) return 0; if (fp->type == KNF_TYPE_FTP) { if (fp->is_ready == 0) { if (!fp->no_reconnect) kftp_reconnect(fp); @@ -335,7 +386,14 @@ off_t knet_read(knetFile *fp, void *buf, off_t len) if (fp->is_ready == 0) khttp_connect_file(fp); } - l = my_read(fp->fd, buf, len); + if (fp->type == KNF_TYPE_LOCAL) { // on Windows, the following block is necessary; not on UNIX + off_t rest = len, curr; + while (rest) { + curr = read(fp->fd, buf + l, rest); + if (curr == 0) break; + l += curr; rest -= curr; + } + } else l = my_netread(fp->fd, buf, len); fp->offset += l; return l; } @@ -366,8 +424,11 @@ int knet_seek(knetFile *fp, off_t off, int whence) int knet_close(knetFile *fp) { if (fp == 0) return 0; - if (fp->ctrl_fd >= 0) close(fp->ctrl_fd); // FTP specific - if (fp->fd >= 0) close(fp->fd); + if (fp->ctrl_fd != -1) netclose(fp->ctrl_fd); // FTP specific + if (fp->fd != -1) { + if (fp->type == KNF_TYPE_LOCAL) close(fp->fd); + else netclose(fp->fd); + } free(fp->host); free(fp->port); free(fp->response); free(fp->retr); // FTP specific free(fp->path); free(fp->http_host); // HTTP specific @@ -381,6 +442,9 @@ int main(void) char *buf; knetFile *fp; int type = 4, l; +#ifdef _WIN32 + knet_win32_init(); +#endif buf = calloc(0x100000, 1); if (type == 0) { fp = knet_open("knetfile.c", "r"); diff --git a/knetfile.h b/knetfile.h index 2c55c80..9021b93 100644 --- a/knetfile.h +++ b/knetfile.h @@ -4,6 +4,17 @@ #include #include +#ifndef _WIN32 +#define netread(fd, ptr, len) read(fd, ptr, len) +#define netwrite(fd, ptr, len) write(fd, ptr, len) +#define netclose(fd) close(fd) +#else +#include +#define netread(fd, ptr, len) recv(fd, ptr, len, 0) +#define netwrite(fd, ptr, len) send(fd, ptr, len, 0) +#define netclose(fd) closesocket(fd) +#endif + // FIXME: currently I/O is unbuffered #define KNF_TYPE_LOCAL 1 @@ -31,6 +42,11 @@ typedef struct knetFile_s { extern "C" { #endif +#ifdef _WIN32 + int knet_win32_init(); + void knet_win32_destroy(); +#endif + knetFile *knet_open(const char *fn, const char *mode); /* -- 2.39.5