00001
00002
00003
00004 #include <Eina.h>
00005 #include <Eet.h>
00006 #include <stdio.h>
00007 #include <limits.h>
00008 #include <sys/types.h>
00009 #include <sys/stat.h>
00010 #include <unistd.h>
00011
00012
00013
00014
00015
00016
00017 typedef struct
00018 {
00019 unsigned int version;
00020 const char *name;
00021 int id;
00022 int not_saved_value;
00023 Eina_Bool enabled;
00024 Eina_List *subs;
00025 } My_Conf_Type;
00026
00027 typedef struct
00028 {
00029 const char *server;
00030 int port;
00031 } My_Conf_Subtype;
00032
00033
00034
00035
00036 static const char MY_CONF_FILE_ENTRY[] = "config";
00037
00038
00039
00040
00041 static Eet_Data_Descriptor *_my_conf_descriptor;
00042 static Eet_Data_Descriptor *_my_conf_sub_descriptor;
00043
00044 static void
00045 _my_conf_descriptor_init(void)
00046 {
00047 Eet_Data_Descriptor_Class eddc;
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, My_Conf_Type);
00062 _my_conf_descriptor = eet_data_descriptor_stream_new(&eddc);
00063
00064 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, My_Conf_Subtype);
00065 _my_conf_sub_descriptor = eet_data_descriptor_stream_new(&eddc);
00066
00067
00068
00069 #define MY_CONF_ADD_BASIC(member, eet_type) \
00070 EET_DATA_DESCRIPTOR_ADD_BASIC \
00071 (_my_conf_descriptor, My_Conf_Type, # member, member, eet_type)
00072 #define MY_CONF_SUB_ADD_BASIC(member, eet_type) \
00073 EET_DATA_DESCRIPTOR_ADD_BASIC \
00074 (_my_conf_sub_descriptor, My_Conf_Subtype, # member, member, eet_type)
00075
00076 MY_CONF_SUB_ADD_BASIC(server, EET_T_STRING);
00077 MY_CONF_SUB_ADD_BASIC(port, EET_T_INT);
00078
00079 MY_CONF_ADD_BASIC(version, EET_T_UINT);
00080 MY_CONF_ADD_BASIC(name, EET_T_STRING);
00081 MY_CONF_ADD_BASIC(id, EET_T_INT);
00082 MY_CONF_ADD_BASIC(enabled, EET_T_UCHAR);
00083
00084
00085 EET_DATA_DESCRIPTOR_ADD_LIST
00086 (_my_conf_descriptor, My_Conf_Type, "subs", subs, _my_conf_sub_descriptor);
00087
00088 #undef MY_CONF_ADD_BASIC
00089 #undef MY_CONF_SUB_ADD_BASIC
00090 }
00091
00092 static void
00093 _my_conf_descriptor_shutdown(void)
00094 {
00095 eet_data_descriptor_free(_my_conf_sub_descriptor);
00096 eet_data_descriptor_free(_my_conf_descriptor);
00097 }
00098
00099 static My_Conf_Type *
00100 _my_conf_new(void)
00101 {
00102 My_Conf_Type *my_conf = calloc(1, sizeof(My_Conf_Type));
00103 My_Conf_Subtype *sub;
00104 if (!my_conf)
00105 {
00106 fprintf(stderr, "ERROR: could not calloc My_Conf_Type\n");
00107 return NULL;
00108 }
00109
00110 my_conf->version = 0x112233;
00111 my_conf->enabled = EINA_TRUE;
00112
00113 sub = calloc(1, sizeof(My_Conf_Subtype));
00114 if (sub)
00115 {
00116 sub->server = eina_stringshare_add("my-server.com");
00117 sub->port = 1234;
00118 my_conf->subs = eina_list_append(my_conf->subs, sub);
00119 }
00120
00121 return my_conf;
00122 }
00123
00124 static void
00125 _my_conf_free(My_Conf_Type *my_conf)
00126 {
00127 My_Conf_Subtype *sub;
00128 EINA_LIST_FREE(my_conf->subs, sub)
00129 {
00130 eina_stringshare_del(sub->server);
00131 free(sub);
00132 }
00133
00134 eina_stringshare_del(my_conf->name);
00135 free(my_conf);
00136 }
00137
00138 static My_Conf_Type *
00139 _my_conf_load(const char *filename)
00140 {
00141 My_Conf_Type *my_conf;
00142 Eet_File *ef = eet_open(filename, EET_FILE_MODE_READ);
00143 if (!ef)
00144 {
00145 fprintf(stderr, "ERROR: could not open '%s' for read\n", filename);
00146 return NULL;
00147 }
00148
00149 my_conf = eet_data_read(ef, _my_conf_descriptor, MY_CONF_FILE_ENTRY);
00150 if (!my_conf)
00151 goto end;
00152
00153 if (my_conf->version < 0x112233)
00154 {
00155 fprintf(stderr,
00156 "WARNING: version %#x was too old, upgrading it to %#x\n",
00157 my_conf->version, 0x112233);
00158
00159 my_conf->version = 0x112233;
00160 my_conf->enabled = EINA_TRUE;
00161 }
00162
00163 end:
00164 eet_close(ef);
00165 return my_conf;
00166 }
00167
00168 static Eina_Bool
00169 _my_conf_save(const My_Conf_Type *my_conf,
00170 const char *filename)
00171 {
00172 char tmp[PATH_MAX];
00173 Eet_File *ef;
00174 Eina_Bool ret;
00175 unsigned int i, len;
00176 struct stat st;
00177
00178 len = eina_strlcpy(tmp, filename, sizeof(tmp));
00179 if (len + 12 >= (int)sizeof(tmp))
00180 {
00181 fprintf(stderr, "ERROR: file name is too big: %s\n", filename);
00182 return EINA_FALSE;
00183 }
00184
00185 i = 0;
00186 do
00187 {
00188 snprintf(tmp + len, 12, ".%u", i);
00189 i++;
00190 }
00191 while (stat(tmp, &st) == 0);
00192
00193 ef = eet_open(tmp, EET_FILE_MODE_WRITE);
00194 if (!ef)
00195 {
00196 fprintf(stderr, "ERROR: could not open '%s' for write\n", tmp);
00197 return EINA_FALSE;
00198 }
00199
00200 ret = eet_data_write
00201 (ef, _my_conf_descriptor, MY_CONF_FILE_ENTRY, my_conf, EINA_TRUE);
00202 eet_close(ef);
00203
00204 if (ret)
00205 {
00206 unlink(filename);
00207 rename(tmp, filename);
00208 }
00209
00210 return ret;
00211 }
00212
00213 int
00214 main(int argc,
00215 char *argv[])
00216 {
00217 My_Conf_Type *my_conf;
00218 const My_Conf_Subtype *sub;
00219 const Eina_List *l;
00220 int ret = 0;
00221
00222 if (argc != 3)
00223 {
00224 fprintf(stderr, "Usage:\n\t%s <input> <output>\n\n", argv[0]);
00225 return -1;
00226 }
00227
00228 eina_init();
00229 eet_init();
00230 _my_conf_descriptor_init();
00231
00232 my_conf = _my_conf_load(argv[1]);
00233 if (!my_conf)
00234 {
00235 printf("creating new configuration.\n");
00236 my_conf = _my_conf_new();
00237 if (!my_conf)
00238 {
00239 ret = -2;
00240 goto end;
00241 }
00242 }
00243
00244 printf("My_Conf_Type:\n"
00245 "\tversion: %#x\n"
00246 "\tname...: '%s'\n"
00247 "\tid.....: %d\n"
00248 "\tenabled: %hhu\n"
00249 "\tsubs...:\n",
00250 my_conf->version,
00251 my_conf->name ? my_conf->name : "",
00252 my_conf->id,
00253 my_conf->enabled);
00254
00255 EINA_LIST_FOREACH(my_conf->subs, l, sub)
00256 printf("\t\tserver: '%s', port: %d\n",
00257 sub->server ? sub->server : "",
00258 sub->port);
00259
00260 if (!_my_conf_save(my_conf, argv[2]))
00261 ret = -3;
00262
00263 _my_conf_free(my_conf);
00264
00265 end:
00266 _my_conf_descriptor_shutdown();
00267 eet_shutdown();
00268 eina_shutdown();
00269
00270 return ret;
00271 }
00272