Mercurial > pidgin
comparison libpurple/util.c @ 21613:31101e7d275f
'man 3 ctime' says of localtime() (and friends):
"The return value points to a statically allocated struct which might be
overwritten by subsequent calls to any of the date and time functions.
The localtime_r() function does the same, but stores the data in a
user-supplied struct."
purple_str_to_time() had multiple calls to date and time functions,
although I didn't experience any problems in my testing I figured it would
be better to use localtime_r() and provide our own struct.
I hope I got this right. At least 'make check' still works :)
author | Stu Tomlinson <stu@nosnilmot.com> |
---|---|
date | Thu, 22 Nov 2007 16:45:38 +0000 |
parents | 18fb032a602a |
children | b2aa68cdc8b9 |
comparison
equal
deleted
inserted
replaced
21612:18fb032a602a | 21613:31101e7d275f |
---|---|
751 time_t | 751 time_t |
752 purple_str_to_time(const char *timestamp, gboolean utc, | 752 purple_str_to_time(const char *timestamp, gboolean utc, |
753 struct tm *tm, long *tz_off, const char **rest) | 753 struct tm *tm, long *tz_off, const char **rest) |
754 { | 754 { |
755 time_t retval = 0; | 755 time_t retval = 0; |
756 struct tm *t; | 756 static struct tm t; |
757 const char *c = timestamp; | 757 const char *c = timestamp; |
758 int year = 0; | 758 int year = 0; |
759 long tzoff = PURPLE_NO_TZ_OFF; | 759 long tzoff = PURPLE_NO_TZ_OFF; |
760 | 760 |
761 time(&retval); | 761 time(&retval); |
762 t = localtime(&retval); | 762 localtime_r(&retval, &t); |
763 | 763 |
764 /* 4 digit year */ | 764 /* 4 digit year */ |
765 if (sscanf(c, "%04d", &year) && year > 1900) | 765 if (sscanf(c, "%04d", &year) && year > 1900) |
766 { | 766 { |
767 c += 4; | 767 c += 4; |
768 if (*c == '-') | 768 if (*c == '-') |
769 c++; | 769 c++; |
770 t->tm_year = year - 1900; | 770 t.tm_year = year - 1900; |
771 } | 771 } |
772 | 772 |
773 /* 2 digit month */ | 773 /* 2 digit month */ |
774 if (!sscanf(c, "%02d", &t->tm_mon)) | 774 if (!sscanf(c, "%02d", &t.tm_mon)) |
775 { | 775 { |
776 if (rest != NULL && *c != '\0') | 776 if (rest != NULL && *c != '\0') |
777 *rest = c; | 777 *rest = c; |
778 return 0; | 778 return 0; |
779 } | 779 } |
780 c += 2; | 780 c += 2; |
781 if (*c == '-' || *c == '/') | 781 if (*c == '-' || *c == '/') |
782 c++; | 782 c++; |
783 t->tm_mon -= 1; | 783 t.tm_mon -= 1; |
784 | 784 |
785 /* 2 digit day */ | 785 /* 2 digit day */ |
786 if (!sscanf(c, "%02d", &t->tm_mday)) | 786 if (!sscanf(c, "%02d", &t.tm_mday)) |
787 { | 787 { |
788 if (rest != NULL && *c != '\0') | 788 if (rest != NULL && *c != '\0') |
789 *rest = c; | 789 *rest = c; |
790 return 0; | 790 return 0; |
791 } | 791 } |
792 c += 2; | 792 c += 2; |
793 if (*c == '/') | 793 if (*c == '/') |
794 { | 794 { |
795 c++; | 795 c++; |
796 | 796 |
797 if (!sscanf(c, "%04d", &t->tm_year)) | 797 if (!sscanf(c, "%04d", &t.tm_year)) |
798 { | 798 { |
799 if (rest != NULL && *c != '\0') | 799 if (rest != NULL && *c != '\0') |
800 *rest = c; | 800 *rest = c; |
801 return 0; | 801 return 0; |
802 } | 802 } |
803 t->tm_year -= 1900; | 803 t.tm_year -= 1900; |
804 } | 804 } |
805 else if (*c == 'T' || *c == '.') | 805 else if (*c == 'T' || *c == '.') |
806 { | 806 { |
807 c++; | 807 c++; |
808 /* we have more than a date, keep going */ | 808 /* we have more than a date, keep going */ |
809 | 809 |
810 /* 2 digit hour */ | 810 /* 2 digit hour */ |
811 if ((sscanf(c, "%02d:%02d:%02d", &t->tm_hour, &t->tm_min, &t->tm_sec) == 3 && (c = c + 8)) || | 811 if ((sscanf(c, "%02d:%02d:%02d", &t.tm_hour, &t.tm_min, &t.tm_sec) == 3 && (c = c + 8)) || |
812 (sscanf(c, "%02d%02d%02d", &t->tm_hour, &t->tm_min, &t->tm_sec) == 3 && (c = c + 6))) | 812 (sscanf(c, "%02d%02d%02d", &t.tm_hour, &t.tm_min, &t.tm_sec) == 3 && (c = c + 6))) |
813 { | 813 { |
814 gboolean offset_positive = FALSE; | 814 gboolean offset_positive = FALSE; |
815 int tzhrs; | 815 int tzhrs; |
816 int tzmins; | 816 int tzmins; |
817 | 817 |
818 t->tm_isdst = -1; | 818 t.tm_isdst = -1; |
819 | 819 |
820 if (*c == '.') { | 820 if (*c == '.') { |
821 do { | 821 do { |
822 c++; | 822 c++; |
823 } while (*c >= '0' && *c <= '9'); /* dealing with precision we don't care about */ | 823 } while (*c >= '0' && *c <= '9'); /* dealing with precision we don't care about */ |
831 tzoff = tzhrs*60*60 + tzmins*60; | 831 tzoff = tzhrs*60*60 + tzmins*60; |
832 if (offset_positive) | 832 if (offset_positive) |
833 tzoff *= -1; | 833 tzoff *= -1; |
834 /* We don't want the C library doing DST calculations | 834 /* We don't want the C library doing DST calculations |
835 * if we know the UTC offset already. */ | 835 * if we know the UTC offset already. */ |
836 t->tm_isdst = 0; | 836 t.tm_isdst = 0; |
837 } | 837 } |
838 else if (utc) | 838 else if (utc) |
839 { | 839 { |
840 struct tm *tmptm; | 840 static struct tm tmptm; |
841 time_t tmp; | 841 time_t tmp; |
842 tmp = mktime(t); | 842 tmp = mktime(&t); |
843 /* we care about whether it *was* dst, and the offset, here on this | 843 /* we care about whether it *was* dst, and the offset, here on this |
844 * date, not whether we are currently observing dst locally *now*. | 844 * date, not whether we are currently observing dst locally *now*. |
845 * This isn't perfect, because we would need to know in advance the | 845 * This isn't perfect, because we would need to know in advance the |
846 * offset we are trying to work out in advance to be sure this | 846 * offset we are trying to work out in advance to be sure this |
847 * works for times around dst transitions but it'll have to do. */ | 847 * works for times around dst transitions but it'll have to do. */ |
848 tmptm = localtime(&tmp); | 848 localtime_r(&tmp, &tmptm); |
849 t->tm_isdst = tmptm->tm_isdst; | 849 t.tm_isdst = tmptm.tm_isdst; |
850 #ifdef HAVE_TM_GMTOFF | 850 #ifdef HAVE_TM_GMTOFF |
851 t->tm_gmtoff = tmptm->tm_gmtoff; | 851 t.tm_gmtoff = tmptm.tm_gmtoff; |
852 #endif | 852 #endif |
853 } | 853 } |
854 | 854 |
855 if (rest != NULL && *c != '\0') | 855 if (rest != NULL && *c != '\0') |
856 { | 856 { |
876 tzoff = PURPLE_NO_TZ_OFF; | 876 tzoff = PURPLE_NO_TZ_OFF; |
877 else | 877 else |
878 tzoff += sys_tzoff; | 878 tzoff += sys_tzoff; |
879 #else | 879 #else |
880 #ifdef HAVE_TM_GMTOFF | 880 #ifdef HAVE_TM_GMTOFF |
881 tzoff += t->tm_gmtoff; | 881 tzoff += t.tm_gmtoff; |
882 #else | 882 #else |
883 # ifdef HAVE_TIMEZONE | 883 # ifdef HAVE_TIMEZONE |
884 tzset(); /* making sure */ | 884 tzset(); /* making sure */ |
885 tzoff -= timezone; | 885 tzoff -= timezone; |
886 # endif | 886 # endif |
895 } | 895 } |
896 } | 896 } |
897 | 897 |
898 if (tm != NULL) | 898 if (tm != NULL) |
899 { | 899 { |
900 *tm = *t; | 900 memcpy(tm, &t, sizeof(struct tm)); |
901 tm->tm_isdst = -1; | 901 tm->tm_isdst = -1; |
902 mktime(tm); | 902 mktime(tm); |
903 } | 903 } |
904 | 904 |
905 retval = mktime(t); | 905 retval = mktime(&t); |
906 if (tzoff != PURPLE_NO_TZ_OFF) | 906 if (tzoff != PURPLE_NO_TZ_OFF) |
907 retval += tzoff; | 907 retval += tzoff; |
908 | 908 |
909 if (tz_off != NULL) | 909 if (tz_off != NULL) |
910 *tz_off = tzoff; | 910 *tz_off = tzoff; |