~ubuntu-branches/ubuntu/raring/reprepro/raring

« back to all changes in this revision

Viewing changes to aptmethod.c

  • Committer: Bazaar Package Importer
  • Author(s): Bernhard R. Link
  • Date: 2011-05-05 16:34:23 UTC
  • mfrom: (21.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20110505163423-x49kbdijyoubai4x
Tags: 4.6.0-1
* new release
- general cleanup
- new FilterSrcList
* increase Standards-Version, no changes needed

Show diffs side-by-side

added added

removed removed

Lines of Context:
61
61
        char *baseuri;
62
62
        /*@null@*/char *fallbackbaseuri;
63
63
        /*@null@*/char *config;
64
 
        int mstdin,mstdout;
 
64
        int mstdin, mstdout;
65
65
        pid_t child;
66
66
 
67
 
        enum { ams_notstarted=0, ams_waitforcapabilities, ams_ok, ams_failed } status;
 
67
        enum {
 
68
                ams_notstarted=0,
 
69
                ams_waitforcapabilities,
 
70
                ams_ok,
 
71
                ams_failed
 
72
        } status;
68
73
 
69
74
        /*@null@*/struct tobedone *tobedone;
70
75
        /*@null@*//*@dependent@*/struct tobedone *lasttobedone;
71
76
        /*@null@*//*@dependent@*/const struct tobedone *nexttosend;
72
77
        /* what is currently read: */
73
78
        /*@null@*/char *inputbuffer;
74
 
        size_t input_size,alreadyread;
 
79
        size_t input_size, alreadyread;
75
80
        /* What is currently written: */
76
81
        /*@null@*/char *command;
77
 
        size_t alreadywritten,output_length;
 
82
        size_t alreadywritten, output_length;
78
83
};
79
84
 
