1/*- 2 * Copyright (c) 2012 Dag-Erling Smørgrav 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote 14 * products derived from this software without specific prior written 15 * permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $Id: t_file.c 648 2013-03-05 17:54:27Z des $ 30 */ 31 32#ifdef HAVE_CONFIG_H 33# include "config.h" 34#endif 35 36#include <err.h> 37#include <errno.h> 38#include <fcntl.h> 39#include <stdarg.h> 40#include <stdio.h> 41#include <stdlib.h> 42#include <string.h> 43#include <unistd.h> 44 45#include "openpam_asprintf.h" 46 47#include "t.h" 48 49static struct t_file *tflist; 50 51/* 52 * Open a temp file. 53 */ 54struct t_file * 55t_fopen(const char *filename) 56{ 57 struct t_file *tf; 58 int fd; 59 60 if ((tf = calloc(sizeof *tf, 1)) == NULL) 61 err(1, "%s(): calloc()", __func__); 62 if (filename) { 63 if ((tf->name = strdup(filename)) == NULL) 64 err(1, "%s(): strdup()", __func__); 65 } else { 66 asprintf(&tf->name, "%s.%lu.%p.tmp", 67 t_progname, (unsigned long)getpid(), (void *)tf); 68 if (tf->name == NULL) 69 err(1, "%s(): asprintf()", __func__); 70 } 71 if ((fd = open(tf->name, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0) 72 err(1, "%s(): %s", __func__, tf->name); 73 if ((tf->file = fdopen(fd, "r+")) == NULL) 74 err(1, "%s(): fdopen()", __func__); 75 if ((tf->next = tflist) != NULL) 76 tf->next->prev = tf; 77 tflist = tf; 78 return (tf); 79} 80 81/* 82 * Write text to the temp file. 83 */ 84int 85t_fprintf(struct t_file *tf, const char *fmt, ...) 86{ 87 va_list ap; 88 int len; 89 90 va_start(ap, fmt); 91 len = vfprintf(tf->file, fmt, ap); 92 va_end(ap); 93 if (ferror(tf->file)) 94 err(1, "%s(): vfprintf()", __func__); 95 return (len); 96} 97 98/* 99 * Rewind the temp file. 100 */ 101void 102t_frewind(struct t_file *tf) 103{ 104 105 errno = 0; 106 rewind(tf->file); 107 if (errno != 0) 108 err(1, "%s(): rewind()", __func__); 109} 110 111/* 112 * Return non-zero if an error occurred. 113 */ 114int 115t_ferror(struct t_file *tf) 116{ 117 118 return (ferror(tf->file)); 119} 120 121/* 122 * Return non-zero if the end of the file was reached. 123 */ 124int 125t_feof(struct t_file *tf) 126{ 127 128 return (feof(tf->file)); 129} 130 131/* 132 * Close a temp file. 133 */ 134void 135t_fclose(struct t_file *tf) 136{ 137 138 if (tf == tflist) 139 tflist = tf->next; 140 if (tf->prev) 141 tf->prev->next = tf->next; 142 if (tf->next) 143 tf->next->prev = tf->prev; 144 fclose(tf->file); 145 if (unlink(tf->name) < 0) 146 warn("%s(): unlink()", __func__); 147 free(tf->name); 148 free(tf); 149} 150 151/* 152 * atexit() function to close all remaining files. 153 */ 154void 155t_fcloseall(void) 156{ 157 158 while (tflist) 159 t_fclose(tflist); 160} 161