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