diff --git a/compat.h b/compat.h index ffc0c899..a9e2674e 100644 --- a/compat.h +++ b/compat.h @@ -1,5 +1,5 @@ /* compat.h: various compatibility bits - Copyright (c) 2003 Philip Kendall + Copyright (c) 2003-2008 Philip Kendall $Id$ @@ -28,6 +28,8 @@ #include +#include + /* Remove the gcc-specific incantations if we're not using gcc */ #ifdef __GNUC__ @@ -43,14 +45,6 @@ #endif /* #ifdef __GNUC__ */ -/* Certain brain damaged operating systems (DOS/Windows) treat text - and binary files different in open(2) and need to be given the - O_BINARY flag to tell them it's a binary file */ -#ifndef O_BINARY -#define O_BINARY 0 -#endif /* #ifndef O_BINARY */ - -/* Replacement functions */ #ifndef HAVE_DIRNAME char *dirname( char *path ); #endif /* #ifndef HAVE_DIRNAME */ @@ -77,4 +71,19 @@ const char* compat_get_temp_path( void ); const char* compat_get_home_path( void ); int compat_is_absolute_path( const char *path ); +#ifndef UI_WII +typedef int compat_fd; +#else /* #ifndef UI_WII */ +typedef FILE* compat_fd; +#endif /* #ifndef UI_WII */ + +extern const compat_fd COMPAT_FILE_OPEN_FAILED; + +compat_fd compat_file_open( const char *path, int write ); +off_t compat_file_get_length( compat_fd fd ); +int compat_file_read( compat_fd fd, utils_file *file ); +int compat_file_write( compat_fd fd, const unsigned char *buffer, + size_t length ); +int compat_file_close( compat_fd fd ); + #endif /* #ifndef FUSE_COMPAT_H */ diff --git a/compat/amiga/Makefile.am b/compat/amiga/Makefile.am index 7dd10f9a..2d7dcead 100644 --- a/compat/amiga/Makefile.am +++ b/compat/amiga/Makefile.am @@ -1,5 +1,5 @@ ## Process this file with automake to produce Makefile.in -## Copyright (c) 2007 Philip Kendall +## Copyright (c) 2007-2008 Philip Kendall ## $Id$ @@ -27,7 +27,8 @@ AM_CPPFLAGS = -I$(srcdir)/../.. noinst_LIBRARIES = libcompatos.a -libcompatos_a_SOURCES = osname.c \ +libcompatos_a_SOURCES = ../unix/file.c \ + osname.c \ paths.c INCLUDES = @GLIB_CFLAGS@ @GTK_CFLAGS@ @LIBSPEC_CFLAGS@ diff --git a/compat/morphos/Makefile.am b/compat/morphos/Makefile.am index 040789ec..cd60cf4c 100644 --- a/compat/morphos/Makefile.am +++ b/compat/morphos/Makefile.am @@ -1,5 +1,5 @@ ## Process this file with automake to produce Makefile.in -## Copyright (c) 2007 Philip Kendall +## Copyright (c) 2007-2008 Philip Kendall ## $Id$ @@ -27,7 +27,8 @@ AM_CPPFLAGS = -I$(srcdir)/../.. noinst_LIBRARIES = libcompatos.a -libcompatos_a_SOURCES = osname.c \ +libcompatos_a_SOURCES = ../unix/file.c \ + osname.c \ ../amiga/paths.c INCLUDES = @GLIB_CFLAGS@ @GTK_CFLAGS@ @LIBSPEC_CFLAGS@ diff --git a/compat/unix/Makefile.am b/compat/unix/Makefile.am index 7dd10f9a..e5f857af 100644 --- a/compat/unix/Makefile.am +++ b/compat/unix/Makefile.am @@ -1,5 +1,5 @@ ## Process this file with automake to produce Makefile.in -## Copyright (c) 2007 Philip Kendall +## Copyright (c) 2007-2008 Philip Kendall ## $Id$ @@ -27,7 +27,8 @@ AM_CPPFLAGS = -I$(srcdir)/../.. noinst_LIBRARIES = libcompatos.a -libcompatos_a_SOURCES = osname.c \ +libcompatos_a_SOURCES = file.c \ + osname.c \ paths.c INCLUDES = @GLIB_CFLAGS@ @GTK_CFLAGS@ @LIBSPEC_CFLAGS@ diff --git a/compat/unix/file.c b/compat/unix/file.c new file mode 100644 index 00000000..a027aeb0 --- /dev/null +++ b/compat/unix/file.c @@ -0,0 +1,112 @@ +/* file.c: File-related compatibility routines + Copyright (c) 2008 Philip Kendall + + $Id$ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Author contact information: + + E-mail: philip-fuse@shadowmagic.org.uk + +*/ + +#include + +#include +#include +#include +#include +#include + +#include "compat.h" +#include "ui/ui.h" + +/* Certain brain damaged operating systems (DOS/Windows) treat text + and binary files different in open(2) and need to be given the + O_BINARY flag to tell them it's a binary file */ +#ifndef O_BINARY +#define O_BINARY 0 +#endif /* #ifndef O_BINARY */ + +const compat_fd COMPAT_FILE_OPEN_FAILED = -1; + +compat_fd +compat_file_open( const char *path, int write ) +{ + int flags = write ? O_WRONLY | O_CREAT : O_RDONLY; + compat_fd r; + flags |= O_BINARY; + r = open( path, flags ); + if( r == COMPAT_FILE_OPEN_FAILED ) { + ui_error( UI_ERROR_ERROR, "failed to open `%s': %s", path, strerror( errno ) ); + } + return r; +} + +off_t +compat_file_get_length( compat_fd fd ) +{ + struct stat file_info; + + if( fstat( fd, &file_info ) ) { + ui_error( UI_ERROR_ERROR, "couldn't stat file: %s", strerror( errno ) ); + return -1; + } + + return file_info.st_size; +} + +int +compat_file_read( compat_fd fd, utils_file *file ) +{ + ssize_t bytes = read( fd, file->buffer, file->length ); + if( bytes != file->length ) { + if( bytes == -1 ) { + ui_error( UI_ERROR_ERROR, "error reading file: %s", strerror( errno ) ); + } else { + ui_error( UI_ERROR_ERROR, + "error reading file: expected %d bytes, but read only %d", + file->length, bytes ); + } + return 1; + } + + return 0; +} + +int +compat_file_write( compat_fd fd, const unsigned char *buffer, size_t length ) +{ + ssize_t bytes = write( fd, buffer, length ); + if( bytes != length ) { + if( bytes == -1 ) { + ui_error( UI_ERROR_ERROR, "error writing file: %s", strerror( errno ) ); + } else { + ui_error( UI_ERROR_ERROR, + "error writing file: expected %d bytes, but wrote only %d", + length, bytes ); + } + return 1; + } + + return 0; +} + +int +compat_file_close( compat_fd fd ) +{ + return close( fd ); +} diff --git a/compat/wii/Makefile.am b/compat/wii/Makefile.am new file mode 100644 index 00000000..e5f857af --- /dev/null +++ b/compat/wii/Makefile.am @@ -0,0 +1,34 @@ +## Process this file with automake to produce Makefile.in +## Copyright (c) 2007-2008 Philip Kendall + +## $Id$ + +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License along +## with this program; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +## +## Author contact information: +## +## E-mail: philip-fuse@shadowmagic.org.uk + +AUTOMAKE_OPTIONS = foreign + +AM_CPPFLAGS = -I$(srcdir)/../.. + +noinst_LIBRARIES = libcompatos.a + +libcompatos_a_SOURCES = file.c \ + osname.c \ + paths.c + +INCLUDES = @GLIB_CFLAGS@ @GTK_CFLAGS@ @LIBSPEC_CFLAGS@ diff --git a/compat/wii/file.c b/compat/wii/file.c new file mode 100644 index 00000000..92549848 --- /dev/null +++ b/compat/wii/file.c @@ -0,0 +1,95 @@ +/* file.c: File-related compatibility routines + Copyright (c) 2008 Philip Kendall + + $Id$ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + Author contact information: + + E-mail: philip-fuse@shadowmagic.org.uk + +*/ + +#include + +#include +#include +#include +#include +#include + +#include "compat.h" +#include "ui/ui.h" + +const compat_fd COMPAT_FILE_OPEN_FAILED = NULL; + +compat_fd +compat_file_open( const char *path, int write ) +{ + compat_fd r; + r = fopen( path, write ? "w" : "r" ); + if( r == COMPAT_FILE_OPEN_FAILED ) { + ui_error( UI_ERROR_ERROR, "failed to open `%s': %s", path, strerror( errno ) ); + } + return r; +} + +off_t +compat_file_get_length( compat_fd fd ) +{ + struct stat file_info; + + if( fstat( fileno( fd ), &file_info ) ) { + ui_error( UI_ERROR_ERROR, "couldn't stat file: %s", strerror( errno ) ); + return -1; + } + + return file_info.st_size; +} + +int +compat_file_read( compat_fd fd, utils_file *file ) +{ + size_t bytes = fread( file->buffer, 1, file->length, fd ); + if( bytes != file->length ) { + ui_error( UI_ERROR_ERROR, + "error reading file: expected %d bytes, but read only %d", + file->length, bytes ); + return 1; + } + + return 0; +} + +int +compat_file_write( compat_fd fd, const unsigned char *buffer, size_t length ) +{ + size_t bytes = fwrite( buffer, 1, length, fd ); + if( bytes != length ) { + ui_error( UI_ERROR_ERROR, + "error writing file: expected %d bytes, but wrote only %d", + length, bytes ); + return 1; + } + + return 0; +} + +int +compat_file_close( compat_fd fd ) +{ + return fclose( fd ); +} diff --git a/compat/win32/Makefile.am b/compat/win32/Makefile.am index 7dd10f9a..2d7dcead 100644 --- a/compat/win32/Makefile.am +++ b/compat/win32/Makefile.am @@ -1,5 +1,5 @@ ## Process this file with automake to produce Makefile.in -## Copyright (c) 2007 Philip Kendall +## Copyright (c) 2007-2008 Philip Kendall ## $Id$ @@ -27,7 +27,8 @@ AM_CPPFLAGS = -I$(srcdir)/../.. noinst_LIBRARIES = libcompatos.a -libcompatos_a_SOURCES = osname.c \ +libcompatos_a_SOURCES = ../unix/file.c \ + osname.c \ paths.c INCLUDES = @GLIB_CFLAGS@ @GTK_CFLAGS@ @LIBSPEC_CFLAGS@ diff --git a/hacking/ChangeLog b/hacking/ChangeLog index bf4715f4..4f6a6c34 100644 --- a/hacking/ChangeLog +++ b/hacking/ChangeLog @@ -2750,3 +2750,7 @@ 20080621 debugger/breakpoint.c: don't try copying an empty condition. 20080621 debugger/debugger.c: when exiting, quit the main emulation loop immediately. +20080623 compat/{amiga/Makefile.am,morphos/Makefile.am,unix/{Makefile.am, + file.c},wii/{Makefile.am,file.c},win32/Makefile.am},compat.h,if1.c, + utils.c: factor out low-level file handling into compat//file.c; + needed for Wii port. diff --git a/if1.c b/if1.c index a920002e..cb993a5c 100644 --- a/if1.c +++ b/if1.c @@ -1221,8 +1221,8 @@ if1_plug( const char *filename, int what ) case 1: if( if1_ula.fd_r >= 0 ) close( if1_ula.fd_r ); - fd = if1_ula.fd_r = open( filename, O_RDWR | O_BINARY | O_NONBLOCK ); - if( fcntl( fd, F_SETFL, O_RDONLY | O_BINARY | O_NONBLOCK ) ) + fd = if1_ula.fd_r = open( filename, O_RDWR | O_NONBLOCK ); + if( fcntl( fd, F_SETFL, O_RDONLY | O_NONBLOCK ) ) ui_error( UI_ERROR_ERROR, "Cannot set O_RDONLY on '%s': %s", filename, strerror( errno ) ); if1_ula.rs232_buffer = 0x100; /* buffer is empty */ @@ -1230,15 +1230,15 @@ if1_plug( const char *filename, int what ) case 2: if( if1_ula.fd_t >= 0 ) close( if1_ula.fd_t ); - fd = if1_ula.fd_t = open( filename, O_RDWR | O_BINARY | O_NONBLOCK ); - if( fcntl( fd, F_SETFL, O_WRONLY | O_BINARY | O_NONBLOCK ) ) + fd = if1_ula.fd_t = open( filename, O_RDWR | O_NONBLOCK ); + if( fcntl( fd, F_SETFL, O_WRONLY | O_NONBLOCK ) ) ui_error( UI_ERROR_ERROR, "Cannot set O_WRONLY on '%s': %s", filename, strerror( errno ) ); break; case 3: if( if1_ula.fd_net >= 0 ) close( if1_ula.fd_net ); - fd = if1_ula.fd_net = open( filename, O_RDWR | O_BINARY | O_NONBLOCK ); + fd = if1_ula.fd_net = open( filename, O_RDWR | O_NONBLOCK ); break; } diff --git a/utils.c b/utils.c index 3c1f25e7..29a631a5 100644 --- a/utils.c +++ b/utils.c @@ -1,5 +1,5 @@ /* utils.c: some useful helper functions - Copyright (c) 1999-2005 Philip Kendall + Copyright (c) 1999-2008 Philip Kendall $Id$ @@ -26,16 +26,10 @@ #include #include -#include #ifdef HAVE_LIBGEN_H #include #endif /* #ifdef HAVE_LIBGEN_H */ -#include -#include -#include -#include #include -#include #include #include @@ -194,14 +188,14 @@ utils_open_file( const char *filename, int autoload, int utils_find_auxiliary_file( const char *filename, utils_aux_type type ) { - int fd; + compat_fd fd; char path[ PATH_MAX ]; path_context ctx; /* If given an absolute path, just look there */ if( compat_is_absolute_path( filename ) ) - return open( filename, O_RDONLY | O_BINARY ); + return compat_file_open( filename, 0 ); /* Otherwise look in some likely locations */ init_path_context( &ctx, type ); @@ -212,8 +206,8 @@ utils_find_auxiliary_file( const char *filename, utils_aux_type type ) #else snprintf( path, PATH_MAX, "%s" FUSE_DIR_SEP_STR "%s", ctx.path, filename ); #endif - fd = open( path, O_RDONLY | O_BINARY ); - if( fd != -1 ) return fd; + fd = compat_file_open( path, 0 ); + if( fd != COMPAT_FILE_OPEN_FAILED ) return fd; } @@ -329,36 +323,28 @@ get_next_path( path_context *ctx ) int utils_read_file( const char *filename, utils_file *file ) { - int fd; + compat_fd fd; int error; - fd = open( filename, O_RDONLY | O_BINARY ); - if( fd == -1 ) { + fd = compat_file_open( filename, 0 ); + if( fd == COMPAT_FILE_OPEN_FAILED ) { ui_error( UI_ERROR_ERROR, "couldn't open '%s': %s", filename, strerror( errno ) ); return 1; } - error = utils_read_fd( fd, filename, file ); + error = compat_file_read( fd, file ); if( error ) return error; return 0; } int -utils_read_fd( int fd, const char *filename, utils_file *file ) +utils_read_fd( compat_fd fd, const char *filename, utils_file *file ) { - struct stat file_info; - - if( fstat( fd, &file_info) ) { - ui_error( UI_ERROR_ERROR, "Couldn't stat '%s': %s", filename, - strerror( errno ) ); - close(fd); - return 1; - } - - file->length = file_info.st_size; + file->length = compat_file_get_length( fd ); + if( file->length == -1 ) return 1; file->buffer = malloc( file->length ); if( !file->buffer ) { @@ -366,15 +352,13 @@ utils_read_fd( int fd, const char *filename, utils_file *file ) return 1; } - if( read( fd, file->buffer, file->length ) != file->length ) { - ui_error( UI_ERROR_ERROR, "Error reading from '%s': %s", filename, - strerror( errno ) ); + if( compat_file_read( fd, file ) ) { free( file->buffer ); - close( fd ); + compat_file_close( fd ); return 1; } - if( close(fd) ) { + if( compat_file_close( fd ) ) { ui_error( UI_ERROR_ERROR, "Couldn't close '%s': %s", filename, strerror( errno ) ); free( file->buffer ); @@ -395,27 +379,17 @@ utils_close_file( utils_file *file ) int utils_write_file( const char *filename, const unsigned char *buffer, size_t length ) { - FILE *f; + compat_fd fd; - f=fopen( filename, "wb" ); - if(!f) { - ui_error( UI_ERROR_ERROR, "error opening '%s': %s", filename, - strerror( errno ) ); - return 1; - } - - if( fwrite( buffer, 1, length, f ) != length ) { - ui_error( UI_ERROR_ERROR, "error writing to '%s': %s", filename, - strerror( errno ) ); - fclose(f); + fd = compat_file_open( filename, 1 ); + if( fd == COMPAT_FILE_OPEN_FAILED ) return 1; + + if( compat_file_write( fd, buffer, length ) ) { + compat_file_close( fd ); return 1; } - if( fclose( f ) ) { - ui_error( UI_ERROR_ERROR, "error closing '%s': %s", filename, - strerror( errno ) ); - return 1; - } + if( compat_file_close( fd ) ) return 1; return 0; }