LCOV - code coverage report
Current view: top level - okssystem/src - File.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 379 0
Test Date: 2026-07-12 15:23:06 Functions: 0.0 % 60 0

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

Generated by: LCOV version 2.0-1