Bootstrap of 'captive-install-acquire' for W32 modules acquiration process.
[captive.git] / src / install / acquire / moduriload.c
1 /* $Id$
2  * W32 disk modules finder for acquiration installation utility
3  * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; exactly version 2 of June 1991 is required
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20 #include "config.h"
21
22 #include "moduriload.h" /* self */
23 #include <glib/gmessages.h>
24 #include <mntent.h>
25 #include <glib/ghash.h>
26 #include <glib/glist.h>
27 #include <libgnomevfs/gnome-vfs-uri.h>
28 #include "../libcaptive-install/proc_partitions.h"
29 #include "main.h"
30 #include <string.h>
31 #include "captivemodid.h"
32 #include "cabinet.h"
33 #include <libgnomevfs/gnome-vfs-ops.h>
34 #include <libgnomevfs/gnome-vfs-directory.h>
35
36
37 /* Config: */
38 #define MAX_FILE_LOAD_LENGTH 5000000    /* Otherwise use cabextract-over-http. */
39
40
41 static void mod_uri_load_module_from_memory
42                 (struct captivemodid_module *module,gconstpointer file_base,size_t file_length,GnomeVFSURI *uri)
43 {
44 gchar *uri_text;
45
46         g_return_if_fail(module!=NULL);
47         g_return_if_fail(file_base!=NULL);
48         g_return_if_fail(uri!=NULL);
49
50         uri_text=gnome_vfs_uri_to_string(uri,GNOME_VFS_URI_HIDE_PASSWORD);
51         g_message("type=%s,id:%s: %s",module->type,module->id,uri_text);
52         g_free(uri_text);
53 }
54
55 void mod_uri_load_file_from_memory(gconstpointer file_base,size_t file_length,GnomeVFSURI *uri)
56 {
57 gchar *file_md5;
58 struct captivemodid_module *module;
59
60         g_return_if_fail(file_base!=NULL);
61         g_return_if_fail(uri!=NULL);
62
63         file_md5=calc_md5(file_base,file_length);
64         if (!(module=captivemodid_module_md5_lookup(file_md5)))
65                 goto fail_free_file_md5;
66
67         if (strcmp("cabinet",module->type))
68                 mod_uri_load_module_from_memory(module,file_base,file_length,uri);
69         else {
70                 struct acquire_cabinet *acquire_cabinet;
71                 /* acquire_cabinet_load() will call mod_uri_load_module_from_memory(): */
72                 acquire_cabinet=acquire_cabinet_new_from_memory(file_base,file_length,uri);
73                 acquire_cabinet_load(acquire_cabinet);
74                 acquire_cabinet_free(acquire_cabinet);
75                 }
76
77 fail_free_file_md5:
78         g_free(file_md5);
79 }
80
81 static void mod_uri_load_file_handle_to_memory(GnomeVFSHandle *handle,GnomeVFSFileInfo *file_info,GnomeVFSURI *uri)
82 {
83 guint8 *file_buffer,file_tail_check;
84 GnomeVFSFileSize bytes_read;
85 GnomeVFSResult errvfsresult;
86
87         g_return_if_fail(handle!=NULL);
88         g_return_if_fail(file_info!=NULL);
89         g_return_if_fail(uri!=NULL);
90
91         /* gnome_vfs_read_entire_file() reads the file by chunks although
92          * it does not need to know the file size.
93          */
94         file_buffer=g_malloc(file_info->size);
95         
96         errvfsresult=gnome_vfs_read(handle,file_buffer,file_info->size,&bytes_read);
97         if (errvfsresult!=GNOME_VFS_OK || bytes_read!=file_info->size)
98                 goto fail_free_file_buffer;
99         errvfsresult=gnome_vfs_read(handle,&file_tail_check,1,NULL);
100         if (errvfsresult!=GNOME_VFS_ERROR_EOF)
101                 goto fail_free_file_buffer;
102         mod_uri_load_file_from_memory(file_buffer,file_info->size,uri);
103
104 fail_free_file_buffer:
105         g_free(file_buffer);
106 }
107
108 static void mod_uri_load_file_handle_remote_cabinet(GnomeVFSHandle *handle,GnomeVFSFileInfo *file_info,GnomeVFSURI *uri)
109 {
110 struct acquire_cabinet *acquire_cabinet;
111
112         g_return_if_fail(handle!=NULL);
113         g_return_if_fail(file_info!=NULL);
114         g_return_if_fail(uri!=NULL);
115
116         acquire_cabinet=acquire_cabinet_new_from_handle(handle,file_info,uri);
117         /* acquire_cabinet_load() will call mod_uri_load_module_from_memory(): */
118         acquire_cabinet_load(acquire_cabinet);
119         acquire_cabinet_free(acquire_cabinet);
120 }
121
122 static void mod_uri_load_file(GnomeVFSURI *uri)
123 {
124 GnomeVFSResult errvfsresult;
125 GnomeVFSFileInfo file_info_local;
126 GnomeVFSHandle *handle;
127
128         g_return_if_fail(uri!=NULL);
129
130         if (GNOME_VFS_OK!=(errvfsresult=gnome_vfs_open_uri(&handle,uri,GNOME_VFS_OPEN_READ)))
131                 goto fail;
132         if (GNOME_VFS_OK!=(errvfsresult=gnome_vfs_get_file_info_from_handle(handle,&file_info_local,GNOME_VFS_FILE_INFO_DEFAULT)))
133                 goto fail_close_handle;
134         if (file_info_local.type!=GNOME_VFS_FILE_TYPE_REGULAR) {
135                 errvfsresult=GNOME_VFS_ERROR_WRONG_FORMAT;
136                 goto fail_close_handle;
137                 }
138         if (!(file_info_local.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE)) {
139                 errvfsresult=GNOME_VFS_ERROR_WRONG_FORMAT;
140                 goto fail_close_handle;
141                 }
142         if (!captivemodid_module_length_is_valid(file_info_local.size)) {
143                 errvfsresult=GNOME_VFS_ERROR_WRONG_FORMAT;
144                 goto fail_close_handle;
145                 }
146         if (file_info_local.size<=MAX_FILE_LOAD_LENGTH)
147                 mod_uri_load_file_handle_to_memory(handle,&file_info_local,uri);
148         else
149                 mod_uri_load_file_handle_remote_cabinet(handle,&file_info_local,uri);
150         errvfsresult=GNOME_VFS_OK;
151         /* PASSTHRU */
152 fail_close_handle:
153         gnome_vfs_close(handle);
154 fail:;
155 }
156
157 static gboolean mod_uri_load_directory_visit_func
158                 (const gchar *rel_path,GnomeVFSFileInfo *info,gboolean recursing_will_loop,GnomeVFSURI *root_uri /* data */,
159                 gboolean *recurse)
160 {
161         g_return_val_if_fail(rel_path!=NULL,FALSE);
162         g_return_val_if_fail(info!=NULL,FALSE);
163         g_return_val_if_fail(root_uri!=NULL,FALSE);
164         g_return_val_if_fail(recurse!=NULL,FALSE);
165
166         *recurse=FALSE;
167
168         switch (info->type) {
169                 case GNOME_VFS_FILE_TYPE_REGULAR: {
170 GnomeVFSURI *file_uri;
171
172                         file_uri=gnome_vfs_uri_append_path(root_uri,rel_path);
173                         mod_uri_load_file(file_uri);
174                         gnome_vfs_uri_unref(file_uri);
175                         } break;
176                 case GNOME_VFS_FILE_TYPE_DIRECTORY: {
177 GnomeVFSURI *directory_uri;
178 GnomeVFSDirectoryHandle *directory_handle;
179
180                         /* Never set '*recurse' if it would cause 'Access denied' error
181                          * as it would completely abort the upper gnome_vfs_directory_visit_uri().
182                          * Check the directory accessibility manually:
183                          */
184                         directory_uri=gnome_vfs_uri_append_path(root_uri,rel_path);
185                         if (GNOME_VFS_OK==gnome_vfs_directory_open_from_uri(&directory_handle,directory_uri,GNOME_VFS_FILE_INFO_DEFAULT)) {
186                                 *recurse=TRUE;
187                                 gnome_vfs_directory_close(directory_handle);    /* errors ignored */
188                                 }
189                         gnome_vfs_uri_unref(directory_uri);
190                         } break;
191                 default:;
192                 }
193
194         return TRUE;    /* continue traversal */
195 }
196
197 static void mod_uri_load_directory(GnomeVFSURI *uri)
198 {
199 GnomeVFSResult errvfsresult;
200
201         g_return_if_fail(uri!=NULL);
202
203         errvfsresult=gnome_vfs_directory_visit_uri(uri,
204                         GNOME_VFS_FILE_INFO_DEFAULT,    /* info_options */
205                         GNOME_VFS_DIRECTORY_VISIT_SAMEFS,       /* visit_options; 'GNOME_VFS_DIRECTORY_VISIT_LOOPCHECK'? */
206                         (GnomeVFSDirectoryVisitFunc)mod_uri_load_directory_visit_func,
207                         uri);   /* data */
208         if (errvfsresult!=GNOME_VFS_OK) {
209 gchar *uri_text;
210
211                 uri_text=gnome_vfs_uri_to_string(uri,GNOME_VFS_URI_HIDE_PASSWORD);
212                 g_warning(_("Error scanning sub-tree of \"%s\": %s"),uri_text,gnome_vfs_result_to_string(errvfsresult));
213                 g_free(uri_text);
214                 }
215 }
216
217 void mod_uri_load(GnomeVFSURI *uri)
218 {
219 GnomeVFSFileInfo file_info_local;
220 GnomeVFSResult errvfsresult;
221
222         g_return_if_fail(uri!=NULL);
223
224         if (optarg_verbose) {
225 gchar *uri_text;
226
227                 uri_text=gnome_vfs_uri_to_string(uri,GNOME_VFS_URI_HIDE_PASSWORD);
228                 g_message(_("Scanning...: %s"),uri_text);
229                 g_free(uri_text);
230                 }
231
232         file_info_local.type=GNOME_VFS_FILE_TYPE_UNKNOWN;
233         if (GNOME_VFS_OK!=(errvfsresult=gnome_vfs_get_file_info_uri(uri,&file_info_local,GNOME_VFS_FILE_INFO_DEFAULT)))
234                 return /* errvfsresult */;
235         switch (file_info_local.type) {
236                 case GNOME_VFS_FILE_TYPE_REGULAR:   return mod_uri_load_file(uri);
237                 case GNOME_VFS_FILE_TYPE_DIRECTORY: return mod_uri_load_directory(uri);
238                 default:                            return /* GNOME_VFS_ERROR_WRONG_FORMAT */;
239                 }
240         /* NOTREACHED */
241 }