mirror of
https://git.code.sf.net/p/fuse-emulator/fuse
synced 2026-01-27 01:41:34 +03:00
Factor out low-level file handling into compat/<os>/file.c; needed for Wii port.
Legacy-ID: 3687
This commit is contained in:
27
compat.h
27
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 <stdlib.h>
|
||||
|
||||
#include <utils.h>
|
||||
|
||||
/* 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 */
|
||||
|
||||
@@ -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@
|
||||
|
||||
@@ -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@
|
||||
|
||||
@@ -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@
|
||||
|
||||
112
compat/unix/file.c
Normal file
112
compat/unix/file.c
Normal file
@@ -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 <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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 );
|
||||
}
|
||||
34
compat/wii/Makefile.am
Normal file
34
compat/wii/Makefile.am
Normal file
@@ -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@
|
||||
95
compat/wii/file.c
Normal file
95
compat/wii/file.c
Normal file
@@ -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 <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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 );
|
||||
}
|
||||
@@ -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@
|
||||
|
||||
@@ -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/<os>/file.c;
|
||||
needed for Wii port.
|
||||
|
||||
10
if1.c
10
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;
|
||||
}
|
||||
|
||||
|
||||
70
utils.c
70
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 <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_LIBGEN_H
|
||||
#include <libgen.h>
|
||||
#endif /* #ifdef HAVE_LIBGEN_H */
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <ui/ui.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user