Added extracting from bz2 archives
[mdictionary] / src / manager / src / untar.c
1 #include <untar.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <bzlib.h>
6 #include <sys/stat.h>
7 #include <glib-2.0/glib.h>
8
9 #define BLOCK_SIZE 512
10 #define BUFFER_SIZE BLOCK_SIZE*32
11 #define ASCII_NR(NR) (NR + 0x30)
12
13 typedef struct _TarHeader
14 {
15         gchar name[100];
16         gchar mode[8];
17         gchar uid[8];
18         gchar gid[8];
19         gchar size[12];
20         gchar mtime[12];
21         gchar chksum[8];
22         gchar typeflag;
23         gchar linkname[100];
24         gchar magic[6];
25         gchar version[2];
26         gchar uname[32];
27         gchar gname[32];
28         gchar devmajor[8];
29         gchar devminor[8];
30         gchar prefix[155];
31         gchar padding[12];
32         gchar *gnu_longname;
33         gchar *gnu_longlink;
34 } TarHeader;
35
36 typedef enum _RecordType
37 {
38         File = ASCII_NR (0),
39         ARCHLINK = ASCII_NR (1),
40         SYMLINK = ASCII_NR (2),
41         CHARDEV = ASCII_NR (3),
42         BLOCKDEV = ASCII_NR (4),
43         Dir = ASCII_NR (5),
44         FIFO = ASCII_NR (6),
45         RESERVED = ASCII_NR (7)
46 } RecordType;
47
48 static gint unpack_file_contents(BZFILE *bz2_file, 
49                                 TarHeader *header,
50                                 gchar *out_name);
51
52
53 static gint unpack_file_contents(BZFILE *bz2_file, 
54                                 TarHeader *header,
55                                 gchar *out_name)
56 {
57         gchar* buffer;
58         guint i;
59         FILE *file_out;
60         gulong length;
61         guint result;
62         gint bzerror;
63         
64         file_out = fopen(out_name, "w");
65         
66         if (file_out == NULL) return -1;
67         
68         sscanf(header->size, "%12lo", &length);
69         printf ("File size: %ld\n", length);
70         
71         for (i=0; i < (length / BLOCK_SIZE); ++i)
72         {
73                 buffer = (gchar*) g_try_malloc (BLOCK_SIZE * sizeof(gchar));
74                 
75                 result = BZ2_bzRead ( &bzerror, bz2_file, buffer, BLOCK_SIZE *
76                                 sizeof (gchar));
77                 
78                 fwrite (buffer, BLOCK_SIZE * sizeof(gchar), 1, file_out);
79                 g_free (buffer);
80         };
81                 
82         i = length % BLOCK_SIZE;
83                                 
84         if (i != 0)
85         {
86                 buffer = (gchar*) g_try_malloc (BLOCK_SIZE * sizeof(gchar));
87                 
88                 if (buffer == NULL)
89                 {
90                         printf ("Memory not allocated");
91                         return -1;
92                 };
93                 
94                 result = BZ2_bzRead(&bzerror, bz2_file, buffer, 
95                                 BLOCK_SIZE * sizeof(gchar));
96                 
97                 if (bzerror == BZ_OK)
98                 {
99                         fwrite (buffer, i * sizeof(gchar), 1, file_out);
100                 }
101                 
102                 else 
103                 {
104                         printf ("bzerror = %d", bzerror);
105                         return -1;
106                 };
107                 
108                 g_free(buffer);
109                 
110         };
111                                 
112         fclose(file_out);
113         
114         return 0;
115 };
116
117 gint decompress_file (gchar *in_file, gchar *out_path)
118 {
119         FILE *file;
120         BZFILE  *bz2_file;
121         guint result;
122         TarHeader* header;
123         gint bzerror;
124         
125         header = (TarHeader*) g_try_malloc (BLOCK_SIZE * sizeof(gchar));
126         
127         if (header == NULL) printf ("\nCould not allocate memory\n");
128         
129         file = fopen (in_file, "rb");
130         
131         if (file != NULL)
132
133         {
134                 bz2_file = BZ2_bzReadOpen (&bzerror, file, 0, 0, NULL, 0);
135
136                 if ( bzerror != BZ_OK ) 
137                 {
138                         BZ2_bzReadClose ( &bzerror, bz2_file );
139                         printf ("There was an error while reading the compressed file\n");
140                 }
141                 
142                 bzerror = BZ_OK;
143                 while (1) 
144                 {
145                         
146                         result = BZ2_bzRead ( &bzerror, bz2_file, header, 
147                                                BLOCK_SIZE * sizeof (char));
148                         
149 //                      printf ("Jestem\n");
150                         
151                         if ( bzerror == BZ_OK )
152                         {
153                                 if (strlen (header->name) == 0)
154                                 {
155                                         printf ("\nFilename length is 0, exitting\n");
156                                         break;
157                                 };
158                                 
159                                 printf ("Name: %s\n", header->name);
160                                 printf ("Prefix: %s\n", header->prefix);
161                                 
162
163                                 gchar *temp = g_strconcat (out_path,
164                                                         header->name, NULL);
165                                 
166                                 switch (header->typeflag)
167                                 {
168                                         case File:
169                                                 printf ("File\n");
170                                                 unpack_file_contents (bz2_file, 
171                                                         header, temp);
172                                                 break;
173                                                 
174                                         case Dir:
175                                                 
176                                                 printf ("Dir %s\n", temp);
177                                                 if (mkdir (temp, S_IRUSR|
178                                                         S_IWUSR|S_IXUSR) != 0)
179                                                 {
180                                                         printf ("Couldn't create directory %s", 
181                                                                temp);
182                                                 };
183                                                 
184                                                 
185                                                 break;
186                                                 
187                                         default:
188                                                 printf ("Only files and dirs can be unpacked");
189                                 }
190                                 
191                                 g_free (temp);
192                                 
193                         }
194                                 
195                         else if ( bzerror != BZ_STREAM_END )
196                         {
197                                 printf ("\nBZ2 READ_CLOSE(stream end) %d\n", bzerror);
198                                 BZ2_bzReadClose ( &bzerror, bz2_file );
199                                 break;
200                         }
201                         
202                         else 
203                         {
204                                 printf ("\nExitting, error nr %d\n", bzerror);
205                                 BZ2_bzReadClose ( &bzerror, bz2_file );
206                                 break;
207                         };
208                         
209                 };
210                 
211         }
212         else 
213         {
214                 printf ("There was an error while trying to read the archive file");
215                 return -100;
216         };
217         
218         return 100;
219         
220         fclose (file);
221 };