Search
lxdream.org :: lxdream :: r1042:0fd066956482
lxdream 0.9.1
released Jun 29
Download Now
changeset1042:0fd066956482
parent1041:5fcc39857c5c
child1043:ec716f2b8ffb
authornkeynes
dateFri Jun 26 13:53:54 2009 +0000 (11 years ago)
Do the save-to-temp and rename thing when saving VMUs, for the sake of limiting corruption possibilities
src/util.c
src/vmu/vmuvol.c
1.1 --- a/src/util.c Fri Jun 26 05:47:04 2009 +0000
1.2 +++ b/src/util.c Fri Jun 26 13:53:54 2009 +0000
1.3 @@ -82,7 +82,7 @@
1.4 return len;
1.5 }
1.6
1.7 -void fwrite_gzip( void *p, size_t sz, size_t count, FILE *f )
1.8 +int fwrite_gzip( void *p, size_t sz, size_t count, FILE *f )
1.9 {
1.10 uLongf size = sz*count;
1.11 uLongf csize = ((int)(size*1.001))+13;
1.12 @@ -91,8 +91,15 @@
1.13 assert( status == Z_OK );
1.14 uint32_t wsize = (uint32_t)csize;
1.15 fwrite( &wsize, sizeof(wsize), 1, f );
1.16 - fwrite( tmp, csize, 1, f );
1.17 + int written = fwrite( tmp, csize, 1, f );
1.18 g_free(tmp);
1.19 +
1.20 + /* Could be finer-grained, but this is enough to know it succeeded/failed */
1.21 + if( written == 1 ) {
1.22 + return count;
1.23 + } else {
1.24 + return 0;
1.25 + }
1.26 }
1.27
1.28 int fread_gzip( void *p, size_t sz, size_t count, FILE *f )
2.1 --- a/src/vmu/vmuvol.c Fri Jun 26 05:47:04 2009 +0000
2.2 +++ b/src/vmu/vmuvol.c Fri Jun 26 13:53:54 2009 +0000
2.3 @@ -19,12 +19,14 @@
2.4 #include <glib/gmem.h>
2.5 #include <glib/gstrfuncs.h>
2.6 #include <string.h>
2.7 +#include <unistd.h>
2.8 #include <stdio.h>
2.9 #include <fcntl.h>
2.10 #include <errno.h>
2.11
2.12 #include "vmu/vmuvol.h"
2.13 #include "dream.h"
2.14 +#include "lxpaths.h"
2.15
2.16 #define VMU_MAX_PARTITIONS 256
2.17 #define VMU_MAX_BLOCKS 65536 /* Actually slightly less than this, but it'll do */
2.18 @@ -187,18 +189,22 @@
2.19 };
2.20
2.21
2.22 -
2.23 gboolean vmu_volume_save( const gchar *filename, vmu_volume_t vol, gboolean create_only )
2.24 {
2.25 struct vmu_file_header head;
2.26 struct vmu_chunk_header chunk;
2.27 int i;
2.28 -
2.29 - FILE *f = fopen( filename, (create_only ? "wx" : "w") ); /* Portable? */
2.30 - if( f == NULL ) {
2.31 +
2.32 + gchar *tempfile = get_filename_at(filename, ".XXXXXXXX.vmu");
2.33 + int fd = mkstemps( tempfile, 4 );
2.34 + if( fd == -1 ) {
2.35 + g_free(tempfile);
2.36 return FALSE;
2.37 }
2.38
2.39 + FILE *f = fdopen( fd, "w+" );
2.40 +
2.41 +
2.42 /* File header */
2.43 memcpy( head.magic, VMU_FILE_MAGIC, 16 );
2.44 head.version = VMU_FILE_VERSION;
2.45 @@ -222,19 +228,31 @@
2.46 for( i=0; i< vol->part_count; i++ ) {
2.47 memcpy( chunk.name, "DATA", 4 );
2.48 chunk.length = 0;
2.49 - fwrite( &chunk, sizeof(chunk), 1, f );
2.50 + if( fwrite( &chunk, sizeof(chunk), 1, f ) != 1 ) goto cleanup;
2.51 long posn = ftell(f);
2.52 - fwrite( &vol->part[i].block_count, sizeof(vol->part[i].block_count), 1, f );
2.53 + if( fwrite( &vol->part[i].block_count, sizeof(vol->part[i].block_count), 1, f ) != 1 ) goto cleanup;
2.54 fwrite_gzip( vol->part[i].blocks, vol->part[i].block_count, VMU_BLOCK_SIZE, f );
2.55 long end = ftell(f);
2.56 fseek( f, posn - sizeof(chunk.length), SEEK_SET );
2.57 chunk.length = end-posn;
2.58 - fwrite( &chunk.length, sizeof(chunk.length), 1, f );
2.59 + if( fwrite( &chunk.length, sizeof(chunk.length), 1, f ) != 1 ) goto cleanup;
2.60 fseek( f, end, SEEK_SET );
2.61 }
2.62 fclose(f);
2.63 +
2.64 + if( rename(tempfile, filename) != 0 )
2.65 + goto cleanup;
2.66 +
2.67 + /* All good */
2.68 vol->dirty = FALSE;
2.69 + g_free(tempfile);
2.70 return TRUE;
2.71 +
2.72 +cleanup:
2.73 + fclose(f);
2.74 + unlink(tempfile);
2.75 + g_free(tempfile);
2.76 + return FALSE;
2.77 }
2.78
2.79 vmu_volume_t vmu_volume_load( const gchar *filename )
.