1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <Efl.h>
6
7 typedef struct _Efl_File_Data Efl_File_Data;
8 struct _Efl_File_Data
9 {
10 Eina_Stringshare *vpath; /* efl_file_set */
11 Eina_Stringshare *key; /* efl_file_key_set */
12 Eina_File *file; /* efl_file_mmap_set */
13 time_t mtime;
14 Eina_Bool file_opened : 1; /* if `file` was opened implicitly during load */
15 Eina_Bool setting : 1; /* set when this file is internally calling methods to avoid infinite recursion */
16 Eina_Bool loaded : 1; /* whether the currently set file properties have been loaded */
17 };
18
19 EOLIAN static void
_efl_file_unload(Eo * obj,Efl_File_Data * pd)20 _efl_file_unload(Eo *obj, Efl_File_Data *pd)
21 {
22 if (!pd->loaded) return;
23 if (!pd->file) return;
24 if (!pd->file_opened) return;
25 pd->setting = 1;
26 eina_file_close(pd->file); // close matching open (dup in _efl_file_mmap_set) OK
27 pd->file = NULL;
28 efl_file_mmap_set(obj, NULL);
29 pd->setting = 0;
30 pd->loaded = pd->file_opened = EINA_FALSE;
31 }
32
33 EOLIAN static Eina_Error
_efl_file_load(Eo * obj,Efl_File_Data * pd)34 _efl_file_load(Eo *obj, Efl_File_Data *pd)
35 {
36 Eina_Error ret = 0;
37
38 if (pd->loaded) return 0;
39 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->vpath, ENOENT);
40 errno = 0;
41 if (!pd->file)
42 {
43 Eina_File *f;
44 f = eina_file_open(pd->vpath, EINA_FALSE);
45 if (!f) return errno ?: ENOENT;
46 pd->file_opened = EINA_TRUE;
47 pd->setting = 1;
48 ret = efl_file_mmap_set(obj, f);
49 pd->setting = 0;
50 if (ret) pd->file_opened = EINA_FALSE;
51 eina_file_close(f); // close matching open OK
52 }
53 pd->loaded = !ret;
54 return ret;
55 }
56
57 EOLIAN static Eina_Error
_efl_file_mmap_set(Eo * obj,Efl_File_Data * pd,const Eina_File * f)58 _efl_file_mmap_set(Eo *obj, Efl_File_Data *pd, const Eina_File *f)
59 {
60 Eina_Error err = 0;
61 Eina_File *file = NULL;
62
63 if (f == pd->file) return 0;
64 if (f)
65 {
66 file = eina_file_dup(f);
67 if (!file) return errno;
68 }
69 if (pd->file) eina_file_close(pd->file); // close matching open (dup above) OK
70 pd->file = file;
71 pd->loaded = EINA_FALSE;
72
73 if (!pd->setting)
74 {
75 /* avoid infinite recursion */
76 pd->setting = 1;
77 err = efl_file_set(obj, eina_file_filename_get(pd->file));
78 pd->setting = 0;
79 }
80 return err;
81 }
82
83 EOLIAN static const Eina_File *
_efl_file_mmap_get(const Eo * obj EINA_UNUSED,Efl_File_Data * pd)84 _efl_file_mmap_get(const Eo *obj EINA_UNUSED, Efl_File_Data *pd)
85 {
86 return pd->file;
87 }
88
89 EOLIAN static Eina_Error
_efl_file_file_set(Eo * obj,Efl_File_Data * pd,const char * file)90 _efl_file_file_set(Eo *obj, Efl_File_Data *pd, const char *file)
91 {
92 char *tmp;
93 Eina_Error err = 0;
94 Eina_Bool same;
95 struct stat st;
96
97 tmp = (char*)(file);
98 if (tmp)
99 tmp = eina_vpath_resolve(tmp);
100
101 same = !eina_stringshare_replace(&pd->vpath, tmp ?: file);
102 free(tmp);
103 if (file)
104 {
105 err = stat(pd->vpath, &st);
106 if (same && (!err)) same = st.st_mtime == pd->mtime;
107 }
108 if (same) return err;
109 pd->mtime = file && (!err) ? st.st_mtime : 0;
110 pd->loaded = EINA_FALSE;
111 if (pd->setting)
112 err = 0; /* this is from mmap_set, which may provide a virtual file */
113 else
114 {
115 pd->setting = 1;
116 err = efl_file_mmap_set(obj, NULL);
117 pd->setting = 0;
118 }
119 return err;
120 }
121
122 EOLIAN static Eina_Stringshare *
_efl_file_file_get(const Eo * obj EINA_UNUSED,Efl_File_Data * pd)123 _efl_file_file_get(const Eo *obj EINA_UNUSED, Efl_File_Data *pd)
124 {
125 return pd->vpath;
126 }
127
128 EOLIAN static void
_efl_file_key_set(Eo * obj EINA_UNUSED,Efl_File_Data * pd,const char * key)129 _efl_file_key_set(Eo *obj EINA_UNUSED, Efl_File_Data *pd, const char *key)
130 {
131 if (eina_stringshare_replace(&pd->key, key))
132 pd->loaded = 0;
133 }
134
135 EOLIAN static Eina_Stringshare *
_efl_file_key_get(const Eo * obj EINA_UNUSED,Efl_File_Data * pd)136 _efl_file_key_get(const Eo *obj EINA_UNUSED, Efl_File_Data *pd)
137 {
138 return pd->key;
139 }
140
141 EOLIAN static Eina_Bool
_efl_file_loaded_get(const Eo * obj EINA_UNUSED,Efl_File_Data * pd)142 _efl_file_loaded_get(const Eo *obj EINA_UNUSED, Efl_File_Data *pd)
143 {
144 return pd->loaded;
145 }
146
147 EOLIAN static void
_efl_file_efl_object_destructor(Eo * obj,Efl_File_Data * pd)148 _efl_file_efl_object_destructor(Eo *obj, Efl_File_Data *pd)
149 {
150 eina_stringshare_del(pd->vpath);
151 eina_stringshare_del(pd->key);
152 eina_file_close(pd->file); // close matching open (dup in _efl_file_mmap_set) OK
153 pd->vpath = NULL;
154 pd->key = NULL;
155 pd->file = NULL;
156 efl_destructor(efl_super(obj, EFL_FILE_MIXIN));
157 }
158
159 EOLIAN static Eo *
_efl_file_efl_object_finalize(Eo * obj,Efl_File_Data * pd)160 _efl_file_efl_object_finalize(Eo *obj, Efl_File_Data *pd)
161 {
162 obj = efl_finalize(efl_super(obj, EFL_FILE_MIXIN));
163 if (!obj) return NULL;
164 if (pd->file || pd->vpath) efl_file_load(obj);
165 return obj;
166 }
167
168 ////////////////////////////////////////////////////////////////////////////
169
170 EAPI Eina_Bool
efl_file_simple_load(Eo * obj,const char * file,const char * key)171 efl_file_simple_load(Eo *obj, const char *file, const char *key)
172 {
173 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
174 efl_ref(obj);
175 if (efl_file_set(obj, file))
176 {
177 EINA_LOG_ERR("File set to '%s' on '%s' failed.", file, efl_debug_name_get(obj));
178 goto fail;
179 }
180 efl_file_key_set(obj, key);
181 if (file)
182 {
183 if (efl_file_load(obj)) goto fail;
184 efl_unref(obj);
185 return EINA_TRUE;
186 }
187 efl_file_unload(obj);
188 efl_unref(obj);
189 return EINA_TRUE;
190 fail:
191 efl_unref(obj);
192 return EINA_FALSE;
193 }
194
195 EAPI Eina_Bool
efl_file_simple_mmap_load(Eo * obj,const Eina_File * file,const char * key)196 efl_file_simple_mmap_load(Eo *obj, const Eina_File *file, const char *key)
197 {
198 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
199 efl_ref(obj);
200 EINA_SAFETY_ON_TRUE_GOTO(efl_file_mmap_set(obj, file), fail);
201 efl_file_key_set(obj, key);
202 if (file)
203 {
204 if (efl_file_load(obj)) goto fail;
205 efl_unref(obj);
206 return EINA_TRUE;
207 }
208 efl_file_unload(obj);
209 efl_unref(obj);
210 return EINA_TRUE;
211 fail:
212 efl_unref(obj);
213 return EINA_FALSE;
214 }
215
216 EAPI void
efl_file_simple_get(const Eo * obj,const char ** file,const char ** key)217 efl_file_simple_get(const Eo *obj, const char **file, const char **key)
218 {
219 efl_ref((Eo*)obj);
220 if (file) *file = efl_file_get(obj);
221 if (key) *key = efl_file_key_get(obj);
222 efl_unref((Eo*)obj);
223 }
224
225 EAPI void
efl_file_simple_mmap_get(const Eo * obj,const Eina_File ** file,const char ** key)226 efl_file_simple_mmap_get(const Eo *obj, const Eina_File **file, const char **key)
227 {
228 efl_ref((Eo*)obj);
229 if (file) *file = efl_file_mmap_get(obj);
230 if (key) *key = efl_file_key_get(obj);
231 efl_unref((Eo*)obj);
232 }
233
234 #include "interfaces/efl_file.eo.c"
235 #include "interfaces/efl_file_save.eo.c"
236