00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 #include "config.h"
00096
00097 #include "EDoc/utils.h"
00098 #include "EDoc/exceptions.h"
00099
00100 #include <string>
00101 #include <vector>
00102 #include <iostream>
00103
00104
00105 #ifdef HAVE_STDLIB_H
00106 #include <stdlib.h>
00107 #endif
00108
00109 #ifdef HAVE_STRING_H
00110 #include <string.h>
00111 #endif
00112
00113 #ifdef HAVE_SYS_SELECT_H
00114 #include <sys/select.h>
00115 #endif
00116
00117 #ifdef HAVE_SYS_WAIT_H
00118 #include <sys/wait.h>
00119 #endif
00120
00121 #ifdef HAVE_SYS_STAT_H
00122 #include <sys/stat.h>
00123 #endif
00124
00125 #ifdef HAVE_UNISTD_H
00126 #include <unistd.h>
00127 #endif
00128
00129 #ifdef HAVE_ERRNO_H
00130 #include <errno.h>
00131 #endif
00132
00133
00134
00135
00136
00137 namespace EDoc
00138 {
00139
00140 std::list<std::string> open_temp_files;
00141
00142 bool PushBack(const std::string& name,
00143 std::vector<std::string>& list)
00144 {
00145 bool already_contains = false;
00146 for (size_t j = 0; j < list.size(); j++)
00147 {
00148 if (list[j] == name)
00149 {
00150 already_contains = true;
00151 }
00152 }
00153
00154 if (!already_contains)
00155 {
00156 list.push_back(name);
00157 }
00158
00159 return !already_contains;
00160 }
00161
00162 std::string GetFileExtension(std::string name)
00163 {
00164 size_t pos = name.rfind('.');
00165 if (pos == std::string::npos)
00166 {
00167 return "";
00168 }
00169
00170 return name.substr(pos + 1);
00171 }
00172
00173 std::pair<std::string, std::string> SplitFileExtension(std::string name)
00174 {
00175 size_t pos = name.rfind('.');
00176 if (pos == std::string::npos)
00177 {
00178 return std::pair<std::string, std::string>(name, "");
00179 }
00180
00181 return std::pair<std::string, std::string>(name.substr(0, pos),
00182 name.substr(pos + 1));
00183 }
00184
00185 std::string CreateTempFilename(std::string base)
00186 {
00187 const char* path = "/tmp/";
00188
00189 char* b = new char[strlen(path) + base.size() + 6 + 1];
00190 strcpy(b, path);
00191 strcat(b, base.c_str());
00192 strcat(b, "XXXXXX");
00193
00194 int fd = mkstemp(b);
00195 if (fd == -1)
00196 {
00197 delete [] b;
00198 EDOC_THROW_EXCEPTION(BugException, "", "");
00199 }
00200 close(fd);
00201
00202 std::string f(b);
00203 delete [] b;
00204 b = NULL;
00205 return f;
00206 }
00207
00208 std::vector<std::string> Split(std::string str, char sep)
00209 {
00210 std::vector<std::string> ret;
00211
00212 size_t last = 0;
00213 while (last != std::string::npos)
00214 {
00215 size_t index = str.find_first_of(sep, last);
00216 if (index != std::string::npos)
00217 {
00218 ret.push_back(str.substr(last, index - last));
00219 last = index + 1;
00220 }
00221 else
00222 {
00223 ret.push_back(str.substr(last));
00224 last = index;
00225 }
00226 }
00227
00228 return ret;
00229 }
00230
00231 int RunProgram(std::string command_in)
00232 {
00233
00234
00235 int pid = fork();
00236 switch (pid)
00237 {
00238 case -1:
00239 {
00240 std::cerr << "ERROR failed fork." << std::endl;
00241 EDOC_THROW_EXCEPTION(BugException, "", "");
00242 break;
00243 }
00244 case 0:
00245 {
00246
00247 std::vector<std::string> sep = Split(command_in, ' ');
00248 size_t len = sep.size();
00249 char** argv = new char*[len + 1];
00250 for (size_t i = 0; i < len; i++)
00251 {
00252 argv[i] = new char[sep[i].size() + 1];
00253 strcpy(argv[i], sep[i].c_str());
00254 EDOC_Debug("argv: " << i << ", value: " << argv[i]);
00255
00256 }
00257 argv[len] = NULL;
00258
00259 EDOC_Debug("Executing command: " << command_in);
00260 EDOC_Debug("argv0: \"" << argv[0] << "\"");
00261
00262
00263 if (execvp(argv[0], argv) == -1)
00264 {
00265 std::cerr << "ERROR: Failed exec. Reason: " << strerror(errno)
00266 << std::endl;
00267 exit(1);
00268 }
00269 }
00270 default:
00271 {
00272
00273 int status = 0;
00274 if (waitpid(pid, &status, 0) == -1)
00275 {
00276 EDOC_THROW_EXCEPTION(BugException, "", "");
00277 }
00278 return status;
00279 }
00280 }
00281 return 0;
00282 }
00283
00284 int RunProgramRedirect(std::string& out, std::string& err, std::string command_in)
00285 {
00286
00287
00288
00289 static const size_t READ = 0;
00290 static const size_t WRITE = 1;
00291
00292 int out_pipe[2];
00293 int err_pipe[2];
00294 int result = 0;
00295
00296 out = "";
00297 err = "";
00298
00299 result = pipe(out_pipe);
00300 if(result == -1)
00301 {
00302 std::cerr << "ERROR failed to create pipe. Reason: " << strerror(errno) << std::endl;
00303 EDOC_THROW_EXCEPTION(BugException, "", "");
00304 }
00305
00306 result = pipe(err_pipe);
00307 if(result == -1)
00308 {
00309
00310 std::cerr << "ERROR failed to create pipe. Reason: " << strerror(errno) << std::endl;
00311 EDOC_THROW_EXCEPTION(BugException, "", "");
00312 }
00313
00314 int pid = fork();
00315 switch (pid)
00316 {
00317 case -1:
00318 {
00319
00320 std::cerr << "ERROR failed fork. Reason: " << strerror(errno) << std::endl;
00321 EDOC_THROW_EXCEPTION(BugException, "", "");
00322 break;
00323 }
00324 case 0:
00325 {
00326
00327
00328 std::vector<std::string> sep = Split(command_in, ' ');
00329 size_t len = sep.size();
00330 char** argv = new char*[len + 1];
00331 for (size_t i = 0; i < len; i++)
00332 {
00333 argv[i] = new char[sep[i].size() + 1];
00334 strcpy(argv[i], sep[i].c_str());
00335 EDOC_Debug("argv: " << i << ", value: " << argv[i]);
00336 }
00337 argv[len] = NULL;
00338
00339 EDOC_Debug("Executing command: " << command_in);
00340 EDOC_Debug("argv0: \"" << argv[0] << "\"");
00341
00342
00343 close(out_pipe[READ]);
00344 close(err_pipe[READ]);
00345
00346
00347 result = dup2(out_pipe[WRITE], 1);
00348 if (result == -1)
00349 {
00350 std::cerr << "ERROR: Failed dup. Reason: " << strerror(errno)
00351 << std::endl;
00352 exit(1);
00353 }
00354
00355 result = dup2(err_pipe[WRITE], 2);
00356 if (result == -1)
00357 {
00358 std::cerr << "ERROR: Failed dup. Reason: " << strerror(errno)
00359 << std::endl;
00360 exit(1);
00361 }
00362
00363
00364 close(out_pipe[WRITE]);
00365 close(err_pipe[WRITE]);
00366
00367
00368
00369 if (execvp(argv[0], argv) == -1)
00370 {
00371 std::cerr << "ERROR: Failed exec. Reason: " << strerror(errno)
00372 << std::endl;
00373 exit(1);
00374 }
00375 }
00376 default:
00377 {
00378
00379
00380
00381 close(out_pipe[WRITE]);
00382 close(err_pipe[WRITE]);
00383
00384
00385
00386 bool out_eof = false;
00387 bool err_eof = false;
00388 static const int BUFSIZE = 100;
00389 char buf[BUFSIZE];
00390 while (!out_eof || !err_eof)
00391 {
00392 int max_descriptor = 0;
00393 fd_set descriptors;
00394 FD_ZERO(&descriptors);
00395
00396 if (out_pipe[READ] > max_descriptor)
00397 {
00398 max_descriptor = out_pipe[READ];
00399 }
00400 FD_SET(out_pipe[READ], &descriptors);
00401
00402 if (err_pipe[READ] > max_descriptor)
00403 {
00404 max_descriptor = err_pipe[READ];
00405 }
00406 FD_SET(err_pipe[READ], &descriptors);
00407
00408 int result = select(max_descriptor + 1,
00409 &descriptors, NULL, NULL, NULL);
00410 if(result == -1)
00411 {
00412
00413 std::cerr << "ERROR failed select. Reason: " << strerror(errno) << std::endl;
00414 EDOC_THROW_EXCEPTION(BugException, "", "");
00415 }
00416
00417 if (FD_ISSET(out_pipe[READ], &descriptors))
00418 {
00419 result = read(out_pipe[READ], buf, BUFSIZE);
00420 if (result == -1)
00421 {
00422
00423 std::cerr << "ERROR failed read. Reason: " << strerror(errno) << std::endl;
00424 EDOC_THROW_EXCEPTION(BugException, "", "");
00425 }
00426 else if (result == 0)
00427 {
00428 out_eof = true;
00429 }
00430 out += std::string(buf, result);
00431 }
00432
00433 if (FD_ISSET(err_pipe[READ], &descriptors))
00434 {
00435 result = read(err_pipe[READ], buf, BUFSIZE);
00436 if (result == -1)
00437 {
00438
00439 std::cerr << "ERROR failed read. Reason: " << strerror(errno) << std::endl;
00440 EDOC_THROW_EXCEPTION(BugException, "", "");
00441 }
00442 else if (result == 0)
00443 {
00444 err_eof = true;
00445 }
00446 err += std::string(buf, result);
00447 }
00448 }
00449
00450 close(out_pipe[READ]);
00451 close(err_pipe[READ]);
00452
00453 int status = 0;
00454 if (waitpid(pid, &status, 0) == -1)
00455 {
00456 EDOC_THROW_EXCEPTION(BugException, "", "");
00457 }
00458 return status;
00459 }
00460 }
00461 return 0;
00462 }
00463
00464 static int mkdirs(char *path, mode_t mode)
00465 {
00466 size_t i;
00467 int retval = 0;
00468
00469 if (!path[0])
00470 {
00471 std::cerr << "Path provided was empty." << std::endl;
00472 return 0;
00473 }
00474
00475 for (i = 1; path[i] != 0; i++)
00476 {
00477 if (path[i] == '/')
00478 {
00479 path[i] = 0;
00480 EDOC_Debug("Making dir: "<< path);
00481 retval = mkdir(path, mode);
00482 if ((retval != 0) && (errno != EEXIST))
00483 {
00484 std::cerr << "Failed to create dir: " << path << std::endl;
00485 path[i] = '/';
00486 return retval;
00487 }
00488 path[i] = '/';
00489 }
00490 }
00491
00492 retval = mkdir(path, mode);
00493 if ((retval != 0) && (errno != EEXIST))
00494 {
00495 std::cerr << "Failed to create dir: " << path << std::endl;
00496 return retval;
00497 }
00498
00499 return 0;
00500 }
00501
00502 void MkDirs(std::string dir)
00503 {
00504 if (mkdirs(const_cast<char*>(dir.c_str()),
00505 S_IRUSR | S_IWUSR | S_IXUSR |
00506 S_IRGRP | S_IWGRP | S_IXGRP |
00507 S_IROTH | S_IWOTH | S_IXOTH) == -1)
00508 {
00509 EDOC_THROW_EXCEPTION(FileIOException, strerror(errno),
00510 "Failed to create directory: " << dir);
00511 }
00512 }
00513
00514 void CopyFile(std::string source, std::string destination)
00515 {
00516
00517
00518
00519
00520 std::ostringstream command;
00521
00522 command << "cp " << source << " " << destination;
00523 if (RunProgram(command.str()) != 0)
00524 {
00525 EDOC_THROW_EXCEPTION(FileIOException, "Failed to copy file.", "");
00526 }
00527 }
00528
00529 bool FileExists(std::string filename)
00530 {
00531 struct stat buffer;
00532 int result = stat(filename.c_str(), &buffer);
00533 if (result == -1)
00534 {
00535 return false;
00536 }
00537 return buffer.st_mode & S_IFREG;
00538 }
00539
00540 static const std::string white_space(" \t\r\n");
00541 std::string TrimWhitespace(const std::string& str)
00542 {
00543 std::string result = str;
00544 std::string::size_type pos;
00545
00546 if ((pos = result.find_first_not_of(white_space)) == std::string::npos)
00547 {
00548 return std::string("");
00549 }
00550 else
00551 {
00552 result.erase(0, pos);
00553 }
00554
00555 if ((pos = result.find_last_not_of(white_space)) != std::string::npos)
00556 {
00557 result.erase(pos+1);
00558 }
00559
00560 return result;
00561 }
00562
00563 std::string MakeTemporaryFile(std::string prefix,
00564 std::string EDOC_UNUSED(suffix), std::string directory)
00565 {
00566 std::string ft = directory + "/" + prefix + "XXXXXX";
00567
00568
00569 char* filename_template = new char[ft.size() + 1];
00570 strcpy(filename_template, ft.c_str());
00571
00572
00573 int result = mkstemp(filename_template);
00574 if (result == -1)
00575 {
00576 delete [] filename_template;
00577 filename_template = NULL;
00578
00579 EDOC_THROW_EXCEPTION(FileIOException, strerror(errno), "Unable to create temporary file: " + ft);
00580 }
00581
00582
00583 prefix = filename_template;
00584 delete [] filename_template;
00585 filename_template = NULL;
00586 result = close(result);
00587 if (result == -1)
00588 {
00589 EDOC_THROW_EXCEPTION(FileIOException, strerror(errno), "Failed closing descriptor for temporary file: " + ft);
00590 }
00591
00592 return prefix;
00593 }
00594
00595 }