mame/src/osd/sdl/sdlfile.c
Couriersud 10bee5ce78 The return of the "misc"
- Added sdlmisc_<targetos>.c again. This was necessary since
  certain tools create stubs for e.g. osd_break_into_debugger.
  If we do not have this in a separate file, the link stage may
  break.
- Applied OS/2 patch [Credit: KO Myung-Hun]
- Cleaned up #includes. Removed stdlib.h were possible.
- More malloc to osd_malloc rename.
- SDL monitor modes are read now when they are needed. This is now consistent across platforms.
2010-01-21 22:54:49 +00:00

497 lines
12 KiB
C

//============================================================
//
// fileio.c - SDL file access functions
//
// Copyright (c) 1996-2010, Nicola Salmoria and the MAME Team.
// Visit http://mamedev.org for licensing and usage restrictions.
//
// SDLMAME by Olivier Galibert and R. Belmont
//
//============================================================
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#ifdef SDLMAME_LINUX
#define __USE_LARGEFILE64
#endif
#ifndef SDLMAME_BSD
#ifdef _XOPEN_SOURCE
#undef _XOPEN_SOURCE
#endif
#define _XOPEN_SOURCE 500
#endif
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
// MAME headers
#include "osdcore.h"
#include "sdlos.h"
#if defined(SDLMAME_WIN32) || defined(SDLMAME_OS2)
#define PATHSEPCH '\\'
#define INVPATHSEPCH '/'
#else
#define PATHSEPCH '/'
#define INVPATHSEPCH '\\'
#endif
static UINT32 create_path_recursive(char *path);
#define NO_ERROR (0)
//============================================================
// TYPE DEFINITIONS
//============================================================
struct _osd_file
{
int handle;
char filename[1];
};
//============================================================
// error_to_file_error
// (does filling this out on non-Windows make any sense?)
//============================================================
static file_error error_to_file_error(UINT32 error)
{
switch (error)
{
case ENOENT:
case ENOTDIR:
return FILERR_NOT_FOUND;
case EACCES:
case EROFS:
#ifndef SDLMAME_WIN32
case ETXTBSY:
#endif
case EEXIST:
case EPERM:
case EISDIR:
case EINVAL:
return FILERR_ACCESS_DENIED;
case ENFILE:
case EMFILE:
return FILERR_TOO_MANY_FILES;
default:
return FILERR_FAILURE;
}
}
//============================================================
// osd_open
//============================================================
file_error osd_open(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize)
{
UINT32 access;
const char *src;
char *dst;
#if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2)
struct stat st;
#else
struct stat64 st;
#endif
char *tmpstr, *envstr;
int i, j;
file_error filerr = FILERR_NONE;
tmpstr = NULL;
// allocate a file object, plus space for the converted filename
*file = (osd_file *) osd_malloc(sizeof(**file) + sizeof(char) * strlen(path));
if (*file == NULL)
{
filerr = FILERR_OUT_OF_MEMORY;
goto error;
}
// convert the path into something compatible
dst = (*file)->filename;
for (src = path; *src != 0; src++)
*dst++ = (*src == INVPATHSEPCH) ? PATHSEPCH : *src;
*dst++ = 0;
// select the file open modes
if (openflags & OPEN_FLAG_WRITE)
{
access = (openflags & OPEN_FLAG_READ) ? O_RDWR : O_WRONLY;
access |= (openflags & OPEN_FLAG_CREATE) ? (O_CREAT | O_TRUNC) : 0;
}
else if (openflags & OPEN_FLAG_READ)
{
access = O_RDONLY;
}
else
{
filerr = FILERR_INVALID_ACCESS;
goto error;
}
tmpstr = (char *) osd_malloc(strlen((*file)->filename)+1);
strcpy(tmpstr, (*file)->filename);
// does path start with an environment variable?
if (tmpstr[0] == '$')
{
char *envval;
envstr = (char *) osd_malloc(strlen(tmpstr)+1);
strcpy(envstr, tmpstr);
i = 0;
while (envstr[i] != PATHSEPCH && envstr[i] != 0 && envstr[i] != '.')
{
i++;
}
envstr[i] = '\0';
envval = osd_getenv(&envstr[1]);
if (envval != NULL)
{
j = strlen(envval) + strlen(tmpstr) + 1;
osd_free(tmpstr);
tmpstr = (char *) osd_malloc(j);
// start with the value of $HOME
strcpy(tmpstr, envval);
// replace the null with a path separator again
envstr[i] = PATHSEPCH;
// append it
strcat(tmpstr, &envstr[i]);
}
else
fprintf(stderr, "Warning: osd_open environment variable %s not found.\n", envstr);
osd_free(envstr);
}
#if defined(SDLMAME_WIN32) || defined(SDLMAME_OS2)
access |= O_BINARY;
#endif
// attempt to open the file
#if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2)
(*file)->handle = open(tmpstr, access, 0666);
#else
(*file)->handle = open64(tmpstr, access, 0666);
#endif
if ((*file)->handle == -1)
{
// create the path if necessary
if ((openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS))
{
char *pathsep = strrchr(tmpstr, PATHSEPCH);
if (pathsep != NULL)
{
int error;
// create the path up to the file
*pathsep = 0;
error = create_path_recursive(tmpstr);
*pathsep = PATHSEPCH;
// attempt to reopen the file
if (error == NO_ERROR)
{
#if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2)
(*file)->handle = open(tmpstr, access, 0666);
#else
(*file)->handle = open64(tmpstr, access, 0666);
#endif
}
}
}
// if we still failed, clean up and osd_free
if ((*file)->handle == -1)
{
osd_free(*file);
*file = NULL;
osd_free(tmpstr);
return error_to_file_error(errno);
}
}
// get the file size
#if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2)
fstat((*file)->handle, &st);
#else
fstat64((*file)->handle, &st);
#endif
*filesize = (UINT64)st.st_size;
error:
// cleanup
if (filerr != FILERR_NONE && *file != NULL)
{
osd_free(*file);
*file = NULL;
}
if (tmpstr)
osd_free(tmpstr);
return filerr;
}
//============================================================
// osd_read
//============================================================
file_error osd_read(osd_file *file, void *buffer, UINT64 offset, UINT32 count, UINT32 *actual)
{
ssize_t result;
#if defined(SDLMAME_DARWIN) || defined(SDLMAME_BSD)
result = pread(file->handle, buffer, count, offset);
if (result < 0)
#elif defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_OS2)
lseek(file->handle, (UINT32)offset&0xffffffff, SEEK_SET);
result = read(file->handle, buffer, count);
if (result < 0)
#elif defined(SDLMAME_UNIX)
result = pread64(file->handle, buffer, count, offset);
if (result < 0)
#else
#error Unknown SDL SUBARCH!
#endif
return error_to_file_error(errno);
if (actual != NULL)
*actual = result;
return FILERR_NONE;
}
//============================================================
// osd_write
//============================================================
file_error osd_write(osd_file *file, const void *buffer, UINT64 offset, UINT32 count, UINT32 *actual)
{
UINT32 result;
#if defined(SDLMAME_DARWIN) || defined(SDLMAME_BSD)
result = pwrite(file->handle, buffer, count, offset);
if (!result)
#elif defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_OS2)
lseek(file->handle, (UINT32)offset&0xffffffff, SEEK_SET);
result = write(file->handle, buffer, count);
if (!result)
#elif defined(SDLMAME_UNIX)
result = pwrite64(file->handle, buffer, count, offset);
if (!result)
#else
#error Unknown SDL SUBARCH!
#endif
return error_to_file_error(errno);
if (actual != NULL)
*actual = result;
return FILERR_NONE;
}
//============================================================
// osd_close
//============================================================
file_error osd_close(osd_file *file)
{
// close the file handle and free the file structure
close(file->handle);
osd_free(file);
return FILERR_NONE;
}
//============================================================
// osd_rmfile
//============================================================
file_error osd_rmfile(const char *filename)
{
if (unlink(filename) == -1)
{
return error_to_file_error(errno);
}
return FILERR_NONE;
}
//============================================================
// create_path_recursive
//============================================================
static UINT32 create_path_recursive(char *path)
{
char *sep = strrchr(path, PATHSEPCH);
UINT32 filerr;
struct stat st;
// if there's still a separator, and it's not the root, nuke it and recurse
if (sep != NULL && sep > path && sep[0] != ':' && sep[-1] != PATHSEPCH)
{
*sep = 0;
filerr = create_path_recursive(path);
*sep = PATHSEPCH;
if (filerr != NO_ERROR)
return filerr;
}
// if the path already exists, we're done
if (!stat(path, &st))
return NO_ERROR;
// create the path
#ifdef SDLMAME_WIN32
if (mkdir(path) != 0)
#else
if (mkdir(path, 0777) != 0)
#endif
return error_to_file_error(errno);
return NO_ERROR;
}
//============================================================
// osd_get_physical_drive_geometry
//============================================================
int osd_get_physical_drive_geometry(const char *filename, UINT32 *cylinders, UINT32 *heads, UINT32 *sectors, UINT32 *bps)
{
return FALSE; // no, no way, huh-uh, forget it
}
/*============================================================ */
/* osd_is_path_separator */
/*============================================================ */
static int osd_is_path_separator(char c)
{
return (c == '/') || (c == '\\');
}
/*============================================================ */
/* osd_is_absolute_path */
/*============================================================ */
int osd_is_absolute_path(const char *path)
{
int result;
if (osd_is_path_separator(path[0]))
result = TRUE;
#if !defined(SDLMAME_WIN32) && !defined(SDLMAME_OS2)
else if (path[0] == '.')
result = TRUE;
#else
#ifndef UNDER_CE
else if (*path && path[1] == ':')
result = TRUE;
#endif
#endif
else
result = FALSE;
return result;
}
/* not used anywhere */
#if 0
//============================================================
// osd_mkdir
//============================================================
file_error osd_mkdir(const char *dir)
{
#ifdef SDLMAME_WIN32
if (mkdir(dir) != 0)
#else
if (mkdir(dir, 0666) != 0)
#endif
{
return error_to_file_error(errno);
}
return FILERR_NONE;
}
//============================================================
// osd_rmdir
//============================================================
static file_error osd_rmdir(const char *dir)
{
if (rmdir(dir) != 0)
{
return error_to_file_error(errno);
}
return FILERR_NONE;
}
#endif
// these are MESS specific - DO NOT TOUCH!!@!
#ifdef MESS
//============================================================
// osd_copyfile
// FIXME: this will not work with blanks in filename ...
//============================================================
file_error osd_copyfile(const char *destfile, const char *srcfile)
{
char command[1024];
sprintf(command, "cp %s %s\n", srcfile, destfile);
system(command);
return FILERR_NONE;
}
//============================================================
// osd_stat
//============================================================
#ifndef SDLMAME_WIN32
osd_directory_entry *osd_stat(const char *path)
{
int err;
osd_directory_entry *result = NULL;
#if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2)
struct stat st;
#else
struct stat64 st;
#endif
#if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2)
err = stat(path, &st);
#else
err = stat64(path, &st);
#endif
if( err == -1) return NULL;
// create an osd_directory_entry; be sure to make sure that the caller can
// free all resources by just freeing the resulting osd_directory_entry
result = (osd_directory_entry *) osd_malloc(sizeof(*result) + strlen(path) + 1);
strcpy(((char *) result) + sizeof(*result), path);
result->name = ((char *) result) + sizeof(*result);
result->type = S_ISDIR(st.st_mode) ? ENTTYPE_DIR : ENTTYPE_FILE;
result->size = (UINT64)st.st_size;
return result;
}
#endif
#endif