Grafx2 now disables safety backups (and warns the user on startup) if another instance is running or if its configuration directory is read-only. Implemented separately on Linux and Windows, tested only on Windows
git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1343 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
parent
7076e8e06d
commit
4c3a0b6f68
69
io.c
69
io.c
@ -284,3 +284,72 @@ void Get_full_filename(char * output_name, char * file_name, char * directory_na
|
||||
}
|
||||
strcat(output_name,file_name);
|
||||
}
|
||||
|
||||
/// Lock file used to prevent several instances of grafx2 from harming each others' backups
|
||||
#ifdef __WIN32__
|
||||
HANDLE Lock_file_handle = INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
int Lock_file_handle = -1;
|
||||
#endif
|
||||
|
||||
byte Create_lock_file(const char *file_directory)
|
||||
{
|
||||
char lock_filename[MAX_PATH_CHARACTERS];
|
||||
|
||||
strcpy(lock_filename,file_directory);
|
||||
strcat(lock_filename,"gfx2.lck");
|
||||
|
||||
#ifdef __WIN32__
|
||||
// Windowzy method for creating a lock file
|
||||
Lock_file_handle = CreateFile(
|
||||
lock_filename,
|
||||
GENERIC_WRITE,
|
||||
0, // No sharing
|
||||
NULL,
|
||||
OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (Lock_file_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
// Unixy method for lock file
|
||||
Lock_file_handle = open(lock_filename,O_WRONLY|O_CREAT);
|
||||
if (Lock_file_handle == -1)
|
||||
{
|
||||
// Usually write-protected media
|
||||
return -1;
|
||||
}
|
||||
if (lockf(Lock_file_handle, F_TLOCK, 0)==-1)
|
||||
{
|
||||
close(Lock_file_handle);
|
||||
// Usually write-protected media
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Release_lock_file(const char *file_directory)
|
||||
{
|
||||
char lock_filename[MAX_PATH_CHARACTERS];
|
||||
|
||||
#ifdef __WIN32__
|
||||
if (Lock_file_handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(Lock_file_handle);
|
||||
}
|
||||
#else
|
||||
if (Lock_file_handle != -1)
|
||||
{
|
||||
close(Lock_file_handle);
|
||||
Lock_file_handle = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Actual deletion
|
||||
strcpy(lock_filename,file_directory);
|
||||
strcat(lock_filename,"gfx2.lck");
|
||||
remove(lock_filename);
|
||||
}
|
||||
9
io.h
9
io.h
@ -94,3 +94,12 @@ void For_each_file(const char * directory_name, void Callback(const char *));
|
||||
/// Creates a fully qualified name from a directory and filename.
|
||||
/// The point is simply to insert a PATH_SEPARATOR when needed.
|
||||
void Get_full_filename(char * output_name, char * file_name, char * directory_name);
|
||||
|
||||
///
|
||||
/// Creates a lock file, to check if an other instance of Grafx2 is running.
|
||||
/// @return 0 on success (first instance), -1 on failure (others are running)
|
||||
byte Create_lock_file(const char *file_directory);
|
||||
|
||||
///
|
||||
/// Release a lock file created by ::Create_Lock_file
|
||||
void Release_lock_file(const char *file_directory);
|
||||
33
loadsave.c
33
loadsave.c
@ -1162,6 +1162,7 @@ T_String_list *Backups_main = NULL;
|
||||
/// A list of files, used for scanning a directory
|
||||
T_String_list *Backups_spare = NULL;
|
||||
|
||||
|
||||
// Settings for safety backup (frequency, numbers, etc)
|
||||
|
||||
const int Rotation_safety_backup = 8;
|
||||
@ -1187,9 +1188,9 @@ void Add_backup_file(const char *name)
|
||||
Extract_filename(file_name, name);
|
||||
|
||||
// Check first character
|
||||
if (file_name[0]=='a')
|
||||
if (file_name[0]==Main_safety_backup_prefix)
|
||||
list = &Backups_main;
|
||||
else if (file_name[0]=='b')
|
||||
else if (file_name[0]==Spare_safety_backup_prefix)
|
||||
list = &Backups_spare;
|
||||
else {
|
||||
// Not a good file
|
||||
@ -1291,13 +1292,22 @@ byte Process_backups(T_String_list **list)
|
||||
}
|
||||
|
||||
|
||||
/// Global indicator that tells if the safety backup system is active
|
||||
byte Safety_backup_active = 0;
|
||||
|
||||
///
|
||||
/// Checks if there are any pending safety backups, and then opens them.
|
||||
///
|
||||
/// @return 0 if no problem, -1 if the backup system cannot be activated, >=1 if some backups are restored
|
||||
int Check_recovery(void)
|
||||
{
|
||||
int restored_spare;
|
||||
int restored_main;
|
||||
|
||||
// First check if can write backups
|
||||
if (Create_lock_file(Config_directory))
|
||||
return -1;
|
||||
|
||||
Safety_backup_active=1;
|
||||
|
||||
Backups_main = NULL;
|
||||
Backups_spare = NULL;
|
||||
@ -1327,13 +1337,7 @@ int Check_recovery(void)
|
||||
Compute_paintbrush_coordinates();
|
||||
Redraw_layered_image();
|
||||
}
|
||||
/*
|
||||
if (restored_main||restored_spare)
|
||||
{
|
||||
Display_all_screen();
|
||||
return 1;
|
||||
}*/
|
||||
return restored_main || restored_spare;
|
||||
return restored_main + restored_spare;
|
||||
}
|
||||
|
||||
void Rotate_safety_backups(void)
|
||||
@ -1343,6 +1347,9 @@ void Rotate_safety_backups(void)
|
||||
char file_name[12+1];
|
||||
char deleted_file[MAX_PATH_CHARACTERS];
|
||||
|
||||
if (!Safety_backup_active)
|
||||
return;
|
||||
|
||||
now = SDL_GetTicks();
|
||||
// It's time to save if either:
|
||||
// - Many edits have taken place
|
||||
@ -1384,6 +1391,9 @@ void Delete_safety_backups(void)
|
||||
{
|
||||
T_String_list *element;
|
||||
|
||||
if (!Safety_backup_active)
|
||||
return;
|
||||
|
||||
Backups_main = NULL;
|
||||
Backups_spare = NULL;
|
||||
|
||||
@ -1401,4 +1411,7 @@ void Delete_safety_backups(void)
|
||||
printf("Failed to delete %s\n",element->String);
|
||||
}
|
||||
|
||||
// Release lock file
|
||||
Release_lock_file(Config_directory);
|
||||
|
||||
}
|
||||
|
||||
108
main.c
108
main.c
@ -760,54 +760,74 @@ int Init_program(int argc,char * argv[])
|
||||
*Brush=MC_White;
|
||||
|
||||
// Test de recuperation de fichiers sauvés
|
||||
if (Check_recovery())
|
||||
{
|
||||
// Some files were loaded from last crash-exit.
|
||||
// Do not load files from command-line, nor show splash screen.
|
||||
Compute_optimal_menu_colors(Main_palette);
|
||||
Display_all_screen();
|
||||
Display_menu();
|
||||
Display_cursor();
|
||||
}
|
||||
else
|
||||
switch (Check_recovery())
|
||||
{
|
||||
T_IO_Context context;
|
||||
|
||||
switch (file_in_command_line)
|
||||
{
|
||||
case 0:
|
||||
if (Config.Opening_message)
|
||||
Button_Message_initial();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Load this file
|
||||
Init_context_layered_image(&context, spare_filename, spare_directory);
|
||||
Load_image(&context);
|
||||
Destroy_context(&context);
|
||||
End_of_modification();
|
||||
Redraw_layered_image();
|
||||
|
||||
Button_Page();
|
||||
// no break ! proceed with the other file now
|
||||
case 1:
|
||||
Init_context_layered_image(&context, main_filename, main_directory);
|
||||
Load_image(&context);
|
||||
Destroy_context(&context);
|
||||
End_of_modification();
|
||||
Redraw_layered_image();
|
||||
|
||||
Hide_cursor();
|
||||
Compute_optimal_menu_colors(Main_palette);
|
||||
Display_all_screen();
|
||||
Display_menu();
|
||||
Display_cursor();
|
||||
Resolution_in_command_line = 0;
|
||||
break;
|
||||
default:
|
||||
// Some files were loaded from last crash-exit.
|
||||
// Do not load files from command-line, nor show splash screen.
|
||||
Compute_optimal_menu_colors(Main_palette);
|
||||
Display_all_screen();
|
||||
Display_menu();
|
||||
Display_cursor();
|
||||
Verbose_message("Images recovered",
|
||||
"Grafx2 has recovered images from\n"
|
||||
"last session, before a crash or\n"
|
||||
"shutdown. Browse the history using\n"
|
||||
"the Undo/Redo button, and when\n"
|
||||
"you find a state that you want to\n"
|
||||
"save, use the 'Save as' button to\n"
|
||||
"save the image.\n"
|
||||
"Some backups can be present in\n"
|
||||
"the spare page too.\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case -1: // Unable to write lock file
|
||||
Verbose_message("Warning",
|
||||
"Safety backups (every minute) are\n"
|
||||
"disabled because Grafx2 is running\n"
|
||||
"from a read-only device, or other\n"
|
||||
"instances are running.");
|
||||
break;
|
||||
|
||||
case 0:
|
||||
|
||||
switch (file_in_command_line)
|
||||
{
|
||||
case 0:
|
||||
if (Config.Opening_message)
|
||||
Button_Message_initial();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Load this file
|
||||
Init_context_layered_image(&context, spare_filename, spare_directory);
|
||||
Load_image(&context);
|
||||
Destroy_context(&context);
|
||||
End_of_modification();
|
||||
Redraw_layered_image();
|
||||
|
||||
Button_Page();
|
||||
// no break ! proceed with the other file now
|
||||
case 1:
|
||||
Init_context_layered_image(&context, main_filename, main_directory);
|
||||
Load_image(&context);
|
||||
Destroy_context(&context);
|
||||
End_of_modification();
|
||||
Redraw_layered_image();
|
||||
|
||||
Hide_cursor();
|
||||
Compute_optimal_menu_colors(Main_palette);
|
||||
Display_all_screen();
|
||||
Display_menu();
|
||||
Display_cursor();
|
||||
Resolution_in_command_line = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user