/* $Id: fileutils.hg,v 1.3 2004/01/22 18:38:12 murrayc Exp $ */ /* 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 Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ _DEFS(glibmm,glib) #ifndef DOXYGEN_SHOULD_SKIP_THIS extern "C" { typedef struct _GDir GDir; } #endif #include #include #include #include GLIBMM_USING_STD(input_iterator_tag) GLIBMM_USING_STD(string) namespace Glib { _WRAP_ENUM(FileTest, GFileTest, NO_GTYPE) /** @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# ) /** @enum FileError::Code * Values corresponding to errno codes returned from file operations * on UNIX. * Unlike errno codes, FileError::Code values are available on all * systems, even Windows. The exact meaning of each code depends on what sort * of file operation you were performing; the UNIX documentation gives more * details. The following error code descriptions come from the GNU C Library * manual, and are under the copyright of that manual. * * It's not very portable to make detailed assumptions about exactly which * errors will be returned from a given operation. Some errors don't occur on * some systems, etc., sometimes there are subtle differences in when a system * will report a given error, etc. */ /** @var FileError::Code FileError::EXISTS * (EEXIST) Operation not permitted; only the owner of the file (or * other resource) or processes with special privileges can perform the operation. *

*/ /** @var FileError::Code FileError::IS_DIRECTORY * (EISDIR) File is a directory; you cannot open a directory for writing, * or create or remove hard links to it. *

*/ /** @var FileError::Code FileError::ACCESS_DENIED * (EACCES) Permission denied; the file permissions do not allow the * attempted operation. *

*/ /** @var FileError::Code FileError::NAME_TOO_LONG * (ENAMETOOLONG) Filename too long. *

*/ /** @var FileError::Code FileError::NO_SUCH_ENTITY * (ENOENT) No such file or directory. This is a "file doesn't exist" * error for ordinary files that are referenced in contexts where they are expected * to already exist. *

*/ /** @var FileError::Code FileError::NOT_DIRECTORY * (ENOTDIR) A file that isn't a directory was specified when a directory * is required. *

*/ /** @var FileError::Code FileError::NO_SUCH_DEVICE * (ENXIO) No such device or address. The system tried to use the device * represented by a file you specified, and it couldn't find the device. This can * mean that the device file was installed incorrectly, or that the physical device * is missing or not correctly attached to the computer. *

*/ /** @var FileError::Code FileError::NOT_DEVICE * (ENODEV) This file is of a type that doesn't support mapping. *

*/ /** @var FileError::Code FileError::READONLY_FILESYSTEM * (EROFS) The directory containing the new link can't be modified * because it's on a read-only file system. *

*/ /** @var FileError::Code FileError::TEXT_FILE_BUSY * (ETXTBSY) Text file busy. *

*/ /** @var FileError::Code FileError::FAULTY_ADDRESS * (EFAULT) You passed in a pointer to bad memory. (Glib won't * reliably return this, don't pass in pointers to bad memory.) *

*/ /** @var FileError::Code FileError::SYMLINK_LOOP * (ELOOP) Too many levels of symbolic links were encountered in * looking up a file name. This often indicates a cycle of symbolic links. *

*/ /** @var FileError::Code FileError::NO_SPACE_LEFT * (ENOSPC) No space left on device; write operation on a file failed * because the disk is full. *

*/ /** @var FileError::Code FileError::NOT_ENOUGH_MEMORY * (ENOMEM) No memory available. The system cannot allocate more * virtual memory because its capacity is full. *

*/ /** @var FileError::Code FileError::TOO_MANY_OPEN_FILES * (EMFILE) The current process has too many files open and can't * open any more. Duplicate descriptors do count toward this limit. *

*/ /** @var FileError::Code FileError::FILE_TABLE_OVERFLOW * (ENFILE) There are too many distinct file openings in the * entire system. *

*/ /** @var FileError::Code FileError::BAD_FILE_DESCRIPTOR * (EBADF) Bad file descriptor; for example, I/O on a descriptor * that has been closed or reading from a descriptor open only for writing * (or vice versa). *

*/ /** @var FileError::Code FileError::INVALID_ARGUMENT * (EINVAL) Invalid argument. This is used to indicate various kinds * of problems with passing the wrong argument to a library function. *

*/ /** @var FileError::Code FileError::BROKEN_PIPE * (EPIPE) Broken pipe; there is no process reading from the other * end of a pipe. Every library function that returns this error code also * generates a SIGPIPE signal; this signal terminates the program * if not handled or blocked. Thus, your program will never actually see * this code unless it has handled or blocked SIGPIPE. *

*/ /** @var FileError::Code FileError::TRYAGAIN * (EAGAIN) Resource temporarily unavailable; the call might work * if you try again later. * We used TRYAGAIN instead of TRY_AGAIN, because that is a defined as a macro by a Unix header. *

*/ /** @var FileError::Code FileError::INTERRUPTED * (EINTR) Interrupted function call; an asynchronous signal occurred * and prevented completion of the call. When this happens, you should try * the call again. *

*/ /** @var FileError::Code FileError::IO_ERROR * (EIO) Input/output error; usually used for physical read or write * errors. I.e. the disk or other physical device hardware is returning errors. *

*/ /** @var FileError::Code FileError::NOT_OWNER * (EPERM) Operation not permitted; only the owner of the file (or other * resource) or processes with special privileges can perform the operation. *

*/ /** @var FileError::Code FileError::FAILED * Does not correspond to a UNIX error code; this is the standard "failed for * unspecified reason" error code present in all Glib::Error error code * enumerations. Returned if no specific code applies. */ class Dir; /** The iterator type of Glib::Dir. * @ingroup FileUtils */ class 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 Dir { public: typedef DirIterator iterator; typedef DirIterator const_iterator; /** 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 /** 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_; // noncopyable Dir(const Dir&); Dir& operator=(const Dir&); }; /** 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. */ 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. */ 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 prefix Template for file name, basename only. * @retval 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 */ 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. * * @retval 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 */ 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 */ std::string file_get_contents(const std::string& filename); } // namespace Glib