Logo Search packages:      
Sourcecode: passepartout version File versions  Download package

filesys.cc

///
// Copyright (C) 2002 - 2004, Fredrik Arnerup & Rasmus Kaj, See COPYING
///
#include "filesys.h"
#include "stringutil.h"
#include "os.h"
#include <errno.h>
#include <memory>
#include <unistd.h>
#include <stdexcept>
#include "defines.h"
#include <sys/stat.h>
#ifndef HAVE_MKDTEMP
#include <sys/types.h>
#endif

using std::string;

ClibException::ClibException(const string& msg)
  : runtime_error(msg + ": " + strerror(errno))
{}

bool exists(const string& filename) {
  return access(filename.c_str(), F_OK) == 0;
}

bool access(const string& filename, int mode) {
  int c_mode = 0;
  if(mode & std::ios::in)  c_mode |= R_OK;
  if(mode & std::ios::out) c_mode |= W_OK;
  int result = access(filename.c_str(), c_mode);
  return result == 0;
}

bool executable(const std::string& filename) {
  return access(filename.c_str(), X_OK) == 0;
}

time_t modified(const std::string& filename) {
  struct stat buf;
  if(stat(filename.c_str(), &buf) == 0) // returns 0 on success, -1 otherwise
    return buf.st_mtime;
  else
    throw ClibException("Failed to stat(2) \"" + filename + '"');
}

string suffix(const string& filename) {
  const string::size_type pos = filename.find_last_of('.');
  if(pos == string::npos)
    return string();
  return filename.substr(pos+1);
}

string no_suffix(const string& filename) {
  const string::size_type pos = filename.find_last_of('.');
  if(pos == string::npos)
    return string();
  return filename.substr(0, pos);
}

string basename(const string& filename) {
  const string::size_type pos = filename.find_last_of('/');
  if(pos == string::npos)
    return filename;
  return filename.substr(pos+1);
}

string path(const string& filename) {
  const string::size_type pos = filename.find_last_of('/');
  if(pos == string::npos)
    return "./";
  return filename.substr(0, pos+1);
}

string expand_path(const string& filename) {
  unsigned int path_max;
  // from man 3 realpath:
#ifdef PATH_MAX
  path_max = PATH_MAX;
#else
  // pathconf doesn't seem to like empty strings
  path_max = pathconf (filename.empty()?".":filename.c_str(), _PC_PATH_MAX);
  if (path_max <= 0)
    path_max = 4096;
#endif

  std::auto_ptr<char> resolved_path(new char[path_max]);
  
  if(realpath(filename.empty()?".":filename.c_str(), resolved_path.get()))
    return resolved_path.get();
  else
    throw ClibException("Failed to resolve \"" + filename + '"');
}

string relative_path(const string& start_path, const string& filename) {
  if(start_path.empty() || !starts_with(filename, start_path))
    return filename;
  int i = start_path.length();
  if(filename[i]=='/')
    i++;
  return filename.substr(i);
}

void unlink(const std::string& filename) {
  if(::unlink(filename.c_str()) != 0)
    throw ClibException("Failed to unlink \"" + filename + '"');
}

void rmdir(const std::string& dirname) {
  if(::rmdir(dirname.c_str()) != 0)
    throw ClibException("Failed to rmdir \"" + dirname + '"');
}

std::string mkdtemp(const std::string& tmpl_name) {
  if(tmpl_name.empty())
    throw std::invalid_argument("Template for mkdtemp must be non-empty");
  
  string name;
  if(tmpl_name[0] == '/') 
    name = tmpl_name;
  else {
    // A non-relative name, put in $TMPDIR
    std::string tmpdir = os::get_env("TMPDIR");
    if(tmpdir.empty())
      name = "/tmp/" + tmpl_name;
    else if(*tmpdir.end() == '/')
      name = tmpdir + tmpl_name;
    else
      name = tmpdir + '/' + tmpl_name;
  }
#ifdef HAVE_MKDTEMP
  char* actual = ::mkdtemp(strcpy(new char[name.length()+1], name.c_str()));
  const string result = actual;
  delete[] actual;
  
#else
#warning Using workaround for lack of mkdtemp.  Probably buggy.
  // This is seriously bad: Not only is there a possible race condition, the
  // man page for mktemp on solaris states that "Only 26 unique file names per
  // thread can be created for each unique template".
  char *actual = ::mktemp(strcpy(new char[name.length()+1], name.c_str()));
  const string result = actual;
  if(::mkdir(actual, 0700) != 0)
    throw ClibException("Failed to mkdir \"" + result + "\"");
  delete[] actual;
  
#endif
  return result;
}

Generated by  Doxygen 1.6.0   Back to index