summaryrefslogtreecommitdiff
path: root/TAO/CIAO/DAnCE/new_RepositoryManager/ZIP_Wrapper.cpp
blob: 1177a6157002ebeb40a924c3967f5b0904cc2180 (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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
// $Id$

///====================================================================
//@filename: ZIP_Wrapper.cpp
//@Author: Stoyan Paunov	spaunov@isis.vanderbilt.edu
//
//@Purpose: to provide a wrapper around ZZIPlib for easy handling of
//			ZIP archives. This wrapper can me used as an auxiliary 
//			class that allows a program to become ZIP-aware



#include "ace/Containers_T.h"		//for ACE_Double_Linked_List
#include "ace/Message_Block.h"		//for ACE_Message_Block

#include "ace/OS_NS_fcntl.h"	  //for open
#include "ace/OS_NS_unistd.h"	  //for close
#include "ace/OS_NS_sys_stat.h"   //for filesize and mkdir

#include <string>
#include <memory>				  //for auto_ptr


/////////////////////////////////////////////////////////////////////////////
//NOTE: some #defines problems with zzip & ACE - put these 2 lines on top!!!!
/////////////////////////////////////////////////////////////////////////////
#include "zziplib.h"				//for ZZIP
#include "ZIP_Wrapper.h"


//ZIP_File_Info constructor
ZIP_File_Info::ZIP_File_Info (char* name, size_t size) 
	: name_ (name), 
	  size_ (size),
	  next_ (0),
	  prev_ (0)
{
}

//ZIP_File_Info default constructor
ZIP_File_Info::ZIP_File_Info () 
	: name_ (""), 
	  size_ (0),
	  next_ (0),
	  prev_ (0)
{
}


//get a list of the files in the archive
size_t ZIP_Wrapper::file_list_info (char* zip_name, ACE_Double_Linked_List<ZIP_File_Info> &list)
{
	size_t num = 0;					//number of files in archive
	ZZIP_DIR * dir;					//pointer to a zip archive
    ZZIP_DIRENT * dir_entry;		//pointer to a file within the archive

	//open the zip archive
    dir = zzip_opendir(zip_name);
    
	if (!dir)
	  return false;

	//read each dir entry and show one line of info per file
    while (dir_entry = zzip_readdir (dir))
	{
		//retrieve the name of the file
		char* name = dir_entry->d_name;

		//remove the subpath part if any		NOTE: Lunux style assumed, need to check
		//while(char* next = strstr(name, "/"))
		//	name = next + 1;

		list.insert_tail (new ZIP_File_Info (name, dir_entry->st_size));
	}

	zzip_closedir(dir);
	return 0;
}

//get file and store it into an ACE_Message_Block
bool ZIP_Wrapper::get_file (char* accessor, ACE_Message_Block &file)
{
	bool return_code = true;

	ZZIP_FILE* zip_file = zzip_open (accessor, O_RDONLY|O_BINARY);

    if (! zip_file)
		return false;
	
	int num_read;
	file.size(BUFSIZ);
	ACE_Message_Block* head = &file;

	// read chunks of 16 bytes into buf and print them to stdout
    while (0 < (num_read = zzip_read(zip_file, head->wr_ptr(), head->size())))
    {
		head->wr_ptr (num_read);
		head->cont (new ACE_Message_Block (BUFSIZ));
		head = head->cont ();
	}

	if (num_read == -1) 
		return_code = false;

	zzip_file_close (zip_file);
	
	return return_code;
}


bool ZIP_Wrapper::get_file (char* archive_path, char* filename, ACE_Message_Block &file)
{
	bool return_code = true;
	ZZIP_DIR * dir;					//pointer to a zip archive

	//open the zip archive
    dir = zzip_opendir(archive_path);

	if (!dir)
	  return false;

	//get the handle to the file
	ZZIP_FILE* zip_file = zzip_file_open (dir, filename, O_RDONLY|O_BINARY);

    if (!zip_file)
		return false;
	
	int num_read;
	file.size(BUFSIZ);
	ACE_Message_Block* head = &file;

	//read the file into the ACE_Message_Block
    while (0 < (num_read = zzip_read(zip_file, head->wr_ptr(), head->size())))
    {
		head->wr_ptr (num_read);
		head->cont (new ACE_Message_Block (BUFSIZ));
		head = head->cont ();
	}

	if (num_read == -1) 
		return_code = false;

	zzip_file_close (zip_file);
	zzip_closedir(dir);
	
	return return_code;
}


//uncompress
//the uncompress format will be
//mkdir(name of zip archive)
//store all files in that directory.
//the path is assumed to be an existing directory
bool ZIP_Wrapper::uncompress (char* zip_archive, char* path)
{
	ZZIP_DIR * dir;					//pointer to a zip archive
    ZZIP_DIRENT * dir_entry;		//pointer to a file within the archive
    ZZIP_FILE* file;				//pointer to a zip file within an archive

	//open the zip archive
    dir = zzip_opendir(zip_archive);
    
	if (!dir)
	  return false;

	//??????
	//check if a directory with the name if the archive exists
	//If not, create it. Else, existing files will be truncated upon open.
	//??????

	//get the name of the archive
	std::string arch_dir (path);
	arch_dir += "/";
	arch_dir += zip_archive;
	arch_dir[arch_dir.length () - 4] = '\0';		//NOTE: Assumes .zip extension

	//create directory
	ACE_OS::mkdir(arch_dir.c_str());				//if dir exists -1 is returned and ignored

	//read each dir entry and show one line of info per file
    while (dir_entry = zzip_readdir (dir))
	{
		//retrieve the name of the file
		char* name = dir_entry->d_name;

		//remove the subpath part if any		NOTE: Lunux style assumed, need to check
		while(char* next = strstr(name, "/"))
			name = next + 1;

		//open a zip handle
		file = zzip_file_open(dir, dir_entry->d_name, O_RDONLY|O_BINARY);
		if (!file)
			return false;

		//allocate buffer

		//TODO: change to ACE_NEW_RETURN
		std::auto_ptr<char> buffer;
		buffer.reset ( new char [dir_entry->st_size + 1]);
		
		//read in the data
		zzip_read(file, &(*buffer), dir_entry->st_size);

		//close the zip handle
		zzip_file_close (file);

		//create file name + path to open
		std::string file_path (arch_dir.c_str ());		//NOTE: need the c-style char to stop at '\0'
		file_path += "/";
		file_path += name;

		//print out the file to be uncompressed
		ACE_OS::write(ACE_STDOUT, file_path.c_str (), file_path.length () );
		ACE_OS::write(ACE_STDOUT, "\n", 1);

	   // Open a file handle to the local filesystem
       ACE_HANDLE handle = ACE_OS::open (file_path.c_str (), _O_CREAT | _O_TRUNC | O_WRONLY);
       if (handle == ACE_INVALID_HANDLE)
         ACE_ERROR_RETURN ((LM_ERROR,
                           ACE_TEXT ("%p\n"),
                           ACE_TEXT ("[uncompress] file creation error")),
                           0);

	   //write the uncompressed data to the file
	   if (ACE_OS::write (handle, &(*buffer), dir_entry->st_size) == -1)
        ACE_ERROR_RETURN ((LM_ERROR,
                           ACE_TEXT ("%p\n"),
                           ACE_TEXT ("[uncompress] file write error")),
                           0);

	   // Close the file handle
       ACE_OS::close (handle);

	   //free buffer
	   //TODO: check if auto_ptr has a fxn to release the memory before scope is exited
		//delete [] buffer;

	}

	zzip_closedir(dir);
	return true;
}