|
@@ -1,176 +0,0 @@
|
1
|
|
-/*
|
2
|
|
- * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
|
3
|
|
- *
|
4
|
|
- * This program is free software; you can redistribute it and/or
|
5
|
|
- * modify it under the terms of the GNU General Public License as
|
6
|
|
- * published by the Free Software Foundation; either version 2 of the
|
7
|
|
- * License, or any later version.
|
8
|
|
- *
|
9
|
|
- * This program is distributed in the hope that it will be useful, but
|
10
|
|
- * WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
|
- * General Public License for more details.
|
13
|
|
- *
|
14
|
|
- * You should have received a copy of the GNU General Public License
|
15
|
|
- * along with this program; if not, write to the Free Software
|
16
|
|
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
17
|
|
- */
|
18
|
|
-
|
19
|
|
-/**
|
20
|
|
- * @file
|
21
|
|
- *
|
22
|
|
- * Download protocols
|
23
|
|
- *
|
24
|
|
- */
|
25
|
|
-
|
26
|
|
-#include <stdint.h>
|
27
|
|
-#include <stdlib.h>
|
28
|
|
-#include <errno.h>
|
29
|
|
-#include <gpxe/umalloc.h>
|
30
|
|
-#include <gpxe/ebuffer.h>
|
31
|
|
-#include <gpxe/download.h>
|
32
|
|
-
|
33
|
|
-static struct async_operations download_async_operations;
|
34
|
|
-
|
35
|
|
-/** Registered download protocols */
|
36
|
|
-static struct download_protocol download_protocols[0]
|
37
|
|
- __table_start ( struct download_protocol, download_protocols );
|
38
|
|
-static struct download_protocol download_protocols_end[0]
|
39
|
|
- __table_end ( struct download_protocol, download_protocols );
|
40
|
|
-
|
41
|
|
-/**
|
42
|
|
- * Identify download protocol
|
43
|
|
- *
|
44
|
|
- * @v name Download protocol name
|
45
|
|
- * @ret protocol Download protocol, or NULL
|
46
|
|
- */
|
47
|
|
-static struct download_protocol * find_protocol ( const char *name ) {
|
48
|
|
- struct download_protocol *protocol;
|
49
|
|
-
|
50
|
|
- for ( protocol = download_protocols; protocol < download_protocols_end;
|
51
|
|
- protocol++ ) {
|
52
|
|
- if ( strcmp ( name, protocol->name ) == 0 )
|
53
|
|
- return protocol;
|
54
|
|
- }
|
55
|
|
- return NULL;
|
56
|
|
-}
|
57
|
|
-
|
58
|
|
-/**
|
59
|
|
- * Start download
|
60
|
|
- *
|
61
|
|
- * @v uri_string URI as a string (e.g. "http://www.nowhere.com/vmlinuz")
|
62
|
|
- * @v parent Parent asynchronous operation
|
63
|
|
- * @ret data Loaded file
|
64
|
|
- * @ret len Length of loaded file
|
65
|
|
- * @ret rc Return status code
|
66
|
|
- *
|
67
|
|
- * Starts download of a file to a user buffer. The user buffer is
|
68
|
|
- * allocated with umalloc(). The parent asynchronous operation will
|
69
|
|
- * be notified via SIGCHLD when the download completes. If the
|
70
|
|
- * download completes successfully, the @c data and @c len fields will
|
71
|
|
- * have been filled in, and the parent takes ownership of the buffer,
|
72
|
|
- * which must eventually be freed with ufree().
|
73
|
|
- *
|
74
|
|
- * The uri_string does not need to remain persistent for the duration
|
75
|
|
- * of the download; the parent may discard it as soon as
|
76
|
|
- * start_download returns.
|
77
|
|
- */
|
78
|
|
-int start_download ( const char *uri_string, struct async *parent,
|
79
|
|
- userptr_t *data, size_t *len ) {
|
80
|
|
- struct download *download;
|
81
|
|
- int rc;
|
82
|
|
-
|
83
|
|
- /* Allocate and populate download structure */
|
84
|
|
- download = malloc ( sizeof ( *download ) );
|
85
|
|
- if ( ! download )
|
86
|
|
- return -ENOMEM;
|
87
|
|
- memset ( download, 0, sizeof ( *download ) );
|
88
|
|
- download->data = data;
|
89
|
|
- download->len = len;
|
90
|
|
- async_init ( &download->async, &download_async_operations, parent );
|
91
|
|
-
|
92
|
|
- /* Parse the URI */
|
93
|
|
- download->uri = parse_uri ( uri_string );
|
94
|
|
- if ( ! download->uri ) {
|
95
|
|
- rc = -ENOMEM;
|
96
|
|
- goto err;
|
97
|
|
- }
|
98
|
|
-
|
99
|
|
- /* Allocate an expandable buffer to hold the file */
|
100
|
|
- if ( ( rc = ebuffer_alloc ( &download->buffer, 0 ) ) != 0 )
|
101
|
|
- goto err;
|
102
|
|
-
|
103
|
|
- /* Identify the download protocol */
|
104
|
|
- download->protocol = find_protocol ( download->uri->scheme );
|
105
|
|
- if ( ! download->protocol ) {
|
106
|
|
- DBG ( "No such protocol \"%s\"\n", download->uri->scheme );
|
107
|
|
- rc = -ENOTSUP;
|
108
|
|
- goto err;
|
109
|
|
- }
|
110
|
|
-
|
111
|
|
- /* Start the actual download */
|
112
|
|
- if ( ( rc = download->protocol->start_download ( download->uri,
|
113
|
|
- &download->buffer, &download->async ) ) != 0 ) {
|
114
|
|
- DBG ( "Could not start \"%s\" download: %s\n",
|
115
|
|
- download->uri->scheme, strerror ( rc ) );
|
116
|
|
- goto err;
|
117
|
|
- }
|
118
|
|
-
|
119
|
|
- return 0;
|
120
|
|
-
|
121
|
|
- err:
|
122
|
|
- async_uninit ( &download->async );
|
123
|
|
- ufree ( download->buffer.addr );
|
124
|
|
- uri_put ( download->uri );
|
125
|
|
- free ( download );
|
126
|
|
- return rc;
|
127
|
|
-}
|
128
|
|
-
|
129
|
|
-/**
|
130
|
|
- * Handle download termination
|
131
|
|
- *
|
132
|
|
- * @v async Download asynchronous operation
|
133
|
|
- * @v signal SIGCHLD
|
134
|
|
- */
|
135
|
|
-static void download_sigchld ( struct async *async,
|
136
|
|
- enum signal signal __unused ) {
|
137
|
|
- struct download *download =
|
138
|
|
- container_of ( async, struct download, async );
|
139
|
|
- int rc;
|
140
|
|
-
|
141
|
|
- /* Reap child */
|
142
|
|
- async_wait ( async, &rc, 1 );
|
143
|
|
-
|
144
|
|
- /* Clean up */
|
145
|
|
- if ( rc == 0 ) {
|
146
|
|
- /* Transfer ownership of buffer to parent */
|
147
|
|
- *(download->data) = download->buffer.addr;
|
148
|
|
- *(download->len) = download->buffer.fill;
|
149
|
|
- } else {
|
150
|
|
- /* Discard the buffer */
|
151
|
|
- ufree ( download->buffer.addr );
|
152
|
|
- }
|
153
|
|
- uri_put ( download->uri );
|
154
|
|
- download->uri = NULL;
|
155
|
|
-
|
156
|
|
- /* Terminate ourselves */
|
157
|
|
- async_done ( async, rc );
|
158
|
|
-}
|
159
|
|
-
|
160
|
|
-/**
|
161
|
|
- * Free download resources
|
162
|
|
- *
|
163
|
|
- * @v async Download asynchronous operation
|
164
|
|
- */
|
165
|
|
-static void download_reap ( struct async *async ) {
|
166
|
|
- free ( container_of ( async, struct download, async ) );
|
167
|
|
-}
|
168
|
|
-
|
169
|
|
-/** Download asynchronous operations */
|
170
|
|
-static struct async_operations download_async_operations = {
|
171
|
|
- .reap = download_reap,
|
172
|
|
- .signal = {
|
173
|
|
- [SIGCHLD] = download_sigchld,
|
174
|
|
- [SIGUPDATE] = SIG_IGN,
|
175
|
|
- },
|
176
|
|
-};
|