195 lines
8.5 KiB
C
Executable File
195 lines
8.5 KiB
C
Executable File
/* Temporary directories and temporary files with automatic cleanup.
|
|
Copyright (C) 2006, 2011-2024 Free Software Foundation, Inc.
|
|
Written by Bruno Haible <bruno@clisp.org>, 2006.
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef _CLEAN_TEMP_H
|
|
#define _CLEAN_TEMP_H
|
|
|
|
/* This file uses _GL_ATTRIBUTE_DEALLOC. */
|
|
#if !_GL_CONFIG_H_INCLUDED
|
|
#error "Please include config.h first."
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
/* Temporary directories and temporary files should be automatically removed
|
|
when the program exits either normally or through a fatal signal. We can't
|
|
rely on the "unlink before close" idiom, because it works only on Unix and
|
|
also - if no signal blocking is used - leaves a time window where a fatal
|
|
signal would not clean up the temporary file.
|
|
|
|
Also, open file descriptors need to be closed before the temporary files
|
|
and the temporary directories can be removed, because only on Unix
|
|
(excluding Cygwin) can one remove directories containing open files.
|
|
|
|
There are two modules:
|
|
- 'clean-temp' provides support for temporary directories and temporary
|
|
files inside these temporary directories,
|
|
- 'clean-temp-simple' provides support for temporary files without
|
|
temporary directories.
|
|
The temporary directories and files are automatically cleaned up (at the
|
|
latest) when the program exits or dies from a fatal signal such as SIGINT,
|
|
SIGTERM, SIGHUP, but not if it dies from a fatal signal such as SIGQUIT,
|
|
SIGKILL, or SIGABRT, SIGSEGV, SIGBUS, SIGILL, SIGFPE.
|
|
|
|
For the cleanup in the normal case, programs that use this module need to
|
|
call 'cleanup_temp_dir' for each successful return of 'create_temp_dir'.
|
|
The cleanup in the case of a fatal signal such as SIGINT, SIGTERM, SIGHUP,
|
|
is done entirely automatically by the functions of this module.
|
|
|
|
Limitations: Files or directories can still be left over if
|
|
- the program is dies from a fatal signal such as SIGQUIT, SIGKILL, or
|
|
SIGABRT, SIGSEGV, SIGBUS, SIGILL, SIGFPE, or
|
|
- in a multithreaded program, the fatal signal handler is already running
|
|
while another thread of the program creates a new temporary directory
|
|
or temporary file, or
|
|
- on native Windows, some temporary files are used by a subprocess while
|
|
the fatal signal interrupts the program.
|
|
*/
|
|
|
|
|
|
/* ============= Temporary files without temporary directories ============= */
|
|
|
|
#include "clean-temp-simple.h"
|
|
|
|
/* ========= Temporary directories and temporary files inside them ========= */
|
|
|
|
struct temp_dir
|
|
{
|
|
/* The absolute pathname of the directory. */
|
|
const char * const dir_name;
|
|
/* Whether errors during explicit cleanup are reported to standard error. */
|
|
bool cleanup_verbose;
|
|
/* More fields are present here, but not public. */
|
|
};
|
|
|
|
/* Remove all registered files and subdirectories inside DIR and DIR itself.
|
|
DIR cannot be used any more after this call.
|
|
Return 0 upon success, or -1 if there was some problem. */
|
|
extern int cleanup_temp_dir (struct temp_dir *dir);
|
|
|
|
/* Create a temporary directory.
|
|
PREFIX is used as a prefix for the name of the temporary directory. It
|
|
should be short and still give an indication about the program.
|
|
PARENTDIR can be used to specify the parent directory; if NULL, a default
|
|
parent directory is used (either $TMPDIR or /tmp or similar).
|
|
CLEANUP_VERBOSE determines whether errors during explicit cleanup are
|
|
reported to standard error.
|
|
Return a fresh 'struct temp_dir' on success. Upon error, an error message
|
|
is shown and NULL is returned. */
|
|
extern struct temp_dir * create_temp_dir (const char *prefix,
|
|
const char *parentdir,
|
|
bool cleanup_verbose)
|
|
_GL_ATTRIBUTE_DEALLOC (cleanup_temp_dir, 1);
|
|
|
|
/* Register the given ABSOLUTE_FILE_NAME as being a file inside DIR, that
|
|
needs to be removed before DIR can be removed.
|
|
Should be called before the file ABSOLUTE_FILE_NAME is created. */
|
|
extern void register_temp_file (struct temp_dir *dir,
|
|
const char *absolute_file_name);
|
|
|
|
/* Unregister the given ABSOLUTE_FILE_NAME as being a file inside DIR, that
|
|
needs to be removed before DIR can be removed.
|
|
Should be called when the file ABSOLUTE_FILE_NAME could not be created. */
|
|
extern void unregister_temp_file (struct temp_dir *dir,
|
|
const char *absolute_file_name);
|
|
|
|
/* Register the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR,
|
|
that needs to be removed before DIR can be removed.
|
|
Should be called before the subdirectory ABSOLUTE_DIR_NAME is created. */
|
|
extern void register_temp_subdir (struct temp_dir *dir,
|
|
const char *absolute_dir_name);
|
|
|
|
/* Unregister the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR,
|
|
that needs to be removed before DIR can be removed.
|
|
Should be called when the subdirectory ABSOLUTE_DIR_NAME could not be
|
|
created. */
|
|
extern void unregister_temp_subdir (struct temp_dir *dir,
|
|
const char *absolute_dir_name);
|
|
|
|
/* Remove the given ABSOLUTE_FILE_NAME and unregister it.
|
|
Return 0 upon success, or -1 if there was some problem. */
|
|
extern int cleanup_temp_file (struct temp_dir *dir,
|
|
const char *absolute_file_name);
|
|
|
|
/* Remove the given ABSOLUTE_DIR_NAME and unregister it.
|
|
Return 0 upon success, or -1 if there was some problem. */
|
|
extern int cleanup_temp_subdir (struct temp_dir *dir,
|
|
const char *absolute_dir_name);
|
|
|
|
/* Remove all registered files and subdirectories inside DIR.
|
|
Return 0 upon success, or -1 if there was some problem. */
|
|
extern int cleanup_temp_dir_contents (struct temp_dir *dir);
|
|
|
|
/* ================== Opening and closing temporary files ================== */
|
|
|
|
/* Open a temporary file in a temporary directory.
|
|
FILE_NAME must already have been passed to register_temp_file.
|
|
Registers the resulting file descriptor to be closed.
|
|
DELETE_ON_CLOSE indicates whether the file can be deleted when the resulting
|
|
file descriptor or stream is closed. */
|
|
extern int open_temp (const char *file_name, int flags, mode_t mode,
|
|
bool delete_on_close);
|
|
extern FILE * fopen_temp (const char *file_name, const char *mode,
|
|
bool delete_on_close);
|
|
|
|
/* Open a temporary file, generating its name based on FILE_NAME_TMPL.
|
|
FILE_NAME_TMPL must match the rules for mk[s]temp (i.e. end in "XXXXXX",
|
|
possibly with a suffix). The name constructed does not exist at the time
|
|
of the call. FILE_NAME_TMPL is overwritten with the result.
|
|
A safe choice for MODE is S_IRUSR | S_IWUSR, a.k.a. 0600.
|
|
Registers the file for deletion.
|
|
Opens the file, with the given FLAGS and mode MODE.
|
|
Registers the resulting file descriptor to be closed. */
|
|
extern int gen_register_open_temp (char *file_name_tmpl, int suffixlen,
|
|
int flags, mode_t mode);
|
|
|
|
/* Close a temporary file.
|
|
FD must have been returned by open_temp or gen_register_open_temp.
|
|
Unregisters the previously registered file descriptor. */
|
|
extern int close_temp (int fd);
|
|
|
|
/* Close a temporary file.
|
|
FP must have been returned by fopen_temp, or by fdopen on a file descriptor
|
|
returned by open_temp or gen_register_open_temp.
|
|
Unregisters the previously registered file descriptor. */
|
|
extern int fclose_temp (FILE *fp);
|
|
|
|
/* Like fwriteerror.
|
|
FP must have been returned by fopen_temp, or by fdopen on a file descriptor
|
|
returned by open_temp or gen_register_open_temp.
|
|
Unregisters the previously registered file descriptor. */
|
|
extern int fwriteerror_temp (FILE *fp);
|
|
|
|
/* Like close_stream.
|
|
FP must have been returned by fopen_temp, or by fdopen on a file descriptor
|
|
returned by open_temp or gen_register_open_temp.
|
|
Unregisters the previously registered file descriptor. */
|
|
extern int close_stream_temp (FILE *fp);
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* _CLEAN_TEMP_H */
|