/*
* Copyright (C) 2023 Andrey V.Kosteltsev <kx@radix-linux.su>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "rcl-zone-utils.h"
static gsize strv_lenght( const gchar *const *list )
{
gsize len = 0;
gchar **p = (gchar **)list;
if( !list || *list == NULL )
return 0;
while( *p )
{
++len;
++p;
}
return len;
}
static gboolean strv_append( const gchar *const **list, const gchar *value )
{
gchar **c;
gchar *v;
gsize len;
if( !list || !value )
return FALSE;
len = strv_lenght( *list );
v = g_strdup( value );
if( !v )
return FALSE;
c = g_realloc( (gpointer)*list, len * sizeof(gchar *) + sizeof(gchar *) * 2 );
if( !c )
{
g_free( (gpointer)v );
return FALSE;
}
c[len] = v;
c[len+1] = NULL;
*list = (const gchar *const *)c;
return TRUE;
}
static gint comparator( gconstpointer item1, gconstpointer item2 )
{
return g_strcmp0( item1, item2 );
}
static GSList *g_slist_insert_sorted_unique( GSList *list, gpointer data, GCompareFunc func )
{
if( !data || !func )
return list;
if( !g_slist_find_custom( list, data, func ) )
list = g_slist_insert_sorted( list, data, func );
return list;
}
static GSList *get_timezones_from_tzdata_zi( void )
{
GSList *list = NULL;
FILE *fp = NULL;
gchar *ln = NULL, *line = NULL;
fp = fopen( "/usr/share/zoneinfo/tzdata.zi", "r" );
if( !fp )
return list;
line = (gchar *)g_malloc0( (gsize)PATH_MAX );
if( !line )
{
fclose( fp );
return list;
}
/**********************************************
Zone line format is: 'Zone' 'timezone' ...
Link line format is: 'Link' 'target' 'alias'
See `man (8) zic' for infirmation.
**********************************************/
while( (ln = fgets( line, PATH_MAX, fp )) )
{
gchar *p, *q;
if( !g_ascii_strncasecmp( ln, "Z", 1 ) )
{
p = &ln[1];
/* Skip spaces */
while( (*p == ' ' || *p == '\t') && *p != '\n' )
++p;
q = p;
/* Take the first entry */
while( *q != ' ' && *q != '\t' && *q != '\n' )
++q;
*q = '\0';
list = g_slist_insert_sorted_unique( list, (gpointer)g_strdup( p ), (GCompareFunc)comparator );
continue;
}
else if( !g_ascii_strncasecmp( ln, "L", 1 ) )
{
p = &ln[1];
/* Skip spaces */
while( (*p == ' ' || *p == '\t') && *p != '\n' )
++p;
q = p;
/* Skip the first entry */
while( *q != ' ' && *q != '\t' && *q != '\n' )
++q;
p = q;
/* Skip spaces */
while( (*p == ' ' || *p == '\t') && *p != '\n' )
++p;
q = p;
/* Take the second entry */
while( *q != ' ' && *q != '\t' && *q != '\n' )
++q;
*q = '\0';
list = g_slist_insert_sorted_unique( list, (gpointer)g_strdup( p ), (GCompareFunc)comparator );
}
else
{
continue;
}
}
g_free( (gpointer)line );
fclose( fp );
return list;
}
void timezones_free( const gchar *const **list )
{
gchar **c, **p;
if( !list || *list == NULL )
return;
p = c = (gpointer)*list;
while( *p )
{
g_free( (gpointer)*p );
++p;
}
g_free( (gpointer)c );
*list = (const gchar *const *)NULL;
}
void timezones_print( const gchar *const **list )
{
gchar **p;
if( !list || *list == NULL )
return;
p = (gpointer)*list;
while( *p )
{
g_print( "%s\n", *p );
++p;
}
}
gboolean get_timezones( const gchar *const **list )
{
GSList *slist = NULL, *iterator = NULL;
gboolean ret = TRUE;
slist = get_timezones_from_tzdata_zi();
if( !slist )
return FALSE;
for( iterator = slist; iterator; iterator = iterator->next )
{
gboolean rc = strv_append( list, (const gchar *)iterator->data );
if( !rc )
ret = FALSE;
g_free( (gpointer)iterator->data );
}
g_slist_free(slist);
return ret;
}