~ubuntu-branches/ubuntu/utopic/mpd/utopic-proposed

« back to all changes in this revision

Viewing changes to src/archive/zzip_archive_plugin.c

  • Committer: Package Import Robot
  • Author(s): Steve Kowalik
  • Date: 2013-11-12 18:17:40 UTC
  • mfrom: (2.2.36 sid)
  • Revision ID: package-import@ubuntu.com-20131112181740-72aa4zihehoobedp
Tags: 0.18.3-1ubuntu1
* Merge from Debian unstable.  Remaining changes:
  - Add libmp3lame-dev to Build-Depends, and enable LAME.
  - Read the user for the daemon from the config file in the init script.
  - Move avahi-daemon from Suggests to Recommends.
  - Added apport hook to include user configuration file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2003-2011 The Music Player Daemon Project
3
 
 * http://www.musicpd.org
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; either version 2 of the License, or
8
 
 * (at your option) any later version.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License along
16
 
 * with this program; if not, write to the Free Software Foundation, Inc.,
17
 
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
 
 */
19
 
 
20
 
/**
21
 
  * zip archive handling (requires zziplib)
22
 
  */
23
 
 
24
 
#include "config.h"
25
 
#include "archive/zzip_archive_plugin.h"
26
 
#include "archive_api.h"
27
 
#include "archive_api.h"
28
 
#include "input_internal.h"
29
 
#include "input_plugin.h"
30
 
#include "refcount.h"
31
 
 
32
 
#include <zzip/zzip.h>
33
 
#include <glib.h>
34
 
#include <string.h>
35
 
 
36
 
struct zzip_archive {
37
 
        struct archive_file base;
38
 
 
39
 
        struct refcount ref;
40
 
 
41
 
        ZZIP_DIR *dir;
42
 
        GSList  *list;
43
 
        GSList  *iter;
44
 
};
45
 
 
46
 
static const struct input_plugin zzip_input_plugin;
47
 
 
48
 
static inline GQuark
49
 
zzip_quark(void)
50
 
{
51
 
        return g_quark_from_static_string("zzip");
52
 
}
53
 
 
54
 
/* archive open && listing routine */
55
 
 
56
 
static struct archive_file *
57
 
zzip_archive_open(const char *pathname, GError **error_r)
58
 
{
59
 
        struct zzip_archive *context = g_malloc(sizeof(*context));
60
 
        ZZIP_DIRENT dirent;
61
 
 
62
 
        archive_file_init(&context->base, &zzip_archive_plugin);
63
 
        refcount_init(&context->ref);
64
 
 
65
 
        // open archive
66
 
        context->list = NULL;
67
 
        context->dir = zzip_dir_open(pathname, NULL);
68
 
        if (context->dir  == NULL) {
69
 
                g_set_error(error_r, zzip_quark(), 0,
70
 
                            "Failed to open ZIP file %s", pathname);
71
 
                return NULL;
72
 
        }
73
 
 
74
 
        while (zzip_dir_read(context->dir, &dirent)) {
75
 
                //add only files
76
 
                if (dirent.st_size > 0) {
77
 
                        context->list = g_slist_prepend(context->list,
78
 
                                                        g_strdup(dirent.d_name));
79
 
                }
80
 
        }
81
 
 
82
 
        return &context->base;
83
 
}
84
 
 
85
 
static void
86
 
zzip_archive_scan_reset(struct archive_file *file)
87
 
{
88
 
        struct zzip_archive *context = (struct zzip_archive *) file;
89
 
        //reset iterator
90
 
        context->iter = context->list;
91
 
}
92
 
 
93
 
static char *
94
 
zzip_archive_scan_next(struct archive_file *file)
95
 
{
96
 
        struct zzip_archive *context = (struct zzip_archive *) file;
97
 
        char *data = NULL;
98
 
        if (context->iter != NULL) {
99
 
                ///fetch data and goto next
100
 
                data = context->iter->data;
101
 
                context->iter = g_slist_next(context->iter);
102
 
        }
103
 
        return data;
104
 
}
105
 
 
106
 
static void
107
 
zzip_archive_close(struct archive_file *file)
108
 
{
109
 
        struct zzip_archive *context = (struct zzip_archive *) file;
110
 
 
111
 
        if (!refcount_dec(&context->ref))
112
 
                return;
113
 
 
114
 
        if (context->list) {
115
 
                //free list
116
 
                for (GSList *tmp = context->list; tmp != NULL; tmp = g_slist_next(tmp))
117
 
                        g_free(tmp->data);
118
 
                g_slist_free(context->list);
119
 
        }
120
 
        //close archive
121
 
        zzip_dir_close (context->dir);
122
 
 
123
 
        g_free(context);
124
 
}
125
 
 
126
 
