export.c

Go to the documentation of this file.
00001 /*
00002  * File Name: export.c
00003  */
00004 
00005 /*
00006  * This file is part of erconftool.
00007  *
00008  * erconftool is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * erconftool is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021  
00022 /**
00023  * Copyright (C) 2008 iRex Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 //----------------------------------------------------------------------------
00028 // Include Files
00029 //----------------------------------------------------------------------------
00030 
00031 // system include files, between < >
00032 #include <glib.h>
00033 #include <glib/gstdio.h>
00034 #include <gconf/gconf-client.h>
00035 #include <sys/utsname.h> /* for uname */
00036 #include <unistd.h> /* for unlink */
00037 #include <sys/stat.h> /* for mkdir */
00038 
00039 // ereader include files, between < >
00040 
00041 // local include files, between " "
00042 #include "log.h"
00043 #include "erconftool.h"
00044 #include "export.h"
00045 #include "show.h"
00046 
00047 #define UNUSED(x) (void)(x)
00048 
00049 
00050 //----------------------------------------------------------------------------
00051 // Type Declarations
00052 //----------------------------------------------------------------------------
00053 
00054 
00055 //----------------------------------------------------------------------------
00056 // Global Constants
00057 //----------------------------------------------------------------------------
00058 
00059 #define PATH_SYSSET "/sys/devices/system/sysset/sysset0/"
00060 
00061 
00062 //----------------------------------------------------------------------------
00063 // Static Variables
00064 //----------------------------------------------------------------------------
00065 
00066 
00067 //============================================================================
00068 // Local Function Definitions
00069 //============================================================================
00070 
00071 static gboolean create_registry (const char *filename);
00072 static void export_device_info  (GKeyFile *key_file);
00073 static void export_gconf        (GConfClient *client, GKeyFile *key_file, const char *path, gboolean force_defaults);
00074 static void export_gconf_entries(GConfClient *client, GKeyFile *key_file, const char *path, gboolean force_defaults);
00075 static void export_gconf_entry  (GConfClient *client, GKeyFile *key_file, GConfEntry* entry, gboolean force_defaults);
00076 
00077 static gchar *get_file_content             (const gchar* file_path);
00078 static char  *get_kernel_version           (void);
00079 static char  *get_micro_bootloader_version (void);
00080 static char  *get_micro_app_version        (void);
00081 static char  *get_sub_dir                  (const char* parent, const char* sub_dir);
00082 
00083 
00084 //============================================================================
00085 // Functions Implementation
00086 //============================================================================
00087 
00088 gboolean export_registry(GConfClient *client, const char *filename, const char **paths, gboolean force_defaults)
00089 {
00090     GKeyFile *key_file = NULL;
00091     FILE     *inifile  = NULL;
00092     GError   *error    = NULL;
00093 
00094     // load ini file from disk
00095     //
00096     key_file = g_key_file_new();
00097     if (!g_key_file_load_from_file(key_file, filename, G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error))
00098     {
00099         if (error->code == G_KEY_FILE_ERROR_PARSE)
00100         {
00101             g_error_free(error);
00102             error = NULL;
00103 
00104             g_print("Error parsing file, backup as: %s.old\n", filename);
00105             // parse error loading ini, backup old
00106             gchar *filename_old = g_strconcat(filename, ".old", NULL);
00107             unlink(filename_old);
00108             rename(filename, filename_old);
00109             g_free(filename_old);
00110         }
00111 
00112         g_print("File does not exist, create new: %s\n", filename);
00113         if (!create_registry(filename))
00114         {
00115             g_print("Error creating new file: %s\n", filename);
00116             return FALSE;
00117         }
00118     }
00119     
00120     // write system information
00121     //
00122     export_device_info(key_file);
00123 
00124     // recurse through registry to load current entries
00125     //
00126     gint i;
00127     for (i = 0; paths[i]; i++)
00128     {    
00129         export_gconf(client, key_file, paths[i], force_defaults);
00130     }
00131     
00132     // read pointercal to load calibation settings
00133 #if 0  // disabled see PR3439
00134     export_pointercal(key_file);
00135 #endif 
00136 
00137     // write updated ini file back to disk
00138     //
00139     inifile = fopen(filename, "w");
00140     if (inifile == NULL)
00141     {
00142         g_print("Error writing file: %s\n", filename);
00143         g_key_file_free(key_file);
00144         return FALSE;
00145     }
00146     else
00147     {
00148         fprintf(inifile, "%s", g_key_file_to_data(key_file, NULL, NULL));
00149         fclose(inifile);
00150     }
00151 
00152     g_key_file_free(key_file);
00153     
00154     return TRUE;
00155 }
00156 
00157 
00158 static gboolean create_registry(const char *filename)
00159 {
00160     // create path
00161     gchar *path = g_path_get_dirname(filename);
00162     if (path)
00163     {
00164         gint rc = g_mkdir(path, 0755);
00165         g_free(path);
00166         if (rc < 0 && errno != EEXIST)
00167         {
00168             // failed to create directory
00169             g_printf("Error creating dir [%s]: %s\n", path, strerror(errno));
00170             return FALSE;
00171         }
00172     }
00173     else
00174     {
00175         // failed to get dirname
00176         return FALSE;
00177     }
00178     
00179     // create an empty ini
00180     if (!g_file_set_contents (filename, "", -1, NULL))
00181     { 
00182         // failed writing to file
00183         return FALSE;
00184     }
00185     
00186     return TRUE;
00187 }
00188 
00189 
00190 static void export_gconf_entry(GConfClient* client, GKeyFile *key_file, GConfEntry* entry, gboolean force_defaults)
00191 {
00192     UNUSED(client);
00193     const char* key     = gconf_entry_get_key(entry);
00194     GConfValue* value   = gconf_entry_get_value(entry);
00195     gboolean is_default = gconf_entry_get_is_default(entry);
00196 
00197 #if (LOGGING_ON)
00198     show_entry(client, entry);
00199 #endif    
00200     
00201     // don't export default value unless forced and the key already exists in the ini file 
00202     if ( is_default 
00203          && !(force_defaults && g_key_file_has_key(key_file, INI_GROUP_REGISTRY, key, NULL)) )
00204     {
00205         LOGPRINTF("default key not exported: %s", key);
00206         return;
00207     }
00208 
00209     LOGPRINTF("is_default [%d] force [%d] has_key [%d]", is_default, force_defaults, g_key_file_has_key(key_file, INI_GROUP_REGISTRY, key, NULL));
00210     
00211     if (value) 
00212     {
00213         switch (value->type) 
00214         {
00215         case GCONF_VALUE_STRING: 
00216             g_key_file_set_string(key_file, INI_GROUP_REGISTRY, key, gconf_value_get_string(value));
00217             break;
00218         
00219         case GCONF_VALUE_INT:
00220             g_key_file_set_integer(key_file, INI_GROUP_REGISTRY, key, gconf_value_get_int(value));
00221             break;      
00222         
00223         case GCONF_VALUE_FLOAT:
00224             g_key_file_set_double(key_file, INI_GROUP_REGISTRY, key, gconf_value_get_float(value));
00225             break;            
00226         
00227         case GCONF_VALUE_BOOL:
00228             g_key_file_set_boolean(key_file, INI_GROUP_REGISTRY, key, gconf_value_get_bool(value));
00229             break;            
00230                     
00231         case GCONF_VALUE_LIST:
00232             {
00233                 GSList *valuelist = gconf_value_get_list(value);
00234                 gsize len = g_slist_length(valuelist);
00235                 
00236                 switch (gconf_value_get_list_type(value))
00237                 {
00238                 case GCONF_VALUE_STRING:
00239                     {
00240                         // make string list of GSList
00241                         //
00242                         gchar **list = g_malloc0((len+1)*sizeof(gchar *));
00243                         gchar **ptr=list;
00244                         while (valuelist!=NULL) 
00245                         {
00246                             const char *str = gconf_value_get_string(valuelist->data);
00247                             if (str)
00248                             {
00249                                 *ptr = g_strdup(str);
00250                                 ptr = ptr + 1;
00251                             }
00252                             valuelist=valuelist->next; 
00253                         }
00254                         
00255                         // set list
00256                         g_key_file_set_string_list(key_file, INI_GROUP_REGISTRY, key, (const gchar * const *)list, len);
00257                         
00258                         // free allocated memory
00259                         g_strfreev(list);                
00260                     }
00261                     break;
00262                             
00263                 case GCONF_VALUE_INT:
00264                     {
00265                         // make integer list of GSList
00266                         //
00267                         gint *list = g_malloc0((len+1)*sizeof(gint));
00268                         gint *ptr=list;
00269                         while (valuelist!=NULL) 
00270                         {
00271                             gint val = gconf_value_get_int(valuelist->data);
00272                             if (val)
00273                             {
00274                                 *ptr++ = val;
00275                             }
00276                             valuelist=valuelist->next; 
00277                         }
00278                         
00279                         // set list
00280                         g_key_file_set_integer_list(key_file, INI_GROUP_REGISTRY, key, list, len);
00281                         
00282                         // free allocated memory
00283                         g_free(list);                
00284                     }
00285                     break;
00286                             
00287                 case GCONF_VALUE_FLOAT:
00288                     {
00289                         // make float list of GSList
00290                         //
00291                         double *list = g_malloc0((len+1)*sizeof(double));
00292                         double *ptr=list;
00293                         while (valuelist!=NULL) 
00294                         {
00295                             double val = gconf_value_get_float(valuelist->data);
00296                             if (val)
00297                             {
00298                                 *ptr++ = val;
00299                             }
00300                             valuelist=valuelist->next; 
00301                         }
00302                         
00303                         // set list
00304                         g_key_file_set_double_list(key_file, INI_GROUP_REGISTRY, key, list, len);
00305                         
00306                         // free allocated memory
00307                         g_free(list);                
00308                     }
00309                     break;
00310                             
00311                 case GCONF_VALUE_BOOL:
00312                     {
00313                         // make boolean list of GSList
00314                         //
00315                         gboolean *list = g_malloc0((len+1)*sizeof(gboolean));
00316                         gboolean *ptr=list;
00317                         while (valuelist!=NULL) 
00318                         {
00319                             gboolean val = gconf_value_get_bool(valuelist->data);
00320                             if (val)
00321                             {
00322                                 *ptr++ = val;
00323                             }
00324                             valuelist=valuelist->next; 
00325                         }
00326                         
00327                         // set list
00328                         g_key_file_set_boolean_list(key_file, INI_GROUP_REGISTRY, key, list, len);
00329                         
00330                         // free allocated memory
00331                         g_free(list);                
00332                     }
00333                     break;
00334                             
00335                 default:
00336                     g_print("Unsupported data type of list for key: %s\n", key);
00337                     break;
00338                 }
00339                 
00340                 g_slist_free(valuelist);
00341             }
00342             break;            
00343                 
00344         case GCONF_VALUE_INVALID:
00345         default:
00346             // invalid or supported data type
00347             g_print("Invalid or unsupported data type for key: %s\n", key);
00348             break;
00349         }
00350     }
00351     else
00352     {
00353         // invalid value
00354         g_print("Invalid value for key: %s\n", key);
00355     } 
00356 }
00357 
00358 
00359 static void export_gconf_entries(GConfClient *client, GKeyFile *key_file, const char *path, gboolean force_defaults)
00360 {
00361     GSList *entries = gconf_client_all_entries(client, (char*) path, NULL);
00362     while (entries!=NULL)
00363     {
00364         export_gconf_entry(client, key_file, (GConfEntry*) entries->data, force_defaults);
00365         entries=entries->next;
00366     }   
00367 }    
00368 
00369 
00370 static void export_gconf(GConfClient *client, GKeyFile *key_file, const char *path, gboolean force_defaults)
00371 {
00372     GSList *tmp = gconf_client_all_dirs(client, path, NULL);
00373 
00374     export_gconf_entries(client, key_file, path, force_defaults);
00375 
00376     // resursively dump all directories below
00377     while (tmp!=NULL) 
00378     {
00379         export_gconf(client, key_file, (char*) tmp->data, force_defaults);
00380         tmp=tmp->next; 
00381     }
00382 }
00383 
00384 
00385 #if 0  // disabled See PR3439
00386 static void export_pointercal(GKeyFile *key_file)
00387 {
00388     FILE        *calfile = NULL;
00389     gint        a_cur[7];
00390     
00391     calfile = fopen(CAL_FILE, "r");
00392     if (calfile == NULL)
00393     {
00394         g_print("Error opening file: %s\n", CAL_FILE);
00395         return;
00396     }
00397     else
00398     {
00399         fscanf(calfile, "%d %d %d %d %d %d %d",
00400                 a_cur + 0,
00401                 a_cur + 1,
00402                 a_cur + 2,
00403                 a_cur + 3,
00404                 a_cur + 4,
00405                 a_cur + 5,
00406                 a_cur + 6);
00407         
00408         fclose(calfile);
00409     }
00410     
00411     g_key_file_set_integer_list(key_file, INI_GROUP_XTSCAL, "pointercal", a_cur, 7);
00412 
00413     return;
00414 }
00415 #endif 
00416 
00417 
00418 static gchar *get_file_content(const gchar* file_path)
00419 {
00420     gchar* contents = NULL;
00421     gsize  len      = 0;
00422 
00423     if (g_file_get_contents(file_path, &contents, &len, NULL) == FALSE)
00424     {
00425         return NULL;
00426     }
00427 
00428     // Remove trailing '\n' characters
00429     while (len > 0 && (contents[len - 1] == '\n' || contents[len - 1] == '\0'))
00430     {
00431         contents[len - 1] = '\0';
00432         len--;
00433     }
00434     return contents;
00435 }
00436 
00437 
00438 static char *get_kernel_version()
00439 {
00440     struct utsname utsbuf;
00441     unsigned int   build_no;
00442 
00443     if (-1 == uname(&utsbuf))
00444     {
00445         // An error occurred.
00446         return NULL;
00447     }
00448 
00449     // Return only the build number of the kernel, not the major version
00450     sscanf(utsbuf.version, "#%d", &build_no);
00451     return g_strdup_printf("%d", build_no);
00452 }
00453 
00454 
00455 static char *get_micro_bootloader_version()
00456 {
00457     char* serio = get_sub_dir("/sys/devices", "serio");
00458     char* bootloader_ver_path = NULL;
00459     char* content             = NULL;
00460 
00461     if (serio == NULL)
00462     {
00463         LOGPRINTF("Can't find the micro device name!");
00464         return NULL;
00465     }
00466 
00467     bootloader_ver_path = g_strdup_printf("%s/boot_ver", serio);
00468     content = get_file_content(bootloader_ver_path);
00469 
00470     g_free(bootloader_ver_path);
00471     g_free(serio);
00472     return content;
00473 }
00474 
00475 
00476 static char *get_micro_app_version()
00477 {
00478     char* serio = get_sub_dir("/sys/devices", "serio");
00479     char* app_ver_path = NULL;
00480     char* content      = NULL;
00481 
00482     if (serio == NULL)
00483     {
00484         LOGPRINTF("Can't find the micro device name!");
00485         return NULL;
00486     }
00487 
00488     app_ver_path = g_strdup_printf("%s/micro_ver", serio);
00489     content = get_file_content(app_ver_path);
00490 
00491     g_free(app_ver_path);
00492     g_free(serio);
00493     return content;
00494 }
00495 
00496 
00497 static char *get_sub_dir(const char* parent, const char* sub_dir)
00498 {
00499     GDir* dir  = g_dir_open(parent, 0, NULL);
00500     const char* file = NULL;
00501     char  full_path[256];
00502 
00503     if (dir == NULL)
00504     {
00505         return NULL;
00506     }
00507 
00508     while ((file = g_dir_read_name(dir)) != NULL)
00509     {
00510         // Skip regular file.
00511         snprintf(full_path, sizeof(full_path), "%s/%s", parent, file);
00512 
00513         if (g_file_test(full_path, G_FILE_TEST_IS_DIR) == TRUE &&
00514             g_str_has_prefix(file, sub_dir) == TRUE)
00515         {
00516             // Sub dir found.
00517             return g_strdup_printf("%s/%s", parent, file);
00518         }
00519     }
00520 
00521     g_dir_close(dir);
00522     return NULL;
00523 }
00524 
00525 
00526 static void export_device_info(GKeyFile *key_file)
00527 {
00528     gchar *data = NULL;
00529     gchar *cat = NULL;
00530     gchar *mod = NULL;
00531     gchar *reg = NULL;
00532     
00533     // Build up product type from category model and region: e.g. DR1000S-XW
00534     cat = get_file_content(PATH_SYSSET "fasm/category");
00535     mod = get_file_content(PATH_SYSSET "fasm/model");
00536     if (mod) g_strchomp(mod); // Need to strip because Jan adds trailing spaces in sysset
00537     reg = get_file_content(PATH_SYSSET "fasm/region");
00538     if (cat && mod && reg) data = g_strconcat(cat, mod, "-", reg, NULL);
00539     if (data) g_key_file_set_string(key_file, INI_GROUP_DEVICEINFO, "product_type", data);
00540     
00541     data = get_file_content(PATH_SYSSET "fasm/serial");
00542     if (data) g_key_file_set_string(key_file, INI_GROUP_DEVICEINFO, "serial_number", data);
00543 
00544     data = get_file_content("/etc/version");
00545     if (data) g_key_file_set_string(key_file, INI_GROUP_DEVICEINFO, "software_version", data);
00546 
00547     data = get_kernel_version();
00548     if (data) g_key_file_set_string(key_file, INI_GROUP_DEVICEINFO, "kernel_version", data);
00549     
00550     data = get_micro_bootloader_version();
00551     if (data) g_key_file_set_string(key_file, INI_GROUP_DEVICEINFO, "micro_bootloader", data);
00552 
00553     data = get_micro_app_version();
00554     if (data) g_key_file_set_string(key_file, INI_GROUP_DEVICEINFO, "micro_application", data);
00555     
00556     if (data) g_free(data);
00557     if (cat) g_free(cat);
00558     if (mod) g_free(mod);
00559     if (reg) g_free(reg);
00560 }
Generated by  doxygen 1.6.2-20100208