~ubuntu-branches/ubuntu/oneiric/curl/oneiric-updates

« back to all changes in this revision

Viewing changes to docs/examples/fopen.c

  • Committer: Bazaar Package Importer
  • Author(s): Artur Rona
  • Date: 2011-01-26 02:50:18 UTC
  • mfrom: (3.4.13 sid)
  • Revision ID: james.westby@ubuntu.com-20110126025018-dzgm2m2t5d1vc9y4
Tags: 7.21.3-1ubuntu1
* Merge from debian unstable.  Remaining changes: (LP: #707756)
  - debian/control:
    + Build-Depends: Replace libssh2-1-dev with openssh-server.
      Drop stunnel since it's in universe, as well.
    + Drop libssh2-1-dev from libcurl4-openssl-dev's Depends.
    Above changes are necessary to be independent from the universe.

Show diffs side-by-side

added added

removed removed

Lines of Context:
53
53
 
54
54
#include <curl/curl.h>
55
55
 
56
 
enum fcurl_type_e { CFTYPE_NONE=0, CFTYPE_FILE=1, CFTYPE_CURL=2 };
 
56
enum fcurl_type_e {
 
57
  CFTYPE_NONE=0,
 
58
  CFTYPE_FILE=1,
 
59
  CFTYPE_CURL=2
 
60
};
57
61
 
58
62
struct fcurl_data
59
63
{
60
 
    enum fcurl_type_e type;     /* type of handle */
61
 
    union {
62
 
        CURL *curl;
63
 
        FILE *file;
64
 
    } handle;                   /* handle */
 
64
  enum fcurl_type_e type;     /* type of handle */
 
65
  union {
 
66
    CURL *curl;
 
67
    FILE *file;
 
68
  } handle;                   /* handle */
65
69
 
66
 
    char *buffer;               /* buffer to store cached data*/
67
 
    int buffer_len;             /* currently allocated buffers length */
68
 
    int buffer_pos;             /* end of data in buffer*/
69
 
    int still_running;          /* Is background url fetch still in progress */
 
70
  char *buffer;               /* buffer to store cached data*/
 
71
  int buffer_len;             /* currently allocated buffers length */
 
72
  int buffer_pos;             /* end of data in buffer*/
 
73
  int still_running;          /* Is background url fetch still in progress */
70
74
};
71
75
 
72
76
typedef struct fcurl_data URL_FILE;
83
87
CURLM *multi_handle;
84
88
 
85
89
/* curl calls this routine to get more data */
86
 
static size_t
87
 
write_callback(char *buffer,
88
 
               size_t size,
89
 
               size_t nitems,
90
 
               void *userp)
 
90
static size_t write_callback(char *buffer,
 
91
                             size_t size,
 
92
                             size_t nitems,
 
93
                             void *userp)
91
94
{
92
 
    char *newbuff;
93
 
    int rembuff;
94
 
 
95
 
    URL_FILE *url = (URL_FILE *)userp;
96
 
    size *= nitems;
97
 
 
98
 
    rembuff=url->buffer_len - url->buffer_pos; /* remaining space in buffer */
99
 
 
100
 
    if(size > rembuff)
101
 
    {
102
 
        /* not enough space in buffer */
103
 
        newbuff=realloc(url->buffer,url->buffer_len + (size - rembuff));
104
 
        if(newbuff==NULL)
105
 
        {
106
 
            fprintf(stderr,"callback buffer grow failed\n");
107
 
            size=rembuff;
108
 
        }
109
 
        else
110
 
        {
111
 
            /* realloc suceeded increase buffer size*/
112
 
            url->buffer_len+=size - rembuff;
113
 
            url->buffer=newbuff;
114
 
 
115
 
            /*printf("Callback buffer grown to %d bytes\n",url->buffer_len);*/
116
 
        }
117
 
    }
118
 
 
119
 
    memcpy(&url->buffer[url->buffer_pos], buffer, size);
120
 
    url->buffer_pos += size;
121
 
 
122
 
    /*fprintf(stderr, "callback %d size bytes\n", size);*/
123
 
 
124
 
    return size;
 
95
  char *newbuff;
 
96
  int rembuff;
 
97
 
 
98
  URL_FILE *url = (URL_FILE *)userp;
 
99
  size *= nitems;
 
100
 
 
101
  rembuff=url->buffer_len - url->buffer_pos; /* remaining space in buffer */
 
102
 
 
103
  if(size > rembuff) {
 
104
    /* not enough space in buffer */
 
105
    newbuff=realloc(url->buffer,url->buffer_len + (size - rembuff));
 
106
    if(newbuff==NULL) {
 
107
      fprintf(stderr,"callback buffer grow failed\n");
 
108
      size=rembuff;
 
109
    }
 
110
    else {
 
111
      /* realloc suceeded increase buffer size*/
 
112
      url->buffer_len+=size - rembuff;
 
113
      url->buffer=newbuff;
 
114
    }
 
115
  }
 
116
 
 
117
  memcpy(&url->buffer[url->buffer_pos], buffer, size);
 
118
  url->buffer_pos += size;
 
119
 
 
120
  return size;
125
121
}
126
122
 
127
123
/* use to attempt to fill the read buffer up to requested number of bytes */
128
 
static int
129
 
fill_buffer(URL_FILE *file,int want,int waittime)
 
124
static int fill_buffer(URL_FILE *file,int want,int waittime)
130
125
{
131
 
    fd_set fdread;
132
 
    fd_set fdwrite;
133
 
    fd_set fdexcep;
134
 
    struct timeval timeout;
135
 
    int rc;
136
 
 
137
 
    /* only attempt to fill buffer if transactions still running and buffer
138
 
     * doesnt exceed required size already
139
 
     */
140
 
    if((!file->still_running) || (file->buffer_pos > want))
141
 
        return 0;
142
 
 
143
 
    /* attempt to fill buffer */
144
 
    do
145
 
    {
146
 
        int maxfd = -1;
147
 
        long curl_timeo = -1;
148
 
 
149
 
        FD_ZERO(&fdread);
150
 
        FD_ZERO(&fdwrite);
151
 
        FD_ZERO(&fdexcep);
152
 
 
153
 
        /* set a suitable timeout to fail on */
154
 
        timeout.tv_sec = 60; /* 1 minute */
155
 
        timeout.tv_usec = 0;
156
 
 
157
 
        curl_multi_timeout(multi_handle, &curl_timeo);
158
 
        if(curl_timeo >= 0) {
159
 
          timeout.tv_sec = curl_timeo / 1000;
160
 
          if(timeout.tv_sec > 1)
161
 
            timeout.tv_sec = 1;
162
 
          else
163
 
            timeout.tv_usec = (curl_timeo % 1000) * 1000;
164
 
        }
165
 
 
166
 
        /* get file descriptors from the transfers */
167
 
        curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
168
 
 
169
 
        /* In a real-world program you OF COURSE check the return code of the
170
 
           function calls.  On success, the value of maxfd is guaranteed to be
171
 
           greater or equal than -1.  We call select(maxfd + 1, ...), specially
172
 
           in case of (maxfd == -1), we call select(0, ...), which is basically
173
 
           equal to sleep. */
174
 
 
175
 
        rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
176
 
 
177
 
        switch(rc) {
178
 
        case -1:
179
 
            /* select error */
180
 
            break;
181
 
 
182
 
        case 0:
183
 
            break;
184
 
 
185
 
        default:
186
 
            /* timeout or readable/writable sockets */
187
 
            curl_multi_perform(multi_handle, &file->still_running);
188
 
            break;
189
 
        }
190
 
    } while(file->still_running && (file->buffer_pos < want));
191
 
    return 1;
 
126
  fd_set fdread;
 
127
  fd_set fdwrite;
 
128
  fd_set fdexcep;
 
129
  struct timeval timeout;
 
130
  int rc;
 
131
 
 
132
  /* only attempt to fill buffer if transactions still running and buffer
 
133
   * doesnt exceed required size already
 
134
   */
 
135
  if((!file->still_running) || (file->buffer_pos > want))
 
136
    return 0;
 
137
 
 
138
  /* attempt to fill buffer */
 
139
  do {
 
140
    int maxfd = -1;
 
141
    long curl_timeo = -1;
 
142
 
 
143
    FD_ZERO(&fdread);
 
144
    FD_ZERO(&fdwrite);
 
145
    FD_ZERO(&fdexcep);
 
146
 
 
147
    /* set a suitable timeout to fail on */
 
148
    timeout.tv_sec = 60; /* 1 minute */
 
149
    timeout.tv_usec = 0;
 
150
 
 
151
    curl_multi_timeout(multi_handle, &curl_timeo);
 
152
    if(curl_timeo >= 0) {
 
153
      timeout.tv_sec = curl_timeo / 1000;
 
154
      if(timeout.tv_sec > 1)
 
155
        timeout.tv_sec = 1;
 
156
      else
 
157
        timeout.tv_usec = (curl_timeo % 1000) * 1000;
 
158
    }
 
159
 
 
160
    /* get file descriptors from the transfers */
 
161
    curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
 
162
 
 
163
    /* In a real-world program you OF COURSE check the return code of the
 
164
       function calls.  On success, the value of maxfd is guaranteed to be
 
165
       greater or equal than -1.  We call select(maxfd + 1, ...), specially
 
166
       in case of (maxfd == -1), we call select(0, ...), which is basically
 
167
       equal to sleep. */
 
168
 
 
169
    rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
 
170
 
 
171
    switch(rc) {
 
172
    case -1:
 
173
      /* select error */
 
174
      break;
 
175
 
 
176
    case 0:
 
177
    default:
 
178
      /* timeout or readable/writable sockets */
 
179
      curl_multi_perform(multi_handle, &file->still_running);
 
180
      break;
 
181
    }
 
182
  } while(file->still_running && (file->buffer_pos < want));
 
183
  return 1;
192
184
}
193
185
 
194
186
/* use to remove want bytes from the front of a files buffer */
195
 
static int
196
 
use_buffer(URL_FILE *file,int want)
197
 
{
198
 
    /* sort out buffer */
199
 
    if((file->buffer_pos - want) <=0)
200
 
    {
201
 
        /* ditch buffer - write will recreate */
202
 
        if(file->buffer)
203
 
            free(file->buffer);
204
 
 
205
 
        file->buffer=NULL;
206
 
        file->buffer_pos=0;
207
 
        file->buffer_len=0;
208
 
    }
209
 
    else
210
 
    {
211
 
        /* move rest down make it available for later */
212
 
        memmove(file->buffer,
213
 
                &file->buffer[want],
214
 
                (file->buffer_pos - want));
215
 
 
216
 
        file->buffer_pos -= want;
217
 
    }
218
 
    return 0;
219
 
}
220
 
 
221
 
 
222
 
 
223
 
URL_FILE *
224
 
url_fopen(const char *url,const char *operation)
225
 
{
226
 
    /* this code could check for URLs or types in the 'url' and
227
 
       basicly use the real fopen() for standard files */
228
 
 
229
 
    URL_FILE *file;
230
 
    (void)operation;
231
 
 
232
 
    file = malloc(sizeof(URL_FILE));
233
 
    if(!file)
234
 
        return NULL;
235
 
 
236
 
    memset(file, 0, sizeof(URL_FILE));
237
 
 
238
 
    if((file->handle.file=fopen(url,operation)))
239
 
    {
240
 
        file->type = CFTYPE_FILE; /* marked as URL */
241
 
    }
242
 
    else
243
 
    {
244
 
        file->type = CFTYPE_CURL; /* marked as URL */
245
 
        file->handle.curl = curl_easy_init();
246
 
 
247
 
        curl_easy_setopt(file->handle.curl, CURLOPT_URL, url);
248
 
        curl_easy_setopt(file->handle.curl, CURLOPT_WRITEDATA, file);
249
 
        curl_easy_setopt(file->handle.curl, CURLOPT_VERBOSE, 0L);
250
 
        curl_easy_setopt(file->handle.curl, CURLOPT_WRITEFUNCTION, write_callback);
251
 
 
252
 
        if(!multi_handle)
253
 
            multi_handle = curl_multi_init();
254
 
 
255
 
        curl_multi_add_handle(multi_handle, file->handle.curl);
256
 
 
257
 
        /* lets start the fetch */
258
 
        curl_multi_perform(multi_handle, &file->still_running);
259
 
 
260
 
        if((file->buffer_pos == 0) && (!file->still_running))
261
 
        {
262
 
            /* if still_running is 0 now, we should return NULL */
263
 
 
264
 
            /* make sure the easy handle is not in the multi handle anymore */
265
 
            curl_multi_remove_handle(multi_handle, file->handle.curl);
266
 
 
267
 
            /* cleanup */
268
 
            curl_easy_cleanup(file->handle.curl);
269
 
 
270
 
            free(file);
271
 
 
272
 
            file = NULL;
273
 
        }
274
 
    }
275
 
    return file;
276
 
}
277
 
 
278
 
int
279
 
url_fclose(URL_FILE *file)
280
 
{
281
 
    int ret=0;/* default is good return */
282
 
 
283
 
    switch(file->type)
284
 
    {
285
 
    case CFTYPE_FILE:
286
 
        ret=fclose(file->handle.file); /* passthrough */
287
 
        break;
288
 
 
289
 
    case CFTYPE_CURL:
290
 
        /* make sure the easy handle is not in the multi handle anymore */
291
 
        curl_multi_remove_handle(multi_handle, file->handle.curl);
292
 
 
293
 
        /* cleanup */
294
 
        curl_easy_cleanup(file->handle.curl);
295
 
        break;
296
 
 
297
 
    default: /* unknown or supported type - oh dear */
298
 
        ret=EOF;
299
 
        errno=EBADF;
300
 
        break;
301
 
 
302
 
    }
303
 
 
304
 
    if(file->buffer)
305
 
        free(file->buffer);/* free any allocated buffer space */
306
 
 
307
 
    free(file);
308
 
 
309
 
    return ret;
310
 
}
311
 
 
312
 
int
313
 
url_feof(URL_FILE *file)
314
 
{
315
 
    int ret=0;
316
 
 
317
 
    switch(file->type)
318
 
    {
319
 
    case CFTYPE_FILE:
320
 
        ret=feof(file->handle.file);
321
 
        break;
322
 
 
323
 
    case CFTYPE_CURL:
324
 
        if((file->buffer_pos == 0) && (!file->still_running))
325
 
            ret = 1;
326
 
        break;
327
 
    default: /* unknown or supported type - oh dear */
328
 
        ret=-1;
329
 
        errno=EBADF;
330
 
        break;
331
 
    }
332
 
    return ret;
333
 
}
334
 
 
335
 
size_t
336
 
url_fread(void *ptr, size_t size, size_t nmemb, URL_FILE *file)
337
 
{
338
 
    size_t want;
339
 
 
340
 
    switch(file->type)
341
 
    {
342
 
    case CFTYPE_FILE:
343
 
        want=fread(ptr,size,nmemb,file->handle.file);
344
 
        break;
345
 
 
346
 
    case CFTYPE_CURL:
347
 
        want = nmemb * size;
348
 
 
349
 
        fill_buffer(file,want,1);
350
 
 
351
 
        /* check if theres data in the buffer - if not fill_buffer()
352
 
         * either errored or EOF */
353
 
        if(!file->buffer_pos)
354
 
            return 0;
355
 
 
356
 
        /* ensure only available data is considered */
357
 
        if(file->buffer_pos < want)
358
 
            want = file->buffer_pos;
359
 
 
360
 
        /* xfer data to caller */
361
 
        memcpy(ptr, file->buffer, want);
362
 
 
363
 
        use_buffer(file,want);
364
 
 
365
 
        want = want / size;     /* number of items - nb correct op - checked
366
 
                                 * with glibc code*/
367
 
 
368
 
        /*printf("(fread) return %d bytes %d left\n", want,file->buffer_pos);*/
369
 
        break;
370
 
 
371
 
    default: /* unknown or supported type - oh dear */
372
 
        want=0;
373
 
        errno=EBADF;
374
 
        break;
375
 
 
376
 
    }
377
 
    return want;
378
 
}
379
 
 
380
 
char *
381
 
url_fgets(char *ptr, int size, URL_FILE *file)
382
 
{
383
 
    int want = size - 1;/* always need to leave room for zero termination */
384
 
    int loop;
385
 
 
386
 
    switch(file->type)
387
 
    {
388
 
    case CFTYPE_FILE:
389
 
        ptr = fgets(ptr,size,file->handle.file);
390
 
        break;
391
 
 
392
 
    case CFTYPE_CURL:
393
 
        fill_buffer(file,want,1);
394
 
 
395
 
        /* check if theres data in the buffer - if not fill either errored or
396
 
         * EOF */
397
 
        if(!file->buffer_pos)
398
 
            return NULL;
399
 
 
400
 
        /* ensure only available data is considered */
401
 
        if(file->buffer_pos < want)
402
 
            want = file->buffer_pos;
403
 
 
404
 
        /*buffer contains data */
405
 
        /* look for newline or eof */
406
 
        for(loop=0;loop < want;loop++)
407
 
        {
408
 
            if(file->buffer[loop] == '\n')
409
 
            {
410
 
                want=loop+1;/* include newline */
411
 
                break;
412
 
            }
413
 
        }
414
 
 
415
 
        /* xfer data to caller */
416
 
        memcpy(ptr, file->buffer, want);
417
 
        ptr[want]=0;/* allways null terminate */
418
 
 
419
 
        use_buffer(file,want);
420
 
 
421
 
        /*printf("(fgets) return %d bytes %d left\n", want,file->buffer_pos);*/
422
 
        break;
423
 
 
424
 
    default: /* unknown or supported type - oh dear */
425
 
        ptr=NULL;
426
 
        errno=EBADF;
427
 
        break;
428
 
    }
429
 
 
430
 
    return ptr;/*success */
431
 
}
432
 
 
433
 
void
434
 
url_rewind(URL_FILE *file)
435
 
{
436
 
    switch(file->type)
437
 
    {
438
 
    case CFTYPE_FILE:
439
 
        rewind(file->handle.file); /* passthrough */
440
 
        break;
441
 
 
442
 
    case CFTYPE_CURL:
443
 
        /* halt transaction */
444
 
        curl_multi_remove_handle(multi_handle, file->handle.curl);
445
 
 
446
 
        /* restart */
447
 
        curl_multi_add_handle(multi_handle, file->handle.curl);
448
 
 
449
 
        /* ditch buffer - write will recreate - resets stream pos*/
450
 
        if(file->buffer)
451
 
            free(file->buffer);
452
 
 
453
 
        file->buffer=NULL;
454
 
        file->buffer_pos=0;
455
 
        file->buffer_len=0;
456
 
 
457
 
        break;
458
 
 
459
 
    default: /* unknown or supported type - oh dear */
460
 
        break;
461
 
 
462
 
    }
463
 
 
464
 
}
465
 
 
 
187
static int use_buffer(URL_FILE *file,int want)
 
188
{
 
189
  /* sort out buffer */
 
190
  if((file->buffer_pos - want) <=0) {
 
191
    /* ditch buffer - write will recreate */
 
192
    if(file->buffer)
 
193
      free(file->buffer);
 
194
 
 
195
    file->buffer=NULL;
 
196
    file->buffer_pos=0;
 
197
    file->buffer_len=0;
 
198
  }
 
199
  else {
 
200
    /* move rest down make it available for later */
 
201
    memmove(file->buffer,
 
202
            &file->buffer[want],
 
203
            (file->buffer_pos - want));
 
204
 
 
205
    file->buffer_pos -= want;
 
206
  }
 
207
  return 0;
 
208
}
 
209
 
 
210
URL_FILE *url_fopen(const char *url,const char *operation)
 
211
{
 
212
  /* this code could check for URLs or types in the 'url' and
 
213
     basicly use the real fopen() for standard files */
 
214
 
 
215
  URL_FILE *file;
 
216
  (void)operation;
 
217
 
 
218
  file = malloc(sizeof(URL_FILE));
 
219
  if(!file)
 
220
    return NULL;
 
221
 
 
222
  memset(file, 0, sizeof(URL_FILE));
 
223
 
 
224
  if((file->handle.file=fopen(url,operation)))
 
225
    file->type = CFTYPE_FILE; /* marked as URL */
 
226
 
 
227
  else {
 
228
    file->type = CFTYPE_CURL; /* marked as URL */
 
229
    file->handle.curl = curl_easy_init();
 
230
 
 
231
    curl_easy_setopt(file->handle.curl, CURLOPT_URL, url);
 
232
    curl_easy_setopt(file->handle.curl, CURLOPT_WRITEDATA, file);
 
233
    curl_easy_setopt(file->handle.curl, CURLOPT_VERBOSE, 0L);
 
234
    curl_easy_setopt(file->handle.curl, CURLOPT_WRITEFUNCTION, write_callback);
 
235
 
 
236
    if(!multi_handle)
 
237
      multi_handle = curl_multi_init();
 
238
 
 
239
    curl_multi_add_handle(multi_handle, file->handle.curl);
 
240
 
 
241
    /* lets start the fetch */
 
242
    curl_multi_perform(multi_handle, &file->still_running);
 
243
 
 
244
    if((file->buffer_pos == 0) && (!file->still_running)) {
 
245
      /* if still_running is 0 now, we should return NULL */
 
246
 
 
247
      /* make sure the easy handle is not in the multi handle anymore */
 
248
      curl_multi_remove_handle(multi_handle, file->handle.curl);
 
249
 
 
250
      /* cleanup */
 
251
      curl_easy_cleanup(file->handle.curl);
 
252
 
 
253
      free(file);
 
254
 
 
255
      file = NULL;
 
256
    }
 
257
  }
 
258
  return file;
 
259
}
 
260
 
 
261
int url_fclose(URL_FILE *file)
 
262
{
 
263
  int ret=0;/* default is good return */
 
264
 
 
265
  switch(file->type) {
 
266
  case CFTYPE_FILE:
 
267
    ret=fclose(file->handle.file); /* passthrough */
 
268
    break;
 
269
 
 
270
  case CFTYPE_CURL:
 
271
    /* make sure the easy handle is not in the multi handle anymore */
 
272
    curl_multi_remove_handle(multi_handle, file->handle.curl);
 
273
 
 
274
    /* cleanup */
 
275
    curl_easy_cleanup(file->handle.curl);
 
276
    break;
 
277
 
 
278
  default: /* unknown or supported type - oh dear */
 
279
    ret=EOF;
 
280
    errno=EBADF;
 
281
    break;
 
282
  }
 
283
 
 
284
  if(file->buffer)
 
285
    free(file->buffer);/* free any allocated buffer space */
 
286
 
 
287
  free(file);
 
288
 
 
289
  return ret;
 
290
}
 
291
 
 
292
int url_feof(URL_FILE *file)
 
293
{
 
294
  int ret=0;
 
295
 
 
296
  switch(file->type) {
 
297
  case CFTYPE_FILE:
 
298
    ret=feof(file->handle.file);
 
299
    break;
 
300
 
 
301
  case CFTYPE_CURL:
 
302
    if((file->buffer_pos == 0) && (!file->still_running))
 
303
      ret = 1;
 
304
    break;
 
305
 
 
306
  default: /* unknown or supported type - oh dear */
 
307
    ret=-1;
 
308
    errno=EBADF;
 
309
    break;
 
310
  }
 
311
  return ret;
 
312
}
 
313
 
 
314
size_t url_fread(void *ptr, size_t size, size_t nmemb, URL_FILE *file)
 
315
{
 
316
  size_t want;
 
317
 
 
318
  switch(file->type) {
 
319
  case CFTYPE_FILE:
 
320
    want=fread(ptr,size,nmemb,file->handle.file);
 
321
    break;
 
322
 
 
323
  case CFTYPE_CURL:
 
324
    want = nmemb * size;
 
325
 
 
326
    fill_buffer(file,want,1);
 
327
 
 
328
    /* check if theres data in the buffer - if not fill_buffer()
 
329
     * either errored or EOF */
 
330
    if(!file->buffer_pos)
 
331
      return 0;
 
332
 
 
333
    /* ensure only available data is considered */
 
334
    if(file->buffer_pos < want)
 
335
      want = file->buffer_pos;
 
336
 
 
337
    /* xfer data to caller */
 
338
    memcpy(ptr, file->buffer, want);
 
339
 
 
340
    use_buffer(file,want);
 
341
 
 
342
    want = want / size;     /* number of items */
 
343
    break;
 
344
 
 
345
  default: /* unknown or supported type - oh dear */
 
346
    want=0;
 
347
    errno=EBADF;
 
348
    break;
 
349
 
 
350
  }
 
351
  return want;
 
352
}
 
353
 
 
354
char *url_fgets(char *ptr, int size, URL_FILE *file)
 
355
{
 
356
  int want = size - 1;/* always need to leave room for zero termination */
 
357
  int loop;
 
358
 
 
359
  switch(file->type) {
 
360
  case CFTYPE_FILE:
 
361
    ptr = fgets(ptr,size,file->handle.file);
 
362
    break;
 
363
 
 
364
  case CFTYPE_CURL:
 
365
    fill_buffer(file,want,1);
 
366
 
 
367
    /* check if theres data in the buffer - if not fill either errored or
 
368
     * EOF */
 
369
    if(!file->buffer_pos)
 
370
      return NULL;
 
371
 
 
372
    /* ensure only available data is considered */
 
373
    if(file->buffer_pos < want)
 
374
      want = file->buffer_pos;
 
375
 
 
376
    /*buffer contains data */
 
377
    /* look for newline or eof */
 
378
    for(loop=0;loop < want;loop++) {
 
379
      if(file->buffer[loop] == '\n') {
 
380
        want=loop+1;/* include newline */
 
381
        break;
 
382
      }
 
383
    }
 
384
 
 
385
    /* xfer data to caller */
 
386
    memcpy(ptr, file->buffer, want);
 
387
    ptr[want]=0;/* allways null terminate */
 
388
 
 
389
    use_buffer(file,want);
 
390
 
 
391
    break;
 
392
 
 
393
  default: /* unknown or supported type - oh dear */
 
394
    ptr=NULL;
 
395
    errno=EBADF;
 
396
    break;
 
397
  }
 
398
 
 
399
  return ptr;/*success */
 
400
}
 
401
 
 
402
void url_rewind(URL_FILE *file)
 
403
{
 
404
  switch(file->type) {
 
405
  case CFTYPE_FILE:
 
406
    rewind(file->handle.file); /* passthrough */
 
407
    break;
 
408
 
 
409
  case CFTYPE_CURL:
 
410
    /* halt transaction */
 
411
    curl_multi_remove_handle(multi_handle, file->handle.curl);
 
412
 
 
413
    /* restart */
 
414
    curl_multi_add_handle(multi_handle, file->handle.curl);
 
415
 
 
416
    /* ditch buffer - write will recreate - resets stream pos*/
 
417
    if(file->buffer)
 
418
      free(file->buffer);
 
419
 
 
420
    file->buffer=NULL;
 
421
    file->buffer_pos=0;
 
422
    file->buffer_len=0;
 
423
 
 
424
    break;
 
425
 
 
426
  default: /* unknown or supported type - oh dear */
 
427
    break;
 
428
  }
 
429
}
466
430
 
467
431
/* Small main program to retrive from a url using fgets and fread saving the
468
432
 * output to two test files (note the fgets method will corrupt binary files if
469
433
 * they contain 0 chars */
470
 
int
471
 
main(int argc, char *argv[])
 
434
int main(int argc, char *argv[])
472
435
{
473
 
    URL_FILE *handle;
474
 
    FILE *outf;
475
 
 
476
 
    int nread;
477
 
    char buffer[256];
478
 
    const char *url;
479
 
 
480
 
    if(argc < 2)
481
 
    {
482
 
        url="http://192.168.7.3/testfile";/* default to testurl */
483
 
    }
484
 
    else
485
 
    {
486
 
        url=argv[1];/* use passed url */
487
 
    }
488
 
 
489
 
    /* copy from url line by line with fgets */
490
 
    outf=fopen("fgets.test","w+");
491
 
    if(!outf)
492
 
    {
493
 
        perror("couldn't open fgets output file\n");
494
 
        return 1;
495
 
    }
496
 
 
497
 
    handle = url_fopen(url, "r");
498
 
    if(!handle)
499
 
    {
500
 
        printf("couldn't url_fopen() %s\n", url);
501
 
        fclose(outf);
502
 
        return 2;
503
 
    }
504
 
 
505
 
    while(!url_feof(handle))
506
 
    {
507
 
        url_fgets(buffer,sizeof(buffer),handle);
508
 
        fwrite(buffer,1,strlen(buffer),outf);
509
 
    }
510
 
 
511
 
    url_fclose(handle);
512
 
 
513
 
    fclose(outf);
514
 
 
515
 
 
516
 
    /* Copy from url with fread */
517
 
    outf=fopen("fread.test","w+");
518
 
    if(!outf)
519
 
    {
520
 
        perror("couldn't open fread output file\n");
521
 
        return 1;
522
 
    }
523
 
 
524
 
    handle = url_fopen("testfile", "r");
525
 
    if(!handle) {
526
 
        printf("couldn't url_fopen() testfile\n");
527
 
        fclose(outf);
528
 
        return 2;
529
 
    }
530
 
 
531
 
    do {
532
 
        nread = url_fread(buffer, 1,sizeof(buffer), handle);
533
 
        fwrite(buffer,1,nread,outf);
534
 
    } while(nread);
535
 
 
536
 
    url_fclose(handle);
537
 
 
538
 
    fclose(outf);
539
 
 
540
 
 
541
 
    /* Test rewind */
542
 
    outf=fopen("rewind.test","w+");
543
 
    if(!outf)
544
 
    {
545
 
        perror("couldn't open fread output file\n");
546
 
        return 1;
547
 
    }
548
 
 
549
 
    handle = url_fopen("testfile", "r");
550
 
    if(!handle) {
551
 
        printf("couldn't url_fopen() testfile\n");
552
 
        fclose(outf);
553
 
        return 2;
554
 
    }
555
 
 
556
 
        nread = url_fread(buffer, 1,sizeof(buffer), handle);
557
 
        fwrite(buffer,1,nread,outf);
558
 
        url_rewind(handle);
559
 
 
560
 
        buffer[0]='\n';
561
 
        fwrite(buffer,1,1,outf);
562
 
 
563
 
        nread = url_fread(buffer, 1,sizeof(buffer), handle);
564
 
        fwrite(buffer,1,nread,outf);
565
 
 
566
 
 
567
 
    url_fclose(handle);
568
 
 
569
 
    fclose(outf);
570
 
 
571
 
 
572
 
    return 0;/* all done */
 
436
  URL_FILE *handle;
 
437
  FILE *outf;
 
438
 
 
439
  int nread;
 
440
  char buffer[256];
 
441
  const char *url;
 
442
 
 
443
  if(argc < 2)
 
444
    url="http://192.168.7.3/testfile";/* default to testurl */
 
445
  else
 
446
    url=argv[1];/* use passed url */
 
447
 
 
448
  /* copy from url line by line with fgets */
 
449
  outf=fopen("fgets.test","w+");
 
450
  if(!outf) {
 
451
    perror("couldn't open fgets output file\n");
 
452
    return 1;
 
453
  }
 
454
 
 
455
  handle = url_fopen(url, "r");
 
456
  if(!handle) {
 
457
    printf("couldn't url_fopen() %s\n", url);
 
458
    fclose(outf);
 
459
    return 2;
 
460
  }
 
461
 
 
462
  while(!url_feof(handle)) {
 
463
    url_fgets(buffer,sizeof(buffer),handle);
 
464
    fwrite(buffer,1,strlen(buffer),outf);
 
465
  }
 
466
 
 
467
  url_fclose(handle);
 
468
 
 
469
  fclose(outf);
 
470
 
 
471
 
 
472
  /* Copy from url with fread */
 
473
  outf=fopen("fread.test","w+");
 
474
  if(!outf) {
 
475
    perror("couldn't open fread output file\n");
 
476
    return 1;
 
477
  }
 
478
 
 
479
  handle = url_fopen("testfile", "r");
 
480
  if(!handle) {
 
481
    printf("couldn't url_fopen() testfile\n");
 
482
    fclose(outf);
 
483
    return 2;
 
484
  }
 
485
 
 
486
  do {
 
487
    nread = url_fread(buffer, 1,sizeof(buffer), handle);
 
488
    fwrite(buffer,1,nread,outf);
 
489
  } while(nread);
 
490
 
 
491
  url_fclose(handle);
 
492
 
 
493
  fclose(outf);
 
494
 
 
495
 
 
496
  /* Test rewind */
 
497
  outf=fopen("rewind.test","w+");
 
498
  if(!outf) {
 
499
    perror("couldn't open fread output file\n");
 
500
    return 1;
 
501
  }
 
502
 
 
503
  handle = url_fopen("testfile", "r");
 
504
  if(!handle) {
 
505
    printf("couldn't url_fopen() testfile\n");
 
506
    fclose(outf);
 
507
    return 2;
 
508
  }
 
509
 
 
510
  nread = url_fread(buffer, 1,sizeof(buffer), handle);
 
511
  fwrite(buffer,1,nread,outf);
 
512
  url_rewind(handle);
 
513
 
 
514
  buffer[0]='\n';
 
515
  fwrite(buffer,1,1,outf);
 
516
 
 
517
  nread = url_fread(buffer, 1,sizeof(buffer), handle);
 
518
  fwrite(buffer,1,nread,outf);
 
519
 
 
520
 
 
521
  url_fclose(handle);
 
522
 
 
523
  fclose(outf);
 
524
 
 
525
 
 
526
  return 0;/* all done */
573
527
}