lib/utility.cc

Code
Comments
Other
Rev Date Author Line
62 19 Jan 06 peter 1 // $Id$
62 19 Jan 06 peter 2
84 13 Mar 06 jari 3 /*
978 12 Dec 09 peter 4   Copyright (C) 2006, 2007, 2008, 2009 Jari Häkkinen, Peter Johansson
1515 26 Sep 12 peter 5   Copyright (C) 2010, 2011, 2012 Peter Johansson
84 13 Mar 06 jari 6
687 04 Aug 08 peter 7   This file is part of svndigest, http://dev.thep.lu.se/svndigest
84 13 Mar 06 jari 8
149 12 Aug 06 jari 9   svndigest is free software; you can redistribute it and/or modify it
84 13 Mar 06 jari 10   under the terms of the GNU General Public License as published by
693 11 Sep 08 jari 11   the Free Software Foundation; either version 3 of the License, or
84 13 Mar 06 jari 12   (at your option) any later version.
84 13 Mar 06 jari 13
149 12 Aug 06 jari 14   svndigest is distributed in the hope that it will be useful, but
84 13 Mar 06 jari 15   WITHOUT ANY WARRANTY; without even the implied warranty of
149 12 Aug 06 jari 16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
84 13 Mar 06 jari 17   General Public License for more details.
84 13 Mar 06 jari 18
84 13 Mar 06 jari 19   You should have received a copy of the GNU General Public License
693 11 Sep 08 jari 20   along with svndigest. If not, see <http://www.gnu.org/licenses/>.
84 13 Mar 06 jari 21 */
84 13 Mar 06 jari 22
1253 31 Oct 10 peter 23 #include <config.h>
1253 31 Oct 10 peter 24
62 19 Jan 06 peter 25 #include "utility.h"
62 19 Jan 06 peter 26
1085 12 Jun 10 peter 27 #include "yat/Exception.h"
1085 12 Jun 10 peter 28
516 09 Dec 07 peter 29 #include <cassert>
755 15 Jan 09 jari 30 #include <cstdio>
198 09 Sep 06 peter 31 #include <cstdlib>
755 15 Jan 09 jari 32 #include <cstring>
1052 18 Apr 10 peter 33 #include <fnmatch.h>
62 19 Jan 06 peter 34 #include <fstream>
62 19 Jan 06 peter 35 #include <sstream>
151 13 Aug 06 jari 36 #include <stdexcept>
62 19 Jan 06 peter 37 #include <string>
705 25 Nov 08 peter 38 #include <sys/stat.h>
115 30 Jun 06 peter 39 #include <unistd.h>
62 19 Jan 06 peter 40
201 09 Sep 06 peter 41 #include <iostream>
201 09 Sep 06 peter 42
1425 16 Dec 11 peter 43 #include <libgen.h>
1425 16 Dec 11 peter 44
62 19 Jan 06 peter 45 namespace theplu{
149 12 Aug 06 jari 46 namespace svndigest{
62 19 Jan 06 peter 47
1547 20 Oct 12 peter 48   std::string absolute_path(const std::string& path)
1547 20 Oct 12 peter 49   {
1547 20 Oct 12 peter 50     if (is_absolute_path(path))
1547 20 Oct 12 peter 51       return path;
1547 20 Oct 12 peter 52     return concatenate_path(pwd(), path);
1547 20 Oct 12 peter 53   }
1547 20 Oct 12 peter 54
151 13 Aug 06 jari 55   int access_rights(const std::string& path, const std::string& bits)
151 13 Aug 06 jari 56   {
163 22 Aug 06 jari 57     if (access(path.c_str(),F_OK)) {
151 13 Aug 06 jari 58       throw std::runtime_error(std::string("access_rights: ") + path +
151 13 Aug 06 jari 59                                "' does not exist.");
151 13 Aug 06 jari 60     }
151 13 Aug 06 jari 61     int mode=0;
589 12 Apr 08 jari 62     for (unsigned int i=0; i<bits.length(); ++i)
151 13 Aug 06 jari 63       switch (bits[i]) {
151 13 Aug 06 jari 64           case 'r':
151 13 Aug 06 jari 65             mode|=R_OK;
151 13 Aug 06 jari 66             break;
151 13 Aug 06 jari 67           case 'w':
151 13 Aug 06 jari 68             mode|=W_OK;
151 13 Aug 06 jari 69             break;
151 13 Aug 06 jari 70           case 'x':
151 13 Aug 06 jari 71             mode|=X_OK;
151 13 Aug 06 jari 72             break;
151 13 Aug 06 jari 73       }
151 13 Aug 06 jari 74     return access(path.c_str(),mode);
151 13 Aug 06 jari 75   }
151 13 Aug 06 jari 76
151 13 Aug 06 jari 77
1085 12 Jun 10 peter 78   void chdir(const std::string& dir)
1085 12 Jun 10 peter 79   {
1085 12 Jun 10 peter 80     if (::chdir(dir.c_str()) )
1085 12 Jun 10 peter 81       throw yat::utility::errno_error("chdir: " + dir + ":");
1085 12 Jun 10 peter 82   }
1085 12 Jun 10 peter 83
1085 12 Jun 10 peter 84
1392 12 Jul 11 peter 85   void chmod(const std::string& filename, mode_t mode)
1392 12 Jul 11 peter 86   {
1392 12 Jul 11 peter 87     if (::chmod(filename.c_str(), mode))
1392 12 Jul 11 peter 88       throw yat::utility::errno_error("chmod: ");
1392 12 Jul 11 peter 89   }
1392 12 Jul 11 peter 90
1392 12 Jul 11 peter 91
705 25 Nov 08 peter 92   std::string concatenate_path(std::string dir, std::string base)
705 25 Nov 08 peter 93   {
709 26 Nov 08 peter 94     if (dir.empty() || dir==".")
705 25 Nov 08 peter 95       return base;
705 25 Nov 08 peter 96     if (dir[dir.size()-1]!='/')
705 25 Nov 08 peter 97       dir.append("/");
705 25 Nov 08 peter 98     return dir+base;
705 25 Nov 08 peter 99   }
705 25 Nov 08 peter 100
705 25 Nov 08 peter 101
462 21 Aug 07 jari 102   void copy_file(const std::string& source, const std::string& target)
462 21 Aug 07 jari 103   {
462 21 Aug 07 jari 104     std::ofstream o(target.c_str());
462 21 Aug 07 jari 105     std::ifstream i(source.c_str());
462 21 Aug 07 jari 106     while (i.good()) {
462 21 Aug 07 jari 107       char ch=i.get();
462 21 Aug 07 jari 108       if (i.good())
462 21 Aug 07 jari 109         o.put(ch);
462 21 Aug 07 jari 110       if (!o.good())
462 21 Aug 07 jari 111         throw std::runtime_error(std::string("copy_file: ") +
462 21 Aug 07 jari 112                                  "writing target file failed '" + target + "'");
462 21 Aug 07 jari 113     }
462 21 Aug 07 jari 114      if (!i.eof() && (i.bad() || i.fail()))  // fail on everything except eof
462 21 Aug 07 jari 115       throw std::runtime_error(std::string("copy_file: ") +
462 21 Aug 07 jari 116                                "error reading source file '" + source + "'");
462 21 Aug 07 jari 117     i.close(); o.close();
1291 12 Nov 10 peter 118     // copy permissions
1291 12 Nov 10 peter 119     struct stat nodestat;
1439 20 Dec 11 peter 120     stat(source.c_str(),&nodestat);
1291 12 Nov 10 peter 121     chmod(target.c_str(), nodestat.st_mode);
462 21 Aug 07 jari 122   }
462 21 Aug 07 jari 123
462 21 Aug 07 jari 124
1432 18 Dec 11 peter 125   std::string  directory_name(const std::string& path)
482 13 Oct 07 peter 126   {
1432 18 Dec 11 peter 127     if (path.size()==1) {
1432 18 Dec 11 peter 128       if (path=="/")
1432 18 Dec 11 peter 129         return path;
1432 18 Dec 11 peter 130       else
1432 18 Dec 11 peter 131         return ".";
1432 18 Dec 11 peter 132     }
1432 18 Dec 11 peter 133     assert(path.size()>=2);
1432 18 Dec 11 peter 134     size_t pos = path.find_last_of('/', path.size()-2);
1432 18 Dec 11 peter 135     if (pos==std::string::npos)
1432 18 Dec 11 peter 136       return ".";
1432 18 Dec 11 peter 137     if (pos==0)
1432 18 Dec 11 peter 138       return "/";
1432 18 Dec 11 peter 139     return path.substr(0,pos);
1432 18 Dec 11 peter 140     return "";
482 13 Oct 07 peter 141   }
482 13 Oct 07 peter 142
482 13 Oct 07 peter 143
1432 18 Dec 11 peter 144   std::string  file_name(const std::string& path)
100 19 Jun 06 peter 145   {
1432 18 Dec 11 peter 146     if (path.size()==1)
1432 18 Dec 11 peter 147       return path;
1432 18 Dec 11 peter 148     size_t pos = path.find_last_of('/');
1432 18 Dec 11 peter 149     if (pos==std::string::npos)
1432 18 Dec 11 peter 150       return path;
1432 18 Dec 11 peter 151     if (pos==path.size()-1)
1432 18 Dec 11 peter 152       return file_name(path.substr(0, path.size()-1));
1432 18 Dec 11 peter 153     return path.substr(pos+1);
100 19 Jun 06 peter 154   }
100 19 Jun 06 peter 155
151 13 Aug 06 jari 156
198 09 Sep 06 peter 157   std::string getenv(const std::string& var)
198 09 Sep 06 peter 158   {
198 09 Sep 06 peter 159     char* buffer=std::getenv(var.c_str());
198 09 Sep 06 peter 160     if (!buffer)
198 09 Sep 06 peter 161       throw std::runtime_error("Environment variable "+var+" is not set");
198 09 Sep 06 peter 162     return std::string(buffer);
198 09 Sep 06 peter 163   }
198 09 Sep 06 peter 164
198 09 Sep 06 peter 165
589 12 Apr 08 jari 166   std::string hex(int x, unsigned int width)
373 19 Jun 07 peter 167   {
373 19 Jun 07 peter 168     std::stringstream ss;
373 19 Jun 07 peter 169     ss << std::hex << x;
373 19 Jun 07 peter 170     if (!width)
373 19 Jun 07 peter 171       return ss.str();
1439 20 Dec 11 peter 172     if (ss.str().size()<width)
373 19 Jun 07 peter 173       return std::string(width-ss.str().size(), '0') + ss.str();
373 19 Jun 07 peter 174     return ss.str().substr(0, width);
373 19 Jun 07 peter 175   }
373 19 Jun 07 peter 176
373 19 Jun 07 peter 177
226 11 Mar 07 peter 178   std::string htrim(std::string str)
226 11 Mar 07 peter 179   {
226 11 Mar 07 peter 180     size_t length=str.size();
226 11 Mar 07 peter 181     while(length && isspace(str[length-1]))
226 11 Mar 07 peter 182       --length;
226 11 Mar 07 peter 183     return str.substr(0,length);
226 11 Mar 07 peter 184   }
226 11 Mar 07 peter 185
226 11 Mar 07 peter 186
1052 18 Apr 10 peter 187   bool fnmatch(const std::string& pattern, const std::string& str)
1052 18 Apr 10 peter 188   {
1098 13 Jun 10 peter 189     int res = ::fnmatch(pattern.c_str(), str.c_str(), 0);
1052 18 Apr 10 peter 190     if (res==0)
1052 18 Apr 10 peter 191       return true;
1052 18 Apr 10 peter 192     if (res!=FNM_NOMATCH) {
1052 18 Apr 10 peter 193       std::stringstream ss;
1097 13 Jun 10 peter 194       ss << "fnmatch with args: " << pattern << ", " << str;
1052 18 Apr 10 peter 195       throw std::runtime_error(ss.str());
1439 20 Dec 11 peter 196     }
1052 18 Apr 10 peter 197     return false;
1052 18 Apr 10 peter 198   }
1052 18 Apr 10 peter 199
1052 18 Apr 10 peter 200
1547 20 Oct 12 peter 201   bool is_absolute_path(const std::string& path)
1547 20 Oct 12 peter 202   {
1547 20 Oct 12 peter 203     return path.size() && path[0]=='/';
1547 20 Oct 12 peter 204   }
1547 20 Oct 12 peter 205
1547 20 Oct 12 peter 206
1186 27 Aug 10 peter 207   void lstat(const std::string path, struct stat* nodestat)
1186 27 Aug 10 peter 208   {
1186 27 Aug 10 peter 209     int res = ::lstat(path.c_str(), nodestat);
1186 27 Aug 10 peter 210     if (res) {
1186 27 Aug 10 peter 211       throw yat::utility::errno_error("lstat: ");
1186 27 Aug 10 peter 212     }
1186 27 Aug 10 peter 213   }
1186 27 Aug 10 peter 214
1186 27 Aug 10 peter 215
226 11 Mar 07 peter 216   std::string ltrim(std::string str)
226 11 Mar 07 peter 217   {
226 11 Mar 07 peter 218     size_t i = 0;
226 11 Mar 07 peter 219     while(i<str.size() && isspace(str[i]))
226 11 Mar 07 peter 220       ++i;
226 11 Mar 07 peter 221     return str.substr(i);
226 11 Mar 07 peter 222   }
226 11 Mar 07 peter 223
482 13 Oct 07 peter 224   void mkdir(const std::string& dir)
1439 20 Dec 11 peter 225   {
482 13 Oct 07 peter 226     int code = ::mkdir(dir.c_str(),0777);
482 13 Oct 07 peter 227     if (code){
482 13 Oct 07 peter 228       std::stringstream ss;
1459 09 Jan 12 peter 229       ss << "mkdir: '" << dir << "': ";
1186 27 Aug 10 peter 230       throw yat::utility::errno_error(ss.str());
482 13 Oct 07 peter 231     }
313 17 May 07 peter 232   }
313 17 May 07 peter 233
313 17 May 07 peter 234
796 01 Jul 09 peter 235   void mkdir_p(const std::string& dir)
1439 20 Dec 11 peter 236   {
797 01 Jul 09 peter 237     if (node_exist(dir))
797 01 Jul 09 peter 238       return;
796 01 Jul 09 peter 239     std::string mother = directory_name(dir);
797 01 Jul 09 peter 240     mkdir_p(mother);
797 01 Jul 09 peter 241     mkdir(dir);
796 01 Jul 09 peter 242   }
796 01 Jul 09 peter 243
796 01 Jul 09 peter 244
226 11 Mar 07 peter 245   bool node_exist(const std::string& path)
226 11 Mar 07 peter 246   {
226 11 Mar 07 peter 247     struct stat buf;
226 11 Mar 07 peter 248     return !stat(path.c_str(),&buf);
226 11 Mar 07 peter 249   }
226 11 Mar 07 peter 250
226 11 Mar 07 peter 251
482 13 Oct 07 peter 252   int percent(int a, int b)
482 13 Oct 07 peter 253   {
482 13 Oct 07 peter 254     if (b)
482 13 Oct 07 peter 255       return (100*a)/b;
482 13 Oct 07 peter 256     return 0;
482 13 Oct 07 peter 257   }
482 13 Oct 07 peter 258
482 13 Oct 07 peter 259
115 30 Jun 06 peter 260   std::string pwd(void)
115 30 Jun 06 peter 261   {
1322 30 Nov 10 peter 262     char buffer[FILENAME_MAX];
1322 30 Nov 10 peter 263     if (!getcwd(buffer, FILENAME_MAX))
1245 25 Oct 10 peter 264       throw yat::utility::errno_error("pwd: ");
115 30 Jun 06 peter 265     return std::string(buffer);
115 30 Jun 06 peter 266   }
115 30 Jun 06 peter 267
297 08 May 07 peter 268
1098 13 Jun 10 peter 269   bool regexp(const std::string& pattern,  const std::string& str,
516 09 Dec 07 peter 270               std::vector<std::string>& vec)
516 09 Dec 07 peter 271   {
1439 20 Dec 11 peter 272     bool regexp__(std::string::const_iterator first1,
1098 13 Jun 10 peter 273                   std::string::const_iterator last1,
1098 13 Jun 10 peter 274                   std::string::const_iterator first2,
1098 13 Jun 10 peter 275                   std::string::const_iterator last2,
1098 13 Jun 10 peter 276                   std::vector<std::string>::iterator item);
1439 20 Dec 11 peter 277
1098 13 Jun 10 peter 278     // find number of special chars
1098 13 Jun 10 peter 279     size_t count=0;
1098 13 Jun 10 peter 280     for (std::string::const_iterator i=pattern.begin(); i!=pattern.end(); ++i)
1098 13 Jun 10 peter 281       if (*i=='*' || *i=='?' || *i=='[')
1098 13 Jun 10 peter 282         ++count;
1098 13 Jun 10 peter 283     vec.resize(count);
1098 13 Jun 10 peter 284     return regexp__(pattern.begin(), pattern.end(), str.begin(), str.end(),
1098 13 Jun 10 peter 285                     vec.begin());
1098 13 Jun 10 peter 286   }
516 09 Dec 07 peter 287
1439 20 Dec 11 peter 288   bool regexp__(std::string::const_iterator first1,
1098 13 Jun 10 peter 289                 std::string::const_iterator last1,
1098 13 Jun 10 peter 290                 std::string::const_iterator first2,
1098 13 Jun 10 peter 291                 std::string::const_iterator last2,
1098 13 Jun 10 peter 292                 std::vector<std::string>::iterator item)
1098 13 Jun 10 peter 293   {
1098 13 Jun 10 peter 294     if (first1==last1) {
1098 13 Jun 10 peter 295       return first2==last2;
516 09 Dec 07 peter 296     }
1098 13 Jun 10 peter 297     if (*first1 == '*') {
1098 13 Jun 10 peter 298       if (first2<last2) {
1098 13 Jun 10 peter 299         item->push_back(*first2);
1098 13 Jun 10 peter 300         if (regexp__(first1, last1, first2+1, last2, item))
1098 13 Jun 10 peter 301           return true;
1098 13 Jun 10 peter 302         item->resize(item->size()-1);
1098 13 Jun 10 peter 303       }
1098 13 Jun 10 peter 304       return regexp__(first1+1, last1, first2, last2, item+1);
1098 13 Jun 10 peter 305     }
1098 13 Jun 10 peter 306     if (*first1 == '?') {
1098 13 Jun 10 peter 307       if (first2==last2)
1098 13 Jun 10 peter 308         return false;
1098 13 Jun 10 peter 309       *item = *first2;
1098 13 Jun 10 peter 310       return regexp__(first1+1, last1, first2+1, last2, item+1);
1098 13 Jun 10 peter 311     }
1098 13 Jun 10 peter 312     if (*first1 == '[') {
1098 13 Jun 10 peter 313       if (first2==last2)
1098 13 Jun 10 peter 314         return false;
1098 13 Jun 10 peter 315       while (*first1 != ']') {
1098 13 Jun 10 peter 316         if (*first1 == *first2) {
1098 13 Jun 10 peter 317           *item = *first2;
1098 13 Jun 10 peter 318         }
1098 13 Jun 10 peter 319         ++first1;
1098 13 Jun 10 peter 320         assert(first1!=last1);
1098 13 Jun 10 peter 321       }
1098 13 Jun 10 peter 322       return regexp__(first1+1, last1, first2+1, last2, item+1);
1098 13 Jun 10 peter 323     }
1098 13 Jun 10 peter 324
1098 13 Jun 10 peter 325     if (first2==last2)
1098 13 Jun 10 peter 326       return false;
1098 13 Jun 10 peter 327     if (*first1 != *first2)
1098 13 Jun 10 peter 328       return false;
1098 13 Jun 10 peter 329     return regexp__(first1+1, last1, first2+1, last2, item);
516 09 Dec 07 peter 330   }
516 09 Dec 07 peter 331
516 09 Dec 07 peter 332
1547 20 Oct 12 peter 333   std::string relative_path(const std::string& abs_path,const std::string& dir)
1547 20 Oct 12 peter 334   {
1547 20 Oct 12 peter 335     if (abs_path == dir)
1547 20 Oct 12 peter 336       return ".";
1547 20 Oct 12 peter 337
1547 20 Oct 12 peter 338     if (abs_path.substr(0,dir.size())==dir) {
1547 20 Oct 12 peter 339       size_t pos = dir.size();
1547 20 Oct 12 peter 340       if (abs_path[pos] == '/') {
1547 20 Oct 12 peter 341         ++pos;
1547 20 Oct 12 peter 342         if (pos==abs_path.size())
1547 20 Oct 12 peter 343           return ".";
1547 20 Oct 12 peter 344       }
1547 20 Oct 12 peter 345       return abs_path.substr(pos);
1547 20 Oct 12 peter 346     }
1547 20 Oct 12 peter 347     assert(0 && "this case is not implemented");
1547 20 Oct 12 peter 348     return "";
1547 20 Oct 12 peter 349   }
1547 20 Oct 12 peter 350
1547 20 Oct 12 peter 351
1423 16 Dec 11 peter 352   void remove(const std::string& fn)
1423 16 Dec 11 peter 353   {
1423 16 Dec 11 peter 354     if (::remove(fn.c_str())) {
1423 16 Dec 11 peter 355       std::string msg("remove: ");
1423 16 Dec 11 peter 356       msg += fn;
1423 16 Dec 11 peter 357       throw yat::utility::errno_error(msg);
1423 16 Dec 11 peter 358     }
1423 16 Dec 11 peter 359   }
1423 16 Dec 11 peter 360
1423 16 Dec 11 peter 361
1132 16 Jul 10 peter 362   void rename(const std::string& from, const std::string to)
1132 16 Jul 10 peter 363   {
1132 16 Jul 10 peter 364     int code = ::rename(from.c_str(), to.c_str());
1132 16 Jul 10 peter 365     if (code){
1132 16 Jul 10 peter 366       std::stringstream ss;
1186 27 Aug 10 peter 367       ss << "rename" << from << " to " << to << ": ";
1186 27 Aug 10 peter 368       throw yat::utility::errno_error(ss.str());
1132 16 Jul 10 peter 369     }
1132 16 Jul 10 peter 370   }
1132 16 Jul 10 peter 371
1132 16 Jul 10 peter 372
514 09 Dec 07 peter 373   void replace(std::string& str, std::string old_str, std::string new_str)
514 09 Dec 07 peter 374   {
514 09 Dec 07 peter 375     std::string::iterator iter(str.begin());
514 09 Dec 07 peter 376     while ((iter=search(iter, str.end(), old_str)) != str.end()) {
514 09 Dec 07 peter 377       size_t i = iter-str.begin();
1439 20 Dec 11 peter 378       str = std::string(str.begin(), iter) + new_str +
514 09 Dec 07 peter 379         std::string(iter+old_str.size(), str.end());
514 09 Dec 07 peter 380       // pointing to char after substr we just inserted
1439 20 Dec 11 peter 381       iter = str.begin() + (i+new_str.size());
514 09 Dec 07 peter 382     }
514 09 Dec 07 peter 383   }
514 09 Dec 07 peter 384
514 09 Dec 07 peter 385
297 08 May 07 peter 386   void touch(std::string str)
297 08 May 07 peter 387   {
297 08 May 07 peter 388     if (!node_exist(str)) {
297 08 May 07 peter 389       std::ofstream os(str.c_str());
297 08 May 07 peter 390       os.close();
297 08 May 07 peter 391     }
297 08 May 07 peter 392   }
297 08 May 07 peter 393
201 09 Sep 06 peter 394
309 12 May 07 peter 395   std::string match(std::string::const_iterator& first,
309 12 May 07 peter 396                     const std::string::const_iterator& last,
309 12 May 07 peter 397                     std::string str)
309 12 May 07 peter 398   {
309 12 May 07 peter 399     if (match_begin(first, last, str)){
309 12 May 07 peter 400       first+=str.size();
309 12 May 07 peter 401       return str;
309 12 May 07 peter 402     }
309 12 May 07 peter 403     return std::string();
309 12 May 07 peter 404   }
309 12 May 07 peter 405
149 12 Aug 06 jari 406 }} // end of namespace svndigest and namespace theplu