diff --git a/lib/crm/common/iso8601.c b/lib/crm/common/iso8601.c index 92e10d2d3d..bf80bed997 100644 --- a/lib/crm/common/iso8601.c +++ b/lib/crm/common/iso8601.c @@ -1,1171 +1,1205 @@ -/* $Id: iso8601.c,v 1.7 2005/08/11 09:53:09 andrew Exp $ */ +/* $Id: iso8601.c,v 1.8 2005/08/11 14:43:30 andrew Exp $ */ /* * Copyright (C) 2005 Andrew Beekhof * * 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.1 of the License, or (at your option) any later version. * * This software 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 library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Primary reference: * http://en.wikipedia.org/wiki/ISO_8601 (as at 2005-08-01) * * Secondary references: * http://hydracen.com/dx/iso8601.htm * http://www.personal.ecu.edu/mccartyr/ISOwdALG.txt * http://www.personal.ecu.edu/mccartyr/isowdcal.html * http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm * */ #include #include #include #include gboolean gregorian_to_ordinal(ha_time_t *a_date); gboolean ordinal_to_gregorian(ha_time_t *a_date); gboolean ordinal_to_weekdays(ha_time_t *a_date); void normalize_time(ha_time_t *a_time); void log_date(int log_level, const char *prefix, ha_time_t *date_time, int flags) { char *date_s = NULL; char *time_s = NULL; char *offset_s = NULL; ha_time_t *dt = NULL; if(flags & ha_log_local) { crm_debug_6("Local version"); dt = date_time; } else { dt = date_time->normalized; } CRM_DEV_ASSERT(dt != NULL); if(crm_assert_failed) { return; } if(flags & ha_log_date) { crm_malloc0(date_s, sizeof(char)*(32)); if(date_s == NULL) { } else if(flags & ha_date_weeks) { snprintf(date_s, 31, "%d-W%.2d-%d", dt->weekyears, dt->weeks, dt->weekdays); } else if(flags & ha_date_ordinal) { snprintf(date_s, 31, "%d-%.3d",dt->years, dt->yeardays); } else { snprintf(date_s, 31, "%.4d-%.2d-%.2d", dt->years, dt->months, dt->days); } } if(flags & ha_log_time) { int offset = 0; crm_malloc0(time_s, sizeof(char)*(32)); if(time_s == NULL) { return; } snprintf(time_s, 31, "%.2d:%.2d:%.2d", dt->hours, dt->minutes, dt->seconds); if(dt->offset != NULL) { offset =(dt->offset->hours * 100) + dt->offset->minutes; } crm_malloc0(offset_s, sizeof(char)*(32)); if((flags & ha_log_local) == 0 || offset == 0) { snprintf(offset_s, 31, "Z"); } else { + int hr = dt->offset->hours; + int mins = dt->offset->minutes; + if(hr < 0) { + hr = 0 - hr; + } + if(mins < 0) { + mins = 0 - mins; + } snprintf(offset_s, 31, " %s%.2d:%.2d", - offset>0?"+":"-", - dt->offset->hours, dt->offset->minutes); + offset>0?"+":"-", hr, mins); } } crm_log_maybe(log_level, "%s%s%s%s%s%s", prefix?prefix:"", prefix?": ":"", date_s?date_s:"", (date_s!=NULL&&time_s!=NULL)?" ":"", time_s?time_s:"", offset_s?offset_s:""); crm_free(date_s); crm_free(time_s); crm_free(offset_s); } void log_time_period(int log_level, ha_time_period_t *dtp, int flags) { log_date(log_level, "Period start:", dtp->start, flags); log_date(log_level, "Period end:", dtp->end, flags); } ha_time_t* parse_time_offset(char **offset_str) { ha_time_t *new_time = NULL; crm_malloc0(new_time, sizeof(ha_time_t)); crm_malloc0(new_time->has, sizeof(ha_has_time_t)); - if((*offset_str)[0] != 'Z') { + if((*offset_str)[0] == 'Z') { + + } else if((*offset_str)[0] == '+' + || (*offset_str)[0] == '-' + || isdigit((*offset_str)[0])) { + gboolean negate = FALSE; + if((*offset_str)[0] == '-') { + negate = TRUE; + } parse_time(offset_str, new_time, FALSE); + if(negate) { + new_time->hours = 0 - new_time->hours; + new_time->minutes = 0 - new_time->minutes; + new_time->seconds = 0 - new_time->seconds; + } + + } else { + time_t now = time(NULL); + struct tm *now_tm = localtime(&now); + int h_offset = now_tm->tm_gmtoff / (3600); + int m_offset = (now_tm->tm_gmtoff - (3600 * h_offset)) / (60); + if(h_offset < 0 && m_offset < 0) { + m_offset = 0 - m_offset; + } + new_time->hours = h_offset; + new_time->minutes = m_offset; + new_time->has->hours = TRUE; + new_time->has->minutes = TRUE; } return new_time; } ha_time_t* parse_time(char **time_str, ha_time_t *a_time, gboolean with_offset) { ha_time_t *new_time = a_time; + tzset(); if(a_time == NULL) { new_time = new_ha_date(FALSE); } CRM_DEV_ASSERT(new_time != NULL); CRM_DEV_ASSERT(new_time->has != NULL); crm_debug_4("Get hours..."); if(parse_int(time_str, 2, 24, &new_time->hours)) { new_time->has->hours = TRUE; } crm_debug_4("Get minutes..."); if(parse_int(time_str, 2, 60, &new_time->minutes)) { new_time->has->minutes = TRUE; } crm_debug_4("Get seconds..."); if(parse_int(time_str, 2, 60, &new_time->seconds)){ new_time->has->seconds = TRUE; } if(with_offset) { crm_debug_4("Get offset..."); while(isspace((*time_str)[0])) { (*time_str)++; } new_time->offset = parse_time_offset(time_str); + normalize_time(new_time); } return new_time; } void normalize_time(ha_time_t *a_time) { CRM_DEV_ASSERT(a_time != NULL); CRM_DEV_ASSERT(a_time->has != NULL); if(a_time->normalized == NULL) { crm_malloc0(a_time->normalized, sizeof(ha_time_t)); } if(a_time->normalized->has == NULL) { crm_malloc0(a_time->normalized->has, sizeof(ha_has_time_t)); } ha_set_time(a_time->normalized, a_time, FALSE); if(a_time->offset != NULL) { if(a_time->offset->has->hours) { - add_hours(a_time->normalized, a_time->offset->hours); + sub_hours(a_time->normalized, a_time->offset->hours); } if(a_time->offset->has->minutes) { - add_minutes(a_time->normalized,a_time->offset->minutes); + sub_minutes(a_time->normalized,a_time->offset->minutes); } if(a_time->offset->has->seconds) { - add_seconds(a_time->normalized,a_time->offset->seconds); + sub_seconds(a_time->normalized,a_time->offset->seconds); } } CRM_DEV_ASSERT(is_date_sane(a_time)); } ha_time_t * parse_date(char **date_str) { + gboolean is_done = FALSE; gboolean converted = FALSE; ha_time_t *new_time = NULL; crm_malloc0(new_time, sizeof(ha_time_t)); crm_malloc0(new_time->has, sizeof(ha_has_time_t)); CRM_DEV_ASSERT(date_str != NULL); CRM_DEV_ASSERT(strlen(*date_str) > 0); - while(isspace((*date_str)[0]) == FALSE) { + while(is_done == FALSE) { char ch = (*date_str)[0]; crm_debug_5("Switching on ch=%c (len=%d)", ch, (int)strlen(*date_str)); if(ch == 0) { /* all done */ + is_done = TRUE; break; } else if(ch == '/') { /* all done - interval marker */ + is_done = TRUE; break; } else if(ch == 'W') { CRM_DEV_ASSERT(new_time->has->weeks == FALSE); (*date_str)++; if(parse_int(date_str, 2, 53, &new_time->weeks)){ new_time->has->weeks = TRUE; new_time->weekyears = new_time->years; new_time->has->weekyears = new_time->has->years; } if((*date_str)[0] == '-') { (*date_str)++; if(parse_int(date_str, 1, 7, &new_time->weekdays)) { new_time->has->weekdays = TRUE; } } if(new_time->weekdays == 0 || new_time->has->weekdays == FALSE) { new_time->weekdays = 1; new_time->has->weekdays = TRUE; } } else if(ch == '-') { (*date_str)++; if(check_for_ordinal(*date_str)) { if(parse_int(date_str, 3, 366, &new_time->yeardays)) { new_time->has->yeardays = TRUE; } } } else if(ch == 'O') { /* ordinal date */ (*date_str)++; if(parse_int(date_str, 3, 366, &new_time->yeardays)){ new_time->has->yeardays = TRUE; } - } else if(ch == 'T') { + } else if(ch == 'T' || ch == ' ') { if(new_time->has->yeardays) { converted = convert_from_ordinal(new_time); } else if(new_time->has->weekdays) { converted = convert_from_weekdays(new_time); } else { converted = convert_from_gregorian(new_time); } (*date_str)++; parse_time(date_str, new_time, TRUE); + is_done = TRUE; } else if(isdigit(ch)) { if(new_time->has->years == FALSE && parse_int(date_str, 4, 9999, &new_time->years)) { new_time->has->years = TRUE; } else if(check_for_ordinal(*date_str) && parse_int( date_str, 3, is_leap_year(new_time->years)?366:365, &new_time->yeardays)) { new_time->has->yeardays = TRUE; } else if(new_time->has->months == FALSE && parse_int(date_str, 2, 12, &new_time->months)) { new_time->has->months = TRUE; } else if(new_time->has->days == FALSE) { if(parse_int(date_str, 2, days_per_month(new_time->months, new_time->years), &new_time->days)) { new_time->has->days = TRUE; } } - } else if(isspace(ch)) { - (*date_str)++; -/* } else if(new_time->has->months == FALSE) { */ -/* new_time->months = str_lookup(*date_str, date_month); */ -/* new_time->has->months = TRUE; */ - -/* } else if(new_time->has->days == FALSE) { */ -/* new_time->days = str_lookup(*date_str, date_day); */ -/* new_time->has->days = TRUE; */ } else { crm_err("Unexpected characters at: %s", *date_str); + is_done = TRUE; break; } } if(converted) { } else if(new_time->has->yeardays) { convert_from_ordinal(new_time); } else if(new_time->has->weekdays) { convert_from_weekdays(new_time); } else { convert_from_gregorian(new_time); } normalize_time(new_time); log_date(LOG_DEBUG_3, "Unpacked", new_time, ha_log_date|ha_log_time); CRM_DEV_ASSERT(is_date_sane(new_time)); return new_time; } ha_time_t* parse_time_duration(char **interval_str) { gboolean is_time = FALSE; ha_time_t *diff = NULL; crm_malloc0(diff, sizeof(ha_time_t)); crm_malloc0(diff->has, sizeof(ha_has_time_t)); CRM_DEV_ASSERT(interval_str != NULL); CRM_DEV_ASSERT(strlen(*interval_str) > 0); CRM_DEV_ASSERT((*interval_str)[0] == 'P'); (*interval_str)++; while(isspace((*interval_str)[0]) == FALSE) { int an_int = 0; char ch = 0; if((*interval_str)[0] == 'T') { is_time = TRUE; (*interval_str)++; } if(parse_int(interval_str, 10, 0, &an_int) == FALSE) { break; } ch = (*interval_str)[0]; (*interval_str)++; crm_debug_4("%c=%d", ch, an_int); switch(ch) { case 0: return diff; break; case 'Y': diff->years = an_int; diff->has->years = TRUE; break; case 'M': if(is_time) { diff->minutes = an_int; diff->has->minutes = TRUE; } else { diff->months = an_int; diff->has->months = TRUE; } break; case 'W': diff->weeks = an_int; diff->has->weeks = TRUE; break; case 'D': diff->days = an_int; diff->has->days = TRUE; break; case 'H': diff->hours = an_int; diff->has->hours = TRUE; break; case 'S': diff->seconds = an_int; diff->has->seconds = TRUE; break; default: break; } } return diff; } ha_time_period_t* parse_time_period(char **period_str) { gboolean invalid = FALSE; const char *original = *period_str; ha_time_period_t *period = NULL; crm_malloc0(period, sizeof(ha_time_period_t)); CRM_DEV_ASSERT(period_str != NULL); CRM_DEV_ASSERT(strlen(*period_str) > 0); tzset(); if((*period_str)[0] == 'P') { period->diff = parse_time_duration(period_str); } else { period->start = parse_date(period_str); } if((*period_str)[0] != 0) { CRM_DEV_ASSERT((*period_str)[0] == '/'); (*period_str)++; if((*period_str)[0] == 'P') { period->diff = parse_time_duration(period_str); } else { period->end = parse_date(period_str); } } else if(period->diff != NULL) { /* just aduration starting from now */ time_t now = time(NULL); crm_malloc0(period->start, sizeof(ha_time_t)); crm_malloc0(period->start->has, sizeof(ha_has_time_t)); crm_malloc0(period->start->offset, sizeof(ha_time_t)); crm_malloc0(period->start->offset->has, sizeof(ha_has_time_t)); ha_set_timet_time(period->start, &now); normalize_time(period->start); } else { CRM_DEV_ASSERT((*period_str)[0] == '/'); return NULL; } /* sanity checks */ if(period->start == NULL && period->end == NULL) { crm_err("Invalid time period: %s", original); invalid = TRUE; } else if(period->start == NULL && period->diff == NULL) { crm_err("Invalid time period: %s", original); invalid = TRUE; } else if(period->end == NULL && period->diff == NULL) { crm_err("Invalid time period: %s", original); invalid = TRUE; } if(invalid) { crm_free(period->start); crm_free(period->end); crm_free(period->diff); crm_free(period); return NULL; } if(period->end == NULL && period->diff == NULL) { } if(period->start == NULL) { period->start = subtract_time(period->end, period->diff); normalize_time(period->start); } else if(period->end == NULL) { period->end = add_time(period->start, period->diff); normalize_time(period->end); } is_date_sane(period->start); is_date_sane(period->end); return period; } int month2days[13] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; /* http://www.personal.ecu.edu/mccartyr/ISOwdALG.txt */ int january1(int year) { int YY = (year - 1) % 100; int C = (year - 1) - YY; int G = YY + YY/4; int jan1 = 1 + (((((C / 100) % 4) * 5) + G) % 7); crm_debug_6("YY=%d, C=%d, G=%d", YY, C, G); crm_debug_5("January 1 %.4d: %d", year, jan1); return jan1; } int weeks_in_year(int year) { int weeks = 52; int jan1 = january1(year); /* if jan1 == thursday */ if(jan1 == 4) { weeks++; } else { jan1 = january1(year+1); /* if dec31 == thursday aka. jan1 of next year is a friday */ if(jan1 == 5) { weeks++; } } return weeks; } gboolean convert_from_gregorian(ha_time_t *a_date) { CRM_DEV_ASSERT(gregorian_to_ordinal(a_date)); CRM_DEV_ASSERT(ordinal_to_weekdays(a_date)); return TRUE; } gboolean gregorian_to_ordinal(ha_time_t *a_date) { CRM_DEV_ASSERT(a_date->has->years); CRM_DEV_ASSERT(a_date->has->months); CRM_DEV_ASSERT(a_date->has->days); CRM_DEV_ASSERT(a_date->months > 0); CRM_DEV_ASSERT(a_date->days > 0); a_date->yeardays = month2days[a_date->months-1]; a_date->yeardays += a_date->days; a_date->has->yeardays = TRUE; if(is_leap_year(a_date->years) && a_date->months > 2) { (a_date->yeardays)++; } crm_debug_4("Converted %.4d-%.2d-%.2d to %.4d-%.3d", a_date->years, a_date->months, a_date->days, a_date->years, a_date->yeardays); return TRUE; } gboolean convert_from_ordinal(ha_time_t *a_date) { CRM_DEV_ASSERT(ordinal_to_gregorian(a_date)); CRM_DEV_ASSERT(ordinal_to_weekdays(a_date)); return TRUE; } gboolean ordinal_to_gregorian(ha_time_t *a_date) { CRM_DEV_ASSERT(a_date->has->years); CRM_DEV_ASSERT(a_date->has->yeardays); CRM_DEV_ASSERT(a_date->yeardays > 0); a_date->days = a_date->yeardays; a_date->months = 11; if(is_leap_year(a_date->years) && a_date->yeardays > 366) { crm_err("Year %.4d only has 366 days (supplied %.3d)", a_date->years, a_date->yeardays); a_date->yeardays = 366; } else if(!is_leap_year(a_date->years) && a_date->yeardays > 365) { crm_err("Year %.4d only has 365 days (supplied %.3d)", a_date->years, a_date->yeardays); a_date->yeardays = 365; } while(a_date->months > 0 && a_date->yeardays <= month2days[a_date->months]) { crm_debug_6("month %d: %d vs. %d", a_date->months, a_date->yeardays, month2days[a_date->months]); (a_date->months)--; } a_date->days -= month2days[a_date->months]; (a_date->months)++; CRM_DEV_ASSERT(a_date->months > 0); if(is_leap_year(a_date->years) && a_date->months > 2) { (a_date->days)--; } if(a_date->days == 0) { /* annoying underflow */ a_date->days = days_per_month(a_date->months, a_date->years); (a_date->months)--; } a_date->has->days = TRUE; a_date->has->months = TRUE; a_date->has->years = TRUE; crm_debug_4("Converted %.4d-%.3d to %.4d-%.2d-%.2d", a_date->years, a_date->yeardays, a_date->years, a_date->months, a_date->days); return TRUE; } gboolean ordinal_to_weekdays(ha_time_t *a_date) { int year_num = 0; int jan1 = january1(a_date->years); int h = -1; CRM_DEV_ASSERT(a_date->has->years); CRM_DEV_ASSERT(a_date->has->yeardays); CRM_DEV_ASSERT(a_date->yeardays > 0); h = a_date->yeardays + jan1 - 1; a_date->weekdays = 1 + ((h-1) % 7); a_date->has->weekdays = TRUE; if(a_date->yeardays <= (8-jan1) && jan1 > 4) { year_num = a_date->years - 1; a_date->weeks = weeks_in_year(year_num); a_date->has->weeks = TRUE; } else { year_num = a_date->years; } if(year_num == a_date->years) { int i = 365; if(is_leap_year(year_num)) { i = 366; } if( (i - a_date->yeardays) < (4 - a_date->weekdays) ) { year_num = a_date->years + 1; a_date->weeks = 1; a_date->has->weeks = TRUE; } } if(year_num == a_date->years) { int j = a_date->yeardays + (7-a_date->weekdays) + (jan1 - 1); a_date->weeks = j / 7; a_date->has->weeks = TRUE; if(jan1 > 4) { a_date->weeks -= 1; } } a_date->weekyears = year_num; a_date->has->weekyears = TRUE; crm_debug_4("Converted %.4d-%.3d to %.4dW%.2d-%d", a_date->years, a_date->yeardays, a_date->weekyears, a_date->weeks, a_date->weekdays); return TRUE; } gboolean convert_from_weekdays(ha_time_t *a_date) { gboolean conversion = FALSE; int jan1 = january1(a_date->weekyears); CRM_DEV_ASSERT(a_date->has->weekyears); CRM_DEV_ASSERT(a_date->has->weeks); CRM_DEV_ASSERT(a_date->has->weekdays); CRM_DEV_ASSERT(a_date->weeks > 0); CRM_DEV_ASSERT(a_date->weekdays > 0); CRM_DEV_ASSERT(a_date->weekdays < 8); a_date->has->years = TRUE; a_date->years = a_date->weekyears; a_date->has->yeardays = TRUE; a_date->yeardays = (7 * (a_date->weeks-1)); /* break up the addition to make sure overflows are correctly handled */ if(a_date->yeardays == 0) { a_date->yeardays = a_date->weekdays; } else { add_yeardays(a_date, a_date->weekdays); } crm_debug_5("Pre-conversion: %dW%d-%d to %.4d-%.3d", a_date->weekyears, a_date->weeks, a_date->weekdays, a_date->years, a_date->yeardays); conversion = ordinal_to_gregorian(a_date); if(conversion) { if(jan1 < 4) { sub_days(a_date, jan1-1); } else if(jan1 > 4) { add_days(a_date, jan1-4); } } return conversion; } void ha_set_time(ha_time_t *lhs, ha_time_t *rhs, gboolean offset) { crm_debug_6("lhs=%p, rhs=%p, offset=%d", lhs, rhs, offset); CRM_DEV_ASSERT(lhs != NULL && rhs != NULL); CRM_DEV_ASSERT(lhs->has != NULL && rhs->has != NULL); lhs->years = rhs->years; lhs->has->years = rhs->has->years; lhs->weekyears = rhs->weekyears; lhs->has->weekyears = rhs->has->weekyears; lhs->months = rhs->months; lhs->has->months = rhs->has->months; lhs->weeks = rhs->weeks; lhs->has->weeks = rhs->has->weeks; lhs->days = rhs->days; lhs->has->days = rhs->has->days; lhs->weekdays = rhs->weekdays; lhs->has->weekdays = rhs->has->weekdays; lhs->yeardays = rhs->yeardays; lhs->has->yeardays = rhs->has->yeardays; lhs->hours = rhs->hours; lhs->has->hours = rhs->has->hours; lhs->minutes = rhs->minutes; lhs->has->minutes = rhs->has->minutes; lhs->seconds = rhs->seconds; lhs->has->seconds = rhs->has->seconds; if(lhs->offset) { reset_time(lhs->offset); } if(offset && rhs->offset) { ha_set_time(lhs->offset, rhs->offset, FALSE); } } void ha_set_tm_time(ha_time_t *lhs, struct tm *rhs) { int wday = rhs->tm_wday; int h_offset = 0; int m_offset = 0; if(rhs->tm_year > 0) { /* years since 1900 */ lhs->years = 1900 + rhs->tm_year; lhs->has->years = TRUE; } if(rhs->tm_yday > 0) { /* days since January 1 [0-365] */ lhs->yeardays = 1 + rhs->tm_yday; lhs->has->yeardays =TRUE; } if(rhs->tm_hour >= 0) { lhs->hours = rhs->tm_hour; lhs->has->hours =TRUE; } if(rhs->tm_min >= 0) { lhs->minutes = rhs->tm_min; lhs->has->minutes =TRUE; } if(rhs->tm_sec >= 0) { lhs->seconds = rhs->tm_sec; lhs->has->seconds =TRUE; } convert_from_ordinal(lhs); /* months since January [0-11] */ CRM_DEV_ASSERT(rhs->tm_mon < 0 || lhs->months == (1 + rhs->tm_mon)); /* day of the month [1-31] */ CRM_DEV_ASSERT(rhs->tm_mday < 0 || lhs->days == rhs->tm_mday); /* days since Sunday [0-6] */ if(wday == 0) { wday= 7; } CRM_DEV_ASSERT(rhs->tm_wday < 0 || lhs->weekdays == wday); CRM_DEV_ASSERT(lhs->offset != NULL); CRM_DEV_ASSERT(lhs->offset->has != NULL); /* tm_gmtoff == offset from UTC in seconds */ h_offset = rhs->tm_gmtoff / (3600); m_offset = (rhs->tm_gmtoff - (3600 * h_offset)) / (60); crm_debug_6("Offset (s): %ld, offset (hh:mm): %.2d:%.2d", rhs->tm_gmtoff, h_offset, m_offset); lhs->offset->hours = h_offset; lhs->offset->has->hours = TRUE; lhs->offset->minutes = m_offset; lhs->offset->has->minutes = TRUE; normalize_time(lhs); } void ha_set_timet_time(ha_time_t *lhs, time_t *rhs) { ha_set_tm_time(lhs, localtime(rhs)); } ha_time_t * add_time(ha_time_t *lhs, ha_time_t *rhs) { ha_time_t *answer = NULL; CRM_DEV_ASSERT(lhs != NULL && rhs != NULL); answer = new_ha_date(FALSE); ha_set_time(answer, lhs, TRUE); normalize_time(lhs); normalize_time(answer); if(rhs->has->years) { add_years(answer, rhs->years); } if(rhs->has->months) { add_months(answer, rhs->months); } if(rhs->has->weeks) { add_weeks(answer, rhs->weeks); } if(rhs->has->days) { add_days(answer, rhs->days); } add_hours(answer, rhs->hours); add_minutes(answer, rhs->minutes); add_seconds(answer, rhs->seconds); return answer; } ha_time_t * subtract_time(ha_time_t *lhs, ha_time_t *rhs) { ha_time_t *answer = NULL; CRM_DEV_ASSERT(lhs != NULL && rhs != NULL); answer = new_ha_date(FALSE); ha_set_time(answer, lhs, TRUE); normalize_time(lhs); normalize_time(rhs); normalize_time(answer); sub_years(answer, rhs->years); sub_months(answer, rhs->months); sub_weeks(answer, rhs->weeks); sub_days(answer, rhs->days); sub_hours(answer, rhs->hours); sub_minutes(answer, rhs->minutes); sub_seconds(answer, rhs->seconds); return answer; } /* ha_time_interval_t* */ /* parse_time_interval(char **interval_str) */ /* { */ /* return NULL; */ /* } */ int month_days[14] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 29 }; int days_per_month(int month, int year) { if(month == 2 && is_leap_year(year)) { month = 13; } return month_days[month]; } gboolean is_leap_year(int year) { gboolean is_leap = FALSE; if(year % 4 == 0) { is_leap = TRUE; } if(year % 100 == 0 && year % 400 != 0 ) { is_leap = FALSE; } return is_leap; } gboolean parse_int(char **str, int field_width, int uppper_bound, int *result) { int lpc = 0; int intermediate = 0; gboolean fraction = FALSE; gboolean negate = FALSE; CRM_DEV_ASSERT(str != NULL); CRM_DEV_ASSERT(*str != NULL); CRM_DEV_ASSERT(result != NULL); *result = 0; if(strlen(*str) <= 0) { return FALSE; } crm_debug_6("max width: %d, first char: %c", field_width, (*str)[0]); if((*str)[0] == '.' || (*str)[0] == ',') { fraction = TRUE; field_width = -1; (*str)++; } else if((*str)[0] == '-') { negate = TRUE; (*str)++; } else if((*str)[0] == '+' || (*str)[0] == ':') { (*str)++; } for(; (fraction || lpc < field_width) && isdigit((*str)[0]); lpc++) { if(fraction) { intermediate = ((*str)[0] - '0')/(10^lpc); } else { *result *= 10; intermediate = (*str)[0] - '0'; } *result += intermediate; (*str)++; } if(fraction) { *result = (int)(*result * uppper_bound); } else if(uppper_bound > 0 && *result > uppper_bound) { *result = uppper_bound; } if(negate) { *result = 0 - *result; } if(lpc > 0) { crm_debug_5("Found int: %d", *result); return TRUE; } return FALSE; } gboolean check_for_ordinal(const char *str) { if(isdigit(str[2]) == FALSE) { crm_debug_6("char 3 == %c", str[2]); return FALSE; } if(isspace(str[3])) { return TRUE; } else if(str[3] == 0) { return TRUE; } else if(str[3] == 'T') { return TRUE; } else if(str[3] == '/') { return TRUE; } crm_debug_6("char 4 == %c", str[3]); return FALSE; } int str_lookup(const char *str, enum date_fields field) { return 0; } void reset_time(ha_time_t *a_time) { a_time->years = 0; a_time->has->years = FALSE; a_time->weekyears = 0; a_time->has->weekyears = FALSE; a_time->months = 0; a_time->has->months = FALSE; a_time->weeks = 0; a_time->has->weeks = FALSE; a_time->days = 0; a_time->has->days = FALSE; a_time->weekdays = 0; a_time->has->weekdays = FALSE; a_time->yeardays = 0; a_time->has->yeardays = FALSE; a_time->hours = 0; a_time->has->hours = FALSE; a_time->minutes = 0; a_time->has->minutes = FALSE; a_time->seconds = 0; a_time->has->seconds = FALSE; } void reset_tm(struct tm *some_tm) { some_tm->tm_sec = -1; /* seconds after the minute [0-60] */ some_tm->tm_min = -1; /* minutes after the hour [0-59] */ some_tm->tm_hour = -1; /* hours since midnight [0-23] */ some_tm->tm_mday = -1; /* day of the month [1-31] */ some_tm->tm_mon = -1; /* months since January [0-11] */ some_tm->tm_year = -1; /* years since 1900 */ some_tm->tm_wday = -1; /* days since Sunday [0-6] */ some_tm->tm_yday = -1; /* days since January 1 [0-365] */ some_tm->tm_isdst = -1; /* Daylight Savings Time flag */ some_tm->tm_gmtoff = -1; /* offset from CUT in seconds */ some_tm->tm_zone = NULL;/* timezone abbreviation */ } gboolean is_date_sane(ha_time_t *a_date) { int ydays = 0; int mdays = 0; int weeks = 0; CRM_DEV_ASSERT(a_date != NULL); ydays = is_leap_year(a_date->years)?366:365; mdays = days_per_month(a_date->months, a_date->years); weeks = weeks_in_year(a_date->weekyears); crm_debug_5("max ydays: %d, max mdays: %d, max weeks: %d", ydays, mdays, weeks); CRM_DEV_ASSERT(a_date->has->years); CRM_DEV_ASSERT(a_date->has->weekyears); CRM_DEV_ASSERT(a_date->has->months); CRM_DEV_ASSERT(a_date->months > 0); CRM_DEV_ASSERT(a_date->months <= 12); CRM_DEV_ASSERT(a_date->has->weeks); CRM_DEV_ASSERT(a_date->weeks > 0); CRM_DEV_ASSERT(a_date->weeks <= weeks); CRM_DEV_ASSERT(a_date->has->days); CRM_DEV_ASSERT(a_date->days > 0); CRM_DEV_ASSERT(a_date->days <= mdays); CRM_DEV_ASSERT(a_date->has->weekdays); CRM_DEV_ASSERT(a_date->weekdays > 0); CRM_DEV_ASSERT(a_date->weekdays <= 7); CRM_DEV_ASSERT(a_date->has->yeardays); CRM_DEV_ASSERT(a_date->yeardays > 0); CRM_DEV_ASSERT(a_date->yeardays <= ydays); CRM_DEV_ASSERT(a_date->hours >= 0); CRM_DEV_ASSERT(a_date->hours < 24); CRM_DEV_ASSERT(a_date->minutes >= 0); CRM_DEV_ASSERT(a_date->minutes < 60); CRM_DEV_ASSERT(a_date->seconds >= 0); CRM_DEV_ASSERT(a_date->seconds <= 60); return TRUE; } #define do_cmp_field(lhs, rhs, field) \ { \ if(lhs->field > rhs->field) { \ crm_debug_2("%s: %d > %d", \ #field, lhs->field, rhs->field); \ return 1; \ } else if(lhs->field < rhs->field) { \ crm_debug_2("%s: %d < %d", \ #field, lhs->field, rhs->field); \ return -1; \ } \ } int compare_date(ha_time_t *lhs, ha_time_t *rhs) { normalize_time(lhs); normalize_time(rhs); do_cmp_field(lhs->normalized, rhs->normalized, years); do_cmp_field(lhs->normalized, rhs->normalized, yeardays); do_cmp_field(lhs->normalized, rhs->normalized, hours); do_cmp_field(lhs->normalized, rhs->normalized, minutes); do_cmp_field(lhs->normalized, rhs->normalized, seconds); return 0; } ha_time_t * new_ha_date(gboolean set_to_now) { - time_t tm_now = time(NULL); + time_t tm_now; ha_time_t *now = NULL; + + tzset(); + tm_now = time(NULL); crm_malloc0(now, sizeof(ha_time_t)); crm_malloc0(now->has, sizeof(ha_has_time_t)); crm_malloc0(now->offset, sizeof(ha_time_t)); crm_malloc0(now->offset->has, sizeof(ha_has_time_t)); if(set_to_now) { ha_set_timet_time(now, &tm_now); } return now; } void free_ha_date(ha_time_t *a_date) { if(a_date == NULL) { return; } free_ha_date(a_date->normalized); free_ha_date(a_date->offset); crm_free(a_date->has); crm_free(a_date); } void log_tm_date(int log_level, struct tm *some_tm) { crm_log_maybe(log_level, "%.2d/%.2d/%.4d %.2d:%.2d:%.2d %s" " (wday=%d, yday=%d, dst=%d, offset=%ld)", some_tm->tm_mday, some_tm->tm_mon, 1900+some_tm->tm_year, some_tm->tm_hour, some_tm->tm_min, some_tm->tm_sec, some_tm->tm_zone, some_tm->tm_wday==0?7:some_tm->tm_wday, 1+some_tm->tm_yday, some_tm->tm_isdst, some_tm->tm_gmtoff); } diff --git a/lib/crm/common/iso8601_fields.c b/lib/crm/common/iso8601_fields.c index e5797bdf54..270ec8620e 100644 --- a/lib/crm/common/iso8601_fields.c +++ b/lib/crm/common/iso8601_fields.c @@ -1,375 +1,404 @@ -/* $Id: iso8601_fields.c,v 1.2 2005/08/08 12:14:47 andrew Exp $ */ +/* $Id: iso8601_fields.c,v 1.3 2005/08/11 14:43:30 andrew Exp $ */ /* * Copyright (C) 2005 Andrew Beekhof * * 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.1 of the License, or (at your option) any later version. * * This software 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 library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * http://en.wikipedia.org/wiki/ISO_8601 as at 2005-08-01 * */ #include #include #include #include #define do_add_field(atime, field, extra, limit, overflow) \ { \ crm_debug_6("Adding %d to %d (limit=%d)", \ extra, atime->field, limit); \ atime->field += extra; \ if(limit > 0) { \ while(limit < atime->field) { \ crm_debug_6("Overflowing: %d", atime->field); \ atime->field -= limit; \ overflow(atime, 1); \ } \ } \ atime->field = atime->field; \ crm_debug_6("Result: %d", atime->field); \ } +#define do_add_time_field(atime, field, extra, limit, overflow) \ + { \ + crm_debug_6("Adding %d to %d (limit=%d)", \ + extra, atime->field, limit); \ + atime->field += extra; \ + if(limit > 0) { \ + while(limit <= atime->field) { \ + crm_debug_6("Overflowing: %d", atime->field); \ + atime->field -= limit; \ + overflow(atime, 1); \ + } \ + } \ + atime->field = atime->field; \ + crm_debug_6("Result: %d", atime->field); \ + } + #define do_sub_field(atime, field, extra, limit, overflow) \ { \ crm_debug_6("Subtracting %d from %d (limit=%d)", \ extra, atime->field, limit); \ atime->field -= extra; \ while(atime->field <= 1) { \ crm_debug_6("Underflowing: %d", atime->field); \ atime->field += limit; \ overflow(atime, 1); \ } \ crm_debug_6("Result: %d", atime->field); \ } +#define do_sub_time_field(atime, field, extra, limit, overflow) \ + { \ + crm_debug_6("Subtracting %d from %d (limit=%d)", \ + extra, atime->field, limit); \ + atime->field -= extra; \ + while(atime->field < 0) { \ + crm_debug_6("Underflowing: %d", atime->field); \ + atime->field += limit; \ + overflow(atime, 1); \ + } \ + crm_debug_6("Result: %d", atime->field); \ + } + void add_seconds(ha_time_t *a_time, int extra) { if(extra < 0) { sub_seconds(a_time, -extra); } else { - do_add_field(a_time, seconds, extra, 60, add_minutes); + do_add_time_field(a_time, seconds, extra, 60, add_minutes); } } void add_minutes(ha_time_t *a_time, int extra) { if(extra < 0) { sub_minutes(a_time, -extra); } else { - do_add_field(a_time, minutes, extra, 60, add_hours); + do_add_time_field(a_time, minutes, extra, 60, add_hours); } } void add_hours(ha_time_t *a_time, int extra) { if(extra < 0) { sub_hours(a_time, -extra); } else { - do_add_field(a_time, hours, extra, 24, add_days); + do_add_time_field(a_time, hours, extra, 24, add_days); } } void add_days(ha_time_t *a_time, int extra) { if(a_time->has->days == FALSE) { crm_debug_4("has->days == FALSE"); return; } if(extra < 0) { sub_days(a_time, -extra); } else { do_add_field(a_time, days, extra, days_per_month(a_time->months, a_time->years), add_months); } convert_from_gregorian(a_time); } void add_weekdays(ha_time_t *a_time, int extra) { if(a_time->has->weekdays == FALSE) { crm_debug_4("has->weekdays == FALSE"); return; } if(extra < 0) { sub_weekdays(a_time, -extra); } else { do_add_field(a_time, weekdays, extra, 7, add_weeks); } convert_from_weekdays(a_time); } void add_yeardays(ha_time_t *a_time, int extra) { if(a_time->has->yeardays == FALSE) { crm_debug_4("has->yeardays == FALSE"); return; } if(extra < 0) { sub_yeardays(a_time, -extra); } else { do_add_field(a_time, yeardays, extra, (is_leap_year(a_time->years)?366:365), add_ordinalyears); } convert_from_ordinal(a_time); } void add_weeks(ha_time_t *a_time, int extra) { if(a_time->has->weeks== FALSE) { crm_debug_4("has->weeks == FALSE"); return; } if(extra < 0) { sub_weeks(a_time, -extra); } else { do_add_field(a_time, weeks, extra, weeks_in_year(a_time->years), add_weekyears); } convert_from_weekdays(a_time); } void add_months(ha_time_t *a_time, int extra) { int max = 0; if(a_time->has->months == FALSE) { crm_debug_4("has->months == FALSE"); return; } if(extra < 0) { sub_months(a_time, -extra); } else { do_add_field(a_time, months, extra, 12, add_years); } max = days_per_month(a_time->months, a_time->years); if(a_time->days > max) { a_time->days = max; } convert_from_gregorian(a_time); } void add_years(ha_time_t *a_time, int extra) { if(a_time->has->years == FALSE) { crm_debug_4("has->years == FALSE"); return; } a_time->years += extra; convert_from_gregorian(a_time); } void add_ordinalyears(ha_time_t *a_time, int extra) { if(a_time->has->years == FALSE) { crm_debug_4("has->years == FALSE"); return; } a_time->years += extra; convert_from_ordinal(a_time); } void add_weekyears(ha_time_t *a_time, int extra) { if(a_time->has->weekyears == FALSE) { crm_debug_4("has->weekyears == FALSE"); return; } a_time->weekyears += extra; convert_from_weekdays(a_time); } void sub_seconds(ha_time_t *a_time, int extra) { if(extra < 0) { add_seconds(a_time, -extra); } else { - do_sub_field(a_time, seconds, extra, 60, sub_minutes); + do_sub_time_field(a_time, seconds, extra, 60, sub_minutes); } } void sub_minutes(ha_time_t *a_time, int extra) { if(extra < 0) { add_minutes(a_time, -extra); } else { - do_sub_field(a_time, minutes, extra, 60, sub_hours); + do_sub_time_field(a_time, minutes, extra, 60, sub_hours); } } void sub_hours(ha_time_t *a_time, int extra) { if(extra < 0) { add_hours(a_time, -extra); } else { - do_sub_field(a_time, hours, extra, 24, sub_days); + do_sub_time_field(a_time, hours, extra, 24, sub_days); } } void sub_days(ha_time_t *a_time, int extra) { if(a_time->has->days == FALSE) { crm_debug_4("has->days == FALSE"); return; } crm_debug_5("Subtracting %d days from %.4d-%.2d-%.2d", extra, a_time->years, a_time->months, a_time->days); if(extra < 0) { add_days(a_time, -extra); } else { do_sub_field(a_time, days, extra, days_per_month(a_time->months, a_time->years), sub_months); } convert_from_gregorian(a_time); } void sub_weekdays(ha_time_t *a_time, int extra) { if(a_time->has->weekdays == FALSE) { crm_debug_4("has->weekdays == FALSE"); return; } crm_debug_5("Subtracting %d days from %.4d-%.2d-%.2d", extra, a_time->years, a_time->months, a_time->days); if(extra < 0) { add_weekdays(a_time, -extra); } else { do_sub_field(a_time, weekdays, extra, 7, sub_weeks); } convert_from_weekdays(a_time); } void sub_yeardays(ha_time_t *a_time, int extra) { if(a_time->has->yeardays == FALSE) { crm_debug_4("has->yeardays == FALSE"); return; } crm_debug_5("Subtracting %d days from %.4d-%.3d", extra, a_time->years, a_time->yeardays); if(extra < 0) { add_yeardays(a_time, -extra); } else { do_sub_field(a_time, yeardays, extra, is_leap_year(a_time->years)?366:365, sub_ordinalyears); } convert_from_ordinal(a_time); } void sub_weeks(ha_time_t *a_time, int extra) { if(a_time->has->weeks == FALSE) { crm_debug_4("has->weeks == FALSE"); return; } if(extra < 0) { add_weeks(a_time, -extra); } else { do_sub_field(a_time, weeks, extra, weeks_in_year(a_time->years), sub_weekyears); } convert_from_weekdays(a_time); } void sub_months(ha_time_t *a_time, int extra) { if(a_time->has->months == FALSE) { crm_debug_4("has->months == FALSE"); return; } if(extra < 0) { add_months(a_time, -extra); } else { do_sub_field(a_time, months, extra, 12, sub_years); } convert_from_gregorian(a_time); } void sub_years(ha_time_t *a_time, int extra) { if(a_time->has->years == FALSE) { crm_debug_4("has->years == FALSE"); return; } a_time->years -= extra; convert_from_gregorian(a_time); } void sub_weekyears(ha_time_t *a_time, int extra) { if(a_time->has->weekyears == FALSE) { crm_debug_4("has->weekyears == FALSE"); return; } a_time->weekyears -= extra; convert_from_weekdays(a_time); } void sub_ordinalyears(ha_time_t *a_time, int extra) { if(a_time->has->years == FALSE) { crm_debug_4("has->years == FALSE"); return; } a_time->years -= extra; convert_from_ordinal(a_time); } diff --git a/lib/crm/common/utils.c b/lib/crm/common/utils.c index 6c301d32b1..718314fe4e 100644 --- a/lib/crm/common/utils.c +++ b/lib/crm/common/utils.c @@ -1,1026 +1,1025 @@ -/* $Id: utils.c,v 1.21 2005/08/08 12:05:02 andrew Exp $ */ +/* $Id: utils.c,v 1.22 2005/08/11 14:43:30 andrew Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * 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.1 of the License, or (at your option) any later version. * * This software 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 library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef MAXLINE # define MAXLINE 512 #endif static uint ref_counter = 0; gboolean crm_assert_failed = FALSE; unsigned int crm_log_level = LOG_INFO; void crm_set_env_options(void); char * generateReference(const char *custom1, const char *custom2) { const char *local_cust1 = custom1; const char *local_cust2 = custom2; int reference_len = 4; char *since_epoch = NULL; reference_len += 20; /* too big */ reference_len += 40; /* too big */ if(local_cust1 == NULL) { local_cust1 = "_empty_"; } reference_len += strlen(local_cust1); if(local_cust2 == NULL) { local_cust2 = "_empty_"; } reference_len += strlen(local_cust2); crm_malloc0(since_epoch, reference_len*(sizeof(char))); if(since_epoch != NULL) { sprintf(since_epoch, "%s-%s-%ld-%u", local_cust1, local_cust2, (unsigned long)time(NULL), ref_counter++); } return since_epoch; } gboolean decodeNVpair(const char *srcstring, char separator, char **name, char **value) { int lpc = 0; int len = 0; const char *temp = NULL; crm_debug_4("Attempting to decode: [%s]", srcstring); if (srcstring != NULL) { len = strlen(srcstring); while(lpc <= len) { if (srcstring[lpc] == separator || srcstring[lpc] == '\0') { crm_malloc0(*name, sizeof(char)*lpc+1); if(*name == NULL) { break; /* and return FALSE */ } strncpy(*name, srcstring, lpc); (*name)[lpc] = '\0'; /* this sucks but as the strtok manpage says.. * it *is* a bug */ len = len-lpc; len--; if(len <= 0) { *value = NULL; } else { crm_malloc0(*value, sizeof(char)*len+1); if(*value == NULL) { crm_free(*name); break; /* and return FALSE */ } temp = srcstring+lpc+1; strncpy(*value, temp, len); (*value)[len] = '\0'; } return TRUE; } lpc++; } } *name = NULL; *value = NULL; return FALSE; } char * generate_hash_key(const char *crm_msg_reference, const char *sys) { int ref_len = strlen(sys?sys:"none") + strlen(crm_msg_reference) + 2; char *hash_key = NULL; crm_malloc0(hash_key, sizeof(char)*(ref_len)); if(hash_key != NULL) { sprintf(hash_key, "%s_%s", sys?sys:"none", crm_msg_reference); hash_key[ref_len-1] = '\0'; crm_debug_3("created hash key: (%s)", hash_key); } return hash_key; } char * generate_hash_value(const char *src_node, const char *src_subsys) { int ref_len; char *hash_value = NULL; if (src_node == NULL || src_subsys == NULL) { return NULL; } if (strcmp(CRM_SYSTEM_DC, src_subsys) == 0) { hash_value = crm_strdup(src_subsys); if (!hash_value) { crm_err("memory allocation failed in " "generate_hash_value()"); return NULL; } return hash_value; } ref_len = strlen(src_subsys) + strlen(src_node) + 2; crm_malloc0(hash_value, sizeof(char)*(ref_len)); if (!hash_value) { crm_err("memory allocation failed in " "generate_hash_value()"); return NULL; } snprintf(hash_value, ref_len-1, "%s_%s", src_node, src_subsys); hash_value[ref_len-1] = '\0';/* make sure it is null terminated */ crm_info("created hash value: (%s)", hash_value); return hash_value; } gboolean decode_hash_value(gpointer value, char **node, char **subsys) { char *char_value = (char*)value; int value_len = strlen(char_value); crm_info("Decoding hash value: (%s:%d)", char_value, value_len); if (strcmp(CRM_SYSTEM_DC, (char*)value) == 0) { *node = NULL; *subsys = (char*)crm_strdup(char_value); if (*subsys == NULL) { crm_err("memory allocation failed in " "decode_hash_value()"); return FALSE; } crm_info("Decoded value: (%s:%d)", *subsys, (int)strlen(*subsys)); return TRUE; } else if (char_value != NULL) { if (decodeNVpair(char_value, '_', node, subsys)) { return TRUE; } else { *node = NULL; *subsys = NULL; return FALSE; } } return FALSE; } char * crm_itoa(int an_int) { int len = 32; char *buffer = NULL; crm_malloc0(buffer, sizeof(char)*(len+1)); if(buffer != NULL) { snprintf(buffer, len, "%d", an_int); } return buffer; } extern int LogToLoggingDaemon(int priority, const char * buf, int bstrlen, gboolean use_pri_str); gboolean crm_log_init(const char *entity) { /* const char *test = "Testing log daemon connection"; */ /* Redirect messages from glib functions to our handler */ /* cl_malloc_forced_for_glib(); */ g_log_set_handler(NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG | G_LOG_FLAG_RECURSION | G_LOG_FLAG_FATAL, cl_glib_msg_handler, NULL); /* and for good measure... - this enum is a bit field (!) */ g_log_set_always_fatal((GLogLevelFlags)0); /*value out of range*/ cl_log_set_entity(entity); cl_log_set_facility(LOG_LOCAL7); cl_set_corerootdir(HA_COREDIR); cl_cdtocoredir(); crm_set_env_options(); CL_SIGNAL(DEBUG_INC, alter_debug); CL_SIGNAL(DEBUG_DEC, alter_debug); return TRUE; } /* returns the old value */ unsigned int set_crm_log_level(unsigned int level) { unsigned int old = crm_log_level; while(crm_log_level < level) { alter_debug(DEBUG_INC); } while(crm_log_level > level) { alter_debug(DEBUG_DEC); } return old; } unsigned int get_crm_log_level(void) { return crm_log_level; } void crm_log_message_adv(int level, const char *prefix, const HA_Message *msg) { if((int)crm_log_level >= level) { do_crm_log(level, NULL, NULL, "#========= %s message start ==========#", prefix?prefix:""); if(level > LOG_DEBUG) { cl_log_message(LOG_DEBUG, msg); } else { cl_log_message(level, msg); } } } void do_crm_log(int log_level, const char *file, const char *function, const char *fmt, ...) { int log_as = log_level; gboolean do_log = FALSE; if(log_level <= (int)crm_log_level) { do_log = TRUE; if(log_level > LOG_INFO) { log_as = LOG_DEBUG; } } if(do_log) { va_list ap; int nbytes; char buf[MAXLINE]; va_start(ap, fmt); nbytes=vsnprintf(buf, MAXLINE, fmt, ap); va_end(ap); log_level -= LOG_INFO; if(log_level > 1) { if(file == NULL && function == NULL) { cl_log(log_as, "[%d] %s", log_level, buf); } else { cl_log(log_as, "mask(%s%s%s [%d]): %s", file?file:"", (file !=NULL && function !=NULL)?":":"", function?function:"", log_level, buf); } } else { if(file == NULL && function == NULL) { cl_log(log_as, "%s", buf); } else { cl_log(log_as, "mask(%s%s%s): %s", file?file:"", (file !=NULL && function !=NULL)?":":"", function?function:"", buf); } } if(nbytes > MAXLINE) { cl_log(LOG_WARNING, "Log from %s() was truncated", crm_str(function)); } } } int compare_version(const char *version1, const char *version2) { int lpc = 0; char *step1 = NULL, *step2 = NULL; char *rest1 = NULL, *rest2 = NULL; if(version1 == NULL && version2 == NULL) { return 0; } else if(version1 == NULL) { return -1; } else if(version2 == NULL) { return 1; } if(version1 != NULL) { rest1 = crm_strdup(version1); } else { version1 = ""; } if(version2 != NULL) { rest2 = crm_strdup(version2); } else { version2 = ""; } while(1) { int cmp = 0; int step1_i = 0; int step2_i = 0; char *tmp1 = NULL, *tmp2 = NULL; decodeNVpair(rest1, '.', &step1, &tmp1); decodeNVpair(rest2, '.', &step2, &tmp2); if(step1 != NULL) { step1_i = atoi(step1); } if(step2 != NULL) { step2_i = atoi(step2); } if(step1_i < step2_i){ cmp = -1; } else if (step1_i > step2_i){ cmp = 1; } crm_debug_4("compare[%d (%d)]: %d(%s) %d(%s)", lpc++, cmp, step1_i, crm_str(step1), step2_i, crm_str(step2)); crm_free(rest1); crm_free(rest2); rest1 = tmp1; rest2 = tmp2; if(step1 == NULL && step2 == NULL) { break; } crm_free(step1); crm_free(step2); if(cmp < 0) { crm_debug_2("%s < %s", version1, version2); return -1; } else if(cmp > 0) { crm_debug_2("%s > %s", version1, version2); return 1; } } crm_debug_2("%s == %s", version1, version2); return 0; } gboolean do_stderr = FALSE; void alter_debug(int nsig) { CL_SIGNAL(DEBUG_INC, alter_debug); CL_SIGNAL(DEBUG_DEC, alter_debug); switch(nsig) { case DEBUG_INC: crm_log_level++; crm_debug("Upped log level to %d", crm_log_level); break; case DEBUG_DEC: crm_log_level--; crm_debug("Reduced log level to %d", crm_log_level); break; default: fprintf(stderr, "Unknown signal %d\n", nsig); cl_log(LOG_ERR, "Unknown signal %d", nsig); break; } } void g_hash_destroy_str(gpointer data) { crm_free(data); } gboolean safe_str_eq(const char *a, const char *b) { if(a == b) { return TRUE; } else if(a == NULL || b == NULL) { return FALSE; } else if(strcmp(a, b) == 0) { return TRUE; } return FALSE; } gboolean safe_str_neq(const char *a, const char *b) { if(a == b) { return FALSE; } else if(a==NULL || b==NULL) { return TRUE; } else if(strcmp(a, b) == 0) { return FALSE; } return TRUE; } char * crm_strdup(const char *a) { char *ret = NULL; CRM_DEV_ASSERT(a != NULL); if(a != NULL) { ret = cl_strdup(a); } else { crm_warn("Cannot dup NULL string"); } return ret; } static GHashTable *crm_uuid_cache = NULL; void set_uuid(ll_cluster_t *hb,crm_data_t *node,const char *attr,const char *uname) { char *uuid_calc = NULL; if(crm_uuid_cache == NULL) { crm_uuid_cache = g_hash_table_new_full( g_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); } CRM_DEV_ASSERT(uname != NULL); /* avoid blocking calls where possible */ uuid_calc = g_hash_table_lookup(crm_uuid_cache, uname); if(uuid_calc != NULL) { crm_xml_add(node, attr, uuid_calc); return; } crm_malloc0(uuid_calc, sizeof(char)*50); if(uuid_calc != NULL) { cl_uuid_t uuid_raw; if(hb->llc_ops->get_uuid_by_name( hb, uname, &uuid_raw) == HA_FAIL) { crm_err("Could not calculate UUID for %s", uname); crm_free(uuid_calc); uuid_calc = crm_strdup(uname); } else { cl_uuid_unparse(&uuid_raw, uuid_calc); g_hash_table_insert( crm_uuid_cache, crm_strdup(uname), crm_strdup(uuid_calc)); } crm_xml_add(node, attr, uuid_calc); } crm_free(uuid_calc); }/*memory leak*/ /* BEAM BUG - this is not a memory leak */ void crm_set_ha_options(ll_cluster_t *hb_cluster) { #if 0 int facility; char *param_val = NULL; const char *param_name = NULL; if(hb_cluster == NULL) { crm_set_env_options(); return; } /* change the logging facility to the one used by heartbeat daemon */ crm_debug("Switching to Heartbeat logger"); if (( facility = hb_cluster->llc_ops->get_logfacility(hb_cluster)) > 0) { cl_log_set_facility(facility); } crm_debug_2("Facility: %d", facility); param_name = KEY_LOGFILE; param_val = hb_cluster->llc_ops->get_parameter(hb_cluster, param_name); crm_debug_3("%s = %s", param_name, param_val); if(param_val != NULL) { cl_log_set_logfile(param_val); cl_free(param_val); param_val = NULL; } param_name = KEY_DBGFILE; param_val = hb_cluster->llc_ops->get_parameter(hb_cluster, param_name); crm_debug_3("%s = %s", param_name, param_val); if(param_val != NULL) { cl_log_set_debugfile(param_val); cl_free(param_val); param_val = NULL; } param_name = KEY_DEBUGLEVEL; param_val = hb_cluster->llc_ops->get_parameter(hb_cluster, param_name); crm_debug_3("%s = %s", param_name, param_val); if(param_val != NULL) { int debug_level = atoi(param_val); if(debug_level > 0 && (debug_level+LOG_INFO) > (int)crm_log_level) { set_crm_log_level(LOG_INFO + debug_level); } cl_free(param_val); param_val = NULL; } param_name = KEY_LOGDAEMON; param_val = hb_cluster->llc_ops->get_parameter(hb_cluster, param_name); crm_debug_3("%s = %s", param_name, param_val); if(param_val != NULL) { int uselogd; crm_str_to_boolean(param_val, &uselogd); cl_log_set_uselogd(uselogd); if(cl_log_get_uselogd()) { cl_set_logging_wqueue_maxlen(500); } cl_free(param_val); param_val = NULL; } param_name = KEY_CONNINTVAL; param_val = hb_cluster->llc_ops->get_parameter(hb_cluster, param_name); crm_debug_3("%s = %s", param_name, param_val); if(param_val != NULL) { int logdtime; logdtime = crm_get_msec(param_val); cl_log_set_logdtime(logdtime); cl_free(param_val); param_val = NULL; } #endif } #define ENV_PREFIX "HA_" void crm_set_env_options(void) { char *param_val = NULL; const char *param_name = NULL; /* apparently we're not allowed to free the result of getenv */ param_name = ENV_PREFIX "" KEY_DEBUGLEVEL; param_val = getenv(param_name); crm_debug("%s = %s", param_name, param_val); if(param_val != NULL) { int debug_level = atoi(param_val); if(debug_level > 0 && (debug_level+LOG_INFO) > (int)crm_log_level) { set_crm_log_level(LOG_INFO + debug_level); } param_val = NULL; } param_name = ENV_PREFIX "" KEY_FACILITY; param_val = getenv(param_name); crm_debug("%s = %s", param_name, param_val); if(param_val != NULL) { int facility = cl_syslogfac_str2int(param_val); if(facility > 0) { cl_log_set_facility(facility); } param_val = NULL; } param_name = ENV_PREFIX "" KEY_LOGFILE; param_val = getenv(param_name); crm_debug("%s = %s", param_name, param_val); if(param_val != NULL) { if(safe_str_eq("/dev/null", param_val)) { param_val = NULL; } cl_log_set_logfile(param_val); param_val = NULL; } param_name = ENV_PREFIX "" KEY_DBGFILE; param_val = getenv(param_name); crm_debug("%s = %s", param_name, param_val); if(param_val != NULL) { if(safe_str_eq("/dev/null", param_val)) { param_val = NULL; } cl_log_set_debugfile(param_val); param_val = NULL; } param_name = ENV_PREFIX "" KEY_LOGDAEMON; param_val = getenv(param_name); crm_debug("%s = %s", param_name, param_val); if(param_val != NULL) { int uselogd; crm_str_to_boolean(param_val, &uselogd); cl_log_set_uselogd(uselogd); if(uselogd) { cl_set_logging_wqueue_maxlen(500); cl_log_set_logd_channel_source(NULL, NULL); } param_val = NULL; } param_name = ENV_PREFIX "" KEY_CONNINTVAL; param_val = getenv(param_name); crm_debug("%s = %s", param_name, param_val); if(param_val != NULL) { int logdtime; logdtime = crm_get_msec(param_val); cl_log_set_logdtime(logdtime); param_val = NULL; } } gboolean crm_is_true(const char * s) { gboolean ret = FALSE; crm_str_to_boolean(s, &ret); return ret; } int crm_str_to_boolean(const char * s, int * ret) { if(s == NULL) { return -1; } else if (strcasecmp(s, "true") == 0 || strcasecmp(s, "on") == 0 || strcasecmp(s, "yes") == 0 || strcasecmp(s, "y") == 0 || strcasecmp(s, "1") == 0){ *ret = TRUE; return 1; } else if (strcasecmp(s, "false") == 0 || strcasecmp(s, "off") == 0 || strcasecmp(s, "no") == 0 || strcasecmp(s, "n") == 0 || strcasecmp(s, "0") == 0){ *ret = FALSE; return 1; } return -1; } #ifndef NUMCHARS # define NUMCHARS "0123456789." #endif #ifndef WHITESPACE # define WHITESPACE " \t\n\r\f" #endif long crm_get_msec(const char * input) { const char * cp = input; const char * units; long multiplier = 1000; long divisor = 1; long ret = -1; double dret; if(input == NULL) { return 0; } cp += strspn(cp, WHITESPACE); units = cp + strspn(cp, NUMCHARS); units += strspn(units, WHITESPACE); if (strchr(NUMCHARS, *cp) == NULL) { return ret; } if (strncasecmp(units, "ms", 2) == 0 || strncasecmp(units, "msec", 4) == 0) { multiplier = 1; divisor = 1; }else if (strncasecmp(units, "us", 2) == 0 || strncasecmp(units, "usec", 4) == 0) { multiplier = 1; divisor = 1000; }else if (strncasecmp(units, "s", 1) == 0 || strncasecmp(units, "sec", 3) == 0) { multiplier = 1000; divisor = 1; }else if (strncasecmp(units, "m", 1) == 0 || strncasecmp(units, "min", 3) == 0) { multiplier = 60*1000; divisor = 1; }else if (*units != EOS && *units != '\n' && *units != '\r') { return ret; } dret = atof(cp); dret *= (double)multiplier; dret /= (double)divisor; dret += 0.5; ret = (long)dret; return(ret); } gboolean ccm_have_quorum(oc_ed_t event) { if(event==OC_EV_MS_NEW_MEMBERSHIP) { return TRUE; } return FALSE; } const char * ccm_event_name(oc_ed_t event) { if(event==OC_EV_MS_NEW_MEMBERSHIP) { return "NEW MEMBERSHIP"; } else if(event==OC_EV_MS_NOT_PRIMARY) { return "NOT PRIMARY"; } else if(event==OC_EV_MS_PRIMARY_RESTORED) { return "PRIMARY RESTORED"; } else if(event==OC_EV_MS_EVICTED) { return "EVICTED"; } else if(event==OC_EV_MS_INVALID) { return "INVALID"; } return "NO QUORUM MEMBERSHIP"; } const char * op_status2text(op_status_t status) { switch(status) { case LRM_OP_PENDING: return "pending"; break; case LRM_OP_DONE: return "complete"; break; case LRM_OP_ERROR: return "ERROR"; break; case LRM_OP_TIMEOUT: return "TIMED OUT"; break; case LRM_OP_NOTSUPPORTED: return "NOT SUPPORTED"; break; case LRM_OP_CANCELLED: return "cancelled"; break; } CRM_DEV_ASSERT(status >= LRM_OP_PENDING && status <= LRM_OP_CANCELLED); crm_err("Unknown status: %d", status); return "UNKNOWN!"; } char * generate_op_key(const char *rsc_id, const char *op_type, int interval) { int len = 35; char *op_id = NULL; CRM_DEV_ASSERT(rsc_id != NULL); if(crm_assert_failed) { return NULL; } CRM_DEV_ASSERT(op_type != NULL); if(crm_assert_failed) { return NULL; } len += strlen(op_type); len += strlen(rsc_id); crm_malloc0(op_id, sizeof(char)*len); if(op_id != NULL) { sprintf(op_id, "%s_%s_%d", rsc_id, op_type, interval); } return op_id; } char * generate_notify_key(const char *rsc_id, const char *notify_type, const char *op_type) { int len = 12; char *op_id = NULL; CRM_DEV_ASSERT(rsc_id != NULL); if(crm_assert_failed) { return NULL; } CRM_DEV_ASSERT(op_type != NULL); if(crm_assert_failed) { return NULL; } CRM_DEV_ASSERT(notify_type != NULL); if(crm_assert_failed) { return NULL; } len += strlen(op_type); len += strlen(rsc_id); len += strlen(notify_type); crm_malloc0(op_id, sizeof(char)*len); if(op_id != NULL) { sprintf(op_id, "%s_%s_notify_%s_0", rsc_id, notify_type, op_type); } return op_id; } char * generate_transition_magic(const char *transition_key, int op_status) { int len = 40; char *fail_state = NULL; CRM_DEV_ASSERT(transition_key != NULL); if(crm_assert_failed) { return NULL; } len += strlen(transition_key); crm_malloc0(fail_state, sizeof(char)*len); if(fail_state != NULL) { snprintf(fail_state, len, "%d:%s", op_status, transition_key); } return fail_state; } gboolean decode_transition_magic( const char *magic, char **uuid, int *transition_id, int *op_status) { char *key = NULL; char *status = NULL; if(decodeNVpair(magic, ':', &status, &key) == FALSE) { return FALSE; } if(decode_transition_key(key, uuid, transition_id) == FALSE) { return FALSE; } *op_status = atoi(status); crm_free(key); crm_free(status); return TRUE; } char * generate_transition_key(int transition_id, const char *node) { int len = 40; char *fail_state = NULL; CRM_DEV_ASSERT(node != NULL); if(crm_assert_failed) { return NULL; } len += strlen(node); crm_malloc0(fail_state, sizeof(char)*len); if(fail_state != NULL) { snprintf(fail_state, len, "%d:%s", transition_id, node); } return fail_state; } gboolean decode_transition_key(const char *key, char **uuid, int *transition_id) { char *transition = NULL; if(decodeNVpair(key, ':', &transition, uuid) == FALSE) { return FALSE; } *transition_id = atoi(transition); crm_free(transition); return TRUE; } gboolean crm_mem_stats(volatile cl_mem_stats_t *mem_stats) { volatile cl_mem_stats_t *active_stats = mem_stats; if(active_stats == NULL) { active_stats = cl_malloc_getstats(); } CRM_DEV_ASSERT(active_stats != NULL); #ifndef CRM_USE_MALLOC if(active_stats->numalloc > active_stats->numfree) { crm_err("Potential memory leak detected:" " %lu alloc's vs. %lu free's (%lu)" " (%lu bytes not freed: req=%lu, alloc'd=%lu)", active_stats->numalloc, active_stats->numfree, active_stats->numalloc - active_stats->numfree, active_stats->nbytes_alloc, active_stats->nbytes_req, active_stats->mallocbytes); return TRUE; } else if(active_stats->numalloc < active_stats->numfree) { crm_debug("Process shrank: %lu alloc's vs. %lu free's (%lu)", active_stats->numalloc, active_stats->numfree, active_stats->numalloc - active_stats->numfree); } #endif return FALSE; } void crm_zero_mem_stats(volatile cl_mem_stats_t *stats) { volatile cl_mem_stats_t *active_stats = NULL; if(stats != NULL) { cl_malloc_setstats(stats); } active_stats = cl_malloc_getstats(); active_stats->numalloc = 0; active_stats->numfree = 0; active_stats->numrealloc = 0; active_stats->nbytes_req = 0; active_stats->nbytes_alloc = 0; active_stats->mallocbytes = 0; active_stats->arena = 0; } -