~ubuntu-branches/ubuntu/hoary/libextractor/hoary

« back to all changes in this revision

Viewing changes to src/plugins/ole2/gsf-input-memory.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2004-10-30 23:50:00 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20041030235000-poix4e5mzhmzkpbk
Tags: 0.3.10-2
* Added fix from cvs for various Sparc64 problems (Closes #278905).
* Added workaround from cvs for re-load glib problem of OLE2 extractor.
* debian/watch added.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 
2
/*
 
3
 * gsf-input-memory.c: 
 
4
 *
 
5
 * Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or
 
8
 * modify it under the terms of version 2.1 of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU Lesser General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 
19
 * USA
 
20
 */
 
21
 
 
22
#include "platform.h"
 
23
#include <string.h>
 
24
#include "gsf-input-memory.h"
 
25
#include "gsf-input-impl.h"
 
26
#include "gsf-impl-utils.h"
 
27
#include "gsf-utils.h"
 
28
#include "gsf-shared-memory.h"
 
29
 
 
30
#ifdef HAVE_MMAP
 
31
#if defined(FREEBSD) || defined(__FreeBSD__)
 
32
/* We must keep the file open while pages are mapped.  */
 
33
/* http://www.freebsd.org/cgi/query-pr.cgi?pr=48291 */
 
34
#define HAVE_BROKEN_MMAP
 
35
#endif
 
36
#endif
 
37
 
 
38
static GObjectClass *parent_class;
 
39
 
 
40
struct _GsfInputMemory {
 
41
        GsfInput parent;
 
42
        GsfSharedMemory *shared;
 
43
#ifdef HAVE_BROKEN_MMAP
 
44
        int fd;
 
45
#endif
 
46
};
 
47
typedef GsfInputClass GsfInputMemoryClass;
 
48
 
 
49
/**
 
50
 * gsf_input_memory_new:
 
51
 * @buf: The input bytes
 
52
 * @length: The length of @buf
 
53
 * @needs_free: Whether you want this memory to be free'd at object destruction
 
54
 *
 
55
 * Returns: A new #GsfInputMemory
 
56
 */
 
57
GsfInput *
 
58
gsf_input_memory_new (guint8 const *buf, gsf_off_t length, gboolean needs_free)
 
59
{
 
60
        GsfInputMemory *mem = g_object_new (GSF_INPUT_MEMORY_TYPE, NULL);
 
61
        if (mem == NULL)
 
62
                return NULL;
 
63
        mem->shared = gsf_shared_memory_new ((void *)buf, length, needs_free);
 
64
        gsf_input_set_size (GSF_INPUT (mem), length);
 
65
        return GSF_INPUT (mem);
 
66
}
 
67
 
 
68
/**
 
69
 * gsf_input_memory_new_clone:
 
70
 * @buf: The input bytes
 
71
 * @length: The length of @buf
 
72
 *
 
73
 * Returns: A new #GsfInputMemory
 
74
 */
 
75
GsfInput *
 
76
gsf_input_memory_new_clone (guint8 const *buf, gsf_off_t length)
 
77
{       
 
78
        GsfInputMemory *mem = NULL;
 
79
        guint8 * cpy = g_try_malloc (length * sizeof (guint8));
 
80
        if (cpy == NULL)
 
81
                return NULL;
 
82
 
 
83
        memcpy (cpy, buf, length);
 
84
        mem = g_object_new (GSF_INPUT_MEMORY_TYPE, NULL);
 
85
        if (mem == NULL)
 
86
                return NULL;
 
87
        mem->shared = gsf_shared_memory_new ((void *)cpy, length, TRUE);
 
88
        gsf_input_set_size (GSF_INPUT (mem), length);
 
89
        return GSF_INPUT (mem);
 
90
}
 
91
 
 
92
static void
 
93
gsf_input_memory_finalize (GObject *obj)
 
94
{
 
95
        GsfInputMemory *mem = (GsfInputMemory *) (obj);
 
96
 
 
97
        if (mem->shared)
 
98
                g_object_unref (G_OBJECT (mem->shared));
 
99
 
 
100
#ifdef HAVE_BROKEN_MMAP
 
101
        if (mem->fd != -1)
 
102
                close (mem->fd);
 
103
#endif
 
104
 
 
105
        parent_class->finalize (obj);
 
106
}
 
107
 
 
108
static GsfInput *
 
109
gsf_input_memory_dup (GsfInput *src_input, GError **err)
 
110
{
 
111
        GsfInputMemory const *src = (GsfInputMemory *) (src_input);
 
112
        GsfInputMemory *dst = g_object_new (GSF_INPUT_MEMORY_TYPE, NULL);
 
113
        if (dst == NULL)
 
114
                return NULL;
 
115
        (void) err;
 
116
 
 
117
        dst->shared = src->shared;
 
118
        g_object_ref (G_OBJECT (dst->shared));
 
119
 
 
120
#ifdef HAVE_BROKEN_MMAP
 
121
        if (src->fd != -1)
 
122
                dst->fd = dup (src->fd);
 
123
#endif
 
124
 
 
125
        return GSF_INPUT (dst);
 
126
}
 
127
 
 
128
static guint8 const *
 
129
gsf_input_memory_read (GsfInput *input, size_t num_bytes, guint8 *optional_buffer)
 
130
{
 
131
        GsfInputMemory *mem = (GsfInputMemory *) (input);
 
132
        guchar const *src = mem->shared->buf;
 
133
 
 
134
        if (src == NULL)
 
135
                return NULL;
 
136
        if (optional_buffer) {
 
137
                memcpy (optional_buffer, src + input->cur_offset, num_bytes);
 
138
                return optional_buffer;
 
139
        } else
 
140
                return src + input->cur_offset;
 
141
}
 
142
 
 
143
static gboolean
 
144
gsf_input_memory_seek (G_GNUC_UNUSED GsfInput *input,
 
145
                       G_GNUC_UNUSED gsf_off_t offset,
 
146
                       G_GNUC_UNUSED GSeekType whence)
 
147
{
 
148
        return FALSE;
 
149
}
 
150
 
 
151
static void
 
152
gsf_input_memory_init (GObject *obj)
 
153
{
 
154
        GsfInputMemory *mem = (GsfInputMemory *) (obj);
 
155
        mem->shared = NULL;
 
156
#ifdef HAVE_BROKEN_MMAP
 
157
        mem->fd = -1;
 
158
#endif
 
159
}
 
160
 
 
161
static void
 
162
gsf_input_memory_class_init (GObjectClass *gobject_class)
 
163
{
 
164
        GsfInputClass *input_class = GSF_INPUT_CLASS (gobject_class);
 
165
 
 
166
        gobject_class->finalize = gsf_input_memory_finalize;
 
167
        input_class->Dup        = gsf_input_memory_dup;
 
168
        input_class->Read       = gsf_input_memory_read;
 
169
        input_class->Seek       = gsf_input_memory_seek;
 
170
 
 
171
        parent_class = g_type_class_peek_parent (gobject_class);
 
172
}
 
173
 
 
174
GSF_CLASS (GsfInputMemory, gsf_input_memory,
 
175
           gsf_input_memory_class_init, gsf_input_memory_init,
 
176
           GSF_INPUT_TYPE)
 
177
 
 
178
/***************************************************************************/
 
179
 
 
180
#ifdef HAVE_MMAP
 
181
 
 
182
#include <unistd.h>
 
183
#include <sys/mman.h>
 
184
#include <sys/types.h>
 
185
#include <sys/stat.h>
 
186
#include <fcntl.h>
 
187
#include <errno.h>
 
188
 
 
189
#ifndef PROT_READ
 
190
#define PROT_READ 0x1
 
191
#endif
 
192
 
 
193
#if !defined(MAP_FAILED) || defined(__osf__)
 
194
/* Someone needs their head examined - BSD ? */
 
195
#       define MAP_FAILED ((void *)-1)
 
196
#endif
 
197
#endif
 
198
     
 
199
/**
 
200
 * gsf_input_mmap_new:
 
201
 * @filename: The file on disk that you want to mmap
 
202
 * @err: A #GError, or optionally %null
 
203
 *
 
204
 * Returns: A new #GsfInputMemory
 
205
 */
 
206
GsfInput *
 
207
gsf_input_mmap_new (char const *filename, GError **err)
 
208
{
 
209
#ifdef HAVE_MMAP
 
210
        GsfInputMemory *mem;
 
211
        guint8 *buf = NULL;
 
212
        struct stat st;
 
213
        int fd;
 
214
        size_t size;
 
215
 
 
216
        fd = open (filename, O_RDONLY);
 
217
        if (fd < 0 || fstat (fd, &st) < 0) {
 
218
                if (err != NULL) {
 
219
                        char *utf8name = gsf_filename_to_utf8 (filename, FALSE);
 
220
                        *err = g_error_new (gsf_input_error (), 0,
 
221
                                "%s: %s", utf8name, g_strerror (errno));
 
222
                        g_free (utf8name);
 
223
                }
 
224
                if (fd >= 0) close (fd);
 
225
                return NULL;
 
226
        }
 
227
 
 
228
        if (!S_ISREG (st.st_mode)) {
 
229
                if (err != NULL) {
 
230
                        char *utf8name = gsf_filename_to_utf8 (filename, FALSE);
 
231
                        *err = g_error_new (gsf_input_error (), 0,
 
232
                                "%s: Is not a regular file", utf8name);
 
233
                        g_free (utf8name);
 
234
                }
 
235
                close (fd);
 
236
                return NULL;
 
237
        }
 
238
        
 
239
        size = (size_t) st.st_size;
 
240
        if ((off_t) size != st.st_size) { /* Check for overflow */
 
241
                if (err != NULL) {
 
242
                        char *utf8name = gsf_filename_to_utf8 (filename, FALSE);
 
243
                        *err = g_error_new (gsf_input_error (), 0,
 
244
                                "%s: %s", utf8name,
 
245
                                "File too large to be memory mapped");
 
246
                        g_free (utf8name);
 
247
                }
 
248
                close (fd);
 
249
                return NULL;
 
250
        }
 
251
        buf = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, (off_t) 0);
 
252
        if (buf == MAP_FAILED) {
 
253
                if (err != NULL) {
 
254
                        char *utf8name = gsf_filename_to_utf8 (filename, FALSE);
 
255
                        *err = g_error_new (gsf_input_error (), 0,
 
256
                                "%s: %s", utf8name, g_strerror (errno));
 
257
                        g_free (utf8name);
 
258
                }
 
259
                close (fd);
 
260
                return NULL;
 
261
        }
 
262
 
 
263
        mem = g_object_new (GSF_INPUT_MEMORY_TYPE, NULL);
 
264
        if (mem == NULL)
 
265
                return NULL;
 
266
        mem->shared = gsf_shared_memory_mmapped_new (buf, (gsf_off_t) size);
 
267
        gsf_input_set_size (GSF_INPUT (mem), (gsf_off_t) size);
 
268
        gsf_input_set_name (GSF_INPUT (mem), filename);
 
269
 
 
270
#ifdef HAVE_BROKEN_MMAP
 
271
        mem->fd = fd;
 
272
#else
 
273
        close (fd);
 
274
#endif
 
275
 
 
276
        return GSF_INPUT (mem);
 
277
#else
 
278
#ifdef __GNUC__
 
279
#warning MMAP Unsupported
 
280
#endif
 
281
        (void)filename;
 
282
        if (err != NULL)
 
283
                *err = g_error_new (gsf_input_error (), 0,
 
284
                        "MMAP Unsupported");
 
285
        return NULL;
 
286
#endif
 
287
}