00001
00006 #include "system.h"
00007
00008 #include "rpmbuild.h"
00009 #include "debug.h"
00010
00011 void addChangelogEntry(Header h, time_t time, const char *name, const char *text)
00012 {
00013 int_32 mytime = time;
00014 if (headerIsEntry(h, RPMTAG_CHANGELOGTIME)) {
00015 (void) headerAppendEntry(h, RPMTAG_CHANGELOGTIME, RPM_INT32_TYPE,
00016 &mytime, 1);
00017 (void) headerAppendEntry(h, RPMTAG_CHANGELOGNAME, RPM_STRING_ARRAY_TYPE,
00018 &name, 1);
00019 (void) headerAppendEntry(h, RPMTAG_CHANGELOGTEXT, RPM_STRING_ARRAY_TYPE,
00020 &text, 1);
00021 } else {
00022 (void) headerAddEntry(h, RPMTAG_CHANGELOGTIME, RPM_INT32_TYPE,
00023 &mytime, 1);
00024 (void) headerAddEntry(h, RPMTAG_CHANGELOGNAME, RPM_STRING_ARRAY_TYPE,
00025 &name, 1);
00026 (void) headerAddEntry(h, RPMTAG_CHANGELOGTEXT, RPM_STRING_ARRAY_TYPE,
00027 &text, 1);
00028 }
00029 }
00030
00037
00038 static int dateToTimet(const char * datestr, time_t * secs)
00039
00040 {
00041 struct tm time;
00042 char * p, * pe, * q, ** idx;
00043 char * date = strcpy(alloca(strlen(datestr) + 1), datestr);
00044 static char * days[] =
00045 { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL };
00046 static char * months[] =
00047 { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
00048 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL };
00049 static char lengths[] =
00050 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
00051
00052 memset(&time, 0, sizeof(time));
00053
00054 pe = date;
00055
00056
00057 p = pe; SKIPSPACE(p);
00058 if (*p == '\0') return -1;
00059 pe = p; SKIPNONSPACE(pe); if (*pe != '\0') *pe++ = '\0';
00060 for (idx = days; *idx && strcmp(*idx, p); idx++)
00061 {};
00062 if (*idx == NULL) return -1;
00063
00064
00065 p = pe; SKIPSPACE(p);
00066 if (*p == '\0') return -1;
00067 pe = p; SKIPNONSPACE(pe); if (*pe != '\0') *pe++ = '\0';
00068 for (idx = months; *idx && strcmp(*idx, p); idx++)
00069 {};
00070 if (*idx == NULL) return -1;
00071 time.tm_mon = idx - months;
00072
00073
00074 p = pe; SKIPSPACE(p);
00075 if (*p == '\0') return -1;
00076 pe = p; SKIPNONSPACE(pe); if (*pe != '\0') *pe++ = '\0';
00077
00078
00079 time.tm_hour = 12;
00080
00081 time.tm_mday = strtol(p, &q, 10);
00082 if (!(q && *q == '\0')) return -1;
00083 if (time.tm_mday < 0 || time.tm_mday > lengths[time.tm_mon]) return -1;
00084
00085
00086 p = pe; SKIPSPACE(p);
00087 if (*p == '\0') return -1;
00088 pe = p; SKIPNONSPACE(pe); if (*pe != '\0') *pe++ = '\0';
00089 time.tm_year = strtol(p, &q, 10);
00090 if (!(q && *q == '\0')) return -1;
00091 if (time.tm_year < 1990 || time.tm_year >= 3000) return -1;
00092 time.tm_year -= 1900;
00093
00094 *secs = mktime(&time);
00095 if (*secs == -1) return -1;
00096
00097
00098 *secs += timezone;
00099
00100 return 0;
00101 }
00102
00103
00110
00111 static int addChangelog(Header h, StringBuf sb)
00112
00113 {
00114 char *s;
00115 int i;
00116 time_t time;
00117 time_t lastTime = 0;
00118 char *date, *name, *text, *next;
00119
00120 s = getStringBuf(sb);
00121
00122
00123 SKIPSPACE(s);
00124
00125 while (*s != '\0') {
00126 if (*s != '*') {
00127 rpmError(RPMERR_BADSPEC,
00128 _("%%changelog entries must start with *\n"));
00129 return RPMERR_BADSPEC;
00130 }
00131
00132
00133 date = s;
00134 while(*s && *s != '\n') s++;
00135 if (! *s) {
00136 rpmError(RPMERR_BADSPEC, _("incomplete %%changelog entry\n"));
00137 return RPMERR_BADSPEC;
00138 }
00139
00140 *s = '\0';
00141
00142 text = s + 1;
00143
00144
00145 date++;
00146 s = date;
00147 for (i = 0; i < 4; i++) {
00148 SKIPSPACE(s);
00149 SKIPNONSPACE(s);
00150 }
00151 SKIPSPACE(date);
00152 if (dateToTimet(date, &time)) {
00153 rpmError(RPMERR_BADSPEC, _("bad date in %%changelog: %s\n"), date);
00154 return RPMERR_BADSPEC;
00155 }
00156 if (lastTime && lastTime < time) {
00157 rpmError(RPMERR_BADSPEC,
00158 _("%%changelog not in descending chronological order\n"));
00159 return RPMERR_BADSPEC;
00160 }
00161 lastTime = time;
00162
00163
00164 SKIPSPACE(s);
00165 if (! *s) {
00166 rpmError(RPMERR_BADSPEC, _("missing name in %%changelog\n"));
00167 return RPMERR_BADSPEC;
00168 }
00169
00170
00171 name = s;
00172 while (*s != '\0') s++;
00173 while (s > name && xisspace(*s)) {
00174 *s-- = '\0';
00175 }
00176 if (s == name) {
00177 rpmError(RPMERR_BADSPEC, _("missing name in %%changelog\n"));
00178 return RPMERR_BADSPEC;
00179 }
00180
00181
00182 SKIPSPACE(text);
00183 if (! *text) {
00184 rpmError(RPMERR_BADSPEC, _("no description in %%changelog\n"));
00185 return RPMERR_BADSPEC;
00186 }
00187
00188
00189 s = text;
00190 do {
00191 s++;
00192 } while (*s && (*(s-1) != '\n' || *s != '*'));
00193 next = s;
00194 s--;
00195
00196
00197 while ((s > text) && xisspace(*s)) {
00198 *s-- = '\0';
00199 }
00200
00201 addChangelogEntry(h, time, name, text);
00202 s = next;
00203 }
00204
00205 return 0;
00206 }
00207
00208
00209 int parseChangelog(Spec spec)
00210 {
00211 int nextPart, res, rc;
00212 StringBuf sb = newStringBuf();
00213
00214
00215 if ((rc = readLine(spec, STRIP_COMMENTS)) > 0) {
00216 sb = freeStringBuf(sb);
00217 return PART_NONE;
00218 }
00219 if (rc)
00220 return rc;
00221
00222 while (! (nextPart = isPart(spec->line))) {
00223 appendStringBuf(sb, spec->line);
00224 if ((rc = readLine(spec, STRIP_COMMENTS)) > 0) {
00225 nextPart = PART_NONE;
00226 break;
00227 }
00228 if (rc)
00229 return rc;
00230 }
00231
00232 res = addChangelog(spec->packages->header, sb);
00233 sb = freeStringBuf(sb);
00234
00235 return (res) ? res : nextPart;
00236 }