[Add] Support for non POSIX systems with open/read/write in packfile system

This commit is contained in:
Allanis 2013-02-23 19:21:13 +00:00
parent 5841d23f54
commit a296bd7aa0
4 changed files with 174 additions and 38 deletions

View File

@ -99,7 +99,7 @@ int main(int argc, char** argv) {
// See if the data file is valid. // See if the data file is valid.
if(pack_check(data)) { if(pack_check(data)) {
ERR("Data file '%s' not found", data); ERR("Data file '%s' not found", DATA);
WARN("You can specify what data file you want to use with '-d'"); WARN("You can specify what data file you want to use with '-d'");
WARN("See -h or -- help for more infoamtion."); WARN("See -h or -- help for more infoamtion.");
SDL_Quit(); SDL_Quit();

View File

@ -8,8 +8,9 @@
#include "pack.h" #include "pack.h"
#include "music.h" #include "music.h"
#define MUSIC_PLAYING (2<<0) #define MUSIC_STOPPED (1<<1)
#define MUSIC_KILL (9<<0) #define MUSIC_PLAYING (1<<2)
#define MUSIC_KILL (1<<9)
#define music_is(f) (music_state & f) #define music_is(f) (music_state & f)
#define music_set(f) (music_state |= f) #define music_set(f) (music_state |= f)
#define music_rm(f) (music_state ^= f) #define music_rm(f) (music_state ^= f)
@ -71,6 +72,7 @@ int music_thread(void* unused) {
// Main loop. // Main loop.
while(!music_is(MUSIC_KILL)) { while(!music_is(MUSIC_KILL)) {
if(music_is(MUSIC_PLAYING)) { if(music_is(MUSIC_PLAYING)) {
music_rm(MUSIC_STOPPED);
SDL_mutexP(music_vorbis_lock); // Lock the mutex. SDL_mutexP(music_vorbis_lock); // Lock the mutex.
SDL_mutexP(sound_lock); SDL_mutexP(sound_lock);
@ -113,6 +115,7 @@ int music_thread(void* unused) {
SDL_mutexV(sound_lock); SDL_mutexV(sound_lock);
SDL_mutexV(music_vorbis_lock); SDL_mutexV(music_vorbis_lock);
} }
music_set(MUSIC_STOPPED);
SDL_Delay(0); // We must not kill resources. SDL_Delay(0); // We must not kill resources.
} }
return 0; return 0;
@ -135,6 +138,10 @@ static int stream_loadBuffer(ALuint buffer) {
&section); // Current bitstream. &section); // Current bitstream.
if(result == 0) return 1; if(result == 0) return 1;
else if(result == OV_HOLE)
WARN("OGG: Vorbis hole detected in music!");
else if(result == OV_EBADLINK)
WARN("OGG: Invalid stream section or corrupt link in music!");
size += result; size += result;
if(size == BUFFER_SIZE) break; // Buffer is full. if(size == BUFFER_SIZE) break; // Buffer is full.
@ -148,7 +155,7 @@ static int stream_loadBuffer(ALuint buffer) {
int music_init(void) { int music_init(void) {
music_vorbis_lock = SDL_CreateMutex(); music_vorbis_lock = SDL_CreateMutex();
music_find(); music_find();
music_vorbis.file.fd = 0; // Indication that it's not loaded.. music_vorbis.file.end = 0; // Indication that it's not loaded..
SDL_mutexP(sound_lock); SDL_mutexP(sound_lock);
@ -235,7 +242,7 @@ static int music_find(void) {
static void music_free(void) { static void music_free(void) {
SDL_mutexP(music_vorbis_lock); SDL_mutexP(music_vorbis_lock);
if(music_vorbis.file.fd != 0) { if(music_vorbis.file.end != 0) {
ov_clear(&music_vorbis.stream); ov_clear(&music_vorbis.stream);
pack_close(&music_vorbis.file); pack_close(&music_vorbis.file);
} }
@ -257,6 +264,7 @@ void music_load(const char* name) {
char tmp[64]; char tmp[64];
music_stop(); music_stop();
while(!music_is(MUSIC_STOPPED)) SDL_Delay(0);
for(i = 0; i < nmusic_selection; i++) for(i = 0; i < nmusic_selection; i++)
if(strcmp(music_selection[i], name)==0) { if(strcmp(music_selection[i], name)==0) {

View File

@ -43,6 +43,7 @@ const uint64_t magic = 0x25524573; // sER%
// Grab the filesize. // Grab the filesize.
static off_t getfilesize(const char* filename) { static off_t getfilesize(const char* filename) {
#ifdef _POSIX_SOURCE
struct stat file; struct stat file;
if(!stat(filename, &file)) if(!stat(filename, &file))
@ -50,46 +51,94 @@ static off_t getfilesize(const char* filename) {
ERR("Unable to get filesize of %s", filename); ERR("Unable to get filesize of %s", filename);
return 0; return 0;
#else
long size;
FILE* fp = fopen(filename, "rb");
if(fp == NULL) return 0;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fclose(fp);
return size;
#endif
} }
// Return true if filename is a Packfile. // Return true if filename is a Packfile.
int pack_check(const char* filename) { int pack_check(const char* filename) {
int ret;
char* buf;
buf = malloc(sizeof(magic));
#ifdef _POSIX_SOURCE
int fd = open(filename, O_RDONLY); int fd = open(filename, O_RDONLY);
if(fd == -1) { if(fd == -1) {
ERR("Error opening %s: %s", filename, strerror(errno)); ERR("Error opening %s: %s", filename, strerror(errno));
return -1; return -1;
} }
char* buf = malloc(sizeof(magic));
if(read(fd, buf, sizeof(magic)) != sizeof(magic)) { if(read(fd, buf, sizeof(magic)) != sizeof(magic)) {
ERR("Error reading magic number: %s", strerror(errno)); ERR("Error reading magic number: %s", strerror(errno));
free(buf); free(buf);
return -1; return -1;
} }
ret = (memcmp(buf, &magic, sizeof(magic))==0) ? 0 : 1;
close(fd);
#else
FILE* file = fopen(filename, "rb");
if(file == NULL) {
ERR("Error opening '%s': %s", filename, strerror(errno));
return -1;
}
buf = malloc(sizeof(magic));
if(fread(buf, 1, sizeof(magic), file) != sizeof(magic)) {
ERR("Error reading magic number: %s", strerror(errno));
free(buf);
return -1;
}
ret = (memcmp(buf, &magic, sizeof(magic))==0) ? 0 : 1;
fclose(file);
#endif
int ret = (memcmp(buf, &magic, sizeof(magic))==0) ? 0 : 1;
free(buf); free(buf);
return ret; return ret;
} }
// Pack nfiles, infiles into outfile. // Pack nfiles, infiles into outfile.
#define WRITE(f,b,n) if(write(f,b,n)==-1) { \ #ifdef _POSIX_SOURCE
#define WRITE(b,n) if(write(outfd, b, n)==-1) { \
ERR("Error writing to file: %s", strerror(errno)); \ ERR("Error writing to file: %s", strerror(errno)); \
free(buf); return -1; } free(buf); return -1; }
#else
#define WRITE(b,n) if(fwrite(b, 1, n, outf)==0) { \
ERR("Error writing to file: %s", strerror(errno)); \
free(buf); return -1; }
#endif
int pack_files(const char* outfile, const char** infiles, const uint32_t nfiles) { int pack_files(const char* outfile, const char** infiles, const uint32_t nfiles) {
void* buf; void* buf;
#ifdef _POSIX_SOURCE
struct stat file; struct stat file;
int outfd, infd;
#else
FILE* outf, *inf;
#endif
uint32_t i; uint32_t i;
int namesize; int namesize;
int outfd, infd;
uint32_t indexsize, pointer; uint32_t indexsize, pointer;
int bytes; int bytes;
const uint8_t b = '\0'; const uint8_t b = '\0';
for(namesize = 0, i = 0; i < nfiles; i++) { for(namesize = 0, i = 0; i < nfiles; i++) {
// Make sure file exists before writing. // Make sure file exists before writing.
#ifdef _POSIX_SOURCE
if(stat(infiles[i], &file)) { if(stat(infiles[i], &file)) {
#else
if(getfilesize(infiles[i]) == 0) {
#endif
ERR("File %s does not exist", infiles[i]); ERR("File %s does not exist", infiles[i]);
return -1; return -1;
} }
@ -106,8 +155,13 @@ int pack_files(const char* outfile, const char** infiles, const uint32_t nfiles)
DEBUG("Index size is %d", indexsize); DEBUG("Index size is %d", indexsize);
// Create the output file. // Create the output file.
#ifdef _POSIX_SOURCE
outfd = creat(outfile, PERMS); outfd = creat(outfile, PERMS);
if(outfd == -1) { if(outfd == -1) {
#else
outf = fopen(outfile, "wb");
if(outf == NULL) {
#endif
ERR("Unable to open %s for writing", outfile); ERR("Unable to open %s for writing", outfile);
return -1; return -1;
} }
@ -116,18 +170,18 @@ int pack_files(const char* outfile, const char** infiles, const uint32_t nfiles)
buf = malloc(BLOCKSIZE); buf = malloc(BLOCKSIZE);
// Magic number. // Magic number.
WRITE(outfd, &magic, sizeof(magic)); WRITE(&magic, sizeof(magic));
DEBUG("Wrote magic number"); DEBUG("Wrote magic number");
// Number of files. // Number of files.
WRITE(outfd, &nfiles, sizeof(nfiles)); WRITE(&nfiles, sizeof(nfiles));
DEBUG("Wrote number of files: %d", nfiles); DEBUG("Wrote number of files: %d", nfiles);
// Create file dependent index part. // Create file dependent index part.
pointer = indexsize; pointer = indexsize;
for(i = 0; i < nfiles; i++) { for(i = 0; i < nfiles; i++) {
WRITE(outfd, infiles[i], strlen(infiles[i])); WRITE(infiles[i], strlen(infiles[i]));
DEBUG("File: '%s' at %d", infiles[i], pointer); DEBUG("File: '%s' at %d", infiles[i], pointer);
WRITE(outfd, &b, 1); WRITE(&b, 1);
WRITE(outfd, &pointer, 4); WRITE(&pointer, 4);
pointer += 4 + getfilesize(infiles[i]) + 16; // Set pointer to be next file pos. pointer += 4 + getfilesize(infiles[i]) + 16; // Set pointer to be next file pos.
} }
@ -136,22 +190,35 @@ int pack_files(const char* outfile, const char** infiles, const uint32_t nfiles)
md5_byte_t* md5val = malloc(16); md5_byte_t* md5val = malloc(16);
for(i = 0; i < nfiles; i++) { for(i = 0; i < nfiles; i++) {
bytes = (uint32_t)getfilesize(infiles[i]); bytes = (uint32_t)getfilesize(infiles[i]);
WRITE(outfd, &bytes, 4); // filesize. WRITE(&bytes, 4); // filesize.
DEBUG("About to write '%s' of %d bytes", infiles[i], bytes); DEBUG("About to write '%s' of %d bytes", infiles[i], bytes);
infd = open(infiles[i], O_RDONLY);
md5_init(&md5); md5_init(&md5);
#ifdef _POSIX_SOURCE
infd = open(infiles[i], O_RDONLY);
while((bytes = read(infd, buf, BLOCKSIZE))) { while((bytes = read(infd, buf, BLOCKSIZE))) {
WRITE(outfd, buf, bytes); // Data. #else
nf = fopen(infiles[i], "rb");
while((bytes = fread(buf, 1, BLOCKSIZE, inf))) {
#endif
WRITE(buf, bytes); // Data.
md5_append(&md5, buf, bytes); md5_append(&md5, buf, bytes);
} }
md5_finish(&md5, md5val); md5_finish(&md5, md5val);
WRITE(outfd, md5val, 16); WRITE(md5val, 16);
#ifdef _POSIX_SOURCE
close(infd); close(infd);
#else
fclose(inf);
#endif
DEBUG("Wrote file '%s'", infiles[i]); DEBUG("Wrote file '%s'", infiles[i]);
} }
free(md5val); free(md5val);
#ifdef _POSIX_SOURCE
close(outfd); close(outfd);
#else
fclose(outf);
#endif
free(buf); free(buf);
DEBUG("Packfile success\n\t%d files\n\t%d bytes", nfiles, (int)getfilesize(outfile)); DEBUG("Packfile success\n\t%d files\n\t%d bytes", nfiles, (int)getfilesize(outfile));
@ -160,9 +227,15 @@ int pack_files(const char* outfile, const char** infiles, const uint32_t nfiles)
#undef WRITE #undef WRITE
// Opens the filename in packfile for reading. // Opens the filename in packfile for reading.
#define READ(f,b,n) if(read(f,b,n) != n) { \ #ifdef _POSIX_SOURCE
#define READ(b,n) if(read(file->fd, (b), (n))!=(n)) { \
ERR("Too few bytes read. Expected more."); \ ERR("Too few bytes read. Expected more."); \
free(buf); return -1; } free(buf); return -1; }
#else
#define READ(b,n) if(fread((b), 1, (n), file->fp)!=(n)) { \
ERR("Fewer bytes read then expected"); \
free(buf); return -1; }
#endif
int pack_open(Packfile* file, const char* packfile, const char* filename) { int pack_open(Packfile* file, const char* packfile, const char* filename) {
int j; int j;
uint32_t nfiles, i; uint32_t nfiles, i;
@ -170,46 +243,57 @@ int pack_open(Packfile* file, const char* packfile, const char* filename) {
file->start = file->end = 0; file->start = file->end = 0;
#ifdef _POSIX_SOURCE
file->fd = open(packfile, O_RDONLY); file->fd = open(packfile, O_RDONLY);
if(file->fd == -1) { if(file->fd == -1) {
#else
file->fp = fopen(packfile, "rb");
if(file->fp == NULL) {
#endif
ERR("Error opening %s: %s", filename, strerror(errno)); ERR("Error opening %s: %s", filename, strerror(errno));
return -1; return -1;
} }
READ(file->fd, buf, sizeof(magic)); // Make sure it's a packfile. READ(buf, sizeof(magic)); // Make sure it's a packfile.
if(memcmp(buf, &magic, sizeof(magic))) { if(memcmp(buf, &magic, sizeof(magic))) {
ERR("File %s is not a valid packfile", filename); ERR("File %s is not a valid packfile", filename);
return -1; return -1;
} }
READ(file->fd, &nfiles, 4); READ(&nfiles, 4);
for(i = 0; i < nfiles; i++) { for(i = 0; i < nfiles; i++) {
// Start to search files. // Start to search files.
j = 0; j = 0;
READ(file->fd, &buf[j], 1); // Get the name. READ(&buf[j], 1); // Get the name.
while(buf[j++] != '\0') while(buf[j++] != '\0')
READ(file->fd, &buf[j], 1); READ(&buf[j], 1);
if(strcmp(filename, buf) == 0) { if(strcmp(filename, buf) == 0) {
// We found the file. // We found the file.
READ(file->fd, &file->start, 4); READ(&file->start, 4);
DEBUG("'%s' found at %d", filename, file->start); DEBUG("'%s' found at %d", filename, file->start);
break; break;
} }
#ifdef _POSIX_SOURCE
lseek(file->fd, 4, SEEK_CUR); // Ignore the file location. lseek(file->fd, 4, SEEK_CUR); // Ignore the file location.
#else
fseek(file->fp, 4, SEEK_CUR);
#endif
} }
free(buf); free(buf);
if(file->start) { if(file->start) {
// Go to the beginning of the file. // Go to the beginning of the file.
#ifdef _POSIX_SOURCE
if((uint32_t)lseek(file->fd, file->start, SEEK_SET) != file->start) { if((uint32_t)lseek(file->fd, file->start, SEEK_SET) != file->start) {
#else
fseek(file->fp, file->start, SEEK_SET);
if(errno) {
#endif
ERR("Failure to seek to file start: %s", strerror(errno)); ERR("Failure to seek to file start: %s", strerror(errno));
return -1; return -1;
} }
if(read(file->fd, &file->end, 4) != 4) { READ(&file->end, 4);
ERR("Too few bytes read. Expected more.");
return -1;
}
DEBUG("\t%d bytes", file->end); DEBUG("\t%d bytes", file->end);
file->pos = file->start; file->pos = file->start;
file->end += file->start; file->end += file->start;
@ -228,7 +312,11 @@ ssize_t pack_read(Packfile* file, void* buf, size_t count) {
int bytes; int bytes;
#ifdef _POSIX_SOURCE
if((bytes = read(file->fd, buf, count)) == -1) { if((bytes = read(file->fd, buf, count)) == -1) {
#else
if((byts = freed(buf, 1, count, file->fp)) == -1) {
#endif
ERR("Error while reading file: %s", strerror(errno)); ERR("Error while reading file: %s", strerror(errno));
return -1; return -1;
} }
@ -270,8 +358,12 @@ void* pack_readfile(const char* packfile, const char* filename, uint32_t* filesi
md5_byte_t* md5fd = malloc(16); md5_byte_t* md5fd = malloc(16);
md5_init(&md5); md5_init(&md5);
md5_append(&md5, buf, bytes); md5_append(&md5, buf, bytes);
md5_finish(&md5, md5val);; md5_finish(&md5, md5val);
#ifdef _POSIX_SOURCE
if((bytes = read(file->fd, md5fd, 16)) == -1) if((bytes = read(file->fd, md5fd, 16)) == -1)
#else
if((bytes = fread(md5fd, 1, 16, file->fp)) == -1)
#endif
WARN("Failure to read MD5, continuing anyway.."); WARN("Failure to read MD5, continuing anyway..");
else if(memcmp(md5val, md5fd, 16)) else if(memcmp(md5val, md5fd, 16))
WARN("MD5 gives different value, possible memory corruption, continuing.."); WARN("MD5 gives different value, possible memory corruption, continuing..");
@ -295,46 +387,75 @@ void* pack_readfile(const char* packfile, const char* filename, uint32_t* filesi
// Load the filenames int the packfile to filenames. // Load the filenames int the packfile to filenames.
// filenames should be freed after use // filenames should be freed after use
// On error if filenames is (char**)-1. // On error if filenames is (char**)-1.
#define READ(f,b,n) if(read(f,b,n)!=n) { ERR("Too few bytes read. Expected more."); return NULL; } #ifdef _POSIX_SOURCE
#define READ(b,n) if(read(fd, (b), (n))!=(n)) { \
ERR("Too few bytes read"); \
return NULL; }
#else
#define READ(b,n) if(fread((b), 1, (n), fp) != (n)) { \
ERR("Too few bytes read"); \
return NULL; }
#endif
char** pack_listfiles(const char* packfile, uint32_t* nfiles) { char** pack_listfiles(const char* packfile, uint32_t* nfiles) {
int fd, j; #ifdef _POSIX_SOURCE
int fd;
#else
FILE* fp;
#endif
int j;
uint32_t i; uint32_t i;
char** filenames; char** filenames;
char* buf = malloc(sizeof(magic)); char* buf = malloc(sizeof(magic));
*nfiles = 0; *nfiles = 0;
#ifdef _POSIX_SOURCE
fd = open(packfile, O_RDONLY); fd = open(packfile, O_RDONLY);
if(fd == -1) { if(fd == -1) {
#else
fp = fopen(packfile, "rb");
if(fp == NULL) {
#endif
ERR("opening %s: %s", packfile, strerror(errno)); ERR("opening %s: %s", packfile, strerror(errno));
return NULL; return NULL;
} }
READ(fd, buf, sizeof(magic)); // Make sure it is a packfile. READ(buf, sizeof(magic)); // Make sure it is a packfile.
if(memcmp(buf, &magic, sizeof(magic))) { if(memcmp(buf, &magic, sizeof(magic))) {
ERR("File %s is not a valid packfile", packfile); ERR("File %s is not a valid packfile", packfile);
return NULL; return NULL;
} }
READ(fd, nfiles, 4); READ(nfiles, 4);
filenames = malloc(((*nfiles)+1)*sizeof(char*)); filenames = malloc(((*nfiles)+1)*sizeof(char*));
for(i = 0; i < *nfiles; i++) { for(i = 0; i < *nfiles; i++) {
// Start searching files. // Start searching files.
j = 0; j = 0;
filenames[i] = malloc(MAX_FILENAME * sizeof(char)); filenames[i] = malloc(MAX_FILENAME * sizeof(char));
READ(fd, &filenames[i][j], 1); // Get the name. READ(&filenames[i][j], 1); // Get the name.
while(filenames[i][j++] != '\0') while(filenames[i][j++] != '\0')
READ(fd, &filenames[i][j], 1); READ(&filenames[i][j], 1);
READ(fd, buf, 4); // skip the location. READ(buf, 4); // skip the location.
} }
free(buf); free(buf);
#ifdef _POSIX_SOURCE
close(fd); close(fd);
#else
fclose(fp);
#endif
return filenames; return filenames;
} }
#undef READ #undef READ
// Close the packfile. // Close the packfile.
int pack_close(Packfile* file) { int pack_close(Packfile* file) {
int i = close(file->fd); int i;
#ifdef _POSIX_SOURCE
i = close(file->fd);
#else
i = fclose(file->fp);
#endif
return (i) ? -1 : 0; return (i) ? -1 : 0;
} }

View File

@ -1,9 +1,16 @@
#pragma once #pragma once
#include <fcntl.h> #include <fcntl.h>
#ifndef _POSIX_SOURCE // No posix.
#include <stdio.h>
#endif
#include <stdint.h> #include <stdint.h>
typedef struct { typedef struct {
#ifdef _POSIX_SOURCE
int fd; // File descriptor. int fd; // File descriptor.
#else
FILE* fp;
#endif
uint32_t pos; // position. uint32_t pos; // position.
uint32_t start, end; // file limits. uint32_t start, end; // file limits.
} Packfile; } Packfile;