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