/* single archive handling */
127
 
 
128
 
struct zzip_input_stream {
129
 
        struct input_stream base;
130
 
 
131
 
        struct zzip_archive *archive;
132
 
 
133
 
        ZZIP_FILE *file;
134
 
};
135
 
 
136
 
static struct input_stream *
137
 
zzip_archive_open_stream(struct archive_file *file,
138
 
                         const char *pathname,
139
 
                         GMutex *mutex, GCond *cond,
140
 
                         GError **error_r)
141
 
{
142
 
        struct zzip_archive *context = (struct zzip_archive *) file;
143
 
        struct zzip_input_stream *zis;
144
 
        ZZIP_STAT z_stat;
145
 
 
146
 
        zis = g_new(struct zzip_input_stream, 1);
147
 
        input_stream_init(&zis->base, &zzip_input_plugin, pathname,
148
 
                          mutex, cond);
149
 
 
150
 
        zis->archive = context;
151
 
        zis->file = zzip_file_open(context->dir, pathname, 0);
152
 
        if (zis->file == NULL) {
153
 
                g_free(zis);
154
 
                g_set_error(error_r, zzip_quark(), 0,
155
 
                            "not found in the ZIP file: %s", pathname);
156
 
                return NULL;
157
 
        }
158
 
 
159
 
        zis->base.ready = true;
160
 
        //we are seekable (but its not recommendent to do so)
161
 
        zis->base.seekable = true;
162
 
 
163
 
        zzip_file_stat(zis->file, &z_stat);
164
 
        zis->base.size = z_stat.st_size;
165
 
 
166
 
        refcount_inc(&context->ref);
167
 
 
168
 
        return &zis->base;
169
 
}
170
 
 
171
 
static void
172
 
zzip_input_close(struct input_stream *is)
173
 
{
174
 
        struct zzip_input_stream *zis = (struct zzip_input_stream *)is;
175
 
 
176
 
        zzip_file_close(zis->file);
177
 
        zzip_archive_close(&zis->archive->base);
178
 
        input_stream_deinit(&zis->base);
179
 
        g_free(zis);
180
 
}
181
 
 
182
 
static size_t
183
 
zzip_input_read(struct input_stream *is, void *ptr, size_t size,
184
 
                GError **error_r)
185
 
{
186
 
        struct zzip_input_stream *zis = (struct zzip_input_stream *)is;
187
 
        int ret;
188
 
 
189
 
        ret = zzip_file_read(zis->file, ptr, size);
190
 
        if (ret < 0) {
191
 
                g_set_error(error_r, zzip_quark(), ret,
192
 
                            "zzip_file_read() has failed");
193
 
                return 0;
194
 
        }
195
 
 
196
 
        is->offset = zzip_tell(zis->file);
197
 
 
198
 
        return ret;
199
 
}
200
 
 
201
 
static bool
202
 
zzip_input_eof(struct input_stream *is)
203
 
{
204
 
        struct zzip_input_stream *zis = (struct zzip_input_stream *)is;
205
 
 
206
 
        return (goffset)zzip_tell(zis->file) == is->size;
207
 
}
208
 
 
209
 
static bool
210
 
zzip_input_seek(struct input_stream *is,
211
 
                goffset offset, int whence, GError **error_r)
212
 
{
213
 
        struct zzip_input_stream *zis = (struct zzip_input_stream *)is;
214
 
        zzip_off_t ofs = zzip_seek(zis->file, offset, whence);
215
 
        if (ofs != -1) {
216
 
                g_set_error(error_r, zzip_quark(), ofs,
217
 
                            "zzip_seek() has failed");
218
 
                is->offset = ofs;
219
 
                return true;
220
 
        }
221
 
        return false;
222
 
}
223
 
 
224
 
/* exported structures */
225
 
 
226
 
static const char *const zzip_archive_extensions[] = {
227
 
        "zip",
228
 
        NULL
229
 
};
230
 
 
231
 
static const struct input_plugin zzip_input_plugin = {
232
 
        .close = zzip_input_close,
233
 
        .read = zzip_input_read,
234
 
        .eof = zzip_input_eof,
235
 
        .seek = zzip_input_seek,
236
 
};
237
 
 
238
 
const struct archive_plugin zzip_archive_plugin = {
239
 
        .name = "zzip",
240
 
        .open = zzip_archive_open,
241
 
        .scan_reset = zzip_archive_scan_reset,
242
 
        .scan_next = zzip_archive_scan_next,
243
 
        .open_stream = zzip_archive_open_stream,
244
 
        .close = zzip_archive_close,
245
 
        .suffixes = zzip_archive_extensions
246
 
};