Gave asynchronous operations approximate POSIX signal semantics. This
[people/xl0/gpxe.git] / src / usr / fetch.c
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  * Fetch file as executable/loadable image
23  *
24  */
25
26 #include <errno.h>
27 #include <vsprintf.h>
28 #include <gpxe/emalloc.h>
29 #include <gpxe/ebuffer.h>
30 #include <gpxe/image.h>
31 #include <gpxe/uri.h>
32 #include <usr/fetch.h>
33
34 #include <byteswap.h>
35 #include <gpxe/dhcp.h>
36 #include <gpxe/tftp.h>
37 #include <gpxe/http.h>
38
39 /**
40  * Fetch file
41  *
42  * @v filename          Filename to fetch
43  * @ret data            Loaded file
44  * @ret len             Length of loaded file
45  * @ret rc              Return status code
46  *
47  * Fetch file to an external buffer allocated with emalloc().  The
48  * caller is responsible for eventually freeing the buffer with
49  * efree().
50  */
51 int fetch ( const char *uri_string, userptr_t *data, size_t *len ) {
52         struct uri *uri;
53         struct buffer buffer;
54         int rc;
55
56         /* Parse the URI */
57         uri = parse_uri ( uri_string );
58         if ( ! uri ) {
59                 rc = -ENOMEM;
60                 goto err_parse_uri;
61         }
62
63         /* Allocate an expandable buffer to hold the file */
64         if ( ( rc = ebuffer_alloc ( &buffer, 0 ) ) != 0 ) {
65                 goto err_ebuffer_alloc;
66         }
67
68 #warning "Temporary pseudo-URL parsing code"
69
70         /* Retrieve the file */
71         struct async async;
72
73         int ( * download ) ( struct uri *uri, struct buffer *buffer,
74                              struct async *parent );
75
76 #if 0
77         server.sin.sin_port = htons ( TFTP_PORT );
78         udp_connect ( &tftp.udp, &server.st );
79         tftp.filename = filename;
80         tftp.buffer = &buffer;
81         aop = tftp_get ( &tftp );
82 #else
83         download = http_get;
84 #endif
85
86         async_init_orphan ( &async );
87         if ( ( rc = download ( uri, &buffer, &async ) ) != 0 )
88                 goto err;
89         uri = NULL;
90         async_wait ( &async, &rc, 1 );
91         if ( rc != 0 )
92                 goto err;
93
94         /* Fill in buffer address and length */
95         *data = buffer.addr;
96         *len = buffer.fill;
97
98         /* Release temporary resources.  The ebuffer storage is now
99          * owned by our caller, so we don't free it.
100          */
101
102         return 0;
103
104  err:
105         efree ( buffer.addr );
106  err_ebuffer_alloc:
107         free_uri ( uri );
108  err_parse_uri:
109         return rc;
110 }