⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 curl.c

📁 linux下开源图片codec
💻 C
字号:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <time.h>#include <errno.h>#include <sys/select.h>#include <curl/curl.h>#include <curl/easy.h>#include "curl.h"/* curl globals */static CURLM *curlm;static fd_set rd, wr, ex;/* my globals */static int url_debug   = 0;static int url_timeout = 30;/* my structs */struct iobuf {    off_t   start;    size_t  size;    char    *data;};struct url_state {    char           *path;    CURL           *curl;    char           errmsg[CURL_ERROR_SIZE];    off_t          curl_pos;    off_t          buf_pos;    struct iobuf   buf;    int            eof;};/* ---------------------------------------------------------------------- *//* curl stuff                                                             */static void __attribute__ ((constructor)) curl_init(void){    curl_global_init(CURL_GLOBAL_ALL);    curlm = curl_multi_init();}static void __attribute__ ((destructor)) curl_fini(void){    curl_multi_cleanup(curlm);    curl_global_cleanup();}static void curl_free_buffer(struct iobuf *buf){    if (buf->data) {	free(buf->data);	memset(buf,0,sizeof(*buf));    }}/* CURLOPT_WRITEFUNCTION */static int curl_write(void *data,  size_t  size, size_t nmemb, void *handle){    struct url_state *h = handle;    curl_free_buffer(&h->buf);    h->buf.start = h->curl_pos;    h->buf.size  = size * nmemb;    h->buf.data  = malloc(h->buf.size);    memcpy(h->buf.data, data, h->buf.size);    if (url_debug)	fprintf(stderr,"  put %5d @ %5d\n",		(int)h->buf.size, (int)h->buf.start);        h->curl_pos += h->buf.size;    return h->buf.size;}/* do transfers */static int curl_xfer(struct url_state *h){    CURLMcode rc;    struct timeval tv;    int count, maxfd;    FD_ZERO(&rd);    FD_ZERO(&wr);    FD_ZERO(&ex);    maxfd = -1;    rc = curl_multi_fdset(curlm, &rd, &wr, &ex, &maxfd);    if (CURLM_OK != rc) {	fprintf(stderr,"curl_multi_fdset: %d %s\n",rc,h->errmsg);	return -1;    }    if (-1 == maxfd) {	/* wait 0.1 sec */	if (url_debug)	    fprintf(stderr,"wait 0.01 sec\n");	tv.tv_sec  = 0;	tv.tv_usec = 100000;    } else {	/* wait for data */	if (url_debug)	    fprintf(stderr,"select for data [maxfd=%d]\n",maxfd);	tv.tv_sec  = url_timeout;	tv.tv_usec = 0;    }    switch (select(maxfd+1, &rd, &wr, &ex, &tv)) {    case -1:	/* Huh? */	perror("select");	exit(1);    case 0:	/* timeout */	return -1;    }    for (;;) {	rc = curl_multi_perform(curlm,&count);	if (CURLM_CALL_MULTI_PERFORM == rc)	    continue;	if (CURLM_OK != rc) {	    fprintf(stderr,"curl_multi_perform: %d %s\n",rc,h->errmsg);	    return -1;	}	if (0 == count)	    h->eof = 1;	break;    }    return 0;}/* curl setup */static int curl_setup(struct url_state *h){    if (h->curl) {	curl_multi_remove_handle(curlm,h->curl);	curl_easy_cleanup(h->curl);    }    h->curl = curl_easy_init();    curl_easy_setopt(h->curl, CURLOPT_URL,           h->path);    curl_easy_setopt(h->curl, CURLOPT_ERRORBUFFER,   h->errmsg);    curl_easy_setopt(h->curl, CURLOPT_WRITEFUNCTION, curl_write);    curl_easy_setopt(h->curl, CURLOPT_WRITEDATA,     h);    curl_multi_add_handle(curlm, h->curl);    h->buf_pos  = 0;    h->curl_pos = 0;    h->eof      = 0;    return 0;}/* ---------------------------------------------------------------------- *//* GNU glibc custom stream interface                                      */static ssize_t url_read(void *handle, char *buf, size_t size){    struct url_state *h = handle;    size_t bytes, total;    off_t off;    int count;        if (url_debug)	fprintf(stderr,"url_read(size=%d)\n",(int)size);    for (total = 0; size > 0;) {	if (h->buf.start                <= h->buf_pos &&	    h->buf.start + h->buf.size  >  h->buf_pos) {	    /* can satisfy from current buffer */	    bytes = h->buf.start + h->buf.size - h->buf_pos;	    off   = h->buf_pos - h->buf.start;	    if (bytes > size)		bytes = size;	    memcpy(buf+total, h->buf.data + off, bytes);	    if (url_debug)		fprintf(stderr,"  get %5d @ %5d [%5d]\n",			(int)bytes, (int)h->buf_pos, (int)off);	    size       -= bytes;	    total      += bytes;	    h->buf_pos += bytes;	    continue;	}	if (h->buf_pos < h->buf.start) {	    /* seeking backwards -- restart transfer */	    if (url_debug)		fprintf(stderr,"  rewind\n");	    curl_free_buffer(&h->buf);	    curl_setup(h);	    while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curlm,&count))		/* nothing */;	}	if (h->eof)	    /* stop on eof */	    break;	/* fetch more data */	if (-1 == curl_xfer(h)) {	    if (0 == total)		return -1;	    break;	}    }    return total;}#if 0static ssize_t url_write(void *handle, const char *buf, size_t size){    //struct url_state *h = handle;    if (url_debug)	fprintf(stderr,"url_write(size=%d)\n",(int)size);    return -1;}#endifstatic int url_seek(void *handle, off64_t *pos, int whence){    struct url_state *h = handle;    int rc = 0;    if (url_debug)	fprintf(stderr,"url_seek(pos=%d,whence=%d)\n", (int)(*pos), whence);    switch (whence) {    case SEEK_SET:	h->buf_pos = *pos;	break;    case SEEK_CUR:	h->buf_pos += *pos;	break;    case SEEK_END: 	rc = -1;    }    *pos = h->buf_pos;    return rc;}static int url_close(void *handle){    struct url_state *h = handle;    if (url_debug)	fprintf(stderr,"url_close()\n");    curl_multi_remove_handle(curlm,h->curl);    curl_easy_cleanup(h->curl);    if (h->buf.data)	free(h->buf.data);    free(h->path);    free(h);    return 0;}static cookie_io_functions_t url_hooks = {    .read  = url_read,#if 0    .write = url_write,#endif    .seek  = url_seek,    .close = url_close,};static FILE *url_open(const char *path, const char *mode){    FILE *fp;    struct url_state *h;    int count;    if (url_debug)	fprintf(stderr,"url_open(%s,%s)\n",path,mode);    h = malloc(sizeof(*h));    if (NULL == h)	goto err;    memset(h,0,sizeof(*h));    h->path = strdup(path);    if (NULL == h->path)	goto err;        /* setup */    curl_setup(h);    fp = fopencookie(h, mode, url_hooks);    if (NULL == fp)	goto err;    /* connect + start fetching */    while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curlm,&count))	/* nothing */;    /* check for errors */    if (0 == count  &&  NULL == h->buf.data) {	errno = ENOENT;	goto fetch_err;    }	    /* all done */    return fp; fetch_err:    curl_multi_remove_handle(curlm,h->curl); err:    if (h->curl)	curl_easy_cleanup(h->curl);    if (h->path)	free(h->path);    if (h)	free(h);    return NULL;}/* ---------------------------------------------------------------------- *//* hook into fopen using GNU ld's --wrap                                  */int curl_is_url(const char *url){    static char *protocols[] = {	"ftp://",	"http://",	NULL,    };    int i;    for (i = 0; protocols[i] != NULL; i++)	if (0 == strncasecmp(url, protocols[i], strlen(protocols[i])))	    return 1;    return 0;}FILE *__wrap_fopen(const char *path, const char *mode);FILE *__real_fopen(const char *path, const char *mode);FILE *__wrap_fopen(const char *path, const char *mode){    if (url_debug)	fprintf(stderr,"fopen(%s,%s)\n",path,mode);    /* catch URLs */    if (curl_is_url(path)) {	if (strchr(mode,'w')) {	    fprintf(stderr,"write access over ftp/http is not supported, sorry\n");	    return NULL;	}	return url_open(path,mode);    }        /* files passed to the real fopen */    return __real_fopen(path,mode);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -