/* Copyright (C) 2002 The gtkmm Development Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*/
_DEFS(glibmm,glib)
#ifndef DOXYGEN_SHOULD_SKIP_THIS
extern "C" { typedef struct _GDir GDir; }
#endif
#include
#include
#include
namespace Glib
{
_WRAP_ENUM(FileTest, GFileTest, NO_GTYPE, decl_prefix GLIBMM_API)
/** @defgroup FileUtils File Utilities
* Various file-related classes and functions.
*/
/** Exception class for file-related errors.
* @ingroup FileUtils
*/
_WRAP_GERROR(FileError, GFileError, G_FILE_ERROR, NO_GTYPE,
s#^EXIST$#EXISTS#,
s#^ISDIR$#IS_DIRECTORY#,
s#^ACCES$#ACCESS_DENIED#,
s#^NAMETOOLONG$#NAME_TOO_LONG#,
s#^NOENT$#NO_SUCH_ENTITY#,
s#^NOTDIR$#NOT_DIRECTORY#,
s#^NXIO$#NO_SUCH_DEVICE#,
s#^NODEV$#NOT_DEVICE#,
s#^ROFS$#READONLY_FILESYSTEM#,
s#^TXTBSY$#TEXT_FILE_BUSY#,
s#^FAULT$#FAULTY_ADDRESS#,
s#^LOOP$#SYMLINK_LOOP#,
s#^NOSPC$#NO_SPACE_LEFT#,
s#^NOMEM$#NOT_ENOUGH_MEMORY#,
s#^MFILE$#TOO_MANY_OPEN_FILES#,
s#^NFILE$#FILE_TABLE_OVERFLOW#,
s#^BADF$#BAD_FILE_DESCRIPTOR#,
s#^INVAL$#INVALID_ARGUMENT#,
s#^PIPE$#BROKEN_PIPE#,
s#^AGAIN$#TRYAGAIN#,
s#^INTR$#INTERRUPTED#,
s#^IO$#IO_ERROR#,
s#^PERM$#NOT_OWNER#,
decl_prefix GLIBMM_API
)
/** @var FileError::Code FileError::EXISTS
* (EEXIST)
*
* @var FileError::Code FileError::IS_DIRECTORY
* (EISDIR)
*
* @var FileError::Code FileError::ACCESS_DENIED
* (EACCES)
*
* @var FileError::Code FileError::NAME_TOO_LONG
* (ENAMETOOLONG)
*
* @var FileError::Code FileError::NO_SUCH_ENTITY
* (ENOENT)
*
* @var FileError::Code FileError::NOT_DIRECTORY
* (ENOTDIR)
*
* @var FileError::Code FileError::NO_SUCH_DEVICE
* (ENXIO)
*
* @var FileError::Code FileError::NOT_DEVICE
* (ENODEV)
*
* @var FileError::Code FileError::READONLY_FILESYSTEM
* (EROFS)
*
* @var FileError::Code FileError::TEXT_FILE_BUSY
* (ETXTBSY)
*
* @var FileError::Code FileError::FAULTY_ADDRESS
* (EFAULT)
*
* @var FileError::Code FileError::SYMLINK_LOOP
* (ELOOP)
*
* @var FileError::Code FileError::NO_SPACE_LEFT
* (ENOSPC)
*
* @var FileError::Code FileError::NOT_ENOUGH_MEMORY
* (ENOMEM)
*
* @var FileError::Code FileError::TOO_MANY_OPEN_FILES
* (EMFILE)
*
* @var FileError::Code FileError::FILE_TABLE_OVERFLOW
* (ENFILE)
*
* @var FileError::Code FileError::BAD_FILE_DESCRIPTOR
* (EBADF)
*
* @var FileError::Code FileError::INVALID_ARGUMENT
* (EINVAL)
*
* @var FileError::Code FileError::BROKEN_PIPE
* (EPIPE)
*
* @var FileError::Code FileError::TRYAGAIN
* (EAGAIN)
*
* We use TRYAGAIN instead of TRY_AGAIN, because that is defined as a macro by a Unix header.
*
* @var FileError::Code FileError::INTERRUPTED
* (EINTR)
*
* @var FileError::Code FileError::IO_ERROR
* (EIO)
*
* @var FileError::Code FileError::NOT_OWNER
* (EPERM)
*
* @var FileError::Code FileError::FAILED
* Returned if no specific code applies.
*/
class Dir;
/** The iterator type of Glib::Dir.
* @ingroup FileUtils
*/
class GLIBMM_API DirIterator
{
public:
typedef std::input_iterator_tag iterator_category;
typedef std::string value_type;
typedef int difference_type;
typedef value_type reference;
typedef void pointer;
DirIterator();
#ifndef DOXYGEN_SHOULD_SKIP_THIS
DirIterator(GDir* gobject, const char* current);
#endif
std::string operator*() const;
DirIterator& operator++();
/** @note DirIterator has input iterator semantics, which means real
* postfix increment is impossible. The return type is @c void to
* prevent surprising behaviour.
*/
void operator++(int);
bool operator==(const DirIterator& rhs) const;
bool operator!=(const DirIterator& rhs) const;
private:
GDir* gobject_;
const char* current_;
};
/** Utility class representing an open directory.
* @ingroup FileUtils
* It's highly recommended to use the iterator interface. With iterators,
* reading an entire directory into a STL container is really easy:
* @code
* Glib::Dir dir (directory_path);
* std::list entries (dir.begin(), dir.end());
* @endcode
* @note The encoding of the directory entries isn't necessarily UTF-8.
* Use Glib::filename_to_utf8() if you need to display them.
*/
class GLIBMM_API Dir
{
public:
using iterator = DirIterator;
using const_iterator = DirIterator;
/** Opens a directory for reading. The names of the files in the
* directory can then be retrieved using read_name().
* @param path The path to the directory you are interested in.
* @throw Glib::FileError
*/
explicit Dir(const std::string& path);
#ifndef DOXYGEN_SHOULD_SKIP_THIS
explicit Dir(GDir* gobject);
#endif
Dir(const Dir&) = delete;
Dir& operator=(const Dir&) = delete;
/** Closes the directory and deallocates all related resources.
*/
~Dir();
/** Retrieves the name of the next entry in the directory.
* The '.' and '..' entries are omitted.
* @return The entry's name or "" if there are no more entries.
* @see begin(), end()
*/
std::string read_name();
/** Resets the directory. The next call to
* read_name() will return the first entry again.
*/
void rewind();
/** Closes the directory and deallocates all related resources.
* Note that close() is implicitely called by ~Dir(). Thus you don't
* need to call close() yourself unless you want to close the directory
* before the destructor runs.
*/
void close();
/** Get the begin of an input iterator sequence.
* @return An input iterator pointing to the first directory entry.
*/
DirIterator begin();
/** Get the end of an input iterator sequence.
* @return An input iterator pointing behind the last directory entry.
*/
DirIterator end();
private:
GDir* gobject_;
};
/** Returns @c true if any of the tests in the bitfield @a test are true.
* @ingroup FileUtils
* For example, (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_DIR) will
* return @c true if the file exists; the check whether it's a directory
* doesn't matter since the existence test is true. With the current set of
* available tests, there's no point passing in more than one test at a time.
*
* Apart from Glib::FILE_TEST_IS_SYMLINK all tests follow symbolic
* links, so for a symbolic link to a regular file file_test() will return
* @c true for both Glib::FILE_TEST_IS_SYMLINK and
* Glib::FILE_TEST_IS_REGULAR.
*
* @note For a dangling symbolic link file_test() will return @c true for
* Glib::FILE_TEST_IS_SYMLINK and @c false for all other flags.
*
* @param filename A filename to test.
* @param test Bitfield of Glib::FileTest flags.
* @return Whether a test was true.
*/
GLIBMM_API
bool file_test(const std::string& filename, FileTest test);
/** Opens a temporary file.
* @ingroup FileUtils
* See the %mkstemp() documentation on most UNIX-like systems. This is a
* portability wrapper, which simply calls %mkstemp() on systems that have
* it, and implements it in GLib otherwise.
* @param filename_template A string that should match the rules for
* %mkstemp(), i.e. end in "XXXXXX". The X string
* will be modified to form the name of a file that didn't exist.
* @return A file handle (as from open()) to the file opened for reading
* and writing. The file is opened in binary mode on platforms where there
* is a difference. The file handle should be closed with close(). In
* case of errors, -1 is returned.
*/
GLIBMM_API
int mkstemp(std::string& filename_template);
/** Opens a file for writing in the preferred directory for temporary files
* (as returned by Glib::get_tmp_dir()).
* @ingroup FileUtils
* @a prefix should a basename template; it'll be suffixed by 6 characters
* in order to form a unique filename. No directory components are allowed.
*
* The actual name used is returned in @a name_used.
*
* @param[out] name_used The actual name used.
* @param prefix Template for file name, basename only.
* @return A file handle (as from open()) to the file opened for reading
* and writing. The file is opened in binary mode on platforms where there is a
* difference. The file handle should be closed with close().
* @throw Glib::FileError
*/
GLIBMM_API
int file_open_tmp(std::string& name_used, const std::string& prefix);
/** Opens a file for writing in the preferred directory for temporary files
* (as returned by Glib::get_tmp_dir()).
* @ingroup FileUtils
* This function works like file_open_tmp(std::string&, const std::string&)
* but uses a default basename prefix.
*
* @param[out] name_used The actual name used.
* @return A file handle (as from open()) to the file opened for reading
* and writing. The file is opened in binary mode on platforms where there is a
* difference. The file handle should be closed with close().
* @throw Glib::FileError
*/
GLIBMM_API
int file_open_tmp(std::string& name_used);
/** Reads an entire file into a string, with good error checking.
* @ingroup FileUtils
* @param filename A file to read contents from.
* @return The file contents.
* @throw Glib::FileError
*/
GLIBMM_API
std::string file_get_contents(const std::string& filename);
/** Writes all of @a contents to a file named @a filename, with good error checking.
*
* @param filename name of a file to write @a contents to, in the GLib file name
* encoding
* @param contents string to write to the file
* @param length length of @a contents, or -1 if @a contents is a nul-terminated string
*
* If a file called @a filename already exists it will be overwritten.
*
* This write is atomic in the sense that it is first written to a temporary
* file which is then renamed to the final name. Notes:
*
* -
* On Unix, if @a filename already exists hard links to @a filename will break.
* Also since the file is recreated, existing permissions, access control
* lists, metadata etc. may be lost. If @a filename is a symbolic link,
* the link itself will be replaced, not the linked file.
*
* -
* On Windows renaming a file will not remove an existing file with the
* new name, so on Windows there is a race condition between the existing
* file being removed and the temporary file being renamed.
*
* -
* On Windows there is no way to remove a file that is open to some
* process, or mapped into memory. Thus, this function will fail if
* @a filename already exists and is open.
*
*
*
* If the call was not successful, an exception is thrown.
* Possible error codes are those in the FileError enumeration.
*
* @newin{2,22}
**/
GLIBMM_API
void file_set_contents (const std::string& filename, const gchar *contents, gssize length);
/** A variant of file_set_contents which accepts a standard C++ string
*
* @newin{2,22}
* */
GLIBMM_API
void file_set_contents (const std::string& filename, const std::string& contents);
} // namespace Glib