Search
lxdream.org :: lxdream/src/vmu/vmuvol.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/vmu/vmuvol.c
changeset 1042:0fd066956482
prev1035:e3093fd7d1da
next1045:0c46bac28888
author nkeynes
date Fri Jun 26 13:53:54 2009 +0000 (11 years ago)
permissions -rw-r--r--
last change Do the save-to-temp and rename thing when saving VMUs, for the sake of limiting corruption possibilities
file annotate diff log raw
1.1 --- a/src/vmu/vmuvol.c Wed Jun 24 05:10:25 2009 +0000
1.2 +++ b/src/vmu/vmuvol.c Fri Jun 26 13:53:54 2009 +0000
1.3 @@ -19,12 +19,14 @@
1.4 #include <glib/gmem.h>
1.5 #include <glib/gstrfuncs.h>
1.6 #include <string.h>
1.7 +#include <unistd.h>
1.8 #include <stdio.h>
1.9 #include <fcntl.h>
1.10 #include <errno.h>
1.11
1.12 #include "vmu/vmuvol.h"
1.13 #include "dream.h"
1.14 +#include "lxpaths.h"
1.15
1.16 #define VMU_MAX_PARTITIONS 256
1.17 #define VMU_MAX_BLOCKS 65536 /* Actually slightly less than this, but it'll do */
1.18 @@ -187,18 +189,22 @@
1.19 };
1.20
1.21
1.22 -
1.23 gboolean vmu_volume_save( const gchar *filename, vmu_volume_t vol, gboolean create_only )
1.24 {
1.25 struct vmu_file_header head;
1.26 struct vmu_chunk_header chunk;
1.27 int i;
1.28 -
1.29 - FILE *f = fopen( filename, (create_only ? "wx" : "w") ); /* Portable? */
1.30 - if( f == NULL ) {
1.31 +
1.32 + gchar *tempfile = get_filename_at(filename, ".XXXXXXXX.vmu");
1.33 + int fd = mkstemps( tempfile, 4 );
1.34 + if( fd == -1 ) {
1.35 + g_free(tempfile);
1.36 return FALSE;
1.37 }
1.38
1.39 + FILE *f = fdopen( fd, "w+" );
1.40 +
1.41 +
1.42 /* File header */
1.43 memcpy( head.magic, VMU_FILE_MAGIC, 16 );
1.44 head.version = VMU_FILE_VERSION;
1.45 @@ -222,19 +228,31 @@
1.46 for( i=0; i< vol->part_count; i++ ) {
1.47 memcpy( chunk.name, "DATA", 4 );
1.48 chunk.length = 0;
1.49 - fwrite( &chunk, sizeof(chunk), 1, f );
1.50 + if( fwrite( &chunk, sizeof(chunk), 1, f ) != 1 ) goto cleanup;
1.51 long posn = ftell(f);
1.52 - fwrite( &vol->part[i].block_count, sizeof(vol->part[i].block_count), 1, f );
1.53 + if( fwrite( &vol->part[i].block_count, sizeof(vol->part[i].block_count), 1, f ) != 1 ) goto cleanup;
1.54 fwrite_gzip( vol->part[i].blocks, vol->part[i].block_count, VMU_BLOCK_SIZE, f );
1.55 long end = ftell(f);
1.56 fseek( f, posn - sizeof(chunk.length), SEEK_SET );
1.57 chunk.length = end-posn;
1.58 - fwrite( &chunk.length, sizeof(chunk.length), 1, f );
1.59 + if( fwrite( &chunk.length, sizeof(chunk.length), 1, f ) != 1 ) goto cleanup;
1.60 fseek( f, end, SEEK_SET );
1.61 }
1.62 fclose(f);
1.63 +
1.64 + if( rename(tempfile, filename) != 0 )
1.65 + goto cleanup;
1.66 +
1.67 + /* All good */
1.68 vol->dirty = FALSE;
1.69 + g_free(tempfile);
1.70 return TRUE;
1.71 +
1.72 +cleanup:
1.73 + fclose(f);
1.74 + unlink(tempfile);
1.75 + g_free(tempfile);
1.76 + return FALSE;
1.77 }
1.78
1.79 vmu_volume_t vmu_volume_load( const gchar *filename )
.