LCOV - code coverage report
Current view: top level - okssystem/src - File.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 381 0
Test Date: 2025-12-21 13:07:08 Functions: 0.0 % 60 0

            Line data    Source code
       1              : /*
       2              :  *  File.cxx
       3              :  *  ers
       4              :  *
       5              :  *  Created by Matthias Wiesmann on 04.01.05.
       6              :  *  Copyright 2005 CERN. All rights reserved.
       7              :  *
       8              :  */
       9              : 
      10              : #include <unistd.h>
      11              : #include <stdio.h>
      12              : #include <libgen.h>
      13              : #include <unistd.h>
      14              : #include <fcntl.h>
      15              : #include <errno.h>
      16              : #include <assert.h>
      17              : #include <dirent.h>
      18              : #include <sys/types.h>
      19              : #include <sys/stat.h>
      20              : #include <sys/param.h>
      21              : #include <iostream>
      22              : #include <sstream>
      23              : #include <fstream>
      24              : #include <pwd.h>
      25              : 
      26              : #include "ers/ers.hpp"
      27              : 
      28              : #include "okssystem/File.hpp"
      29              : #include "okssystem/exceptions.hpp"
      30              : #include "okssystem/Executable.hpp"
      31              : #include "okssystem/User.hpp"
      32              : 
      33              : #define SPACE_CHAR ' ' 
      34              : 
      35              : const char * const OksSystem::File::HUMAN_SIZE_STR[] = { "B", "KB", "MB", "GB" };
      36              : const char * const OksSystem::File::HUMAN_OPEN_STR[] = { "READ", "WRITE", "NOBLOCK", "APPEND", "CREATE", "TRUNCATE","EXCLUSIVE"  };
      37              : const char * const OksSystem::File::FILE_COMMAND_PATH = "/usr/bin/file";
      38              : const char * const OksSystem::File::FILE_FLAG_STR = "-rwxS";
      39              : const char * const OksSystem::File::FILE_PROTOCOL = "file";
      40              : 
      41              : 
      42              : #define READ_CHAR_CODE (OksSystem::File::FILE_FLAG_STR[1])
      43              : #define WRITE_CHAR_CODE (OksSystem::File::FILE_FLAG_STR[2])
      44              : #define EXECUTE_CHAR_CODE (OksSystem::File::FILE_FLAG_STR[3])
      45              : #define NOTHING_CHAR_CODE (OksSystem::File::FILE_FLAG_STR[0])
      46              : #define SETUID_CHAR_CODE (OksSystem::File::FILE_FLAG_STR[4])
      47              : 
      48              : #define SLASH_CHAR '/' 
      49              : #define COLON_CHAR ':'
      50              : #define DOT_CHAR '.' 
      51              : 
      52              : const int OksSystem::File::KILOBYTE = 1024;
      53              : 
      54              : 
      55              : // --------------------------------------
      56              : // Static Methods
      57              : // --------------------------------------
      58              : 
      59              : 
      60              : /** Extracts the protocol part of an url. 
      61              :   * The protocol part is everything until the colon (:)
      62              :   * \param url an url 
      63              :   * \return the protocol part of an empty string 
      64              :   */
      65              : 
      66            0 : std::string OksSystem::File::protocol(const std::string &url) throw() {
      67            0 :     std::string::size_type colon = url.find(COLON_CHAR);
      68            0 :     if (colon==std::string::npos) return std::string();
      69            0 :     return url.substr(0,colon);
      70              : } // protocol
      71              : 
      72              : /** Extracts the extension of an url or path 
      73              :   * \param url an url or file path 
      74              :   * \return the extension (without the dot) or an empty string 
      75              :   */
      76              : 
      77            0 : std::string OksSystem::File::extension(const std::string &url) throw() {
      78            0 :     std::string::size_type dot = url.rfind(DOT_CHAR);
      79            0 :     if (dot==std::string::npos) return std::string();
      80            0 :     return url.substr(dot+1);
      81              : } // extension
      82              : 
      83              : /** Extracts the short file name of an url or path 
      84              :   * \param url an url or file path 
      85              :   * \return the short name or the full url if it cannot be found 
      86              :   */
      87              : 
      88            0 : std::string OksSystem::File::short_name(const std::string &url) throw() {
      89            0 :     std::string::size_type slash = url.rfind(SLASH_CHAR);
      90            0 :     if (slash==std::string::npos) return url;
      91            0 :     return url.substr(slash+1);
      92              : } // extension
      93              : 
      94              : /** Extacts the uri part of an url.
      95              :   * The uri of an url is everything except the protocol part
      96              :   * In the case of \c file or \c http urls, the uri is the local path 
      97              :   * \param url an url
      98              :   * \return the uri or the full url if no colon in the string
      99              :   */
     100              : 
     101            0 : std::string OksSystem::File::uri(const std::string &url) throw() {
     102            0 :     std::string::size_type colon = url.find(COLON_CHAR);
     103            0 :     if (colon==std::string::npos) return url;
     104            0 :     return url.substr(colon+1);
     105              : } // uri
     106              : 
     107              : 
     108              : /** Calculates the depth of a file. 
     109              :   * This depth is the number of parent directories.
     110              :   * Files in the root directory have depht of 0, 
     111              :   * other files have a depth of their parent's depth + 1
     112              :   * \param path to analyze 
     113              :   * \return depth or -1 if the format of the path is not understood. 
     114              :   */
     115              : 
     116            0 : int OksSystem::File::depth(const std::string &path) throw() {
     117            0 :     if (path[0] == SLASH_CHAR) {
     118            0 :         int count = 0;
     119            0 :         std::string rest = path.substr(1); 
     120            0 :         while(! rest.empty()) {
     121            0 :             std::string::size_type slash = rest.find(SLASH_CHAR);
     122            0 :             if (slash==std::string::npos) return count;
     123            0 :             count++;
     124            0 :             rest = rest.substr(slash+1);
     125              :         } // while
     126            0 :         return count;   
     127            0 :     } // path with slash 
     128            0 :     if (protocol(path) == FILE_PROTOCOL) {
     129            0 :         return depth(uri(path));
     130              :     } //
     131              :     return -1;
     132              : } // depth
     133              : 
     134              : /** Extracts the first line of a text 
     135              :   * \param text the text to process
     136              :   * \return the first line of the text
     137              :   */
     138              : 
     139            0 : std::string OksSystem::File::first_line(const std::string &text) {
     140            0 :     std::string::size_type nl = text.find('\n');
     141            0 :     if (nl>0) return text.substr(0,nl); 
     142            0 :     return text;
     143              : } // first_line
     144              : 
     145              : 
     146              : /** Builds a \c File object ou of an url 
     147              :   * \param url the url, it must start with the file protocol
     148              :   * \return a File object
     149              :   */
     150              : 
     151            0 : OksSystem::File OksSystem::File::from_url(const std::string &url) {
     152            0 :     std::string prot = protocol(url);
     153            0 :     ERS_PRECONDITION(prot==FILE_PROTOCOL); 
     154            0 :     const std::string path = uri(url); 
     155            0 :     return File(path);
     156            0 : } // from_url
     157              : 
     158              : /** \return a string containing the working directory for the process */
     159              : 
     160            0 : std::string OksSystem::File::working_directory() {
     161            0 :     char *wd_buffer = getcwd(0,MAXPATHLEN);  
     162            0 :     if (wd_buffer) {
     163            0 :         std::string directory = std::string(wd_buffer);
     164            0 :         free(wd_buffer); 
     165            0 :         return directory;
     166            0 :     }
     167            0 :     std::string message("getting the current working directory");
     168            0 :     throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "getcwd", message.c_str() );
     169            0 : } // working_directory 
     170              : 
     171            0 : void OksSystem::File::working_directory(const File &dir) {
     172            0 :     const char * path = dir.c_full_name(); 
     173            0 :     const int status = ::chdir(path); 
     174            0 :     if (status<0) {
     175            0 :       std::string message = "on directory " + dir.full_name(); 
     176            0 :       throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "chdir", message.c_str() );
     177            0 :     }
     178            0 : } // working_directory
     179              : 
     180              : 
     181              : /** Expands a file containing a home directory reference (~user). 
     182              :   */
     183              : 
     184              : 
     185            0 : std::string OksSystem::File::expand_home(const std::string path) {
     186            0 :     ERS_PRECONDITION(! path.empty());
     187            0 :     ERS_PRECONDITION(path[0] == '~'); 
     188            0 :     std::string::size_type slash = path.find('/');
     189            0 :     const std::string user_name = path.substr(1,slash-1); 
     190            0 :     const std::string rest_path = path.substr(slash);  
     191            0 :     OksSystem::User user;
     192            0 :     if (! user_name.empty()) {
     193            0 :         user = OksSystem::User(user_name);
     194              :     } 
     195            0 :     return user.home() + rest_path;
     196            0 : } // home_directory
     197              : 
     198              : 
     199              : /** Builds a prettyfied version of permissions. 
     200              : * This should look similar to what \c ls returns with the -l flag
     201              : * \param permissions the permission to beautify 
     202              : * \return a string containing the beautified permissions 
     203              : */
     204              : 
     205            0 : std::string OksSystem::File::pretty_permissions(mode_t permissions) {
     206            0 :     char buffer[11];
     207            0 :     buffer[0] = (permissions & S_ISUID) ? SETUID_CHAR_CODE : NOTHING_CHAR_CODE;
     208            0 :     buffer[1] = (permissions & S_IRUSR) ? READ_CHAR_CODE : NOTHING_CHAR_CODE;
     209            0 :     buffer[2] = (permissions & S_IWUSR) ? WRITE_CHAR_CODE : NOTHING_CHAR_CODE;
     210            0 :     buffer[3] = (permissions & S_IXUSR) ? EXECUTE_CHAR_CODE : NOTHING_CHAR_CODE;
     211            0 :     buffer[4] = (permissions & S_IRGRP) ? READ_CHAR_CODE : NOTHING_CHAR_CODE;
     212            0 :     buffer[5] = (permissions & S_IWGRP) ? WRITE_CHAR_CODE : NOTHING_CHAR_CODE;
     213            0 :     buffer[6] = (permissions & S_IXGRP) ? EXECUTE_CHAR_CODE : NOTHING_CHAR_CODE;
     214            0 :     buffer[7] = (permissions & S_IROTH) ? READ_CHAR_CODE : NOTHING_CHAR_CODE;
     215            0 :     buffer[8] = (permissions & S_IWOTH) ? WRITE_CHAR_CODE : NOTHING_CHAR_CODE;
     216            0 :     buffer[9] = (permissions & S_IXOTH) ? EXECUTE_CHAR_CODE : NOTHING_CHAR_CODE;
     217            0 :     buffer[10] = '\0';
     218            0 :     return std::string(buffer); 
     219              : } // pretty_permissions
     220              : 
     221              : /** Builds a prettyfied version of flags used by the \c open OksSystem call
     222              : * \param flags as passed to \c open
     223              : * \return a string containing the beautified flags
     224              : * \note This method only handles flags available accross plateforms. 
     225              : */
     226              : 
     227            0 : std::string OksSystem::File::pretty_open_flag(int flags) {
     228            0 :     std::ostringstream flag_str;
     229            0 :     if (flags & O_WRONLY) {
     230            0 :         flag_str << HUMAN_OPEN_STR[1];
     231            0 :     } else if (flags & O_RDWR) {
     232            0 :         flag_str << HUMAN_OPEN_STR[0] << "-" << HUMAN_OPEN_STR[1];
     233              :     } else {
     234            0 :         flag_str << HUMAN_OPEN_STR[0];
     235              :     }
     236            0 :     if (flags & O_NONBLOCK) {
     237            0 :         flag_str << "/" << HUMAN_OPEN_STR[2];
     238              :     } 
     239            0 :     if (flags & O_APPEND) {
     240            0 :         flag_str << "/" << HUMAN_OPEN_STR[3];
     241              :     }
     242            0 :     if (flags & O_CREAT) {
     243            0 :         flag_str << "/" << HUMAN_OPEN_STR[4];
     244              :     }
     245            0 :     if (flags & O_TRUNC) {
     246            0 :         flag_str << "/" << HUMAN_OPEN_STR[5];
     247              :     } 
     248            0 :     if (flags & O_EXCL) {
     249            0 :         flag_str << "/" << HUMAN_OPEN_STR[6];
     250              :     }
     251            0 :     flag_str << "(" << flags << ")";
     252            0 :     return flag_str.str();
     253            0 : } // pretty_open_permission
     254              : 
     255              : 
     256            0 : int  OksSystem::File::unit(int u) {
     257            0 :     ERS_PRECONDITION(u >= 0);
     258            0 :     if (u==0) return 1;
     259            0 :     return KILOBYTE * unit(u-1);
     260              : } // unit
     261              : 
     262              : /** Builds a human readable textual description of a file size.
     263              : * The file size is expressed in Gigabytes (GB), Megabytes (MB) and Kilobytes (KB) and Bytes (B).
     264              : * \param size the size of the file
     265              : * \param cut_small should the display only contain the highest quantity? 
     266              : * For example if a file is 1 gigabyte and 20 bytes, if \c cut_small is \c true, then
     267              : * the 20 bytes are ignored. 
     268              : * \return a string containing the textual description
     269              : */
     270              : 
     271            0 : std::string OksSystem::File::pretty_size(size_t size, bool cut_small) {
     272            0 :     if (0==size) return "0";
     273            0 :     std::ostringstream size_str;
     274              :     bool writen_something = false;
     275            0 :     for(int i=3;i>=0;i--) {
     276            0 :         const unsigned int size_unit = unit(i);
     277            0 :         if (size > size_unit && ! (cut_small && writen_something)) {
     278            0 :             const int amount = size / size_unit;
     279            0 :             size = size % size_unit;
     280            0 :             size_str << amount << SPACE_CHAR << HUMAN_SIZE_STR[i];
     281              :             writen_something = true;
     282              :         } // if unit is present
     283              :     } // loop
     284            0 :     return size_str.str(); 
     285            0 : } // pretty_size
     286              : 
     287              : // --------------------------------------
     288              : // Constructors
     289              : // --------------------------------------
     290              : 
     291              : 
     292              : /** Constructor 
     293              :   * \note This method does not create a file, it simply builds an object describing a file 
     294              :   */
     295              : 
     296            0 : OksSystem::File::File(const std::string &name) {
     297            0 :     set_name(name); 
     298            0 : } // File
     299              : 
     300              : /** Constructor 
     301              :   * \overload
     302              :   */
     303              : 
     304            0 : OksSystem::File::File(const char* c_name) {
     305            0 :     ERS_PRECONDITION(c_name); 
     306            0 :     std::string name = std::string(c_name);
     307            0 :     set_name(name); 
     308            0 : } // File
     309              : 
     310              : /** Constructor 
     311              : * \overload
     312              : */
     313              : 
     314            0 : OksSystem::File::File(const File& other) {
     315            0 :     set_name(other.m_full_name);
     316            0 : } // File
     317              : 
     318              : // --------------------------------------
     319              : // Operators
     320              : // --------------------------------------
     321              : 
     322              : 
     323              : 
     324            0 : OksSystem::File::operator std::string() const throw() {
     325            0 :     return m_full_name;
     326              : } // operator std::string
     327              : 
     328            0 : OksSystem::File::operator const char*() const throw() {
     329            0 :     return m_full_name.c_str();
     330              : } // operator const char*
     331              : 
     332              : /** Cast to boolean, checks if the file exists 
     333              :   * \return \c true if the file exists 
     334              :   */
     335              : 
     336            0 : OksSystem::File::operator bool() const throw() {
     337            0 :     return exists(); 
     338              : } // operator bool
     339              : 
     340              : /** Comparison operator 
     341              :   * As path are canonicalized, we simply compare the full paths. 
     342              :   * \param other file to compare this file to
     343              :   * \return true if both file are equal 
     344              :   * \note This comparison method does not taken hard links into account 
     345              :   */
     346              : 
     347            0 : bool OksSystem::File::equals(const File &other) const throw() {
     348            0 :     return (m_full_name == other.m_full_name);
     349              : } // operator==
     350              : 
     351              : /** Cast to size type 
     352              :   * \return the size of the file
     353              :   * \see size()
     354              :   */
     355              : 
     356            0 : OksSystem::File::operator size_t() const {
     357            0 :     return size();
     358              : } // operator size_t
     359              : 
     360              : 
     361              : 
     362              : 
     363              : // --------------------------------------
     364              : // Methods
     365              : // --------------------------------------
     366              : 
     367              : 
     368              : /** Sets the name for a file.
     369              :   * The path name is first expanded and the canonlicalized. 
     370              :   * Expension means the following
     371              :   * \li If the path starts with / nothing is done 
     372              :   * \li If the path starts with ~ the username is resolved and the path starts from there
     373              :   * \li If the path starts with any other character, the working directory is prepended. 
     374              :   * 
     375              :   * The path is then made canonical, this implies removing all ./ and ../ sequences, 
     376              :   * and resolving all symbolic links. 
     377              :   * \param name the name of the file
     378              :   */
     379              : 
     380            0 : void OksSystem::File::set_name(const std::string &name) {
     381            0 :     ERS_PRECONDITION(! name.empty()); 
     382            0 :     const char c = name[0];
     383            0 :     std::string long_path;
     384            0 :     switch (c) {
     385            0 :         case '/' :
     386            0 :             long_path = name;
     387              :             break;
     388            0 :         case '~' : 
     389            0 :             long_path = expand_home(name); 
     390            0 :             break;
     391            0 :         default:
     392            0 :             long_path = working_directory() + "/" + name;
     393            0 :             break;
     394              :     } // switch     
     395            0 :     char buffer[PATH_MAX];
     396            0 :     const char* result = realpath(long_path.c_str(),buffer); 
     397            0 :     if (result==0) { // could not resolve path 
     398            0 :         m_full_name = long_path;
     399              :     } else { // we could canonicalize the path 
     400            0 :         m_full_name = buffer;
     401              :     } // 
     402            0 : } // set_name
     403              : 
     404              : /** \return the full (absolute) path of the file */
     405              : 
     406            0 : const std::string & OksSystem::File::full_name() const throw() {
     407            0 :     return m_full_name;
     408              : } // full_name
     409              : 
     410              : /** \return the full (absolute) path of the file */
     411              : 
     412            0 : const char* OksSystem::File::c_full_name() const throw() {
     413            0 :     return m_full_name.c_str(); 
     414              : } // c_full_name
     415              : 
     416              : 
     417              : /** \return the short name of the file - that is the name of the file in its directory */
     418              : 
     419            0 : std::string OksSystem::File::short_name() const throw() {
     420            0 :     return short_name(m_full_name);
     421              : } // short_name
     422              : 
     423              : /** Finds the name of the enclosing directory 
     424              :   * \return the path of the directory containing the file 
     425              :   */
     426              : 
     427            0 : std::string OksSystem::File::parent_name() const throw() {
     428            0 :   std::string::size_type size = m_full_name.size();
     429            0 :   std::string::size_type slash = m_full_name.rfind(SLASH_CHAR,size-1);
     430            0 :   if (slash==std::string::npos || slash==0) return ("/"); 
     431            0 :   return m_full_name.substr(0,slash); 
     432              : } // directory
     433              : 
     434              : /** \return the extension of the file */
     435              : 
     436            0 : std::string OksSystem::File::extension() const throw() {
     437            0 :     return extension(m_full_name);
     438              : } // extension
     439              : 
     440            0 : int OksSystem::File::depth() const throw() {
     441            0 :     return depth(m_full_name);
     442              : } // depth
     443              : 
     444              : /** \return the parent directory */
     445              : 
     446            0 : OksSystem::File OksSystem::File::parent() const {
     447            0 :     return File(parent_name());
     448              : } // parent
     449              : 
     450            0 : OksSystem::File OksSystem::File::child(const std::string &name) const {
     451            0 :     std::string child_name = m_full_name + "/" + name;
     452            0 :     return OksSystem::File(child_name);
     453            0 : } // child
     454              : 
     455            0 : OksSystem::File OksSystem::File::temporary(const std::string &prefix) const {
     456            0 :     char *tmp_name = tempnam(m_full_name.c_str(),prefix.c_str());
     457            0 :     if ( !tmp_name ) {
     458            0 :       std::string message = "while creating a valid filename in directory " + m_full_name;
     459            0 :       throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "tempnam", message.c_str() );
     460            0 :     }
     461            0 :     OksSystem::File tmp_file(tmp_name);
     462            0 :     free(tmp_name);
     463            0 :     return tmp_file;
     464              : } // temporary
     465              : 
     466              : 
     467              : /** Checks if the file exists in the fileOksSystem
     468              :   * \return \c true if the file exists, false otherwise 
     469              :   * \exception ers::IOIssue if an error occurs 
     470              :   */
     471              : 
     472            0 : bool OksSystem::File::exists() const throw() {
     473            0 :     struct stat file_status;
     474            0 :     const int result = stat(m_full_name.c_str(),&file_status);
     475            0 :     if (0==result) return true;
     476              :     return false;
     477              : } // exists
     478              : 
     479              : /** Extracts the mode information of the file. 
     480              :   * This is used to determine both the file type and the file permissions 
     481              :   * \return the mode of the file
     482              :   * \exception OksSystem::FStatFail if fstat fails
     483              :   */
     484              : 
     485            0 : mode_t OksSystem::File::get_mode() const {
     486            0 :     struct stat file_status;
     487            0 :     const int result = stat(m_full_name.c_str(),&file_status);
     488            0 :     if (0==result) {
     489            0 :         return file_status.st_mode;
     490              :     } // if
     491            0 :     std::string message = "on file/directory " + m_full_name;
     492            0 :     throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "stat", message.c_str() );
     493            0 : } // mode
     494              : 
     495              : 
     496              : /** \return the permissions for the file
     497              :   * \exception ers::IOIssue if an error occurs or the file does not exist 
     498              :   */
     499              : 
     500            0 : mode_t OksSystem::File::permissions() const {
     501            0 :     mode_t mode = get_mode();
     502            0 :     return (mode & 07777);
     503              : } // permissions
     504              : 
     505              : /** \return the prettfied permissions for the file
     506              :   * \exception ers::IOIssue if an error occurs or the file does not exist 
     507              :   */
     508              : 
     509            0 : std::string OksSystem::File::pretty_permissions() const {
     510            0 :     return pretty_permissions(permissions()); 
     511              : } // pretty_permissions
     512              : 
     513              : /** Converts permissions into a string 
     514              :   * \param permissions the permissions
     515              :   * \return a string contaning the permissions in octal form
     516              :   */
     517              : 
     518            0 : std::string OksSystem::File::to_string(mode_t permissions) throw() {
     519            0 :     std::ostringstream stream;
     520            0 :     stream.setf(std::ios::oct,std::ios::basefield);
     521            0 :     stream << permissions;
     522            0 :     return stream.str();
     523            0 : } // to_string
     524              : 
     525              : 
     526              : /** \return the size (in bytes) of the file
     527              :   * \exception OksSystem::IOIssue if an error occurs or the file does not exist 
     528              :   */
     529              : 
     530            0 : size_t OksSystem::File::size() const {
     531            0 :     struct stat file_status;
     532            0 :     const int result = stat(m_full_name.c_str(),&file_status);
     533            0 :     if (0==result) return file_status.st_size;
     534            0 :     std::string message = "on file/directory " + m_full_name;
     535            0 :     throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "stat", message.c_str() );
     536            0 : } // size 
     537              : 
     538              : /** \return the user-id of the owner of the file
     539              :   * \exception OksSystem::IOIssue if an error occurs or the file does not exist 
     540              :   */
     541              : 
     542            0 : uid_t OksSystem::File::owner_id() const {
     543            0 :     struct stat file_status;
     544            0 :     const int result = stat(m_full_name.c_str(),&file_status);
     545            0 :     if (0==result) return file_status.st_uid;
     546            0 :     std::string message = "on file/directory " + m_full_name;
     547            0 :     throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "stat", message.c_str() );
     548            0 : } // owner_id
     549              : 
     550            0 : OksSystem::User OksSystem::File::owner() const {
     551            0 :     return User(owner_id());
     552              : } // owner
     553              : 
     554              : 
     555              : /** \return the group-id of the group of the file
     556              :   * \exception ers::IOIssue if an error occurs or the file does not exist 
     557              :   */
     558              : 
     559            0 : gid_t OksSystem::File::group() const {
     560            0 :     struct stat file_status;
     561            0 :     const int result = stat(m_full_name.c_str(),&file_status);
     562            0 :     if (0==result) return file_status.st_gid;
     563            0 :     std::string message = "on file/directory " + m_full_name;
     564            0 :     throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "stat", message.c_str() );
     565            0 : } // owner
     566              : 
     567              : 
     568              : /** Checks if the file a regular file (i.e not a directory, named pipe or anything else). 
     569              :   * \return \c true if the file is regular 
     570              :   * \exception ers::IOIssue if an error occurs or the file does not exist 
     571              :   */
     572              : 
     573            0 : bool OksSystem::File::is_regular() const {
     574            0 :     const mode_t mode = get_mode();
     575            0 :     return (mode & S_IFREG);
     576              : } // is_regular
     577              : 
     578              : 
     579              : /** Checks if the file a directory 
     580              :  * \return \c true if the file is a directory  
     581              :  * \exception ers::IOIssue if an error occurs or the file does not exist 
     582              :  */
     583              : 
     584            0 : bool OksSystem::File::is_directory() const {
     585            0 :     const mode_t mode = get_mode();
     586            0 :     return (mode & S_IFDIR);
     587              : } // is_regular
     588              : 
     589              : /** Checks if the file a named pipe (FIFO) 
     590              :  * \return \c true if the file is named pipe (FIFO) 
     591              :  * \exception ers::IOIssue if an error occurs or the file does not exist 
     592              :  */
     593              : 
     594            0 : bool OksSystem::File::is_fifo() const {
     595            0 :     const mode_t mode = get_mode();
     596            0 :     return (mode & S_IFIFO);
     597              : } // is_pipe
     598              : 
     599              : 
     600            0 : std::string OksSystem::File::file_type() const {
     601            0 :     OksSystem::Executable file_command(FILE_COMMAND_PATH); 
     602            0 :     OksSystem::Executable::param_collection params;
     603            0 :     params.push_back("-b"); 
     604            0 :     params.push_back(full_name()); 
     605            0 :     return first_line(file_command.pipe_in(params)); 
     606            0 : } // file_type
     607              :     
     608              : /** Builds a vector containing all the files contained in a directory 
     609              :   * \return a vector of files contained in the directory 
     610              :   * \exception OksSystem::OpenFail if the directory could not be openend
     611              :   * \exception OksSystem::CloseFail if the directory cannot be closed 
     612              :   */
     613              : 
     614            0 : OksSystem::File::file_list_t OksSystem::File::directory() const {
     615            0 :     file_list_t file_vector;
     616            0 :     DIR* directory_ptr = opendir(m_full_name.c_str());
     617            0 :     if (! directory_ptr) {
     618            0 :       std::string message = "on directory " + m_full_name;
     619            0 :       throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "opendir", message.c_str() );
     620            0 :     }
     621            0 :     while(true) {
     622            0 :         struct dirent* directory_entry = readdir(directory_ptr); 
     623            0 :         if (directory_entry) {
     624            0 :             const std::string name = directory_entry->d_name;
     625            0 :             if ((name!=".") && (name!="..")) {
     626            0 :                 std::string path = m_full_name + "/" + name;
     627            0 :                 OksSystem::File file(path); 
     628            0 :                 file_vector.push_back(file);
     629            0 :             } // if
     630            0 :         } else {
     631              :             break;
     632              :         } // if / else
     633            0 :     } // while
     634            0 :     int status = closedir(directory_ptr);
     635            0 :     if (status<0) {
     636            0 :       std::string message = "on directory " + m_full_name;
     637            0 :       throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "closedir", message.c_str() );
     638            0 :     }
     639            0 :     return file_vector;
     640            0 : } // directory
     641              : 
     642              : /** Unlinks (i.e deletes) a file. 
     643              :   * \exception ers::IOIssue if an error occurs or the file does not exist 
     644              :   */
     645              : 
     646            0 : void OksSystem::File::unlink() const {
     647            0 :     const int result = ::unlink(m_full_name.c_str());
     648            0 :     if (0==result) return;
     649            0 :     throw OksSystem::RemoveFileIssue( ERS_HERE, errno, m_full_name.c_str() ); 
     650              : } //unlink
     651              : 
     652            0 : void OksSystem::File::rmdir() const {
     653            0 :     const int result = ::rmdir(m_full_name.c_str());
     654            0 :     if (0==result) return;
     655            0 :     std::string message = "on directory " + m_full_name;
     656            0 :     throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "rmdir", message.c_str() ); 
     657            0 : } // rmdir
     658              : 
     659              : 
     660              : /** Recursively delete files and directories.
     661              :   * If the file is a directory, all its child are deleted recursively. 
     662              :   * \exception OksSystem::UnlinkFail if \c unlink fails 
     663              :   */
     664              : 
     665            0 : void OksSystem::File::remove() const {
     666            0 :     if (is_directory()) {
     667            0 :         file_list_t childs = directory(); 
     668            0 :         for (file_list_t::const_iterator p=childs.begin();p!=childs.end();p++) {
     669            0 :             const File f = *p;
     670            0 :             if(f.exists()) {
     671            0 :               f.remove(); 
     672              :             }
     673            0 :         } // for
     674            0 :         rmdir();
     675            0 :     } else {
     676            0 :         unlink(); 
     677              :     } 
     678            0 : } // remove
     679              : 
     680              : 
     681              : /** Renames or moves a file. 
     682              :   * \param new_name the new name of the file 
     683              :   * \exception ers::IOIssue if an error occurs or the file does not exist 
     684              :   */
     685              : 
     686            0 : void OksSystem::File::rename(const File &other) const {
     687            0 :     const char *source = c_full_name() ;
     688            0 :     const char *dest = other.c_full_name();
     689            0 :     const int result = ::rename(source,dest); 
     690            0 :     if (0==result) return;
     691            0 :     throw OksSystem::RenameFileIssue( ERS_HERE, errno, source, dest );
     692              : } // rename
     693              : 
     694              : /** Sets the permissions of the file 
     695              :   * \param permissions the new permissions
     696              :   * \exception ers::IOIssue if an error occurs or the file does not exist 
     697              :   */
     698              :  
     699            0 : void OksSystem::File::permissions(mode_t perm) const {
     700            0 :   if(perm !=  permissions()) {
     701            0 :     const int result = ::chmod(m_full_name.c_str(),perm); 
     702            0 :     if (0==result) {
     703            0 :       return;
     704              :     }
     705            0 :     std::string message = "on file/directory " + m_full_name;
     706            0 :     throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "chmod", message.c_str());
     707            0 :   }
     708              : } // permissions
     709              : 
     710              : /** Creates a directory
     711              :   * The current object is taken as the name of the directory to create. 
     712              :   * \param perm the permissions to associate with the directory 
     713              :   * \note if the directory exists, the method attempts to do a \c chmod 
     714              :   * to match the permissions
     715              :   */ 
     716              : 
     717            0 : void OksSystem::File::make_dir(mode_t perm) const {
     718              : 
     719            0 :     errno = 0;
     720            0 :     const int result = ::mkdir(m_full_name.c_str(),perm);
     721            0 :     int mkdir_error = errno;
     722              : 
     723            0 :     if (0==result) {
     724            0 :       try {
     725            0 :         permissions(perm);
     726              :       }
     727            0 :       catch (OksSystem::OksSystemCallIssue &e){
     728            0 :         std::string message = "on directory " + m_full_name;
     729            0 :         throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "mkdir -> chmod", message.c_str() ); 
     730            0 :       }
     731              :       return;
     732              :     } else {
     733            0 :       if (exists()) {
     734            0 :         if (is_directory()) { // already exists we attempt a chmod
     735            0 :           try {
     736            0 :             permissions(perm);
     737              :           }
     738            0 :           catch (OksSystem::OksSystemCallIssue &e){
     739              :             // ignore this case...
     740            0 :           }
     741            0 :           return;
     742              :         } // is directory
     743              :       } else { // exists
     744            0 :         std::string message = "on directory " + m_full_name;
     745            0 :         throw OksSystem::OksSystemCallIssue(ERS_HERE, mkdir_error, "mkdir", message.c_str()); 
     746            0 :       }
     747              :     }
     748              :     
     749              : } // makedir
     750              : 
     751              : /** Builds a full path. 
     752              :   * The current object is taken as the name of a directory to create. 
     753              :   * This method creates all the parent directories as needed
     754              :   * \param permissions the permissions to associate with the directory
     755              :   * \note If parent directories are created, their permissions will be those
     756              :   *       defined in \c permissions ORed with 0700. 
     757              :   *       This is needed to ensure we can actually write into the directories 
     758              :   *       we create. 
     759              :   */
     760              : 
     761            0 : void OksSystem::File::make_path(mode_t perm) const { 
     762            0 :     const File father = parent(); 
     763            0 :     if (! father.exists()) {
     764            0 :         mode_t father_permission = perm | S_IRWXU;// we need rights to write sons
     765            0 :         father.make_path(father_permission); 
     766              :     } // if
     767            0 :     make_dir(perm); 
     768            0 : } // makepath
     769              : 
     770              : /** Makes sure that the path for a file exists 
     771              :   * This is done by calling \c make_path on the parent directory 
     772              :   * \param permissions permissions used to create directories
     773              :   * \see OksSystem::File::make_path()
     774              :   */
     775              : 
     776            0 : void  OksSystem::File::ensure_path(mode_t perm) const {
     777            0 :     const File father = parent();
     778            0 :     father.make_path(perm); 
     779            0 : } // ensure_path
     780              : 
     781              : 
     782              : /** Creates a named pipe (FIFO) 
     783              :   * \param perm the permission to give the pipe
     784              :   */
     785              : 
     786            0 : void OksSystem::File::make_fifo(mode_t perm) const {
     787            0 :     if (exists()) {
     788            0 :         if (is_fifo()) {
     789            0 :           if(perm != permissions()) {
     790            0 :             permissions(perm); 
     791            0 :             return;
     792              :           } else {
     793              :             return;
     794              :           }
     795              :         } // is_fifo
     796              :     } // exists
     797            0 :     const int status = ::mkfifo(m_full_name.c_str(),perm); 
     798            0 :     if (status==0) {
     799            0 :       permissions(perm);
     800            0 :       return;
     801              :     } 
     802            0 :     std::string message = "while creating FIFO " + m_full_name;
     803            0 :     throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "mkfifo", message.c_str() ); 
     804            0 : } // makefifo
     805              :     
     806              : 
     807              : 
     808              : 
     809              : /** Conversion into a input stream pointer
     810              :   * This actually creates a new input stream that reads from the file. 
     811              :   * \return a dynamically allocated input stream 
     812              :   * \exception ers::IOIssue if an error occurs or the file does not exist 
     813              :   */
     814              : 
     815            0 : std::istream* OksSystem::File::input() const {
     816            0 :     try {
     817            0 :         std::ifstream *stream = new std::ifstream(m_full_name.c_str());
     818            0 :         stream->exceptions(std::ios::failbit | std::ios::badbit); 
     819            0 :         return stream;
     820            0 :     } catch (std::ios_base::failure &ex) {
     821            0 :         throw OksSystem::OpenFileIssue( ERS_HERE, errno, m_full_name.c_str(), ex ); 
     822            0 :     } // catch
     823              : } // std::istream*
     824              : 
     825              : /** Conversion into an output stream pointer
     826              :  * This actually creates a new output stream that writes to the file. 
     827              :  * \return a dynamically allocated output stream 
     828              :  * \param append is the file opened in append mode 
     829              :  * \exception ers::IOIssue if an error occurs
     830              :  */
     831              :     
     832            0 : std::ostream* OksSystem::File::output(bool append) const {
     833            0 :     try {
     834            0 :         std::ios::openmode mode = std::ios::out;
     835            0 :         if (append) {
     836            0 :             mode |= std::ios::app;
     837              :         }
     838            0 :         std::ofstream *stream = new std::ofstream(m_full_name.c_str(),mode);
     839            0 :         stream->exceptions(std::ios::failbit | std::ios::badbit); 
     840            0 :         return stream;
     841            0 :     } catch (std::ios_base::failure &ex) {
     842            0 :         throw OksSystem::OpenFileIssue( ERS_HERE, errno, m_full_name.c_str(), ex ); 
     843            0 :     } // catch
     844              : } // std::ostream*
     845              : 
     846              : /** Stream a file object into a STL stream. 
     847              :   * \param stream destination stream.
     848              :   * \param file the file to write
     849              :   * \return the stream passed as parameter
     850              :   */
     851              : 
     852            0 : std::ostream& operator<<(std::ostream& stream, const OksSystem::File& file) {
     853            0 :     stream << OksSystem::File::FILE_PROTOCOL << ":/" << file.full_name();
     854            0 :     return stream;
     855              : } // operator<<
     856              : 
     857            0 : bool operator ==(const OksSystem::File &a, const OksSystem::File &b)  throw() {
     858            0 :     return a.equals(b); 
     859              : } // operator ==
     860              : 
     861            0 : bool operator !=(const OksSystem::File &a, const OksSystem::File &b)  throw() {
     862            0 :     return ! a.equals(b); 
     863              : } // operator !=
     864              : 
     865              : 
     866              : 
     867              : 
     868              : 
        

Generated by: LCOV version 2.0-1