3 * $Id: sw_info.c,v 1.1 1999/06/02 16:53:35 mdw Exp $
5 * Maintenance of `.sw-info' files
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of sw-tools.
14 * sw-tools is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * sw-tools is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with sw-tools; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 /*----- Revision history --------------------------------------------------*
32 * Revision 1.1 1999/06/02 16:53:35 mdw
37 /*----- Header files ------------------------------------------------------*/
49 #include <sys/types.h>
53 #include <mLib/alloc.h>
54 #include <mLib/dstr.h>
55 #include <mLib/lock.h>
56 #include <mLib/quis.h>
57 #include <mLib/report.h>
62 /*----- Static variables --------------------------------------------------*/
64 static struct swfield {
69 { "package", offsetof(swinfo, package), "Package" },
70 { "version", offsetof(swinfo, version), "Version" },
71 { "maintainer", offsetof(swinfo, maintainer), "Maintained by" },
72 { "date", offsetof(swinfo, date), "Last modified" },
73 { "only-arch", offsetof(swinfo, only_arch), "Only build for" },
74 { "arch", offsetof(swinfo, arch), "Successfully built" },
77 typedef struct swfield swfield;
79 #define SWINFO(sw, off) (*(char **)((char *)sw + off))
81 /*----- Main code ---------------------------------------------------------*/
83 /* --- @swinfo_clear@ --- *
85 * Arguments: @swinfo *sw@ = pointe to info block
89 * Use: Clears an info block so that it doesn't contain anything.
90 * This is mainly useful when building skeletons to apply using
94 void swinfo_clear(swinfo *sw)
97 for (f = swfields; f->name; f++)
98 SWINFO(sw, f->off) = 0;
101 /* --- @swinfo_fetch@ --- *
103 * Arguments: @swinfo *sw@ = pointer to info block to fill in
105 * Returns: Zero if OK, else nonzero.
107 * Use: Fills in the info block if it can.
110 int swinfo_fetch(swinfo *sw)
117 /* --- Initialize the various fields --- */
121 /* --- Open the data file --- */
123 if ((fp = fopen(".sw-info", "r")) == 0)
126 /* --- Read the lines from the file --- */
128 for (; dstr_putline(&d, fp) != EOF; DRESET(&d)) {
133 /* --- Find the field name --- */
135 while (isspace((unsigned char)*p))
137 if (*p == 0 || *p == '#')
140 /* --- Find the end of the field name --- */
143 while (*p && *p != '=' && !isspace((unsigned char)*p))
146 /* --- Skip an optional `=' sign --- */
152 while (isspace((unsigned char)*p))
154 if (*p == '=' && ch != '=') {
156 while (isspace((unsigned char)*p))
163 /* --- Look up the key in the table --- */
165 for (f = swfields; f->name; f++) {
166 if (strcmp(key, f->name) == 0)
169 moan("unknown key `%s' at line %i in `.sw-info'", key, line);
172 /* --- Put the value in --- */
175 SWINFO(sw, f->off) = xstrdup(value);
183 /* --- @swinfo_sanity@ --- *
185 * Arguments: @swinfo *sw@ = pointer to an info block
187 * Returns: Yes, if the block is OK.
189 * Use: Objects if the information in the info block is bad.
192 void swinfo_sanity(swinfo *sw)
195 die(1, "unknown package name. Try `%s setup PACKAGE VERSION'.", QUIS);
197 die(1, "unknown package version. Try `%s setup PACKAGE VERSION'.",
200 die(1, "unknown maintainer. Try `%s setup PACKAGE VERSION'.", QUIS);
202 die(1, "unknown date. Try `%s setup PACKAGE VERSION'.", QUIS);
205 /* --- @swinfo_put@ --- *
207 * Arguments: @swinfo *sw@ = pointer to an info block
209 * Returns: Zero if it worked, nonzero if not.
211 * Use: Writes an info block to the appropriate file.
214 int swinfo_put(swinfo *sw)
220 /* --- Quick sanity check --- */
224 /* --- Write the new data out --- */
226 if ((fp = fopen(".sw-info.new", "w")) == 0)
228 for (f = swfields; f->name; f++) {
229 if (!SWINFO(sw, f->off))
231 if (fprintf(fp, "%s = %s\n", f->name, SWINFO(sw, f->off)) == EOF) {
237 if (fclose(fp) == EOF) {
242 /* --- Carefully! replace the old one --- *
244 * Keep an old one around just in case, unless the renames fail because
248 remove(".sw-info.older"); /* Don't care if this fails */
249 if (rename(".sw-info.old", ".sw-info.older") && errno != ENOENT)
250 { e = errno; goto tidy_0; }
251 if (rename(".sw-info", ".sw-info.old") && errno != ENOENT)
252 { e = errno; goto tidy_1; }
253 if (rename(".sw-info.new", ".sw-info"))
254 { e = errno; goto tidy_2; }
255 remove(".sw-info.older"); /* Don't care if this fails */
258 /* --- Tidy up if anything went tits-up --- */
261 rename(".sw-info.old", ".sw-info");
263 rename(".sw-info.older", ".sw-info.old");
265 remove(".sw-info.new");
270 /* --- @swinfo_destroy@ --- *
272 * Arguments: @swinfo *sw@ = pointer to info block
276 * Use: Destroys an info block when it's not useful any more.
279 void swinfo_destroy(swinfo *sw)
283 for (f = swfields; f->name; f++) {
284 if (SWINFO(sw, f->off))
285 free(SWINFO(sw, f->off));
289 /* --- @swinfo_update@ --- *
291 * Arguments: @swinfo *sw@ = pointer to info block
292 * @swinfo *skel@ = pointer to skeleton values
296 * Use: Updates the fields in an information block, except for the
297 * architecture names stuff. (I'll leave that for later,
298 * because it's rather more involved.
301 void swinfo_update(swinfo *sw, swinfo *skel)
307 /* --- Set up a default maintainer --- */
309 if (!skel->maintainer && !sw->maintainer) {
310 char *u = getenv("USER");
313 u = getenv("LOGNAME");
315 struct passwd *pw = getpwuid(getuid());
317 moan("you don't seem to exist");
318 sprintf(ubuf, "uid %i", (int)getuid());
323 skel->maintainer = u;
326 /* --- Set up a default date --- */
330 struct tm *tm = localtime(&t);
331 strftime(dbuf, sizeof(dbuf), "%Y-%m-%d", tm);
335 /* --- Set a default architecture list --- */
337 if (!skel->arch && !sw->arch)
340 /* --- Grind through all the fields --- */
342 for (f = swfields; f->name; f++) {
343 if (!SWINFO(skel, f->off) || strcmp(SWINFO(skel, f->off), "-") == 0)
345 if (SWINFO(sw, f->off))
346 free(SWINFO(sw, f->off));
347 SWINFO(sw, f->off) = xstrdup(SWINFO(skel, f->off));
351 /*----- Subcommands -------------------------------------------------------*/
353 /* --- @sw_setup@ --- */
355 int sw_setup(int argc, char *argv[])
358 if (argc < 3 || argc > 4)
359 die(1, "Usage: setup PACKAGE VERSION [MAINTAINER]");
362 skel.package = argv[1];
363 skel.version = argv[2];
365 skel.maintainer = argv[3];
366 swinfo_update(&sw, &skel);
371 /* --- @sw_status@ --- */
373 int sw_status(int argc, char *argv[])
377 if (swinfo_fetch(&sw)) {
378 die(1, "couldn't read build status: %s (try running setup)",
381 for (f = swfields; f->name; f++) {
382 if (SWINFO(&sw, f->off))
383 printf("%s: %s\n", f->desc, SWINFO(&sw, f->off));
388 /* --- @sw_commit@ --- */
390 int sw_commit(int argc, char *argv[])
395 die(1, "Usage: commit");
396 if (swinfo_fetch(&sw)) {
397 die(1, "couldn't read build status: %s (try running setup)",
401 /* --- Make sure everything has been built properly --- */
405 archcons *all = arch_readtab();
408 for (a = aa = arch_filter(all, sw.arch, 0, 0); a; a = a->cdr)
409 a->car->flags |= archFlag_built;
413 aa = arch_filter(all, sw.only_arch, archFlag_built, 0);
416 fprintf(stderr, "%s: not built for", QUIS);
417 for (a = aa; a; a = a->cdr) {
418 fprintf(stderr, "%s%s", sep, a->car->arch);
427 /* --- Write to the index file --- */
430 FILE *fp = fopen(PREFIX "/sw-index", "a");
435 die(1, "couldn't open index file: %s", strerror(errno));
436 if (lock_file(fileno(fp), LOCK_EXCL))
437 die(1, "couldn't obtain lock on index file: %s", strerror(errno));
439 for (f = swfields; f->name; f++) {
440 if (SWINFO(&sw, f->off)) {
441 fprintf(fp, "%s%s = %s", sep, f->name, SWINFO(&sw, f->off));
452 /*----- That's all, folks -------------------------------------------------*/