/* Test al_ustr_get on invalid sequences. */ static void t22(void) { ALLEGRO_USTR_INFO info; const ALLEGRO_USTR *us; /* Empty string. */ al_set_errno(0); CHECK(al_ustr_get(al_ustr_empty_string(), 0) < 0); CHECK(al_get_errno() == ERANGE); /* 5-byte sequence. */ us = al_ref_cstr(&info, "\xf8\x88\x80\x80\x80"); al_set_errno(0); CHECK(al_ustr_get(us, 0) < 0); CHECK(al_get_errno() == EILSEQ); /* Start in trail byte. */ us = al_ref_cstr(&info, "ð"); al_set_errno(0); CHECK(al_ustr_get(us, 1) < 0); CHECK(al_get_errno() == EILSEQ); /* Truncated 3-byte sequence. */ us = al_ref_cstr(&info, "\xEF\xBF"); al_set_errno(0); CHECK(al_ustr_get(us, 0) < 0); CHECK(al_get_errno() == EILSEQ); }
static ALLEGRO_PATH *_unix_find_home(void) { char *home_env = getenv("HOME"); if (!home_env || home_env[0] == '\0') { /* since HOME isn't set, we have to ask libc for the info */ /* get user id */ uid_t uid = getuid(); /* grab user information */ struct passwd *pass = getpwuid(uid); if (!pass) { al_set_errno(errno); return NULL; } if (pass->pw_dir) { /* hey, we got our home directory */ return al_create_path_for_directory(pass->pw_dir); } al_set_errno(ENOENT); return NULL; } else { return al_create_path_for_directory(home_env); } }
/* Function: al_fopen_fd */ ALLEGRO_FILE *al_fopen_fd(int fd, const char *mode) { ALLEGRO_FILE *f; USERDATA *userdata; FILE *fp; userdata = al_malloc(sizeof(USERDATA)); if (!userdata) return NULL; /* The fd should remain open if this function fails in any way, * so delay the fdopen() call to last. */ userdata->fp = NULL; userdata->errnum = 0; f = al_create_file_handle(&_al_file_interface_stdio, userdata); if (!f) { al_free(userdata); return NULL; } fp = fdopen(fd, mode); if (!fp) { al_set_errno(errno); al_fclose(f); return NULL; } userdata->fp = fp; return f; }
/* Function: al_ustr_rfind_chr */ int al_ustr_rfind_chr(const ALLEGRO_USTR *us, int end_pos, int32_t c) { char encc[4]; size_t sizec; struct _al_tagbstring enctb; int rc; /* Fast path for ASCII characters. */ if (c < 128) { rc = _al_bstrrchrp(us, c, end_pos - 1); return (rc == _AL_BSTR_ERR) ? -1 : rc; } /* Non-ASCII. We can simply encode the character into a string and search * for that. */ sizec = al_utf8_encode(encc, c); if (!sizec) { al_set_errno(EINVAL); return -1; /* error */ } _al_blk2tbstr(enctb, encc, sizec); rc = _al_binstrr(us, end_pos - sizec, &enctb); return (rc == _AL_BSTR_ERR) ? -1 : rc; }
/* Function: al_open_memfile */ ALLEGRO_FILE *al_open_memfile(void *mem, int64_t size, const char *mode) { ALLEGRO_FILE *memfile; ALLEGRO_FILE_MEMFILE *userdata = NULL; ASSERT(mem); ASSERT(size > 0); userdata = al_malloc(sizeof(ALLEGRO_FILE_MEMFILE)); if (!userdata) { al_set_errno(ENOMEM); return NULL; } memset(userdata, 0, sizeof(*userdata)); userdata->size = size; userdata->pos = 0; userdata->mem = mem; userdata->readable = strchr(mode, 'r') || strchr(mode, 'R'); userdata->writable = strchr(mode, 'w') || strchr(mode, 'W'); memfile = al_create_file_handle(&memfile_vtable, userdata); if (!memfile) { al_free(userdata); } return memfile; }
static void *file_stdio_fopen(const char *path, const char *mode) { FILE *fp; USERDATA *userdata; ALLEGRO_DEBUG("opening %s %s\n", path, mode); #ifdef ALLEGRO_WINDOWS { wchar_t *wpath = _al_win_utf8_to_utf16(path); wchar_t *wmode = _al_win_utf8_to_utf16(mode); fp = _wfopen(wpath, wmode); al_free(wpath); al_free(wmode); } #else fp = fopen(path, mode); #endif if (!fp) { al_set_errno(errno); return NULL; } userdata = al_malloc(sizeof(USERDATA)); if (!userdata) { fclose(fp); return NULL; } userdata->fp = fp; userdata->errnum = 0; return userdata; }
static off_t curl_file_fsize(ALLEGRO_FILE *f) { /* Not implemented. */ (void)f; al_set_errno(ENOSYS); return -1; }
static bool file_stdio_fseek(ALLEGRO_FILE *f, int64_t offset, int whence) { USERDATA *userdata = get_userdata(f); int rc; switch (whence) { case ALLEGRO_SEEK_SET: whence = SEEK_SET; break; case ALLEGRO_SEEK_CUR: whence = SEEK_CUR; break; case ALLEGRO_SEEK_END: whence = SEEK_END; break; } #if defined(ALLEGRO_HAVE_FSEEKO) rc = fseeko(userdata->fp, offset, whence); #elif defined(ALLEGRO_HAVE_FSEEKI64) rc = _fseeki64(userdata->fp, offset, whence); #else rc = fseek(userdata->fp, offset, whence); #endif if (rc == -1) { userdata->errnum = errno; al_set_errno(errno); return false; } return true; }
static off_t file_stdio_fsize(ALLEGRO_FILE *f) { int64_t old_pos; int64_t new_pos; old_pos = file_stdio_ftell(f); if (old_pos == -1) goto Error; if (!file_stdio_fseek(f, 0, ALLEGRO_SEEK_END)) goto Error; new_pos = file_stdio_ftell(f); if (new_pos == -1) goto Error; if (!file_stdio_fseek(f, old_pos, ALLEGRO_SEEK_SET)) goto Error; return new_pos; Error: al_set_errno(errno); return -1; }
static bool file_stdio_fseek(ALLEGRO_FILE *f, int64_t offset, int whence) { FILE *fp = get_fp(f); int rc; switch (whence) { case ALLEGRO_SEEK_SET: whence = SEEK_SET; break; case ALLEGRO_SEEK_CUR: whence = SEEK_CUR; break; case ALLEGRO_SEEK_END: whence = SEEK_END; break; } #ifdef ALLEGRO_HAVE_FSEEKO rc = fseeko(fp, offset, whence); #else rc = fseek(fp, offset, whence); #endif if (rc == -1) { al_set_errno(errno); return false; } return true; }
static int64_t curl_file_ftell(ALLEGRO_FILE *f) { /* Not implemented. */ (void)f; al_set_errno(ENOSYS); return -1; }
static void *file_phys_fopen(const char *filename, const char *mode) { PHYSFS_file *phys; ALLEGRO_FILE_PHYSFS *fp; /* XXX handle '+' modes */ /* It might be worth adding a function to parse mode strings, to be * shared amongst these kinds of addons. */ if (streq(mode, "r") || streq(mode, "rb")) phys = PHYSFS_openRead(filename); else if (streq(mode, "w") || streq(mode, "wb")) phys = PHYSFS_openWrite(filename); else if (streq(mode, "a") || streq(mode, "ab")) phys = PHYSFS_openAppend(filename); else phys = NULL; if (!phys) { phys_set_errno(NULL); return NULL; } fp = al_malloc(sizeof(*fp)); if (!fp) { al_set_errno(ENOMEM); PHYSFS_close(phys); return NULL; } fp->phys = phys; fp->error_indicator = false; return fp; }
static size_t curl_file_fwrite(ALLEGRO_FILE *f, const void *ptr, size_t size) { (void)f; (void)ptr; (void)size; al_set_errno(EBADF); return 0; }
static int curl_file_fungetc(ALLEGRO_FILE *f, int c) { /* Not implemented. */ (void)f; (void)c; al_set_errno(ENOSYS); return -1; }
static int file_stdio_fungetc(ALLEGRO_FILE *f, int c) { int rc = ungetc(c, get_fp(f)); if (rc == EOF) { al_set_errno(errno); } return rc; }
static bool file_stdio_fflush(ALLEGRO_FILE *f) { FILE *fp = get_fp(f); if (fflush(fp) == EOF) { al_set_errno(errno); return false; } return true; }
static size_t file_stdio_fwrite(ALLEGRO_FILE *f, const void *ptr, size_t size) { size_t ret; ret = fwrite(ptr, 1, size, get_fp(f)); if (ret < size) { al_set_errno(errno); } return ret; }
static size_t file_stdio_fread(ALLEGRO_FILE *f, void *ptr, size_t size) { if (size == 1) { /* Optimise common case. */ int c = fgetc(get_fp(f)); if (c == EOF) { al_set_errno(errno); return 0; } *((char *)ptr) = (char)c; return 1; } else { size_t ret = fread(ptr, 1, size, get_fp(f)); if (ret < size) { al_set_errno(errno); } return ret; } }
/* Function: al_fopen_fd */ ALLEGRO_FILE *al_fopen_fd(int fd, const char *mode) { ALLEGRO_FILE *f; FILE *fp; /* The fd should remain open if this function fails in either way. */ fp = fdopen(fd, mode); if (!fp) { al_set_errno(errno); return NULL; } f = al_create_file_handle(&_al_file_interface_stdio, fp); if (!f) { al_set_errno(errno); return NULL; } return f; }
static bool file_stdio_fflush(ALLEGRO_FILE *f) { USERDATA *userdata = get_userdata(f); if (fflush(userdata->fp) == EOF) { userdata->errnum = errno; al_set_errno(errno); return false; } return true; }
static void phys_set_errno(ALLEGRO_FILE_PHYSFS *fp) { /* It might be worth mapping some common error strings from * PHYSFS_getLastError() onto errno values. There are no guarantees, * though. */ al_set_errno(-1); if (fp) { fp->error_indicator = true; } }
static int file_stdio_fungetc(ALLEGRO_FILE *f, int c) { USERDATA *userdata = get_userdata(f); int rc; rc = ungetc(c, userdata->fp); if (rc == EOF) { userdata->errnum = errno; al_set_errno(errno); } return rc; }
static ALLEGRO_FILE *file_stdio_fopen(const char *path, const char *mode) { FILE *fp; ALLEGRO_FILE_STDIO *f; fp = fopen(path, mode); if (!fp) { al_set_errno(ENOMEM); return NULL; } f = _AL_MALLOC(sizeof(*f)); if (!f) { al_set_errno(ENOMEM); fclose(fp); return NULL; } f->file.vtable = &_al_file_interface_stdio; f->fp = fp; return (ALLEGRO_FILE *)f; }
static size_t file_stdio_fwrite(ALLEGRO_FILE *f, const void *ptr, size_t size) { USERDATA *userdata = get_userdata(f); size_t ret; ret = fwrite(ptr, 1, size, userdata->fp); if (ret < size) { userdata->errnum = errno; al_set_errno(errno); } return ret; }
static size_t file_stdio_fread(ALLEGRO_FILE *f, void *ptr, size_t size) { USERDATA *userdata = get_userdata(f); if (size == 1) { /* Optimise common case. */ int c = fgetc(userdata->fp); if (c == EOF) { userdata->errnum = errno; al_set_errno(errno); return 0; } *((char *)ptr) = (char)c; return 1; } else { size_t ret = fread(ptr, 1, size, userdata->fp); if (ret < size) { userdata->errnum = errno; al_set_errno(errno); } return ret; } }
/* Function: al_fopen_fd */ ALLEGRO_FILE *al_fopen_fd(int fd, const char *mode) { ALLEGRO_FILE_STDIO *f; FILE *fp; /* The fd should remain open if this function fails in either way. */ f = _AL_MALLOC(sizeof(*f)); if (!f) { al_set_errno(ENOMEM); return NULL; } fp = fdopen(fd, mode); if (!fp) { al_set_errno(errno); _AL_FREE(f); return NULL; } f->file.vtable = &_al_file_interface_stdio; f->fp = fp; return (ALLEGRO_FILE *)f; }
static int64_t file_stdio_ftell(ALLEGRO_FILE *f) { FILE *fp = get_fp(f); int64_t ret; #ifdef ALLEGRO_HAVE_FTELLO ret = ftello(fp); #else ret = ftell(fp); #endif if (ret == -1) { al_set_errno(errno); } return ret; }
static bool curl_file_fseek(ALLEGRO_FILE *f, int64_t offset, int whence) { if (whence != ALLEGRO_SEEK_CUR || offset < 0) { /* Not implemented. */ al_set_errno(ENOSYS); return false; } while (offset > 0) { if (al_fgetc(f) == EOF) break; offset--; } return offset == 0; }
static int64_t file_stdio_ftell(ALLEGRO_FILE *f) { USERDATA *userdata = get_userdata(f); int64_t ret; #ifdef ALLEGRO_HAVE_FTELLO ret = ftello(userdata->fp); #else ret = ftell(userdata->fp); #endif if (ret == -1) { userdata->errnum = errno; al_set_errno(errno); } return ret; }
static bool file_stdio_fclose(ALLEGRO_FILE *f) { USERDATA *userdata = get_userdata(f); bool ret; if (userdata->fp == NULL) { /* This can happen in the middle of al_fopen_fd. */ ret = true; } else if (fclose(userdata->fp) == 0) { ret = true; } else { al_set_errno(errno); ret = false; } al_free(userdata); return ret; }