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; }
file_error osd_write(osd_file *file, const void *buffer, UINT64 offset, UINT32 length, UINT32 *actual) { #ifdef ANDROID UINT32 result; result = pwrite(file->handle, buffer, length, offset); if (!result) return error_to_file_error(errno); if (actual != NULL) *actual = result; return FILERR_NONE; #else size_t count; // seek to the new location; note that most fseek implementations are limited to 32 bits fseek((FILE *)file, offset, SEEK_SET); // perform the write count = fwrite(buffer, 1, length, (FILE *)file); if (actual != NULL) *actual = count; return FILERR_NONE; #endif }
file_error osd_write(osd_file *file, const void *buffer, UINT64 offset, UINT32 count, UINT32 *actual) { UINT32 result; switch (file->type) { case SDLFILE_FILE: #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) || defined(__CELLOS_LV2__) 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; break; default: return FILERR_FAILURE; } }
file_error osd_rmfile(const char *filename) { if (unlink(filename) == -1) { return error_to_file_error(errno); } return FILERR_NONE; }
file_error sdl_read_socket(osd_file *file, void *buffer, UINT64 offset, UINT32 count, UINT32 *actual) { #ifndef SDLMAME_WIN32 ssize_t result; char line[80]; struct timeval timeout; fd_set readfds; FD_ZERO(&readfds); FD_SET(file->handle, &readfds); timeout.tv_sec = timeout.tv_usec = 0; if (select(file->handle + 1, &readfds, NULL, NULL, &timeout) < 0) { sprintf(line, "%s : %s : %d ", __func__, __FILE__, __LINE__); perror(line); return error_to_file_error(errno); } else if (FD_ISSET(file->handle, &readfds)) { result = read(file->handle, buffer, count); } else { return FILERR_FAILURE; } if (result < 0) { return error_to_file_error(errno); } if (actual != NULL ) { *actual = result; } #endif return FILERR_NONE; }
file_error osd_truncate(osd_file *file, UINT64 offset) { UINT32 result; switch (file->type) { case SDLFILE_FILE: result = ftruncate(file->handle, offset); if (!result) return error_to_file_error(errno); return FILERR_NONE; default: return FILERR_FAILURE; } }
file_error sdl_write_ptty(osd_file *file, const void *buffer, UINT64 offset, UINT32 count, UINT32 *actual) { UINT32 result; result = write(file->handle, buffer, count); if (result < 0) { return error_to_file_error(errno); } if (actual != NULL ) { *actual = result; } return FILERR_NONE; }
file_error sdl_read_ptty(osd_file *file, void *buffer, UINT64 offset, UINT32 count, UINT32 *actual) { ssize_t result; result = read(file->handle, buffer, count); if (result < 0) { return error_to_file_error(errno); } if (actual != NULL ) { *actual = result; } return FILERR_NONE; }
file_error sdl_write_socket(osd_file *file, const void *buffer, UINT64 offset, UINT32 count, UINT32 *actual) { #ifndef SDLMAME_WIN32 ssize_t result; result = write(file->handle, buffer, count); if (result < 0) { return error_to_file_error(errno); } if (actual != NULL ) { *actual = result; } #endif return FILERR_NONE; }
file_error osd_read(osd_file *file, void *buffer, UINT64 offset, UINT32 count, UINT32 *actual) { ssize_t result; switch (file->type) { case SDLFILE_FILE: #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; break; case SDLFILE_SOCKET: return sdl_read_socket(file, buffer, offset, count, actual); break; case SDLFILE_PTTY: return sdl_read_ptty(file, buffer, offset, count, actual); break; default: return FILERR_FAILURE; } }
file_error osd_write(osd_file *file, const void *buffer, UINT64 offset, UINT32 count, UINT32 *actual) { UINT32 result; switch (file->type) { case SDLFILE_FILE: #if defined(__MACH__) || defined(SDLMAME_BSD) result = pwrite(file->handle, buffer, count, offset); if (!result) #elif defined(WIN32) || defined(SDLMAME_NO64BITIO) || defined(ANDROID) || 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; break; /* case SDLFILE_SOCKET: return sdl_write_socket(file, buffer, offset, count, actual); break; case SDLFILE_PTTY: return sdl_write_ptty(file, buffer, offset, count, actual); break; */ default: return FILERR_FAILURE; } }
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) { 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; }
file_error sdl_read_socket(osd_file *file, void *buffer, UINT64 offset, UINT32 count, UINT32 *actual) { #if (!defined(SDLMAME_WIN32)) && (!defined(SDLMAME_EMSCRIPTEN)) ssize_t result; char line[80]; struct timeval timeout; fd_set readfds; FD_ZERO(&readfds); FD_SET(file->socket, &readfds); timeout.tv_sec = timeout.tv_usec = 0; if (select(file->socket + 1, &readfds, NULL, NULL, &timeout) < 0) { sprintf(line, "%s : %s : %d ", __func__, __FILE__, __LINE__); perror(line); return error_to_file_error(errno); } else if (FD_ISSET(file->socket, &readfds)) { if (file->handle == -1) { // connected socket result = read(file->socket, buffer, count); } else { // listening socket int AcceptSocket; AcceptSocket = accept(file->socket, NULL, NULL); if (AcceptSocket < 0) { return FILERR_FAILURE; } close(file->socket); file->socket = AcceptSocket; file->handle = -1; if (actual != NULL ) { *actual = 0; } return FILERR_NONE; } } else { return FILERR_FAILURE; } if (result < 0) { return error_to_file_error(errno); } if (actual != NULL ) { *actual = result; } #endif return FILERR_NONE; }