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_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; } }
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; }
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; }
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; }
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; } }
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; } }
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; }