62
62
/*@null@*/char *fallbackbaseuri;
63
63
/*@null@*/char *config;
67
enum { ams_notstarted=0, ams_waitforcapabilities, ams_ok, ams_failed } status;
69
ams_waitforcapabilities,
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;
80
85
struct aptmethodrun {
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;
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) {
123
if( (*method_ptr)->child > 0 ) {
125
fprintf(stderr,"Still waiting for %d\n",(int)(*method_ptr)->child);
128
if ((*method_ptr)->child > 0) {
131
"Still waiting for %d\n", (int)(*method_ptr)->child);
126
132
method_ptr = &(*method_ptr)->next;
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);
142
148
fprintf(stderr, "Closing stdin of %d\n",
143
149
(int)method->child);
145
151
method->mstdin = -1;
146
if( method->mstdout >= 0 ) {
152
if (method->mstdout >= 0) {
147
153
(void)close(method->mstdout);
149
155
fprintf(stderr, "Closing stdout of %d\n",
150
156
(int)method->child);
152
158
method->mstdout = -1;
154
while( run->methods != NULL || uncompress_running() ) {
160
while (run->methods != NULL || uncompress_running()) {
155
161
pid_t pid;int status;
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;
163
if( lastmethod != NULL ) {
169
if (lastmethod != NULL) {
164
170
lastmethod->next = next;
166
172
run->methods = next;
187
193
retvalue aptmethod_initialize_run(struct aptmethodrun **run) {
188
194
struct aptmethodrun *r;
190
r = calloc(1,sizeof(struct aptmethodrun));
196
r = zNEW(struct aptmethodrun);
197
if (FAILEDTOALLOC(r))
192
198
return RET_ERROR_OOM;
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;
203
method = calloc(1,sizeof(struct aptmethod));
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;
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'))) {
217
221
fprintf(stderr, "No colon found in method-URI '%s'!\n", uri);
219
223
return RET_ERROR;
222
fprintf(stderr,"Unexpected character '%c' in method-URI '%s'!\n",*p,uri);
227
"Unexpected character '%c' in method-URI '%s'!\n", *p, uri);
224
229
return RET_ERROR;
227
fprintf(stderr,"Zero-length name in method-URI '%s'!\n",uri);
233
"Zero-length name in method-URI '%s'!\n", uri);
229
235
return RET_ERROR;
232
method->name = strndup(uri,p-uri);
233
if( method->name == NULL ) {
238
method->name = strndup(uri, p-uri);
239
if (FAILEDTOALLOC(method->name)) {
235
241
return RET_ERROR_OOM;
237
243
method->baseuri = strdup(uri);
238
if( method->baseuri == NULL ) {
244
if (FAILEDTOALLOC(method->baseuri)) {
239
245
free(method->name);
241
247
return RET_ERROR_OOM;
243
if( fallbackuri == NULL )
249
if (fallbackuri == NULL)
244
250
method->fallbackbaseuri = NULL;
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);
282
288
/* When there is nothing to get, there is no reason to startup
284
if( method->tobedone == NULL ) {
290
if (method->tobedone == NULL) {
285
291
return RET_NOTHING;
288
294
/* when we are already running, we are already ready...*/
289
if( method->child > 0 ) {
295
if (method->child > 0) {
293
299
method->status = ams_waitforcapabilities;
295
301
r = pipe(mstdin);
298
304
fprintf(stderr, "Error %d creating pipe: %s\n",
300
306
return RET_ERRNO(e);
302
308
r = pipe(mstdout);
305
311
(void)close(mstdin[0]); (void)close(mstdin[1]);
306
312
fprintf(stderr, "Error %d in pipe syscall: %s\n",
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;
399
if( FAILEDTOALLOC(destfile) ) {
406
if (FAILEDTOALLOC(destfile)) {
401
408
return RET_ERROR_OOM;
403
if( FAILEDTOALLOC(uri) ) {
410
if (FAILEDTOALLOC(uri)) {
405
412
return RET_ERROR_OOM;
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;
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;
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) {
486
493
/* remove item: */
487
if( lasttodo == NULL )
494
if (lasttodo == NULL)
488
495
method->tobedone = todo->next;
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;
496
if( method->lasttobedone == todo ) {
503
if (method->lasttobedone == todo) {
497
504
method->lasttobedone = todo->next;
499
fprintf(stderr,"aptmethod error receiving '%s':\n'%s'\n",
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? */
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;
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) {
524
533
todo = todo->next;
532
541
checksums_free(checksumsfromapt);
534
543
/* remove item: */
535
if( lasttodo == NULL )
544
if (lasttodo == NULL)
536
545
method->tobedone = todo->next;
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;
544
if( method->lasttobedone == todo ) {
553
if (method->lasttobedone == todo) {
545
554
method->lasttobedone = todo->next;
551
fprintf(stderr, "Method '%s' retrieved unexpected file '%s' at '%s'!\n",
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;
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) {
562
r = chunk_getvalue(chunk,"Message",&message);
563
if( RET_WAS_ERROR(r) )
566
fprintf(stderr,"aptmethod '%s': '%s'\n",method->baseuri,message);
570
r = chunk_getvalue(chunk,"URI",&message);
571
if( RET_WAS_ERROR(r) )
574
fprintf(stderr,"aptmethod %s '%s'\n",type,message);
578
fprintf(stderr,"aptmethod '%s': '%s'\n",method->baseuri,type);
572
r = chunk_getvalue(chunk, "Message", &message);
573
if (RET_WAS_ERROR(r))
576
fprintf(stderr, "aptmethod '%s': '%s'\n",
577
method->baseuri, message);
581
r = chunk_getvalue(chunk, "URI", &message);
582
if (RET_WAS_ERROR(r))
585
fprintf(stderr, "aptmethod %s '%s'\n", type, message);
589
fprintf(stderr, "aptmethod '%s': '%s'\n", method->baseuri, type);
581
static inline retvalue gotcapabilities(struct aptmethod *method,const char *chunk) {
592
static inline retvalue gotcapabilities(struct aptmethod *method, const char *chunk) {
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))
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");
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))
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);
601
fprintf(stderr,"Sending config: '%s'\n",method->command);
612
fprintf(stderr, "Sending config: '%s'\n",
604
616
free(method->config);
621
633
//TODO: is it worth the mess to make this in-situ?
623
r = chunk_getvalue(chunk,"URI",&uri);
624
if( r == RET_NOTHING ) {
635
r = chunk_getvalue(chunk, "URI", &uri);
636
if (r == RET_NOTHING) {
626
638
"Missing URI header in uridone received from '%s' method!\n",
629
641
method->status = ams_failed;
631
if( RET_WAS_ERROR(r) )
643
if (RET_WAS_ERROR(r))
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;
638
650
r = chunk_getvalue(chunk, "Alt-Filename", &altfilename);
639
if( r == RET_NOTHING ) {
651
if (r == RET_NOTHING) {
641
653
"Missing Filename header in uridone received from '%s' method!\n",
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>"));
645
658
r = urierror(method, uri, mprintf(
646
659
"<File not there, apt-method suggests '%s' instead>", altfilename));
652
if( RET_WAS_ERROR(r) ) {
665
if (RET_WAS_ERROR(r)) {
657
670
fprintf(stderr, "aptmethod got '%s'\n", uri);
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],
664
677
RET_UPDATE(result, r);
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);
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]);
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);
682
r = uridone(method, uri, filename, checksums);
695
r = uridone(method, uri, filename, checksums);
688
static inline retvalue goturierror(struct aptmethod *method,const char *chunk) {
701
static inline retvalue goturierror(struct aptmethod *method, const char *chunk) {
692
r = chunk_getvalue(chunk,"URI",&uri);
693
if( r == RET_NOTHING ) {
705
r = chunk_getvalue(chunk, "URI", &uri);
706
if (r == RET_NOTHING) {
695
708
"Missing URI header in urierror received from '%s' method!\n", method->name);
698
if( RET_WAS_ERROR(r) )
711
if (RET_WAS_ERROR(r))
701
r = chunk_getvalue(chunk,"Message",&message);
702
if( r == RET_NOTHING ) {
714
r = chunk_getvalue(chunk, "Message", &message);
715
if (r == RET_NOTHING) {
705
if( RET_WAS_ERROR(r) ) {
718
if (RET_WAS_ERROR(r)) {
710
r = urierror(method,uri,message);
723
r = urierror(method, uri, message);
715
728
static inline retvalue parsereceivedblock(struct aptmethod *method, const char *input) {
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++; }
720
while( *input == '\n' || *input == '\r' )
733
while (*input == '\n' || *input == '\r')
722
if( *input == '\0' ) {
735
if (*input == '\0') {
724
737
"Unexpected number of newlines from '%s' method!\n", method->name);
725
738
return RET_NOTHING;
728
switch( (*(input+1)=='0')?*input:'\0' ) {
741
switch ((*(input+1)=='0')?*input:'\0') {
730
switch( *(input+2) ) {
743
switch (*(input+2)) {
731
744
/* 100 Capabilities */
735
fprintf(stderr,"Got '%s'\n",input);
748
fprintf(stderr, "Got '%s'\n",
737
return gotcapabilities(method,input);
751
return gotcapabilities(method, input);
742
return logmessage(method,p,"101");
756
return logmessage(method, p, "101");
749
return logmessage(method,p,"102");
763
return logmessage(method, p, "102");
754
"Error or unsupported message received: '%s'\n", input);
768
"Error or unsupported message received: '%s'\n",
755
770
return RET_ERROR;
758
switch( *(input+2) ) {
773
switch (*(input+2)) {
759
774
/* 200 URI Start */
763
return logmessage(method,p,"start");
778
return logmessage(method, p, "start");
766
781
/* 201 URI Done */
769
784
return goturidone(method, p);
772
"Error or unsupported message received: '%s'\n", input);
787
"Error or unsupported message received: '%s'\n",
773
789
return RET_ERROR;
777
switch( *(input+2) ) {
793
switch (*(input+2)) {
780
r = goturierror(method,p);
796
r = goturierror(method, p);
784
(void)logmessage(method,p,"general error");
800
(void)logmessage(method, p, "general error");
785
801
method->status = ams_failed;
790
"Error or unsupported message received: '%s'\n", input);
806
"Error or unsupported message received: '%s'\n",
793
810
/* a failed download is not a error yet, as it might
794
811
* be redone from another source later */
797
fprintf(stderr, "Unexpected data from '%s' method: '%s'\n",
815
"Unexpected data from '%s' method: '%s'\n",
798
816
method->name, input);
799
817
return RET_ERROR;
807
825
int consecutivenewlines;
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;
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) {
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) {
838
"Ridiculously long answer from method!\n");
819
839
method->status = ams_failed;
820
840
return RET_ERROR;
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;
827
847
method->inputbuffer = newptr;
828
848
method->input_size = method->alreadyread + 1024;
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 */
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);
837
858
fprintf(stderr, "Error %d reading pipe from aptmethod: %s\n",
849
870
p = method->inputbuffer;
850
871
consecutivenewlines = 0;
854
fprintf(stderr, "Unexpected Zeroes in method output!\n");
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)
861
} else if( *p != '\r' ) {
883
} else if (*p != '\r') {
862
884
consecutivenewlines = 0;
869
891
*p ='\0'; p++; r--;
870
892
res = parsereceivedblock(method, method->inputbuffer);
872
memmove(method->inputbuffer,p,r);
894
memmove(method->inputbuffer, p, r);
873
895
method->alreadyread = r;
874
RET_UPDATE(result,res);
896
RET_UPDATE(result, res);
882
if( method->status != ams_ok )
904
if (method->status != ams_ok)
883
905
return RET_NOTHING;
885
if( method->command == NULL ) {
907
if (method->command == NULL) {
886
908
const struct tobedone *todo;
888
910
/* nothing queued to send, nothing to be queued...*/
889
911
todo = method->nexttosend;
894
916
return RET_ERROR_INTERRUPTED;
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);
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;
911
934
method->output_length = strlen(method->command);
938
961
pid_t child;int status;
939
962
retvalue result = RET_OK, r;
941
while( (child = waitpid(-1,&status,WNOHANG)) > 0 ) {
964
while ((child = waitpid(-1, &status, WNOHANG)) > 0) {
942
965
struct aptmethod *method;
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)
948
if( method == NULL ) {
972
if (method == NULL) {
949
973
/* perhaps an uncompressor terminated */
950
974
r = uncompress_checkpid(child, status);
953
if( RET_WAS_ERROR(r) ) {
977
if (RET_WAS_ERROR(r)) {
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",
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;
969
if( method->mstdout != -1 ) {
993
if (method->mstdout != -1) {
970
994
(void)close(method->mstdout);
971
995
method->mstdout = -1;
973
997
method->child = -1;
974
if( method->status != ams_failed )
998
if (method->status != ams_failed)
975
999
method->status = ams_notstarted;
977
1001
/* say something if it exited unnormal: */
978
if( WIFEXITED(status) ) {
1002
if (WIFEXITED(status)) {
981
1005
exitcode = WEXITSTATUS(status);
982
if( exitcode != 0 ) {
1006
if (exitcode != 0) {
984
1008
"Method %s://%s exited with non-zero exit code %d!\n",
985
1009
method->name, method->baseuri,
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) {
1002
fd_set readfds,writefds;
1028
fd_set readfds, writefds;
1003
1029
struct aptmethod *method;
1006
1032
/* First calculate what to look at: */
1007
1033
FD_ZERO(&readfds);
1008
1034
FD_ZERO(&writefds);
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;
1019
fprintf(stderr,"want to write to '%s'\n",method->baseuri);
1045
fprintf(stderr, "want to write to '%s'\n",
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;
1029
fprintf(stderr,"want to read from '%s'\n",method->baseuri);
1056
fprintf(stderr, "want to read from '%s'\n",
1033
if( *workleft == 0 )
1034
1062
return RET_NOTHING;
1036
1064
// TODO: think about a timeout...
1037
v = select(maxfd+1,&readfds,&writefds,NULL,NULL);
1065
v = select(maxfd + 1, &readfds, &writefds, NULL, NULL);
1040
1068
//TODO: handle (e == EINTR) && interrupted() specially
1041
1069
fprintf(stderr, "Select returned error %d: %s\n",
1064
1094
retvalue aptmethod_download(struct aptmethodrun *run) {
1065
1095
struct aptmethod *method;
1069
1099
result = RET_NOTHING;
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);
1080
1110
/* waiting for them to finish: */
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());