80
85
struct aptmethodrun {
89
94
 
90
95
static void free_todolist(/*@only@*/ struct tobedone *todo) {
91
96
 
92
 
        while( todo != NULL ) {
 
97
        while (todo != NULL) {
93
98
                struct tobedone *h = todo->next;
94
99
 
95
100
                todo_free(todo);
98
103
}
99
104
 
100
105
static void aptmethod_free(/*@only@*/struct aptmethod *method) {
101
 
        if( method == NULL )
 
106
        if (method == NULL)
102
107
                return;
103
108
        free(method->name);
104
109
        free(method->baseuri);
114
119
 
115
120
retvalue aptmethod_shutdown(struct aptmethodrun *run) {
116
121
        retvalue result = RET_OK, r;
117
 
        struct aptmethod *method,*lastmethod,**method_ptr;
 
122
        struct aptmethod *method, *lastmethod, **method_ptr;
118
123
 
119
124
        /* first get rid of everything not running: */
120
125
        method_ptr = &run->methods;
121
 
        while( *method_ptr != NULL ) {
 
126
        while (*method_ptr != NULL) {
122
127
 
123
 
                if( (*method_ptr)->child > 0 ) {
124
 
                        if( verbose > 10 )
125
 
                                fprintf(stderr,"Still waiting for %d\n",(int)(*method_ptr)->child);
 
128
                if ((*method_ptr)->child > 0) {
 
129
                        if (verbose > 10)
 
130
                                fprintf(stderr,
 
131
"Still waiting for %d\n", (int)(*method_ptr)->child);
126
132
                        method_ptr = &(*method_ptr)->next;
127
133
                        continue;
128
134
                } else {
135
141
        }
136
142
 
137
143
        /* finally get rid of all the processes: */
138
 
        for( method = run->methods ; method != NULL ; method = method->next ) {
139
 
                if( method->mstdin >= 0 ) {
 
144
        for (method = run->methods ; method != NULL ; method = method->next) {
 
145
                if (method->mstdin >= 0) {
140
146
                        (void)close(method->mstdin);
141
 
                        if( verbose > 30 )
 
147
                        if (verbose > 30)
142
148
                                fprintf(stderr, "Closing stdin of %d\n",
143
149
                                                (int)method->child);
144
150
                }
145
151
                method->mstdin = -1;
146
 
                if( method->mstdout >= 0 ) {
 
152
                if (method->mstdout >= 0) {
147
153
                        (void)close(method->mstdout);
148
 
                        if( verbose > 30 )
 
154
                        if (verbose > 30)
149
155
                                fprintf(stderr, "Closing stdout of %d\n",
150
156
                                                (int)method->child);
151
157
                }
152
158
                method->mstdout = -1;
153
159
        }
154
 
        while( run->methods != NULL || uncompress_running() ) {
 
160
        while (run->methods != NULL || uncompress_running()) {
155
161
                pid_t pid;int status;
156
162
 
157
163
                pid = wait(&status);
158
164
                lastmethod = NULL; method = run->methods;
159
 
                while( method != NULL ) {
160
 
                        if( method->child == pid ) {
 
165
                while (method != NULL) {
 
166
                        if (method->child == pid) {
161
167
                                struct aptmethod *next = method->next;
162
168
 
163
 
                                if( lastmethod != NULL ) {
 
169
                                if (lastmethod != NULL) {
164
170
                                        lastmethod->next = next;
165
171
                                } else
166
172
                                        run->methods = next;
173
179
                                method = method->next;
174
180
                        }
175
181
                }
176
 
                if( pid > 0 ) {
 
182
                if (pid > 0) {
177
183
                        r = uncompress_checkpid(pid, status);
178
184
                        RET_UPDATE(result, r);
179
185
                }
187
193
retvalue aptmethod_initialize_run(struct aptmethodrun **run) {
188
194
        struct aptmethodrun *r;
189
195
 
190
 
        r = calloc(1,sizeof(struct aptmethodrun));
191
 
        if( r == NULL )
 
196
        r = zNEW(struct aptmethodrun);
 
197
        if (FAILEDTOALLOC(r))
192
198
                return RET_ERROR_OOM;
193
 
        else {
194
 
                *run = r;
195
 
                return RET_OK;
196
 
        }
 
199
        *run = r;
 
200
        return RET_OK;
197
201
}
198
202
 
199
203
retvalue aptmethod_newmethod(struct aptmethodrun *run, const char *uri, const char *fallbackuri, const struct strlist *config, struct aptmethod **m) {
200
204
        struct aptmethod *method;
201
205
        const char *p;
202
206
 
203
 
        method = calloc(1,sizeof(struct aptmethod));
204
 
        if( method == NULL )
 
207
        method = zNEW(struct aptmethod);
 
208
        if (FAILEDTOALLOC(method))
205
209
                return RET_ERROR_OOM;
206
210
        method->mstdin = -1;
207
211
        method->mstdout = -1;
208
212
        method->child = -1;
209
213
        method->status = ams_notstarted;
210
214
        p = uri;
211
 
        while( *p != '\0' && ( *p == '_' || *p == '-' ||
 
215
        while (*p != '\0' && (*p == '_' || *p == '-' ||
212
216
                (*p>='a' && *p<='z') || (*p>='A' && *p<='Z') ||
213
 
                (*p>='0' && *p<='9') ) ) {
 
217
                (*p>='0' && *p<='9'))) {
214
218
                p++;
215
219
        }
216
 
        if( *p == '\0' ) {
 
220
        if (*p == '\0') {
217
221
                fprintf(stderr, "No colon found in method-URI '%s'!\n", uri);
218
222
                free(method);
219
223
                return RET_ERROR;
220
224
        }
221
 
        if( *p != ':' ) {
222
 
                fprintf(stderr,"Unexpected character '%c' in method-URI '%s'!\n",*p,uri);
 
225
        if (*p != ':') {
 
226
                fprintf(stderr,
 
227
"Unexpected character '%c' in method-URI '%s'!\n", *p, uri);
223
228
                free(method);
224
229
                return RET_ERROR;
225
230
        }
226
 
        if( p == uri ) {
227
 
                fprintf(stderr,"Zero-length name in method-URI '%s'!\n",uri);
 
231
        if (p == uri) {
 
232
                fprintf(stderr,
 
233
"Zero-length name in method-URI '%s'!\n", uri);
228
234
                free(method);
229
235
                return RET_ERROR;
230
236
        }
231
237
 
232
 
        method->name = strndup(uri,p-uri);
233
 
        if( method->name == NULL ) {
 
238
        method->name = strndup(uri, p-uri);
 
239
        if (FAILEDTOALLOC(method->name)) {
234
240
                free(method);
235
241
                return RET_ERROR_OOM;
236
242
        }
237
243
        method->baseuri = strdup(uri);
238
 
        if( method->baseuri == NULL ) {
 
244
        if (FAILEDTOALLOC(method->baseuri)) {
239
245
                free(method->name);
240
246
                free(method);
241
247
                return RET_ERROR_OOM;
242
248
        }
243
 
        if( fallbackuri == NULL )
 
249
        if (fallbackuri == NULL)
244
250
                method->fallbackbaseuri = NULL;
245
251
        else {
246
252
                method->fallbackbaseuri = strdup(fallbackuri);
247
 
                if( method->fallbackbaseuri == NULL ) {
 
253
                if (FAILEDTOALLOC(method->fallbackbaseuri)) {
248
254
                        free(method->baseuri);
249
255
                        free(method->name);
250
256
                        free(method);
253
259
        }
254
260
#define CONF601 "601 Configuration"
255
261
#define CONFITEM "\nConfig-Item: "
256
 
        if( config->count == 0 )
 
262
        if (config->count == 0)
257
263
                method->config = strdup(CONF601 CONFITEM "Dir=/" "\n\n");
258
264
        else
259
265
                method->config = strlist_concat(config,
260
266
                                CONF601 CONFITEM, CONFITEM, "\n\n");
261
 
        if( method->config == NULL ) {
 
267
        if (FAILEDTOALLOC(method->config)) {
262
268
                free(method->fallbackbaseuri);
263
269
                free(method->baseuri);
264
270
                free(method->name);
281
287
 
282
288
        /* When there is nothing to get, there is no reason to startup
283
289
         * the method. */
284
 
        if( method->tobedone == NULL ) {
 
290
        if (method->tobedone == NULL) {
285
291
                return RET_NOTHING;
286
292
        }
287
293
 
288
294
        /* when we are already running, we are already ready...*/
289
 
        if( method->child > 0 ) {
 
295
        if (method->child > 0) {
290
296
                return RET_OK;
291
297
        }
292
298
 
293
299
        method->status = ams_waitforcapabilities;
294
300
 
295
301
        r = pipe(mstdin);
296
 
        if( r < 0 ) {
 
302
        if (r < 0) {
297
303
                int e = errno;
298
304
                fprintf(stderr, "Error %d creating pipe: %s\n",
299
305
                                e, strerror(e));
300
306
                return RET_ERRNO(e);
301
307
        }
302
308
        r = pipe(mstdout);
303
 
        if( r < 0 ) {
 
309
        if (r < 0) {
304
310
                int e = errno;
305
311
                (void)close(mstdin[0]); (void)close(mstdin[1]);
306
312
                fprintf(stderr, "Error %d in pipe syscall: %s\n",
308
314
                return RET_ERRNO(e);
309
315
        }
310
316
 
311
 
        if( interrupted() ) {
 
317
        if (interrupted()) {
312
318
                (void)close(mstdin[0]);(void)close(mstdin[1]);
313
319
                (void)close(mstdout[0]);(void)close(mstdout[1]);
314
320
                return RET_ERROR_INTERRUPTED;
315
321
        }
316
322
        f = fork();
317
 
        if( f < 0 ) {
 
323
        if (f < 0) {
318
324
                int e = errno;
319
325
                (void)close(mstdin[0]); (void)close(mstdin[1]);
320
326
                (void)close(mstdout[0]); (void)close(mstdout[1]);
322
328
                                e, strerror(e));
323
329
                return RET_ERRNO(e);
324
330
        }
325
 
        if( f == 0 ) {
 
331
        if (f == 0) {
326
332
                char *methodname;
327
333
                int e;
328
334
                /* child: */
329
335
                (void)close(mstdin[1]);
330
336
                (void)close(mstdout[0]);
331
 
                if( dup2(mstdin[0],0) < 0 ) {
 
337
                if (dup2(mstdin[0], 0) < 0) {
332
338
                        e = errno;
333
339
                        fprintf(stderr, "Error %d while setting stdin: %s\n",
334
340
                                        e, strerror(e));
335
341
                        exit(255);
336
342
                }
337
 
                if( dup2(mstdout[1],1) < 0 ) {
 
343
                if (dup2(mstdout[1], 1) < 0) {
338
344
                        e = errno;
339
345
                        fprintf(stderr, "Error %d while setting stdout: %s\n",
340
346
                                        e, strerror(e));
343
349
                closefrom(3);
344
350
 
345
351
                methodname = calc_dirconcat(global.methoddir, method->name);
346
 
                if( FAILEDTOALLOC(methodname) )
 
352
                if (FAILEDTOALLOC(methodname))
347
353
                        exit(255);
348
354
 
349
355
                /* not really useful here, unless someone write reprepro
362
368
        }
363
369
        /* the main program continues... */
364
370
        method->child = f;
365
 
        if( verbose > 10 )
366
 
                fprintf(stderr,"Method '%s' started as %d\n",method->baseuri,(int)f);
 
371
        if (verbose > 10)
 
372
                fprintf(stderr,
 
373
"Method '%s' started as %d\n", method->baseuri, (int)f);
367
374
        (void)close(mstdin[0]);
368
375
        (void)close(mstdout[1]);
369
376
        markcloseonexec(mstdin[1]);
383
390
 
384
391
static inline void enqueue(struct aptmethod *method, /*@only@*/struct tobedone *todo) {
385
392
        todo->next = NULL;
386
 
        if( method->lasttobedone == NULL )
 
393
        if (method->lasttobedone == NULL)
387
394
                method->nexttosend = method->lasttobedone = method->tobedone = todo;
388
395
        else {
389
396
                method->lasttobedone->next = todo;
390
397
                method->lasttobedone = todo;
391
 
                if( method->nexttosend == NULL )
 
398
                if (method->nexttosend == NULL)
392
399
                        method->nexttosend = todo;
393
400
        }
394
401
}
396
403
static retvalue enqueuenew(struct aptmethod *method, /*@only@*/char *uri, /*@only@*/char *destfile, queue_callback *callback, void *privdata1, void *privdata2) {
397
404
        struct tobedone *todo;
398
405
 
399
 
        if( FAILEDTOALLOC(destfile) ) {
 
406
        if (FAILEDTOALLOC(destfile)) {
400
407
                free(uri);
401
408
                return RET_ERROR_OOM;
402
409
        }
403
 
        if( FAILEDTOALLOC(uri) ) {
 
410
        if (FAILEDTOALLOC(uri)) {
404
411
                free(destfile);
405
412
                return RET_ERROR_OOM;
406
413
        }
407
414
 
408
 
        todo = malloc(sizeof(struct tobedone));
409
 
        if( FAILEDTOALLOC(todo) ) {
 
415
        todo = NEW(struct tobedone);
 
416
        if (FAILEDTOALLOC(todo)) {
410
417
                free(uri); free(destfile);
411
418
                return RET_ERROR_OOM;
412
419
        }
441
448
static retvalue requeue_or_fail(struct aptmethod *method, /*@only@*/struct tobedone *todo) {
442
449
        retvalue r;
443
450
 
444
 
        if( todo->lasttry ) {
445
 
                if( todo->callback == NULL )
 
451
        if (todo->lasttry) {
 
452
                if (todo->callback == NULL)
446
453
                        r = RET_ERROR;
447
454
                else
448
455
                        r = todo->callback(qa_error,
455
462
                size_t l, old_len, new_len;
456
463
                char *s;
457
464
 
458
 
                assert( method->fallbackbaseuri != NULL );
 
465
                assert (method->fallbackbaseuri != NULL);
459
466
 
460
467
                old_len = strlen(method->baseuri);
461
468
                new_len = strlen(method->fallbackbaseuri);
462
469
                l = strlen(todo->uri);
463
470
                s = malloc(l+new_len+1-old_len);
464
 
                if( FAILEDTOALLOC(s) ) {
 
471
                if (FAILEDTOALLOC(s)) {
465
472
                        todo_free(todo);
466
473
                        return RET_ERROR_OOM;
467
474
                }
476
483
}
477
484
 
478
485
/* look which file could not be received and remove it: */
479
 
static retvalue urierror(struct aptmethod *method,const char *uri,/*@only@*/char *message) {
480
 
        struct tobedone *todo,*lasttodo;
 
486
static retvalue urierror(struct aptmethod *method, const char *uri, /*@only@*/char *message) {
 
487
        struct tobedone *todo, *lasttodo;
481
488
 
482
489
        lasttodo = NULL; todo = method->tobedone;
483
 
        while( todo != NULL ) {
484
 
                if( strcmp(todo->uri,uri) == 0)  {
 
490
        while (todo != NULL) {
 
491
                if (strcmp(todo->uri, uri) == 0)  {
485
492
 
486
493
                        /* remove item: */
487
 
                        if( lasttodo == NULL )
 
494
                        if (lasttodo == NULL)
488
495
                                method->tobedone = todo->next;
489
496
                        else
490
497
                                lasttodo->next = todo->next;
491
 
                        if( method->nexttosend == todo ) {
 
498
                        if (method->nexttosend == todo) {
492
499
                                /* just in case some method received
493
500
                                 * files before we request them ;-) */
494
501
                                method->nexttosend = todo->next;
495
502
                        }
496
 
                        if( method->lasttobedone == todo ) {
 
503
                        if (method->lasttobedone == todo) {
497
504
                                method->lasttobedone = todo->next;
498
505
                        }
499
 
                        fprintf(stderr,"aptmethod error receiving '%s':\n'%s'\n",
 
506
                        fprintf(stderr,
 
507
"aptmethod error receiving '%s':\n'%s'\n",
500
508
                                        uri, (message != NULL)?message:"");
501
509
                        /* put message in failed items to show it later? */
502
510
                        free(message);
506
514
                todo = todo->next;
507
515
        }
508
516
        /* huh? If if have not asked for it, how can there be errors? */
509
 
        fprintf(stderr, "Method '%s' reported error with unrequested file '%s':\n'%s'!\n",
 
517
        fprintf(stderr,
 
518
"Method '%s' reported error with unrequested file '%s':\n'%s'!\n",
510
519
                        method->name, uri, message);
511
520
        free(message);
512
521
        return RET_ERROR;
514
523
 
515
524
/* look where a received file has to go to: */
516
525
static retvalue uridone(struct aptmethod *method, const char *uri, const char *filename, /*@only@*//*@null@*/struct checksums *checksumsfromapt) {
517
 
        struct tobedone *todo,*lasttodo;
 
526
        struct tobedone *todo, *lasttodo;
518
527
        retvalue r;
519
528
 
520
529
        lasttodo = NULL; todo = method->tobedone;
521
 
        while( todo != NULL ) {
522
 
                if( strcmp(todo->uri,uri) != 0)  {
 
530
        while (todo != NULL) {
 
531
                if (strcmp(todo->uri, uri) != 0)  {
523
532
                        lasttodo = todo;
524
533
                        todo = todo->next;
525
534
                        continue;
532
541
                checksums_free(checksumsfromapt);
533
542
 
534
543
                /* remove item: */
535
 
                if( lasttodo == NULL )
 
544
                if (lasttodo == NULL)
536
545
                        method->tobedone = todo->next;
537
546
                else
538
547
                        lasttodo->next = todo->next;
539
 
                if( method->nexttosend == todo ) {
 
548
                if (method->nexttosend == todo) {
540
549
                        /* just in case some method received
541
550
                         * files before we request them ;-) */
542
551
                        method->nexttosend = todo->next;
543
552
                }
544
 
                if( method->lasttobedone == todo ) {
 
553
                if (method->lasttobedone == todo) {
545
554
                        method->lasttobedone = todo->next;
546
555
                }
547
556
                todo_free(todo);
548
557
                return r;
549
558
        }
550
559
        /* huh? */
551
 
        fprintf(stderr, "Method '%s' retrieved unexpected file '%s' at '%s'!\n",
 
560
        fprintf(stderr,
 
561
"Method '%s' retrieved unexpected file '%s' at '%s'!\n",
552
562
                        method->name, uri, filename);
553
563
        checksums_free(checksumsfromapt);
554
564
        return RET_ERROR;
555
565
}
556
566
 
557
567
/***************************Input and Output****************************/
558
 
static retvalue logmessage(const struct aptmethod *method,const char *chunk,const char *type) {
 
568
static retvalue logmessage(const struct aptmethod *method, const char *chunk, const char *type) {
559
569
        retvalue r;
560
570
        char *message;
561
571
 
562
 
        r = chunk_getvalue(chunk,"Message",&message);
563
 
        if( RET_WAS_ERROR(r) )
564
 
                return r;
565
 
        if( RET_IS_OK(r) ) {
566
 
                fprintf(stderr,"aptmethod '%s': '%s'\n",method->baseuri,message);
567
 
                free(message);
568
 
                return RET_OK;
569
 
        }
570
 
        r = chunk_getvalue(chunk,"URI",&message);
571
 
        if( RET_WAS_ERROR(r) )
572
 
                return r;
573
 
        if( RET_IS_OK(r) ) {
574
 
                fprintf(stderr,"aptmethod %s '%s'\n",type,message);
575
 
                free(message);
576
 
                return RET_OK;
577
 
        }
578
 
        fprintf(stderr,"aptmethod '%s': '%s'\n",method->baseuri,type);
 
572
        r = chunk_getvalue(chunk, "Message", &message);
 
573
        if (RET_WAS_ERROR(r))
 
574
                return r;
 
575
        if (RET_IS_OK(r)) {
 
576
                fprintf(stderr, "aptmethod '%s': '%s'\n",
 
577
                                method->baseuri, message);
 
578
                free(message);
 
579
                return RET_OK;
 
580
        }
 
581
        r = chunk_getvalue(chunk, "URI", &message);
 
582
        if (RET_WAS_ERROR(r))
 
583
                return r;
 
584
        if (RET_IS_OK(r)) {
 
585
                fprintf(stderr, "aptmethod %s '%s'\n", type, message);
 
586
                free(message);
 
587
                return RET_OK;
 
588
        }
 
589
        fprintf(stderr, "aptmethod '%s': '%s'\n", method->baseuri, type);
579
590
        return RET_OK;
580
591
}
581
 
static inline retvalue gotcapabilities(struct aptmethod *method,const char *chunk) {
 
592
static inline retvalue gotcapabilities(struct aptmethod *method, const char *chunk) {
582
593
        retvalue r;
583
594
 
584
 
        r = chunk_gettruth(chunk,"Single-Instance");
585
 
        if( RET_WAS_ERROR(r) )
 
595
        r = chunk_gettruth(chunk, "Single-Instance");
 
596
        if (RET_WAS_ERROR(r))
586
597
                return r;
587
598
// TODO: what to do with this?
588
 
//      if( r != RET_NOTHING ) {
589
 
//              fprintf(stderr,"WARNING: Single-instance not yet supported!\n");
 
599
//      if (r != RET_NOTHING) {
 
600
//              fprintf(stderr, "WARNING: Single-instance not yet supported!\n");
590
601
//      }
591
 
        r = chunk_gettruth(chunk,"Send-Config");
592
 
        if( RET_WAS_ERROR(r) )
 
602
        r = chunk_gettruth(chunk, "Send-Config");
 
603
        if (RET_WAS_ERROR(r))
593
604
                return r;
594
 
        if( r != RET_NOTHING ) {
 
605
        if (r != RET_NOTHING) {
595
606
                assert(method->command == NULL);
596
607
                method->alreadywritten = 0;
597
608
                method->command = method->config;
598
609
                method->config = NULL;
599
610
                method->output_length = strlen(method->command);
600
 
                if( verbose > 11 ) {
601
 
                        fprintf(stderr,"Sending config: '%s'\n",method->command);
 
611
                if (verbose > 11) {
 
612
                        fprintf(stderr, "Sending config: '%s'\n",
 
613
                                        method->command);
602
614
                }
603
615
        } else {
604
616
                free(method->config);
620
632
 
621
633
        //TODO: is it worth the mess to make this in-situ?
622
634
 
623
 
        r = chunk_getvalue(chunk,"URI",&uri);
624
 
        if( r == RET_NOTHING ) {
 
635
        r = chunk_getvalue(chunk, "URI", &uri);
 
636
        if (r == RET_NOTHING) {
625
637
                fprintf(stderr,
626
638
"Missing URI header in uridone received from '%s' method!\n",
627
639
                                method->name);
628
640
                r = RET_ERROR;
629
641
                method->status = ams_failed;
630
642
        }
631
 
        if( RET_WAS_ERROR(r) )
 
643
        if (RET_WAS_ERROR(r))
632
644
                return r;
633
645
 
634
 
        r = chunk_getvalue(chunk,"Filename",&filename);
635
 
        if( r == RET_NOTHING ) {
 
646
        r = chunk_getvalue(chunk, "Filename", &filename);
 
647
        if (r == RET_NOTHING) {
636
648
                char *altfilename;
637
649
 
638
650
                r = chunk_getvalue(chunk, "Alt-Filename", &altfilename);
639
 
                if( r == RET_NOTHING ) {
 
651
                if (r == RET_NOTHING) {
640
652
                        fprintf(stderr,
641
653
"Missing Filename header in uridone received from '%s' method!\n",
642
654
                                        method->name);
643
 
                        r = urierror(method, uri, strdup("<no error but missing Filename from apt-method>"));
 
655
                        r = urierror(method, uri, strdup(
 
656
"<no error but missing Filename from apt-method>"));
644
657
                } else {
645
658
                        r = urierror(method, uri, mprintf(
646
659
"<File not there, apt-method suggests '%s' instead>", altfilename));
649
662
                free(uri);
650
663
                return r;
651
664
        }
652
 
        if( RET_WAS_ERROR(r) ) {
 
665
        if (RET_WAS_ERROR(r)) {
653
666
                free(uri);
654
667
                return r;
655
668
        }
656
 
        if( verbose >= 1 )
 
669
        if (verbose >= 1)
657
670
                fprintf(stderr, "aptmethod got '%s'\n", uri);
658
671
 
659
672
        result = RET_NOTHING;
660
 
        for( type = cs_md5sum ; type < cs_COUNT ; type++ ) {
 
673
        for (type = cs_md5sum ; type < cs_COUNT ; type++) {
661
674
                hashes[type] = NULL;
662
675
                r = chunk_getvalue(chunk, method_hash_names[type],
663
676
                                &hashes[type]);
664
677
                RET_UPDATE(result, r);
665
678
        }
666
 
        if( RET_IS_OK(result) && hashes[cs_md5sum] == NULL ) {
 
679
        if (RET_IS_OK(result) && hashes[cs_md5sum] == NULL) {
667
680
                /* the lenny version also has this, better ask for
668
681
                 * in case the old MD5-Hash vanishes in the future */
669
682
                r = chunk_getvalue(chunk, "MD5Sum-Hash", &hashes[cs_md5sum]);
670
683
                RET_UPDATE(result, r);
671
684
        }
672
 
        if( RET_WAS_ERROR(result) ) {
 
685
        if (RET_WAS_ERROR(result)) {
673
686
                free(uri); free(filename);
674
 
                for( type = cs_md5sum ; type < cs_COUNT ; type++ )
 
687
                for (type = cs_md5sum ; type < cs_COUNT ; type++)
675
688
                        free(hashes[type]);
676
689
                return result;
677
690
        }
678
 
        if( RET_IS_OK(result) ) {
 
691
        if (RET_IS_OK(result)) {
679
692
                /* ignore errors, we can recompute them from the file */
680
693
                (void)checksums_init(&checksums, hashes);
681
694
        }
682
 
        r = uridone(method, uri, filename, checksums);
 
695
        r = uridone(method, uri, filename, checksums);
683
696
        free(uri);
684
697
        free(filename);
685
698
        return r;
686
699
}
687
700
 
688
 
static inline retvalue goturierror(struct aptmethod *method,const char *chunk) {
 
701
static inline retvalue goturierror(struct aptmethod *method, const char *chunk) {
689
702
        retvalue r;
690
 
        char *uri,*message;
 
703
        char *uri, *message;
691
704
 
692
 
        r = chunk_getvalue(chunk,"URI",&uri);
693
 
        if( r == RET_NOTHING ) {
 
705
        r = chunk_getvalue(chunk, "URI", &uri);
 
706
        if (r == RET_NOTHING) {
694
707
                fprintf(stderr,
695
708
"Missing URI header in urierror received from '%s' method!\n", method->name);
696
709
                r = RET_ERROR;
697
710
        }
698
 
        if( RET_WAS_ERROR(r) )
 
711
        if (RET_WAS_ERROR(r))
699
712
                return r;
700
713
 
701
 
        r = chunk_getvalue(chunk,"Message",&message);
702
 
        if( r == RET_NOTHING ) {
 
714
        r = chunk_getvalue(chunk, "Message", &message);
 
715
        if (r == RET_NOTHING) {
703
716
                message = NULL;
704
717
        }
705
 
        if( RET_WAS_ERROR(r) ) {
 
718
        if (RET_WAS_ERROR(r)) {
706
719
                free(uri);
707
720
                return r;
708
721
        }
709
722
 
710
 
        r = urierror(method,uri,message);
 
723
        r = urierror(method, uri, message);
711
724
        free(uri);
712
725
        return r;
713
726
}
715
728
static inline retvalue parsereceivedblock(struct aptmethod *method, const char *input) {
716
729
        const char *p;
717
730
        retvalue r;
718
 
#define OVERLINE {while( *p != '\0' && *p != '\n') p++; if(*p == '\n') p++; }
 
731
#define OVERLINE {while (*p != '\0' && *p != '\n') p++; if (*p == '\n') p++; }
719
732
 
720
 
        while( *input == '\n' || *input == '\r' )
 
733
        while (*input == '\n' || *input == '\r')
721
734
                input++;
722
 
        if( *input == '\0' ) {
 
735
        if (*input == '\0') {
723
736
                fprintf(stderr,
724
737
"Unexpected number of newlines from '%s' method!\n", method->name);
725
738
                return RET_NOTHING;
726
739
        }
727
740
        p = input;
728
 
        switch( (*(input+1)=='0')?*input:'\0' ) {
 
741
        switch ((*(input+1)=='0')?*input:'\0') {
729
742
                case '1':
730
 
                        switch( *(input+2) ) {
 
743
                        switch (*(input+2)) {
731
744
                                /* 100 Capabilities */
732
745
                                case '0':
733
746
                                        OVERLINE;
734
 
                                        if( verbose > 14 ) {
735
 
                                                fprintf(stderr,"Got '%s'\n",input);
 
747
                                        if (verbose > 14) {
 
748
                                                fprintf(stderr, "Got '%s'\n",
 
749
                                                                input);
736
750
                                        }
737
 
                                        return gotcapabilities(method,input);
 
751
                                        return gotcapabilities(method, input);
738
752
                                /* 101 Log */
739
753
                                case '1':
740
 
                                        if( verbose > 10 ) {
 
754
                                        if (verbose > 10) {
741
755
                                                OVERLINE;
742
 
                                                return logmessage(method,p,"101");
 
756
                                                return logmessage(method, p, "101");
743
757
                                        }
744
758
                                        return RET_OK;
745
759
                                /* 102 Status */
746
760
                                case '2':
747
 
                                        if( verbose > 5 ) {
 
761
                                        if (verbose > 5) {
748
762
                                                OVERLINE;
749
 
                                                return logmessage(method,p,"102");
 
763
                                                return logmessage(method, p, "102");
750
764
                                        }
751
765
                                        return RET_OK;
752
766
                                default:
753
767
                                        fprintf(stderr,
754
 
"Error or unsupported message received: '%s'\n",        input);
 
768
"Error or unsupported message received: '%s'\n",
 
769
                                                        input);
755
770
                                        return RET_ERROR;
756
771
                        }
757
772
                case '2':
758
 
                        switch( *(input+2) ) {
 
773
                        switch (*(input+2)) {
759
774
                                /* 200 URI Start */
760
775
                                case '0':
761
 
                                        if( verbose > 5 ) {
 
776
                                        if (verbose > 5) {
762
777
                                                OVERLINE;
763
 
                                                return logmessage(method,p,"start");
 
778
                                                return logmessage(method, p, "start");
764
779
                                        }
765
780
                                        return RET_OK;
766
781
                                /* 201 URI Done */
769
784
                                        return goturidone(method, p);
770
785
                                default:
771
786
                                        fprintf(stderr,
772
 
"Error or unsupported message received: '%s'\n",        input);
 
787
"Error or unsupported message received: '%s'\n",
 
788
                                                        input);
773
789
                                        return RET_ERROR;
774
790
                        }
775
791
 
776
792
                case '4':
777
 
                        switch( *(input+2) ) {
 
793
                        switch (*(input+2)) {
778
794
                                case '0':
779
795
                                        OVERLINE;
780
 
                                        r = goturierror(method,p);
 
796
                                        r = goturierror(method, p);
781
797
                                        break;
782
798
                                case '1':
783
799
                                        OVERLINE;
784
 
                                        (void)logmessage(method,p,"general error");
 
800
                                        (void)logmessage(method, p, "general error");
785
801
                                        method->status = ams_failed;
786
802
                                        r = RET_ERROR;
787
803
                                        break;
788
804
                                default:
789
805
                                        fprintf(stderr,
790
 
"Error or unsupported message received: '%s'\n",        input);
 
806
"Error or unsupported message received: '%s'\n",
 
807
                                                        input);
791
808
                                        r = RET_ERROR;
792
809
                        }
793
810
                        /* a failed download is not a error yet, as it might
794
811
                         * be redone from another source later */
795
812
                        return r;
796
813
                default:
797
 
                        fprintf(stderr, "Unexpected data from '%s' method: '%s'\n",
 
814
                        fprintf(stderr,
 
815
"Unexpected data from '%s' method: '%s'\n",
798
816
                                        method->name, input);
799
817
                        return RET_ERROR;
800
818
        }
806
824
        char *p;
807
825
        int consecutivenewlines;
808
826
 
809
 
        assert( method->status != ams_ok || method->tobedone != NULL );
810
 
        if( method->status != ams_waitforcapabilities && method->status != ams_ok )
 
827
        assert (method->status != ams_ok || method->tobedone != NULL);
 
828
        if (method->status != ams_waitforcapabilities
 
829
                        && method->status != ams_ok)
811
830
                return RET_NOTHING;
812
831
 
813
832
        /* First look if we have enough room to read.. */
814
 
        if( method->alreadyread + 1024 >= method->input_size ) {
 
833
        if (method->alreadyread + 1024 >= method->input_size) {
815
834
                char *newptr;
816
835
 
817
 
                if( method->input_size >= (size_t)128000 ) {
818
 
                        fprintf(stderr, "Ridiculously long answer from method!\n");
 
836
                if (method->input_size >= (size_t)128000) {
 
837
                        fprintf(stderr,
 
838
"Ridiculously long answer from method!\n");
819
839
                        method->status = ams_failed;
820
840
                        return RET_ERROR;
821
841
                }
822
842
 
823
 
                newptr = realloc(method->inputbuffer,method->alreadyread+1024);
824
 
                if( newptr == NULL ) {
 
843
                newptr = realloc(method->inputbuffer, method->alreadyread+1024);
 
844
                if (FAILEDTOALLOC(newptr)) {
825
845
                        return RET_ERROR_OOM;
826
846
                }
827
847
                method->inputbuffer = newptr;
828
848
                method->input_size = method->alreadyread + 1024;
829
849
        }
830
 
        assert( method->inputbuffer != NULL );
 
850
        assert (method->inputbuffer != NULL);
831
851
        /* then read as much as the pipe is able to fill of our buffer */
832
852
 
833
 
        r = read(method->mstdout,method->inputbuffer+method->alreadyread,method->input_size-method->alreadyread-1);
 
853
        r = read(method->mstdout, method->inputbuffer + method->alreadyread,
 
854
                        method->input_size - method->alreadyread - 1);
834
855
 
835
 
        if( r < 0 ) {
 
856
        if (r < 0) {
836
857
                int e = errno;
837
858
                fprintf(stderr, "Error %d reading pipe from aptmethod: %s\n",
838
859
                                e, strerror(e));
849
870
                p = method->inputbuffer;
850
871
                consecutivenewlines = 0;
851
872
 
852
 
                while( r > 0 ) {
853
 
                        if( *p == '\0' ) {
854
 
                                fprintf(stderr, "Unexpected Zeroes in method output!\n");
 
873
                while (r > 0) {
 
874
                        if (*p == '\0') {
 
875
                                fprintf(stderr,
 
876
"Unexpected Zeroes in method output!\n");
855
877
                                method->status = ams_failed;
856
878
                                return RET_ERROR;
857
 
                        } else if( *p == '\n' ) {
 
879
                        } else if (*p == '\n') {
858
880
                                consecutivenewlines++;
859
 
                                if( consecutivenewlines >= 2 )
 
881
                                if (consecutivenewlines >= 2)
860
882
                                        break;
861
 
                        } else if( *p != '\r' ) {
 
883
                        } else if (*p != '\r') {
862
884
                                consecutivenewlines = 0;
863
885
                        }
864
886
                        p++; r--;
865
887
                }
866
 
                if( r <= 0 ) {
 
888
                if (r <= 0) {
867
889
                        return result;
868
890
                }
869
891
                *p ='\0'; p++; r--;
870
892
                res = parsereceivedblock(method, method->inputbuffer);
871
 
                if( r > 0 )
872
 
                        memmove(method->inputbuffer,p,r);
 
893
                if (r > 0)
 
894
                        memmove(method->inputbuffer, p, r);
873
895
                method->alreadyread = r;
874
 
                RET_UPDATE(result,res);
 
896
                RET_UPDATE(result, res);
875
897
        }
876
898
}
877
899
 
879
901
        size_t l;
880
902
        ssize_t r;
881
903
 
882
 
        if( method->status != ams_ok )
 
904
        if (method->status != ams_ok)
883
905
                return RET_NOTHING;
884
906
 
885
 
        if( method->command == NULL ) {
 
907
        if (method->command == NULL) {
886
908
                const struct tobedone *todo;
887
909
 
888
910
                /* nothing queued to send, nothing to be queued...*/
889
911
                todo = method->nexttosend;
890
 
                if( todo == NULL )
 
912
                if (todo == NULL)
891
913
                        return RET_OK;
892
914
 
893
 
                if( interrupted() )
 
915
                if (interrupted())
894
916
                        return RET_ERROR_INTERRUPTED;
895
917
 
896
918
                method->alreadywritten = 0;
897
919
                // TODO: make sure this is already checked for earlier...
898
 
                assert( strchr(todo->uri, '\n') == NULL &&
899
 
                        strchr(todo->filename,'\n') == NULL );
900
 
                /* http-aptmethod seems to loose the last byte if the file is already
901
 
                 * in place, so we better unlink the target first...
 
920
                assert (strchr(todo->uri, '\n') == NULL &&
 
921
                        strchr(todo->filename, '\n') == NULL);
 
922
                /* http-aptmethod seems to loose the last byte,
 
923
                 * if the file is already in place,
 
924
                 * so we better unlink the target first...
902
925
                 * but this is done elsewhere already
903
926
                unlink(todo->filename);
904
927
                */
905
928
                method->command = mprintf(
906
929
                         "600 URI Acquire\nURI: %s\nFilename: %s\n\n",
907
930
                         todo->uri, todo->filename);
908
 
                if( method->command == NULL ) {
 
931
                if (FAILEDTOALLOC(method->command)) {
909
932
                        return RET_ERROR_OOM;
910
933
                }
911
934
                method->output_length = strlen(method->command);
915
938
 
916
939
        l = method->output_length - method->alreadywritten;
917
940
 
918
 
        r = write(method->mstdin,method->command+method->alreadywritten,l);
919
 
        if( r < 0 ) {
 
941
        r = write(method->mstdin, method->command + method->alreadywritten, l);
 
942
        if (r < 0) {
920
943
                int e = errno;
921
944
 
922
945
                fprintf(stderr, "Error %d writing to pipe: %s\n",
924
947
                //TODO: disable the whole method??
925
948
                method->status = ams_failed;
926
949
                return RET_ERRNO(e);
927
 
        } else if( (size_t)r < l ) {
 
950
        } else if ((size_t)r < l) {
928
951
                method->alreadywritten += r;
929
952
                return RET_OK;
930
953
        }
938
961
        pid_t child;int status;
939
962
        retvalue result = RET_OK, r;
940
963
 
941
 
        while( (child = waitpid(-1,&status,WNOHANG)) > 0 ) {
 
964
        while ((child = waitpid(-1, &status, WNOHANG)) > 0) {
942
965
                struct aptmethod *method;
943
966
 
944
 
                for( method = run->methods; method != NULL ; method = method->next) {
945
 
                        if( method->child == child )
 
967
                for (method = run->methods ; method != NULL ;
 
968
                                             method = method->next) {
 
969
                        if (method->child == child)
946
970
                                break;
947
971
                }
948
 
                if( method == NULL ) {
 
972
                if (method == NULL) {
949
973
                        /* perhaps an uncompressor terminated */
950
974
                        r = uncompress_checkpid(child, status);
951
 
                        if( RET_IS_OK(r) )
 
975
                        if (RET_IS_OK(r))
952
976
                                continue;
953
 
                        if( RET_WAS_ERROR(r) ) {
 
977
                        if (RET_WAS_ERROR(r)) {
954
978
                                result = r;
955
979
                                continue;
956
980
                        }
957
981
                        else {
958
982
                                fprintf(stderr,
959
 
                                                "Unexpected child died (maybe gpg died if signing/verifing was done): %d\n",
 
983
"Unexpected child died (maybe gpg died if signing/verifing was done): %d\n",
960
984
                                                (int)child);
961
985
                                continue;
962
986
                        }
963
987
                }
964
988
                /* Make sure we do not cope with this child any more */
965
 
                if( method->mstdin != -1 ) {
 
989
                if (method->mstdin != -1) {
966
990
                        (void)close(method->mstdin);
967
991
                        method->mstdin = -1;
968
992
                }
969
 
                if( method->mstdout != -1 ) {
 
993
                if (method->mstdout != -1) {
970
994
                        (void)close(method->mstdout);
971
995
                        method->mstdout = -1;
972
996
                }
973
997
                method->child = -1;
974
 
                if( method->status != ams_failed )
 
998
                if (method->status != ams_failed)
975
999
                        method->status = ams_notstarted;
976
1000
 
977
1001
                /* say something if it exited unnormal: */
978
 
                if( WIFEXITED(status) ) {
 
1002
                if (WIFEXITED(status)) {
979
1003
                        int exitcode;
980
1004
 
981
1005
                        exitcode = WEXITSTATUS(status);
982
 
                        if( exitcode != 0 ) {
 
1006
                        if (exitcode != 0) {
983
1007
                                fprintf(stderr,
984
1008
"Method %s://%s exited with non-zero exit code %d!\n",
985
1009
                                        method->name, method->baseuri,
988
1012
                                result = RET_ERROR;
989
1013
                        }
990
1014
                } else {
991
 
                        fprintf(stderr,"Method %s://%s exited unnormally!\n",method->name,method->baseuri);
 
1015
                        fprintf(stderr, "Method %s://%s exited unnormally!\n",
 
1016
                                        method->name, method->baseuri);
992
1017
                        method->status = ams_notstarted;
993
1018
                        result = RET_ERROR;
994
1019
                }
996
1021
        return result;
997
1022
}
998
1023
 
999
 
/* *workleft is always set, even when return indicated error. (workleft < 0 when critical)*/
 
1024
/* *workleft is always set, even when return indicated error.
 
1025
 * (workleft < 0 when critical)*/
1000
1026
static retvalue readwrite(struct aptmethodrun *run, /*@out@*/int *workleft) {
1001
 
        int maxfd,v;
1002
 
        fd_set readfds,writefds;
 
1027
        int maxfd, v;
 
1028
        fd_set readfds, writefds;
1003
1029
        struct aptmethod *method;
1004
 
        retvalue result,r;
 
1030
        retvalue result, r;
1005
1031
 
1006
1032
        /* First calculate what to look at: */
1007
1033
        FD_ZERO(&readfds);
1008
1034
        FD_ZERO(&writefds);
1009
1035
        maxfd = 0;
1010
1036
        *workleft = 0;
1011
 
        for( method = run->methods ; method != NULL ; method = method->next ) {
1012
 
                if( method->status == ams_ok &&
1013
 
                    ( method->command != NULL || method->nexttosend != NULL )) {
1014
 
                        FD_SET(method->mstdin,&writefds);
1015
 
                        if( method->mstdin > maxfd )
 
1037
        for (method = run->methods ; method != NULL ; method = method->next) {
 
1038
                if (method->status == ams_ok &&
 
1039
                    (method->command != NULL || method->nexttosend != NULL)) {
 
1040
                        FD_SET(method->mstdin, &writefds);
 
1041
                        if (method->mstdin > maxfd)
1016
1042
                                maxfd = method->mstdin;
1017
1043
                        (*workleft)++;
1018
 
                        if( verbose > 19 )
1019
 
                                fprintf(stderr,"want to write to '%s'\n",method->baseuri);
 
1044
                        if (verbose > 19)
 
1045
                                fprintf(stderr, "want to write to '%s'\n",
 
1046
                                                method->baseuri);
1020
1047
                }
1021
 
                if( method->status == ams_waitforcapabilities ||
 
1048
                if (method->status == ams_waitforcapabilities ||
1022
1049
                                (method->status == ams_ok &&
1023
 
                                method->tobedone != NULL ) ) {
1024
 
                        FD_SET(method->mstdout,&readfds);
1025
 
                        if( method->mstdout > maxfd )
 
1050
                                method->tobedone != NULL)) {
 
1051
                        FD_SET(method->mstdout, &readfds);
 
1052
                        if (method->mstdout > maxfd)
1026
1053
                                maxfd = method->mstdout;
1027
1054
                        (*workleft)++;
1028
 
                        if( verbose > 19 )
1029
 
                                fprintf(stderr,"want to read from '%s'\n",method->baseuri);
 
1055
                        if (verbose > 19)
 
1056
                                fprintf(stderr, "want to read from '%s'\n",
 
1057
                                                method->baseuri);
1030
1058
                }
1031
1059
        }
1032
1060
 
1033
 
        if( *workleft == 0 )
 
1061
        if (*workleft == 0)
1034
1062
                return RET_NOTHING;
1035
1063
 
1036
1064
        // TODO: think about a timeout...
1037
 
        v = select(maxfd+1,&readfds,&writefds,NULL,NULL);
1038
 
        if( v < 0 ) {
 
1065
        v = select(maxfd + 1, &readfds, &writefds, NULL, NULL);
 
1066
        if (v < 0) {
1039
1067
                int e = errno;
1040
1068
                //TODO: handle (e == EINTR) && interrupted() specially
1041
1069
                fprintf(stderr, "Select returned error %d: %s\n",
1048
1076
        result = RET_NOTHING;
1049
1077
 
1050
1078
        maxfd = 0;
1051
 
        for( method = run->methods ; method != NULL ; method = method->next ) {
1052
 
                if( method->mstdout != -1 && FD_ISSET(method->mstdout,&readfds) ) {
 
1079
        for (method = run->methods ; method != NULL ; method = method->next) {
 
1080
                if (method->mstdout != -1 &&
 
1081
                                FD_ISSET(method->mstdout, &readfds)) {
1053
1082
                        r = receivedata(method);
1054
 
                        RET_UPDATE(result,r);
 
1083
                        RET_UPDATE(result, r);
1055
1084
                }
1056
 
                if( method->mstdin != -1 && FD_ISSET(method->mstdin,&writefds) ) {
 
1085
                if (method->mstdin != -1 &&
 
1086
                                FD_ISSET(method->mstdin, &writefds)) {
1057
1087
                        r = senddata(method);
1058
 
                        RET_UPDATE(result,r);
 
1088
                        RET_UPDATE(result, r);
1059
1089
                }
1060
1090
        }
1061
1091
        return result;
1063
1093
 
1064
1094
retvalue aptmethod_download(struct aptmethodrun *run) {
1065
1095
        struct aptmethod *method;
1066
 
        retvalue result,r;
 
1096
        retvalue result, r;
1067
1097
        int workleft;
1068
1098
 
1069
1099
        result = RET_NOTHING;
1070
1100
 
1071
1101
        /* fire up all methods, removing those that do not work: */
1072
 
        for( method = run->methods; method != NULL ; method = method->next ) {
 
1102
        for (method = run->methods; method != NULL ; method = method->next) {
1073
1103
                r = aptmethod_startup(method);
1074
1104
                /* do not remove failed methods here any longer,
1075
1105
                 * and not remove methods having nothing to do,
1076
1106
                 * as this breaks when no index files are downloaded
1077
1107
                 * due to all already being in place... */
1078
 
                RET_UPDATE(result,r);
 
1108
                RET_UPDATE(result, r);
1079
1109
        }
1080
1110
        /* waiting for them to finish: */
1081
1111
        do {
1082
1112
          r = checkchilds(run);
1083
 
          RET_UPDATE(result,r);
 
1113
          RET_UPDATE(result, r);
1084
1114
          r = readwrite(run, &workleft);
1085
 
          RET_UPDATE(result,r);
 
1115
          RET_UPDATE(result, r);
1086
1116
          // TODO: check interrupted here...
1087
 
        } while( workleft > 0 || uncompress_running() );
 
1117
        } while (workleft > 0 || uncompress_running());
1088
1118
 
1089
1119
        return result;
1090
1120
}