summaryrefslogtreecommitdiff
path: root/src/lib/eina/eina_file_common.h
blob: 2fc87001e5beaabd841e942eeda6bb6adcb67104 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
/* 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 <http://www.gnu.org/licenses/>.
 */

#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. */

#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). */
};

/**
 * @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 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 path The path to append to the current directory.
 * @param 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 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 file The path of the file.
 *
 */
void eina_file_clean_close(Eina_File *file);

/**
 * @brief Closes a file from the OS perspective.
 *
 * @param 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 file The file.
 * @param 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 file The file.
 * @param map The memory mapped region that is to be freed.
 * @param 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 file The virtual file to map in memory
 *
 */
void *eina_file_virtual_map_all(Eina_File *file);

/**
 * @brief Map a part of a virtual file to a buffer.
 *
 * @param file The virtual file to map in memory
 * @param offset The offset inside the file to start mapping
 * @param length The length of the region to map
 *
 */
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 file The file handler to unmap memory from.
 * @param 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 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 key1 The first key.
 * @param key1_length The length of the first key.
 * @param key2 The second key.
 * @param 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 key A pointer to the key.
 * @param 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_ */