/* * XML Catalog Manager (xmlcatmgr) * $Id: generic.c,v 1.1 2004/08/31 19:07:23 jmmv Exp $ * * Copyright (c) 2003, 2004 Julio M. Merino Vidal. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name of the author nor the names of contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Functions in this file are called directly from main, based on the * action given in the command line. They issue tasks that are common * to both XML and SGML modes, and the proceed to execute the specific * mode action based on function pointers. */ #include "system.h" #ifndef lint __RCSID("$Id: generic.c,v 1.1 2004/08/31 19:07:23 jmmv Exp $"); #endif #include "generic.h" #include "mem.h" /* --------------------------------------------------------------------- */ /* * Common tasks to the add action: open the catalog file for read and * write, lock it and execute the specific function depending on the * mode. */ bool generic_add(int argc, char *const *argv, const char *catname, bool (*func)(int, char *const *, FILE *, bool), bool prepend) { bool res; FILE *f; assert(argv != NULL && catname != NULL && func != NULL); f = fopen(catname, "r+"); if (f == NULL) { warn("failed to open `%s'", catname); res = false; } else { (void)lockf(fileno(f), F_LOCK, 0); res = func(argc, argv, f, prepend); (void)lockf(fileno(f), F_ULOCK, 0); fclose(f); } return res; } /* --------------------------------------------------------------------- */ /* * Common tasks to the create action: create the catalog file, wait for * a lock and initialize it with the respective mode function. * Obtaining the lock is tricky, because open(2) can't do it atomically * in a standard way. */ bool generic_create(const char *catname, bool (*func)(FILE *)) { bool res; int fd; assert(catname != NULL && func != NULL); res = false; fd = open(catname, O_WRONLY | O_CREAT | O_EXCL, 0644); if (fd == -1) { warn("failed to create `%s'", catname); } else { FILE *f; f = fdopen(fd, "a"); if (f == NULL) { warn("failed to create `%s'", catname); close(fd); } else { (void)lockf(fileno(f), F_LOCK, 0); fseek(f, 0, SEEK_END); if (ftell(f) != 0L) { warnx("failed to create `%s': modified by another process", catname); } else { res = func(f); if (!res) warn("failed to initialize `%s'", catname); } (void)lockf(fileno(f), F_ULOCK, 0); fclose(f); if (!res) (void)generic_destroy(catname); } } return res; } /* --------------------------------------------------------------------- */ /* * Destroy action: remove the catalog file. Catalog modes do not have * to do anything special. */ bool generic_destroy(const char *catname) { bool res; assert(catname != NULL); res = unlink(catname) == -1 ? false : true; if (!res) warn("failed to destroy `%s'", catname); return res; } /* --------------------------------------------------------------------- */ /* * Common tasks to the lookup action: open the catalog for read and call * the respective mode function. */ bool generic_lookup(int argc, char *const *argv, const char *catname, bool (*func)(int, char *const *, FILE *)) { bool res; FILE *f; assert(argv != NULL && catname != NULL && func != NULL); if (argc == 0) { warnx("too few arguments for `lookup' action"); res = false; } else { f = fopen(catname, "r"); if (f == NULL) { warn("failed to open `%s'", catname); res = false; } else { res = func(argc, argv, f); fclose(f); } } return res; } /* --------------------------------------------------------------------- */ /* * Common tasks to the remove action: open the catalog file for read and * write, lock it and execute the specific function depending on the * mode. */ bool generic_remove(int argc, char *const *argv, const char *catname, bool (*func)(int, char *const *, FILE *)) { bool res; FILE *f; assert(argv != NULL && catname != NULL && func != NULL); f = fopen(catname, "r+"); if (f == NULL) { warn("failed to open `%s'", catname); res = false; } else { (void)lockf(fileno(f), F_LOCK, 0); res = func(argc, argv, f); (void)lockf(fileno(f), F_ULOCK, 0); fclose(f); } return res; } /* * Local Variables: *** * mode: c *** * c-file-style: "stroustrup" *** * End: *** * vim: syntax=c:expandtab:shiftwidth=4:softtabstop=4 */