Example #1
0
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;
}
Example #2
0
osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, ptr &file, std::uint64_t &filesize)
{
	std::string dst;
	if (posix_check_socket_path(path))
		return posix_open_socket(path, openflags, file, filesize);
	else if (posix_check_ptty_path(path))
		return posix_open_ptty(openflags, file, filesize, dst);

	// select the file open modes
	int access;
	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
	{
		return error::INVALID_ACCESS;
	}
#if defined(WIN32)
	access |= O_BINARY;
#endif

	// convert the path into something compatible
	dst = path;
#if defined(WIN32)
	for (auto it = dst.begin(); it != dst.end(); ++it)
		*it = (INVPATHSEPCH == *it) ? PATHSEPCH : *it;
#endif
	osd_subst_env(dst, dst);

	// attempt to open the file
	int fd = -1;
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__HAIKU__) || defined(WIN32) || defined(SDLMAME_NO64BITIO) || defined(__ANDROID__)
	fd = ::open(dst.c_str(), access, 0666);
#else
	fd = ::open64(dst.c_str(), access, 0666);
#endif

	if (fd < 0)
	{
		// create the path if necessary
		if ((openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS))
		{
			auto const pathsep = dst.rfind(PATHSEPCH);
			if (pathsep != std::string::npos)
			{
				// create the path up to the file
				osd_file::error const error = create_path_recursive(dst.substr(0, pathsep));

				// attempt to reopen the file
				if (error == osd_file::error::NONE)
				{
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__HAIKU__) || defined(WIN32) || defined(SDLMAME_NO64BITIO) || defined(__ANDROID__)
					fd = ::open(dst.c_str(), access, 0666);
#else
					fd = ::open64(dst.c_str(), access, 0666);
#endif
				}
			}
		}

		// if we still failed, clean up and osd_free
		if (fd < 0)
		{
			return errno_to_file_error(errno);
		}
	}

	// get the file size
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__HAIKU__) || defined(WIN32) || defined(SDLMAME_NO64BITIO) || defined(__ANDROID__)
	struct stat st;
	if (::fstat(fd, &st) < 0)
#else
	struct stat64 st;
	if (::fstat64(fd, &st) < 0)
#endif
	{
		int const error = errno;
		::close(fd);
		return errno_to_file_error(error);
	}
	filesize = std::uint64_t(std::make_unsigned_t<decltype(st.st_size)>(st.st_size));

	try
	{
		file = std::make_unique<posix_osd_file>(fd);
		return error::NONE;
	}
	catch (...)
	{
		::close(fd);
		return error::OUT_OF_MEMORY;
	}
}
Example #3
0
file_error osd_open(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize)
{
    UINT32 access;
    const char *src;
    char *dst;
    struct stat st;

    char *tmpstr, *envstr;
    int i, j;
    file_error filerr = FILERR_NONE;

#ifdef ANDROID
    __android_log_print(ANDROID_LOG_INFO, "libSDL", "Leo %s",path);
#endif

    tmpstr = NULL;

    // allocate a file object, plus space for the converted filename
    *file = 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 = malloc(strlen((*file)->filename)+1);
    strcpy(tmpstr, (*file)->filename);

    // does path start with an environment variable?
    if (tmpstr[0] == '$')
    {
        char *envval;
        envstr = malloc(strlen(tmpstr)+1);

        strcpy(envstr, tmpstr);

        i = 0;
        while (envstr[i] != PATHSEPCH && envstr[i] != 0 && envstr[i] != '.')
        {
            i++;
        }

        envstr[i] = '\0';

        envval = getenv(&envstr[1]);
        if (envval)
        {
            j = strlen(envval) + strlen(tmpstr) + 1;
            free(tmpstr);
            tmpstr = 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: Environment variable %s not found.\n", envstr);
        free(envstr);
    }

    // attempt to open the file
    (*file)->handle = open(tmpstr, access, 0666);

    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)
                {
                    (*file)->handle = open(tmpstr, access, 0666);
                }
            }
        }

        // if we still failed, clean up and free
        if ((*file)->handle == -1)
        {
            free(*file);
            *file = NULL;
            free(tmpstr);
            return error_to_file_error(errno);
        }
    }

    // get the file size
    fstat((*file)->handle, &st);

    *filesize = (UINT64)st.st_size;
