/* EINA - EFL data type library * Copyright (C) 2013 Cedric Bail * * 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 . */ #ifndef EINA_FILE_COMMON_H_ # define EINA_FILE_COMMON_H_ #include "eina_file.h" #include "eina_tmpstr.h" #include "eina_lock.h" #include "eina_list.h" #include "eina_util.h" #define EINA_FILE_MAGIC 0xFEEDBEEF /** * @addtogroup Eina_Tools_Group Tools * * @{ */ /** * @addtogroup Eina_File_Group File * * @brief Functions to handle files and directories. * * This module performs internal housekeeping and utility tasks for Eina_File. * It also provides the underlying data types for things like file handles, file * maps and file iterators. * * @{ */ /** * @typedef Eina_File_Map * * Type definition for an Eina File Map. * */ typedef struct _Eina_File_Map Eina_File_Map; /** * @typedef Eina_Lines_Iterator * * Type definition for an Eina Lines Iterator. * */ typedef struct _Eina_Lines_Iterator Eina_Lines_Iterator; /** * @struct _Eina_File * * This is the underlying data structure that represents a file in Eina. * */ struct _Eina_File { EINA_MAGIC; /**< Indicates whether Eina Magic should be used. */ const char *filename; /**< The absolute path of the file. Note that the path given when calling @ref eina_file_open will be run through @ref eina_file_path_sanitize before it is stored here. */ Eina_Hash *map; /**< Tracks portions of a file that have been mapped with mmap(2). The key is a tuple offset/length and the data is a pointer to the mapped region. */ Eina_Hash *rmap; /**< Similar function to #map, but used to look up mapped areas by pointer rather than offset/length. */ void *global_map; /**< A pointer to the entire contents of the file that have been mapped with mmap(2). This is the common case, and EFL and is optimized for it. */ Eina_Lock lock; /**< A file locking mechanism. */ #ifndef _WIN32 unsigned long long length; /**< The length of the file in bytes. */ time_t mtime; /**< The last modified time. */ ino_t inode; /**< The inode. */ #ifdef _STAT_VER_LINUX unsigned long int mtime_nsec; /**< The nano version of the last modified time. */ #endif #else ULONGLONG length; /**< The length of the file in bytes. */ ULONGLONG mtime; /**< The last modified time. */ #endif int refcount; /**< Keeps track of references to #map. */ int global_refcount; /**< Keeps track of references to #global_map. */ Eina_Statgen statgen;/**< For inexact stats a stat gen count to rate limit syscalls to stat file */ #ifndef _WIN32 int fd; /**< The file descriptor. */ #else HANDLE handle; /**< A Win32 file handle for this file. */ #endif Eina_List *dead_map; /**< Tracks regions that get a failure from mmap(2). */ Eina_Bool shared : 1; /**< Indicates whether this file can be shared */ Eina_Bool delete_me : 1; /**< Indicates that this file should be deleted */ Eina_Bool global_faulty : 1; /**< Indicates whether #global_map is bad */ Eina_Bool global_hugetlb : 1; /**< Indicates whether #global_map uses HugeTLB */ Eina_Bool virtual : 1; /**< Indicates that this is a virtual file */ Eina_Bool copied : 1; /**< Indicates whether this file has copied data */ }; /** * @struct _Eina_File_Map * * This represents a memory mapped region of a file. * */ struct _Eina_File_Map { void *map; /**< A pointer to the mapped region */ unsigned long int offset; /**< The offset in the file */ unsigned long int length; /**< The length of the region */ int refcount; /**< Tracks references to this region */ Eina_Bool hugetlb : 1; /**< Indicates if we are using HugeTLB */ Eina_Bool faulty : 1; /**< Indicates if this region was not mapped correctly (i.e. the call to mmap(2) failed). */ #ifdef _WIN32 void *ret; /**< A pointer to the mapped region */ #endif }; /** * @struct _Eina_Lines_Iterator * * This represents a line iterator a file. * */ struct _Eina_Lines_Iterator { Eina_Iterator iterator; /**< The iterator itself */ Eina_File *fp; /**< The file this iterator is associated with */ const char *map; /**< A pointer to the head of the file that has been mapped with mmap(2). */ const char *end; /**< A pointer to the end of the file that has been mapped with mmap(2). */ int boundary; /**< Currently hard coded to 4096. */ Eina_File_Line current; /**< The current line */ }; #ifndef EINA_LOG_COLOR_DEFAULT /** Set the color for Eina log entries */ #define EINA_LOG_COLOR_DEFAULT EINA_COLOR_CYAN #endif #ifdef ERR #undef ERR #endif /** Macro for logging Eina errors */ #define ERR(...) EINA_LOG_DOM_ERR(_eina_file_log_dom, __VA_ARGS__) #ifdef WRN #undef WRN #endif /** Macro for logging Eina warnings */ #define WRN(...) EINA_LOG_DOM_WARN(_eina_file_log_dom, __VA_ARGS__) #ifdef INF #undef INF #endif /** Macro for logging Eina info messages */ #define INF(...) EINA_LOG_DOM_INFO(_eina_file_log_dom, __VA_ARGS__) #ifdef DBG #undef DBG #endif /** Macro for logging Eina debug messages */ #define DBG(...) EINA_LOG_DOM_DBG(_eina_file_log_dom, __VA_ARGS__) /** * @brief Determines if a path is relative or absolute. * The implementation simply checks if the first char in the path is '/'. If it * is not, the path is considered relative. * * @param[in] path The path to check. * * @return EINA_TRUE if the path is relative, EINA_FALSE otherwise. * */ Eina_Bool eina_file_path_relative(const char *path); /** * @brief Gets the current directory and optionally appends a path to it. * If a string was passed in via the @p path parameter, it will * be appended to the current working directory. Presumably, this will be a * relative path. * * @param[in] path The path to append to the current directory. * @param[in] len The length of @p path. * * @return A pointer to a string that contains the absolute path to the current * working directory plus any path you send in. * */ Eina_Tmpstr *eina_file_current_directory_get(const char *path, size_t len); /** * @brief Cleans up Eina after a file is no longer needed. * * @param[in,out] path The path of the file. * * @return On success, it will return the @p path string. If @p path is @c NULL, * it will return and empty string. * */ char *eina_file_cleanup(Eina_Tmpstr *path); /** * @brief Closes and cleans up after an Eina file. * * @param[in,out] file The path of the file. * */ void eina_file_clean_close(Eina_File *file); /** * @brief Closes a file from the OS perspective. * * @param[in,out] file The path of the file. * */ void eina_file_real_close(Eina_File *file); /** * @brief Resets the internal housekeeping structures after a file has changed. * Despite the name, this routine does not write anything to disk. It invalidates * the memory maps for the file. If the file has shrunk, it also adds any mapped * regions past the end of the file to the dead_map. * * @param[in,out] file The file. * @param[in] length The current length of the file after the change. * */ void eina_file_flush(Eina_File *file, unsigned long int length); /** * @brief Removes a mapped region from the file and frees the resources. * This routine will remove a previously mapped region from the internal Eina File * housekeeping and free the resources associated with it. In the case where * the map is part of the dead_map, @p free_func will be called to handle the actual * deallocation. * * @param[in,out] file The file. * @param[in,out] map The memory mapped region that is to be freed. * @param[in] free_func A pointer to a function that will be called to * free up the resources used by the map. * */ void eina_file_common_map_free(Eina_File *file, void *map, void (*free_func)(Eina_File_Map *map)); /** A pointer to the global Eina file cache. */ extern Eina_Hash *_eina_file_cache; /** The global file lock cache */ extern Eina_Lock _eina_file_lock_cache; /** The global Eina log file domain. */ extern int _eina_file_log_dom; // Common function to handle virtual file /** * @brief Map the entire contents of a virtual file to a buffer. * * @param[in] file The virtual file to map in memory * @return The buffer */ void *eina_file_virtual_map_all(Eina_File *file); /** * @brief Map a part of a virtual file to a buffer. * * @param[in,out] file The virtual file to map in memory * @param[in] offset The offset inside the file to start mapping * @param[in] length The length of the region to map * @return The buffer */ void *eina_file_virtual_map_new(Eina_File *file, unsigned long int offset, unsigned long int length); /** * @brief Unref and unmap memory if possible. * * @param[in,out] file The file handler to unmap memory from. * @param[in,out] map Memory map to unref and unmap. * */ void eina_file_virtual_map_free(Eina_File *file, void *map); // Common hash function /** * @brief Get the length of a map key. * @warning This function is not yet implemented. At present it only returns * @code sizeof (unsigned long int) * 2 @endcode * * @param[in] key The key for which length will be calculated. * * @return The length of the key. * */ unsigned int eina_file_map_key_length(const void *key); /** * @brief Compares two map keys. * The implementation assumes that @p key1 and @p key2 are both pointers to an * array with 2 elements, as is the case with the Eina file map keys. * * @param[in] key1 The first key. * @param[in] key1_length The length of the first key. * @param[in] key2 The second key. * @param[in] key2_length The length of the second key. * * @return Positive number if Key1 > Key2, else a negative number. Will return * zero if both elements of the key are exactly the same. * */ int eina_file_map_key_cmp(const unsigned long long int *key1, int key1_length, const unsigned long long int *key2, int key2_length); /** * @brief Creates a hash from a map key. * * @param[in] key A pointer to the key. * @param[in] key_length The length of the key. * * @return A key hash. * */ int eina_file_map_key_hash(const unsigned long long int *key, int key_length); /** * @} */ /** * @} */ #endif /* EINA_FILE_COMMON_H_ */