summaryrefslogtreecommitdiff
path: root/src/modules/loaders/loader_bz2.c
blob: 7ac225f60811e5037a80a62786d492754b6f6e82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "loader_common.h"
#include <bzlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>

#define OUTBUF_SIZE 16384
#define INBUF_SIZE 1024

static int uncompress_file (FILE *fp, int dest)
{
	BZFILE *bf;
	DATA8 outbuf[OUTBUF_SIZE];
	int bytes, error, ret = 1;

	bf = BZ2_bzReadOpen (&error, fp, 0, 0, NULL, 0);

	if (error != BZ_OK) {
		BZ2_bzReadClose (NULL, bf);
		return 0;
	}

	while (1) {
		bytes = BZ2_bzRead (&error, bf, &outbuf, OUTBUF_SIZE);

		if (error == BZ_OK || error == BZ_STREAM_END)
			write (dest, outbuf, bytes);

		if (error == BZ_STREAM_END)
			break;
		else if (error != BZ_OK) {
			ret = 0;
			break;
		}
	}

	BZ2_bzReadClose (&error, bf);

	return ret;
}

char load (ImlibImage *im, ImlibProgressFunction progress,
           char progress_granularity, char immediate_load)
{
	ImlibLoader *loader;
	FILE *fp;
	int dest, res;
	char *file, tmp[] = "/tmp/imlib2_loader_bz2-XXXXXX", *p;
	char real_ext[16];

	assert (im);

	/* make sure this file ends in ".bz2" and that there's another ext
	 * (e.g. "foo.png.bz2"
	 */
	p = strrchr(im->real_file, '.');
	if (p && p != im->real_file) {
		if (strcasecmp(p + 1, "bz2"))
			return 0;
	} else
		return 0;

	strncpy (real_ext, p - sizeof (real_ext) + 1, sizeof (real_ext));
	real_ext[sizeof (real_ext) - 1] = '\0';

	/* abort if there's no dot in the "real" filename */
	if (!strrchr (real_ext, '.'))
		return 0;

	if (!(fp = fopen (im->real_file, "rb"))) {
		return 0;
	}

	if ((dest = mkstemp (tmp)) < 0) {
		fclose (fp);
		return 0;
	}

	res = uncompress_file (fp, dest);
	fclose (fp);
	close (dest);

	if (!res) {
		unlink (tmp);
		return 0;
	}

	if (!(loader = __imlib_FindBestLoaderForFile (real_ext, 0))) {
		unlink (tmp);
		return 0;
	}

	/* remember the original filename */
	file = strdup (im->real_file);

	free (im->real_file);
	im->real_file = strdup (tmp);
	loader->load (im, progress, progress_granularity, immediate_load);

	free (im->real_file);
	im->real_file = file;
	unlink (tmp);

	return 1;
}

void formats (ImlibLoader *l)
{
	/* this is the only bit you have to change... */
	char *list_formats[] = {"bz2"};
	int i;

   /* don't bother changing any of this - it just reads this in
	* and sets the struct values and makes copies
	*/
	l->num_formats = sizeof (list_formats) / sizeof (char *);
	l->formats = malloc (sizeof (char *) * l->num_formats);

	for (i = 0; i < l->num_formats; i++)
		l->formats[i] = strdup (list_formats[i]);
}