Utils.cc

00001 // ----------------------------------------------------------------------^
00002 // Copyright (C) 2004, 2005, 2006, 2007, 2008 Giorgio Calderone
00003 // (mailto: <gcalderone@ifc.inaf.it>)
00004 // 
00005 // This file is part of MCS.
00006 // 
00007 // MCS is free software; you can redistribute it and/or modify
00008 // it under the terms of the GNU General Public License as published by
00009 // the Free Software Foundation; either version 2 of the License, or
00010 // (at your option) any later version.
00011 // 
00012 // MCS is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 // 
00017 // You should have received a copy of the GNU General Public License
00018 // along with MCS; if not, write to the Free Software
00019 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 // 
00021 // ----------------------------------------------------------------------$
00022 #include "mcs.hh"
00023 using namespace mcs;
00024 
00025 
00026 int mcs::extractCode(const char* msg)
00027 {
00028   int ret;
00029   ret = 0;
00030   ret += (msg[1] - '0') * 100;
00031   ret += (msg[2] - '0') * 10 ;
00032   ret += (msg[3] - '0')      ;
00033   return ret;
00034 }
00035 
00036 
00037 
00038 
00039 bool mcs::File_Dir_Exist(string fn, unsigned int& size)
00040 {
00041   DIR *dp;
00042   ifstream f;
00043   size = 0;
00044 
00045   if (fn.empty()) return false;
00046   dp = opendir(fn.csz);
00047   if (dp) {
00048     closedir(dp);
00049     return true;
00050   }
00051   else {
00052     f.open(fn.csz);
00053     if (f.is_open()) {
00054       f.seekg(0, ios::end);  // Seek the end of file (to get the size)
00055       size = f.tellg();      // Size of file
00056       f.seekg(0, ios::beg);  // Seek the start of file
00057       f.close();
00058       return true;
00059     }
00060     else
00061       return false;
00062   }
00063 }
00064 
00065 
00066 string mcs::Pwd()
00067 {
00068   char* p;
00069   string s;
00070   p=getcwd(NULL, 0);
00071   s=p;
00072   free(p);
00073   return s;
00074 }
00075 
00076 
00077 string mcs::itos(int i)
00078 {
00079   char buf[20];
00080   sprintf(buf, "%d", i);
00081   return string(buf);
00082 }
00083 
00084 
00085 int mcs::stoi(string s)
00086 {
00087   int i;
00088   if (sscanf(s.c_str(), "%d", &i) == 1)
00089     return i;
00090   else
00091     throw MCS_ERROR(MSG_CONVERSION_STRING_INT);
00092 }
00093 
00094 
00095 int mcs::stoi(string s, int errval)
00096 {
00097   int i;
00098   if (sscanf(s.c_str(), "%d", &i) == 1)
00099     return i;
00100   else
00101     return errval;
00102 }
00103 
00104 
00105 string mcs::dtos(double f)
00106 {
00107   char buf[20];
00108   sprintf(buf, "%f", f);
00109   return string(buf);
00110 }
00111 
00112 
00113 string mcs::btos(bool b)
00114 {
00115   if (b)
00116     return string("true");
00117   else
00118     return string("false");
00119 }
00120 
00121 
00122 string mcs::vtos(vector<string> vec)
00123 {
00124   unsigned int i;
00125   string buf = "";
00126   string nl = "\n";
00127 
00128   for (i=0; i<vec.size(); i++)
00129     buf += vec[i] + nl;
00130 
00131   return buf;
00132 }
00133 
00134 
00135 string mcs::subst(string s, string what, string with, int op)
00136 {
00137     string s2 = "(" + what + string(")");
00138     string templ = s2;
00139 
00140     if (op & MCS_SUBST_LEADING)
00141     templ = "^" + s2;
00142 
00143     if (op & MCS_SUBST_TRAILING) {
00144     if (op & MCS_SUBST_LEADING)
00145         templ += "|" + s2;
00146     templ += "$";
00147     }
00148     pcrecpp::RE re(templ,
00149            pcrecpp::RE_Options().set_dollar_endonly(true));
00150 
00151     if (op & MCS_SUBST_QUOTE_WITH) {
00152     pcrecpp::RE re("\\\\");
00153     re.GlobalReplace("\\\\\\\\", &with);
00154     }
00155     re.GlobalReplace(with, &s);
00156     return s;
00157 }
00158 
00159 
00160 string mcs::trim(string s)
00161 {
00162     return subst(s, " +", "", MCS_SUBST_LEADING | MCS_SUBST_TRAILING);
00163 }
00164 
00165 
00166 string mcs::chomp(string s)
00167 {
00168     return subst(s, "\n+", "", MCS_SUBST_TRAILING);
00169 }
00170 
00171 
00172 string mcs::remTabs(string s)
00173 {
00174     return subst(s, "\t", "");
00175 }
00176 
00177 
00178 string mcs::remLeading(string& s, const char* p)
00179 {
00180     s = subst(s, p, "", MCS_SUBST_LEADING);
00181     return s;
00182 }
00183 
00184 
00185 string mcs::remTrailing(string& s, const char* p)
00186 {
00187     s = subst(s, p, "", MCS_SUBST_TRAILING);
00188     return s;
00189 }
00190 
00191 
00192 std::vector<std::string> mcs::split(string s, string sep)
00193 {
00194     vector<string> v;
00195 
00196     //First characters must not be equal top sep
00197     pcrecpp::RE pre("^\\Q" + sep + "\\E+");
00198     pre.GlobalReplace("", &s);
00199 
00200     pcrecpp::StringPiece input(s);
00201     pcrecpp::RE re("([^\\Q" + sep + "\\E]+)\\Q" + sep + "\\E*");
00202     //pcrecpp::RE re("(\\S+) *");
00203 
00204     while (re.Consume(&input, &s))
00205     v.push_back(s);
00206 
00207     return v;
00208 }
00209 
00210 
00211 string mcs::hexDump(const void* pvoid, unsigned int size)
00212 {
00213   const char* buf = (const char*) pvoid;
00214   string s = "";
00215   unsigned int i, j, count;
00216   char lbuf[40];
00217 
00218   i = 0;
00219   while (i < size) {
00220     count = size - i;
00221     if (count > 8)
00222       count = 8;
00223 
00224     sprintf(lbuf, "%06d ", i);
00225     s += lbuf;
00226 
00227     for (j=0; j<count; j++) {
00228       sprintf(lbuf, "%02X", buf[i+j]);
00229       s += lbuf;
00230     }
00231 
00232     s += " ";
00233 
00234     for (j=0; j<count; j++) {
00235       if (isprint(buf[i+j]))
00236     sprintf(lbuf, "%c", buf[i+j]);
00237       else
00238     sprintf(lbuf, ".");
00239 
00240       s += lbuf;
00241     }
00242 
00243     s += "\n";
00244     i += count; 
00245   }
00246   return s;
00247 }
00248 
00249 
00250 mode_t mcs::read_umask()
00251 {
00252   mode_t mask = umask (0);
00253   umask(mask);
00254   return mask;
00255 }
00256 
00257 
00258 
00259 bool mcs::mkDir(string path, mode_t perm, enum ThrowExceptions throwexc)
00260 {
00261   if (perm == MCS_MKDIR_UMASK)
00262     perm = (S_IRWXU | S_IRWXG | S_IRWXO) & ~read_umask();
00263 
00264   if (mkdir(path.csz, perm))
00265     if (throwexc)
00266       throw MCS_ERROR(MSG_CANT_MKDIR, path.csz);
00267     else
00268       return false;
00269   else
00270     return true;
00271 }
00272 
00273 
00274 bool mcs::rmDir(string path, enum ThrowExceptions throwexc)
00275 {
00276   string s;
00277   //TODO: custom "rmdir"
00278   s = "rm -rf " + path;
00279 
00280   if (system(s.csz))
00281     if (throwexc)
00282       throw MCS_ERROR(MSG_CANT_RMDIR, path.csz);
00283     else
00284       return false;
00285   else
00286     return true;
00287 }
00288 
00289 
00290 void mcs::ls2Record(string fn, Record& v)
00291 {
00292   DIR *dp;
00293   struct dirent *ep;
00294   string s, r;
00295   ifstream f;
00296 
00297   if (fn.empty()) return;
00298 
00299   dp = opendir (fn.c_str());
00300   if (dp) {
00301     while ((ep = readdir (dp))) {
00302       r=ep->d_name;
00303       if ( r != "."   &&   r != ".." )
00304       ls2Record(fn + string("/") + r, v);
00305     }
00306     closedir (dp);
00307   }
00308   else {
00309     f.open(fn.c_str());
00310     if (f.is_open()) {
00311     Data d(NULL, STRING, "FILE", fn.length());
00312     d = fn;
00313     v.addField(&d);
00314     f.close();
00315     }
00316   }
00317 }
00318 
00319 
00320 
00321 
00322 //This routine is to be used inside this file, not by users
00323 static char* appendFileNameToPath(char* OLDNAME, char* NEWNAME)
00324 {
00325   char* buf;
00326   char* p;
00327 
00328   p = strrchr(OLDNAME, '/');
00329   if (p == NULL)
00330     p = OLDNAME;
00331   else {
00332     p++;
00333   }
00334 
00335   //Plus two: one to eventually add a slash, one for NULL
00336   buf = (char*) malloc(strlen(NEWNAME) + strlen(p) + 2);
00337 
00338   strcpy(buf, NEWNAME);
00339 
00340   if (buf[strlen(buf) - 1] != '/') { //If last character is not a slash
00341     buf[strlen(buf) + 1] = 0;
00342     buf[strlen(buf)] = '/';
00343   }
00344 
00345   strcpy(buf + strlen(buf), p);
00346   return buf;
00347 }
00348 
00349 
00350 
00351 
00352 #define BUFSIZE 16384
00353 int mcs::copy(char* OLDNAME, char* NEWNAME)
00354 {
00355   FILE *inf, *outf;
00356   int nread;
00357   char buf[BUFSIZE];
00358 
00359   if ((outf = fopen(NEWNAME, "wb")) == NULL) {
00360     if (errno == EISDIR) {
00361       char* b = appendFileNameToPath(OLDNAME, NEWNAME);
00362       int ret = copy(OLDNAME, b);
00363       free(b);
00364       return ret;
00365     }
00366     else {
00367       fprintf(stderr, "Error opening file %s: %s\n", NEWNAME,
00368           strerror(errno));
00369       return -1;
00370     }
00371   }
00372   else {
00373     if ((inf = fopen(OLDNAME, "rb")) == NULL) {
00374       fclose(outf);
00375       fprintf(stderr, "Error opening file %s: %s\n", OLDNAME,
00376           strerror(errno));
00377       return -1;
00378     }
00379 
00380 
00381     while (! feof(inf)) {
00382       nread = fread(buf, sizeof(char), BUFSIZE, inf);
00383       fwrite(buf, sizeof(char), nread, outf);
00384     }
00385 
00386     fclose(inf);
00387     fclose(outf);
00388 
00389     //Success
00390     return 0;
00391   }
00392 }
00393 
00394 
00395 int mcs::move(char* OLDNAME, char* NEWNAME)
00396 {
00397   char* buf;
00398   int ret;
00399 
00400   ret = rename(OLDNAME, NEWNAME);
00401 
00402   if (ret == -1)  //An error occurred
00403     switch(errno) {
00404 
00405     case EISDIR: //NEWNAME is a directory but the OLDNAME isn't.
00406       //So append the filename to the NEWNAME directory and retry
00407       buf = appendFileNameToPath(OLDNAME, NEWNAME);
00408       ret = move(OLDNAME, buf);
00409       free(buf);
00410       return ret;
00411 
00412 
00413     case EBUSY: //This error can happen if NEWNAME is one of: ".", ".."
00414       if (NEWNAME[strlen(NEWNAME) - 1] != '/') { //That's a directory
00415     buf = appendFileNameToPath(OLDNAME, NEWNAME);
00416     ret = move(OLDNAME, buf);
00417     free(buf);
00418     return ret;
00419       }
00420 
00421 
00422     case EXDEV:  //Different filesystems, must copy, then delete
00423       ret = copy(OLDNAME, NEWNAME);
00424       if (ret == 0) {
00425     if (unlink(OLDNAME) == -1) {
00426       fprintf(stderr, "Error deleting file %s: %s\n", OLDNAME,
00427           strerror(errno));
00428       return -1;
00429     }
00430       }
00431       return ret;
00432 
00433 
00434 
00435     default:
00436       fprintf(stderr, "Error renaming %s ==> %s: %s\n", OLDNAME, NEWNAME,
00437           strerror(errno));
00438       return -1;
00439     }
00440 
00441 
00442   //Success
00443   return 0;
00444 }
00445 
00446 
00447 
00448 
00449 
00450 const char* mcs::B64_Codec::cb64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00451 const char* mcs::B64_Codec::cd64="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
00452 
00453 
00454 mcs::B64_Codec::B64_Codec()
00455 {
00456   bufAllocated = NULL;
00457   precDataCount = 0;
00458   blocksout = 0;
00459 }
00460 
00461 mcs::B64_Codec::~B64_Codec()
00462 {
00463   freeBuffer();
00464 }
00465 
00466 
00467 void mcs::B64_Codec::requireSpace(unsigned int Length)
00468 {
00469   if (Length < 0)
00470     ; //ERROR
00471 
00472   if ((! bufAllocated)   ||
00473       (bufsize < Length)) {
00474     bufsize = Length;
00475     bufAllocated = (char*) realloc(bufAllocated, bufsize);
00476     memset(bufAllocated, 0, bufsize);
00477   }
00478   this->buf_out = bufAllocated;
00479 }
00480 
00481 void mcs::B64_Codec::freeBuffer()
00482 {
00483   if (bufAllocated)
00484     free(bufAllocated);
00485 
00486   bufAllocated = NULL;
00487   bufsize = 0;
00488 }
00489 
00490 
00491 bool mcs::B64_Codec::eob()
00492 {
00493   if (precDataCount)
00494     return false;
00495   else
00496     return ((bool) (pin >= EOIB));
00497 }
00498 
00499 unsigned char mcs::B64_Codec::readData()
00500 {
00501   if (precDataCount) {
00502     unsigned char ret = precData[0];
00503     precData[0] = precData[1];
00504     precData[1] = precData[2];
00505     precData[2] = precData[3];
00506     precDataCount--;
00507     return ret;
00508   }
00509   else
00510     return *pin++;
00511 }
00512 
00513 void mcs::B64_Codec::writeData(unsigned char d)
00514 { *pout++ = d; }
00515 
00516 char* mcs::B64_Codec::buffer()
00517 { return buf_out; }
00518 
00519 unsigned int mcs::B64_Codec::bufUsed()
00520 { return pout - buf_out; }
00521 
00522 
00523 unsigned int mcs::B64_Codec::encode(char* buf_in, int Length, char* par_buf_out,
00524                     unsigned int linesize)
00525 {
00526   unsigned int rescue = 0;
00527   unsigned char in[3], out[4];
00528   int i, len = 0;
00529 
00530   int origLength = Length;  //Save "Length" because we are going to
00531                 //change it.
00532 
00533   //Number of bytes being read (those from precedent call:
00534   //precDataCount, plus actual buffer: Length) must be a multiple of 3
00535   //bytes.
00536   if (Length) {
00537     rescue = (precDataCount + Length) % 3; //"rescue" bytes need to be
00538                                            //saved for a later call.
00539     Length -= rescue;
00540   }
00541 
00542   //Setup input buffer
00543   EOIB = buf_in + Length;
00544   pin = buf_in;
00545 
00546   //Setup output buffer
00547   if (par_buf_out) {
00548     freeBuffer();
00549     buf_out = par_buf_out;
00550   }
00551   else {
00552     requireSpace(origLength * 2);
00553     buf_out = bufAllocated;
00554   }
00555   pout = buf_out;
00556 
00557 
00558   //Set linesize
00559   if (linesize < MCS_B64_MIN_LINE)
00560     linesize = MCS_B64_MIN_LINE;
00561   this->linesize = linesize;
00562 
00563 
00564   //Encode
00565   while (! eob()) {
00566     len = 0;
00567     for(i=0;  i<3;  i++) {
00568       if (! eob()) {
00569     in[i] = (unsigned char) readData();
00570     len++;
00571       }
00572       else
00573     in[i] = 0;
00574     }
00575     if (len) {
00576       encodeblock(in, out, len);
00577       for(i=0;  i<4;  i++) {
00578     writeData(out[i]);
00579       }
00580       blocksout++;
00581     }
00582     if (blocksout >= (linesize/4)) {
00583       writeData('\r');
00584       writeData('\n');
00585       blocksout = 0;
00586     }
00587   }
00588 
00589 
00590   if (Length) {  //Save bytes from input buffer for a later call
00591     for (unsigned int i=0; i<rescue; i++)
00592       precData[i] = readData();
00593 
00594     precDataCount = rescue;
00595   }
00596   else {  //Or if we are at end of file simply write a newline
00597     writeData('\r');
00598     writeData('\n');
00599 
00600     precDataCount = 0;  //Setup for new encoding
00601     blocksout = 0;
00602   }
00603 
00604   return pout - buf_out;
00605 }
00606 
00607 
00608 
00609 unsigned int mcs::B64_Codec::decode(char* buf_in, int Length, char* par_buf_out)
00610 {
00611   unsigned char in[4], out[3], v, d;
00612   int i, len;
00613 
00614   //Setup input buffer
00615   EOIB = buf_in + Length;
00616   pin = buf_in;
00617 
00618   //Setup output buffer
00619   if (par_buf_out) {
00620     freeBuffer();
00621     buf_out = par_buf_out;
00622   }
00623   else {
00624     requireSpace(Length);
00625     buf_out = bufAllocated;
00626   }
00627   pout = buf_out;
00628 
00629 
00630   //Decode data
00631   len = 0;
00632   while (! eob()) {
00633     d = v = readData();
00634 
00635     //Check if the character is allowed
00636     v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]);
00637     if ((v != 0)     &&
00638     (v != '$')        ) {
00639       in[len] = v - 62;
00640 
00641       if (precDataCount == 0)
00642     precData[len] = d;
00643 
00644       len++;
00645     }
00646 
00647     //If we have a complete 4 byte block
00648     if (len == 4) {
00649       decodeblock(in, out);
00650       for(i=0; i<len-1; i++)
00651     writeData(out[i]);
00652 
00653       len = 0;
00654     }
00655   }
00656 
00657   if (len > 0) {  //If some byte hasn't been decoded yet
00658     precDataCount = len; //...save it for a later call
00659 
00660     if (Length == 0) { //Or if we are at the end of file
00661       decodeblock(in, out); //..decode it!
00662       for(i=0; i<len-1; i++)
00663     writeData(out[i]);
00664 
00665       precDataCount = 0;  //Setup for new encoding
00666     }
00667   }
00668 
00669   return pout - buf_out;
00670 }
00671 
00672 void mcs::B64_Codec::encodeblock( unsigned char in[3], unsigned char out[4], int len )
00673 {
00674   out[0] = cb64[ in[0] >> 2 ];
00675   out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
00676   out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
00677   out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');
00678 }
00679 
00680 void mcs::B64_Codec::decodeblock( unsigned char in[4], unsigned char out[3] )
00681 {
00682   out[ 0 ] = (unsigned char ) (in[0] << 2 | in[1] >> 4);
00683   out[ 1 ] = (unsigned char ) (in[1] << 4 | in[2] >> 2);
00684   out[ 2 ] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]);
00685 }
00686 
00687 
00688 
00689 
00690 //returns 0 if timeout, 1 if ready, -1 if error
00691 int mcs::Select(int fd, unsigned int sec_timeout, unsigned int usec_timeout, int op)
00692 {
00693     fd_set set;
00694     struct timeval timeout;
00695     int ret;
00696 
00697     FD_ZERO (&set);
00698     FD_SET (fd, &set);
00699     timeout.tv_sec  = sec_timeout;
00700     timeout.tv_usec = usec_timeout;
00701 
00702     if (op == MCS_SELECT_READ)
00703     ret = select(FD_SETSIZE, &set, NULL, NULL, &timeout);
00704     else
00705     ret =  select(FD_SETSIZE, NULL, &set, NULL, &timeout);
00706 
00707     return ret;
00708 }
00709 
00710 
00711 
00712 //returns 0 if timeout, number of fd ready, -1 if error
00713 int mcs::Select(int fd[], int nfd, unsigned int sec_timeout, unsigned int usec_timeout, int op)
00714 {
00715     fd_set set;
00716     struct timeval timeout;
00717     int i, ret;
00718 
00719     FD_ZERO (&set);
00720     for (i=0; i<nfd; i++) {
00721     FD_SET (fd[i], &set);
00722     fd[i] = 0;
00723     }
00724 
00725     timeout.tv_sec  = sec_timeout;
00726     timeout.tv_usec = usec_timeout;
00727 
00728     if (op == MCS_SELECT_READ)
00729     ret = select(FD_SETSIZE, &set, NULL, NULL, &timeout);
00730     else
00731     ret = select(FD_SETSIZE, NULL, &set, NULL, &timeout);
00732 
00733     for (i=0; i<nfd; i++)
00734     fd[i] = FD_ISSET(i, &set);
00735 
00736     return ret;
00737 }
00738 
00739 
00740 

mcslogo

MCS (My Customizable Server) ver. 0.3.3-alpha3
Documentation generated on Thu Mar 22 13:22:23 UTC 2012