00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "EDocBFD/bfd_utils.h"
00023
00024 #include "EDocBFD/Section.h"
00025 #include "EDocBFD/BFDArchive.h"
00026
00027 #include "EDoc/utils.h"
00028 #include "EDocBFD/exceptions.h"
00029 #include "EDoc/persistence_data.h"
00030
00031 #ifdef HAVE_STRING_H
00032 #include <string.h>
00033 #endif
00034
00035 #ifdef HAVE_FCNTL_H
00036 #include <fcntl.h>
00037 #endif
00038
00039 #ifdef HAVE_UNISTD_H
00040 #include <unistd.h>
00041 #endif
00042
00043 #ifdef HAVE_ERRNO_H
00044 #include <errno.h>
00045 #endif
00046
00047 #ifdef HAVE_SYS_STAT_H
00048 #include <sys/stat.h>
00049 #endif
00050
00051 namespace EDocBFD
00052 {
00053
00054
00055
00056 bool bfd_initialised = false;
00057
00058
00059 void ProcessReadBFD(std::list<EDoc::ManagedFile>& input_files,
00060 struct bfd* abfd, const EDoc::ManagedFile& filename)
00061 {
00062
00063 if (!bfd_check_format(abfd, bfd_object) &&
00064 !bfd_check_format(abfd, bfd_archive))
00065 {
00066 EDOC_THROW_EXCEPTION(BFDException, "Unknown binary format.", "");
00067 }
00068
00069 EDOC_Debug(std::cerr << "BFD Format of file: " << filename.GetFileNameRep()
00070 << " is: " << bfd_format_string(abfd->format));
00071
00072
00073 if (bfd_check_format(abfd, bfd_archive))
00074 {
00075 for (struct bfd* ibfd = bfd_openr_next_archived_file(abfd, NULL);
00076 ibfd; ibfd = bfd_openr_next_archived_file(abfd, ibfd))
00077 {
00078
00079
00080
00081
00082
00083
00084
00085 ProcessReadBFD(input_files, ibfd, filename);
00086 }
00087
00088
00089
00090
00091 return;
00092 }
00093
00094
00095 EDOC_Debug("Received object format BFD.");
00096 try
00097 {
00098 if (!abfd->sections)
00099 {
00100 EDOC_Debug("Contains no sections.");
00101 return;
00102 }
00103
00104
00105 asection* p;
00106 bool has_edoc_data = false;
00107
00108 for (p = abfd->sections; p != NULL; p = p->next)
00109 {
00110 if (strcmp(p->name, EDOC_SECTION_NAME))
00111 {
00112 continue;
00113 }
00114
00115 std::list<EDoc::ManagedFile> files(HandleEDocSection(abfd, p, filename));
00116 if (files.size())
00117 {
00118 has_edoc_data = true;
00119 EDOC_Fine("Appending: " << files.size()
00120 << " edoc files to input files list.");
00121 EDoc::Append(input_files, files);
00122 }
00123 }
00124 }
00125 catch(...)
00126 {
00127 EDOC_Fine("An error occured looking for input files.");
00128 EDoc::Erase(input_files);
00129 throw;
00130 }
00131
00132 }
00133
00134 void InitialiseBFD()
00135 {
00136 if (bfd_initialised)
00137 {
00138 bfd_init();
00139 bfd_initialised = true;
00140 }
00141 }
00142
00143 struct bfd* OpenBFDFile(std::string filename)
00144 {
00145
00146 InitialiseBFD();
00147
00148
00149 struct bfd* abfd = bfd_openr(filename.c_str(), "default");
00150 if (abfd == NULL)
00151 {
00152 bfd_error_type error_code = bfd_get_error();
00153 EDOC_THROW_EXCEPTION(BFDException, bfd_errmsg(error_code), "");
00154 }
00155
00156 try
00157 {
00158
00159 if (!bfd_check_format(abfd, bfd_object) &&
00160 !bfd_check_format(abfd, bfd_archive))
00161 {
00162 EDOC_THROW_EXCEPTION(BFDException,
00163 "Unknown binary format.", "");
00164 }
00165
00166 EDOC_Debug("BFD Format of file: " << filename
00167 << " is: " << bfd_format_string(abfd->format));
00168 }
00169 catch(...)
00170 {
00171 bfd_close(abfd);
00172 throw;
00173 }
00174
00175 return abfd;
00176 }
00177
00178 std::list<EDoc::ManagedFile> HandleEDocSection(bfd* abfd, asection* asect,
00179 const EDoc::ManagedFile& arch)
00180 {
00181 std::list<EDoc::ManagedFile> ret;
00182 Section section(abfd, asect);
00183
00184 try
00185 {
00186 while (!section.IsEof())
00187 {
00188 std::string data;
00189
00190
00191 data = section.ReadEx(4);
00192 uint32_t block_size = 0;
00193 block_size = ( ((uint32_t)((uint8_t)data[0]) << 24) |
00194 ((uint32_t)((uint8_t)data[1]) << 16) |
00195 ((uint32_t)((uint8_t)data[2]) << 8) |
00196 ((uint32_t)((uint8_t)data[3]) << 0));
00197 EDOC_Finest("Got block size: " << block_size);
00198
00199
00200 data = section.ReadEx(4);
00201 uint32_t filename_size = 0;
00202 filename_size = ( ((uint32_t)((uint8_t)data[0]) << 24) |
00203 ((uint32_t)((uint8_t)data[1]) << 16) |
00204 ((uint32_t)((uint8_t)data[2]) << 8) |
00205 ((uint32_t)((uint8_t)data[3]) << 0));
00206
00207 EDOC_Finest("Got filename size: " << filename_size);
00208 std::string filename = section.ReadEx(filename_size);
00209 EDOC_Debug("Extracted: " << filename
00210 << " of size: " << (block_size - filename_size));
00211
00212
00213 std::string outfile = EDoc::CreateTempFilename();
00214 int fd = open(outfile.c_str(), O_WRONLY, O_TRUNC);
00215 if (fd == -1)
00216 {
00217 EDOC_THROW_EXCEPTION(BFDException, "", "");
00218 }
00219
00220 std::list<std::string> id = arch.GetIdentifier();
00221 id.push_back(filename);
00222 ret.push_back(EDoc::ManagedFile(id, outfile,
00223 new ExtractedBFDFile(outfile)));
00224
00225
00226
00227 uint32_t file_size = block_size - filename_size - 8;
00228
00229 char temp[1024];
00230 size_t blocks_to_read = file_size / 1024;
00231 for (size_t i = 0; i < blocks_to_read; i++)
00232 {
00233 ssize_t result = section.ReadEx(temp, 1024);
00234 if (write(fd, temp, result) != result)
00235 {
00236 EDOC_THROW_EXCEPTION(BFDException, "", "");
00237 }
00238 }
00239
00240 if (file_size % 1024)
00241 {
00242 ssize_t result = section.ReadEx(temp, file_size % 1024);
00243 if (write(fd, temp, result) != result)
00244 {
00245 EDOC_THROW_EXCEPTION(BFDException, "", "");
00246 }
00247 }
00248
00249 close(fd);
00250 EDOC_Finest("Completed writing contents of extrated file to "
00251 "temp file.");
00252 }
00253 }
00254 catch(...)
00255 {
00256 EDOC_Debug("An error occured re-throwing.");
00257 EDoc::Erase(ret);
00258 throw;
00259 }
00260
00261 return ret;
00262 }
00263
00264 void EmbedFileInBinary(const std::string& file_to_embed,
00265 const std::string embedded_name,
00266 const std::string& binary_file,
00267 std::string section)
00268 {
00269 std::string tmpfile = EDoc::CreateTempFilename();
00270 int fd = open(tmpfile.c_str(), O_WRONLY, O_TRUNC);
00271 if (fd == -1)
00272 {
00273 EDOC_THROW_EXCEPTION(BFDException, "", "");
00274 }
00275
00276 try
00277 {
00278
00279
00280
00281
00282
00283
00284 struct stat buffer;
00285 int result = stat(file_to_embed.c_str(), &buffer);
00286 if ((result == -1) || !(buffer.st_mode & S_IFREG))
00287 {
00288 EDOC_THROW_EXCEPTION(EDoc::BugException, "", "");
00289 }
00290
00291 size_t block_size = embedded_name.size() + 8 + buffer.st_size;
00292 unsigned char c = 0;
00293
00294 c = (block_size & 0xFF000000) >> 24;
00295 result = write(fd, &c, 1);
00296 if (result != 1)
00297 {
00298 EDOC_THROW_EXCEPTION(EDoc::BugException, "", "");
00299 }
00300
00301 c = (block_size & 0x00FF0000) >> 16;
00302 result = write(fd, &c, 1);
00303 if (result != 1)
00304 {
00305 EDOC_THROW_EXCEPTION(EDoc::BugException, "", "");
00306 }
00307
00308 c = (block_size & 0x0000FF00) >> 8;
00309 result = write(fd, &c, 1);
00310 if (result != 1)
00311 {
00312 EDOC_THROW_EXCEPTION(EDoc::BugException, "", "");
00313 }
00314
00315 c = (block_size & 0x000000FF) >> 0;
00316 result = write(fd, &c, 1);
00317 if (result != 1)
00318 {
00319 EDOC_THROW_EXCEPTION(EDoc::BugException, "", "");
00320 }
00321
00322 c = (embedded_name.size() & 0xFF000000) >> 24;
00323 result = write(fd, &c, 1);
00324 if (result != 1)
00325 {
00326 EDOC_THROW_EXCEPTION(EDoc::BugException, "", "");
00327 }
00328
00329 c = (embedded_name.size() & 0x00FF0000) >> 16;
00330 result = write(fd, &c, 1);
00331 if (result != 1)
00332 {
00333 EDOC_THROW_EXCEPTION(EDoc::BugException, "", "");
00334 }
00335
00336 c = (embedded_name.size() & 0x0000FF00) >> 8;
00337 result = write(fd, &c, 1);
00338 if (result != 1)
00339 {
00340 EDOC_THROW_EXCEPTION(EDoc::BugException, "", "");
00341 }
00342
00343 c = (embedded_name.size() & 0x000000FF) >> 0;
00344 result = write(fd, &c, 1);
00345 if (result != 1)
00346 {
00347 EDOC_THROW_EXCEPTION(EDoc::BugException, "", "");
00348 }
00349
00350 result = write(fd, embedded_name.c_str(), embedded_name.size());
00351 if (result != (ssize_t)embedded_name.size())
00352 {
00353 EDOC_THROW_EXCEPTION(EDoc::BugException, "", "");
00354 }
00355
00356
00357 int fd2 = open(file_to_embed.c_str(), O_RDONLY, 0);
00358 if (fd2 == -1)
00359 {
00360 EDOC_THROW_EXCEPTION(BFDException, "", "");
00361 }
00362
00363
00364 char temp[1024];
00365 size_t blocks_to_write = buffer.st_size / 1024;
00366
00367 for (size_t i = 0; i < blocks_to_write; i++)
00368 {
00369 ssize_t result = read(fd2, temp, 1024);
00370 if (result == 0)
00371 {
00372 EDOC_THROW_EXCEPTION(BFDException, "", "");
00373 }
00374 if (write(fd, temp, result) != result)
00375 {
00376 EDOC_THROW_EXCEPTION(BFDException, "", "");
00377 }
00378 }
00379
00380 if (buffer.st_size % 1024)
00381 {
00382 ssize_t result = read(fd2, temp, buffer.st_size % 1024);
00383 if (result == 0)
00384 {
00385 EDOC_THROW_EXCEPTION(BFDException, "", "");
00386 }
00387 if (write(fd, temp, result) != result)
00388 {
00389 EDOC_THROW_EXCEPTION(BFDException, "", "");
00390 }
00391 }
00392
00393 close(fd2);
00394 close(fd);
00395
00396
00397 std::ostringstream stream;
00398 stream << "objcopy --remove-section=" << section << " --add-section "
00399 << section << "=" << tmpfile
00400 << " " << binary_file;
00401 if (EDoc::RunProgram(stream.str()) != 0)
00402 {
00403 EDOC_THROW_EXCEPTION(EDoc::BugException, "", "");
00404 }
00405
00406
00407 unlink(tmpfile.c_str());
00408 }
00409 catch(...)
00410 {
00411 unlink(tmpfile.c_str());
00412 throw;
00413 }
00414 }
00415
00416
00417 }