#ifdef ANDROID
    __android_log_print(ANDROID_LOG_INFO, "libSDL", "Leido %s %uld",path,(unsigned int)filesize);
#endif
error:
    // cleanup
    if (filerr != FILERR_NONE && *file != NULL)
    {
        free(*file);
        *file = NULL;
    }
    if (tmpstr)
        free(tmpstr);
    return filerr;
}
Example #4
0
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) || defined(SDLMAME_HAIKU)
	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_array(sizeof(**file) + sizeof(char) * strlen(path));
	if (*file == NULL)
	{
		filerr = FILERR_OUT_OF_MEMORY;
		goto error;
	}

	if (sdl_check_socket_path(path))
	{
		(*file)->type = SDLFILE_SOCKET;
		filerr = sdl_open_socket(path, openflags, file, filesize);
		goto error;
	}

	if (strlen(sdlfile_ptty_identifier) > 0 && strncmp(path, sdlfile_ptty_identifier, strlen(sdlfile_ptty_identifier)) == 0)
	{
		(*file)->type = SDLFILE_PTTY;
		filerr = sdl_open_ptty(path, openflags, file, filesize);
		goto error;
	}

	(*file)->type = SDLFILE_FILE;

	// 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_array(strlen((*file)->filename)+1);
	strcpy(tmpstr, (*file)->filename);

	// does path start with an environment variable?
	if (tmpstr[0] == '$')
	{
		envstr = (char *) osd_malloc_array(strlen(tmpstr)+1);

		strcpy(envstr, tmpstr);

		i = 0;
		while (envstr[i] != PATHSEPCH && envstr[i] != 0 && envstr[i] != '.')
		{
			i++;
		}

		envstr[i] = '\0';

		const char *envval = osd_getenv(&envstr[1]);
		if (envval != NULL)
		{
			j = strlen(envval) + strlen(tmpstr) + 1;
			osd_free(tmpstr);
			tmpstr = (char *) osd_malloc_array(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) || defined(SDLMAME_HAIKU)
	(*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) || defined(SDLMAME_HAIKU)
					(*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) || defined(SDLMAME_HAIKU)
	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;
}
Example #5
0
file_error osd_open(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize)
{
	DWORD disposition, access, sharemode;
	file_error filerr = FILERR_NONE;
	const TCHAR *src;
	DWORD upper;
	TCHAR *t_path;
	TCHAR *dst;

	// convert path to TCHAR
	t_path = tstring_from_utf8(path);
	if (t_path == NULL)
	{
		filerr = FILERR_OUT_OF_MEMORY;
		goto error;
	}

	// allocate a file object, plus space for the converted filename
	*file = (osd_file *)malloc(sizeof(**file) + sizeof(TCHAR) * _tcslen(t_path));
	if (*file == NULL)
	{
		filerr = FILERR_OUT_OF_MEMORY;
		goto error;
	}

	// convert the path into something Windows compatible
	dst = (*file)->filename;
	for (src = t_path; *src != 0; src++)
		*dst++ = *src;//(*src == '/') ? '\\' : *src;
	*dst++ = 0;

	// select the file open modes
	if (openflags & OPEN_FLAG_WRITE)
	{
		disposition = (!is_path_to_physical_drive(path) && (openflags & OPEN_FLAG_CREATE)) ? CREATE_ALWAYS : OPEN_EXISTING;
		access = (openflags & OPEN_FLAG_READ) ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_WRITE;
		sharemode = 0;
	}
	else if (openflags & OPEN_FLAG_READ)
	{
		disposition = OPEN_EXISTING;
		access = GENERIC_READ;
		sharemode = FILE_SHARE_READ;
	}
	else
	{
		filerr = FILERR_INVALID_ACCESS;
		goto error;
	}

	// attempt to open the file
	(*file)->handle = CreateFile((*file)->filename, access, sharemode, NULL, disposition, 0, NULL);
	if ((*file)->handle == INVALID_HANDLE_VALUE)
	{
		DWORD error = GetLastError();

		// create the path if necessary
		if (error == ERROR_PATH_NOT_FOUND && (openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS))
		{
			TCHAR *pathsep = _tcsrchr((*file)->filename, '\\');
			if (pathsep != NULL)
			{
				// create the path up to the file
				*pathsep = 0;
				error = create_path_recursive((*file)->filename);
				*pathsep = '\\';

				// attempt to reopen the file
				if (error == NO_ERROR)
					(*file)->handle = CreateFile((*file)->filename, access, sharemode, NULL, disposition, 0, NULL);
			}
		}

		// if we still failed, clean up and free
		if ((*file)->handle == INVALID_HANDLE_VALUE)
		{
			filerr = win_error_to_file_error(error);
			goto error;
		}
	}

	// get the file size
	*filesize = GetFileSize((*file)->handle, &upper);
	*filesize |= (UINT64)upper << 32;

error:
	// cleanup
	if (filerr != FILERR_NONE && *file != NULL)
	{
		free(*file);
		*file = NULL;
	}
	free(t_path);
	return filerr;
}
Example #6
0
osd_file::error osd_file::open(std::string const &orig_path, UINT32 openflags, ptr &file, std::uint64_t &filesize)
{
    std::string path;
    try {
        osd_subst_env(path, orig_path);
    }
    catch (...) {
        return error::OUT_OF_MEMORY;
    }

    if (win_check_socket_path(path))
        return win_open_socket(path, openflags, file, filesize);
    else if (win_check_ptty_path(path))
        return win_open_ptty(path, openflags, file, filesize);

    // convert path to TCHAR
    TCHAR *t_path = tstring_from_utf8(path.c_str());
    osd_disposer<TCHAR> t_path_disposer(t_path);
    if (!t_path)
        return error::OUT_OF_MEMORY;

    // convert the path into something Windows compatible
    for (TCHAR *src = t_path; *src != 0; src++)
        *src = /* ('/' == *src) ? '\\' : */ *src;

    // select the file open modes
    DWORD disposition, access, sharemode;
    if (openflags & OPEN_FLAG_WRITE)
    {
        disposition = (!is_path_to_physical_drive(path.c_str()) && (openflags & OPEN_FLAG_CREATE)) ? CREATE_ALWAYS : OPEN_EXISTING;
        access = (openflags & OPEN_FLAG_READ) ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_WRITE;
        sharemode = FILE_SHARE_READ;
    }
    else if (openflags & OPEN_FLAG_READ)
    {
        disposition = OPEN_EXISTING;
        access = GENERIC_READ;
        sharemode = FILE_SHARE_READ;
    }
    else
    {
        return error::INVALID_ACCESS;
    }

    // attempt to open the file
    HANDLE h = CreateFile(t_path, access, sharemode, nullptr, disposition, 0, nullptr);
    if (INVALID_HANDLE_VALUE == h)
    {
        DWORD err = GetLastError();
        // create the path if necessary
        if ((ERROR_PATH_NOT_FOUND == err) && (openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS))
        {
            TCHAR *pathsep = _tcsrchr(t_path, '\\');
            if (pathsep != nullptr)
            {
                // create the path up to the file
                *pathsep = 0;
                err = create_path_recursive(t_path);
                *pathsep = '\\';

                // attempt to reopen the file
                if (err == NO_ERROR)
                {
                    h = CreateFile(t_path, access, sharemode, nullptr, disposition, 0, nullptr);
                    err = GetLastError();
                }
            }
        }

        // if we still failed, clean up and free
        if (INVALID_HANDLE_VALUE == h)
            return win_error_to_file_error(err);
    }

    // get the file size
    DWORD upper, lower;
    lower = GetFileSize(h, &upper);
    if (INVALID_FILE_SIZE == lower)
    {
        DWORD const err = GetLastError();
        if (NO_ERROR != err)
        {
            CloseHandle(h);
            return win_error_to_file_error(err);
        }
    }

    try
    {
        file = std::make_unique<win_osd_file>(h);
        filesize = (std::uint64_t(upper) << 32) | lower;
        return error::NONE;
    }
    catch (...)
    {
        CloseHandle(h);
        return error::OUT_OF_MEMORY;
    }
}
Example #7
0
osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, ptr &file, std::uint64_t &filesize)
{
    std::string path;
    try {
        osd_subst_env(path, orig_path);
    }
    catch (...) {
        return error::OUT_OF_MEMORY;
    }

    if (win_check_socket_path(path))
        return win_open_socket(path, openflags, file, filesize);
    else if (win_check_ptty_path(path))
        return win_open_ptty(path, openflags, file, filesize);

    // convert path to TCHAR
    osd::text::tstring t_path = osd::text::to_tstring(path);

    // convert the path into something Windows compatible (the actual interesting part appears
    // to have been commented out???)
    for (auto iter = t_path.begin(); iter != t_path.end(); iter++)
        *iter = /* ('/' == *iter) ? '\\' : */ *iter;

    // select the file open modes
    DWORD disposition, access, sharemode;
    if (openflags & OPEN_FLAG_WRITE)
    {
        disposition = (!is_path_to_physical_drive(path.c_str()) && (openflags & OPEN_FLAG_CREATE)) ? CREATE_ALWAYS : OPEN_EXISTING;
        access = (openflags & OPEN_FLAG_READ) ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_WRITE;
        sharemode = FILE_SHARE_READ;
    }
    else if (openflags & OPEN_FLAG_READ)
    {
        disposition = OPEN_EXISTING;
        access = GENERIC_READ;
        sharemode = FILE_SHARE_READ;
    }
    else
    {
        return error::INVALID_ACCESS;
    }

    // attempt to open the file
    HANDLE h = CreateFile(t_path.c_str(), access, sharemode, nullptr, disposition, 0, nullptr);
    if (INVALID_HANDLE_VALUE == h)
    {
        DWORD err = GetLastError();
        // create the path if necessary
        if ((ERROR_PATH_NOT_FOUND == err) && (openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS))
        {
            auto pathsep = t_path.rfind('\\');
            if (pathsep != decltype(t_path)::npos)
            {
                // create the path up to the file
                t_path[pathsep] = 0;
                err = create_path_recursive(&t_path[0]);
                t_path[pathsep] = '\\';

                // attempt to reopen the file
                if (err == NO_ERROR)
                {
                    h = CreateFile(t_path.c_str(), access, sharemode, nullptr, disposition, 0, nullptr);
                    err = GetLastError();
                }
            }
        }

        // if we still failed, clean up and free
        if (INVALID_HANDLE_VALUE == h)
            return win_error_to_file_error(err);
    }

    // get the file size
    DWORD upper, lower;
    lower = GetFileSize(h, &upper);
    if (INVALID_FILE_SIZE == lower)
    {
        DWORD const err = GetLastError();
        if (NO_ERROR != err)
        {
            CloseHandle(h);
            return win_error_to_file_error(err);
        }
    }

    try
    {
        file = std::make_unique<win_osd_file>(h);
        filesize = (std::uint64_t(upper) << 32) | lower;
        return error::NONE;
    }
    catch (...)
    {
        CloseHandle(h);
        return error::OUT_OF_MEMORY;
    }
}
Example #8
0
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) || defined(__CELLOS_LV2__)
	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;
	}

	(*file)->type = SDLFILE_FILE;

	// 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);

	#if (defined(SDLMAME_WIN32) || defined(SDLMAME_OS2)) && !defined(__CELLOS_LV2__)
	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) || defined(__CELLOS_LV2__)
	(*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) || defined(__CELLOS_LV2__)
					(*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) || defined(__CELLOS_LV2__)
	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;
}