1255365Sdes/*- 2255365Sdes * Copyright (c) 2012 Dag-Erling Sm��rgrav 3255365Sdes * All rights reserved. 4255365Sdes * 5255365Sdes * Redistribution and use in source and binary forms, with or without 6255365Sdes * modification, are permitted provided that the following conditions 7255365Sdes * are met: 8255365Sdes * 1. Redistributions of source code must retain the above copyright 9255365Sdes * notice, this list of conditions and the following disclaimer. 10255365Sdes * 2. Redistributions in binary form must reproduce the above copyright 11255365Sdes * notice, this list of conditions and the following disclaimer in the 12255365Sdes * documentation and/or other materials provided with the distribution. 13255365Sdes * 3. The name of the author may not be used to endorse or promote 14255365Sdes * products derived from this software without specific prior written 15255365Sdes * permission. 16255365Sdes * 17255365Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18255365Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19255365Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20255365Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21255365Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22255365Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23255365Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24255365Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25255365Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26255365Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27255365Sdes * SUCH DAMAGE. 28255365Sdes * 29255365Sdes * $Id: t_file.c 648 2013-03-05 17:54:27Z des $ 30255365Sdes */ 31255365Sdes 32255365Sdes#ifdef HAVE_CONFIG_H 33255365Sdes# include "config.h" 34255365Sdes#endif 35255365Sdes 36255365Sdes#include <err.h> 37255365Sdes#include <errno.h> 38255365Sdes#include <fcntl.h> 39255365Sdes#include <stdarg.h> 40255365Sdes#include <stdio.h> 41255365Sdes#include <stdlib.h> 42255365Sdes#include <string.h> 43255365Sdes#include <unistd.h> 44255365Sdes 45255365Sdes#include "openpam_asprintf.h" 46255365Sdes 47255365Sdes#include "t.h" 48255365Sdes 49255365Sdesstatic struct t_file *tflist; 50255365Sdes 51255365Sdes/* 52255365Sdes * Open a temp file. 53255365Sdes */ 54255365Sdesstruct t_file * 55255365Sdest_fopen(const char *filename) 56255365Sdes{ 57255365Sdes struct t_file *tf; 58255365Sdes int fd; 59255365Sdes 60255365Sdes if ((tf = calloc(sizeof *tf, 1)) == NULL) 61255365Sdes err(1, "%s(): calloc()", __func__); 62255365Sdes if (filename) { 63255365Sdes if ((tf->name = strdup(filename)) == NULL) 64255365Sdes err(1, "%s(): strdup()", __func__); 65255365Sdes } else { 66255365Sdes asprintf(&tf->name, "%s.%lu.%p.tmp", 67255365Sdes t_progname, (unsigned long)getpid(), (void *)tf); 68255365Sdes if (tf->name == NULL) 69255365Sdes err(1, "%s(): asprintf()", __func__); 70255365Sdes } 71255365Sdes if ((fd = open(tf->name, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0) 72255365Sdes err(1, "%s(): %s", __func__, tf->name); 73255365Sdes if ((tf->file = fdopen(fd, "r+")) == NULL) 74255365Sdes err(1, "%s(): fdopen()", __func__); 75255365Sdes if ((tf->next = tflist) != NULL) 76255365Sdes tf->next->prev = tf; 77255365Sdes tflist = tf; 78255365Sdes return (tf); 79255365Sdes} 80255365Sdes 81255365Sdes/* 82255365Sdes * Write text to the temp file. 83255365Sdes */ 84255365Sdesint 85255365Sdest_fprintf(struct t_file *tf, const char *fmt, ...) 86255365Sdes{ 87255365Sdes va_list ap; 88255365Sdes int len; 89255365Sdes 90255365Sdes va_start(ap, fmt); 91255365Sdes len = vfprintf(tf->file, fmt, ap); 92255365Sdes va_end(ap); 93255365Sdes if (ferror(tf->file)) 94255365Sdes err(1, "%s(): vfprintf()", __func__); 95255365Sdes return (len); 96255365Sdes} 97255365Sdes 98255365Sdes/* 99255365Sdes * Rewind the temp file. 100255365Sdes */ 101255365Sdesvoid 102255365Sdest_frewind(struct t_file *tf) 103255365Sdes{ 104255365Sdes 105255365Sdes errno = 0; 106255365Sdes rewind(tf->file); 107255365Sdes if (errno != 0) 108255365Sdes err(1, "%s(): rewind()", __func__); 109255365Sdes} 110255365Sdes 111255365Sdes/* 112255365Sdes * Return non-zero if an error occurred. 113255365Sdes */ 114255365Sdesint 115255365Sdest_ferror(struct t_file *tf) 116255365Sdes{ 117255365Sdes 118255365Sdes return (ferror(tf->file)); 119255365Sdes} 120255365Sdes 121255365Sdes/* 122255365Sdes * Return non-zero if the end of the file was reached. 123255365Sdes */ 124255365Sdesint 125255365Sdest_feof(struct t_file *tf) 126255365Sdes{ 127255365Sdes 128255365Sdes return (feof(tf->file)); 129255365Sdes} 130255365Sdes 131255365Sdes/* 132255365Sdes * Close a temp file. 133255365Sdes */ 134255365Sdesvoid 135255365Sdest_fclose(struct t_file *tf) 136255365Sdes{ 137255365Sdes 138255365Sdes if (tf == tflist) 139255365Sdes tflist = tf->next; 140255365Sdes if (tf->prev) 141255365Sdes tf->prev->next = tf->next; 142255365Sdes if (tf->next) 143255365Sdes tf->next->prev = tf->prev; 144255365Sdes fclose(tf->file); 145255365Sdes if (unlink(tf->name) < 0) 146255365Sdes warn("%s(): unlink()", __func__); 147255365Sdes free(tf->name); 148255365Sdes free(tf); 149255365Sdes} 150255365Sdes 151255365Sdes/* 152255365Sdes * atexit() function to close all remaining files. 153255365Sdes */ 154255365Sdesvoid 155255365Sdest_fcloseall(void) 156255365Sdes{ 157255365Sdes 158255365Sdes while (tflist) 159255365Sdes t_fclose(tflist); 160255365Sdes} 161