Cleaned up old Windows file rename workaround by using Win API native functions; see issue #430
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
* Copyright (c) 2010 Oliver Duis <www.oliverduis.de>
|
||||
*
|
||||
* RawTherapee is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -501,11 +502,7 @@ int ImageIO::loadPPMFromMemory(const char* buffer, int width, int height, bool s
|
||||
|
||||
int ImageIO::savePNG (Glib::ustring fname, int compression, int bps) {
|
||||
|
||||
// create a temporary file name that is opened in parallel by e.g. image viewers whilte RT is still writing
|
||||
Glib::ustring tmpFname=fname;
|
||||
tmpFname.append(".tmp");
|
||||
|
||||
FILE *file = safe_g_fopen (tmpFname, "wb");
|
||||
FILE *file = safe_g_fopen_WriteBinLock (fname);
|
||||
|
||||
if (!file)
|
||||
return IMIO_CANNOTREADFILE;
|
||||
@@ -572,9 +569,6 @@ int ImageIO::savePNG (Glib::ustring fname, int compression, int bps) {
|
||||
delete [] row;
|
||||
fclose (file);
|
||||
|
||||
// Rename temporary filename, practically atomic
|
||||
safe_g_rename(tmpFname,fname);
|
||||
|
||||
if (pl) {
|
||||
pl->setProgressStr ("Ready.");
|
||||
pl->setProgress (1.0);
|
||||
@@ -592,11 +586,7 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality) {
|
||||
cinfo.err = jpeg_std_error (&jerr);
|
||||
jpeg_create_compress (&cinfo);
|
||||
|
||||
// create a temporary file name that is opened in parallel by e.g. image viewers whilte RT is still writing
|
||||
Glib::ustring tmpFname=fname;
|
||||
tmpFname.append(".tmp");
|
||||
|
||||
FILE *file = safe_g_fopen (tmpFname, "wb");
|
||||
FILE *file = safe_g_fopen_WriteBinLock (fname);
|
||||
|
||||
if (!file)
|
||||
return IMIO_CANNOTREADFILE;
|
||||
@@ -686,9 +676,6 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality) {
|
||||
delete [] row;
|
||||
fclose (file);
|
||||
|
||||
// Rename temporary filename, practically atomic
|
||||
safe_g_rename(tmpFname,fname);
|
||||
|
||||
if (pl) {
|
||||
pl->setProgressStr ("Ready.");
|
||||
pl->setProgress (1.0);
|
||||
@@ -709,7 +696,7 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) {
|
||||
unsigned char* linebuffer = new unsigned char[lineWidth];
|
||||
// TODO the following needs to be looked into - do we really need two ways to write a Tiff file ?
|
||||
if (exifRoot && uncompressed) {
|
||||
FILE *file = safe_g_fopen (fname, "wb");
|
||||
FILE *file = safe_g_fopen_WriteBinLock (fname);
|
||||
|
||||
if (!file)
|
||||
return IMIO_CANNOTREADFILE;
|
||||
|
@@ -22,6 +22,10 @@
|
||||
#include <safegtk.h>
|
||||
#include <guiutils.h>
|
||||
#include <glib/gstdio.h>
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
|
||||
Glib::RefPtr<Gdk::Pixbuf> safe_create_from_file(const std::string& filename)
|
||||
@@ -169,7 +173,7 @@ bool safe_spawn_command_line_async (const Glib::ustring& cmd_utf8)
|
||||
#ifdef GLIBMM_EXCEPTIONS_ENABLED
|
||||
try {
|
||||
cmd = Glib::filename_from_utf8(cmd_utf8);
|
||||
printf ("command line: |%s|\n", cmd.c_str());
|
||||
printf ("command line: %s\n", cmd.c_str());
|
||||
Glib::spawn_command_line_async (cmd.c_str());
|
||||
success = true;
|
||||
} catch (Glib::Exception& ex) {
|
||||
@@ -179,7 +183,7 @@ bool safe_spawn_command_line_async (const Glib::ustring& cmd_utf8)
|
||||
std::auto_ptr<Glib::Error> error;
|
||||
cmd = Glib::filename_from_utf8(cmd_utf8, error);
|
||||
if (!error.get()) {
|
||||
printf ("command line: |%s|\n", cmd.c_str());
|
||||
printf ("command line: %s\n", cmd.c_str());
|
||||
Glib::spawn_command_line_async (cmd, error);
|
||||
}
|
||||
if (error.get())
|
||||
@@ -201,7 +205,7 @@ bool safe_spawn_command_line_sync (const Glib::ustring& cmd_utf8)
|
||||
int exitStatus=-1;
|
||||
try {
|
||||
//cmd = Glib::filename_from_utf8(cmd_utf8);
|
||||
printf ("command line: |%s|\n", cmd_utf8.c_str());
|
||||
printf ("command line: %s\n", cmd_utf8.c_str());
|
||||
|
||||
// if it crashes here on windows, make sure you have the GTK runtime files gspawn-win32-helper*.exe files in RT directory
|
||||
Glib::spawn_command_line_sync (cmd_utf8, NULL, NULL, &exitStatus);
|
||||
@@ -211,6 +215,29 @@ bool safe_spawn_command_line_sync (const Glib::ustring& cmd_utf8)
|
||||
return (exitStatus==0);
|
||||
}
|
||||
|
||||
// Opens a file for binary writing and request exclusive lock (cases were you need "wb" mode plus locking)
|
||||
// (Important on Windows to prevent Explorer to crash RT when parallel scanning e.g. a currently written image file)
|
||||
FILE * safe_g_fopen_WriteBinLock(const Glib::ustring& fname) {
|
||||
FILE* f=NULL;
|
||||
|
||||
#ifdef WIN32
|
||||
// g_fopen just uses _wfopen internally on Windows, does not lock access and has no options to set this
|
||||
// so use a native function to work around this problem
|
||||
wchar_t *wFname = (wchar_t*)g_utf8_to_utf16 (fname.c_str(), -1, NULL, NULL, NULL);
|
||||
HANDLE hFile = CreateFileW(wFname, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
g_free(wFname);
|
||||
|
||||
if (hFile==INVALID_HANDLE_VALUE)
|
||||
f=NULL;
|
||||
else
|
||||
f=_fdopen( _open_osfhandle((intptr_t)hFile, 0) , "wb");
|
||||
#else
|
||||
f = safe_g_fopen(fname, "wb");
|
||||
#endif
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
FILE * safe_g_fopen(const Glib::ustring& src,const gchar *mode)
|
||||
{
|
||||
return g_fopen(src.c_str(),mode);
|
||||
|
@@ -31,6 +31,7 @@ std::string safe_locale_from_utf8 (const Glib::ustring& utf8_str);
|
||||
std::string safe_filename_from_utf8 (const Glib::ustring& utf8_str);
|
||||
|
||||
FILE * safe_g_fopen(const Glib::ustring& src,const gchar *mode);
|
||||
FILE * safe_g_fopen_WriteBinLock(const Glib::ustring& fname);
|
||||
bool safe_file_test (const Glib::ustring& filename, Glib::FileTest test);
|
||||
int safe_g_remove(const Glib::ustring& filename);
|
||||
int safe_g_rename(const Glib::ustring& oldFilename, const Glib::ustring& newFilename);
|
||||
|
Reference in New Issue
Block a user