From a42b57186f33d147087eb6fba46e6a3a390faaf0 Mon Sep 17 00:00:00 2001 From: Julien BLACHE Date: Sat, 17 Jan 2009 10:18:40 +0000 Subject: [PATCH] Make batch mode create output files atomically. --- ChangeLog | 2 ++ frontend/scanimage.c | 39 +++++++++++++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index c92d2f108..74a1b2324 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,8 @@ 2009-01-17 Julien Blache * doc/descriptions/hp.desc: add SCSI identifiers for the ScanJet IIc, from Daniel Golle (sane-devel, 20061105). + * frontend/scanimage.c: make batch mode create output files + atomically. Patch by Simon Matter . 2009-01-16 Chris Bagwell * doc/Makefile.in, frontend/Makefile.in, include/Makefile.in, diff --git a/frontend/scanimage.c b/frontend/scanimage.c index c22dc6f65..2b72b7620 100644 --- a/frontend/scanimage.c +++ b/frontend/scanimage.c @@ -2,7 +2,7 @@ Uses the SANE library. Copyright (C) 1996, 1997, 1998 Andreas Beck and David Mosberger - Copyright (C) 1999 - 2008 by the SANE Project -- See AUTHORS and ChangeLog + Copyright (C) 1999 - 2009 by the SANE Project -- See AUTHORS and ChangeLog for details. For questions and comments contact the sane-devel mailinglist (see @@ -2161,8 +2161,13 @@ List of available devices:", prog_name); do { char path[PATH_MAX]; + char part_path[PATH_MAX]; if (batch) /* format is NULL unless batch mode */ - sprintf (path, format, n); /* love --(C++) */ + { + sprintf (path, format, n); /* love --(C++) */ + strcpy (part_path, path); + strcat (part_path, ".part"); + } if (batch) @@ -2199,9 +2204,10 @@ List of available devices:", prog_name); break; } - if (batch && NULL == freopen (path, "w", stdout)) + /* write to .part file while scanning is in progress */ + if (batch && NULL == freopen (part_path, "w", stdout)) { - fprintf (stderr, "cannot open %s\n", path); + fprintf (stderr, "cannot open %s\n", part_path); sane_cancel (device); return SANE_STATUS_ACCESS_DENIED; } @@ -2216,15 +2222,36 @@ List of available devices:", prog_name); switch (status) { case SANE_STATUS_GOOD: - break; case SANE_STATUS_EOF: status = SANE_STATUS_GOOD; + if (batch) + { + /* close output file by redirecting, do not close + stdout here! */ + if (NULL == freopen ("/dev/null", "w", stdout)) + { + fprintf (stderr, "cannot open /dev/null\n"); + sane_cancel (device); + return SANE_STATUS_ACCESS_DENIED; + } + else + { + /* let the fully scanned file show up */ + if (rename (part_path, path)) + { + fprintf (stderr, "cannot rename %s to %s\n", + part_path, path); + sane_cancel (device); + return SANE_STATUS_ACCESS_DENIED; + } + } + } break; default: if (batch) { fclose (stdout); - unlink (path); + unlink (part_path); } break; } /* switch */