From 94f2dc6b4e525a23810e720c343957d5ad526ede Mon Sep 17 00:00:00 2001 From: giraffedata Date: Thu, 1 Jan 2015 20:08:53 +0000 Subject: On Windows, unlink temporary files via atexit git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@2358 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- lib/pmfileio.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 121 insertions(+), 8 deletions(-) (limited to 'lib/pmfileio.c') diff --git a/lib/pmfileio.c b/lib/pmfileio.c index b629fd23..a4533b56 100644 --- a/lib/pmfileio.c +++ b/lib/pmfileio.c @@ -306,17 +306,130 @@ pm_make_tmpfile(FILE ** const filePP, +bool const canUnlinkOpen = +#if CAN_UNLINK_OPEN + 1 +#else + 0 +#endif + ; + + + +typedef struct UnlinkListEntry { +/*---------------------------------------------------------------------------- + This is an entry in the linked list of files to close and unlink as the + program exits. +-----------------------------------------------------------------------------*/ + struct UnlinkListEntry * next; + int fd; + char fileName[1]; /* Actually variable length */ +} UnlinkListEntry; + +static UnlinkListEntry * unlinkListP; + + + +static void +unlinkTempFiles(void) { +/*---------------------------------------------------------------------------- + Close and unlink (so presumably delete) the files in the list + *unlinkListP. + + This is an atexit function. +-----------------------------------------------------------------------------*/ + while (unlinkListP) { + UnlinkListEntry * const firstEntryP = unlinkListP; + + unlinkListP = unlinkListP->next; + + close(firstEntryP->fd); + unlink(firstEntryP->fileName); + + free(firstEntryP); + } +} + + + +static UnlinkListEntry * +newUnlinkListEntry(const char * const fileName, + int const fd) { + + UnlinkListEntry * const unlinkListEntryP = + malloc(sizeof(*unlinkListEntryP) + strlen(fileName) + 1); + + if (unlinkListEntryP) { + strcpy(unlinkListEntryP->fileName, fileName); + unlinkListEntryP->fd = fd; + unlinkListEntryP->next = NULL; + } + return unlinkListEntryP; +} + + + +static void +addUnlinkListEntry(const char * const fileName, + int const fd) { + + UnlinkListEntry * const unlinkListEntryP = + newUnlinkListEntry(fileName, fd); + + if (unlinkListEntryP) { + unlinkListEntryP->next = unlinkListP; + unlinkListP = unlinkListEntryP; + } +} + + + +static void +scheduleUnlinkAtExit(const char * const fileName, + int const fd) { +/*---------------------------------------------------------------------------- + Set things up to have the file unlinked as the program exits. + + This is messy and probably doesn't work in all situations; it is a hack + to get Unix code essentially working on Windows, without messing up the + code too badly for Unix. +-----------------------------------------------------------------------------*/ + static bool unlinkListEstablished = false; + + if (!unlinkListEstablished) { + atexit(unlinkTempFiles); + unlinkListP = NULL; + unlinkListEstablished = true; + } + + addUnlinkListEntry(fileName, fd); +} + + + +static void +arrangeUnlink(const char * const fileName, + int const fd) { + + if (canUnlinkOpen) + unlink(fileName); + else + scheduleUnlinkAtExit(fileName, fd); +} + + + FILE * pm_tmpfile(void) { FILE * fileP; - const char * tmpfile; + const char * tmpfileNm; - pm_make_tmpfile(&fileP, &tmpfile); + pm_make_tmpfile(&fileP, &tmpfileNm); - unlink(tmpfile); + arrangeUnlink(tmpfileNm, fileno(fileP)); - pm_strfree(tmpfile); + pm_strfree(tmpfileNm); return fileP; } @@ -327,13 +440,13 @@ int pm_tmpfile_fd(void) { int fd; - const char * tmpfile; + const char * tmpfileNm; - pm_make_tmpfile_fd(&fd, &tmpfile); + pm_make_tmpfile_fd(&fd, &tmpfileNm); - unlink(tmpfile); + arrangeUnlink(tmpfileNm, fd); - pm_strfree(tmpfile); + pm_strfree(tmpfileNm); return fd; } -- cgit 1.4.1